Skip to content

Commit 3316cf0

Browse files
authored
Merge pull request #41996 from DougGregor/implicit-open-by-default
[SE-0352] Implicit opening of existentials by default
2 parents d0950d1 + c76a99b commit 3316cf0

File tree

11 files changed

+44
-23
lines changed

11 files changed

+44
-23
lines changed

CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,28 @@ _**Note:** This is in reverse chronological order, so newer entries are added to
55

66
## Swift 5.7
77

8+
* [SE-0352][]:
9+
10+
It's now possible to call a generic function with a value of protocol type
11+
in places that would previously fail because `any` types do not conform
12+
to their protocols. For example:
13+
14+
```
15+
protocol P {
16+
associatedtype A
17+
func getA() -> A
18+
}
19+
20+
func takeP<T: P>(_ value: T) { }
21+
22+
func test(p: any P) {
23+
takeP(p) // was an error "type 'any P' cannot conform to 'P'", now accepted
24+
}
25+
```
26+
27+
This operates by "opening" the value of protocol type and passing the
28+
underlying type directly to the generic function.
29+
830
* [SE-0347][]:
931

1032
It's now possible to use a default value expression with a generic parameter type
@@ -9162,6 +9184,7 @@ Swift 1.0
91629184
[SE-0345]: <https://github.com/apple/swift-evolution/blob/main/proposals/0345-if-let-shorthand.md>
91639185
[SE-0326]: <https://github.com/apple/swift-evolution/blob/main/proposals/0326-extending-multi-statement-closure-inference.md>
91649186
[SE-0347]: <https://github.com/apple/swift-evolution/blob/main/proposals/0347-type-inference-from-default-exprs.md>
9187+
[SE-0352]: <https://github.com/apple/swift-evolution/blob/main/proposals/0352-implicit-open-existentials.md>
91659188

91669189
[SR-75]: <https://bugs.swift.org/browse/SR-75>
91679190
[SR-106]: <https://bugs.swift.org/browse/SR-106>

lib/Frontend/CompilerInvocation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
462462
Opts.EnableOpenedExistentialTypes =
463463
Args.hasFlag(OPT_enable_experimental_opened_existential_types,
464464
OPT_disable_experimental_opened_existential_types,
465-
false);
465+
true);
466466

467467
Opts.EnableExperimentalVariadicGenerics |=
468468
Args.hasArg(OPT_enable_experimental_variadic_generics);

test/Generics/existential_restrictions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -enable-objc-interop
1+
// RUN: %target-typecheck-verify-swift -enable-objc-interop -disable-experimental-opened-existential-types
22

33
protocol P { }
44
@objc protocol OP { }

test/RemoteAST/existentials.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,6 @@ printDynamicTypeAndAddressForExistential(q)
5151
// Case five: existential metatypes.
5252
// CHECK-NEXT: Any.Type
5353
let metatype : Any.Type = Any.self
54-
printDynamicTypeAndAddressForExistential(metatype)
54+
printDynamicTypeAndAddressForExistential(metatype as Any.Type)
5555
56-
stopRemoteAST()
56+
stopRemoteAST()

test/SILGen/builtins.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ func class_archetype_to_native_object<T : C>(_ t: T) -> Builtin.NativeObject {
224224
// CHECK-NEXT: [[PTR:%[0-9]+]] = unchecked_ref_cast [[REF]] : $@opened({{.*}}) ClassProto to $Builtin.NativeObject
225225
// CHECK-NEXT: return [[PTR]]
226226
func class_existential_to_native_object(_ t:ClassProto) -> Builtin.NativeObject {
227-
return Builtin.unsafeCastToNativeObject(t)
227+
return Builtin.unsafeCastToNativeObject(t as ClassProto)
228228
}
229229

230230
// CHECK-LABEL: sil hidden [ossa] @$s8builtins24class_from_native_object{{[_0-9a-zA-Z]*}}F
@@ -718,7 +718,7 @@ func refcast_class_any(_ o: A) -> AnyObject {
718718
// CHECK-LABEL: sil hidden [ossa] @$s8builtins20refcast_punknown_any{{[_0-9a-zA-Z]*}}F
719719
// CHECK: unchecked_ref_cast_addr PUnknown in %{{.*}} : $*PUnknown to AnyObject in %{{.*}} : $*AnyObject
720720
func refcast_punknown_any(_ o: PUnknown) -> AnyObject {
721-
return Builtin.castReference(o)
721+
return Builtin.castReference(o as PUnknown)
722722
}
723723

724724
// CHECK-LABEL: sil hidden [ossa] @$s8builtins18refcast_pclass_anyyyXlAA6PClass_pF :
@@ -728,7 +728,7 @@ func refcast_punknown_any(_ o: PUnknown) -> AnyObject {
728728
// CHECK: return [[ARG_CAST]]
729729
// CHECK: } // end sil function '$s8builtins18refcast_pclass_anyyyXlAA6PClass_pF'
730730
func refcast_pclass_any(_ o: PClass) -> AnyObject {
731-
return Builtin.castReference(o)
731+
return Builtin.castReference(o as PClass)
732732
}
733733

734734
// CHECK-LABEL: sil hidden [ossa] @$s8builtins20refcast_any_punknown{{[_0-9a-zA-Z]*}}F

test/SILOptimizer/specialize_class_inherits_base_inherits_protocol.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ protocol Q: P { }
55

66
@inline(never) func sink<T>(_ x: T) {}
77

8-
func p<T: Q>(_ x: T) { sink(x.p()) }
8+
func p<T: Q>(_ x: T) { sink(x.p() as Any.Type) }
99

1010
class Foo<T>: Q { func p() -> Any.Type { return T.self } }
1111
class Bar<T>: Foo<T> {}
Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
// RUN: %target-typecheck-verify-swift
22

3-
func wantsError<T: Error>(_: T) {}
4-
// expected-note@-1 {{required by global function 'wantsError' where 'T' = 'any ErrorRefinement'}}
5-
// expected-note@-2 {{required by global function 'wantsError' where 'T' = 'any Error & OtherProtocol'}}
6-
// expected-note@-3 {{required by global function 'wantsError' where 'T' = 'any C & Error'}}
3+
func opensError<T: Error>(_: T) {}
4+
func wantsError<T: Error>(_: T, _: T) {}
5+
// expected-note@-1 3{{required by global function 'wantsError' where 'T' = 'any}}
76

87
func testSimple(error: Error) {
9-
wantsError(error)
8+
opensError(error)
109
}
1110

1211
protocol ErrorRefinement : Error {}
1312
func testErrorRefinment(error: ErrorRefinement) {
14-
wantsError(error) // expected-error {{type 'any ErrorRefinement' cannot conform to 'Error'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
13+
opensError(error) // okay
14+
wantsError(error, error) // expected-error {{type 'any ErrorRefinement' cannot conform to 'Error'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
1515
}
1616

1717
protocol OtherProtocol {}
1818
func testErrorComposition(error: Error & OtherProtocol) {
19-
wantsError(error) // expected-error {{type 'any Error & OtherProtocol' cannot conform to 'Error'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
19+
opensError(error) // okay
20+
wantsError(error, error) // expected-error {{type 'any Error & OtherProtocol' cannot conform to 'Error'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
2021
}
2122

2223
class C {}
2324
func testErrorCompositionWithClass(error: Error & C) {
24-
wantsError(error) // expected-error {{type 'any C & Error' cannot conform to 'Error'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
25+
opensError(error) // okay
26+
wantsError(error, error) // expected-error {{type 'any C & Error' cannot conform to 'Error'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
2527
}

test/stdlib/Runtime.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ Runtime.test("abstraction barrier on casting generic param bound to existential"
521521
dynamicWithErasedType,
522522
dynamicExistentialWithErasedType,
523523
dynamicDoubleWrappedExistentialWithErasedType)
524-
= castWithAbstractionBarrier(x)
524+
= castWithAbstractionBarrier(x as SomeProtocol)
525525

526526
expectTrue(staticWithConcreteType == SomeProtocol.self)
527527
expectTrue(dynamicWithConcreteType == SomeProtocol.self)

test/type/subclass_composition.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,6 @@ func dependentMemberTypes<T : BaseIntAndP2>(
315315
func conformsToAnyObject<T : AnyObject>(_: T) {}
316316
// expected-note@-1 {{where 'T' = 'any P1'}}
317317
func conformsToP1<T : P1>(_: T) {}
318-
// expected-note@-1 {{required by global function 'conformsToP1' where 'T' = 'any P1'}}
319318
func conformsToP2<T : P2>(_: T) {}
320319
func conformsToBaseIntAndP2<T : Base<Int> & P2>(_: T) {}
321320
// expected-note@-1 {{where 'T' = 'FakeDerived'}}
@@ -428,8 +427,6 @@ func conformsTo<T1 : P2, T2 : Base<Int> & P2>(
428427
// expected-error@-1 {{global function 'conformsToAnyObject' requires that 'any P1' be a class type}}
429428

430429
conformsToP1(p1)
431-
// expected-error@-1 {{type 'any P1' cannot conform to 'P1'}}
432-
// expected-note@-2 {{only concrete types such as structs, enums and classes can conform to protocols}}
433430

434431
// FIXME: Following diagnostics are not great because when
435432
// `conformsTo*` methods are re-typechecked, they loose information

test/type/subclass_composition_objc.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ func testSelfConformance(c: ObjCClass, p: ObjCProtocol, cp: ObjCClass & ObjCProt
5050
func takesStaticObjCProtocol<T : StaticObjCProtocol>(_: T) {}
5151

5252
func testSelfConformance(cp: ObjCClass & StaticObjCProtocol) {
53-
takesStaticObjCProtocol(cp)
54-
// expected-error@-1 {{'any ObjCClass & StaticObjCProtocol' cannot be used as a type conforming to protocol 'StaticObjCProtocol' because 'StaticObjCProtocol' has static requirements}}
53+
takesStaticObjCProtocol(cp) // okay because the type is opened
5554
}
5655

5756
func testMetatypeSelfConformance(m1: (ObjCClass & ObjCProtocol).Protocol,

validation-test/Reflection/existentials.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ protocol Q {}
518518
protocol Composition : P, Q {}
519519
struct S : Composition {}
520520
func getComposition() -> P & Q { return S() }
521-
reflect(any: getComposition())
521+
reflect(any: getComposition() as P & Q)
522522
// CHECK-64: Mangled name: $s12existentials1P_AA1Qp
523523
// CHECK-64: Demangled name: existentials.P & existentials.Q
524524
// CHECK-32: Mangled name: $s12existentials1P_AA1Qp

0 commit comments

Comments
 (0)