Skip to content

Commit edd8f70

Browse files
committed
Sema: Change the diagnostic to choices made by the constraint system
1 parent 4f1dbdb commit edd8f70

File tree

2 files changed

+60
-28
lines changed

2 files changed

+60
-28
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,35 @@ Expr *FailureDiagnostic::getArgumentExprFor(Expr *anchor) const {
101101
return nullptr;
102102
}
103103

104+
// TODO: Replace duplications of this logic with calls to this.
105+
Optional<SelectedOverload> FailureDiagnostic::getChoiceFor(Expr *expr) {
106+
auto &cs = getConstraintSystem();
107+
ConstraintLocator *locator = nullptr;
108+
109+
if (auto *call = dyn_cast<CallExpr>(expr)) {
110+
auto *fnExpr = call->getFn();
111+
return getChoiceFor(fnExpr);
112+
} else if (auto *UDE = dyn_cast<UnresolvedDotExpr>(expr)) {
113+
locator = cs.getConstraintLocator(UDE, ConstraintLocator::Member);
114+
} else if (auto *UME = dyn_cast<UnresolvedMemberExpr>(expr)) {
115+
locator = cs.getConstraintLocator(UME, ConstraintLocator::UnresolvedMember);
116+
} else if (auto *TE = dyn_cast<TypeExpr>(expr)) {
117+
locator = cs.getConstraintLocator(call,
118+
{ConstraintLocator::ApplyFunction,
119+
ConstraintLocator::ConstructorMember},
120+
/*summaryFlags=*/0);
121+
} else if (auto *SE = dyn_cast<SubscriptExpr>(expr)) {
122+
locator = cs.getConstraintLocator(SE, ConstraintLocator::SubscriptMember);
123+
} else {
124+
locator = cs.getConstraintLocator(expr);
125+
}
126+
127+
if(!locator)
128+
return None;
129+
130+
return getOverloadChoiceIfAvailable(locator);
131+
}
132+
104133
Type RequirementFailure::getOwnerType() const {
105134
return getType(getRawAnchor())
106135
->getInOutObjectType()
@@ -2042,42 +2071,43 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() {
20422071
emitDiagnostic(loc, diag::super_initializer_not_in_initializer);
20432072
return true;
20442073
}
2074+
2075+
auto isInsideCall = [this](Expr *expr) {
2076+
auto &cs = getConstraintSystem();
2077+
auto argExpr = cs.getParentExpr(expr);
2078+
if (!argExpr)
2079+
return false;
2080+
auto possibleCallExpr = cs.getParentExpr(expr);
2081+
return possibleCallExpr && isa<CallExpr>(possibleCallExpr);
2082+
};
2083+
2084+
auto *initCall = cs.getParentExpr(cs.getParentExpr(ctorRef));
2085+
2086+
auto isImmutable = [&DC](ValueDecl *decl) {
2087+
if (auto *storage = dyn_cast<AbstractStorageDecl>(decl))
2088+
return !storage->isSettable(DC) ||
2089+
!storage->isSetterAccessibleFrom(DC);
20452090

2046-
// Dig through the chain of member accesses until we find the last
2047-
// UnresolvedDotExpr.
2048-
auto *lastUnresolved = ctorRef;
2049-
while (auto *nextMember =
2050-
dyn_cast_or_null<UnresolvedDotExpr>(lastUnresolved->getBase()))
2051-
lastUnresolved = nextMember;
2052-
2053-
if (auto *DRE = dyn_cast<DeclRefExpr>(lastUnresolved->getBase())) {
2054-
auto isInsideCall = [this](Expr *expr) {
2055-
auto &cs = getConstraintSystem();
2056-
auto argExpr = cs.getParentExpr(expr);
2057-
if (!argExpr)
2058-
return false;
2059-
auto possibleCallExpr = cs.getParentExpr(expr);
2060-
return possibleCallExpr && isa<CallExpr>(possibleCallExpr);
2061-
};
2062-
2063-
auto *initCall = cs.getParentExpr(cs.getParentExpr(ctorRef));
2064-
2065-
// We can only check if the base is settable here so provide the
2066-
// assignment diagnostic as it's our best guess.
2067-
if (DRE->getDecl()->isSettable(DC, DRE) && !isInsideCall(initCall) &&
2091+
return false;
2092+
};
2093+
2094+
auto selection = getChoiceFor(ctorRef->getBase());
2095+
if (selection) {
2096+
OverloadChoice choice = selection.getValue().choice;
2097+
if (choice.isDecl() && !isImmutable(choice.getDecl()) && !isInsideCall(initCall) &&
20682098
cs.getContextualTypePurpose() == CTP_Unused) {
20692099
auto fixItLoc = ctorRef->getBase()->getSourceRange().End;
20702100
emitDiagnostic(loc, diag::init_not_instance_member_use_assignment)
20712101
.fixItInsertAfter(fixItLoc, " = ");
20722102
return true;
20732103
}
2074-
}
20752104

2076-
SourceRange fixItRng = ctorRef->getNameLoc().getSourceRange();
2077-
emitDiagnostic(loc, diag::init_not_instance_member)
2078-
.fixItInsert(fixItRng.Start, "type(of: ")
2079-
.fixItInsertAfter(fixItRng.End, ")");
2080-
return true;
2105+
SourceRange fixItRng = ctorRef->getNameLoc().getSourceRange();
2106+
emitDiagnostic(loc, diag::init_not_instance_member)
2107+
.fixItInsert(fixItRng.Start, "type(of: ")
2108+
.fixItInsertAfter(fixItRng.End, ")");
2109+
return true;
2110+
}
20812111
}
20822112
}
20832113

lib/Sema/CSDiagnostics.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ class FailureDiagnostic {
154154
/// \returns An argument expression if given anchor is a call, member
155155
/// reference or subscript, nullptr otherwise.
156156
Expr *getArgumentExprFor(Expr *anchor) const;
157+
158+
Optional<SelectedOverload> getChoiceFor(Expr *);
157159

158160
private:
159161
/// Compute anchor expression associated with current diagnostic.

0 commit comments

Comments
 (0)