Skip to content

Commit 97ee702

Browse files
authored
Merge pull request #62917 from DougGregor/macro-expansion-diags
2 parents 2f8751c + c06216c commit 97ee702

12 files changed

+113
-27
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6786,6 +6786,10 @@ ERROR(external_macro_not_found,none,
67866786
"external macro implementation type '%0.%1' could not be found for "
67876787
"macro %2; the type must be public and provided via "
67886788
"'-load-plugin-library'", (StringRef, StringRef, DeclName))
6789+
ERROR(macro_must_be_defined,none,
6790+
"macro %0 requires a definition", (DeclName))
6791+
ERROR(external_macro_outside_macro_definition,none,
6792+
"macro 'externalMacro' can only be used to define another macro", ())
67896793
NOTE(macro_note, none,
67906794
"%1 (in macro %0)", (DeclName, StringRef))
67916795
WARNING(macro_warning, none,

include/swift/AST/MacroDefinition.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ class MacroDefinition {
112112
return data.builtin;
113113
}
114114

115-
explicit operator bool() const { return kind != Kind::Invalid; }
115+
operator Kind() const { return kind; }
116116
};
117117

118118
}

include/swift/Sema/ConstraintSystem.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,6 +1798,9 @@ enum class ConstraintSystemFlags {
17981798

17991799
/// When set, ignore async/sync mismatches
18001800
IgnoreAsyncSyncMismatch = 0x80,
1801+
1802+
/// Disable macro expansions.
1803+
DisableMacroExpansions = 0x100,
18011804
};
18021805

18031806
/// Options that affect the constraint system as a whole.

lib/Sema/CSApply.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5406,11 +5406,13 @@ namespace {
54065406
ConcreteDeclRef macroRef = resolveConcreteDeclRef(macro, locator);
54075407
E->setMacroRef(macroRef);
54085408

5409-
if (auto newExpr = expandMacroExpr(dc, E, macroRef, expandedType)) {
5410-
E->setRewritten(newExpr);
5411-
cs.cacheExprTypes(E);
5409+
if (!cs.Options.contains(ConstraintSystemFlags::DisableMacroExpansions)) {
5410+
if (auto newExpr = expandMacroExpr(dc, E, macroRef, expandedType)) {
5411+
E->setRewritten(newExpr);
5412+
}
54125413
}
54135414

5415+
cs.cacheExprTypes(E);
54145416
return E;
54155417
}
54165418

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,9 @@ TypeChecker::typeCheckTarget(SolutionApplicationTarget &target,
422422
if (options.contains(TypeCheckExprFlags::LeaveClosureBodyUnchecked))
423423
csOptions |= ConstraintSystemFlags::LeaveClosureBodyUnchecked;
424424

425+
if (options.contains(TypeCheckExprFlags::DisableMacroExpansions))
426+
csOptions |= ConstraintSystemFlags::DisableMacroExpansions;
427+
425428
ConstraintSystem cs(dc, csOptions);
426429

427430
if (auto *expr = target.getAsExpr()) {

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "swift/AST/ForeignErrorConvention.h"
4040
#include "swift/AST/GenericEnvironment.h"
4141
#include "swift/AST/Initializer.h"
42+
#include "swift/AST/MacroDefinition.h"
4243
#include "swift/AST/NameLookup.h"
4344
#include "swift/AST/NameLookupRequests.h"
4445
#include "swift/AST/PrettyStackTrace.h"
@@ -2004,6 +2005,39 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
20042005
MD->diagnose(diag::macro_in_nested, MD->getName());
20052006
if (!MD->getMacroContexts())
20062007
MD->diagnose(diag::macro_without_context, MD->getName());
2008+
2009+
// Check the macro definition.
2010+
switch (auto macroDef = MD->getDefinition()) {
2011+
case MacroDefinition::Kind::Undefined:
2012+
MD->diagnose(diag::macro_must_be_defined, MD->getName());
2013+
break;
2014+
2015+
case MacroDefinition::Kind::Invalid:
2016+
case MacroDefinition::Kind::Builtin:
2017+
// Nothing else to check here.
2018+
break;
2019+
2020+
case MacroDefinition::Kind::External: {
2021+
// Retrieve the external definition of the macro.
2022+
auto external = macroDef.getExternalMacro();
2023+
ExternalMacroDefinitionRequest request{
2024+
&Ctx, external.moduleName, external.macroTypeName
2025+
};
2026+
auto externalDef = evaluateOrDefault(
2027+
Ctx.evaluator, request, ExternalMacroDefinition()
2028+
);
2029+
if (!externalDef.opaqueHandle) {
2030+
MD->diagnose(
2031+
diag::external_macro_not_found,
2032+
external.moduleName.str(),
2033+
external.macroTypeName.str(),
2034+
MD->getName()
2035+
).limitBehavior(DiagnosticBehavior::Warning);
2036+
}
2037+
2038+
break;
2039+
}
2040+
}
20072041
}
20082042

20092043
void visitMacroExpansionDecl(MacroExpansionDecl *MED) {

lib/Sema/TypeCheckMacros.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,8 @@ MacroDefinition MacroDefinitionRequest::evaluate(
234234

235235
PrettyStackTraceDecl debugStack("type checking macro definition", macro);
236236
Type typeCheckedType = TypeChecker::typeCheckExpression(
237-
definition, macro, contextualType);
237+
definition, macro, contextualType,
238+
TypeCheckExprFlags::DisableMacroExpansions);
238239
if (!typeCheckedType)
239240
return MacroDefinition::forInvalid();
240241

@@ -352,13 +353,14 @@ Expr *swift::expandMacroExpr(
352353
case MacroDefinition::Kind::Builtin: {
353354
switch (macroDef.getBuiltinKind()) {
354355
case BuiltinMacroKind::ExternalMacro:
355-
// FIXME: Error here.
356+
ctx.Diags.diagnose(
357+
expr->getLoc(), diag::external_macro_outside_macro_definition);
356358
return nullptr;
357359
}
358360
}
359361

360362
case MacroDefinition::Kind::External: {
361-
// Retrieve the extternal definition of the macro.
363+
// Retrieve the external definition of the macro.
362364
auto external = macroDef.getExternalMacro();
363365
ExternalMacroDefinitionRequest request{
364366
&ctx, external.moduleName, external.macroTypeName

lib/Sema/TypeChecker.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ enum class TypeCheckExprFlags {
138138

139139
/// Don't type check expressions for correct availability.
140140
DisableExprAvailabilityChecking = 0x08,
141+
142+
/// Don't expansino macros.
143+
DisableMacroExpansions = 0x10,
141144
};
142145

143146
using TypeCheckExprOptions = OptionSet<TypeCheckExprFlags>;

test/Macros/macro_availability_macosx.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
@available(macOS 12.0, *)
55
struct X { }
66

7-
@expression macro m1: X = A.B // expected-error{{'X' is only available in macOS 12.0 or newer}}
7+
@expression macro m1: X = #externalMacro(module: "A", type: "B") // expected-error{{'X' is only available in macOS 12.0 or newer}}
8+
// expected-warning@-1{{external macro implementation type 'A.B' could not be found for macro 'm1'}}
89
910
@available(macOS 12.0, *)
10-
@expression macro m2: X = A.B
11+
@expression macro m2: X = #externalMacro(module: "A", type: "B")
12+
// expected-warning@-1{{external macro implementation type 'A.B' could not be found for macro 'm2'}}

test/Macros/macro_expand.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
@expression macro customFileID: String = #externalMacro(module: "MacroDefinition", type: "FileIDMacro")
2020
@expression macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MacroDefinition", type: "StringifyMacro")
21-
@expression macro fileID<T: _ExpressibleByStringLiteral>: T = #externalMacro(module: "MacroDefinition", type: "FileIDMacro")
21+
@expression macro fileID<T: ExpressibleByStringLiteral>: T = #externalMacro(module: "MacroDefinition", type: "FileIDMacro")
2222
@expression macro recurse(_: Bool) = #externalMacro(module: "MacroDefinition", type: "RecursiveMacro")
2323

2424
func testFileID(a: Int, b: Int) {

test/Macros/macros_diagnostics.swift

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,49 +2,69 @@
22

33
@expression macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MacroDefinition", type: "StringifyMacro")
44
// expected-note@-1 2{{'stringify' declared here}}
5+
// expected-warning@-2{{external macro implementation type}}
56
@expression macro missingMacro1(_: Any) = MissingModule.MissingType // expected-note{{'missingMacro1' declared here}}
67
// expected-warning@-1{{external macro definitions are now written using #externalMacro}}{{43-68=#externalMacro(module: "MissingModule", type: "MissingType")}}
7-
@expression macro missingMacro2(_: Any) = MissingModule.MissingType
8+
// expected-warning@-2{{external macro implementation type}}
9+
@expression macro missingMacro2(_: Any) = #externalMacro(module: "MissingModule", type: "MissingType")
10+
// expected-warning@-1{{external macro implementation type}}
811

912
protocol P { }
1013

11-
@expression macro tryToHide<T: P>(_: P) -> some P = BuiltinMacros.Blah
14+
@expression macro tryToHide<T: P>(_: T) -> some P = #externalMacro(module: "BuiltinMacros", type: "Blah")
1215
// expected-error@-1{{some' types are only permitted in properties, subscripts, and functions}}
16+
// expected-error@-2{{generic parameter 'T' could not be inferred}}
1317

1418
internal struct X { } // expected-note{{type declared here}}
1519

16-
@expression public macro createAnX: X = BuiltinMacros.Blah
20+
@expression public macro createAnX: X = #externalMacro(module: "BuiltinMacros", type: "Blah")
1721
// expected-error@-1{{macro cannot be declared public because its result type uses an internal type}}
22+
// expected-warning@-2{{external macro implementation type}}
1823

19-
@expression macro m1: Int = A.B
20-
@expression macro m1: Float = A.B
24+
@expression macro m1: Int = #externalMacro(module: "BuiltinMacros", type: "Blah")
25+
// expected-warning@-1{{external macro implementation type}}
26+
@expression macro m1: Float = #externalMacro(module: "BuiltinMacros", type: "Blah")
27+
// expected-warning@-1{{external macro implementation type}}
2128

22-
@expression macro m2: Int = A.B // expected-note{{'m2' previously declared here}}
23-
@expression macro m2: Int = A.B // expected-error{{invalid redeclaration of 'm2'}}
29+
@expression macro m2: Int = #externalMacro(module: "BuiltinMacros", type: "Blah") // expected-note{{'m2' previously declared here}}
30+
// expected-warning@-1{{external macro implementation type}}
31+
@expression macro m2: Int = #externalMacro(module: "BuiltinMacros", type: "Blah") // expected-error{{invalid redeclaration of 'm2'}}
32+
// expected-warning@-1{{external macro implementation type}}
2433

25-
@expression macro m3(_: Int) -> Int = A.B
26-
@expression macro m3(_: Int) -> Float = A.B
34+
@expression macro m3(_: Int) -> Int = #externalMacro(module: "BuiltinMacros", type: "Blah")
35+
// expected-warning@-1{{external macro implementation type}}
36+
@expression macro m3(_: Int) -> Float = #externalMacro(module: "BuiltinMacros", type: "Blah")
37+
// expected-warning@-1{{external macro implementation type}}
2738

28-
@expression macro m4(_: Int) -> Int = A.B // expected-note{{'m4' previously declared here}}
29-
@expression macro m4(_: Int) -> Int = A.B // expected-error{{invalid redeclaration of 'm4'}}
39+
@expression macro m4(_: Int) -> Int = #externalMacro(module: "BuiltinMacros", type: "Blah") // expected-note{{'m4' previously declared here}}
40+
// expected-warning@-1{{external macro implementation type}}
41+
@expression macro m4(_: Int) -> Int = #externalMacro(module: "BuiltinMacros", type: "Blah") // expected-error{{invalid redeclaration of 'm4'}}
42+
// expected-warning@-1{{external macro implementation type}}
3043

3144
struct ZZZ {
32-
macro m5: Int = A.B
45+
macro m5: Int = #externalMacro(module: "BuiltinMacros", type: "Blah")
3346
// expected-error@-1{{macro 'm5' can only be declared at file scope}}
3447
// expected-error@-2{{macro 'm5' must declare its applicable contexts (e.g., '@expression')}}
48+
// expected-warning@-3{{external macro implementation type}}
3549
}
3650

37-
@expression macro multiArgMacro(_: Any, second: Any) = MissingModule.MissingType
51+
@expression macro multiArgMacro(_: Any, second: Any) = #externalMacro(module: "MissingModule", type: "MissingType")
3852
// expected-note@-1{{'multiArgMacro(_:second:)' declared here}}
53+
// expected-warning@-2{{external macro implementation type}}
54+
55+
@expression macro overloaded1(_ p: P) = #externalMacro(module: "MissingModule", type: "MissingType")
56+
// expected-warning@-1{{external macro implementation type}}
3957

40-
@expression macro overloaded1(_ p: P) = MissingModule.MissingType
4158
func overloaded1(_ p: Any) { }
4259

43-
@expression macro notOverloaded1(_ p: P) = MissingModule.MissingType // expected-note{{'notOverloaded1' previously declared here}}
44-
@expression macro notOverloaded1(_ p: P) = MissingModule.MissingOtherType // expected-error{{invalid redeclaration of 'notOverloaded1'}}
60+
@expression macro notOverloaded1(_ p: P) = #externalMacro(module: "MissingModule", type: "MissingType") // expected-note{{'notOverloaded1' previously declared here}}
61+
// expected-warning@-1{{external macro implementation type}}
62+
@expression macro notOverloaded1(_ p: P) = #externalMacro(module: "MissingModule", type: "MissingOtherType") // expected-error{{invalid redeclaration of 'notOverloaded1'}}
63+
// expected-warning@-1{{external macro implementation type}}
4564

46-
@expression macro intIdentity(value: Int, _: Float) -> Int = MissingModule.MissingType
65+
@expression macro intIdentity(value: Int, _: Float) -> Int = #externalMacro(module: "MissingModule", type: "MissingType")
4766
// expected-note@-1{{macro 'intIdentity(value:_:)' declared here}}
67+
// expected-warning@-2{{external macro implementation type}}
4868

4969
func testDiags(a: Int, b: Int) {
5070
// FIXME: Bad diagnostic.
@@ -79,3 +99,10 @@ func shadow(a: Int, b: Int, stringify: Int) {
7999
func testMissing() {
80100
#missingMacro1("hello") // expected-error{{external macro implementation type 'MissingModule.MissingType' could not be found for macro 'missingMacro1'; the type must be public and provided via '-load-plugin-library'}}
81101
}
102+
103+
@expression macro undefined() // expected-error{{macro 'undefined()' requires a definition}}
104+
105+
func testExternalMacroOutOfPlace() {
106+
let _: Int = #externalMacro(module: "A", type: "B")
107+
// expected-error@-1{{macro 'externalMacro' can only be used to define another macro}}
108+
}

test/Macros/parsing.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,15 @@ protocol P { }
33
protocol Q { associatedtype Assoc }
44

55
@expression macro m1: Int = #externalMacro(module: "A", type: "M1")
6+
// expected-warning@-1{{external macro implementation type 'A.M1' could not be found for macro 'm1'; the type must be public and provided via '-load-plugin-library'}}
67
@expression macro m2(_: Int) = #externalMacro(module: "A", type: "M2")
8+
// expected-warning@-1{{external macro implementation type 'A.M2' could not be found for macro 'm2'; the type must be public and provided via '-load-plugin-library'}}
79
@expression macro m3(a b: Int) -> Int = #externalMacro(module: "A", type: "M3")
10+
// expected-warning@-1{{external macro implementation type 'A.M3' could not be found for macro 'm3(a:)'; the type must be public and provided via '-load-plugin-library'}}
811
@expression macro m4<T: Q>: T = #externalMacro(module: "A", type: "M4") where T.Assoc: P
12+
// expected-warning@-1{{external macro implementation type 'A.M4' could not be found for macro 'm4'; the type must be public and provided via '-load-plugin-library'}}
913
@expression macro m5<T: P>(_: T) = #externalMacro(module: "A", type: "M4")
14+
// expected-warning@-1{{external macro implementation type 'A.M4' could not be found for macro 'm5'; the type must be public and provided via '-load-plugin-library'}}
1015

1116
@expression macro m6 = A // expected-error{{expected '(' for macro parameters or ':' for a value-like macro}}
17+
// expected-error@-1{{macro must itself be defined by a macro expansion such as '#externalMacro(...)'}}

0 commit comments

Comments
 (0)