Skip to content

Commit b36f3cc

Browse files
committed
[BitwiseCopyable] Suppress via ~.
In addition to the existing language mechanism of `@available(*, unavailable)`.
1 parent d197571 commit b36f3cc

File tree

10 files changed

+96
-21
lines changed

10 files changed

+96
-21
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7674,6 +7674,8 @@ ERROR(non_bitwise_copyable_type_indirect_enum_element,none,
76747674
"enum with indirect case cannot conform to 'BitwiseCopyable'", ())
76757675
NOTE(note_non_bitwise_copyable_type_indirect_enum_element,none,
76767676
"indirect case is here", ())
7677+
ERROR(non_bitwise_copyable_type_suppressed,none,
7678+
"cannot both conform to and suppress conformance to 'BitwiseCopyable'", ())
76777679
ERROR(non_bitwise_copyable_type_cxx_nontrivial,none,
76787680
"non-trivial C++ type cannot conform to 'BitwiseCopyable'", ())
76797681
ERROR(non_bitwise_copyable_c_type_nontrivial,none,

include/swift/AST/KnownProtocols.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ PROTOCOL(FloatingPoint)
150150
INVERTIBLE_PROTOCOL_WITH_NAME(Name, #Name)
151151
#include "swift/ABI/InvertibleProtocols.def"
152152

153-
PROTOCOL_(BitwiseCopyable)
153+
REPRESSIBLE_PROTOCOL_(BitwiseCopyable)
154154

155155
EXPRESSIBLE_BY_LITERAL_PROTOCOL(ExpressibleByArrayLiteral, "Array", false)
156156
EXPRESSIBLE_BY_LITERAL_PROTOCOL(ExpressibleByBooleanLiteral, "BooleanLiteralType", true)

lib/SIL/IR/TypeLowering.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3078,6 +3078,7 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
30783078
// (7) being or containing a variadic generic type which doesn't conform
30793079
// unconditionally but does in this case
30803080
// (8) being or containing the error type
3081+
// (9) explicitly suppressing conformance
30813082
bool hasNoNonconformingNode = visitAggregateLeaves(
30823083
origType, substType, forExpansion,
30833084
/*isLeafAggregate=*/
@@ -3093,6 +3094,13 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
30933094
if (!nominal)
30943095
return false;
30953096

3097+
// A trivial type that suppresses conformance doesn't conform (case
3098+
// (9)).
3099+
if (nominal && nominal->suppressesConformance(
3100+
KnownProtocolKind::BitwiseCopyable)) {
3101+
return true;
3102+
}
3103+
30963104
// Nominals with fields that are generic may not conform
30973105
// unconditionally (the only kind automatically derived currently)
30983106
// and so may lack a conformance (case (2)).
@@ -3173,6 +3181,13 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
31733181
return true;
31743182
}
31753183

3184+
// A trivial type that suppresses conformance doesn't conform (case
3185+
// (9)).
3186+
if (nominal->suppressesConformance(
3187+
KnownProtocolKind::BitwiseCopyable)) {
3188+
return false;
3189+
}
3190+
31763191
// A generic type may be trivial when instantiated with particular
31773192
// types but lack a conformance (case (3)).
31783193
if (nominal->isGenericContext()) {

lib/Sema/TypeCheckBitwise.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,14 @@ void BitwiseCopyableStorageVisitor::emitNonconformingMemberTypeDiagnostic(
229229
static bool checkBitwiseCopyableInstanceStorage(NominalTypeDecl *nominal,
230230
DeclContext *dc,
231231
BitwiseCopyableCheck check) {
232+
auto *conformanceDecl = dc->getAsDecl() ? dc->getAsDecl() : nominal;
233+
if (nominal->suppressesConformance(KnownProtocolKind::BitwiseCopyable)) {
234+
if (!isImplicit(check)) {
235+
conformanceDecl->diagnose(diag::non_bitwise_copyable_type_suppressed);
236+
}
237+
return true;
238+
}
239+
232240
if (dc->mapTypeIntoContext(nominal->getDeclaredInterfaceType())
233241
->isNoncopyable()) {
234242
// Already separately diagnosed when explicit.

stdlib/public/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "Freestand
317317
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "Extern")
318318
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "BitwiseCopyable")
319319
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "BorrowingSwitch")
320+
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "ConformanceSuppression")
320321

321322
if("${SWIFT_NATIVE_SWIFT_TOOLS_PATH}" STREQUAL "")
322323
set(swift_bin_dir "${CMAKE_BINARY_DIR}/bin")

stdlib/public/core/CommandLine.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,17 @@ internal func _swift_stdlib_getUnsafeArgvArgc(_: UnsafeMutablePointer<Int32>)
1919
-> UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>
2020

2121
/// Command-line arguments for the current process.
22+
#if $BitwiseCopyable && $ConformanceSuppression
2223
@frozen // namespace
23-
public enum CommandLine {}
24+
public enum CommandLine : ~_BitwiseCopyable {
25+
}
26+
#else
27+
@frozen // namespace
28+
public enum CommandLine {
29+
}
30+
@available(*, unavailable)
31+
extension CommandLine : _BitwiseCopyable {}
32+
#endif
2433

2534
extension CommandLine {
2635
/// The backing static variable for argument count may come either from the
@@ -104,7 +113,4 @@ extension CommandLine {
104113
}
105114
}
106115

107-
@available(*, unavailable)
108-
extension CommandLine : _BitwiseCopyable {}
109-
110116
#endif // SWIFT_STDLIB_HAS_COMMANDLINE

stdlib/public/core/MemoryLayout.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,15 @@
3939
/// let pointPointer = UnsafeMutableRawPointer.allocate(
4040
/// byteCount: count * MemoryLayout<Point>.stride,
4141
/// alignment: MemoryLayout<Point>.alignment)
42+
#if $BitwiseCopyable && $ConformanceSuppression
43+
@frozen // namespace
44+
public enum MemoryLayout<T: ~Copyable>: ~_BitwiseCopyable, Copyable {}
45+
#else
4246
@frozen // namespace
4347
public enum MemoryLayout<T: ~Copyable>: Copyable {}
44-
4548
@available(*, unavailable)
4649
extension MemoryLayout: _BitwiseCopyable {}
50+
#endif
4751

4852
extension MemoryLayout where T: ~Copyable {
4953
/// The contiguous memory footprint of `T`, in bytes.

stdlib/public/core/Unicode.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -671,9 +671,11 @@ public func transcode<Input, InputEncoding, OutputEncoding>(
671671
}
672672

673673
/// A namespace for Unicode utilities.
674+
#if $BitwiseCopyable && $ConformanceSuppression
675+
@frozen
676+
public enum Unicode : ~_BitwiseCopyable {}
677+
#else
674678
@frozen
675679
public enum Unicode {}
676-
677-
@available(*, unavailable)
678-
extension Unicode : _BitwiseCopyable {}
680+
#endif
679681

test/SILGen/bitwise_copyable.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
// RUN: %target-swift-frontend \
2-
// RUN: %s \
3-
// RUN: -emit-silgen \
4-
// RUN: -disable-availability-checking \
5-
// RUN: -enable-experimental-feature BitwiseCopyable \
1+
// RUN: %target-swift-frontend \
2+
// RUN: %s \
3+
// RUN: -emit-silgen \
4+
// RUN: -disable-availability-checking \
5+
// RUN: -enable-experimental-feature ConformanceSuppression \
6+
// RUN: -enable-experimental-feature BitwiseCopyable \
67
// RUN: -enable-builtin-module
78

89
// REQUIRES: asserts
@@ -59,3 +60,5 @@ struct NeverGoingToBeBitwiseCopyable {
5960
@available(*, unavailable)
6061
extension NeverGoingToBeBitwiseCopyable : _BitwiseCopyable {
6162
}
63+
64+
struct AlsoNotBitwiseCopyable : ~_BitwiseCopyable {}

test/Sema/bitwise_copyable_2.swift

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
// RUN: %target-typecheck-verify-swift \
2-
// RUN: -enable-experimental-feature NonescapableTypes \
3-
// RUN: -enable-experimental-feature BitwiseCopyable \
4-
// RUN: -enable-builtin-module \
1+
// RUN: %target-typecheck-verify-swift \
2+
// RUN: -enable-experimental-feature NonescapableTypes \
3+
// RUN: -enable-experimental-feature ConformanceSuppression \
4+
// RUN: -enable-experimental-feature BitwiseCopyable \
5+
// RUN: -enable-builtin-module \
56
// RUN: -debug-diagnostic-names
67

78
// This test file only exists in order to test without noncopyable_generics and can be deleted once that is always enabled.
@@ -35,11 +36,14 @@ func take<T : _BitwiseCopyable>(_ t: T) {}
3536
func passInternalUsableStruct(_ s: InternalUsableStruct) { take(s) } // expected-error{{type_does_not_conform_decl_owner}}
3637
// expected-note@-8{{where_requirement_failure_one_subst}}
3738

38-
func passMemoryLayout<T>(_ m: MemoryLayout<T>) { take(m) } // expected-error{{conformance_availability_unavailable}}
39+
func passMemoryLayout<T>(_ m: MemoryLayout<T>) { take(m) } // expected-error{{global function 'take' requires that 'MemoryLayout<T>' conform to '_BitwiseCopyable'}}
40+
// expected-note@-11{{where 'T' = 'MemoryLayout<T>'}}
3941

40-
func passCommandLine(_ m: CommandLine) { take(m) } // expected-error{{conformance_availability_unavailable}}
42+
func passCommandLine(_ m: CommandLine) { take(m) } // expected-error{{global function 'take' requires that 'CommandLine' conform to '_BitwiseCopyable'}}
43+
// expected-note@-14{{where 'T' = 'CommandLine'}}
4144

42-
func passUnicode(_ m: Unicode) { take(m) } // expected-error{{conformance_availability_unavailable}}
45+
func passUnicode(_ m: Unicode) { take(m) } // expected-error{{global function 'take' requires that 'Unicode' conform to '_BitwiseCopyable'}}
46+
// expected-note@-17{{where 'T' = 'Unicode'}}
4347

4448
import Builtin
4549

@@ -62,3 +66,33 @@ enum E_Raw_String : String {
6266
}
6367

6468
func passE_Raw_String(_ e: E_Raw_String) { take(e) }
69+
70+
struct S_Suppressed : ~_BitwiseCopyable {
71+
var i: Int
72+
}
73+
74+
func passS_Suppressed(_ s: S_Suppressed) { take(s) } // expected-error{{global function 'take' requires that 'S_Suppressed' conform to '_BitwiseCopyable'}}
75+
// expected-note@-46{{where 'T' = 'S_Suppressed'}}
76+
77+
struct S_Suppressed_Extension {}
78+
extension S_Suppressed_Extension : ~_BitwiseCopyable {} // expected-error{{conformance to inferrable protocol '_BitwiseCopyable' cannot be suppressed in an extension}}
79+
80+
struct S_Explicit_Suppressed : _BitwiseCopyable, ~_BitwiseCopyable {} // expected-error{{cannot both conform to and suppress conformance to 'BitwiseCopyable'}}
81+
82+
func passS_Explicit_Suppressed(_ s: S_Explicit_Suppressed) { take(s) }
83+
84+
struct S_Suppressed_Explicit : ~_BitwiseCopyable, _BitwiseCopyable {} // expected-error{{cannot both conform to and suppress conformance to 'BitwiseCopyable'}}
85+
86+
func passS_Explicit_Suppressed(_ s: S_Suppressed_Explicit) { take(s) }
87+
88+
struct S_Suppressed_Twice : ~_BitwiseCopyable, ~_BitwiseCopyable {} // expected-warning{{already suppressed conformance to '_BitwiseCopyable'}}
89+
90+
enum E : ~Equatable { // expected-error{{conformance to 'Equatable' cannot be suppressed}}
91+
case i
92+
case e
93+
case io
94+
}
95+
96+
enum E_Suppressed : ~_BitwiseCopyable {}
97+
98+
extension E_Suppressed : _BitwiseCopyable {} // expected-error{{cannot both conform to and suppress conformance to 'BitwiseCopyable'}}

0 commit comments

Comments
 (0)