Skip to content

Commit 9abc333

Browse files
committed
[Sema] Fold SequenceExpr in pre-checking pre-walk
Doing it in the post-walk meant we ended up walking the children twice, which lead to duplicate diagnostics and incorrect inference of the level of application for function references. Move it to the pre-walk, ensuring that we resolve any operator references before folding.
1 parent ef43305 commit 9abc333

File tree

5 files changed

+35
-24
lines changed

5 files changed

+35
-24
lines changed

lib/Sema/PreCheckExpr.cpp

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,9 +1056,6 @@ namespace {
10561056
/// Keep track of acceptable DiscardAssignmentExpr's.
10571057
llvm::SmallPtrSet<DiscardAssignmentExpr*, 2> CorrectDiscardAssignmentExprs;
10581058

1059-
/// The current number of nested \c SequenceExprs that we're within.
1060-
unsigned SequenceExprDepth = 0;
1061-
10621059
/// The current number of nested \c SingleValueStmtExprs that we're within.
10631060
unsigned SingleValueStmtExprDepth = 0;
10641061

@@ -1127,6 +1124,16 @@ namespace {
11271124
PreWalkResult<Expr *> walkToExprPre(Expr *expr) override {
11281125
auto &diags = Ctx.Diags;
11291126

1127+
// Fold sequence expressions.
1128+
if (auto *seqExpr = dyn_cast<SequenceExpr>(expr)) {
1129+
auto result = TypeChecker::foldSequence(seqExpr, DC);
1130+
result = result->walk(*this);
1131+
if (!result)
1132+
return Action::Stop();
1133+
// Already walked.
1134+
return Action::SkipNode(result);
1135+
}
1136+
11301137
// FIXME(diagnostics): `InOutType` could appear here as a result
11311138
// of successful re-typecheck of the one of the sub-expressions e.g.
11321139
// `let _: Int = { (s: inout S) in s.bar() }`. On the first
@@ -1158,11 +1165,9 @@ namespace {
11581165
return Action::Stop();
11591166

11601167
// If we're going to recurse, record this expression on the stack.
1161-
if (recursive) {
1162-
if (isa<SequenceExpr>(expr))
1163-
SequenceExprDepth++;
1168+
if (recursive)
11641169
ExprStack.push_back(expr);
1165-
}
1170+
11661171
return Action::VisitNodeIf(recursive, expr);
11671172
};
11681173

@@ -1292,17 +1297,6 @@ namespace {
12921297
assert(ExprStack.back() == expr);
12931298
ExprStack.pop_back();
12941299

1295-
// Fold sequence expressions.
1296-
if (auto *seqExpr = dyn_cast<SequenceExpr>(expr)) {
1297-
auto result = TypeChecker::foldSequence(seqExpr, DC);
1298-
SequenceExprDepth--;
1299-
result = result->walk(*this);
1300-
if (!result)
1301-
return Action::Stop();
1302-
1303-
return Action::Continue(result);
1304-
}
1305-
13061300
// Type check the type parameters in an UnresolvedSpecializeExpr.
13071301
if (auto *us = dyn_cast<UnresolvedSpecializeExpr>(expr)) {
13081302
if (auto *typeExpr = simplifyUnresolvedSpecializeExpr(us))
@@ -1430,8 +1424,7 @@ namespace {
14301424
// or if we're inside a SequenceExpr (since the whole tree will be
14311425
// re-checked when we finish folding anyway).
14321426
if (auto *DAE = dyn_cast<DiscardAssignmentExpr>(expr)) {
1433-
if (!CorrectDiscardAssignmentExprs.count(DAE) &&
1434-
SequenceExprDepth == 0) {
1427+
if (!CorrectDiscardAssignmentExprs.count(DAE)) {
14351428
ctx.Diags.diagnose(expr->getLoc(),
14361429
diag::discard_expr_outside_of_assignment);
14371430
return Action::Stop();
@@ -1688,7 +1681,7 @@ bool PreCheckExpression::possiblyInTypeContext(Expr *E) {
16881681
/// been explicitly marked as correct, and the current AST state allows it.
16891682
bool PreCheckExpression::canSimplifyDiscardAssignmentExpr(
16901683
DiscardAssignmentExpr *DAE) {
1691-
return !CorrectDiscardAssignmentExprs.count(DAE) && SequenceExprDepth == 0 &&
1684+
return !CorrectDiscardAssignmentExprs.count(DAE) &&
16921685
possiblyInTypeContext(DAE);
16931686
}
16941687

lib/Sema/TypeCheckExpr.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,15 @@ swift::DefaultTypeRequest::evaluate(Evaluator &evaluator,
631631
}
632632

633633
Expr *TypeChecker::foldSequence(SequenceExpr *expr, DeclContext *dc) {
634+
// First resolve any unresolved decl references in operator positions.
635+
for (auto i : indices(expr->getElements())) {
636+
if (i % 2 == 0)
637+
continue;
638+
auto *elt = expr->getElement(i);
639+
if (auto *UDRE = dyn_cast<UnresolvedDeclRefExpr>(elt))
640+
elt = TypeChecker::resolveDeclRefExpr(UDRE, dc);
641+
expr->setElement(i, elt);
642+
}
634643
ArrayRef<Expr*> Elts = expr->getElements();
635644
assert(Elts.size() > 1 && "inadequate number of elements in sequence");
636645
assert((Elts.size() & 1) == 1 && "even number of elements in sequence");

test/Constraints/argument_matching.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,3 +1810,14 @@ func test_extraneous_argument_with_inout() {
18101810
var x: Int = 0
18111811
test(42, &x) // expected-error {{extra argument in call}}
18121812
}
1813+
1814+
// https://github.com/swiftlang/swift/issues/75527
1815+
struct Issue75527 {
1816+
func foo(x: Int) {}
1817+
1818+
func bar() {
1819+
typealias Magic<T> = T
1820+
let fn = Issue75527.foo(self) as Magic
1821+
fn(0) // Make sure the argument label does not escape here.
1822+
}
1823+
}

test/StringProcessing/Parse/forward-slash-regex.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ do {
5252
_=/0/
5353
// expected-error@-1 {{'_' can only appear in a pattern or on the left side of an assignment}}
5454
// expected-error@-2 {{cannot find operator '=/' in scope}}
55-
// expected-error@-3 {{'/' is not a postfix unary operator}}
5655
}
5756

5857
// No closing '/' so a prefix operator.

test/expr/primary/super/unsupported.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@ class Derived: Base {
4242
// expected-error@+1 {{'super' may be used only to access a superclass member, subscript, or initializer}}
4343
let _ = self[super]
4444

45-
// FIXME: Duplicate diagnostic because expression is re-pre-checked after folding initial sequence expression.
46-
// expected-error@+1 2 {{'super' may be used only to access a superclass member, subscript, or initializer}}
45+
// expected-error@+1 {{'super' may be used only to access a superclass member, subscript, or initializer}}
4746
_ = (0, super)
4847

4948
func nested() {

0 commit comments

Comments
 (0)