Skip to content

Commit 79a2ab0

Browse files
committed
[ConstraintSystem] Record unable to infer base only if hole originated from affected reference
If base type of a unresolved member reference couldn't be determined (represented as a hole type), before recording a fix about lack of contextual information, let's make sure that hole originated in either base or result type of this reference, otherwise the problem is contextual e.g. generic parameter, which supposed to act as contextual type for a reference, couldn't be inferred.
1 parent 923d6ed commit 79a2ab0

File tree

3 files changed

+69
-29
lines changed

3 files changed

+69
-29
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 68 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6966,6 +6966,24 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
69666966

69676967
auto locator = getConstraintLocator(locatorB);
69686968

6969+
auto formUnsolved = [&](bool activate = false) {
6970+
// If requested, generate a constraint.
6971+
if (flags.contains(TMF_GenerateConstraints)) {
6972+
auto *memberRef = Constraint::createMemberOrOuterDisjunction(
6973+
*this, kind, baseTy, memberTy, member, useDC, functionRefKind,
6974+
outerAlternatives, locator);
6975+
6976+
addUnsolvedConstraint(memberRef);
6977+
6978+
if (activate)
6979+
activateConstraint(memberRef);
6980+
6981+
return SolutionKind::Solved;
6982+
}
6983+
6984+
return SolutionKind::Unsolved;
6985+
};
6986+
69696987
// If the base type of this member lookup is a "hole" there is no
69706988
// reason to perform a lookup because it wouldn't return any results.
69716989
if (shouldAttemptFixes()) {
@@ -6977,15 +6995,57 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
69776995
// If this is an unresolved member ref e.g. `.foo` and its contextual base
69786996
// type has been determined to be a "hole", let's mark the resulting member
69796997
// type as a potential hole and continue solving.
6980-
if (kind == ConstraintKind::UnresolvedValueMember &&
6981-
baseObjTy->getMetatypeInstanceType()->isHole()) {
6982-
auto *fix =
6983-
SpecifyBaseTypeForContextualMember::create(*this, member, locator);
6984-
if (recordFix(fix))
6985-
return SolutionKind::Error;
6998+
if (kind == ConstraintKind::UnresolvedValueMember) {
6999+
// Let's look through all metatypes to find "underlying" type
7000+
// of this lookup.
7001+
Type underlyingType = baseObjTy;
7002+
while (auto *MT = underlyingType->getAs<AnyMetatypeType>()) {
7003+
underlyingType = MT->getInstanceType();
7004+
}
7005+
7006+
// Let's delay solving this constraint in diagnostic
7007+
// mode until it's certain that there is no way to
7008+
// find out what the base type is.
7009+
if (underlyingType->isTypeVariableOrMember())
7010+
return formUnsolved();
69867011

6987-
markMemberTypeAsPotentialHole(memberTy);
6988-
return SolutionKind::Solved;
7012+
// Let's record a fix only if the hole originates either
7013+
// at the result of the chain (that could happen since solving
7014+
// of this constraint is delayed until base could be resolved),
7015+
// or it is certain that base type can't be bound to any other
7016+
// type but a hole.
7017+
auto shouldRecordFixForHole = [&](HoleType *baseType) {
7018+
auto *originator =
7019+
baseType->getOriginatorType().dyn_cast<TypeVariableType *>();
7020+
7021+
if (!originator)
7022+
return false;
7023+
7024+
auto *originatorLoc = originator->getImpl().getLocator();
7025+
7026+
// It could either be a hole associated directly with the base
7027+
// or a hole which came from result type of the chain.
7028+
if (originatorLoc->isLastElement<
7029+
LocatorPathElt::UnresolvedMemberChainResult>()) {
7030+
auto *UMCR = castToExpr<UnresolvedMemberChainResultExpr>(
7031+
originatorLoc->getAnchor());
7032+
return UMCR->getChainBase() == getAsExpr(locator->getAnchor());
7033+
}
7034+
7035+
return originatorLoc == locator;
7036+
};
7037+
7038+
if (auto *hole = underlyingType->getAs<HoleType>()) {
7039+
if (shouldRecordFixForHole(hole)) {
7040+
auto *fix = SpecifyBaseTypeForContextualMember::create(*this, member,
7041+
locator);
7042+
if (recordFix(fix))
7043+
return SolutionKind::Error;
7044+
}
7045+
7046+
markMemberTypeAsPotentialHole(memberTy);
7047+
return SolutionKind::Solved;
7048+
}
69897049
} else if ((kind == ConstraintKind::ValueMember ||
69907050
kind == ConstraintKind::ValueWitness) &&
69917051
baseObjTy->getMetatypeInstanceType()->isHole()) {
@@ -7000,24 +7060,6 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
70007060
performMemberLookup(kind, member, baseTy, functionRefKind, locator,
70017061
/*includeInaccessibleMembers*/ shouldAttemptFixes());
70027062

7003-
auto formUnsolved = [&](bool activate = false) {
7004-
// If requested, generate a constraint.
7005-
if (flags.contains(TMF_GenerateConstraints)) {
7006-
auto *memberRef = Constraint::createMemberOrOuterDisjunction(
7007-
*this, kind, baseTy, memberTy, member, useDC, functionRefKind,
7008-
outerAlternatives, locator);
7009-
7010-
addUnsolvedConstraint(memberRef);
7011-
7012-
if (activate)
7013-
activateConstraint(memberRef);
7014-
7015-
return SolutionKind::Solved;
7016-
}
7017-
7018-
return SolutionKind::Unsolved;
7019-
};
7020-
70217063
switch (result.OverallResult) {
70227064
case MemberLookupResult::Unsolved:
70237065
return formUnsolved();

test/Constraints/valid_pointer_conversions.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,4 @@ SR12382(&i) // expected-error {{cannot convert value of type 'UnsafeMutablePoint
4545
//problem/68254165 - Bad diagnostic when using String init(decodingCString:) with an incorrect pointer type
4646
func rdar68254165(ptr: UnsafeMutablePointer<Int8>) {
4747
_ = String(decodingCString: ptr, as: .utf8) // expected-error {{generic parameter 'Encoding' could not be inferred}}
48-
// expected-error@-1 {{type '_.Type' has no member 'utf8'}}
4948
}

test/decl/enum/enumtest.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,7 @@ func test3a(_ a: ZeroOneTwoThree) {
100100
var h = ZeroOneTwoThree(1)
101101

102102
var i = 0 > 3 ? .none : .some(3) // expected-error {{cannot infer contextual base in reference to member 'none'}}
103-
// expected-error@-1 {{cannot infer contextual base in reference to member 'some'}}
104-
103+
105104
test3a; // expected-error {{unused function}}
106105
.Zero // expected-error {{reference to member 'Zero' cannot be resolved without a contextual type}}
107106
test3a // expected-error {{unused function}}

0 commit comments

Comments
 (0)