diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 5a3a5824c5a..17ef27b6cc1 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -7322,7 +7322,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, // Dig out the instance type and figure out what members of the instance type // we are going to see. auto baseTy = candidate.getBaseType(); - auto baseObjTy = baseTy->getRValueType(); + const auto baseObjTy = baseTy->getRValueType(); bool hasInstanceMembers = false; bool hasInstanceMethods = false; @@ -7369,18 +7369,6 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, hasInstanceMethods = true; } - // If our base is an existential type, we can't make use of any - // member whose signature involves associated types. - if (instanceTy->isExistentialType()) { - if (auto *proto = decl->getDeclContext()->getSelfProtocolDecl()) { - if (!proto->isAvailableInExistential(decl)) { - result.addUnviable(candidate, - MemberLookupResult::UR_UnavailableInExistential); - return; - } - } - } - // If the invocation's argument expression has a favored type, // use that information to determine whether a specific overload for // the candidate should be favored. @@ -7400,6 +7388,20 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, } } + const auto isUnsupportedExistentialMemberAccess = [&] { + // If our base is an existential type, we can't make use of any + // member whose signature involves associated types. + if (instanceTy->isExistentialType()) { + if (auto *proto = decl->getDeclContext()->getSelfProtocolDecl()) { + if (!proto->isAvailableInExistential(decl)) { + return true; + } + } + } + + return false; + }; + // See if we have an instance method, instance member or static method, // and check if it can be accessed on our base type. @@ -7413,20 +7415,35 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, ? candidate : OverloadChoice(instanceTy, decl, FunctionRefKind::SingleApply); - // If this is an instance member referenced from metatype - // let's add unviable result to the set because it could be - // either curried reference or an invalid call. - // - // New candidate shouldn't affect performance because such - // choice would only be attempted when solver is in diagnostic mode. - result.addUnviable(choice, MemberLookupResult::UR_InstanceMemberOnType); - bool invalidMethodRef = isa(decl) && !hasInstanceMethods; - bool invalidMemberRef = !isa(decl) && !hasInstanceMembers; - // If this is definitely an invalid way to reference a method or member - // on the metatype, let's stop here. - if (invalidMethodRef || invalidMemberRef) + const bool invalidMethodRef = isa(decl) && !hasInstanceMethods; + const bool invalidMemberRef = !isa(decl) && !hasInstanceMembers; + + if (invalidMethodRef || invalidMemberRef) { + // If this is definitely an invalid way to reference a method or member + // on the metatype, let's stop here. + result.addUnviable(choice, + MemberLookupResult::UR_InstanceMemberOnType); return; + } else if (isUnsupportedExistentialMemberAccess()) { + // If the member reference itself is legal, but it turns out to be an + // unsupported existential member access, do not make further + // assumptions about the correctness of a potential call -- let + // the unsupported member access error prevail. + result.addUnviable(candidate, + MemberLookupResult::UR_UnavailableInExistential); + return; + } else { + // Otherwise, still add an unviable result to the set, because it + // could be an invalid call that was supposed to be performed on an + // instance of the type. + // + // New candidate shouldn't affect performance because such + // choice would only be attempted when solver is in diagnostic mode. + result.addUnviable(choice, + MemberLookupResult::UR_InstanceMemberOnType); + + } } // If the underlying type of a typealias is fully concrete, it is legal @@ -7477,6 +7494,12 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, } } + if (isUnsupportedExistentialMemberAccess()) { + result.addUnviable(candidate, + MemberLookupResult::UR_UnavailableInExistential); + return; + } + // If we have an rvalue base, make sure that the result isn't 'mutating' // (only valid on lvalues). if (!baseTy->is() && diff --git a/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift index 5bbac18ffb8..05d6410ead2 100644 --- a/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift +++ b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift @@ -442,19 +442,19 @@ protocol P1_TypeMemberOnInstanceAndViceVersa { subscript(invariantSelfSubscript _: Void) -> G { get } } do { + // Test that invalid reference errors prevail over unsupported existential + // member accesses. func test(protoMeta: P1_TypeMemberOnInstanceAndViceVersa.Protocol, existMeta: P1_TypeMemberOnInstanceAndViceVersa.Type, instance: P1_TypeMemberOnInstanceAndViceVersa) { // P1_TypeMemberOnInstanceAndViceVersa.Protocol - // FIXME: These should be diagnosed as invalid references. - protoMeta.static_invariantSelfMethod() // expected-error {{member 'static_invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} - protoMeta.static_invariantSelfProp // expected-error {{member 'static_invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} - protoMeta[static_invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} + protoMeta.static_invariantSelfMethod() // expected-error {{static member 'static_invariantSelfMethod' cannot be used on protocol metatype 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'}} + protoMeta.static_invariantSelfProp // expected-error {{static member 'static_invariantSelfProp' cannot be used on protocol metatype 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'}} + protoMeta[static_invariantSelfSubscript: ()] // expected-error {{static member 'subscript' cannot be used on protocol metatype 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'}} _ = protoMeta.covariantSelfMethod // ok protoMeta.invariantSelfMethod // expected-error {{member 'invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} - // FIXME: These should be diagnosed as invalid references. - protoMeta.invariantSelfProp // expected-error {{member 'invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} - protoMeta[invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} + protoMeta.invariantSelfProp // expected-error {{instance member 'invariantSelfProp' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}} + protoMeta[invariantSelfSubscript: ()] // expected-error {{instance member 'subscript' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}} // P1_TypeMemberOnInstanceAndViceVersa.Type _ = existMeta.static_covariantSelfMethod // ok @@ -463,16 +463,14 @@ do { existMeta.static_invariantSelfMethod // expected-error {{member 'static_invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} existMeta.static_invariantSelfProp // expected-error {{member 'static_invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} existMeta[static_invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} - // FIXME: These should be diagnosed as invalid references. - existMeta.invariantSelfMethod // expected-error {{member 'invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} - existMeta.invariantSelfProp // expected-error {{member 'invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} - existMeta[invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} + existMeta.invariantSelfMethod // expected-error {{instance member 'invariantSelfMethod' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}} + existMeta.invariantSelfProp // expected-error {{instance member 'invariantSelfProp' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}} + existMeta[invariantSelfSubscript: ()] // expected-error {{instance member 'subscript' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}} // P1_TypeMemberOnInstanceAndViceVersa - // FIXME: These should be diagnosed as invalid references. - instance.static_invariantSelfMethod // expected-error {{member 'static_invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa'; use a generic constraint instead}} - instance.static_invariantSelfProp // expected-error {{member 'static_invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa'; use a generic constraint instead}} - instance[static_invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa'; use a generic constraint instead}} + instance.static_invariantSelfMethod // expected-error {{static member 'static_invariantSelfMethod' cannot be used on instance of type 'P1_TypeMemberOnInstanceAndViceVersa'}} + instance.static_invariantSelfProp // expected-error {{static member 'static_invariantSelfProp' cannot be used on instance of type 'P1_TypeMemberOnInstanceAndViceVersa'}} + instance[static_invariantSelfSubscript: ()] // expected-error {{static member 'subscript' cannot be used on instance of type 'P1_TypeMemberOnInstanceAndViceVersa'}} } }