From cc7a41fc2c14906c73dc4c2bebc2b9e61ba1cf9b Mon Sep 17 00:00:00 2001 From: Kavon Farvardin Date: Wed, 20 Sep 2023 11:04:25 -0700 Subject: [PATCH] [stdilb] introduce `Copyable` protocol This replaces the old, unavailable `_Copyable`. rdar://110420673 --- include/swift/AST/KnownProtocols.def | 2 +- stdlib/public/core/Misc.swift | 5 +++- .../async_overload_filtering.swift | 2 +- test/Constraints/copyable_requirement.swift | 21 +++++++------- test/Constraints/moveonly_constraints.swift | 9 +++--- test/ModuleInterface/copyable.swift | 2 +- ...t_copyable.swift => inverses_legacy.swift} | 16 +++-------- test/SILGen/unmanaged_ownership.swift | 2 +- .../nonescaping_partial_apply_gauntlet.swift | 2 +- .../opaque_values_Onone_stdlib.swift | 2 +- test/Sema/copyable.swift | 28 +++++++++---------- test/Sema/copyable_constraint.swift | 2 +- test/Sema/moveonly_sendable.swift | 2 +- 13 files changed, 43 insertions(+), 52 deletions(-) rename test/Parse/{without_copyable.swift => inverses_legacy.swift} (70%) diff --git a/include/swift/AST/KnownProtocols.def b/include/swift/AST/KnownProtocols.def index d55dd229cb7..5fc531f75cf 100644 --- a/include/swift/AST/KnownProtocols.def +++ b/include/swift/AST/KnownProtocols.def @@ -126,7 +126,7 @@ PROTOCOL(AsyncIteratorProtocol) PROTOCOL(FloatingPoint) -PROTOCOL_(Copyable) +PROTOCOL(Copyable) EXPRESSIBLE_BY_LITERAL_PROTOCOL(ExpressibleByArrayLiteral, "Array", false) EXPRESSIBLE_BY_LITERAL_PROTOCOL(ExpressibleByBooleanLiteral, "BooleanLiteralType", true) diff --git a/stdlib/public/core/Misc.swift b/stdlib/public/core/Misc.swift index af478b9115c..7bdc22e3ed9 100644 --- a/stdlib/public/core/Misc.swift +++ b/stdlib/public/core/Misc.swift @@ -164,4 +164,7 @@ public func _unsafePerformance(_ c: () -> T) -> T { /// constraints on generics in your programs. It is currently /// only used internally by the compiler. @available(*, unavailable) -@_marker public protocol _Copyable {} +@_marker public protocol _Copyable {} // FIXME: rdar://115793371 (delete _Copyable from stdlib) + + +@_marker public protocol Copyable {} diff --git a/test/Concurrency/async_overload_filtering.swift b/test/Concurrency/async_overload_filtering.swift index aaf44645b8e..31b89ccf310 100644 --- a/test/Concurrency/async_overload_filtering.swift +++ b/test/Concurrency/async_overload_filtering.swift @@ -18,7 +18,7 @@ func filter_async(_: String) -> Void {} var a: String? = nil // CHECK: attempting disjunction choice $T0 bound to decl async_overload_filtering.(file).filter_async(fn2:) -// CHECK-NEXT: added constraint: {{.*}} conforms to _Copyable +// CHECK-NEXT: added constraint: {{.*}} conforms to Copyable // CHECK-NEXT: overload set choice binding $T0 := {{.*}} // CHECK-NEXT: (considering: ({{.*}}) -> {{.*}} applicable fn {{.*}} // CHECK: increasing 'sync-in-asynchronous' score by 1 diff --git a/test/Constraints/copyable_requirement.swift b/test/Constraints/copyable_requirement.swift index cb636f3977a..ec6db2ca9f4 100644 --- a/test/Constraints/copyable_requirement.swift +++ b/test/Constraints/copyable_requirement.swift @@ -108,7 +108,7 @@ func checkBasicBoxes() { _ = rb.get() _ = rb.val - let vb2: ValBox = .init(MO()) // expected-error {{type 'MO' does not conform to protocol '_Copyable'}} + let vb2: ValBox = .init(MO()) // expected-error {{type 'MO' does not conform to protocol 'Copyable'}} } func checkExistential() { @@ -126,15 +126,15 @@ func checkExistential() { } func checkMethodCalls() { - let tg: NotStoredGenerically = NotStoredGenerically() // expected-error {{type 'MO' does not conform to protocol '_Copyable'}} + let tg: NotStoredGenerically = NotStoredGenerically() // expected-error {{type 'MO' does not conform to protocol 'Copyable'}} tg.take(MO()) tg.give() let _ = Maybe.just(MO()) // expected-error {{noncopyable type 'MO' cannot be substituted for copyable generic parameter 'T' in 'Maybe'}} - let _: Maybe = .none // expected-error {{type 'MO' does not conform to protocol '_Copyable'}} - let _ = Maybe.just(MO()) // expected-error {{type 'MO' does not conform to protocol '_Copyable'}} - let _: Maybe = .just(MO()) // expected-error {{type 'MO' does not conform to protocol '_Copyable'}} + let _: Maybe = .none // expected-error {{type 'MO' does not conform to protocol 'Copyable'}} + let _ = Maybe.just(MO()) // expected-error {{type 'MO' does not conform to protocol 'Copyable'}} + let _: Maybe = .just(MO()) // expected-error {{type 'MO' does not conform to protocol 'Copyable'}} takeMaybe(.just(MO())) // expected-error {{noncopyable type 'MO' cannot be substituted for copyable generic parameter 'T' in 'takeMaybe'}} takeMaybe(true ? .none : .just(MO())) @@ -144,7 +144,7 @@ func checkMethodCalls() { func checkCasting(_ b: any Box, _ mo: borrowing MO, _ a: Any) { // casting dynamically is allowed, but should always fail since you can't // construct such a type. - let box = b as! ValBox // expected-error {{type 'MO' does not conform to protocol '_Copyable'}} + let box = b as! ValBox // expected-error {{type 'MO' does not conform to protocol 'Copyable'}} let dup = box let _: MO = dup.get() @@ -157,8 +157,7 @@ func checkCasting(_ b: any Box, _ mo: borrowing MO, _ a: Any) { let _: Sendable = (MO(), MO()) // expected-error {{noncopyable type '(MO, MO)' cannot be erased to copyable existential type 'any Sendable'}} let _: Sendable = MO() // expected-error {{noncopyable type 'MO' cannot be erased to copyable existential type 'any Sendable'}} - let _: _Copyable = mo // expected-error {{'_Copyable' is unavailable}} - // expected-error@-1 {{noncopyable type 'MO' cannot be erased to copyable existential type 'any _Copyable'}} + let _: Copyable = mo // expected-error {{noncopyable type 'MO' cannot be erased to copyable existential type 'any Copyable'}} let _: AnyObject = MO() // expected-error {{noncopyable type 'MO' cannot be erased to copyable existential type 'AnyObject'}} let _: Any = mo // expected-error {{noncopyable type 'MO' cannot be erased to copyable existential type 'Any'}} @@ -262,11 +261,11 @@ protocol HasType { } class SomeGuy: HasType { // expected-error {{type 'SomeGuy' does not conform to protocol 'HasType'}} - typealias Ty = MO // expected-note {{possibly intended match 'SomeGuy.Ty' (aka 'MO') does not conform to '_Copyable'}} + typealias Ty = MO // expected-note {{possibly intended match 'SomeGuy.Ty' (aka 'MO') does not conform to 'Copyable'}} } struct AnotherGuy: HasType { // expected-error {{type 'AnotherGuy' does not conform to protocol 'HasType'}} - @_moveOnly struct Ty {} // expected-note {{possibly intended match 'AnotherGuy.Ty' does not conform to '_Copyable'}} + @_moveOnly struct Ty {} // expected-note {{possibly intended match 'AnotherGuy.Ty' does not conform to 'Copyable'}} } protocol Gives: HasType { @@ -274,7 +273,7 @@ protocol Gives: HasType { } struct GenerousGuy: Gives { // expected-error {{type 'GenerousGuy' does not conform to protocol 'HasType'}} - typealias Ty = MO // expected-note {{possibly intended match 'GenerousGuy.Ty' (aka 'MO') does not conform to '_Copyable'}} + typealias Ty = MO // expected-note {{possibly intended match 'GenerousGuy.Ty' (aka 'MO') does not conform to 'Copyable'}} func give() -> Ty {} } diff --git a/test/Constraints/moveonly_constraints.swift b/test/Constraints/moveonly_constraints.swift index 5687c116295..e4809c95dde 100644 --- a/test/Constraints/moveonly_constraints.swift +++ b/test/Constraints/moveonly_constraints.swift @@ -160,8 +160,7 @@ func checkCasting(_ b: any Box, _ mo: borrowing MO, _ a: Any) { let _: Sendable = (MO(), MO()) // expected-error {{noncopyable type '(MO, MO)' cannot be erased to copyable existential type 'any Sendable'}} let _: Sendable = MO() // expected-error {{noncopyable type 'MO' cannot be erased to copyable existential type 'any Sendable'}} - let _: _Copyable = mo // expected-error {{'_Copyable' is unavailable}} - // expected-error@-1 {{noncopyable type 'MO' cannot be erased to copyable existential type 'any _Copyable'}} + let _: Copyable = mo // expected-error {{noncopyable type 'MO' cannot be erased to copyable existential type 'any Copyable'}} let _: AnyObject = MO() // expected-error {{noncopyable type 'MO' cannot be erased to copyable existential type 'AnyObject'}} let _: Any = mo // expected-error {{noncopyable type 'MO' cannot be erased to copyable existential type 'Any'}} @@ -260,11 +259,11 @@ protocol HasType { } class SomeGuy: HasType { // expected-error {{type 'SomeGuy' does not conform to protocol 'HasType'}} - typealias Ty = MO // expected-note {{possibly intended match 'SomeGuy.Ty' (aka 'MO') does not conform to '_Copyable'}} + typealias Ty = MO // expected-note {{possibly intended match 'SomeGuy.Ty' (aka 'MO') does not conform to 'Copyable'}} } struct AnotherGuy: HasType { // expected-error {{type 'AnotherGuy' does not conform to protocol 'HasType'}} - @_moveOnly struct Ty {} // expected-note {{possibly intended match 'AnotherGuy.Ty' does not conform to '_Copyable'}} + @_moveOnly struct Ty {} // expected-note {{possibly intended match 'AnotherGuy.Ty' does not conform to 'Copyable'}} } protocol Gives: HasType { @@ -272,7 +271,7 @@ protocol Gives: HasType { } struct GenerousGuy: Gives { // expected-error {{type 'GenerousGuy' does not conform to protocol 'HasType'}} - typealias Ty = MO // expected-note {{possibly intended match 'GenerousGuy.Ty' (aka 'MO') does not conform to '_Copyable'}} + typealias Ty = MO // expected-note {{possibly intended match 'GenerousGuy.Ty' (aka 'MO') does not conform to 'Copyable'}} func give() -> Ty {} } diff --git a/test/ModuleInterface/copyable.swift b/test/ModuleInterface/copyable.swift index 018483ec5be..595d1b014c0 100644 --- a/test/ModuleInterface/copyable.swift +++ b/test/ModuleInterface/copyable.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) -// This test checks that conformances to _Copyable do not appear in swiftinterface files +// This test checks that conformances to Copyable do not appear in swiftinterface files // Generate the parseable interface of the current file via the merge-modules step // RUN: %target-build-swift -emit-module -o %t/Test.swiftmodule -emit-module-interface-path %t/TestMerge.swiftinterface -module-name Test %s -enable-library-evolution -swift-version 5 diff --git a/test/Parse/without_copyable.swift b/test/Parse/inverses_legacy.swift similarity index 70% rename from test/Parse/without_copyable.swift rename to test/Parse/inverses_legacy.swift index 9c125c11aa2..c12b512dbca 100644 --- a/test/Parse/without_copyable.swift +++ b/test/Parse/inverses_legacy.swift @@ -21,22 +21,18 @@ struct U: // expected-error {{noncopyable struct 'U' cannot conform to 'Sando'}} class C: // expected-error {{type 'C' does not conform to protocol 'Sando'}} ~Copyable, // expected-error {{cannot suppress conformances here}} - // expected-error@-1 {{cannot find type 'Copyable' in scope}} ~Sando // expected-error {{cannot suppress conformances here}} {} protocol Rope: ~Copyable { // expected-error {{cannot suppress conformances here}} - // expected-error@-1 {{cannot find type 'Copyable' in scope}} associatedtype Element: ~Copyable // expected-error {{cannot suppress conformances here}} - // expected-error@-1 {{cannot find type 'Copyable' in scope}} } extension S: ~Copyable {} // expected-error {{cannot suppress conformances here}} - // expected-error@-1 {{cannot find type 'Copyable' in scope}} + // expected-error@-1 {{noncopyable struct 'S' cannot conform to 'Copyable'}} func takeNoncopyableGeneric(_ t: T) {} // expected-error {{cannot suppress conformances here}} - // expected-error@-1 {{cannot find type 'Copyable' in scope}} @_moveOnly struct ExtraNonCopyable: // expected-error {{duplicate attribute}}{{1-12=}} ~Copyable // expected-note {{attribute already specified here}} @@ -48,6 +44,7 @@ struct HasADeinit: ~Copyable { deinit {} } public struct MoveOnlyS1 : ~Copyable { deinit {} } public struct MoveOnlyS2 : ~Copyable { deinit {} } +public struct MoveOnlyS3 : ~Copyable { deinit {} } // expected-error {{cannot suppress conformances here}} public enum MoveOnlyE1 : ~Copyable { case holding(s: MoveOnlyS1) @@ -60,22 +57,17 @@ public enum MoveOnlyE2 : ~Copyable { } func more() { - let foo: any ~Copyable = 19 // expected-error@:16 {{cannot suppress conformances here}} - // expected-error@-1 {{cannot find type 'Copyable' in scope}} + let _: any ~Copyable = 19 // expected-error@:14 {{cannot suppress conformances here}} - let foo: any ~Equatable = 19 // expected-error@:16 {{cannot suppress conformances here}} + let _: any ~Equatable = 19 // expected-error@:14 {{cannot suppress conformances here}} } func blah(_ t: T) where T: ~Copyable, // expected-error@:31 {{cannot suppress conformances here}} - // expected-error@-1 {{cannot find type 'Copyable' in scope}} T: ~Hashable {} // expected-error@:31 {{cannot suppress conformances here}} func foo(x: T) {} // expected-error {{cannot suppress conformances here}} - // expected-error@-1 {{cannot find type 'Copyable' in scope}} struct Buurap {} // expected-error {{cannot suppress conformances here}} - // expected-error@-1 {{cannot find type 'Copyable' in scope}} protocol Foo where Self: ~Copyable {} // expected-error {{cannot suppress conformances here}} - // expected-error@-1 {{cannot find type 'Copyable' in scope}} diff --git a/test/SILGen/unmanaged_ownership.swift b/test/SILGen/unmanaged_ownership.swift index 8549c4c7655..19001f3588e 100644 --- a/test/SILGen/unmanaged_ownership.swift +++ b/test/SILGen/unmanaged_ownership.swift @@ -1,7 +1,7 @@ // RUN: %target-swift-emit-silgen -parse-stdlib -module-name Swift %s | %FileCheck %s -@_marker protocol _Copyable {} +@_marker protocol Copyable {} class C {} diff --git a/test/SILOptimizer/nonescaping_partial_apply_gauntlet.swift b/test/SILOptimizer/nonescaping_partial_apply_gauntlet.swift index e51a78fde0c..e666400e324 100644 --- a/test/SILOptimizer/nonescaping_partial_apply_gauntlet.swift +++ b/test/SILOptimizer/nonescaping_partial_apply_gauntlet.swift @@ -5,7 +5,7 @@ // RUN: %target-swift-frontend -emit-sil -parse-stdlib -module-name Swift %s // RUN: %target-swift-frontend -emit-sil -O -parse-stdlib -module-name Swift %s -@_marker protocol _Copyable {} +@_marker protocol Copyable {} precedencegroup CastingPrecedence {} precedencegroup AssignmentPrecedence {} diff --git a/test/SILOptimizer/opaque_values_Onone_stdlib.swift b/test/SILOptimizer/opaque_values_Onone_stdlib.swift index 154a1e24320..9da2edcebe1 100644 --- a/test/SILOptimizer/opaque_values_Onone_stdlib.swift +++ b/test/SILOptimizer/opaque_values_Onone_stdlib.swift @@ -10,7 +10,7 @@ precedencegroup AssignmentPrecedence { assignment: true } precedencegroup CastingPrecedence {} public protocol _ObjectiveCBridgeable {} -@_marker public protocol _Copyable {} +@_marker public protocol Copyable {} public protocol _ExpressibleByBuiltinBooleanLiteral { init(_builtinBooleanLiteral value: Builtin.Int1) diff --git a/test/Sema/copyable.swift b/test/Sema/copyable.swift index 44bb6e957da..150f9412d3b 100644 --- a/test/Sema/copyable.swift +++ b/test/Sema/copyable.swift @@ -1,30 +1,28 @@ // RUN: %target-typecheck-verify-swift -protocol P: _Copyable {} // expected-error {{'_Copyable' is unavailable}} +protocol P: Copyable {} struct S: P {} -typealias PleaseLetMeDoIt = _Copyable // expected-error {{'_Copyable' is unavailable}} -typealias WhatIfIQualify = Swift._Copyable // expected-error {{'_Copyable' is unavailable}} +typealias PleaseLetMeDoIt = Copyable +typealias WhatIfIQualify = Swift.Copyable -class C: _Copyable {} // expected-error {{'_Copyable' is unavailable}} +class C: Copyable {} -@_moveOnly struct MOStruct: _Copyable {} -// expected-error@-1 {{noncopyable struct 'MOStruct' cannot conform to '_Copyable'}} -// expected-error@-2 {{'_Copyable' is unavailable}} +@_moveOnly struct MOStruct: Copyable {} // expected-error {{noncopyable struct 'MOStruct' cannot conform to 'Copyable'}} -func whatever(_ t: T) where T: _Copyable {} // expected-error {{'_Copyable' is unavailable}} -func vatever(_ t: T) {} // expected-error {{'_Copyable' is unavailable}} -func buttever(_ t: any _Copyable) {} // expected-error {{'_Copyable' is unavailable}} -func zuttever(_ t: some _Copyable) {} // expected-error 2{{'_Copyable' is unavailable}} +func whatever(_ t: T) where T: Copyable {} +func vatever(_ t: T) {} +func buttever(_ t: any Copyable) {} +func zuttever(_ t: some Copyable) {} -enum RockNRoll { // expected-error {{'_Copyable' is unavailable}} - case isNoisePollution(_Copyable) // expected-error {{'_Copyable' is unavailable}} +enum RockNRoll { + case isNoisePollution(Copyable) case isMusic(T) } enum namespace { - typealias _Copyable = Int + typealias Copyable = Int - func _Copyable() -> _Copyable { return 0 } + func Copyable() -> Copyable { return 0 } } diff --git a/test/Sema/copyable_constraint.swift b/test/Sema/copyable_constraint.swift index 1210345b467..d7dc938d7eb 100644 --- a/test/Sema/copyable_constraint.swift +++ b/test/Sema/copyable_constraint.swift @@ -5,7 +5,7 @@ // FIXME: Now demonstrate that plain -parse-stdlib, such as in some arbitrary test, doesn't get the Copyable constraint :( // RUN: not %target-swift-frontend -typecheck -verify -parse-stdlib %s -@_marker public protocol _Copyable {} +@_marker public protocol Copyable {} func nextTime(_ t: T) {} // expected-note {{generic parameter 'T' has an implicit Copyable requirement}} diff --git a/test/Sema/moveonly_sendable.swift b/test/Sema/moveonly_sendable.swift index 5dcfcc9be5a..9b86af3fbe0 100644 --- a/test/Sema/moveonly_sendable.swift +++ b/test/Sema/moveonly_sendable.swift @@ -131,7 +131,7 @@ protocol GiveSendable { // make sure witnessing associatedtypes is still prevented, even though we meet the explicit constraint. class Bad: GiveSendable { // expected-error {{type 'Bad' does not conform to protocol 'GiveSendable'}} - typealias T = FileDescriptor // expected-note {{possibly intended match 'Bad.T' (aka 'FileDescriptor') does not conform to '_Copyable'}} + typealias T = FileDescriptor // expected-note {{possibly intended match 'Bad.T' (aka 'FileDescriptor') does not conform to 'Copyable'}} func give() -> FileDescriptor { return FileDescriptor(id: -1) } }