Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BitwiseCopyable] Promote to feature. #73235

Merged
merged 6 commits into from
May 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -7728,12 +7728,14 @@ NOTE(note_non_bitwise_copyable_type_indirect_enum_element,none,
"indirect case is here", ())
ERROR(non_bitwise_copyable_type_suppressed,none,
"cannot both conform to and suppress conformance to 'BitwiseCopyable'", ())
ERROR(non_bitwise_copyable_type_sensitive,none,
"a @sensitive type cannot conform to 'BitwiseCopyable'", ())
ERROR(non_bitwise_copyable_type_cxx_nontrivial,none,
"non-trivial C++ type cannot conform to 'BitwiseCopyable'", ())
ERROR(non_bitwise_copyable_c_type_nontrivial,none,
"type with unrepresentable fields cannot derive conformance to 'BitwiseCopyable'", ())
NOTE(note_non_bitwise_copyable_c_type_add_attr,none,
"annotate the type __attribute__((__swift_attr__(\"_BitwiseCopyable\")))",())
"annotate the type __attribute__((__swift_attr__(\"BitwiseCopyable\")))",())
ERROR(non_bitwise_copyable_type_member,none,
"%select{stored property %2|associated value %2}1 of "
"'BitwiseCopyable'-conforming %kind3 has non-bitwise-copyable type %0",
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/KnownProtocols.def
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ PROTOCOL(FloatingPoint)
INVERTIBLE_PROTOCOL_WITH_NAME(Name, #Name)
#include "swift/ABI/InvertibleProtocols.def"

REPRESSIBLE_PROTOCOL_(BitwiseCopyable)
REPRESSIBLE_PROTOCOL(BitwiseCopyable)

EXPRESSIBLE_BY_LITERAL_PROTOCOL(ExpressibleByArrayLiteral, "Array", false)
EXPRESSIBLE_BY_LITERAL_PROTOCOL(ExpressibleByBooleanLiteral, "BooleanLiteralType", true)
Expand Down
9 changes: 3 additions & 6 deletions include/swift/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ LANGUAGE_FEATURE(BuiltinCreateTask, 0, "Builtin.createTask and Builtin.createDis
SUPPRESSIBLE_LANGUAGE_FEATURE(AssociatedTypeImplements, 0, "@_implements on associated types")
LANGUAGE_FEATURE(BuiltinAddressOfRawLayout, 0, "Builtin.addressOfRawLayout")
LANGUAGE_FEATURE(MoveOnlyPartialConsumption, 429, "Partial consumption of noncopyable values")
/// Enable bitwise-copyable feature.
LANGUAGE_FEATURE(BitwiseCopyable, 426, "BitwiseCopyable protocol")
SUPPRESSIBLE_LANGUAGE_FEATURE(ConformanceSuppression, 426, "Suppressible inferred conformances")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ConformanceSuppression considered part of 426 or 428?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


// Swift 6
UPCOMING_FEATURE(ConciseMagicFile, 274, 6)
Expand Down Expand Up @@ -343,12 +346,6 @@ EXPERIMENTAL_FEATURE(StaticExclusiveOnly, true)
/// Enable the @extractConstantsFromMembers attribute.
EXPERIMENTAL_FEATURE(ExtractConstantsFromMembers, false)

/// Enable bitwise-copyable feature.
EXPERIMENTAL_FEATURE(BitwiseCopyable, true)

/// Enable the suppression of inferred, non-invertible, protocols via ~.
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(ConformanceSuppression, true)

/// Enables the FixedArray data type.
EXPERIMENTAL_FEATURE(FixedArrays, true)

Expand Down
3 changes: 0 additions & 3 deletions lib/AST/LifetimeDependence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,6 @@ static LifetimeDependenceKind getLifetimeDependenceKindFromDecl(
}

static bool isBitwiseCopyable(Type type, ModuleDecl *mod, ASTContext &ctx) {
if (!ctx.LangOpts.hasFeature(Feature::BitwiseCopyable)) {
return false;
}
auto *bitwiseCopyableProtocol =
ctx.getProtocol(KnownProtocolKind::BitwiseCopyable);
if (!bitwiseCopyableProtocol) {
Expand Down
5 changes: 1 addition & 4 deletions lib/AST/ProtocolConformance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1284,10 +1284,7 @@ static SmallVector<ProtocolConformance *, 2> findSynthesizedConformances(
for (auto ip : InvertibleProtocolSet::allKnown())
trySynthesize(getKnownProtocolKind(ip));

if (nominal->getASTContext().LangOpts.hasFeature(
Feature::BitwiseCopyable)) {
trySynthesize(KnownProtocolKind::BitwiseCopyable);
}
trySynthesize(KnownProtocolKind::BitwiseCopyable);
}

/// Distributed actors can synthesize Encodable/Decodable, so look for those
Expand Down
4 changes: 1 addition & 3 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8028,9 +8028,7 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
continue;
}

if (swiftAttr->getAttribute() == "_BitwiseCopyable") {
if (!SwiftContext.LangOpts.hasFeature(Feature::BitwiseCopyable))
continue;
if (swiftAttr->getAttribute() == "BitwiseCopyable") {
auto *protocol =
SwiftContext.getProtocol(KnownProtocolKind::BitwiseCopyable);
auto *nominal = dyn_cast<NominalTypeDecl>(MappedDecl);
Expand Down
37 changes: 28 additions & 9 deletions lib/SIL/IR/TypeLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsSIL.h"
#include "swift/AST/Expr.h"
#include "swift/AST/FileUnit.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/Module.h"
Expand All @@ -28,6 +29,7 @@
#include "swift/AST/Pattern.h"
#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/PropertyWrappers.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/TypeDifferenceVisitor.h"
#include "swift/AST/Types.h"
#include "swift/ClangImporter/ClangModule.h"
Expand Down Expand Up @@ -3041,8 +3043,6 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
AbstractionPattern origType,
CanType substType,
TypeExpansionContext forExpansion) {
if (!Context.LangOpts.hasFeature(Feature::BitwiseCopyable))
return;
auto *bitwiseCopyableProtocol =
Context.getProtocol(KnownProtocolKind::BitwiseCopyable);
if (!bitwiseCopyableProtocol)
Expand All @@ -3057,10 +3057,20 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,

if (auto *nominal = substType.getAnyNominal()) {
auto *module = nominal->getModuleContext();
if (module && module->isBuiltFromInterface()) {
// Don't verify for types in modules built from interfaces; the feature
// may not have been enabled in them.
return;
if (module) {
if (module->isBuiltFromInterface()) {
// Don't verify for types in modules built from interfaces; the feature
// may not have been enabled in them.
return;
}
auto *file = dyn_cast_or_null<FileUnit>(module->getModuleScopeContext());
if (file && file->getKind() == FileUnitKind::Source) {
auto sourceFile = nominal->getParentSourceFile();
if (sourceFile && sourceFile->Kind == SourceFileKind::SIL) {
// Don't verify for types in SIL files.
return;
}
}
}
}

Expand All @@ -3086,6 +3096,7 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
// unconditionally but does in this case
// (8) being or containing the error type
// (9) explicitly suppressing conformance
// (10) a layout constrained archetype
bool hasNoNonconformingNode = visitAggregateLeaves(
origType, substType, forExpansion,
/*isLeafAggregate=*/
Expand Down Expand Up @@ -3155,7 +3166,7 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,

// ModuleTypes are trivial but don't warrant being given a
// conformance to BitwiseCopyable (case (3)).
if (isa<ModuleType, SILTokenType>(ty)) {
if (isa<ModuleType>(ty) || isa<SILTokenType>(ty)) {
// These types should never appear within aggregates.
assert(isTopLevel && "aggregate containing marker type!?");
// If they did, though, they would not justify the aggregate's
Expand All @@ -3174,13 +3185,21 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
return !isTopLevel;
}

// Case (10): a layout-constrained archetype.
if (auto archetype = dyn_cast<ArchetypeType>(ty)) {
auto constraint = archetype->getLayoutConstraint();
if (constraint && constraint->isTrivial()) {
return false;
}
}

auto *nominal = ty.getAnyNominal();

// Non-nominal types (besides case (3) handled above) are trivial iff
// conforming.
if (!nominal) {
llvm::errs()
<< "Non-nominal type without conformance to _BitwiseCopyable:\n"
<< "Non-nominal type without conformance to BitwiseCopyable:\n"
<< ty << "\n"
<< "within " << substType << "\n"
<< "of " << origType << "\n";
Expand Down Expand Up @@ -3291,7 +3310,7 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
return true;
});
if (hasNoConformingArchetypeNode) {
llvm::errs() << "Non-trivial type with _BitwiseCopyable conformance!?:\n"
llvm::errs() << "Non-trivial type with BitwiseCopyable conformance!?:\n"
<< substType << "\n";
conformance.print(llvm::errs());
llvm::errs() << "\n"
Expand Down
8 changes: 8 additions & 0 deletions lib/Sema/TypeCheckBitwise.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,14 @@ static bool checkBitwiseCopyableInstanceStorage(NominalTypeDecl *nominal,
return true;
}

auto &attrs = nominal->getAttrs();
if (attrs.hasAttribute<SensitiveAttr>()) {
if (!isImplicit(check)) {
conformanceDecl->diagnose(diag::non_bitwise_copyable_type_sensitive);
}
return true;
}

if (dc->mapTypeIntoContext(nominal->getDeclaredInterfaceType())
->isNoncopyable()) {
// Already separately diagnosed when explicit.
Expand Down
6 changes: 3 additions & 3 deletions lib/Sema/TypeCheckDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,9 +682,9 @@ ExistentialConformsToSelfRequest::evaluate(Evaluator &evaluator,
ProtocolDecl *decl) const {
// Marker protocols always self-conform.
if (decl->isMarkerProtocol()) {
// Except for BitwiseCopyable an existential of which is non-trivial.
if (decl->getASTContext().LangOpts.hasFeature(Feature::BitwiseCopyable) &&
decl->getKnownProtocolKind() == KnownProtocolKind::BitwiseCopyable) {
// Except for BitwiseCopyable an existential of which is not bitwise
// copyable.
if (decl->getKnownProtocolKind() == KnownProtocolKind::BitwiseCopyable) {
return false;
}
return true;
Expand Down
8 changes: 3 additions & 5 deletions lib/Sema/TypeCheckProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6117,11 +6117,9 @@ void TypeChecker::checkConformancesInContext(IterableDeclContext *idc) {
break;
}
case KnownProtocolKind::BitwiseCopyable: {
if (Context.LangOpts.hasFeature(Feature::BitwiseCopyable)) {
checkBitwiseCopyableConformance(
conformance, /*isImplicit=*/conformance->getSourceKind() ==
ConformanceEntryKind::Synthesized);
}
checkBitwiseCopyableConformance(
conformance, /*isImplicit=*/conformance->getSourceKind() ==
ConformanceEntryKind::Synthesized);
break;
}
default:
Expand Down
2 changes: 0 additions & 2 deletions stdlib/public/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -315,9 +315,7 @@ list(APPEND swift_stdlib_compile_flags "-Xfrontend" "-enable-experimental-concis
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "Macros")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "FreestandingMacros")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "Extern")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "BitwiseCopyable")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "BorrowingSwitch")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "ConformanceSuppression")

if("${SWIFT_NATIVE_SWIFT_TOOLS_PATH}" STREQUAL "")
set(swift_bin_dir "${CMAKE_BINARY_DIR}/bin")
Expand Down
10 changes: 1 addition & 9 deletions stdlib/public/core/CommandLine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,9 @@ internal func _swift_stdlib_getUnsafeArgvArgc(_: UnsafeMutablePointer<Int32>)
-> UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>

/// Command-line arguments for the current process.
#if $BitwiseCopyable && $ConformanceSuppression
@frozen // namespace
public enum CommandLine : ~_BitwiseCopyable {
public enum CommandLine : ~BitwiseCopyable {
}
#else
@frozen // namespace
public enum CommandLine {
}
@available(*, unavailable)
extension CommandLine : _BitwiseCopyable {}
#endif

extension CommandLine {
/// The backing static variable for argument count may come either from the
Expand Down
6 changes: 3 additions & 3 deletions stdlib/public/core/KeyPath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1857,12 +1857,12 @@ internal struct RawKeyPathComponent {
}
}

internal func _pop<T : _BitwiseCopyable>(from: inout UnsafeRawBufferPointer,
internal func _pop<T : BitwiseCopyable>(from: inout UnsafeRawBufferPointer,
as type: T.Type) -> T {
let buffer = _pop(from: &from, as: type, count: 1)
return buffer.baseAddress.unsafelyUnwrapped.pointee
}
internal func _pop<T : _BitwiseCopyable>(from: inout UnsafeRawBufferPointer,
internal func _pop<T : BitwiseCopyable>(from: inout UnsafeRawBufferPointer,
as: T.Type,
count: Int) -> UnsafeBufferPointer<T> {
from = MemoryLayout<T>._roundingUpBaseToAlignment(from)
Expand Down Expand Up @@ -3482,7 +3482,7 @@ internal struct InstantiateKeyPathBuffer: KeyPathPatternVisitor {
}
return (baseAddress, misalign)
}
mutating func pushDest<T : _BitwiseCopyable>(_ value: T) {
mutating func pushDest<T : BitwiseCopyable>(_ value: T) {
let size = MemoryLayout<T>.size
let (baseAddress, misalign) = adjustDestForAlignment(of: T.self)
_withUnprotectedUnsafeBytes(of: value) {
Expand Down
9 changes: 1 addition & 8 deletions stdlib/public/core/MemoryLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,8 @@
/// let pointPointer = UnsafeMutableRawPointer.allocate(
/// byteCount: count * MemoryLayout<Point>.stride,
/// alignment: MemoryLayout<Point>.alignment)
#if $BitwiseCopyable && $ConformanceSuppression
@frozen // namespace
public enum MemoryLayout<T: ~Copyable>: ~_BitwiseCopyable, Copyable {}
#else
@frozen // namespace
public enum MemoryLayout<T: ~Copyable>: Copyable {}
@available(*, unavailable)
extension MemoryLayout: _BitwiseCopyable {}
#endif
public enum MemoryLayout<T: ~Copyable>: ~BitwiseCopyable, Copyable {}

extension MemoryLayout where T: ~Copyable {
/// The contiguous memory footprint of `T`, in bytes.
Expand Down
7 changes: 5 additions & 2 deletions stdlib/public/core/Misc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,10 @@ func _rethrowsViaClosure(_ fn: () throws -> ()) rethrows {
@_marker public protocol Escapable {}

#if $NoncopyableGenerics && $NonescapableTypes
@_marker public protocol _BitwiseCopyable: ~Escapable { }
@_marker public protocol BitwiseCopyable: ~Escapable { }
#else
@_marker public protocol _BitwiseCopyable { }
@_marker public protocol BitwiseCopyable { }
#endif

@available(*, unavailable)
@_marker public protocol _BitwiseCopyable {}
2 changes: 1 addition & 1 deletion stdlib/public/core/Optional.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ extension Optional: Copyable /* where Wrapped: Copyable */ {}

extension Optional: Sendable where Wrapped: ~Copyable & Sendable { }

extension Optional: _BitwiseCopyable where Wrapped: _BitwiseCopyable { }
extension Optional: BitwiseCopyable where Wrapped: BitwiseCopyable { }

@_preInverseGenerics
extension Optional: ExpressibleByNilLiteral where Wrapped: ~Copyable {
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/core/Pointer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public protocol _Pointer:
Strideable,
_CustomDebugStringConvertibleOrNone,
_CustomReflectableOrNone,
_BitwiseCopyable
BitwiseCopyable
{
/// A type that represents the distance between two pointers.
typealias Distance = Int
Expand Down
8 changes: 4 additions & 4 deletions stdlib/public/core/SIMDVector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ prefix operator .!
/// elementwise accesses. Computational operations are defined on the `SIMD`
/// protocol, which refines this protocol, and on the concrete types that
/// conform to `SIMD`.
public protocol SIMDStorage : _BitwiseCopyable {
public protocol SIMDStorage : BitwiseCopyable {
/// The type of scalars in the vector space.
#if $Embedded
associatedtype Scalar: Hashable
Expand Down Expand Up @@ -64,7 +64,7 @@ extension SIMDStorage {
}

/// A type that can be used as an element in a SIMD vector.
public protocol SIMDScalar : _BitwiseCopyable {
public protocol SIMDScalar : BitwiseCopyable {
associatedtype SIMDMaskScalar: SIMDScalar & FixedWidthInteger & SignedInteger
where SIMDMaskScalar.SIMDMaskScalar == SIMDMaskScalar
associatedtype SIMD2Storage: SIMDStorage where SIMD2Storage.Scalar == Self
Expand All @@ -81,7 +81,7 @@ public protocol SIMD<Scalar>:
SIMDStorage,
Hashable,
ExpressibleByArrayLiteral,
_BitwiseCopyable
BitwiseCopyable
{
/// The mask type resulting from pointwise comparisons of this vector type.
associatedtype MaskStorage: SIMD
Expand All @@ -97,7 +97,7 @@ public protocol SIMD<Scalar>:
Hashable,
CustomStringConvertible,
ExpressibleByArrayLiteral,
_BitwiseCopyable
BitwiseCopyable
{
/// The mask type resulting from pointwise comparisons of this vector type.
associatedtype MaskStorage: SIMD
Expand Down
8 changes: 1 addition & 7 deletions stdlib/public/core/Unicode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -671,11 +671,5 @@ public func transcode<Input, InputEncoding, OutputEncoding>(
}

/// A namespace for Unicode utilities.
#if $BitwiseCopyable && $ConformanceSuppression
@frozen
public enum Unicode : ~_BitwiseCopyable {}
#else
@frozen
public enum Unicode {}
#endif

public enum Unicode : ~BitwiseCopyable {}