Skip to content

Commit 211ee70

Browse files
authored
Merge pull request #41444 from DougGregor/se-0341-default
Enable SE-0341 "Opaque Parameter Declarations" by default.
2 parents 781a90c + 27056a0 commit 211ee70

File tree

10 files changed

+87
-26
lines changed

10 files changed

+87
-26
lines changed

CHANGELOG.md

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

66
## Swift 5.7
77

8+
* [SE-0341][]:
9+
10+
Opaque types can now be used in the parameters of functions and subscripts, wher they provide a shorthand syntax for the introduction of a generic parameter. For example, the following:
11+
12+
```swift
13+
func horizontal(_ v1: some View, _ v2: some View) -> some View {
14+
HStack {
15+
v1
16+
v2
17+
}
18+
}
19+
```
20+
21+
is equivalent to
22+
23+
```swift
24+
func horizontal<V1: View, V2: View>(_ v1: V1, _ v2: V2) -> some View {
25+
HStack {
26+
v1
27+
v2
28+
}
29+
}
30+
```
31+
32+
With this, `some` in a parameter type provides a generalization where the
33+
caller chooses the parameter's type as well as its value, whereas `some` in
34+
the result type provides a generalization where the callee chooses the
35+
resulting type and value.
36+
837
* The compiler now correctly emits warnings for more kinds of expressions where a protocol conformance is used and may be unavailable at runtime. Previously, member reference expressions and type erasing expressions that used potentially unavailable conformances were not diagnosed, leading to potential crashes at runtime.
938

1039
```swift
@@ -8962,6 +8991,7 @@ Swift 1.0
89628991
[SE-0331]: <https://github.com/apple/swift-evolution/blob/main/proposals/0331-remove-sendable-from-unsafepointer.md>
89638992
[SE-0337]: <https://github.com/apple/swift-evolution/blob/main/proposals/0337-support-incremental-migration-to-concurrency-checking.md>
89648993
[SE-0335]: <https://github.com/apple/swift-evolution/blob/main/proposals/0335-existential-any.md>
8994+
[SE-0341]: <https://github.com/apple/swift-evolution/blob/main/proposals/0341-opaque-parameters.md>
89658995

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

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4988,7 +4988,7 @@ ERROR(unable_to_parse_c_function_type,none,
49884988

49894989
// Opaque types
49904990
ERROR(unsupported_opaque_type,none,
4991-
"'some' types are only implemented for the declared type of properties and subscripts and the return type of functions", ())
4991+
"'some' types are only permitted in properties, subscripts, and functions", ())
49924992

49934993
ERROR(opaque_type_unsupported_pattern,none,
49944994
"'some' type can only be declared on a single property declaration", ())
@@ -4997,9 +4997,9 @@ ERROR(opaque_type_in_protocol_requirement,none,
49974997
"'some' type cannot be the return type of a protocol requirement; did you mean to add an associated type?",
49984998
())
49994999
ERROR(opaque_type_in_parameter,none,
5000-
"'some' cannot appear in parameter position in result "
5001-
"type %0",
5002-
(Type))
5000+
"'some' cannot appear in parameter position in %select{result|parameter}0"
5001+
" type %1",
5002+
(bool, Type))
50035003

50045004
// Function differentiability
50055005
ERROR(attr_only_on_parameters_of_differentiable,none,

include/swift/Basic/LangOptions.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -313,10 +313,6 @@ namespace swift {
313313
/// `func f() -> <T> T`.
314314
bool EnableExperimentalNamedOpaqueTypes = false;
315315

316-
/// Enable experimental support for opaque parameter types, e.g.
317-
/// `func f(collection: some Collection)`.
318-
bool EnableExperimentalOpaqueParameters = false;
319-
320316
/// Enable support for explicit existential types via the \c any
321317
/// keyword.
322318
bool EnableExplicitExistentialTypes = true;

include/swift/Option/FrontendOptions.td

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,6 @@ def enable_experimental_eager_clang_module_diagnostics :
296296
Flag<["-"], "enable-experimental-eager-clang-module-diagnostics">,
297297
HelpText<"Enable experimental eager diagnostics reporting on the importability of all referenced C, C++, and Objective-C libraries">;
298298

299-
def enable_experimental_opaque_parameters :
300-
Flag<["-"], "enable-experimental-opaque-parameters">,
301-
HelpText<"Enable experimental support for opaque parameters">;
302-
303299
def enable_experimental_pairwise_build_block :
304300
Flag<["-"], "enable-experimental-pairwise-build-block">,
305301
HelpText<"Enable experimental pairwise 'buildBlock' for result builders">;

lib/AST/NameLookup.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2507,9 +2507,6 @@ static SmallVector<GenericTypeParamDecl *, 2>
25072507
createOpaqueParameterGenericParams(
25082508
GenericContext *genericContext, GenericParamList *parsedGenericParams) {
25092509
ASTContext &ctx = genericContext->getASTContext();
2510-
if (!ctx.LangOpts.EnableExperimentalOpaqueParameters)
2511-
return { };
2512-
25132510
auto value = dyn_cast_or_null<ValueDecl>(genericContext->getAsDecl());
25142511
if (!value)
25152512
return { };

lib/Frontend/CompilerInvocation.cpp

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

448-
Opts.EnableExperimentalOpaqueParameters |=
449-
Args.hasArg(OPT_enable_experimental_opaque_parameters);
450-
451448
Opts.EnableExplicitExistentialTypes |=
452449
Args.hasArg(OPT_enable_explicit_existential_types);
453450

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3251,6 +3251,44 @@ void TypeChecker::checkParameterList(ParameterList *params,
32513251
}
32523252
}
32533253

3254+
// Opaque types cannot occur in parameter position.
3255+
Type interfaceType = param->getInterfaceType();
3256+
if (interfaceType->hasTypeParameter()) {
3257+
interfaceType.findIf([&](Type type) {
3258+
if (auto fnType = type->getAs<FunctionType>()) {
3259+
for (auto innerParam : fnType->getParams()) {
3260+
auto paramType = innerParam.getPlainType();
3261+
if (!paramType->hasTypeParameter())
3262+
continue;
3263+
3264+
bool hadError = paramType.findIf([&](Type innerType) {
3265+
auto genericParam = innerType->getAs<GenericTypeParamType>();
3266+
if (!genericParam)
3267+
return false;
3268+
3269+
auto genericParamDecl = genericParam->getDecl();
3270+
if (!genericParamDecl)
3271+
return false;
3272+
3273+
if (!genericParamDecl->isOpaqueType())
3274+
return false;
3275+
3276+
param->diagnose(
3277+
diag::opaque_type_in_parameter, true, interfaceType);
3278+
return true;
3279+
});
3280+
3281+
if (hadError)
3282+
return true;
3283+
}
3284+
3285+
return false;
3286+
}
3287+
3288+
return false;
3289+
});
3290+
}
3291+
32543292
if (param->hasAttachedPropertyWrapper())
32553293
(void) param->getPropertyWrapperInitializerInfo();
32563294

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
274274

275275
ctx.Diags.diagnose(repr->getLoc(),
276276
diag::opaque_type_in_parameter,
277-
interfaceType);
277+
false, interfaceType);
278278
return true;
279279
}
280280
}

test/type/opaque.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,23 +73,23 @@ struct Test {
7373
let inferredOpaqueStructural2 = (bar(), bas()) // expected-error{{inferred type}}
7474
}
7575

76-
let zingle = {() -> some P in 1 } // expected-error{{'some' types are only implemented}}
76+
let zingle = {() -> some P in 1 } // expected-error{{'some' types are only permitted}}
7777

7878

7979
func twoOpaqueTypes() -> (some P, some P) { return (1, 2) }
8080
func asArrayElem() -> [some P] { return [1] }
8181

8282
// Invalid positions
8383

84-
typealias Foo = some P // expected-error{{'some' types are only implemented}}
84+
typealias Foo = some P // expected-error{{'some' types are only permitted}}
8585

86-
func blibble(blobble: some P) {} // expected-error{{'some' types are only implemented}}
86+
func blibble(blobble: some P) {}
8787
func blib() -> P & some Q { return 1 } // expected-error{{'some' should appear at the beginning}}
8888
func blab() -> some P? { return 1 } // expected-error{{must specify only}} expected-note{{did you mean to write an optional of an 'opaque' type?}}
89-
func blorb<T: some P>(_: T) { } // expected-error{{'some' types are only implemented}}
90-
func blub<T>() -> T where T == some P { return 1 } // expected-error{{'some' types are only implemented}} expected-error{{cannot convert}}
89+
func blorb<T: some P>(_: T) { } // expected-error{{'some' types are only permitted}}
90+
func blub<T>() -> T where T == some P { return 1 } // expected-error{{'some' types are only permitted}} expected-error{{cannot convert}}
9191

92-
protocol OP: some P {} // expected-error{{'some' types are only implemented}}
92+
protocol OP: some P {} // expected-error{{'some' types are only permitted}}
9393

9494
func foo() -> some P {
9595
let x = (some P).self // expected-error*{{}}

test/type/opaque_parameters.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -enable-experimental-opaque-parameters -enable-parameterized-protocol-types -disable-availability-checking
1+
// RUN: %target-typecheck-verify-swift -enable-parameterized-protocol-types -disable-availability-checking
22

33
protocol P { }
44

@@ -102,3 +102,10 @@ func testPrimaries(
102102
_ = takeMatchedPrimaryCollections(arrayOfInts, setOfInts)
103103
_ = takeMatchedPrimaryCollections(arrayOfInts, setOfStrings) // expected-error{{type of expression is ambiguous without more context}}
104104
}
105+
106+
107+
// Prohibit use of opaque parameters in consuming positions.
108+
typealias FnType<T> = (T) -> Void
109+
110+
func consumingA(fn: (some P) -> Void) { } // expected-error{{'some' cannot appear in parameter position in parameter type '(some P) -> Void'}}
111+
func consumingB(fn: FnType<some P>) { } // expected-error{{'some' cannot appear in parameter position in parameter type '(some P) -> Void'}}

0 commit comments

Comments
 (0)