Skip to content

Commit 2788747

Browse files
authored
Merge pull request #31479 from xedin/audit-use-of-cs-in-diags
[Diagnostics] Audit use of constraint system in diagnostics
2 parents 278fb49 + 786b16c commit 2788747

File tree

4 files changed

+99
-53
lines changed

4 files changed

+99
-53
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 77 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,20 @@ bool FailureDiagnostic::diagnoseAsNote() {
5252
}
5353

5454
ASTNode FailureDiagnostic::getAnchor() const {
55-
auto &cs = getConstraintSystem();
56-
5755
auto *locator = getLocator();
5856
// Resolve the locator to a specific expression.
59-
SourceRange range;
60-
ConstraintLocator *resolved = simplifyLocator(cs, locator, range);
61-
if (!resolved || !resolved->getAnchor())
62-
return locator->getAnchor();
6357

64-
auto anchor = resolved->getAnchor();
58+
auto anchor = locator->getAnchor();
59+
60+
{
61+
SourceRange range;
62+
auto path = locator->getPath();
63+
64+
simplifyLocator(anchor, path, range);
65+
if (!anchor)
66+
return locator->getAnchor();
67+
}
68+
6569
// FIXME: Work around an odd locator representation that doesn't separate the
6670
// base of a subscript member from the member access.
6771
if (locator->isLastElement<LocatorPathElt::SubscriptMember>()) {
@@ -73,7 +77,11 @@ ASTNode FailureDiagnostic::getAnchor() const {
7377
}
7478

7579
Type FailureDiagnostic::getType(ASTNode node, bool wantRValue) const {
76-
return resolveType(S.getType(node), /*reconstituteSugar=*/false, wantRValue);
80+
return resolveType(getRawType(node), /*reconstituteSugar=*/false, wantRValue);
81+
}
82+
83+
Type FailureDiagnostic::getRawType(ASTNode node) const {
84+
return S.getType(node);
7785
}
7886

7987
template <typename... ArgTypes>
@@ -146,6 +154,18 @@ Type FailureDiagnostic::restoreGenericParameters(
146154
});
147155
}
148156

157+
bool FailureDiagnostic::conformsToKnownProtocol(
158+
Type type, KnownProtocolKind protocol) const {
159+
auto &cs = getConstraintSystem();
160+
return constraints::conformsToKnownProtocol(cs, type, protocol);
161+
}
162+
163+
Type FailureDiagnostic::isRawRepresentable(Type type,
164+
KnownProtocolKind protocol) const {
165+
auto &cs = getConstraintSystem();
166+
return constraints::isRawRepresentable(cs, type, protocol);
167+
}
168+
149169
Type RequirementFailure::getOwnerType() const {
150170
auto anchor = getRawAnchor();
151171

@@ -183,7 +203,7 @@ const Requirement &RequirementFailure::getRequirement() const {
183203

184204
ProtocolConformance *RequirementFailure::getConformanceForConditionalReq(
185205
ConstraintLocator *locator) {
186-
auto &cs = getConstraintSystem();
206+
auto &solution = getSolution();
187207
auto reqElt = locator->castLastElementTo<LocatorPathElt::AnyRequirement>();
188208
if (!reqElt.isConditionalRequirement())
189209
return nullptr;
@@ -192,10 +212,10 @@ ProtocolConformance *RequirementFailure::getConformanceForConditionalReq(
192212
auto *typeReqLoc = getConstraintLocator(getRawAnchor(), path.drop_back());
193213

194214
auto result = llvm::find_if(
195-
cs.CheckedConformances,
215+
solution.Conformances,
196216
[&](const std::pair<ConstraintLocator *, ProtocolConformanceRef>
197217
&conformance) { return conformance.first == typeReqLoc; });
198-
assert(result != cs.CheckedConformances.end());
218+
assert(result != solution.Conformances.end());
199219

200220
auto conformance = result->second;
201221
assert(conformance.isConcrete());
@@ -407,9 +427,8 @@ bool MissingConformanceFailure::diagnoseAsError() {
407427
if (auto *binaryOp = dyn_cast_or_null<BinaryExpr>(findParentExpr(anchor))) {
408428
auto *caseExpr = binaryOp->getArg()->getElement(0);
409429

410-
auto &cs = getConstraintSystem();
411430
llvm::SmallPtrSet<Expr *, 4> anchors;
412-
for (const auto *fix : cs.getFixes()) {
431+
for (const auto *fix : getSolution().Fixes) {
413432
if (auto anchor = fix->getAnchor()) {
414433
if (anchor.is<Expr *>())
415434
anchors.insert(getAsExpr(anchor));
@@ -1262,12 +1281,11 @@ bool RValueTreatedAsLValueFailure::diagnoseAsError() {
12621281
ParameterTypeFlags())});
12631282

12641283
if (auto info = getFunctionArgApplyInfo(argLoc)) {
1265-
auto &cs = getConstraintSystem();
12661284
auto paramType = info->getParamType();
12671285
auto argType = getType(inoutExpr)->getWithoutSpecifierType();
12681286

12691287
PointerTypeKind ptr;
1270-
if (cs.isArrayType(argType) &&
1288+
if (isArrayType(argType) &&
12711289
paramType->getAnyPointerElementType(ptr) &&
12721290
(ptr == PTK_UnsafePointer || ptr == PTK_UnsafeRawPointer)) {
12731291
emitDiagnosticAt(inoutExpr->getLoc(),
@@ -2021,8 +2039,7 @@ bool ContextualFailure::diagnoseAsError() {
20212039
}
20222040

20232041
case ConstraintLocator::RValueAdjustment: {
2024-
auto &cs = getConstraintSystem();
2025-
2042+
auto &solution = getSolution();
20262043
auto overload = getOverloadChoiceIfAvailable(
20272044
getConstraintLocator(anchor, ConstraintLocator::UnresolvedMember));
20282045
if (!(overload && overload->choice.isDecl()))
@@ -2048,8 +2065,11 @@ bool ContextualFailure::diagnoseAsError() {
20482065

20492066
auto params = fnType->getParams();
20502067

2051-
ParameterListInfo info(params, choice,
2052-
hasAppliedSelf(cs, overload->choice));
2068+
ParameterListInfo info(
2069+
params, choice,
2070+
hasAppliedSelf(overload->choice, [&solution](Type type) {
2071+
return solution.simplifyType(type);
2072+
}));
20532073
auto numMissingArgs = llvm::count_if(
20542074
indices(params), [&info](const unsigned paramIdx) -> bool {
20552075
return !info.hasDefaultArgument(paramIdx);
@@ -2402,9 +2422,8 @@ bool ContextualFailure::diagnoseConversionToBool() const {
24022422

24032423
// If we're trying to convert something from optional type to an integer, then
24042424
// a comparison against nil was probably expected.
2405-
auto &cs = getConstraintSystem();
2406-
if (conformsToKnownProtocol(cs, fromType, KnownProtocolKind::BinaryInteger) &&
2407-
conformsToKnownProtocol(cs, fromType,
2425+
if (conformsToKnownProtocol(fromType, KnownProtocolKind::BinaryInteger) &&
2426+
conformsToKnownProtocol(fromType,
24082427
KnownProtocolKind::ExpressibleByIntegerLiteral)) {
24092428
StringRef prefix = "((";
24102429
StringRef suffix;
@@ -2499,7 +2518,6 @@ bool ContextualFailure::diagnoseYieldByReferenceMismatch() const {
24992518
bool ContextualFailure::tryRawRepresentableFixIts(
25002519
InFlightDiagnostic &diagnostic,
25012520
KnownProtocolKind rawRepresentableProtocol) const {
2502-
auto &CS = getConstraintSystem();
25032521
auto anchor = getAnchor();
25042522
auto fromType = getFromType();
25052523
auto toType = getToType();
@@ -2554,14 +2572,14 @@ bool ContextualFailure::tryRawRepresentableFixIts(
25542572
}
25552573
};
25562574

2557-
if (conformsToKnownProtocol(CS, fromType, rawRepresentableProtocol)) {
2558-
if (conformsToKnownProtocol(CS, fromType, KnownProtocolKind::OptionSet) &&
2575+
if (conformsToKnownProtocol(fromType, rawRepresentableProtocol)) {
2576+
if (conformsToKnownProtocol(fromType, KnownProtocolKind::OptionSet) &&
25592577
isExpr<IntegerLiteralExpr>(anchor) &&
25602578
castToExpr<IntegerLiteralExpr>(anchor)->getDigitsText() == "0") {
25612579
diagnostic.fixItReplace(::getSourceRange(anchor), "[]");
25622580
return true;
25632581
}
2564-
if (auto rawTy = isRawRepresentable(CS, toType, rawRepresentableProtocol)) {
2582+
if (auto rawTy = isRawRepresentable(toType, rawRepresentableProtocol)) {
25652583
// Produce before/after strings like 'Result(rawValue: RawType(<expr>))'
25662584
// or just 'Result(rawValue: <expr>)'.
25672585
std::string convWrapBefore = toType.getString();
@@ -2591,8 +2609,8 @@ bool ContextualFailure::tryRawRepresentableFixIts(
25912609
}
25922610
}
25932611

2594-
if (auto rawTy = isRawRepresentable(CS, fromType, rawRepresentableProtocol)) {
2595-
if (conformsToKnownProtocol(CS, toType, rawRepresentableProtocol)) {
2612+
if (auto rawTy = isRawRepresentable(fromType, rawRepresentableProtocol)) {
2613+
if (conformsToKnownProtocol(toType, rawRepresentableProtocol)) {
25962614
std::string convWrapBefore;
25972615
std::string convWrapAfter = ".rawValue";
25982616
if (!TypeChecker::isConvertibleTo(rawTy, toType, getDC())) {
@@ -2873,12 +2891,11 @@ void ContextualFailure::tryComputedPropertyFixIts() const {
28732891
}
28742892

28752893
bool ContextualFailure::isIntegerToStringIndexConversion() const {
2876-
auto &cs = getConstraintSystem();
28772894
auto kind = KnownProtocolKind::ExpressibleByIntegerLiteral;
28782895

28792896
auto fromType = getFromType();
28802897
auto toType = getToType()->getCanonicalType();
2881-
return (conformsToKnownProtocol(cs, fromType, kind) &&
2898+
return (conformsToKnownProtocol(fromType, kind) &&
28822899
toType.getString() == "String.CharacterView.Index");
28832900
}
28842901

@@ -3135,12 +3152,18 @@ bool MissingPropertyWrapperUnwrapFailure::diagnoseAsError() {
31353152
}
31363153

31373154
bool SubscriptMisuseFailure::diagnoseAsError() {
3155+
auto *locator = getLocator();
31383156
auto &sourceMgr = getASTContext().SourceMgr;
31393157

31403158
auto *memberExpr = castToExpr<UnresolvedDotExpr>(getRawAnchor());
31413159

31423160
auto memberRange = getSourceRange();
3143-
(void)simplifyLocator(getConstraintSystem(), getLocator(), memberRange);
3161+
3162+
{
3163+
auto rawAnchor = getRawAnchor();
3164+
auto path = locator->getPath();
3165+
simplifyLocator(rawAnchor, path, memberRange);
3166+
}
31443167

31453168
auto nameLoc = DeclNameLoc(memberRange.Start);
31463169

@@ -3170,7 +3193,7 @@ bool SubscriptMisuseFailure::diagnoseAsError() {
31703193
}
31713194
diag.flush();
31723195

3173-
if (auto overload = getOverloadChoiceIfAvailable(getLocator())) {
3196+
if (auto overload = getOverloadChoiceIfAvailable(locator)) {
31743197
emitDiagnosticAt(overload->choice.getDecl(), diag::kind_declared_here,
31753198
DescriptiveDeclKind::Subscript);
31763199
}
@@ -3402,27 +3425,26 @@ bool MissingMemberFailure::diagnoseForDynamicCallable() const {
34023425
}
34033426

34043427
bool MissingMemberFailure::diagnoseInLiteralCollectionContext() const {
3405-
auto &cs = getConstraintSystem();
34063428
auto *expr = castToExpr(getAnchor());
3407-
auto *parentExpr = cs.getParentExpr(expr);
3429+
auto *parentExpr = findParentExpr(expr);
34083430
auto &solution = getSolution();
34093431

34103432
if (!(parentExpr && isa<UnresolvedMemberExpr>(expr)))
34113433
return false;
34123434

34133435
auto parentType = getType(parentExpr);
34143436

3415-
if (!cs.isCollectionType(parentType) && !parentType->is<TupleType>())
3437+
if (!isCollectionType(parentType) && !parentType->is<TupleType>())
34163438
return false;
34173439

34183440
if (isa<TupleExpr>(parentExpr)) {
3419-
parentExpr = cs.getParentExpr(parentExpr);
3441+
parentExpr = findParentExpr(parentExpr);
34203442
if (!parentExpr)
34213443
return false;
34223444
}
34233445

34243446
if (auto *defaultableVar =
3425-
cs.getType(parentExpr)->getAs<TypeVariableType>()) {
3447+
getRawType(parentExpr)->getAs<TypeVariableType>()) {
34263448
if (solution.DefaultedConstraints.count(
34273449
defaultableVar->getImpl().getLocator()) != 0) {
34283450
emitDiagnostic(diag::unresolved_member_no_inference, getName());
@@ -4261,12 +4283,11 @@ bool MissingArgumentsFailure::isMisplacedMissingArgument(
42614283
return (*fix)->getKind() == kind;
42624284
};
42634285

4264-
auto &cs = solution.getConstraintSystem();
42654286
auto *callLocator =
4266-
cs.getConstraintLocator(anchor, ConstraintLocator::ApplyArgument);
4287+
solution.getConstraintLocator(anchor, {ConstraintLocator::ApplyArgument});
42674288

42684289
auto argFlags = fnType->getParams()[0].getParameterFlags();
4269-
auto *argLoc = cs.getConstraintLocator(
4290+
auto *argLoc = solution.getConstraintLocator(
42704291
callLocator, LocatorPathElt::ApplyArgToParam(0, 0, argFlags));
42714292

42724293
if (!(hasFixFor(FixKind::AllowArgumentTypeMismatch, argLoc) &&
@@ -4295,7 +4316,7 @@ bool MissingArgumentsFailure::isMisplacedMissingArgument(
42954316
auto argType = solution.simplifyType(solution.getType(argument));
42964317
auto paramType = fnType->getParams()[1].getPlainType();
42974318

4298-
return TypeChecker::isConvertibleTo(argType, paramType, cs.DC);
4319+
return TypeChecker::isConvertibleTo(argType, paramType, solution.getDC());
42994320
}
43004321

43014322
std::tuple<Expr *, Expr *, unsigned, bool>
@@ -5053,7 +5074,7 @@ bool MissingGenericArgumentsFailure::diagnoseForAnchor(
50535074

50545075
bool MissingGenericArgumentsFailure::diagnoseParameter(
50555076
Anchor anchor, GenericTypeParamType *GP) const {
5056-
auto &cs = getConstraintSystem();
5077+
auto &solution = getSolution();
50575078

50585079
auto loc = anchor.is<Expr *>() ? anchor.get<Expr *>()->getLoc()
50595080
: anchor.get<TypeRepr *>()->getLoc();
@@ -5063,7 +5084,7 @@ bool MissingGenericArgumentsFailure::diagnoseParameter(
50635084
// going to be completely cut off from the rest of constraint system,
50645085
// that's why we'd get two fixes in this case which is not ideal.
50655086
if (locator->isForContextualType() &&
5066-
llvm::count_if(cs.DefaultedConstraints,
5087+
llvm::count_if(solution.DefaultedConstraints,
50675088
[&GP](const ConstraintLocator *locator) {
50685089
return locator->getGenericParameter() == GP;
50695090
}) > 1) {
@@ -5103,7 +5124,7 @@ bool MissingGenericArgumentsFailure::diagnoseParameter(
51035124

51045125
void MissingGenericArgumentsFailure::emitGenericSignatureNote(
51055126
Anchor anchor) const {
5106-
auto &cs = getConstraintSystem();
5127+
auto &solution = getSolution();
51075128
auto *paramDC = getDeclContext();
51085129

51095130
if (!paramDC)
@@ -5121,7 +5142,9 @@ void MissingGenericArgumentsFailure::emitGenericSignatureNote(
51215142
};
51225143

51235144
llvm::SmallDenseMap<GenericTypeParamDecl *, Type> params;
5124-
for (auto *typeVar : cs.getTypeVariables()) {
5145+
for (auto &entry : solution.typeBindings) {
5146+
auto *typeVar = entry.first;
5147+
51255148
auto *GP = typeVar->getImpl().getGenericParameter();
51265149
if (!GP)
51275150
continue;
@@ -5131,7 +5154,7 @@ void MissingGenericArgumentsFailure::emitGenericSignatureNote(
51315154

51325155
// If this is one of the defaulted parameter types, attempt
51335156
// to emit placeholder for it instead of `Any`.
5134-
if (llvm::any_of(cs.DefaultedConstraints,
5157+
if (llvm::any_of(solution.DefaultedConstraints,
51355158
[&](const ConstraintLocator *locator) {
51365159
return GP->getDecl() == getParamDecl(locator);
51375160
}))
@@ -5558,11 +5581,14 @@ bool ArgumentMismatchFailure::diagnoseUseOfReferenceEqualityOperator() const {
55585581
// let's avoid producing a diagnostic second time, because first
55595582
// one would cover both arguments.
55605583
if (getAsExpr(getAnchor()) == rhs && rhsType->is<FunctionType>()) {
5561-
auto &cs = getConstraintSystem();
5562-
if (cs.hasFixFor(getConstraintLocator(
5563-
binaryOp, {ConstraintLocator::ApplyArgument,
5564-
LocatorPathElt::ApplyArgToParam(
5565-
0, 0, getParameterFlagsAtIndex(0))})))
5584+
auto *argLoc = getConstraintLocator(
5585+
binaryOp,
5586+
{ConstraintLocator::ApplyArgument,
5587+
LocatorPathElt::ApplyArgToParam(0, 0, getParameterFlagsAtIndex(0))});
5588+
5589+
if (llvm::any_of(getSolution().Fixes, [&argLoc](const ConstraintFix *fix) {
5590+
return fix->getLocator() == argLoc;
5591+
}))
55665592
return true;
55675593
}
55685594

lib/Sema/CSDiagnostics.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ class FailureDiagnostic {
8686

8787
Type getType(ASTNode node, bool wantRValue = true) const;
8888

89+
/// Get type associated with a given ASTNode without resolving it,
90+
/// which means that returned type would have type variables.
91+
Type getRawType(ASTNode node) const;
92+
8993
/// Resolve type variables present in the raw type, if any.
9094
Type resolveType(Type rawType, bool reconstituteSugar = false,
9195
bool wantRValue = true) const {
@@ -202,6 +206,19 @@ class FailureDiagnostic {
202206
Type type,
203207
llvm::function_ref<void(GenericTypeParamType *, Type)> substitution =
204208
[](GenericTypeParamType *, Type) {});
209+
210+
bool isCollectionType(Type type) const {
211+
auto &cs = getConstraintSystem();
212+
return cs.isCollectionType(type);
213+
}
214+
215+
bool isArrayType(Type type) const {
216+
auto &cs = getConstraintSystem();
217+
return bool(cs.isArrayType(type));
218+
}
219+
220+
bool conformsToKnownProtocol(Type type, KnownProtocolKind protocol) const;
221+
Type isRawRepresentable(Type type, KnownProtocolKind protocol) const;
205222
};
206223

207224
/// Base class for all of the diagnostics related to generic requirement
@@ -658,8 +675,7 @@ class ContextualFailure : public FailureDiagnostic {
658675

659676
bool isIntegerType(Type type) const {
660677
return conformsToKnownProtocol(
661-
getConstraintSystem(), type,
662-
KnownProtocolKind::ExpressibleByIntegerLiteral);
678+
type, KnownProtocolKind::ExpressibleByIntegerLiteral);
663679
}
664680

665681
/// Return true if the conversion from fromType to toType is

lib/Sema/ConstraintSystem.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2508,6 +2508,8 @@ size_t Solution::getTotalMemory() const {
25082508
Conformances.size() * sizeof(std::pair<ConstraintLocator *, ProtocolConformanceRef>);
25092509
}
25102510

2511+
DeclContext *Solution::getDC() const { return constraintSystem->DC; }
2512+
25112513
DeclName OverloadChoice::getName() const {
25122514
switch (getKind()) {
25132515
case OverloadChoiceKind::Decl:

0 commit comments

Comments
 (0)