Skip to content

Commit ca3aa67

Browse files
authored
Merge pull request #31867 from xedin/pinpoint-arg-attr-mismatches
[ConstraintSystem] Add a new locator element - `argument attribute`
2 parents 759a73e + 5db1c70 commit ca3aa67

File tree

6 files changed

+87
-7
lines changed

6 files changed

+87
-7
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,6 +1239,14 @@ bool RValueTreatedAsLValueFailure::diagnoseAsError() {
12391239
if (auto callExpr = dyn_cast<ApplyExpr>(diagExpr)) {
12401240
Expr *argExpr = callExpr->getArg();
12411241
loc = callExpr->getFn()->getLoc();
1242+
auto *locator = getLocator();
1243+
1244+
// `argument attribute` is used for identification purposes
1245+
// only, so it could be looked through in this situation.
1246+
if (locator->isLastElement<LocatorPathElt::ArgumentAttribute>()) {
1247+
auto path = locator->getPath();
1248+
locator = getConstraintLocator(getRawAnchor(), path.drop_back());
1249+
}
12421250

12431251
if (isa<PrefixUnaryExpr>(callExpr) || isa<PostfixUnaryExpr>(callExpr)) {
12441252
subElementDiagID = diag::cannot_apply_lvalue_unop_to_subelement;
@@ -1247,16 +1255,14 @@ bool RValueTreatedAsLValueFailure::diagnoseAsError() {
12471255
} else if (isa<BinaryExpr>(callExpr)) {
12481256
subElementDiagID = diag::cannot_apply_lvalue_binop_to_subelement;
12491257
rvalueDiagID = diag::cannot_apply_lvalue_binop_to_rvalue;
1250-
auto argTuple = dyn_cast<TupleExpr>(argExpr);
1251-
diagExpr = argTuple->getElement(0);
1252-
} else if (getLocator()->getPath().size() > 0) {
1253-
auto argElt =
1254-
getLocator()->castLastElementTo<LocatorPathElt::ApplyArgToParam>();
1255-
1258+
diagExpr = castToExpr(simplifyLocatorToAnchor(locator));
1259+
} else if (auto argElt =
1260+
locator
1261+
->getLastElementAs<LocatorPathElt::ApplyArgToParam>()) {
12561262
subElementDiagID = diag::cannot_pass_rvalue_inout_subelement;
12571263
rvalueDiagID = diag::cannot_pass_rvalue_inout;
12581264
if (auto argTuple = dyn_cast<TupleExpr>(argExpr))
1259-
diagExpr = argTuple->getElement(argElt.getArgIdx());
1265+
diagExpr = argTuple->getElement(argElt->getArgIdx());
12601266
else if (auto parens = dyn_cast<ParenExpr>(argExpr))
12611267
diagExpr = parens->getSubExpr();
12621268
} else {

lib/Sema/CSFix.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ bool TreatRValueAsLValue::diagnose(const Solution &solution,
119119

120120
TreatRValueAsLValue *TreatRValueAsLValue::create(ConstraintSystem &cs,
121121
ConstraintLocator *locator) {
122+
if (locator->isLastElement<LocatorPathElt::ApplyArgToParam>())
123+
locator = cs.getConstraintLocator(
124+
locator, LocatorPathElt::ArgumentAttribute::forInOut());
125+
122126
return new (cs.getAllocator()) TreatRValueAsLValue(cs, locator);
123127
}
124128

@@ -168,6 +172,10 @@ bool MarkExplicitlyEscaping::diagnose(const Solution &solution,
168172
MarkExplicitlyEscaping *
169173
MarkExplicitlyEscaping::create(ConstraintSystem &cs, Type lhs, Type rhs,
170174
ConstraintLocator *locator) {
175+
if (locator->isLastElement<LocatorPathElt::ApplyArgToParam>())
176+
locator = cs.getConstraintLocator(
177+
locator, LocatorPathElt::ArgumentAttribute::forEscaping());
178+
171179
return new (cs.getAllocator()) MarkExplicitlyEscaping(cs, lhs, rhs, locator);
172180
}
173181

lib/Sema/ConstraintLocator.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ void ConstraintLocator::Profile(llvm::FoldingSetNodeID &id, ASTNode anchor,
5757
id.AddPointer(elt.castTo<LocatorPathElt::PatternMatch>().getPattern());
5858
break;
5959

60+
case ArgumentAttribute:
6061
case GenericArgument:
6162
case NamedTupleElement:
6263
case TupleElement:
@@ -125,6 +126,7 @@ unsigned LocatorPathElt::getNewSummaryFlags() const {
125126
case ConstraintLocator::ImplicitCallAsFunction:
126127
case ConstraintLocator::TernaryBranch:
127128
case ConstraintLocator::PatternMatch:
129+
case ConstraintLocator::ArgumentAttribute:
128130
return 0;
129131

130132
case ConstraintLocator::FunctionArgument:
@@ -500,6 +502,25 @@ void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) const {
500502
case PatternMatch:
501503
out << "pattern match";
502504
break;
505+
506+
case ArgumentAttribute: {
507+
using AttrLoc = LocatorPathElt::ArgumentAttribute;
508+
509+
auto attrElt = elt.castTo<AttrLoc>();
510+
out << "argument attribute: ";
511+
512+
switch (attrElt.getAttr()) {
513+
case AttrLoc::Attribute::InOut:
514+
out << "inout";
515+
break;
516+
517+
case AttrLoc::Attribute::Escaping:
518+
out << "@escaping";
519+
break;
520+
}
521+
522+
break;
523+
}
503524
}
504525
}
505526
out << ']';

lib/Sema/ConstraintLocator.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
8686
case SynthesizedArgument:
8787
case KeyPathDynamicMember:
8888
case TernaryBranch:
89+
case ArgumentAttribute:
8990
return 1;
9091

9192
case TypeParameterRequirement:
@@ -847,6 +848,31 @@ class LocatorPathElt::PatternMatch final : public LocatorPathElt {
847848
}
848849
};
849850

851+
class LocatorPathElt::ArgumentAttribute final : public LocatorPathElt {
852+
public:
853+
enum Attribute : uint8_t { InOut, Escaping };
854+
855+
private:
856+
ArgumentAttribute(Attribute attr)
857+
: LocatorPathElt(ConstraintLocator::ArgumentAttribute,
858+
static_cast<uint8_t>(attr)) {}
859+
860+
public:
861+
Attribute getAttr() const { return static_cast<Attribute>(getValue(0)); }
862+
863+
static ArgumentAttribute forInOut() {
864+
return ArgumentAttribute(Attribute::InOut);
865+
}
866+
867+
static ArgumentAttribute forEscaping() {
868+
return ArgumentAttribute(Attribute::Escaping);
869+
}
870+
871+
static bool classof(const LocatorPathElt *elt) {
872+
return elt->getKind() == ConstraintLocator::ArgumentAttribute;
873+
}
874+
};
875+
850876
/// A simple stack-only builder object that constructs a
851877
/// constraint locator without allocating memory.
852878
///

lib/Sema/ConstraintLocatorPathElts.def

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ CUSTOM_LOCATOR_PATH_ELT(TernaryBranch)
181181
/// Performing a pattern patch.
182182
CUSTOM_LOCATOR_PATH_ELT(PatternMatch)
183183

184+
/// Points to a particular attribute associated with one of
185+
/// the arguments e.g. `inout` or its type e.g. `@escaping`.
186+
///
187+
/// This is very useful when dealing with argument-to-parameter
188+
/// failures because it allows to express in the locator kind
189+
/// of a problem.
190+
CUSTOM_LOCATOR_PATH_ELT(ArgumentAttribute)
191+
184192
#undef LOCATOR_PATH_ELT
185193
#undef CUSTOM_LOCATOR_PATH_ELT
186194
#undef SIMPLE_LOCATOR_PATH_ELT

lib/Sema/ConstraintSystem.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,10 @@ ConstraintLocator *ConstraintSystem::getCalleeLocator(
462462
return getConstraintLocator(anchor, LocatorPathElt::ApplyFunction());
463463
}
464464

465+
if (locator->isLastElement<LocatorPathElt::ArgumentAttribute>()) {
466+
return getConstraintLocator(anchor, path.drop_back());
467+
}
468+
465469
// If we have a locator that starts with a key path component element, we
466470
// may have a callee given by a property or subscript component.
467471
if (auto componentElt =
@@ -3524,6 +3528,13 @@ void constraints::simplifyLocator(ASTNode &anchor,
35243528
continue;
35253529
}
35263530

3531+
case ConstraintLocator::ArgumentAttribute: {
3532+
// At this point we should have already found argument expression
3533+
// this attribute belogs to, so we can leave this element in place
3534+
// because it points out exact location useful for diagnostics.
3535+
break;
3536+
}
3537+
35273538
default:
35283539
// FIXME: Lots of other cases to handle.
35293540
break;

0 commit comments

Comments
 (0)