Skip to content

Commit 3991949

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 b4a2d89 commit 3991949

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
@@ -7446,7 +7446,7 @@ ERROR(property_wrapper_effectful,none,
74467446

74477447
ERROR(property_with_wrapper_conflict_attribute,none,
74487448
"property %0 with a wrapper cannot also be "
7449-
"%select{lazy|@NSCopying|@NSManaged|weak|unowned|unmanaged}1",
7449+
"%select{lazy|@NSCopying|@NSManaged|@abi|weak|unowned|unmanaged}1",
74507450
(Identifier, int))
74517451
ERROR(property_wrapper_not_single_var, none,
74527452
"property wrapper can only apply to a single variable", ())
@@ -8498,6 +8498,10 @@ ERROR(attr_abi_no_default_arguments,none,
84988498
"affect the parameter's ABI",
84998499
(Decl *))
85008500
8501+
ERROR(attr_abi_no_macros,none,
8502+
"%kind0 cannot be expanded in '@abi' attribute",
8503+
(Decl *))
8504+
85018505
// These macros insert 'final', 'non-final', or nothing depending on both the
85028506
// current decl and its counterpart, such that 'non-final' is used if the
85038507
// 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
@@ -4399,6 +4399,12 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
43994399
}
44004400
}
44014401

4402+
// Macros can't be attached to ABI-only decls. (If we diagnosed above,
4403+
// don't bother with this.)
4404+
if (attr->isValid() && !ABIRoleInfo(D).providesAPI()) {
4405+
diagnoseAndRemoveAttr(attr, diag::attr_abi_no_macros, macro);
4406+
}
4407+
44024408
return;
44034409
}
44044410

@@ -4480,16 +4486,25 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
44804486
// function, storage with an explicit getter, or parameter of function type.
44814487
if (nominal->getAttrs().hasAttribute<ResultBuilderAttr>()) {
44824488
ValueDecl *decl;
4489+
ValueDecl *abiRelevantDecl;
44834490
if (auto param = dyn_cast<ParamDecl>(D)) {
44844491
decl = param;
4492+
abiRelevantDecl = dyn_cast<ValueDecl>(
4493+
param->getDeclContext()->getAsDecl());
44854494
} else if (auto func = dyn_cast<FuncDecl>(D)) {
44864495
decl = func;
4496+
abiRelevantDecl = func;
44874497
} else if (auto storage = dyn_cast<AbstractStorageDecl>(D)) {
44884498
decl = storage;
4499+
abiRelevantDecl = storage;
44894500

44904501
// Check whether this is a storage declaration that is not permitted
44914502
// to have a result builder attached.
44924503
auto shouldDiagnose = [&]() -> bool {
4504+
// We'll diagnose use in @abi later.
4505+
if (!ABIRoleInfo(abiRelevantDecl).providesAPI())
4506+
return false;
4507+
44934508
// An uninitialized stored property in a struct can have a function
44944509
// builder attached.
44954510
if (auto var = dyn_cast<VarDecl>(decl)) {
@@ -4533,6 +4548,14 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
45334548
return;
45344549
}
45354550

4551+
// Result builders shouldn't be applied to an ABI-only decl because they
4552+
// have no ABI effect.
4553+
if (!ABIRoleInfo(abiRelevantDecl).providesAPI()) {
4554+
diagnoseAndRemoveAttr(attr, diag::attr_abi_forbidden_attr,
4555+
nominal->getNameStr(), /*isModifier=*/false);
4556+
return;
4557+
}
4558+
45364559
// Diagnose and ignore arguments.
45374560
if (attr->hasArgs()) {
45384561
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
@@ -1395,6 +1395,12 @@ static SourceFile *evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo,
13951395
}
13961396
}
13971397

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

14001406
auto moduleDecl = dc->getParentModule();

lib/Sema/TypeCheckPropertyWrapper.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -481,11 +481,15 @@ AttachedPropertyWrappersRequest::evaluate(Evaluator &evaluator,
481481
continue;
482482
}
483483

484+
auto abiRole = ABIRoleInfo(var);
485+
bool hasOrIsABI = !abiRole.providesAPI() || !abiRole.providesABI();
486+
484487
// Note: Getting the semantic attrs here would trigger a request cycle.
485488
auto attachedAttrs = var->getAttrs();
486489

487490
// Check for conflicting attributes.
488-
if (attachedAttrs.hasAttribute<LazyAttr>() ||
491+
if (hasOrIsABI ||
492+
attachedAttrs.hasAttribute<LazyAttr>() ||
489493
attachedAttrs.hasAttribute<NSCopyingAttr>() ||
490494
attachedAttrs.hasAttribute<NSManagedAttr>() ||
491495
(attachedAttrs.hasAttribute<ReferenceOwnershipAttr>() &&
@@ -498,9 +502,11 @@ AttachedPropertyWrappersRequest::evaluate(Evaluator &evaluator,
498502
whichKind = 1;
499503
else if (attachedAttrs.hasAttribute<NSManagedAttr>())
500504
whichKind = 2;
505+
else if (hasOrIsABI)
506+
whichKind = 3;
501507
else {
502508
auto attr = attachedAttrs.getAttribute<ReferenceOwnershipAttr>();
503-
whichKind = 2 + static_cast<unsigned>(attr->get());
509+
whichKind = 3 + static_cast<unsigned>(attr->get());
504510
}
505511
var->diagnose(diag::property_with_wrapper_conflict_attribute,
506512
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
@@ -1267,6 +1267,60 @@ nonisolated func isolation17() async {}
12671267
@abi(@concurrent func isolation19() async)
12681268
nonisolated(nonsending) func isolation19() async {}
12691269
1270+
// CustomAttr for property wrapper -- banned in and with '@abi'
1271+
// Banned because we would need to design behavior for its auxiliary decls.
1272+
@propertyWrapper struct PropertyWrapper {
1273+
var wrappedValue: Int { fatalError() }
1274+
}
1275+
1276+
struct CustomAttrPropertyWrapper {
1277+
@abi(@PropertyWrapper var v1: Int) // expected-error {{property 'v1' with a wrapper cannot also be @abi}}
1278+
@PropertyWrapper var v1: Int // expected-error {{property 'v1' with a wrapper cannot also be @abi}}
1279+
1280+
@abi(@PropertyWrapper var v2: Int) // expected-error {{property 'v2' with a wrapper cannot also be @abi}}
1281+
var v2: Int
1282+
1283+
@abi(var v3: Int)
1284+
@PropertyWrapper var v3: Int // expected-error {{property 'v3' with a wrapper cannot also be @abi}}
1285+
}
1286+
1287+
// CustomAttr for attached macro -- see Macros/macro_expand_peers.swift
1288+
1289+
// CustomAttr for result builder -- banned in '@abi'
1290+
// Has no ABI impact on either a parameter or a decl.
1291+
@resultBuilder struct ResultBuilder {
1292+
static func buildBlock(_ values: Int...) -> Int { values.reduce(0, +) }
1293+
}
1294+
1295+
struct CustomAttrResultBuilder {
1296+
@abi(@ResultBuilder var v1: Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{8-22=}}
1297+
@ResultBuilder var v1: Int { 0 }
1298+
1299+
@abi(@ResultBuilder var v2: Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{8-22=}}
1300+
var v2: Int { 0 }
1301+
1302+
@abi(var v3: Int)
1303+
@ResultBuilder var v3: Int { 0 }
1304+
1305+
@abi(@ResultBuilder func fn11() -> Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{8-22=}}
1306+
@ResultBuilder func fn11() -> Int { 0 }
1307+
1308+
@abi(@ResultBuilder func fn21() -> Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{8-22=}}
1309+
func fn21() -> Int { 0 }
1310+
1311+
@abi(func fn31() -> Int)
1312+
@ResultBuilder func fn31() -> Int { 0 }
1313+
1314+
@abi(func fn12(@ResultBuilder _: () -> Int) -> Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{18-32=}}
1315+
func fn12(@ResultBuilder _: () -> Int) -> Int { 0 }
1316+
1317+
@abi(func fn22(@ResultBuilder _: () -> Int) -> Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{18-32=}}
1318+
func fn22(_: () -> Int) -> Int { 0 }
1319+
1320+
@abi(func fn32(_: () -> Int) -> Int)
1321+
func fn32(@ResultBuilder _: () -> Int) -> Int { 0 }
1322+
}
1323+
12701324
// NSCopying - see attr/attr_abi_objc.swift
12711325

12721326
// @LLDBDebuggerFunction -- banned in @abi

0 commit comments

Comments
 (0)