Skip to content

Commit de63cec

Browse files
committed
Diagnose CustomAttrs as needed in @abi
CustomAttr backs four different features, each of which requires a different behavior in `@abi`: • Global actors: Permitted (and permitted to vary) since they can affect mangling • Result builders: Forbidden inside an `@abi` since they have no ABI impact • Property wrappers: Forbidden both inside an `@abi` and on a decl with an `@abi` since it’s not clear how we would apply `@abi` to the auxiliary decls • Attached macros: Forbidden inside an `@abi` since an ABI-only decl has no body, accessors, members, peers, extensions, or (currently) conformances Implement these behaviors (outside of `ABIDeclChecker` since they can’t be described there).
1 parent f249559 commit de63cec

File tree

6 files changed

+122
-5
lines changed

6 files changed

+122
-5
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7407,7 +7407,7 @@ ERROR(property_wrapper_effectful,none,
74077407

74087408
ERROR(property_with_wrapper_conflict_attribute,none,
74097409
"property %0 with a wrapper cannot also be "
7410-
"%select{lazy|@NSCopying|@NSManaged|weak|unowned|unmanaged}1",
7410+
"%select{lazy|@NSCopying|@NSManaged|@abi|weak|unowned|unmanaged}1",
74117411
(Identifier, int))
74127412
ERROR(property_wrapper_not_single_var, none,
74137413
"property wrapper can only apply to a single variable", ())
@@ -8447,6 +8447,10 @@ ERROR(attr_abi_no_default_arguments,none,
84478447
"affect the parameter's ABI",
84488448
(Decl *))
84498449
8450+
ERROR(attr_abi_no_macros,none,
8451+
"%kind0 cannot be expanded in '@abi' attribute",
8452+
(Decl *))
8453+
84508454
// These macros insert 'final', 'non-final', or nothing depending on both the
84518455
// current decl and its counterpart, such that 'non-final' is used if the
84528456
// counterpart would be described as 'final' or 'static'. They must be kept in

lib/Sema/TypeCheckAttr.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4390,6 +4390,12 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
43904390
}
43914391
}
43924392

4393+
// Macros can't be attached to ABI-only decls. (If we diagnosed above,
4394+
// don't bother with this.)
4395+
if (attr->isValid() && !ABIRoleInfo(D).providesAPI()) {
4396+
diagnoseAndRemoveAttr(attr, diag::attr_abi_no_macros, macro);
4397+
}
4398+
43934399
return;
43944400
}
43954401

@@ -4471,16 +4477,25 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
44714477
// function, storage with an explicit getter, or parameter of function type.
44724478
if (nominal->getAttrs().hasAttribute<ResultBuilderAttr>()) {
44734479
ValueDecl *decl;
4480+
ValueDecl *abiRelevantDecl;
44744481
if (auto param = dyn_cast<ParamDecl>(D)) {
44754482
decl = param;
4483+
abiRelevantDecl = dyn_cast<ValueDecl>(
4484+
param->getDeclContext()->getAsDecl());
44764485
} else if (auto func = dyn_cast<FuncDecl>(D)) {
44774486
decl = func;
4487+
abiRelevantDecl = func;
44784488
} else if (auto storage = dyn_cast<AbstractStorageDecl>(D)) {
44794489
decl = storage;
4490+
abiRelevantDecl = storage;
44804491

44814492
// Check whether this is a storage declaration that is not permitted
44824493
// to have a result builder attached.
44834494
auto shouldDiagnose = [&]() -> bool {
4495+
// We'll diagnose use in @abi later.
4496+
if (!ABIRoleInfo(abiRelevantDecl).providesAPI())
4497+
return false;
4498+
44844499
// An uninitialized stored property in a struct can have a function
44854500
// builder attached.
44864501
if (auto var = dyn_cast<VarDecl>(decl)) {
@@ -4524,6 +4539,14 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
45244539
return;
45254540
}
45264541

4542+
// Result builders shouldn't be applied to an ABI-only decl because they
4543+
// have no ABI effect.
4544+
if (!ABIRoleInfo(abiRelevantDecl).providesAPI()) {
4545+
diagnoseAndRemoveAttr(attr, diag::attr_abi_forbidden_attr,
4546+
nominal->getNameStr(), /*isModifier=*/false);
4547+
return;
4548+
}
4549+
45274550
// Diagnose and ignore arguments.
45284551
if (attr->hasArgs()) {
45294552
diagnose(attr->getLocation(), diag::result_builder_arguments)

lib/Sema/TypeCheckMacros.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,6 +1396,12 @@ static SourceFile *evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo,
13961396
}
13971397
}
13981398

1399+
// Macros are so spectacularly not valid in an `@abi` attribute that we cannot
1400+
// even attempt to expand them.
1401+
if (!ABIRoleInfo(attachedTo).providesAPI()) {
1402+
return nullptr;
1403+
}
1404+
13991405
ASTContext &ctx = dc->getASTContext();
14001406

14011407
auto moduleDecl = dc->getParentModule();

lib/Sema/TypeCheckPropertyWrapper.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -484,11 +484,15 @@ AttachedPropertyWrappersRequest::evaluate(Evaluator &evaluator,
484484
continue;
485485
}
486486

487+
auto abiRole = ABIRoleInfo(var);
488+
bool hasOrIsABI = !abiRole.providesAPI() || !abiRole.providesABI();
489+
487490
// Note: Getting the semantic attrs here would trigger a request cycle.
488491
auto attachedAttrs = var->getAttrs();
489492

490493
// Check for conflicting attributes.
491-
if (attachedAttrs.hasAttribute<LazyAttr>() ||
494+
if (hasOrIsABI ||
495+
attachedAttrs.hasAttribute<LazyAttr>() ||
492496
attachedAttrs.hasAttribute<NSCopyingAttr>() ||
493497
attachedAttrs.hasAttribute<NSManagedAttr>() ||
494498
(attachedAttrs.hasAttribute<ReferenceOwnershipAttr>() &&
@@ -501,9 +505,11 @@ AttachedPropertyWrappersRequest::evaluate(Evaluator &evaluator,
501505
whichKind = 1;
502506
else if (attachedAttrs.hasAttribute<NSManagedAttr>())
503507
whichKind = 2;
508+
else if (hasOrIsABI)
509+
whichKind = 3;
504510
else {
505511
auto attr = attachedAttrs.getAttribute<ReferenceOwnershipAttr>();
506-
whichKind = 2 + static_cast<unsigned>(attr->get());
512+
whichKind = 3 + static_cast<unsigned>(attr->get());
507513
}
508514
var->diagnose(diag::property_with_wrapper_conflict_attribute,
509515
var->getName(), whichKind);

test/Macros/macro_expand_peers.swift

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
// REQUIRES: swift_swift_parser, executable_test
2+
// REQUIRES: swift_feature_ABIAttribute
23

34
// For _Concurrency.
45
// UNSUPPORTED: use_os_stdlib
56
// UNSUPPORTED: back_deployment_runtime
67

78
// RUN: %empty-directory(%t)
89
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -parse-as-library -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath
9-
// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -parse-as-library -disable-availability-checking -DTEST_DIAGNOSTICS
10+
// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -parse-as-library -disable-availability-checking -enable-experimental-feature ABIAttribute -DTEST_DIAGNOSTICS
1011

1112
// Check with the imported macro library vs. the local declaration of the macro.
1213
// RUN: %target-swift-frontend -swift-version 5 -emit-module -o %t/macro_library.swiftmodule %S/Inputs/macro_library.swift -module-name macro_library -load-plugin-library %t/%target-library-name(MacroDefinition)
1314

14-
// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -parse-as-library -disable-availability-checking -DIMPORT_MACRO_LIBRARY -I %t -DTEST_DIAGNOSTICS
15+
// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -parse-as-library -disable-availability-checking -DIMPORT_MACRO_LIBRARY -I %t -enable-experimental-feature ABIAttribute -DTEST_DIAGNOSTICS
1516

1617

1718
// RUN: %target-swift-frontend -swift-version 5 -typecheck -load-plugin-library %t/%target-library-name(MacroDefinition) -parse-as-library %s -disable-availability-checking -dump-macro-expansions > %t/expansions-dump.txt 2>&1
@@ -309,3 +310,26 @@ func closuresInPeerMacroCrash() {}
309310
@trait(Trait {})
310311
@trait(Trait {})
311312
var closuresInPeerMacroOnVariableCrash: Int = 0
313+
314+
// Test that macros can't be used in @abi
315+
316+
#if TEST_DIAGNOSTICS
317+
struct ABIAttrWithAttachedMacro {
318+
// expected-error@+1 {{macro 'addCompletionHandler()' cannot be expanded in '@abi' attribute}}
319+
@abi(@addCompletionHandler func fn1() async)
320+
@addCompletionHandler func fn1() async {}
321+
// From diagnostics in the expansion:
322+
// expected-note@-2 3{{in expansion of macro 'addCompletionHandler' on instance method 'fn1()' here}}
323+
// expected-note@-4 {{'fn1()' previously declared here}}
324+
325+
// expected-error@+1 {{macro 'addCompletionHandler()' cannot be expanded in '@abi' attribute}}
326+
@abi(@addCompletionHandler func fn2() async)
327+
func fn2() async {}
328+
329+
@abi(func fn3() async)
330+
@addCompletionHandler func fn3() async {}
331+
// From diagnostics in the expansion:
332+
// expected-note@-2 2{{in expansion of macro 'addCompletionHandler' on instance method 'fn3()' here}}
333+
// expected-note@-4 {{'fn3()' previously declared here}}
334+
}
335+
#endif

test/attr/attr_abi.swift

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,60 @@ nonisolated func isolation17() async {}
12681268
@abi(@execution(concurrent) func isolation19() async)
12691269
@execution(caller) func isolation19() async {}
12701270
1271+
// CustomAttr for property wrapper -- banned in and with '@abi'
1272+
// Banned because we would need to design behavior for its auxiliary decls.
1273+
@propertyWrapper struct PropertyWrapper {
1274+
var wrappedValue: Int { fatalError() }
1275+
}
1276+
1277+
struct CustomAttrPropertyWrapper {
1278+
@abi(@PropertyWrapper var v1: Int) // expected-error {{property 'v1' with a wrapper cannot also be @abi}}
1279+
@PropertyWrapper var v1: Int // expected-error {{property 'v1' with a wrapper cannot also be @abi}}
1280+
1281+
@abi(@PropertyWrapper var v2: Int) // expected-error {{property 'v2' with a wrapper cannot also be @abi}}
1282+
var v2: Int
1283+
1284+
@abi(var v3: Int)
1285+
@PropertyWrapper var v3: Int // expected-error {{property 'v3' with a wrapper cannot also be @abi}}
1286+
}
1287+
1288+
// CustomAttr for attached macro -- see Macros/macro_expand_peers.swift
1289+
1290+
// CustomAttr for result builder -- banned in '@abi'
1291+
// Has no ABI impact on either a parameter or a decl.
1292+
@resultBuilder struct ResultBuilder {
1293+
static func buildBlock(_ values: Int...) -> Int { values.reduce(0, +) }
1294+
}
1295+
1296+
struct CustomAttrResultBuilder {
1297+
@abi(@ResultBuilder var v1: Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{8-22=}}
1298+
@ResultBuilder var v1: Int { 0 }
1299+
1300+
@abi(@ResultBuilder var v2: Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{8-22=}}
1301+
var v2: Int { 0 }
1302+
1303+
@abi(var v3: Int)
1304+
@ResultBuilder var v3: Int { 0 }
1305+
1306+
@abi(@ResultBuilder func fn11() -> Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{8-22=}}
1307+
@ResultBuilder func fn11() -> Int { 0 }
1308+
1309+
@abi(@ResultBuilder func fn21() -> Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{8-22=}}
1310+
func fn21() -> Int { 0 }
1311+
1312+
@abi(func fn31() -> Int)
1313+
@ResultBuilder func fn31() -> Int { 0 }
1314+
1315+
@abi(func fn12(@ResultBuilder _: () -> Int) -> Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{18-32=}}
1316+
func fn12(@ResultBuilder _: () -> Int) -> Int { 0 }
1317+
1318+
@abi(func fn22(@ResultBuilder _: () -> Int) -> Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{18-32=}}
1319+
func fn22(_: () -> Int) -> Int { 0 }
1320+
1321+
@abi(func fn32(_: () -> Int) -> Int)
1322+
func fn32(@ResultBuilder _: () -> Int) -> Int { 0 }
1323+
}
1324+
12711325
// NSCopying - see attr/attr_abi_objc.swift
12721326

12731327
// @LLDBDebuggerFunction -- banned in @abi

0 commit comments

Comments
 (0)