Skip to content

Commit 52a736e

Browse files
authored
Merge pull request #29000 from hborla/unresolved-member-expr-diagnostics
[ConstraintSystem] Finish porting unresolved member reference failures.
2 parents e3b58be + 94bbb8f commit 52a736e

File tree

6 files changed

+25
-76
lines changed

6 files changed

+25
-76
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,6 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
240240
bool visitIdentityExpr(IdentityExpr *E);
241241
bool visitTryExpr(TryExpr *E);
242242

243-
bool visitUnresolvedMemberExpr(UnresolvedMemberExpr *E);
244243
bool visitUnresolvedDotExpr(UnresolvedDotExpr *UDE);
245244
bool visitArrayExpr(ArrayExpr *E);
246245
bool visitDictionaryExpr(DictionaryExpr *E);
@@ -2126,65 +2125,6 @@ bool FailureDiagnosis::visitObjectLiteralExpr(ObjectLiteralExpr *E) {
21262125
return true;
21272126
}
21282127

2129-
bool FailureDiagnosis::visitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
2130-
// If we have no contextual type, there is no way to resolve this. Just
2131-
// diagnose this as an ambiguity.
2132-
if (!CS.getContextualType())
2133-
return false;
2134-
2135-
// OTOH, if we do have a contextual type, we can provide a more specific
2136-
// error. Dig out the UnresolvedValueMember constraint for this expr node.
2137-
Constraint *memberConstraint = nullptr;
2138-
auto checkConstraint = [&](Constraint *C) {
2139-
if (C->getKind() == ConstraintKind::UnresolvedValueMember &&
2140-
simplifyLocatorToAnchor(C->getLocator()) == E)
2141-
memberConstraint = C;
2142-
};
2143-
2144-
if (CS.failedConstraint)
2145-
checkConstraint(CS.failedConstraint);
2146-
for (auto &C : CS.getConstraints()) {
2147-
if (memberConstraint) break;
2148-
checkConstraint(&C);
2149-
}
2150-
2151-
// If we can't find the member constraint in question, then we failed.
2152-
if (!memberConstraint)
2153-
return false;
2154-
2155-
std::function<bool(ArrayRef<OverloadChoice>)> callback = [&](
2156-
ArrayRef<OverloadChoice> candidates) {
2157-
bool hasTrailingClosure = callArgHasTrailingClosure(E->getArgument());
2158-
2159-
// Dump all of our viable candidates into a CalleeCandidateInfo & sort it
2160-
// out.
2161-
CalleeCandidateInfo candidateInfo(Type(), candidates, hasTrailingClosure,
2162-
CS);
2163-
2164-
// Filter the candidate list based on the argument we may or may not have.
2165-
candidateInfo.filterContextualMemberList(E->getArgument());
2166-
2167-
// If we have multiple candidates, then we have an ambiguity.
2168-
if (candidateInfo.size() != 1) {
2169-
SourceRange argRange;
2170-
if (auto arg = E->getArgument())
2171-
argRange = arg->getSourceRange();
2172-
diagnose(E->getNameLoc(), diag::ambiguous_member_overload_set,
2173-
E->getName())
2174-
.highlight(argRange);
2175-
candidateInfo.suggestPotentialOverloads(E->getNameLoc().getBaseNameLoc());
2176-
return true;
2177-
}
2178-
2179-
return false;
2180-
};
2181-
2182-
return diagnoseMemberFailures(E, nullptr, memberConstraint->getKind(),
2183-
memberConstraint->getMember(),
2184-
memberConstraint->getFunctionRefKind(),
2185-
memberConstraint->getLocator(), callback);
2186-
}
2187-
21882128
bool FailureDiagnosis::diagnoseMemberFailures(
21892129
Expr *E, Expr *baseExpr, ConstraintKind lookupKind, DeclNameRef memberName,
21902130
FunctionRefKind funcRefKind, ConstraintLocator *locator,

lib/Sema/CSFix.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -472,14 +472,15 @@ UseSubscriptOperator *UseSubscriptOperator::create(ConstraintSystem &cs,
472472
bool DefineMemberBasedOnUse::diagnose(bool asNote) const {
473473
auto failure = MissingMemberFailure(getConstraintSystem(), BaseType,
474474
Name, getLocator());
475-
return failure.diagnose(asNote);
475+
return AlreadyDiagnosed || failure.diagnose(asNote);
476476
}
477477

478478
DefineMemberBasedOnUse *
479479
DefineMemberBasedOnUse::create(ConstraintSystem &cs, Type baseType,
480-
DeclNameRef member, ConstraintLocator *locator) {
480+
DeclNameRef member, bool alreadyDiagnosed,
481+
ConstraintLocator *locator) {
481482
return new (cs.getAllocator())
482-
DefineMemberBasedOnUse(cs, baseType, member, locator);
483+
DefineMemberBasedOnUse(cs, baseType, member, alreadyDiagnosed, locator);
483484
}
484485

485486
AllowMemberRefOnExistential *

lib/Sema/CSFix.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -806,10 +806,19 @@ class DefineMemberBasedOnUse final : public ConstraintFix {
806806
Type BaseType;
807807
DeclNameRef Name;
808808

809+
/// Whether or not the member error is already diagnosed. This can happen
810+
/// when referencing an erroneous member, and the error is diagnosed at the
811+
/// member declaration.
812+
///
813+
/// We still want to define erroneous members based on use in order to find
814+
/// a solution through the new diagnostic infrastructure, but we don't
815+
/// want to report a second error message.
816+
bool AlreadyDiagnosed;
817+
809818
DefineMemberBasedOnUse(ConstraintSystem &cs, Type baseType, DeclNameRef member,
810-
ConstraintLocator *locator)
819+
bool alreadyDiagnosed, ConstraintLocator *locator)
811820
: ConstraintFix(cs, FixKind::DefineMemberBasedOnUse, locator),
812-
BaseType(baseType), Name(member) {}
821+
BaseType(baseType), Name(member), AlreadyDiagnosed(alreadyDiagnosed) {}
813822

814823
public:
815824
std::string getName() const override {
@@ -822,7 +831,7 @@ class DefineMemberBasedOnUse final : public ConstraintFix {
822831
bool diagnose(bool asNote = false) const override;
823832

824833
static DefineMemberBasedOnUse *create(ConstraintSystem &cs, Type baseType,
825-
DeclNameRef member,
834+
DeclNameRef member, bool alreadyDiagnosed,
826835
ConstraintLocator *locator);
827836
};
828837

lib/Sema/CSSimplify.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6121,8 +6121,6 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
61216121
return formUnsolved();
61226122

61236123
case MemberLookupResult::ErrorAlreadyDiagnosed:
6124-
return SolutionKind::Error;
6125-
61266124
case MemberLookupResult::HasResults:
61276125
// Keep going!
61286126
break;
@@ -6198,8 +6196,10 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
61986196
return type;
61996197
});
62006198

6201-
auto *fix =
6202-
DefineMemberBasedOnUse::create(*this, baseTy, member, locator);
6199+
bool alreadyDiagnosed = (result.OverallResult ==
6200+
MemberLookupResult::ErrorAlreadyDiagnosed);
6201+
auto *fix = DefineMemberBasedOnUse::create(*this, baseTy, member,
6202+
alreadyDiagnosed, locator);
62036203
// Impact is higher if the base is expected to be inferred from context,
62046204
// because a failure to find a member ultimately means that base type is
62056205
// not a match in this case.
@@ -6208,9 +6208,8 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
62086208
if (recordFix(fix, impact))
62096209
return SolutionKind::Error;
62106210

6211-
// Allow member type to default to `Any` to make it possible to form
6212-
// solutions when contextual type of the result cannot be deduced e.g.
6213-
// `let _ = x.foo`.
6211+
// Record a hole for memberTy to make it possible to form solutions
6212+
// when contextual result type cannot be deduced e.g. `let _ = x.foo`.
62146213
if (auto *memberTypeVar = memberTy->getAs<TypeVariableType>())
62156214
recordPotentialHole(memberTypeVar);
62166215

@@ -7860,7 +7859,7 @@ ConstraintSystem::simplifyDynamicCallableApplicableFnConstraint(
78607859
DeclNameRef memberName({ ctx, ctx.Id_dynamicallyCall, {argLabel} });
78617860

78627861
auto *fix = DefineMemberBasedOnUse::create(
7863-
*this, desugar2, memberName,
7862+
*this, desugar2, memberName, /*alreadyDiagnosed=*/false,
78647863
getConstraintLocator(loc, ConstraintLocator::DynamicCallable));
78657864

78667865
if (recordFix(fix))

test/Constraints/diagnostics.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,8 @@ struct Toe {
251251
let toenail: Nail // expected-error {{use of undeclared type 'Nail'}}
252252

253253
func clip() {
254-
toenail.inspect { x in
254+
// FIXME: We shouldn't report this because toenail.inspect is a hole
255+
toenail.inspect { x in // expected-error {{unable to infer closure return type; add explicit type to disambiguate}}
255256
toenail.inspect { y in }
256257
}
257258
}

test/Constraints/rdar46377919.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,4 @@ class Foo {
99

1010
func foo() -> Foo {
1111
return Foo(lhs: 2, rhs: 2)
12-
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '<<error type>>'}}
1312
}

0 commit comments

Comments
 (0)