Skip to content

Commit cf77b9f

Browse files
committed
[BitwiseCopyable] Allow conformance via swift_attr
If an imported type's conformance cannot be implicitly inferred, allow it to be explicitly stated via `__attribute__((__swift_attr__("_BitwiseCopyable")))`.
1 parent a0ac007 commit cf77b9f

File tree

4 files changed

+36
-0
lines changed

4 files changed

+36
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7652,6 +7652,8 @@ ERROR(non_bitwise_copyable_type_cxx_nontrivial,none,
76527652
"non-trivial C++ type cannot conform to 'BitwiseCopyable'", ())
76537653
ERROR(non_bitwise_copyable_c_type_nontrivial,none,
76547654
"type with unrepresentable fields cannot derive conformance to 'BitwiseCopyable'", ())
7655+
NOTE(note_non_bitwise_copyable_c_type_add_attr,none,
7656+
"annotate the type __attribute__((__swift_attr__(\"_BitwiseCopyable\")))",())
76557657
ERROR(non_bitwise_copyable_type_member,none,
76567658
"%select{stored property %2|associated value %2}1 of "
76577659
"'BitwiseCopyable'-conforming %kind3 has non-bitwise-copyable type %0",

lib/ClangImporter/ImportDecl.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8039,6 +8039,30 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
80398039
continue;
80408040
}
80418041

8042+
if (swiftAttr->getAttribute() == "_BitwiseCopyable") {
8043+
if (!SwiftContext.LangOpts.hasFeature(Feature::BitwiseCopyable))
8044+
continue;
8045+
auto *protocol =
8046+
SwiftContext.getProtocol(KnownProtocolKind::BitwiseCopyable);
8047+
auto *nominal = dyn_cast<NominalTypeDecl>(MappedDecl);
8048+
if (!nominal)
8049+
continue;
8050+
auto *module = nominal->getModuleContext();
8051+
// Don't synthesize a conformance if one already exists.
8052+
auto ty = nominal->getDeclaredInterfaceType();
8053+
if (module->lookupConformance(ty, protocol))
8054+
continue;
8055+
auto conformance = SwiftContext.getNormalConformance(
8056+
ty, protocol, nominal->getLoc(), nominal->getDeclContextForModule(),
8057+
ProtocolConformanceState::Complete,
8058+
/*isUnchecked=*/false,
8059+
/*isPreconcurrency=*/false);
8060+
conformance->setSourceKindAndImplyingConformance(
8061+
ConformanceEntryKind::Synthesized, nullptr);
8062+
8063+
nominal->registerProtocolConformance(conformance, /*synthesized=*/true);
8064+
}
8065+
80428066
// Dig out a buffer with the attribute text.
80438067
unsigned bufferID = getClangSwiftAttrSourceBuffer(
80448068
swiftAttr->getAttribute());

lib/Sema/TypeCheckBitwise.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ static bool checkBitwiseCopyableInstanceStorage(NominalTypeDecl *nominal,
272272
if (sd && sd->hasUnreferenceableStorage()) {
273273
if (!isImplicit(check)) {
274274
sd->diagnose(diag::non_bitwise_copyable_c_type_nontrivial);
275+
sd->diagnose(diag::note_non_bitwise_copyable_c_type_add_attr);
275276
}
276277
return true;
277278
}

test/Sema/bitwse_copyable_import.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ struct IntsTrailing2 {
5454
int is[];
5555
};
5656

57+
struct IntsTrailing3 {
58+
double d;
59+
float f;
60+
int is[];
61+
} __attribute__((__swift_attr__("_BitwiseCopyable")));
62+
5763
//--- Downstream.swift
5864

5965
func take<T : _BitwiseCopyable>(_ t: T) {}
@@ -76,3 +82,6 @@ extension IntsTrailing2 : _BitwiseCopyable {} //expected-error{{bitwise_copyable
7682
func passIntsTrailing2(_ t: IntsTrailing2) {
7783
take(t)
7884
}
85+
func passIntsTrailing3(_ t: IntsTrailing3) {
86+
take(t)
87+
}

0 commit comments

Comments
 (0)