Skip to content

Commit 1892356

Browse files
committed
[Sema] Move member chain transformation into precheck
Move the analysis and transformation of unresolved member chains into the PreCheckExpression pass in order to make sure that contextual types get hooked up properly before we actually begin generating constraints.
1 parent 74d0040 commit 1892356

File tree

4 files changed

+61
-76
lines changed

4 files changed

+61
-76
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,8 @@ void MissingOptionalUnwrapFailure::offerDefaultValueUnwrapFixIt(
11311131
bool needsParensInside =
11321132
exprNeedsParensBeforeAddingNilCoalescing(DC, const_cast<Expr *>(expr));
11331133
auto parentExpr = findParentExpr(anchor);
1134+
if (parentExpr && isa<UnresolvedMemberChainResultExpr>(parentExpr))
1135+
parentExpr = findParentExpr(parentExpr);
11341136
bool needsParensOutside = exprNeedsParensAfterAddingNilCoalescing(
11351137
DC, const_cast<Expr *>(expr), parentExpr);
11361138

@@ -6325,6 +6327,12 @@ bool MissingContextualBaseInMemberRefFailure::diagnoseAsError() {
63256327
// Member reference could be wrapped into a number of parens
63266328
// e.g. `((.foo))`.
63276329
auto *parentExpr = findParentExpr(anchor);
6330+
UnresolvedMemberChainResultExpr *resultExpr = nullptr;
6331+
if (parentExpr && isa<UnresolvedMemberChainResultExpr>(parentExpr)) {
6332+
resultExpr = cast<UnresolvedMemberChainResultExpr>(parentExpr);
6333+
parentExpr = findParentExpr(parentExpr);
6334+
}
6335+
63286336
do {
63296337
// If we have found something which isn't a paren let's stop,
63306338
// otherwise let's keep unwrapping until there are either no
@@ -6333,7 +6341,7 @@ bool MissingContextualBaseInMemberRefFailure::diagnoseAsError() {
63336341
break;
63346342
} while ((parentExpr = findParentExpr(parentExpr)));
63356343

6336-
auto diagnostic = parentExpr || getContextualType(anchor)
6344+
auto diagnostic = parentExpr || (resultExpr && getContextualType(resultExpr))
63376345
? diag::cannot_infer_base_of_unresolved_member
63386346
: diag::unresolved_member_no_inference;
63396347

lib/Sema/CSGen.cpp

Lines changed: 1 addition & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -74,46 +74,6 @@ static bool mergeRepresentativeEquivalenceClasses(ConstraintSystem &CS,
7474
return false;
7575
}
7676

77-
/// Find the next element in a chain of members. If this expression is (or
78-
/// could be) the base of such a chain, this will return \c nullptr.
79-
static Expr *getMemberChainSubExpr(Expr *expr) {
80-
assert(expr && "getMemberChainSubExpr called with null expr!");
81-
if (auto *UDE = dyn_cast<UnresolvedDotExpr>(expr)) {
82-
return UDE->getBase();
83-
} else if (auto *CE = dyn_cast<CallExpr>(expr)) {
84-
return CE->getFn();
85-
} else if (auto *BOE = dyn_cast<BindOptionalExpr>(expr)) {
86-
return BOE->getSubExpr();
87-
} else if (auto *FVE = dyn_cast<ForceValueExpr>(expr)) {
88-
return FVE->getSubExpr();
89-
} else if (auto *SE = dyn_cast<SubscriptExpr>(expr)) {
90-
return SE->getBase();
91-
} else {
92-
return nullptr;
93-
}
94-
}
95-
96-
/// Returns the base of a chain of member accesses/method calls. Most
97-
/// expressions do not participate in member chains, and just return \c this.
98-
static UnresolvedMemberExpr *getUnresolvedMemberChainBase(Expr *expr) {
99-
if (auto *subExpr = getMemberChainSubExpr(expr))
100-
return getUnresolvedMemberChainBase(subExpr);
101-
else
102-
return dyn_cast<UnresolvedMemberExpr>(expr);
103-
}
104-
105-
/// Whether this expression is a member of a member chain.
106-
static bool isMemberChainMember(Expr *expr) {
107-
return getMemberChainSubExpr(expr) != nullptr;
108-
}
109-
/// Whether this expression sits at the end of a chain of member accesses.
110-
static bool isMemberChainTail(Expr *expr, Expr *parent) {
111-
assert(expr && "isMemberChainTail called with null expr!");
112-
// If this expression's parent is not itself part of a chain (or, this expr
113-
// has no parent expr), this must be the tail of the chain.
114-
return parent == nullptr || !isMemberChainMember(parent);
115-
}
116-
11777
namespace {
11878

11979
/// Internal struct for tracking information about types within a series
@@ -836,10 +796,6 @@ namespace {
836796
/// found during our walk.
837797
llvm::MapVector<UnresolvedMemberExpr *, Type> UnresolvedBaseTypes;
838798

839-
/// A map from the tail of each unresolved member chain to the respective
840-
/// base of the chain.
841-
llvm::MapVector<Expr *, UnresolvedMemberExpr *>UnresolvedChainBases;
842-
843799
/// Returns false and emits the specified diagnostic if the member reference
844800
/// base is a nil literal. Returns true otherwise.
845801
bool isValidBaseOfMemberRef(Expr *base, Diag<> diagnostic) {
@@ -1480,16 +1436,6 @@ namespace {
14801436
assert(result != UnresolvedBaseTypes.end());
14811437
return result->second;
14821438
}
1483-
1484-
void setUnresolvedChainBase(Expr *tail, UnresolvedMemberExpr *base) {
1485-
UnresolvedChainBases.insert({tail, base});
1486-
}
1487-
1488-
UnresolvedMemberExpr *getUnresolvedChainBase(Expr *tail) {
1489-
auto result = UnresolvedChainBases.find(tail);
1490-
assert(result != UnresolvedChainBases.end());
1491-
return result->second;
1492-
}
14931439

14941440
virtual Type visitUnresolvedMemberExpr(UnresolvedMemberExpr *expr) {
14951441
auto baseLocator = CS.getConstraintLocator(
@@ -1564,7 +1510,7 @@ namespace {
15641510
"Unexpected expression at end of unresolved member chain");
15651511

15661512
auto memberTy = CS.getType(tail);
1567-
auto *base = getUnresolvedChainBase(tail);
1513+
auto *base = TypeChecker::getUnresolvedMemberChainBase(tail);
15681514

15691515
// Copy any type variable options from the result of the tail member to
15701516
// the result of the entire chain.
@@ -3839,26 +3785,6 @@ namespace {
38393785
if (auto *assignment = dyn_cast<AssignExpr>(expr))
38403786
CG.markAcceptableDiscardExprs(assignment->getDest());
38413787

3842-
// If we find an unresolved member chain, wrap it in an
3843-
// UnresolvedMemberChainResultExpr (unless this has already been done)
3844-
// and generate constraints for the wrapped expression.
3845-
auto *parent = Parent.getAsExpr();
3846-
if (isMemberChainTail(expr, parent)) {
3847-
if (auto *UME = getUnresolvedMemberChainBase(expr)) {
3848-
CG.setUnresolvedChainBase(expr, UME);
3849-
if (!parent || !isa<UnresolvedMemberChainResultExpr>(parent)) {
3850-
auto &cs = CG.getConstraintSystem();
3851-
auto &context = cs.getASTContext();
3852-
auto typeInfo = cs.getContextualTypeInfo(expr);
3853-
expr = new (context) UnresolvedMemberChainResultExpr(expr);
3854-
if (typeInfo) {
3855-
cs.setContextualType(expr, (*typeInfo).typeLoc,
3856-
(*typeInfo).purpose);
3857-
}
3858-
}
3859-
}
3860-
}
3861-
38623788
return { true, expr };
38633789
}
38643790

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,44 @@ static bool findNonMembers(ArrayRef<LookupResultEntry> lookupResults,
477477
return AllDeclRefs;
478478
}
479479

480+
/// Find the next element in a chain of members. If this expression is (or
481+
/// could be) the base of such a chain, this will return \c nullptr.
482+
static Expr *getMemberChainSubExpr(Expr *expr) {
483+
assert(expr && "getMemberChainSubExpr called with null expr!");
484+
if (auto *UDE = dyn_cast<UnresolvedDotExpr>(expr)) {
485+
return UDE->getBase();
486+
} else if (auto *CE = dyn_cast<CallExpr>(expr)) {
487+
return CE->getFn();
488+
} else if (auto *BOE = dyn_cast<BindOptionalExpr>(expr)) {
489+
return BOE->getSubExpr();
490+
} else if (auto *FVE = dyn_cast<ForceValueExpr>(expr)) {
491+
return FVE->getSubExpr();
492+
} else if (auto *SE = dyn_cast<SubscriptExpr>(expr)) {
493+
return SE->getBase();
494+
} else {
495+
return nullptr;
496+
}
497+
}
498+
499+
UnresolvedMemberExpr *TypeChecker::getUnresolvedMemberChainBase(Expr *expr) {
500+
if (auto *subExpr = getMemberChainSubExpr(expr))
501+
return getUnresolvedMemberChainBase(subExpr);
502+
else
503+
return dyn_cast<UnresolvedMemberExpr>(expr);
504+
}
505+
506+
/// Whether this expression is a member of a member chain.
507+
static bool isMemberChainMember(Expr *expr) {
508+
return getMemberChainSubExpr(expr) != nullptr;
509+
}
510+
/// Whether this expression sits at the end of a chain of member accesses.
511+
static bool isMemberChainTail(Expr *expr, Expr *parent) {
512+
assert(expr && "isMemberChainTail called with null expr!");
513+
// If this expression's parent is not itself part of a chain (or, this expr
514+
// has no parent expr), this must be the tail of the chain.
515+
return parent == nullptr || !isMemberChainMember(parent);
516+
}
517+
480518
/// Bind an UnresolvedDeclRefExpr by performing name lookup and
481519
/// returning the resultant expression. Context is the DeclContext used
482520
/// for the lookup.
@@ -1326,6 +1364,14 @@ namespace {
13261364
if (auto *simplified = simplifyTypeConstructionWithLiteralArg(expr))
13271365
return simplified;
13281366

1367+
// If we find an unresolved member chain, wrap it in an
1368+
// UnresolvedMemberChainResultExpr (unless this has already been done).
1369+
auto *parent = Parent.getAsExpr();
1370+
if (isMemberChainTail(expr, parent))
1371+
if (auto *UME = TypeChecker::getUnresolvedMemberChainBase(expr))
1372+
if (!parent || !isa<UnresolvedMemberChainResultExpr>(parent))
1373+
return new (ctx) UnresolvedMemberChainResultExpr(expr);
1374+
13291375
return expr;
13301376
}
13311377

lib/Sema/TypeChecker.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,11 @@ bool requirePointerArgumentIntrinsics(ASTContext &ctx, SourceLoc loc);
12071207
/// Require that the library intrinsics for creating
12081208
/// array literals exist.
12091209
bool requireArrayLiteralIntrinsics(ASTContext &ctx, SourceLoc loc);
1210+
1211+
/// Gets the \c UnresolvedMemberExpr at the base of a chain of member accesses.
1212+
/// If \c expr is not part of a member chain or the base is something other than
1213+
/// an \c UnresolvedMemberExpr, \c nullptr is returned.
1214+
UnresolvedMemberExpr *getUnresolvedMemberChainBase(Expr *expr);
12101215
}; // namespace TypeChecker
12111216

12121217
/// Temporary on-stack storage and unescaping for encoded diagnostic

0 commit comments

Comments
 (0)