Skip to content

Commit 58459e7

Browse files
authored
[CS] Allow simplification of key path subscript arg locators (#27194)
[CS] Allow simplification of key path subscript arg locators
2 parents 0bd7621 + 0943176 commit 58459e7

File tree

5 files changed

+247
-198
lines changed

5 files changed

+247
-198
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 0 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -74,202 +74,6 @@ static bool isUnresolvedOrTypeVarType(Type ty) {
7474
return ty->isTypeVariableOrMember() || ty->is<UnresolvedType>();
7575
}
7676

77-
/// Given a subpath of an old locator, compute its summary flags.
78-
static unsigned recomputeSummaryFlags(ConstraintLocator *oldLocator,
79-
ArrayRef<LocatorPathElt> path) {
80-
if (oldLocator->getSummaryFlags() != 0)
81-
return ConstraintLocator::getSummaryFlagsForPath(path);
82-
return 0;
83-
}
84-
85-
ConstraintLocator *
86-
constraints::simplifyLocator(ConstraintSystem &cs, ConstraintLocator *locator,
87-
SourceRange &range) {
88-
auto path = locator->getPath();
89-
auto anchor = locator->getAnchor();
90-
simplifyLocator(anchor, path, range);
91-
92-
// If we didn't simplify anything, just return the input.
93-
if (anchor == locator->getAnchor() &&
94-
path.size() == locator->getPath().size()) {
95-
return locator;
96-
}
97-
98-
// Recompute the summary flags if we had any to begin with. This is
99-
// necessary because we might remove e.g. tuple elements from the path.
100-
unsigned summaryFlags = recomputeSummaryFlags(locator, path);
101-
return cs.getConstraintLocator(anchor, path, summaryFlags);
102-
}
103-
104-
void constraints::simplifyLocator(Expr *&anchor,
105-
ArrayRef<LocatorPathElt> &path,
106-
SourceRange &range) {
107-
range = SourceRange();
108-
109-
while (!path.empty()) {
110-
switch (path[0].getKind()) {
111-
case ConstraintLocator::ApplyArgument: {
112-
// Extract application argument.
113-
if (auto applyExpr = dyn_cast<ApplyExpr>(anchor)) {
114-
anchor = applyExpr->getArg();
115-
path = path.slice(1);
116-
continue;
117-
}
118-
119-
if (auto subscriptExpr = dyn_cast<SubscriptExpr>(anchor)) {
120-
anchor = subscriptExpr->getIndex();
121-
path = path.slice(1);
122-
continue;
123-
}
124-
125-
if (auto objectLiteralExpr = dyn_cast<ObjectLiteralExpr>(anchor)) {
126-
anchor = objectLiteralExpr->getArg();
127-
path = path.slice(1);
128-
continue;
129-
}
130-
131-
if (auto *UME = dyn_cast<UnresolvedMemberExpr>(anchor)) {
132-
anchor = UME->getArgument();
133-
path = path.slice(1);
134-
continue;
135-
}
136-
break;
137-
}
138-
139-
case ConstraintLocator::ApplyFunction:
140-
// Extract application function.
141-
if (auto applyExpr = dyn_cast<ApplyExpr>(anchor)) {
142-
anchor = applyExpr->getFn();
143-
path = path.slice(1);
144-
continue;
145-
}
146-
147-
// The subscript itself is the function.
148-
if (auto subscriptExpr = dyn_cast<SubscriptExpr>(anchor)) {
149-
anchor = subscriptExpr;
150-
path = path.slice(1);
151-
continue;
152-
}
153-
154-
// The unresolved member itself is the function.
155-
if (auto unresolvedMember = dyn_cast<UnresolvedMemberExpr>(anchor)) {
156-
if (unresolvedMember->getArgument()) {
157-
anchor = unresolvedMember;
158-
path = path.slice(1);
159-
continue;
160-
}
161-
}
162-
163-
break;
164-
165-
case ConstraintLocator::AutoclosureResult:
166-
case ConstraintLocator::LValueConversion:
167-
case ConstraintLocator::RValueAdjustment:
168-
case ConstraintLocator::UnresolvedMember:
169-
// Arguments in autoclosure positions, lvalue and rvalue adjustments, and
170-
// scalar-to-tuple conversions, and unresolved members are
171-
// implicit.
172-
path = path.slice(1);
173-
continue;
174-
175-
case ConstraintLocator::NamedTupleElement:
176-
case ConstraintLocator::TupleElement: {
177-
// Extract tuple element.
178-
auto elt = path[0].castTo<LocatorPathElt::AnyTupleElement>();
179-
unsigned index = elt.getIndex();
180-
if (auto tupleExpr = dyn_cast<TupleExpr>(anchor)) {
181-
if (index < tupleExpr->getNumElements()) {
182-
anchor = tupleExpr->getElement(index);
183-
path = path.slice(1);
184-
continue;
185-
}
186-
}
187-
188-
if (auto *CE = dyn_cast<CollectionExpr>(anchor)) {
189-
if (index < CE->getNumElements()) {
190-
anchor = CE->getElement(index);
191-
path = path.slice(1);
192-
continue;
193-
}
194-
}
195-
break;
196-
}
197-
198-
case ConstraintLocator::ApplyArgToParam: {
199-
auto elt = path[0].castTo<LocatorPathElt::ApplyArgToParam>();
200-
// Extract tuple element.
201-
if (auto tupleExpr = dyn_cast<TupleExpr>(anchor)) {
202-
unsigned index = elt.getArgIdx();
203-
if (index < tupleExpr->getNumElements()) {
204-
anchor = tupleExpr->getElement(index);
205-
path = path.slice(1);
206-
continue;
207-
}
208-
}
209-
210-
// Extract subexpression in parentheses.
211-
if (auto parenExpr = dyn_cast<ParenExpr>(anchor)) {
212-
assert(elt.getArgIdx() == 0);
213-
214-
anchor = parenExpr->getSubExpr();
215-
path = path.slice(1);
216-
continue;
217-
}
218-
break;
219-
}
220-
case ConstraintLocator::ConstructorMember:
221-
if (auto typeExpr = dyn_cast<TypeExpr>(anchor)) {
222-
// This is really an implicit 'init' MemberRef, so point at the base,
223-
// i.e. the TypeExpr.
224-
range = SourceRange();
225-
anchor = typeExpr;
226-
path = path.slice(1);
227-
continue;
228-
}
229-
LLVM_FALLTHROUGH;
230-
231-
case ConstraintLocator::Member:
232-
case ConstraintLocator::MemberRefBase:
233-
if (auto UDE = dyn_cast<UnresolvedDotExpr>(anchor)) {
234-
range = UDE->getNameLoc().getSourceRange();
235-
anchor = UDE->getBase();
236-
path = path.slice(1);
237-
continue;
238-
}
239-
break;
240-
241-
case ConstraintLocator::SubscriptMember:
242-
if (isa<SubscriptExpr>(anchor)) {
243-
path = path.slice(1);
244-
continue;
245-
}
246-
break;
247-
248-
case ConstraintLocator::ClosureResult:
249-
if (auto CE = dyn_cast<ClosureExpr>(anchor)) {
250-
if (CE->hasSingleExpressionBody()) {
251-
anchor = CE->getSingleExpressionBody();
252-
path = path.slice(1);
253-
continue;
254-
}
255-
}
256-
break;
257-
258-
case ConstraintLocator::ContextualType:
259-
// This was just for identifying purposes, strip it off.
260-
path = path.slice(1);
261-
continue;
262-
263-
default:
264-
// FIXME: Lots of other cases to handle.
265-
break;
266-
}
267-
268-
// If we get here, we couldn't simplify the path further.
269-
break;
270-
}
271-
}
272-
27377
/// Flags that can be used to control name lookup.
27478
enum TCCFlags {
27579
/// Allow the result of the subexpression to be an lvalue. If this is not

lib/Sema/CSDiagnostics.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,8 +2018,10 @@ bool ContextualFailure::diagnoseConversionToNil() const {
20182018
}
20192019

20202020
// `nil` is passed as an argument to a parameter which doesn't
2021-
// expect it e.g. `foo(a: nil)` or `s[x: nil]`.
2022-
if (isa<ApplyExpr>(enclosingExpr) || isa<SubscriptExpr>(enclosingExpr))
2021+
// expect it e.g. `foo(a: nil)`, `s[x: nil]` or `\S.[x: nil]`.
2022+
// FIXME: Find a more robust way of checking this.
2023+
if (isa<ApplyExpr>(enclosingExpr) || isa<SubscriptExpr>(enclosingExpr) ||
2024+
isa<KeyPathExpr>(enclosingExpr))
20232025
CTP = CTP_CallArgument;
20242026
} else if (auto *CE = dyn_cast<CoerceExpr>(parentExpr)) {
20252027
// `nil` is passed as a left-hand side of the coercion

0 commit comments

Comments
 (0)