Skip to content

Commit ee26438

Browse files
authored
Merge branch 'release/5.7' into se-0338-5.7
2 parents ea2f24e + afb1404 commit ee26438

38 files changed

+277
-117
lines changed

CHANGELOG.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,42 @@ _**Note:** This is in reverse chronological order, so newer entries are added to
3838
pool, `Sendable` checking will be performed, so the compiler will emit a
3939
diagnostic in the call to `f` if `c` is not of `Sendable` type.
4040

41+
* [SE-0353][]:
42+
43+
Protocols with primary associated types can now be used in existential types,
44+
enabling same-type constraints on those associated types.
45+
46+
```
47+
let strings: any Collection<String> = [ "Hello" ]
48+
```
49+
50+
Note that language features requiring runtime support like dynamic casts
51+
(`is`, `as?`, `as!`), as well as generic usages of parameterized existentials
52+
in generic types (e.g. `Array<any Collection<Int>>`) involve additional
53+
availability checks to use. Back-deploying usages in generic position can be
54+
worked around with a generic type-erasing wrapper struct, which is now much
55+
simpler to implement:
56+
57+
```swift
58+
struct AnyCollection<T> {
59+
var wrapped: any Collection<T>
60+
}
61+
62+
let arrayOfCollections: [AnyCollection<T>] = [ /**/ ]
63+
```
64+
4165
* [SE-0329][]:
4266
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.
4367

68+
* [SE-0309][]:
69+
70+
Protocols with associated types and `Self` requirements can now be used as the
71+
types of values with the `any` keyword.
72+
73+
Protocol methods that return associated types can be called on an `any` type;
74+
the result is type-erased to the associated type's upper bound, which is another
75+
`any` type having the same constraints as the associated type. For example:
76+
4477
```swift
4578
func delayedHello() async throws {
4679
try await Task.sleep(until: .now + .milliseconds(123), clock: .continuous)

include/swift/Basic/LangOptions.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,6 @@ namespace swift {
338338
/// in calls to generic functions.
339339
bool EnableOpenedExistentialTypes = false;
340340

341-
/// Enable support for parameterized protocol types in existential
342-
/// position.
343-
bool EnableParameterizedExistentialTypes = false;
344-
345341
/// Enable experimental flow-sensitive concurrent captures.
346342
bool EnableExperimentalFlowSensitiveConcurrentCaptures = false;
347343

include/swift/Option/FrontendOptions.td

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -543,10 +543,6 @@ def enable_explicit_existential_types :
543543
Flag<["-"], "enable-explicit-existential-types">,
544544
HelpText<"Enable experimental support for explicit existential types">;
545545

546-
def enable_parameterized_existential_types :
547-
Flag<["-"], "enable-parameterized-existential-types">,
548-
HelpText<"Enable experimental support for parameterized existential types">;
549-
550546
def enable_experimental_opened_existential_types :
551547
Flag<["-"], "enable-experimental-opened-existential-types">,
552548
HelpText<"Enable experimental support for implicitly opened existentials">;

include/swift/Sema/Constraint.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ enum class ConversionRestrictionKind {
264264
ProtocolMetatypeToProtocolClass,
265265
/// Inout-to-pointer conversion.
266266
InoutToPointer,
267+
/// Converting from `inout` to a C pointer has `PointerToCPointer` semantics.
268+
InoutToCPointer,
267269
/// Array-to-pointer conversion.
268270
ArrayToPointer,
269271
/// String-to-pointer conversion.
@@ -303,8 +305,8 @@ enum class ConversionRestrictionKind {
303305
/// via an implicit Double initializer call passing a CGFloat value.
304306
CGFloatToDouble,
305307
/// Implicit conversion between Swift and C pointers:
306-
// - Unsafe[Mutable]RawPointer -> Unsafe[Mutable]Pointer<[U]Int>
307-
// - Unsafe[Mutable]Pointer<Int{8, 16, ...}> <-> Unsafe[Mutable]Pointer<UInt{8, 16, ...}>
308+
/// - Unsafe[Mutable]RawPointer -> Unsafe[Mutable]Pointer<[U]Int>
309+
/// - Unsafe[Mutable]Pointer<Int{8, 16, ...}> <-> Unsafe[Mutable]Pointer<UInt{8, 16, ...}>
308310
PointerToCPointer,
309311
// Convert a pack into a type with an equivalent arity.
310312
// - If the arity of the pack is 1, drops the pack structure <T> => T

lib/Frontend/CompilerInvocation.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
448448
Opts.EnableExperimentalNamedOpaqueTypes |=
449449
Args.hasArg(OPT_enable_experimental_named_opaque_types);
450450

451-
Opts.EnableParameterizedExistentialTypes |=
452-
Args.hasArg(OPT_enable_parameterized_existential_types);
453-
454451
Opts.EnableOpenedExistentialTypes =
455452
Args.hasFlag(OPT_enable_experimental_opened_existential_types,
456453
OPT_disable_experimental_opened_existential_types,

lib/Parse/ParseType.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -881,13 +881,20 @@ Parser::parseTypeSimpleOrComposition(Diag<> MessageID, ParseTypeReason reason) {
881881
Tok.isContextualKeyword("any")) {
882882
auto keyword = Tok.getText();
883883
auto badLoc = consumeToken();
884+
885+
// Suggest moving `some` or `any` in front of the first type unless
886+
// the first type is an opaque or existential type.
887+
if (opaqueLoc.isValid() || anyLoc.isValid()) {
888+
diagnose(badLoc, diag::opaque_mid_composition, keyword)
889+
.fixItRemove(badLoc);
890+
} else {
891+
diagnose(badLoc, diag::opaque_mid_composition, keyword)
892+
.fixItRemove(badLoc)
893+
.fixItInsert(FirstTypeLoc, keyword.str() + " ");
894+
}
884895

885896
const bool isAnyKeyword = keyword.equals("any");
886897

887-
diagnose(badLoc, diag::opaque_mid_composition, keyword)
888-
.fixItRemove(badLoc)
889-
.fixItInsert(FirstTypeLoc, keyword.str() + " ");
890-
891898
if (isAnyKeyword) {
892899
if (anyLoc.isInvalid()) {
893900
anyLoc = badLoc;

lib/Sema/CSApply.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6646,7 +6646,8 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
66466646
return buildCollectionUpcastExpr(expr, toType, /*bridged=*/false, locator);
66476647
}
66486648

6649-
case ConversionRestrictionKind::InoutToPointer: {
6649+
case ConversionRestrictionKind::InoutToPointer:
6650+
case ConversionRestrictionKind::InoutToCPointer: {
66506651
bool isOptional = false;
66516652
Type unwrappedTy = toType;
66526653
if (Type unwrapped = toType->getOptionalObjectType()) {
@@ -6664,7 +6665,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
66646665
result = cs.cacheType(new (ctx) InjectIntoOptionalExpr(result, toType));
66656666
return result;
66666667
}
6667-
6668+
66686669
case ConversionRestrictionKind::ArrayToPointer: {
66696670
bool isOptional = false;
66706671
Type unwrappedTy = toType;

lib/Sema/CSBindings.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1993,10 +1993,16 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const {
19931993
// without any contextual information, so even though `x` would get
19941994
// bound to result type of the chain, underlying type variable wouldn't
19951995
// be resolved, so we need to propagate holes up the conversion chain.
1996+
// Also propagate in code completion mode because in some cases code
1997+
// completion relies on type variable being a potential hole.
19961998
if (TypeVar->getImpl().canBindToHole()) {
1997-
if (auto objectTy = type->getOptionalObjectType()) {
1998-
if (auto *typeVar = objectTy->getAs<TypeVariableType>())
1999-
cs.recordPotentialHole(typeVar);
1999+
if (srcLocator->directlyAt<OptionalEvaluationExpr>() ||
2000+
cs.isForCodeCompletion()) {
2001+
if (auto objectTy = type->getOptionalObjectType()) {
2002+
if (auto *typeVar = objectTy->getAs<TypeVariableType>()) {
2003+
cs.recordPotentialHole(typeVar);
2004+
}
2005+
}
20002006
}
20012007
}
20022008

lib/Sema/CSClosure.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,7 +1394,15 @@ class ClosureConstraintApplication
13941394
}
13951395

13961396
auto caseStmt = cast<CaseStmt>(rawCase.get<Stmt *>());
1397-
visitCaseStmt(caseStmt);
1397+
// Body of the `case` statement can contain a `fallthrough`
1398+
// statement that requires both source and destination
1399+
// `case` preambles to be type-checked, so bodies of `case`
1400+
// statements should be visited after preambles.
1401+
visitCaseStmtPreamble(caseStmt);
1402+
}
1403+
1404+
for (auto *caseStmt : switchStmt->getCases()) {
1405+
visitCaseStmtBody(caseStmt);
13981406

13991407
// Check restrictions on '@unknown'.
14001408
if (caseStmt->hasUnknownAttr()) {
@@ -1421,7 +1429,7 @@ class ClosureConstraintApplication
14211429
return doStmt;
14221430
}
14231431

1424-
ASTNode visitCaseStmt(CaseStmt *caseStmt) {
1432+
void visitCaseStmtPreamble(CaseStmt *caseStmt) {
14251433
// Translate the patterns and guard expressions for each case label item.
14261434
for (auto &caseItem : caseStmt->getMutableCaseLabelItems()) {
14271435
SolutionApplicationTarget caseTarget(&caseItem, closure);
@@ -1437,11 +1445,16 @@ class ClosureConstraintApplication
14371445
solution.getType(prev)->mapTypeOutOfContext());
14381446
expected->setInterfaceType(type);
14391447
}
1448+
}
14401449

1441-
// Translate the body.
1450+
void visitCaseStmtBody(CaseStmt *caseStmt) {
14421451
auto *newBody = visit(caseStmt->getBody()).get<Stmt *>();
14431452
caseStmt->setBody(cast<BraceStmt>(newBody));
1453+
}
14441454

1455+
ASTNode visitCaseStmt(CaseStmt *caseStmt) {
1456+
visitCaseStmtPreamble(caseStmt);
1457+
visitCaseStmtBody(caseStmt);
14451458
return caseStmt;
14461459
}
14471460

lib/Sema/CSDiagnostics.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6897,6 +6897,7 @@ void NonEphemeralConversionFailure::emitSuggestionNotes() const {
68976897
break;
68986898
}
68996899
case ConversionRestrictionKind::InoutToPointer:
6900+
case ConversionRestrictionKind::InoutToCPointer:
69006901
// For an arbitrary inout-to-pointer, we can suggest
69016902
// withUnsafe[Mutable][Bytes/Pointer].
69026903
if (auto alternative = getAlternativeKind())

0 commit comments

Comments
 (0)