mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Sema: Check for invalid reference *before* checking for unsupported existential member access
This commit is contained in:
@@ -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<FuncDecl>(decl) && !hasInstanceMethods;
|
||||
bool invalidMemberRef = !isa<FuncDecl>(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<FuncDecl>(decl) && !hasInstanceMethods;
|
||||
const bool invalidMemberRef = !isa<FuncDecl>(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<AnyMetatypeType>() &&
|
||||
|
||||
@@ -442,19 +442,19 @@ protocol P1_TypeMemberOnInstanceAndViceVersa {
|
||||
subscript(invariantSelfSubscript _: Void) -> G<Self> { 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'}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user