Skip to content

Commit a43faf8

Browse files
Merge pull request #71242 from nate-chandler/bitwise-copyable/not-for-unchecked
[BitwiseCopyable] Don't derive on @unchecked field
2 parents aa350a9 + c8119e3 commit a43faf8

15 files changed

+109
-31
lines changed

lib/SIL/IR/TypeLowering.cpp

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "swift/AST/Pattern.h"
2929
#include "swift/AST/PrettyStackTrace.h"
3030
#include "swift/AST/PropertyWrappers.h"
31+
#include "swift/AST/ProtocolConformance.h"
3132
#include "swift/AST/TypeDifferenceVisitor.h"
3233
#include "swift/AST/Types.h"
3334
#include "swift/ClangImporter/ClangModule.h"
@@ -3009,6 +3010,21 @@ void TypeConverter::verifyLexicalLowering(const TypeLowering &lowering,
30093010
}
30103011
}
30113012

3013+
static bool isUnchecked(ProtocolConformanceRef conformance) {
3014+
if (!conformance)
3015+
return false;
3016+
if (!conformance.isConcrete())
3017+
return false;
3018+
auto concrete = conformance.getConcrete();
3019+
assert(concrete);
3020+
auto *root = concrete->getRootConformance();
3021+
assert(root);
3022+
auto *normal = dyn_cast<NormalProtocolConformance>(root);
3023+
if (!normal)
3024+
return false;
3025+
return normal->isUnchecked();
3026+
}
3027+
30123028
void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
30133029
AbstractionPattern origType,
30143030
CanType substType,
@@ -3042,10 +3058,17 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
30423058
if (!nominal)
30433059
return false;
30443060

3045-
// Nominals with generic parameters must be explicitly conformed to
3046-
// BitwiseCopyable.
3047-
auto *generic = ty.getAnyGeneric();
3048-
if (generic && generic->isGenericContext()) {
3061+
// Don't walk into types whose conformance is unchecked--such
3062+
// conformances obstruct automatic inference of BitwiseCopyable.
3063+
auto conformance = M.checkConformance(ty, bitwiseCopyableProtocol);
3064+
if (isUnchecked(conformance)) {
3065+
return true;
3066+
}
3067+
3068+
// Nominals with fields that conditionally conform to BitwiseCopyable
3069+
// must be explicitly conditionally conformed. Such a field must be a
3070+
// generic context.
3071+
if (nominal->isGenericContext()) {
30493072
return true;
30503073
}
30513074

@@ -3059,10 +3082,12 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
30593082
// Return false to indicate seeing a leaf which justifies the type
30603083
// being trivial but not conforming to BitwiseCopyable.
30613084

3062-
// A BitwiseCopyable conformer appearing within its layout doesn't
3063-
// explain why substType doesn't itself conform.
3064-
if (M.checkConformance(ty, bitwiseCopyableProtocol))
3065-
return true;
3085+
// A BitwiseCopyable conformer appearing within its layout explains a
3086+
// non-conformance iff the conformance is @unchecked.
3087+
auto conformance = M.checkConformance(ty, bitwiseCopyableProtocol);
3088+
if (conformance) {
3089+
return !isUnchecked(conformance);
3090+
}
30663091

30673092
// ModuleTypes are trivial but don't warrant being given a conformance
30683093
// to BitwiseCopyable.
@@ -3099,15 +3124,15 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
30993124
return true;
31003125
}
31013126

3102-
/// A non-conforming generic nominal type justifies substType not
3103-
/// conforming.
3104-
auto *generic = ty.getAnyGeneric();
3105-
if (generic && generic->isGenericContext()) {
3127+
/// A field of conditionally-BitwiseCopyable type justifies the
3128+
/// aggregate not conforming because the aggregate must be conformed
3129+
/// explicitly in that case.
3130+
if (nominal->isGenericContext()) {
31063131
return false;
31073132
}
31083133

31093134
// The field is trivial and the whole type is nonconforming. That's
3110-
// legal iff the type is public.
3135+
// legal iff the field's type is public.
31113136
return !nominal
31123137
->getFormalAccessScope(
31133138
/*useDC=*/nullptr,
@@ -3148,6 +3173,7 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
31483173
llvm::errs() << "Non-trivial type with _BitwiseCopyable conformance!?:\n"
31493174
<< substType << "\n";
31503175
conformance.print(llvm::errs());
3176+
llvm::errs() << "\n";
31513177
assert(false);
31523178
}
31533179
}

lib/Sema/TypeCheckBitwise.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class BitwiseCopyableStorageVisitor : public StorageVisitor {
106106

107107
bool visitMemberDecl(ValueDecl *storage, Type ty);
108108
bool visitMemberType(Type type, SourceLoc loc);
109+
bool isUnchecked(ProtocolConformanceRef conformance);
109110
bool visitNonconformingMemberType(Type type, SourceLoc loc);
110111
void emitNonconformingMemberTypeDiagnostic(Type ty, SourceLoc loc);
111112
};
@@ -136,6 +137,13 @@ bool BitwiseCopyableStorageVisitor::visitMemberType(Type ty, SourceLoc loc) {
136137
return visitNonconformingMemberType(ty, loc);
137138
}
138139

140+
if (isImplicit(check) && isUnchecked(conformance)) {
141+
// Do not automatically derive conformance if one of the field's
142+
// conformance is @unchecked.
143+
invalid = true;
144+
return true;
145+
}
146+
139147
// Walk the conformance, diagnosing any missing BitwiseCopyable conformances.
140148
bool anyMissing = false;
141149
conformance.forEachMissingConformance(
@@ -150,6 +158,20 @@ bool BitwiseCopyableStorageVisitor::visitMemberType(Type ty, SourceLoc loc) {
150158
return anyMissing;
151159
}
152160

161+
bool BitwiseCopyableStorageVisitor::isUnchecked(
162+
ProtocolConformanceRef conformance) {
163+
if (!conformance.isConcrete())
164+
return false;
165+
auto concrete = conformance.getConcrete();
166+
assert(concrete);
167+
auto *root = concrete->getRootConformance();
168+
assert(root);
169+
auto *normal = dyn_cast<NormalProtocolConformance>(root);
170+
if (!normal)
171+
return false;
172+
return normal->isUnchecked();
173+
}
174+
153175
bool BitwiseCopyableStorageVisitor::visitNonconformingMemberType(
154176
Type ty, SourceLoc loc) {
155177
if (ty->hasError())

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2165,7 +2165,8 @@ static void diagnoseConformanceImpliedByConditionalConformance(
21652165
/// to the given protocol. This should return true when @unchecked can be
21662166
/// used to disable those semantic checks.
21672167
static bool hasAdditionalSemanticChecks(ProtocolDecl *proto) {
2168-
return proto->isSpecificProtocol(KnownProtocolKind::Sendable);
2168+
return proto->isSpecificProtocol(KnownProtocolKind::Sendable) ||
2169+
proto->isSpecificProtocol(KnownProtocolKind::BitwiseCopyable);
21692170
}
21702171

21712172
/// Determine whether the type \c T conforms to the protocol \c Proto,

stdlib/public/core/BridgeObjectiveC.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ public func _getBridgedNonVerbatimObjectiveCType<T>(_: T.Type) -> Any.Type?
407407
/// already have writeback-scoped lifetime.
408408
@frozen
409409
public struct AutoreleasingUnsafeMutablePointer<Pointee /* TODO : class */>
410-
: _Pointer {
410+
: _Pointer, @unchecked _BitwiseCopyable {
411411

412412
public let _rawValue: Builtin.RawPointer
413413

stdlib/public/core/CTypes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ public typealias CBool = Bool
142142
/// Opaque pointers are used to represent C pointers to types that
143143
/// cannot be represented in Swift, such as incomplete struct types.
144144
@frozen
145-
public struct OpaquePointer {
145+
public struct OpaquePointer : @unchecked _BitwiseCopyable {
146146
@usableFromInline
147147
internal var _rawValue: Builtin.RawPointer
148148

stdlib/public/core/Integers.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1904,7 +1904,8 @@ public protocol _LosslessStringConvertibleOrNone {}
19041904
/// customization points for arithmetic operations. When you provide just those
19051905
/// methods, the standard library provides default implementations for all
19061906
/// other arithmetic methods and operators.
1907-
public protocol FixedWidthInteger: BinaryInteger, _LosslessStringConvertibleOrNone
1907+
public protocol FixedWidthInteger
1908+
: BinaryInteger, _LosslessStringConvertibleOrNone, _BitwiseCopyable
19081909
where Magnitude: FixedWidthInteger & UnsignedInteger,
19091910
Stride: FixedWidthInteger & SignedInteger {
19101911
/// The number of bits used for the underlying binary representation of

stdlib/public/core/SIMDVector.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ public protocol SIMDScalar : _BitwiseCopyable {
8080
public protocol SIMD<Scalar>:
8181
SIMDStorage,
8282
Hashable,
83-
ExpressibleByArrayLiteral
83+
ExpressibleByArrayLiteral,
84+
_BitwiseCopyable
8485
{
8586
/// The mask type resulting from pointwise comparisons of this vector type.
8687
associatedtype MaskStorage: SIMD
@@ -95,7 +96,8 @@ public protocol SIMD<Scalar>:
9596
Codable,
9697
Hashable,
9798
CustomStringConvertible,
98-
ExpressibleByArrayLiteral
99+
ExpressibleByArrayLiteral,
100+
_BitwiseCopyable
99101
{
100102
/// The mask type resulting from pointwise comparisons of this vector type.
101103
associatedtype MaskStorage: SIMD

stdlib/public/core/UnsafeBufferPointer.swift.gyb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
/// collection with an `${Self}` instance copies the instances out of the
3131
/// referenced memory and into the new collection.
3232
@frozen // unsafe-performance
33-
public struct Unsafe${Mutable}BufferPointer<Element> {
33+
public struct Unsafe${Mutable}BufferPointer<Element>
34+
: @unchecked _BitwiseCopyable {
3435

3536
@usableFromInline
3637
let _position: Unsafe${Mutable}Pointer<Element>?

stdlib/public/core/UnsafePointer.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@
205205
/// let numberPointer = UnsafePointer<Int>(&number)
206206
/// // Accessing 'numberPointer' is undefined behavior.
207207
@frozen // unsafe-performance
208-
public struct UnsafePointer<Pointee>: _Pointer {
208+
public struct UnsafePointer<Pointee>: _Pointer, @unchecked _BitwiseCopyable {
209209

210210
/// A type that represents the distance between two pointers.
211211
public typealias Distance = Int
@@ -578,7 +578,8 @@ public struct UnsafePointer<Pointee>: _Pointer {
578578
/// let numberPointer = UnsafeMutablePointer<Int>(&number)
579579
/// // Accessing 'numberPointer' is undefined behavior.
580580
@frozen // unsafe-performance
581-
public struct UnsafeMutablePointer<Pointee>: _Pointer {
581+
public struct UnsafeMutablePointer<Pointee>
582+
: _Pointer, @unchecked _BitwiseCopyable {
582583

583584
/// A type that represents the distance between two pointers.
584585
public typealias Distance = Int

stdlib/public/core/UnsafeRawPointer.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@
169169
/// let numberPointer = UnsafeRawPointer(&number)
170170
/// // Accessing 'numberPointer' is undefined behavior.
171171
@frozen
172-
public struct UnsafeRawPointer: _Pointer {
172+
public struct UnsafeRawPointer: _Pointer, @unchecked _BitwiseCopyable {
173173

174174
public typealias Pointee = UInt8
175175

@@ -727,7 +727,7 @@ extension UnsafeRawPointer {
727727
/// let numberPointer = UnsafeMutableRawPointer(&number)
728728
/// // Accessing 'numberPointer' is undefined behavior.
729729
@frozen
730-
public struct UnsafeMutableRawPointer: _Pointer {
730+
public struct UnsafeMutableRawPointer: _Pointer, @unchecked _BitwiseCopyable {
731731

732732
public typealias Pointee = UInt8
733733

test/Sema/bitwise_copyable.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,21 @@ struct S_Explicit_With_Metatype_Optional_AnyObject : _BitwiseCopyable {
9494
var ty: Optional<AnyObject>.Type
9595
}
9696

97+
struct S_Unchecked : @unchecked _BitwiseCopyable {}
98+
99+
struct S_Implicit_With_S_Unchecked {
100+
var s: S_Unchecked
101+
}
102+
103+
func passS_Implicit_With_S_Unchecked(_ s: S_Implicit_With_S_Unchecked) {
104+
take1(s) // expected-error{{type_does_not_conform_decl_owner}}
105+
// expected-note@-92 {{where_requirement_failure_one_subst}}
106+
}
107+
108+
struct S_Explicit_With_S_Unchecked : _BitwiseCopyable {
109+
var s: S_Unchecked
110+
}
111+
97112
//==============================================================================
98113
//===========================DEPENDENCY-FREE TESTS=(END)======================}}
99114
//==============================================================================

test/SourceKit/DocSupport/doc_clang_module.swift.response

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5654,6 +5654,11 @@ var FooSubUnnamedEnumeratorA1: Int { get }
56545654
key.kind: source.lang.swift.ref.protocol,
56555655
key.name: "_Pointer",
56565656
key.usr: "s:s8_PointerP"
5657+
},
5658+
{
5659+
key.kind: source.lang.swift.ref.protocol,
5660+
key.name: "_BitwiseCopyable",
5661+
key.usr: "s:s16_BitwiseCopyableP"
56575662
}
56585663
]
56595664
},

test/api-digester/Outputs/cake-abi.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,6 +1745,13 @@
17451745
"usr": "s:s25LosslessStringConvertibleP",
17461746
"mangledName": "$ss25LosslessStringConvertibleP"
17471747
},
1748+
{
1749+
"kind": "Conformance",
1750+
"name": "_BitwiseCopyable",
1751+
"printedName": "_BitwiseCopyable",
1752+
"usr": "s:s16_BitwiseCopyableP",
1753+
"mangledName": "$ss16_BitwiseCopyableP"
1754+
},
17481755
{
17491756
"kind": "Conformance",
17501757
"name": "SignedNumeric",
@@ -2022,13 +2029,6 @@
20222029
],
20232030
"usr": "s:s10SIMDScalarP",
20242031
"mangledName": "$ss10SIMDScalarP"
2025-
},
2026-
{
2027-
"kind": "Conformance",
2028-
"name": "_BitwiseCopyable",
2029-
"printedName": "_BitwiseCopyable",
2030-
"usr": "s:s16_BitwiseCopyableP",
2031-
"mangledName": "$ss16_BitwiseCopyableP"
20322032
}
20332033
]
20342034
}

test/api-digester/Outputs/stability-stdlib-source-x86_64.swift.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,4 @@ Func withoutActuallyEscaping(_:do:) is now without @rethrows
4848

4949
Protocol SIMDScalar has generic signature change from <Self == Self.SIMD16Storage.Scalar, Self.SIMD16Storage : Swift.SIMDStorage, Self.SIMD2Storage : Swift.SIMDStorage, Self.SIMD32Storage : Swift.SIMDStorage, Self.SIMD4Storage : Swift.SIMDStorage, Self.SIMD64Storage : Swift.SIMDStorage, Self.SIMD8Storage : Swift.SIMDStorage, Self.SIMDMaskScalar : Swift.FixedWidthInteger, Self.SIMDMaskScalar : Swift.SIMDScalar, Self.SIMDMaskScalar : Swift.SignedInteger, Self.SIMD16Storage.Scalar == Self.SIMD2Storage.Scalar, Self.SIMD2Storage.Scalar == Self.SIMD32Storage.Scalar, Self.SIMD32Storage.Scalar == Self.SIMD4Storage.Scalar, Self.SIMD4Storage.Scalar == Self.SIMD64Storage.Scalar, Self.SIMD64Storage.Scalar == Self.SIMD8Storage.Scalar> to <Self : Swift._BitwiseCopyable, Self == Self.SIMD16Storage.Scalar, Self.SIMD16Storage : Swift.SIMDStorage, Self.SIMD2Storage : Swift.SIMDStorage, Self.SIMD32Storage : Swift.SIMDStorage, Self.SIMD4Storage : Swift.SIMDStorage, Self.SIMD64Storage : Swift.SIMDStorage, Self.SIMD8Storage : Swift.SIMDStorage, Self.SIMDMaskScalar : Swift.FixedWidthInteger, Self.SIMDMaskScalar : Swift.SIMDScalar, Self.SIMDMaskScalar : Swift.SignedInteger, Self.SIMDMaskScalar == Self.SIMDMaskScalar.SIMDMaskScalar, Self.SIMD16Storage.Scalar == Self.SIMD2Storage.Scalar, Self.SIMD2Storage.Scalar == Self.SIMD32Storage.Scalar, Self.SIMD32Storage.Scalar == Self.SIMD4Storage.Scalar, Self.SIMD4Storage.Scalar == Self.SIMD64Storage.Scalar, Self.SIMD64Storage.Scalar == Self.SIMD8Storage.Scalar>
5050
Protocol SIMDStorage has generic signature change from <Self.Scalar : Swift.Decodable, Self.Scalar : Swift.Encodable, Self.Scalar : Swift.Hashable> to <Self : Swift._BitwiseCopyable, Self.Scalar : Swift.Decodable, Self.Scalar : Swift.Encodable, Self.Scalar : Swift.Hashable>
51+
Protocol FixedWidthInteger has generic signature change from <Self : Swift.BinaryInteger, Self : Swift.LosslessStringConvertible, Self.Magnitude : Swift.FixedWidthInteger, Self.Magnitude : Swift.UnsignedInteger, Self.Stride : Swift.FixedWidthInteger, Self.Stride : Swift.SignedInteger> to <Self : Swift.BinaryInteger, Self : Swift.LosslessStringConvertible, Self : Swift._BitwiseCopyable, Self.Magnitude : Swift.FixedWidthInteger, Self.Magnitude : Swift.UnsignedInteger, Self.Stride : Swift.FixedWidthInteger, Self.Stride : Swift.SignedInteger>

test/api-digester/stability-stdlib-abi-without-asserts.test

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,5 +179,8 @@ Protocol SIMDStorage has added inherited protocol _BitwiseCopyable
179179
Protocol SIMDStorage has generic signature change from <Self.Scalar : Swift.Decodable, Self.Scalar : Swift.Encodable, Self.Scalar : Swift.Hashable> to <Self : Swift._BitwiseCopyable, Self.Scalar : Swift.Decodable, Self.Scalar : Swift.Encodable, Self.Scalar : Swift.Hashable>
180180
Protocol _Pointer has added inherited protocol _BitwiseCopyable
181181
Protocol _Pointer has generic signature change from <Self : Swift.CustomDebugStringConvertible, Self : Swift.CustomReflectable, Self : Swift.Hashable, Self : Swift.Strideable> to <Self : Swift.CustomDebugStringConvertible, Self : Swift.CustomReflectable, Self : Swift.Hashable, Self : Swift.Strideable, Self : Swift._BitwiseCopyable>
182+
Protocol FixedWidthInteger has added inherited protocol _BitwiseCopyable
183+
Protocol FixedWidthInteger has generic signature change from <Self : Swift.BinaryInteger, Self : Swift.LosslessStringConvertible, Self.Magnitude : Swift.FixedWidthInteger, Self.Magnitude : Swift.UnsignedInteger, Self.Stride : Swift.FixedWidthInteger, Self.Stride : Swift.SignedInteger> to <Self : Swift.BinaryInteger, Self : Swift.LosslessStringConvertible, Self : Swift._BitwiseCopyable, Self.Magnitude : Swift.FixedWidthInteger, Self.Magnitude : Swift.UnsignedInteger, Self.Stride : Swift.FixedWidthInteger, Self.Stride : Swift.SignedInteger>
184+
182185

183186
// *** DO NOT DISABLE OR XFAIL THIS TEST. *** (See comment above.)

0 commit comments

Comments
 (0)