Skip to content

Commit 7009207

Browse files
committed
[ConstraintSystem] Adjust handling of incorrect member references on protocol metatypes
Since it's now possible to refer to static members declared on a protocol metatype if result type conforms to the protocol we need to adjust failure detection to identify that conformance failure means and invalid reference in certain situations.
1 parent 3a145f5 commit 7009207

File tree

3 files changed

+44
-11
lines changed

3 files changed

+44
-11
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5962,6 +5962,27 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
59625962
}
59635963
}
59645964

5965+
if (path.back().is<LocatorPathElt::MemberRefBase>()) {
5966+
path.pop_back();
5967+
5968+
auto *memberLoc = getConstraintLocator(anchor, path);
5969+
if (auto overload = findSelectedOverloadFor(memberLoc)) {
5970+
const auto &choice = overload->choice;
5971+
assert(choice.isDecl());
5972+
5973+
auto *decl = choice.getDecl();
5974+
auto nameRef = choice.getFunctionRefKind() == FunctionRefKind::Compound
5975+
? decl->createNameRef()
5976+
: DeclNameRef(decl->getBaseName());
5977+
5978+
auto *fix = AllowTypeOrInstanceMember::create(
5979+
*this, MetatypeType::get(protocolTy, getASTContext()), decl,
5980+
nameRef, memberLoc);
5981+
5982+
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
5983+
}
5984+
}
5985+
59655986
// If this is an implicit Hashable conformance check generated for each
59665987
// index argument of the keypath subscript component, we could just treat
59675988
// it as though it conforms.

lib/Sema/ConstraintSystem.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,17 +1606,27 @@ ConstraintSystem::getTypeOfMemberReference(
16061606

16071607
Type selfObjTy = openedParams.front().getPlainType()->getMetatypeInstanceType();
16081608
if (outerDC->getSelfProtocolDecl()) {
1609+
// For a protocol, substitute the base object directly. We don't need a
1610+
// conformance constraint because we wouldn't have found the declaration
1611+
// if it didn't conform.
1612+
addConstraint(ConstraintKind::Bind, baseOpenedTy, selfObjTy,
1613+
getConstraintLocator(locator));
1614+
16091615
if (isStaticMemberRefOnProtocol) {
1610-
// If this is a static member reference on a protocol metatype
1611-
// we need to make sure that base type, we yet to infer from a
1612-
// result type of the member, does indeed conform to `Self`.
1613-
addSelfConstraint(*this, baseOpenedTy, selfObjTy, locator);
1614-
} else {
1615-
// For a protocol, substitute the base object directly. We don't need a
1616-
// conformance constraint because we wouldn't have found the declaration
1617-
// if it didn't conform.
1618-
addConstraint(ConstraintKind::Bind, baseOpenedTy, selfObjTy,
1619-
getConstraintLocator(locator));
1616+
// Since base is a protocol metatype we could use to make sure that
1617+
// self type inferred from result of the member does indeed conform
1618+
// to the expected protocol.
1619+
//
1620+
// Delay solving this constraint until after member choice has
1621+
// been completely resolved by the constraint system, so that
1622+
// conformance failure has access to a referenced declaration.
1623+
auto *constraint = Constraint::create(
1624+
*this, ConstraintKind::ConformsTo, selfObjTy, baseObjTy,
1625+
getConstraintLocator(
1626+
locator.withPathElement(ConstraintLocator::MemberRefBase)));
1627+
1628+
addUnsolvedConstraint(constraint);
1629+
activateConstraint(constraint);
16201630
}
16211631
} else if (!isDynamicResult) {
16221632
addSelfConstraint(*this, baseOpenedTy, selfObjTy, locator);

test/decl/enum/enumtest.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ func test1a() -> unionSearchFlags {
3636

3737
func test1b(_ b : Bool) {
3838
_ = 123
39-
_ = .description == 1 // expected-error {{cannot infer contextual base in reference to member 'description'}}
39+
_ = .description == 1
40+
// expected-error@-1 {{instance member 'description' cannot be used on type 'Int'}}
41+
// expected-error@-2 {{member 'description' in 'Int' produces result of type 'String', but context expects 'Int'}}
4042
}
4143

4244
enum MaybeInt {

0 commit comments

Comments
 (0)