Skip to content

[ConstraintSystem] Record unable to infer base only if hole origina… #33842

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 68 additions & 26 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6966,6 +6966,24 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(

auto locator = getConstraintLocator(locatorB);

auto formUnsolved = [&](bool activate = false) {
// If requested, generate a constraint.
if (flags.contains(TMF_GenerateConstraints)) {
auto *memberRef = Constraint::createMemberOrOuterDisjunction(
*this, kind, baseTy, memberTy, member, useDC, functionRefKind,
outerAlternatives, locator);

addUnsolvedConstraint(memberRef);

if (activate)
activateConstraint(memberRef);

return SolutionKind::Solved;
}

return SolutionKind::Unsolved;
};

// If the base type of this member lookup is a "hole" there is no
// reason to perform a lookup because it wouldn't return any results.
if (shouldAttemptFixes()) {
Expand All @@ -6977,15 +6995,57 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
// If this is an unresolved member ref e.g. `.foo` and its contextual base
// type has been determined to be a "hole", let's mark the resulting member
// type as a potential hole and continue solving.
if (kind == ConstraintKind::UnresolvedValueMember &&
baseObjTy->getMetatypeInstanceType()->isHole()) {
auto *fix =
SpecifyBaseTypeForContextualMember::create(*this, member, locator);
if (recordFix(fix))
return SolutionKind::Error;
if (kind == ConstraintKind::UnresolvedValueMember) {
// Let's look through all metatypes to find "underlying" type
// of this lookup.
Type underlyingType = baseObjTy;
while (auto *MT = underlyingType->getAs<AnyMetatypeType>()) {
underlyingType = MT->getInstanceType();
}

// Let's delay solving this constraint in diagnostic
// mode until it's certain that there is no way to
// find out what the base type is.
if (underlyingType->isTypeVariableOrMember())
return formUnsolved();

markMemberTypeAsPotentialHole(memberTy);
return SolutionKind::Solved;
// Let's record a fix only if the hole originates either
// at the result of the chain (that could happen since solving
// of this constraint is delayed until base could be resolved),
// or it is certain that base type can't be bound to any other
// type but a hole.
auto shouldRecordFixForHole = [&](HoleType *baseType) {
auto *originator =
baseType->getOriginatorType().dyn_cast<TypeVariableType *>();

if (!originator)
return false;

auto *originatorLoc = originator->getImpl().getLocator();

// It could either be a hole associated directly with the base
// or a hole which came from result type of the chain.
if (originatorLoc->isLastElement<
LocatorPathElt::UnresolvedMemberChainResult>()) {
auto *UMCR = castToExpr<UnresolvedMemberChainResultExpr>(
originatorLoc->getAnchor());
return UMCR->getChainBase() == getAsExpr(locator->getAnchor());
}

return originatorLoc == locator;
};

if (auto *hole = underlyingType->getAs<HoleType>()) {
if (shouldRecordFixForHole(hole)) {
auto *fix = SpecifyBaseTypeForContextualMember::create(*this, member,
locator);
if (recordFix(fix))
return SolutionKind::Error;
}

markMemberTypeAsPotentialHole(memberTy);
return SolutionKind::Solved;
}
} else if ((kind == ConstraintKind::ValueMember ||
kind == ConstraintKind::ValueWitness) &&
baseObjTy->getMetatypeInstanceType()->isHole()) {
Expand All @@ -7000,24 +7060,6 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
performMemberLookup(kind, member, baseTy, functionRefKind, locator,
/*includeInaccessibleMembers*/ shouldAttemptFixes());

auto formUnsolved = [&](bool activate = false) {
// If requested, generate a constraint.
if (flags.contains(TMF_GenerateConstraints)) {
auto *memberRef = Constraint::createMemberOrOuterDisjunction(
*this, kind, baseTy, memberTy, member, useDC, functionRefKind,
outerAlternatives, locator);

addUnsolvedConstraint(memberRef);

if (activate)
activateConstraint(memberRef);

return SolutionKind::Solved;
}

return SolutionKind::Unsolved;
};

switch (result.OverallResult) {
case MemberLookupResult::Unsolved:
return formUnsolved();
Expand Down
1 change: 0 additions & 1 deletion test/Constraints/valid_pointer_conversions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,4 @@ SR12382(&i) // expected-error {{cannot convert value of type 'UnsafeMutablePoint
//problem/68254165 - Bad diagnostic when using String init(decodingCString:) with an incorrect pointer type
func rdar68254165(ptr: UnsafeMutablePointer<Int8>) {
_ = String(decodingCString: ptr, as: .utf8) // expected-error {{generic parameter 'Encoding' could not be inferred}}
// expected-error@-1 {{type '_.Type' has no member 'utf8'}}
}
3 changes: 1 addition & 2 deletions test/decl/enum/enumtest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@ func test3a(_ a: ZeroOneTwoThree) {
var h = ZeroOneTwoThree(1)

var i = 0 > 3 ? .none : .some(3) // expected-error {{cannot infer contextual base in reference to member 'none'}}
// expected-error@-1 {{cannot infer contextual base in reference to member 'some'}}


test3a; // expected-error {{unused function}}
.Zero // expected-error {{reference to member 'Zero' cannot be resolved without a contextual type}}
test3a // expected-error {{unused function}}
Expand Down