Skip to content

Commit 006db7f

Browse files
authored
Merge pull request #42249 from slavapestov/se-0346-cherry-pick-5.7
Cherry-pick latest SE-0346 changes to 5.7 branch
2 parents bcc8add + c9c3956 commit 006db7f

21 files changed

+160
-144
lines changed

include/swift/AST/ASTPrinter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ StringRef getAccessorKindString(AccessorKind value);
389389
/// for the compiler features that it uses. Note that printBody
390390
/// may be called multiple times if the declaration uses suppressible
391391
/// features.
392-
bool printWithCompatibilityFeatureChecks(ASTPrinter &printer,
392+
void printWithCompatibilityFeatureChecks(ASTPrinter &printer,
393393
PrintOptions &options,
394394
Decl *decl,
395395
llvm::function_ref<void()> printBody);

include/swift/AST/DiagnosticsParse.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -378,9 +378,6 @@ ERROR(expected_rbrace_actor,none,
378378
"expected '}' in actor", ())
379379

380380
// Protocol
381-
ERROR(generic_arguments_protocol,PointsToFirstBadToken,
382-
"protocols do not allow generic parameters; use associated types instead",
383-
())
384381
ERROR(expected_lbrace_protocol,PointsToFirstBadToken,
385382
"expected '{' in protocol type", ())
386383
ERROR(expected_rbrace_protocol,none,

include/swift/Basic/Features.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ LANGUAGE_FEATURE(BuiltinStackAlloc, 0, "Builtin.stackAlloc", true)
7474
SUPPRESSIBLE_LANGUAGE_FEATURE(SpecializeAttributeWithAvailability, 0, "@_specialize attribute with availability", true)
7575
LANGUAGE_FEATURE(BuiltinAssumeAlignment, 0, "Builtin.assumeAlignment", true)
7676
SUPPRESSIBLE_LANGUAGE_FEATURE(UnsafeInheritExecutor, 0, "@_unsafeInheritExecutor", true)
77-
SUPPRESSIBLE_LANGUAGE_FEATURE(PrimaryAssociatedTypes, 0, "Primary associated types", true)
77+
SUPPRESSIBLE_LANGUAGE_FEATURE(PrimaryAssociatedTypes, 346, "Primary associated types", true)
7878
SUPPRESSIBLE_LANGUAGE_FEATURE(UnavailableFromAsync, 0, "@_unavailableFromAsync", true)
7979
SUPPRESSIBLE_LANGUAGE_FEATURE(NoAsyncAvailability, 340, "@available(*, noasync)", true)
8080

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -330,9 +330,9 @@ namespace swift {
330330
/// in calls to generic functions.
331331
bool EnableOpenedExistentialTypes = false;
332332

333-
/// Enable support for protocol types parameterized by primary
334-
/// associated type.
335-
bool EnableParameterizedProtocolTypes = false;
333+
/// Enable support for parameterized protocol types in existential
334+
/// position.
335+
bool EnableParameterizedExistentialTypes = false;
336336

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

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -536,9 +536,9 @@ def enable_explicit_existential_types :
536536
Flag<["-"], "enable-explicit-existential-types">,
537537
HelpText<"Enable experimental support for explicit existential types">;
538538

539-
def enable_parameterized_protocol_types :
540-
Flag<["-"], "enable-parameterized-protocol-types">,
541-
HelpText<"Enable experimental support for primary associated types and parameterized protocols">;
539+
def enable_parameterized_existential_types :
540+
Flag<["-"], "enable-parameterized-existential-types">,
541+
HelpText<"Enable experimental support for parameterized existential types">;
542542

543543
def enable_experimental_opened_existential_types :
544544
Flag<["-"], "enable-experimental-opened-existential-types">,

lib/AST/ASTPrinter.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2588,12 +2588,12 @@ void PrintAST::printSynthesizedExtensionImpl(Type ExtendedType,
25882588
// protocol Foo {}
25892589
// extension Foo where <requirments from ExtDecl> { ... }
25902590
// struct Bar {}
2591-
// extension Bar: Foo where <requirments from TransformContext> { ... }
2591+
// extension Bar: Foo where <requirements from TransformContext> { ... }
25922592
//
25932593
// should produce a synthesized extension of Bar with both sets of
2594-
// requirments:
2594+
// requirements:
25952595
//
2596-
// extension Bar where <requirments from ExtDecl+TransformContext { ... }
2596+
// extension Bar where <requirements from ExtDecl+TransformContext> { ... }
25972597
//
25982598
if (!printCombinedRequirementsIfNeeded())
25992599
printDeclGenericRequirements(ExtDecl);
@@ -3208,21 +3208,21 @@ static void printWithSuppressibleFeatureChecks(ASTPrinter &printer,
32083208
/// #endif
32093209
/// #endif
32103210
/// ```
3211-
bool swift::printWithCompatibilityFeatureChecks(ASTPrinter &printer,
3211+
void swift::printWithCompatibilityFeatureChecks(ASTPrinter &printer,
32123212
PrintOptions &options,
32133213
Decl *decl,
32143214
llvm::function_ref<void()> printBody) {
32153215
// A single accessor does not get a feature check,
32163216
// it should go around the whole decl.
32173217
if (isa<AccessorDecl>(decl)) {
32183218
printBody();
3219-
return false;
3219+
return;
32203220
}
32213221

32223222
FeatureSet features = getUniqueFeaturesUsed(decl);
32233223
if (features.empty()) {
32243224
printBody();
3225-
return false;
3225+
return;
32263226
}
32273227

32283228
// Enter a `#if` for the required features, if any.
@@ -3252,8 +3252,6 @@ bool swift::printWithCompatibilityFeatureChecks(ASTPrinter &printer,
32523252
printer.printNewline();
32533253
printer << "#endif";
32543254
}
3255-
3256-
return true;
32573255
}
32583256

32593257
void PrintAST::visitExtensionDecl(ExtensionDecl *decl) {

lib/Frontend/CompilerInvocation.cpp

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

451-
Opts.EnableParameterizedProtocolTypes |=
452-
Args.hasArg(OPT_enable_parameterized_protocol_types);
451+
Opts.EnableParameterizedExistentialTypes |=
452+
Args.hasArg(OPT_enable_parameterized_existential_types);
453453

454454
Opts.EnableOpenedExistentialTypes =
455455
Args.hasFlag(OPT_enable_experimental_opened_existential_types,

lib/Frontend/ModuleInterfaceSupport.cpp

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -650,17 +650,8 @@ class InheritedProtocolCollector {
650650
printer << " {}";
651651
};
652652

653-
bool printedNewline = false;
654-
if (printOptions.PrintCompatibilityFeatureChecks) {
655-
printedNewline =
656-
printWithCompatibilityFeatureChecks(printer, curPrintOptions,
657-
proto, printBody);
658-
} else {
659-
printBody();
660-
printedNewline = false;
661-
}
662-
if (!printedNewline)
663-
printer << "\n";
653+
printBody();
654+
printer << "\n";
664655
}
665656
}
666657

lib/Parse/ParseDecl.cpp

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8062,19 +8062,8 @@ parseDeclProtocol(ParseDeclOptions Flags, DeclAttributes &Attributes) {
80628062
return Status;
80638063

80648064
SmallVector<PrimaryAssociatedTypeName, 2> PrimaryAssociatedTypeNames;
8065-
8066-
if (Context.LangOpts.EnableParameterizedProtocolTypes) {
8067-
if (startsWithLess(Tok)) {
8068-
Status |= parsePrimaryAssociatedTypes(PrimaryAssociatedTypeNames);
8069-
}
8070-
} else {
8071-
// Protocols don't support generic parameters, but people often want them and
8072-
// we want to have good error recovery if they try them out. Parse them and
8073-
// produce a specific diagnostic if present.
8074-
if (startsWithLess(Tok)) {
8075-
diagnose(Tok, diag::generic_arguments_protocol);
8076-
maybeParseGenericParams();
8077-
}
8065+
if (startsWithLess(Tok)) {
8066+
Status |= parsePrimaryAssociatedTypes(PrimaryAssociatedTypeNames);
80788067
}
80798068

80808069
DebuggerContextChange DCC (*this);

lib/Sema/TypeCheckType.cpp

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -628,50 +628,48 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
628628
auto &ctx = dc->getASTContext();
629629
auto &diags = ctx.Diags;
630630

631-
if (ctx.LangOpts.EnableParameterizedProtocolTypes) {
632-
if (auto *protoType = type->getAs<ProtocolType>()) {
633-
// Build ParameterizedProtocolType if the protocol has a primary associated
634-
// type and we're in a supported context (for now just generic requirements,
635-
// inheritance clause, extension binding).
636-
if (!resolution.getOptions().isParameterizedProtocolSupported()) {
637-
diags.diagnose(loc, diag::parameterized_protocol_not_supported);
638-
return ErrorType::get(ctx);
639-
}
631+
if (auto *protoType = type->getAs<ProtocolType>()) {
632+
// Build ParameterizedProtocolType if the protocol has a primary associated
633+
// type and we're in a supported context (for now just generic requirements,
634+
// inheritance clause, extension binding).
635+
if (!resolution.getOptions().isParameterizedProtocolSupported(ctx.LangOpts)) {
636+
diags.diagnose(loc, diag::parameterized_protocol_not_supported);
637+
return ErrorType::get(ctx);
638+
}
640639

641-
auto *protoDecl = protoType->getDecl();
642-
auto assocTypes = protoDecl->getPrimaryAssociatedTypes();
643-
if (assocTypes.empty()) {
644-
diags.diagnose(loc, diag::protocol_does_not_have_primary_assoc_type,
645-
protoType);
640+
auto *protoDecl = protoType->getDecl();
641+
auto assocTypes = protoDecl->getPrimaryAssociatedTypes();
642+
if (assocTypes.empty()) {
643+
diags.diagnose(loc, diag::protocol_does_not_have_primary_assoc_type,
644+
protoType);
646645

647-
return ErrorType::get(ctx);
648-
}
649-
650-
auto genericArgs = generic->getGenericArgs();
646+
return ErrorType::get(ctx);
647+
}
651648

652-
if (genericArgs.size() != assocTypes.size()) {
653-
diags.diagnose(loc,
654-
diag::parameterized_protocol_type_argument_count_mismatch,
655-
protoType, genericArgs.size(), assocTypes.size(),
656-
(genericArgs.size() < assocTypes.size()) ? 1 : 0);
649+
auto genericArgs = generic->getGenericArgs();
657650

658-
return ErrorType::get(ctx);
659-
}
651+
if (genericArgs.size() != assocTypes.size()) {
652+
diags.diagnose(loc,
653+
diag::parameterized_protocol_type_argument_count_mismatch,
654+
protoType, genericArgs.size(), assocTypes.size(),
655+
(genericArgs.size() < assocTypes.size()) ? 1 : 0);
660656

661-
auto genericResolution =
662-
resolution.withOptions(adjustOptionsForGenericArgs(options));
657+
return ErrorType::get(ctx);
658+
}
663659

664-
SmallVector<Type, 2> argTys;
665-
for (auto *genericArg : genericArgs) {
666-
Type argTy = genericResolution.resolveType(genericArg, silParams);
667-
if (!argTy || argTy->hasError())
668-
return ErrorType::get(ctx);
660+
auto genericResolution =
661+
resolution.withOptions(adjustOptionsForGenericArgs(options));
669662

670-
argTys.push_back(argTy);
671-
}
663+
SmallVector<Type, 2> argTys;
664+
for (auto *genericArg : genericArgs) {
665+
Type argTy = genericResolution.resolveType(genericArg, silParams);
666+
if (!argTy || argTy->hasError())
667+
return ErrorType::get(ctx);
672668

673-
return ParameterizedProtocolType::get(ctx, protoType, argTys);
669+
argTys.push_back(argTy);
674670
}
671+
672+
return ParameterizedProtocolType::get(ctx, protoType, argTys);
675673
}
676674

677675
// We must either have an unbound generic type, or a generic type alias.

lib/Sema/TypeCheckType.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "swift/AST/Type.h"
2020
#include "swift/AST/Types.h"
2121
#include "swift/AST/TypeResolutionStage.h"
22+
#include "swift/Basic/LangOptions.h"
2223
#include "llvm/ADT/None.h"
2324

2425
namespace swift {
@@ -277,13 +278,17 @@ class TypeResolutionOptions {
277278
}
278279

279280
/// Whether parameterized protocol types are supported in this context.
280-
bool isParameterizedProtocolSupported() const {
281+
///
282+
/// FIXME: Remove LangOptions parameter once EnableParameterizedExistentialTypes
283+
/// staging flag is gone.
284+
bool isParameterizedProtocolSupported(const LangOptions &opts) const {
281285
switch (context) {
282286
case Context::Inherited:
283287
case Context::ExtensionBinding:
284288
case Context::GenericRequirement:
285-
case Context::ExistentialConstraint:
286289
return true;
290+
case Context::ExistentialConstraint:
291+
return opts.EnableParameterizedExistentialTypes;
287292
case Context::None:
288293
case Context::TypeAliasDecl:
289294
case Context::GenericTypeAliasDecl:

test/Constraints/opened_existentials.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-experimental-opened-existential-types -enable-parameterized-protocol-types
1+
// RUN: %target-typecheck-verify-swift -enable-experimental-opened-existential-types
22

33
protocol Q { }
44

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -typecheck -module-name ParameterizedProtocols -emit-module-interface-path %t/ParameterizedProtocols.swiftinterface %s
3+
// RUN: %FileCheck %s < %t/ParameterizedProtocols.swiftinterface
4+
5+
public struct S1 : P1 {
6+
public typealias T = Int
7+
}
8+
9+
public struct S2 : Q1 {}
10+
11+
protocol P1 : P2 {}
12+
13+
public protocol P2<T> {
14+
associatedtype T
15+
}
16+
17+
protocol Q1 : Q2 {}
18+
19+
public protocol Q2 {}
20+
21+
// CHECK: extension ParameterizedProtocols.S1 : ParameterizedProtocols.P2 {}
22+
// CHECK-NEXT: extension ParameterizedProtocols.S2 : ParameterizedProtocols.Q2 {}

test/ModuleInterface/parameterized-protocols.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-swift-frontend -typecheck -module-name ParameterizedProtocols -emit-module-interface-path %t/ParameterizedProtocols.swiftinterface -enable-parameterized-protocol-types %s
2+
// RUN: %target-swift-frontend -typecheck -module-name ParameterizedProtocols -emit-module-interface-path %t/ParameterizedProtocols.swiftinterface %s
33
// RUN: %FileCheck %s < %t/ParameterizedProtocols.swiftinterface
44

55
public protocol HasPrimaryAssociatedTypes<T, U> {

test/Parse/invalid.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func d(_ b: String -> <T>() -> T) {} // expected-error {{expected type for funct
6767

6868

6969
// <rdar://problem/22143680> QoI: terrible diagnostic when trying to form a generic protocol
70-
protocol Animal<Food> { // expected-error {{protocols do not allow generic parameters; use associated types instead}}
70+
protocol Animal<Food> { // expected-error {{an associated type named 'Food' must be declared in the protocol 'Animal' or a protocol it inherits}}
7171
func feed(_ food: Food) // expected-error {{cannot find type 'Food' in scope}}
7272
}
7373

test/SILGen/existential_parameters.swift renamed to test/SILGen/parameterized_existentials.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-emit-silgen -module-name parameterized -enable-parameterized-protocol-types %s | %FileCheck %s
1+
// RUN: %target-swift-emit-silgen -module-name parameterized -enable-parameterized-existential-types %s | %FileCheck %s
22

33
protocol P<T, U, V> {
44
associatedtype T

test/SILOptimizer/cast_folding_parameterized_protocol.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend %s -emit-sil -enable-parameterized-protocol-types -O -o - | %FileCheck %s
1+
// RUN: %target-swift-frontend %s -emit-sil -enable-parameterized-existential-types -O -o - | %FileCheck %s
22

33
public protocol P<T> {
44
associatedtype T

test/type/opaque_parameters.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-parameterized-protocol-types -disable-availability-checking -requirement-machine-inferred-signatures=on
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking -requirement-machine-inferred-signatures=on
22

33
protocol P { }
44

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on -disable-availability-checking -enable-parameterized-existential-types
2+
3+
protocol Sequence<Element> {
4+
associatedtype Element
5+
}
6+
7+
struct ConcreteSequence<Element> : Sequence {}
8+
9+
extension Sequence {
10+
func map<Other>(_ transform: (Self.Element) -> Other) -> ConcreteSequence<Other> {
11+
return ConcreteSequence<Other>()
12+
}
13+
}
14+
15+
protocol DoubleWide<X, Y> {
16+
associatedtype X
17+
associatedtype Y
18+
19+
var x: X { get }
20+
var y: Y { get }
21+
}
22+
23+
extension Int: DoubleWide {
24+
typealias X = Int
25+
typealias Y = Int
26+
27+
var x: X { 0 }
28+
var y: X { 0 }
29+
}
30+
31+
struct Collapse<T: DoubleWide>: DoubleWide {
32+
typealias X = T
33+
typealias Y = T
34+
35+
var x: X
36+
var y: X { self.x }
37+
}
38+
39+
func test() -> any DoubleWide<some DoubleWide<Int, Int>, some DoubleWide<Int, Int>> { return Collapse<Int>(x: 42) }
40+
41+
func diagonalizeAny(_ x: any Sequence<Int>) -> any Sequence<(Int, Int)> {
42+
return x.map { ($0, $0) }
43+
}
44+
45+
func erase<T>(_ x: ConcreteSequence<T>) -> any Sequence<T> {
46+
return x as any Sequence<T>
47+
}
48+
49+
protocol Sponge<A, B> {
50+
associatedtype A
51+
associatedtype B
52+
}
53+
54+
func saturation(_ dry: any Sponge, _ wet: any Sponge<Int, Int>) {
55+
_ = dry as any Sponge<Int, Int>
56+
// expected-error@-1 {{'any Sponge' is not convertible to 'any Sponge<Int, Int>'}}
57+
// expected-note@-2 {{did you mean to use 'as!' to force downcast?}}
58+
_ = dry as any Sponge
59+
60+
_ = wet as any Sponge<Int, Int> // Ok
61+
_ = wet as any Sponge // Ok
62+
_ = wet as any Sponge<String, String> // expected-error {{'any Sponge<Int, Int>' is not convertible to 'any Sponge<String, String>'}}
63+
// expected-note@-1 {{did you mean to use 'as!' to force downcast?}}
64+
}

0 commit comments

Comments
 (0)