mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +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>() &&
|
||||
|
||||
Reference in New Issue
Block a user