Skip to content

Commit 47b375f

Browse files
authored
Merge pull request #40361 from hborla/enable-structural-opaque-types
[SE-0328] Enable structural opaque result types.
2 parents aebd771 + 122020e commit 47b375f

File tree

7 files changed

+41
-24
lines changed

7 files changed

+41
-24
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,9 +1881,6 @@ WARNING(spi_attribute_on_import_of_public_module,none,
18811881
(DeclName, StringRef))
18821882

18831883
// Opaque return types
1884-
ERROR(structural_opaque_types_are_experimental,none,
1885-
"'opaque' types cannot be nested inside other types; "
1886-
"structural 'opaque' types are an experimental feature", ())
18871884
ERROR(opaque_type_invalid_constraint,none,
18881885
"an 'opaque' type must specify only 'Any', 'AnyObject', protocols, "
18891886
"and/or a base class", ())
@@ -4878,6 +4875,10 @@ ERROR(opaque_type_unsupported_pattern,none,
48784875
ERROR(opaque_type_in_protocol_requirement,none,
48794876
"'some' type cannot be the return type of a protocol requirement; did you mean to add an associated type?",
48804877
())
4878+
ERROR(opaque_type_in_parameter,none,
4879+
"'some' cannot appear in parameter position in result "
4880+
"type %0",
4881+
(Type))
48814882

48824883
// Function differentiability
48834884
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
@@ -310,10 +310,6 @@ namespace swift {
310310
/// `func f() -> <T> T`.
311311
bool EnableExperimentalNamedOpaqueTypes = false;
312312

313-
/// Enable experimental support for structural opaque result types, e.g.
314-
/// `func f() -> (some P)?`.
315-
bool EnableExperimentalStructuralOpaqueTypes = false;
316-
317313
/// Enable experimental flow-sensitive concurrent captures.
318314
bool EnableExperimentalFlowSensitiveConcurrentCaptures = false;
319315

lib/Frontend/CompilerInvocation.cpp

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

441-
Opts.EnableExperimentalStructuralOpaqueTypes |=
442-
Args.hasArg(OPT_enable_experimental_structural_opaque_types);
443-
444441
Opts.EnableExperimentalDistributed |=
445442
Args.hasArg(OPT_enable_experimental_distributed);
446443

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,6 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
115115
auto *dc = originatingDecl->getInnermostDeclContext();
116116
auto &ctx = dc->getASTContext();
117117

118-
// Support for structural opaque result types is hidden behind a compiler flag
119-
// until the proposal gets approved.
120-
if (!ctx.LangOpts.EnableExperimentalStructuralOpaqueTypes &&
121-
!isa<OpaqueReturnTypeRepr>(repr)) {
122-
ctx.Diags.diagnose(repr->getLoc(), diag::structural_opaque_types_are_experimental);
123-
return nullptr;
124-
}
125-
126118
// Protocol requirements can't have opaque return types.
127119
//
128120
// TODO: Maybe one day we could treat this as sugar for an associated type.
@@ -285,6 +277,28 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
285277
/*unboundTyOpener*/ nullptr,
286278
/*placeholderHandler*/ nullptr)
287279
.resolveType(repr);
280+
281+
// Opaque types cannot be used in parameter position.
282+
Type desugared = interfaceType->getDesugaredType();
283+
bool hasError = desugared.findIf([&](Type type) -> bool {
284+
if (auto *fnType = type->getAs<FunctionType>()) {
285+
for (auto param : fnType->getParams()) {
286+
if (!param.getPlainType()->hasOpaqueArchetype())
287+
continue;
288+
289+
ctx.Diags.diagnose(repr->getLoc(),
290+
diag::opaque_type_in_parameter,
291+
interfaceType);
292+
return true;
293+
}
294+
}
295+
296+
return false;
297+
});
298+
299+
if (hasError)
300+
return nullptr;
301+
288302
auto metatype = MetatypeType::get(interfaceType);
289303
opaqueDecl->setInterfaceType(metatype);
290304
return opaqueDecl;

test/Constraints/result_builder_opaque_result_structural.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-structural-opaque-types -disable-availability-checking
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking
22

33
@resultBuilder
44
struct TupleBuilder {

test/type/opaque.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,8 @@ struct Test {
7676
let zingle = {() -> some P in 1 } // expected-error{{'some' types are only implemented}}
7777

7878

79-
// Support for structural opaque result types is hidden behind a compiler flag
80-
// until the proposal gets approved.
81-
func twoOpaqueTypes() -> (some P, some P) { return (1, 2) } // expected-error{{'opaque' types cannot be nested inside other types}}
82-
func asArrayElem() -> (some P)! { return [1] } // expected-error{{'opaque' types cannot be nested inside other types}}
79+
func twoOpaqueTypes() -> (some P, some P) { return (1, 2) } // expected-error{{'(some P, some P)' contains multiple 'opaque' types, but only one 'opaque' type is supported}}
80+
func asArrayElem() -> [some P] { return [1] }
8381

8482
// Invalid positions
8583

test/type/opaque_return_structural.swift

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

33
// Tests for experimental extensions to opaque return type support.
44

@@ -85,3 +85,14 @@ func structuralMemberLookupBad() {
8585
tup.0.paul();
8686
tup.0.d(); // expected-error{{value of type 'some P' has no member 'd'}}
8787
}
88+
89+
// expected-error@+1 {{'some' cannot appear in parameter position in result type '(some P) -> Void'}}
90+
func opaqueParameter() -> (some P) -> Void {}
91+
92+
// expected-error@+1 {{'some' cannot appear in parameter position in result type '((some P) -> Void) -> Void'}}
93+
func opaqueParameter() -> ((some P) -> Void) -> Void {}
94+
95+
typealias Takes<T> = (T) -> Void
96+
97+
// expected-error@+1 {{'some' cannot appear in parameter position in result type 'Takes<some P>' (aka '(some P) -> ()')}}
98+
func indirectOpaqueParameter() -> Takes<some P> {}

0 commit comments

Comments
 (0)