mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[ConstraintSystem] Implement new rule for static member lookup in generic contexts
Instead of requiring result type of the member to conform to declaring protocol, as originally proposed by SE-0299, let's instead require `Self` to be bound to some concrete type in extension that declares a static member. This would make sure that: 1. Members are only visible on a particular type; 2. There is no ambiguity regarding what base of the member chain is going to be.
This commit is contained in:
@@ -1589,19 +1589,12 @@ ConstraintSystem::getTypeOfMemberReference(
|
||||
// reference e.g. it might be incorrect initializer call
|
||||
// or result type is invalid.
|
||||
if (!(shouldAttemptFixes() && hasFixFor(getConstraintLocator(locator)))) {
|
||||
// Member type with Self applied.
|
||||
auto refTy = openedType->castTo<FunctionType>()->getResult();
|
||||
// If member is a function type, let's use its result type
|
||||
// since it could be either a static method or a property
|
||||
// which returns a function type.
|
||||
if (auto *funcTy = refTy->getAs<FunctionType>())
|
||||
baseOpenedTy = funcTy->getResult();
|
||||
else
|
||||
baseOpenedTy = refTy;
|
||||
|
||||
// It should be possible to form optional chains which start
|
||||
// from a protocol metatype.
|
||||
baseOpenedTy = baseOpenedTy->lookThroughAllOptionalTypes();
|
||||
if (auto concreteSelf =
|
||||
getConcreteReplacementForProtocolSelfType(value)) {
|
||||
// Concrete type replacing `Self` could be generic, so we need
|
||||
// to make sure that it's opened before use.
|
||||
baseOpenedTy = openType(concreteSelf, replacements);
|
||||
}
|
||||
}
|
||||
} else if (baseObjTy->isExistentialType()) {
|
||||
auto openedArchetype = OpenedArchetypeType::get(baseObjTy);
|
||||
@@ -4540,6 +4533,23 @@ bool constraints::hasExplicitResult(ClosureExpr *closure) {
|
||||
ClosureHasExplicitResultRequest{closure}, false);
|
||||
}
|
||||
|
||||
Type constraints::getConcreteReplacementForProtocolSelfType(ValueDecl *member) {
|
||||
auto *DC = member->getDeclContext();
|
||||
|
||||
if (!DC->getSelfProtocolDecl())
|
||||
return Type();
|
||||
|
||||
GenericSignature signature;
|
||||
if (auto *genericContext = member->getAsGenericContext()) {
|
||||
signature = genericContext->getGenericSignature();
|
||||
} else {
|
||||
signature = DC->getGenericSignatureOfContext();
|
||||
}
|
||||
|
||||
auto selfTy = DC->getProtocolSelfType();
|
||||
return signature->getConcreteType(selfTy);
|
||||
}
|
||||
|
||||
static bool isOperator(Expr *expr, StringRef expectedName) {
|
||||
auto name = getOperatorName(expr);
|
||||
return name ? name->is(expectedName) : false;
|
||||
|
||||
Reference in New Issue
Block a user