Skip to content

[5.7] Enable SE-0353 By Default #59076

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

Merged
merged 4 commits into from
May 26, 2022
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,42 @@ _**Note:** This is in reverse chronological order, so newer entries are added to

## Swift 5.7

* [SE-0353][]:

Protocols with primary associated types can now be used in existential types,
enabling same-type constraints on those associated types.

```
let strings: any Collection<String> = [ "Hello" ]
```

Note that language features requiring runtime support like dynamic casts
(`is`, `as?`, `as!`), as well as generic usages of parameterized existentials
in generic types (e.g. `Array<any Collection<Int>>`) involve additional
availability checks to use. Back-deploying usages in generic position can be
worked around with a generic type-erasing wrapper struct, which is now much
simpler to implement:

```swift
struct AnyCollection<T> {
var wrapped: any Collection<T>
}

let arrayOfCollections: [AnyCollection<T>] = [ /**/ ]
```

* [SE-0329][]:
New types representing time and clocks were introduced. This includes a protocol `Clock` defining clocks which allow for defining a concept of now and a way to wake up after a given instant. Additionally a new protocol `InstantProtocol` for defining instants in time was added. Furthermore a new protocol `DurationProtocol` was added to define an elapsed duration between two given `InstantProtocol` types. Most commonly the `Clock` types for general use are the `SuspendingClock` and `ContinuousClock` which represent the most fundamental clocks for the system. The `SuspendingClock` type does not progress while the machine is suspended whereas the `ContinuousClock` progresses no matter the state of the machine.

* [SE-0309][]:

Protocols with associated types and `Self` requirements can now be used as the
types of values with the `any` keyword.

Protocol methods that return associated types can be called on an `any` type;
the result is type-erased to the associated type's upper bound, which is another
`any` type having the same constraints as the associated type. For example:

```swift
func delayedHello() async throws {
try await Task.sleep(until: .now + .milliseconds(123), clock: .continuous)
Expand Down
4 changes: 0 additions & 4 deletions include/swift/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,10 +338,6 @@ namespace swift {
/// in calls to generic functions.
bool EnableOpenedExistentialTypes = false;

/// Enable support for parameterized protocol types in existential
/// position.
bool EnableParameterizedExistentialTypes = false;

/// Enable experimental flow-sensitive concurrent captures.
bool EnableExperimentalFlowSensitiveConcurrentCaptures = false;

Expand Down
4 changes: 0 additions & 4 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -543,10 +543,6 @@ def enable_explicit_existential_types :
Flag<["-"], "enable-explicit-existential-types">,
HelpText<"Enable experimental support for explicit existential types">;

def enable_parameterized_existential_types :
Flag<["-"], "enable-parameterized-existential-types">,
HelpText<"Enable experimental support for parameterized existential types">;

def enable_experimental_opened_existential_types :
Flag<["-"], "enable-experimental-opened-existential-types">,
HelpText<"Enable experimental support for implicitly opened existentials">;
Expand Down
3 changes: 0 additions & 3 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,9 +448,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.EnableExperimentalNamedOpaqueTypes |=
Args.hasArg(OPT_enable_experimental_named_opaque_types);

Opts.EnableParameterizedExistentialTypes |=
Args.hasArg(OPT_enable_parameterized_existential_types);

Opts.EnableOpenedExistentialTypes =
Args.hasFlag(OPT_enable_experimental_opened_existential_types,
OPT_disable_experimental_opened_existential_types,
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/TypeCheckType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
// Build ParameterizedProtocolType if the protocol has a primary associated
// type and we're in a supported context (for now just generic requirements,
// inheritance clause, extension binding).
if (!resolution.getOptions().isParameterizedProtocolSupported(ctx.LangOpts)) {
if (!resolution.getOptions().isParameterizedProtocolSupported()) {
diags.diagnose(loc, diag::parameterized_protocol_not_supported);
return ErrorType::get(ctx);
}
Expand Down
8 changes: 2 additions & 6 deletions lib/Sema/TypeCheckType.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,18 +284,14 @@ class TypeResolutionOptions {
}

/// Whether parameterized protocol types are supported in this context.
///
/// FIXME: Remove LangOptions parameter once EnableParameterizedExistentialTypes
/// staging flag is gone.
bool isParameterizedProtocolSupported(const LangOptions &opts) const {
bool isParameterizedProtocolSupported() const {
switch (context) {
case Context::Inherited:
case Context::ExtensionBinding:
case Context::GenericRequirement:
return true;
case Context::ExistentialConstraint:
case Context::MetatypeBase:
return opts.EnableParameterizedExistentialTypes;
return true;
case Context::None:
case Context::TypeAliasDecl:
case Context::GenericTypeAliasDecl:
Expand Down
30 changes: 30 additions & 0 deletions test/Constraints/existential_metatypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,33 @@ func testP3(_ p: P3, something: Something) {
func testIUOToAny(_ t: AnyObject.Type!) {
let _: Any = t
}

protocol P4<T> {
associatedtype T
}

protocol Q4<T> {
associatedtype T
}

protocol PP4<U>: P4<Self.U.T> {
associatedtype U: P4<U>
}

func parameterizedExistentials() {
var qp: (any Q4<Int>).Type
var pp: (any P4<Int>).Type = qp // expected-error{{cannot convert value of type '(any Q4<Int>).Type' to specified type '(any P4<Int>).Type'}}

var qt: any Q4<Int>.Type
qt = qp // expected-error{{cannot assign value of type '(any Q4<Int>).Type' to type 'any Q4<Int>.Type'}}
qp = qt // expected-error{{cannot assign value of type 'any Q4<Int>.Type' to type '(any Q4<Int>).Type'}}
var pt: any P4<Int>.Type = qt // expected-error{{cannot convert value of type 'any Q4<Int>.Type' to specified type 'any P4<Int>.Type'}}
pt = pp // expected-error{{cannot assign value of type '(any P4<Int>).Type' to type 'any P4<Int>.Type'}}
pp = pt // expected-error{{cannot assign value of type 'any P4<Int>.Type' to type '(any P4<Int>).Type'}}

var ppp: (any PP4<Int>).Type
pp = ppp // expected-error{{cannot assign value of type '(any PP4<Int>).Type' to type '(any P4<Int>).Type'}}

var ppt: any PP4<Int>.Type
pt = ppt
}
31 changes: 0 additions & 31 deletions test/Constraints/parameterized_existential_metatypes.swift

This file was deleted.

2 changes: 1 addition & 1 deletion test/IRGen/existential_shape_metadata.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -emit-ir %s -swift-version 5 -disable-availability-checking -enable-parameterized-existential-types | %IRGenFileCheck %s
// RUN: %target-swift-frontend -emit-ir %s -swift-version 5 -disable-availability-checking | %IRGenFileCheck %s

// CHECK-LABEL: @"$sl26existential_shape_metadata2Q0_pyxXPXGMq" = linkonce_odr hidden constant
// CHECK-SAME: { i32 {{.*}}sub ([[INT]] ptrtoint (i8** @{{[0-9]+}} to [[INT]])
Expand Down
2 changes: 1 addition & 1 deletion test/Interpreter/parameterized_existentials.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-run-simple-swift(-Xfrontend -enable-parameterized-existential-types -Xfrontend -disable-availability-checking)
// RUN: %target-run-simple-swift(-Xfrontend -disable-availability-checking)
// REQUIRES: executable_test

import StdlibUnittest
Expand Down
2 changes: 1 addition & 1 deletion test/RemoteAST/parameterized_existentials.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-remoteast-test -enable-parameterized-existential-types -disable-availability-checking %s | %FileCheck %s
// RUN: %target-swift-remoteast-test -disable-availability-checking %s | %FileCheck %s

// REQUIRES: swift-remoteast-test

Expand Down
2 changes: 1 addition & 1 deletion test/SILGen/parameterized_existentials.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-emit-silgen -module-name parameterized -enable-parameterized-existential-types -disable-availability-checking %s | %FileCheck %s
// RUN: %target-swift-emit-silgen -module-name parameterized -disable-availability-checking %s | %FileCheck %s

protocol P<T, U, V> {
associatedtype T
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend %s -emit-sil -enable-parameterized-existential-types -disable-availability-checking -O -o - | %FileCheck %s
// RUN: %target-swift-frontend %s -emit-sil -disable-availability-checking -O -o - | %FileCheck %s

public protocol P<T> {
associatedtype T
Expand Down
6 changes: 3 additions & 3 deletions test/Sema/availability_parameterized_existential.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx10.50 -disable-objc-attr-requires-foundation-module -enable-parameterized-existential-types
// RUN: not %target-swift-frontend -target %target-cpu-apple-macosx10.50 -disable-objc-attr-requires-foundation-module -enable-parameterized-existential-types -typecheck %s 2>&1 | %FileCheck %s '--implicit-check-not=<unknown>:0'
// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx10.50 -disable-objc-attr-requires-foundation-module
// RUN: not %target-swift-frontend -target %target-cpu-apple-macosx10.50 -disable-objc-attr-requires-foundation-module -typecheck %s 2>&1 | %FileCheck %s '--implicit-check-not=<unknown>:0'

// Make sure we do not emit availability errors or warnings when -disable-availability-checking is passed
// RUN: not %target-swift-frontend -target %target-cpu-apple-macosx10.50 -typecheck -disable-objc-attr-requires-foundation-module -enable-parameterized-existential-types -disable-availability-checking %s 2>&1 | %FileCheck %s '--implicit-check-not=error:'
// RUN: not %target-swift-frontend -target %target-cpu-apple-macosx10.50 -typecheck -disable-objc-attr-requires-foundation-module -disable-availability-checking %s 2>&1 | %FileCheck %s '--implicit-check-not=error:'

// REQUIRES: OS=macosx

Expand Down
4 changes: 2 additions & 2 deletions test/Serialization/parameterized_protocol.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -enable-parameterized-existential-types -emit-module %S/Inputs/parameterized_protocol_other.swift -emit-module-path %t/parameterized_protocol_other.swiftmodule
// RUN: %target-typecheck-verify-swift -enable-parameterized-existential-types -I%t
// RUN: %target-swift-frontend -emit-module %S/Inputs/parameterized_protocol_other.swift -emit-module-path %t/parameterized_protocol_other.swiftmodule
// RUN: %target-typecheck-verify-swift -I%t

import parameterized_protocol_other

Expand Down
2 changes: 1 addition & 1 deletion test/type/opaque_parameterized_existential.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -enable-parameterized-existential-types -disable-availability-checking -typecheck -verify %s
// RUN: %target-swift-frontend -disable-availability-checking -typecheck -verify %s

// I do not like nested some type params,
// I do not like them Σam-i-am
Expand Down
2 changes: 1 addition & 1 deletion test/type/parameterized_existential.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on -disable-availability-checking -enable-parameterized-existential-types
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on -disable-availability-checking

protocol Sequence<Element> {
associatedtype Element
Expand Down
8 changes: 4 additions & 4 deletions test/type/parameterized_protocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ protocol Invalid5<Element, Element> {

/// Test semantics

protocol Sequence<Element> {
protocol Sequence<Element> { // expected-note {{'Sequence' declared here}}
associatedtype Element
// expected-note@-1 {{protocol requires nested type 'Element'; do you want to add it?}}
}
Expand Down Expand Up @@ -189,17 +189,17 @@ func returnsSequenceOfInt1() -> Sequence<Int> {}
// expected-error@-1 {{protocol type with type arguments can only be used as a generic constraint}}

func takesSequenceOfInt2(_: any Sequence<Int>) {}
// expected-error@-1 {{protocol type with type arguments can only be used as a generic constraint}}

func returnsSequenceOfInt2() -> any Sequence<Int> {}
// expected-error@-1 {{protocol type with type arguments can only be used as a generic constraint}}

func typeExpr() {
_ = Sequence<Int>.self
// expected-error@-1 {{protocol type with type arguments can only be used as a generic constraint}}

_ = any Sequence<Int>.self
// expected-error@-1 {{protocol type with type arguments can only be used as a generic constraint}}
// expected-error@-1 {{'self' is not a member type of protocol 'parameterized_protocol.Sequence<Swift.Int>'}}

_ = (any Sequence<Int>).self
}

/// Not supported as a protocol composition term for now
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: not %target-swift-frontend -disable-availability-checking -emit-ir -enable-parameterized-existential-types %s
// RUN: not %target-swift-frontend -disable-availability-checking -emit-ir %s

protocol P<X, Y> {
associatedtype X : P
Expand Down