Skip to content

Commit e4e82ec

Browse files
committed
[Sema] Avoid applying diagnostic hack to caller-side expression macros
We can't assume that type-checking the expression macro in the parameter will also fail if it fails at the call site since e.g name lookup may differ. Make sure we only apply this logic to simple literals. rdar://154771596
1 parent a18f72c commit e4e82ec

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

lib/Sema/TypeCheckExpr.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -774,14 +774,30 @@ Expr *CallerSideDefaultArgExprRequest::evaluate(
774774
if (!TypeChecker::typeCheckParameterDefault(initExpr, dc, paramTy,
775775
param->isAutoClosure(),
776776
/*atCallerSide=*/true)) {
777-
if (param->hasDefaultExpr()) {
777+
auto isSimpleLiteral = [&]() -> bool {
778+
switch (param->getDefaultArgumentKind()) {
779+
#define MAGIC_IDENTIFIER(NAME, STRING) \
780+
case DefaultArgumentKind::NAME: return true;
781+
#include "swift/AST/MagicIdentifierKinds.def"
782+
case DefaultArgumentKind::NilLiteral:
783+
case DefaultArgumentKind::EmptyArray:
784+
case DefaultArgumentKind::EmptyDictionary:
785+
return true;
786+
default:
787+
return false;
788+
}
789+
};
790+
if (param->hasDefaultExpr() && isSimpleLiteral()) {
778791
// HACK: If we were unable to type-check the default argument in context,
779792
// then retry by type-checking it within the parameter decl, which should
780793
// also fail. This will present the user with a better error message and
781794
// allow us to avoid diagnosing on each call site.
795+
// Note we can't do this for expression macros since name lookup may
796+
// differ at the call side vs the declaration. We can however do it for
797+
// simple literals.
782798
transaction.abort();
783799
(void)param->getTypeCheckedDefaultExpr();
784-
assert(ctx.Diags.hadAnyError());
800+
ASSERT(ctx.Diags.hadAnyError());
785801
}
786802
return new (ctx) ErrorExpr(initExpr->getSourceRange(), paramTy);
787803
}

test/Macros/rdar154771596.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: split-file %s %t
5+
6+
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath
7+
8+
// RUN: %target-swift-frontend -emit-module %t/Lib.swift -module-name Lib -emit-module-path %t/Lib.swiftmodule
9+
10+
// RUN: %target-swift-frontend -typecheck -verify -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -I %t %t/a.swift -primary-file %t/b.swift
11+
12+
//--- Lib.swift
13+
14+
@freestanding(expression)
15+
public macro magicFile() -> String = #externalMacro(module: "MacroDefinition", type: "MagicFileMacro")
16+
17+
//--- a.swift
18+
19+
import Lib
20+
21+
func foo(x: String = #magicFile) {}
22+
23+
//--- b.swift
24+
25+
// We're missing the necessary import in this file, make sure we diagnose.
26+
func bar() {
27+
foo() // expected-error {{no macro named 'magicFile'}}
28+
}

0 commit comments

Comments
 (0)