Skip to content

Commit 01ce1d2

Browse files
committed
[Sema] Move anonymous closure argument check from parser to semantic analysis
1 parent ce082bc commit 01ce1d2

File tree

5 files changed

+32
-10
lines changed

5 files changed

+32
-10
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,8 +1311,6 @@ ERROR(dollar_identifier_decl,none,
13111311
"cannot declare entity named %0; the '$' prefix is reserved for "
13121312
"implicitly-synthesized declarations", (Identifier))
13131313

1314-
ERROR(anon_closure_arg_not_in_closure,none,
1315-
"anonymous closure argument not contained in a closure", ())
13161314
ERROR(anon_closure_arg_in_closure_with_args,none,
13171315
"anonymous closure arguments cannot be used inside a closure that has "
13181316
"explicit arguments", ())

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,6 +1702,8 @@ ERROR(extra_trailing_closure_in_call,none,
17021702
ERROR(closure_bad_param,none,
17031703
"%select{|trailing }1closure passed to parameter of type %0 that does not "
17041704
"accept a closure", (Type, bool))
1705+
ERROR(anon_closure_arg_not_in_closure,none,
1706+
"anonymous closure argument not contained in a closure", ())
17051707
GROUPED_WARNING(unlabeled_trailing_closure_deprecated,
17061708
TrailingClosureMatching,Deprecation,
17071709
"backward matching of the unlabeled trailing closure is deprecated; label the argument with %0 to suppress this warning",

lib/Parse/ParseExpr.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3192,14 +3192,10 @@ Expr *Parser::parseExprAnonClosureArg() {
31923192
auto closure = dyn_cast_or_null<ClosureExpr>(
31933193
dyn_cast<AbstractClosureExpr>(CurDeclContext));
31943194
if (!closure) {
3195-
if (Context.LangOpts.DebuggerSupport) {
3196-
auto refKind = DeclRefKind::Ordinary;
3197-
auto identifier = Context.getIdentifier(Name);
3198-
return new (Context) UnresolvedDeclRefExpr(DeclNameRef(identifier),
3199-
refKind, DeclNameLoc(Loc));
3200-
}
3201-
diagnose(Loc, diag::anon_closure_arg_not_in_closure);
3202-
return new (Context) ErrorExpr(Loc);
3195+
auto refKind = DeclRefKind::Ordinary;
3196+
auto identifier = Context.getIdentifier(Name);
3197+
return new (Context) UnresolvedDeclRefExpr(DeclNameRef(identifier), refKind,
3198+
DeclNameLoc(Loc));
32033199
}
32043200

32053201
// Check whether the closure already has explicit parameters.

lib/Sema/PreCheckTarget.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,23 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
946946
}
947947

948948
auto emitBasicError = [&] {
949+
// Check for anonymous closure arguments (e.g. $0, $1) used outside
950+
// closures.
951+
if (Name.isSimpleName()) {
952+
StringRef nameStr = Name.getBaseIdentifier().str();
953+
if (nameStr.starts_with("$")) {
954+
StringRef numStr = nameStr.substr(1);
955+
unsigned ArgNo;
956+
if (!numStr.getAsInteger(10, ArgNo)) {
957+
auto *closure = dyn_cast_or_null<ClosureExpr>(DC);
958+
if (!closure) {
959+
Context.Diags.diagnose(Loc, diag::anon_closure_arg_not_in_closure)
960+
.highlight(UDRE->getSourceRange());
961+
return;
962+
}
963+
}
964+
}
965+
}
949966
if (Name.isSimpleName(Context.Id_self)) {
950967
// `self` gets diagnosed with a different error when it can't be found.
951968
Context.Diags.diagnose(Loc, diag::cannot_find_self_in_scope)

test/Sema/issue-54030.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// https://github.com/swiftlang/swift/issues/54030
4+
5+
if $0 {} // expected-error {{anonymous closure argument not contained in a closure}}
6+
7+
#if false
8+
if $0 {}
9+
#endif

0 commit comments

Comments
 (0)