Skip to content

Commit 2237658

Browse files
Merge pull request #73103 from AnthonyLatsis/brassica-oleracea
Sema: Fix existential member access type erasure around metatypes
2 parents 3e637b0 + d18a7fd commit 2237658

File tree

8 files changed

+225
-103
lines changed

8 files changed

+225
-103
lines changed

include/swift/Sema/ConstraintLocatorPathElts.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,11 @@ SIMPLE_LOCATOR_PATH_ELT(CoercionOperand)
287287
/// A fallback type for some AST location (i.e. key path literal).
288288
SIMPLE_LOCATOR_PATH_ELT(FallbackType)
289289

290+
/// An implicit conversion (upcast) associated with an existential member access
291+
/// performed to abstract the member reference type away from context-specific
292+
/// types like `Self` that are not well-formed in the access context.
293+
SIMPLE_LOCATOR_PATH_ELT(ExistentialMemberAccessConversion)
294+
290295
#undef LOCATOR_PATH_ELT
291296
#undef CUSTOM_LOCATOR_PATH_ELT
292297
#undef SIMPLE_LOCATOR_PATH_ELT

include/swift/Sema/ConstraintSystem.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4442,8 +4442,7 @@ class ConstraintSystem {
44424442
/// determine the reference type of the member reference.
44434443
Type getMemberReferenceTypeFromOpenedType(
44444444
Type &openedType, Type baseObjTy, ValueDecl *value, DeclContext *outerDC,
4445-
ConstraintLocator *locator, bool hasAppliedSelf,
4446-
bool isStaticMemberRefOnProtocol, bool isDynamicResult,
4445+
ConstraintLocator *locator, bool hasAppliedSelf, bool isDynamicLookup,
44474446
OpenedTypeMap &replacements);
44484447

44494448
/// Retrieve the type of a reference to the given value declaration,
@@ -4453,16 +4452,14 @@ class ConstraintSystem {
44534452
/// this routine "opens up" the type by replacing each instance of a generic
44544453
/// parameter with a fresh type variable.
44554454
///
4456-
/// \param isDynamicResult Indicates that this declaration was found via
4455+
/// \param isDynamicLookup Indicates that this declaration was found via
44574456
/// dynamic lookup.
44584457
///
44594458
/// \returns a description of the type of this declaration reference.
44604459
DeclReferenceType getTypeOfMemberReference(
4461-
Type baseTy, ValueDecl *decl, DeclContext *useDC,
4462-
bool isDynamicResult,
4463-
FunctionRefKind functionRefKind,
4464-
ConstraintLocator *locator,
4465-
OpenedTypeMap *replacements = nullptr);
4460+
Type baseTy, ValueDecl *decl, DeclContext *useDC, bool isDynamicLookup,
4461+
FunctionRefKind functionRefKind, ConstraintLocator *locator,
4462+
OpenedTypeMap *replacements = nullptr);
44664463

44674464
/// Retrieve a list of generic parameter types solver has "opened" (replaced
44684465
/// with a type variable) at the given location.

lib/Sema/CSDiagnostics.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,17 +1323,18 @@ class UnintendedExtraGenericParamMemberFailure final
13231323
bool diagnoseAsError() override;
13241324
};
13251325

1326-
/// Diagnose cases where a member only accessible on generic constraints
1327-
/// requiring conformance to a protocol is used on a value of the
1328-
/// existential protocol type e.g.
1326+
/// Diagnose cases where a protocol member cannot be accessed with an
1327+
/// existential, e.g. due to occurrences of `Self` in non-covariant position in
1328+
/// the type of the member reference:
13291329
///
13301330
/// ```swift
1331+
/// struct G<T> {}
13311332
/// protocol P {
1332-
/// var foo: Self { get }
1333+
/// func foo() -> G<Self>
13331334
/// }
13341335
///
1335-
/// func bar<X : P>(p: X) {
1336-
/// p.foo
1336+
/// func bar(p: any P) {
1337+
/// p.foo()
13371338
/// }
13381339
/// ```
13391340
class InvalidMemberRefOnExistential final : public InvalidMemberRefFailure {

lib/Sema/CSSimplify.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5620,6 +5620,23 @@ bool ConstraintSystem::repairFailures(
56205620
}
56215621
}
56225622

5623+
// If there is a conversion associated with an existential member access
5624+
// along the path, the problem is that the constraint system does not support
5625+
// the (formally sane) upcast required to access the member.
5626+
if (llvm::find_if(path, [](const LocatorPathElt &elt) -> bool {
5627+
return elt.is<LocatorPathElt::ExistentialMemberAccessConversion>();
5628+
}) != path.end()) {
5629+
if (auto overload = findSelectedOverloadFor(castToExpr(anchor))) {
5630+
auto &choice = overload->choice;
5631+
conversionsOrFixes.push_back(AllowMemberRefOnExistential::create(
5632+
*this, choice.getBaseType(), choice.getDecl(),
5633+
DeclNameRef(choice.getDecl()->getName()),
5634+
getConstraintLocator(locator)));
5635+
5636+
return true;
5637+
}
5638+
}
5639+
56235640
auto elt = path.back();
56245641
switch (elt.getKind()) {
56255642
case ConstraintLocator::LValueConversion: {
@@ -15153,7 +15170,8 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1515315170
case FixKind::GenericArgumentsMismatch:
1515415171
case FixKind::AllowConcreteTypeSpecialization:
1515515172
case FixKind::IgnoreGenericSpecializationArityMismatch:
15156-
case FixKind::IgnoreKeyPathSubscriptIndexMismatch: {
15173+
case FixKind::IgnoreKeyPathSubscriptIndexMismatch:
15174+
case FixKind::AllowMemberRefOnExistential: {
1515715175
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
1515815176
}
1515915177
case FixKind::IgnoreThrownErrorMismatch: {
@@ -15376,7 +15394,6 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1537615394
case FixKind::RemoveCall:
1537715395
case FixKind::RemoveUnwrap:
1537815396
case FixKind::DefineMemberBasedOnUse:
15379-
case FixKind::AllowMemberRefOnExistential:
1538015397
case FixKind::AllowTypeOrInstanceMember:
1538115398
case FixKind::AllowInvalidPartialApplication:
1538215399
case FixKind::AllowInvalidInitRef:

lib/Sema/ConstraintLocator.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ unsigned LocatorPathElt::getNewSummaryFlags() const {
112112
case ConstraintLocator::ThrownErrorType:
113113
case ConstraintLocator::FallbackType:
114114
case ConstraintLocator::KeyPathSubscriptIndex:
115+
case ConstraintLocator::ExistentialMemberAccessConversion:
115116
return 0;
116117

117118
case ConstraintLocator::FunctionArgument:
@@ -532,6 +533,9 @@ void LocatorPathElt::dump(raw_ostream &out) const {
532533
out << "key path subscript index parameter";
533534
break;
534535
}
536+
case ConstraintLocator::ExistentialMemberAccessConversion:
537+
out << "existential member access conversion";
538+
break;
535539
}
536540
}
537541

0 commit comments

Comments
 (0)