Skip to content

Commit d3523d3

Browse files
authored
Merge pull request #39073 from hamishknight/i-understood-that-reference
2 parents 8224df3 + 8be85c0 commit d3523d3

File tree

4 files changed

+35
-35
lines changed

4 files changed

+35
-35
lines changed

include/swift/AST/Expr.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -558,8 +558,8 @@ class alignas(8) Expr : public ASTAllocated<Expr> {
558558
/// the parent map.
559559
llvm::DenseMap<Expr *, Expr *> getParentMap();
560560

561-
/// Whether this expression is a valid parent for a TypeExpr.
562-
bool isValidTypeExprParent() const;
561+
/// Whether this expression is a valid parent for a given TypeExpr.
562+
bool isValidParentOfTypeExpr(Expr *typeExpr) const;
563563

564564
SWIFT_DEBUG_DUMP;
565565
void dump(raw_ostream &OS, unsigned Indent = 0) const;

lib/AST/Expr.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ llvm::DenseMap<Expr *, Expr *> Expr::getParentMap() {
736736
return parentMap;
737737
}
738738

739-
bool Expr::isValidTypeExprParent() const {
739+
bool Expr::isValidParentOfTypeExpr(Expr *typeExpr) const {
740740
// Allow references to types as a part of:
741741
// - member references T.foo, T.Type, T.self, etc.
742742
// - constructor calls T()
@@ -746,7 +746,6 @@ bool Expr::isValidTypeExprParent() const {
746746
switch (getKind()) {
747747
case ExprKind::Error:
748748
case ExprKind::DotSelf:
749-
case ExprKind::Call:
750749
case ExprKind::MemberRef:
751750
case ExprKind::UnresolvedMember:
752751
case ExprKind::DotSyntaxCall:
@@ -755,9 +754,15 @@ bool Expr::isValidTypeExprParent() const {
755754
case ExprKind::DotSyntaxBaseIgnored:
756755
case ExprKind::UnresolvedSpecialize:
757756
case ExprKind::OpenExistential:
758-
case ExprKind::Subscript:
759757
return true;
760758

759+
// For these cases we need to ensure the type expr is the function or base.
760+
// We do not permit e.g 'foo(T)'.
761+
case ExprKind::Call:
762+
return cast<CallExpr>(this)->getFn() == typeExpr;
763+
case ExprKind::Subscript:
764+
return cast<SubscriptExpr>(this)->getBase() == typeExpr;
765+
761766
case ExprKind::NilLiteral:
762767
case ExprKind::BooleanLiteral:
763768
case ExprKind::IntegerLiteral:

lib/Sema/MiscDiagnostics.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
621621
DiagnosticBehavior behavior = DiagnosticBehavior::Error;
622622

623623
if (auto *ParentExpr = Parent.getAsExpr()) {
624-
if (ParentExpr->isValidTypeExprParent())
624+
if (ParentExpr->isValidParentOfTypeExpr(E))
625625
return;
626626

627627
if (!Ctx.LangOpts.isSwiftVersionAtLeast(6)) {

lib/Sema/PreCheckExpr.cpp

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -902,13 +902,6 @@ namespace {
902902
/// insert RebindSelfInConstructorExpr nodes.
903903
llvm::SmallVector<Expr *, 8> ExprStack;
904904

905-
/// A stack, corresponding to \c ExprStack above, that indicates at each
906-
/// level whether the enclosing context is plausibly something that will
907-
/// be folded into a \c TypeExpr after \c simplifyTypeExpr is called.
908-
/// This helps us determine whether '_' should become a placeholder type or
909-
/// not, which lets us produce better diagnostics during type checking.
910-
llvm::SmallVector<bool, 8> PossibleTypeContextStack;
911-
912905
/// The 'self' variable to use when rebinding 'self' in a constructor.
913906
VarDecl *UnresolvedCtorSelf = nullptr;
914907

@@ -942,12 +935,12 @@ namespace {
942935
/// the type conforms to the expected literal protocol.
943936
Expr *simplifyTypeConstructionWithLiteralArg(Expr *E);
944937

945-
/// Whether we are in a context that might turn out to be a \c TypeExpr
946-
/// after \c simplifyTypeExpr is called up the tree. This function allows
947-
/// us to make better guesses about whether invalid uses of '_' were
948-
/// "supposed" to be \c DiscardAssignmentExprs or patterns, which results
949-
/// in better diagnostics after type checking.
950-
bool possiblyInTypeContext();
938+
/// Whether the current expression \p E is in a context that might turn out
939+
/// to be a \c TypeExpr after \c simplifyTypeExpr is called up the tree.
940+
/// This function allows us to make better guesses about whether invalid
941+
/// uses of '_' were "supposed" to be \c DiscardAssignmentExprs or patterns,
942+
/// which results in better diagnostics after type checking.
943+
bool possiblyInTypeContext(Expr *E);
951944

952945
/// Whether we can simplify the given discard assignment expr. Not possible
953946
/// if it's been marked "valid" or if the current state of the AST disallows
@@ -1170,17 +1163,7 @@ namespace {
11701163
if (recursive) {
11711164
if (isa<SequenceExpr>(expr))
11721165
SequenceExprDepth++;
1173-
1174-
// The next level is considered a type context if either:
1175-
// - The expression is a valid parent for a TypeExpr, or
1176-
// - The current level is a type context and the expression "looks
1177-
// like" a type (and is not a call arg).
1178-
bool shouldEnterTypeContext = expr->isValidTypeExprParent();
1179-
bool shouldContinueTypeContext = possiblyInTypeContext() &&
1180-
exprLooksLikeAType(expr) && !CallArgs.count(expr);
11811166
ExprStack.push_back(expr);
1182-
PossibleTypeContextStack.push_back(shouldEnterTypeContext ||
1183-
shouldContinueTypeContext);
11841167
}
11851168

11861169
return std::make_pair(recursive, expr);
@@ -1302,7 +1285,6 @@ namespace {
13021285
// Remove this expression from the stack.
13031286
assert(ExprStack.back() == expr);
13041287
ExprStack.pop_back();
1305-
PossibleTypeContextStack.pop_back();
13061288

13071289
// Mark the direct callee as being a callee.
13081290
if (auto *call = dyn_cast<ApplyExpr>(expr))
@@ -1591,17 +1573,30 @@ TypeExpr *PreCheckExpression::simplifyUnresolvedSpecializeExpr(
15911573
return nullptr;
15921574
}
15931575

1594-
bool PreCheckExpression::possiblyInTypeContext() {
1595-
return !PossibleTypeContextStack.empty() && PossibleTypeContextStack.back();
1576+
bool PreCheckExpression::possiblyInTypeContext(Expr *E) {
1577+
// Walk back up the stack of parents looking for a valid type context.
1578+
for (auto *ParentExpr : llvm::reverse(ExprStack)) {
1579+
// We're considered to be in a type context if either:
1580+
// - We have a valid parent for a TypeExpr, or
1581+
// - The parent "looks like" a type (and is not a call arg), and we can
1582+
// reach a valid parent for a TypeExpr if we continue walking.
1583+
if (ParentExpr->isValidParentOfTypeExpr(E))
1584+
return true;
1585+
1586+
if (!exprLooksLikeAType(ParentExpr) || CallArgs.count(ParentExpr))
1587+
return false;
1588+
1589+
E = ParentExpr;
1590+
}
1591+
return false;
15961592
}
15971593

15981594
/// Only allow simplification of a DiscardAssignmentExpr if it hasn't already
15991595
/// been explicitly marked as correct, and the current AST state allows it.
16001596
bool PreCheckExpression::canSimplifyDiscardAssignmentExpr(
16011597
DiscardAssignmentExpr *DAE) {
1602-
return !CorrectDiscardAssignmentExprs.count(DAE) &&
1603-
possiblyInTypeContext() &&
1604-
SequenceExprDepth == 0;
1598+
return !CorrectDiscardAssignmentExprs.count(DAE) && SequenceExprDepth == 0 &&
1599+
possiblyInTypeContext(DAE);
16051600
}
16061601

16071602
/// Simplify expressions which are type sugar productions that got parsed

0 commit comments

Comments
 (0)