Skip to content

Commit 49bc1ed

Browse files
committed
Allow opaque parameters in structural positions
1 parent 66e12e8 commit 49bc1ed

File tree

5 files changed

+62
-42
lines changed

5 files changed

+62
-42
lines changed

include/swift/AST/TypeRepr.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ enum class TypeReprKind : uint8_t {
4747
enum : unsigned { NumTypeReprKindBits =
4848
countBitsUsed(static_cast<unsigned>(TypeReprKind::Last_TypeRepr)) };
4949

50+
class OpaqueReturnTypeRepr;
51+
using CollectedOpaqueReprs = SmallVector<OpaqueReturnTypeRepr *, 2>;
52+
5053
/// Representation of a type as written in source.
5154
class alignas(1 << TypeReprAlignInBits) TypeRepr
5255
: public ASTAllocated<TypeRepr> {
@@ -165,6 +168,10 @@ class alignas(1 << TypeReprAlignInBits) TypeRepr
165168
/// opaque return type reprs.
166169
bool hasOpaque();
167170

171+
/// Walk the type representation recursively, collecting any
172+
/// `OpaqueReturnTypeRepr`s.
173+
CollectedOpaqueReprs collectOpaqueReturnTypeReprs();
174+
168175
//*** Allocation Routines ************************************************/
169176

170177
void print(raw_ostream &OS, const PrintOptions &Opts = PrintOptions()) const;

lib/AST/NameLookup.cpp

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2594,31 +2594,31 @@ createOpaqueParameterGenericParams(
25942594
SmallVector<GenericTypeParamDecl *, 2> implicitGenericParams;
25952595
auto dc = value->getInnermostDeclContext();
25962596
for (auto param : *params) {
2597-
// Don't permit variadic or inout parameters.
2598-
if (param->isVariadic() || param->isInOut())
2597+
// Don't permit variadic parameters.
2598+
if (param->isVariadic())
25992599
continue;
26002600

26012601
auto typeRepr = param->getTypeRepr();
26022602
if (!typeRepr)
26032603
continue;
26042604

2605-
// FIXME: Do we want to allow any structure here? Optionals?
2606-
auto opaqueRepr = dyn_cast<OpaqueReturnTypeRepr>(typeRepr);
2607-
if (!opaqueRepr)
2608-
continue;
2609-
2610-
// Allocate a new generic parameter to represent this opaque type.
2611-
auto gp = GenericTypeParamDecl::create(
2612-
dc, Identifier(), SourceLoc(), /*isTypeSequence=*/false,
2613-
GenericTypeParamDecl::InvalidDepth, index++, /*isOpaqueType=*/true,
2614-
opaqueRepr);
2615-
gp->setImplicit();
2616-
2617-
// Use the underlying constraint as the constraint on the generic parameter.
2618-
InheritedEntry inherited[1] = { { TypeLoc(opaqueRepr->getConstraint()) } };
2619-
gp->setInherited(ctx.AllocateCopy(inherited));
2620-
2621-
implicitGenericParams.push_back(gp);
2605+
auto opaqueTypeReprs = typeRepr->collectOpaqueReturnTypeReprs();
2606+
for (auto opaqueRepr : opaqueTypeReprs) {
2607+
// Allocate a new generic parameter to represent this opaque type.
2608+
auto gp = GenericTypeParamDecl::create(
2609+
dc, Identifier(), SourceLoc(), /*isTypeSequence=*/false,
2610+
GenericTypeParamDecl::InvalidDepth, index++, /*isOpaqueType=*/true,
2611+
opaqueRepr);
2612+
gp->setImplicit();
2613+
2614+
// Use the underlying constraint as the constraint on the generic parameter.
2615+
InheritedEntry inherited[1] = {
2616+
{ TypeLoc(opaqueRepr->getConstraint()) }
2617+
};
2618+
gp->setInherited(ctx.AllocateCopy(inherited));
2619+
2620+
implicitGenericParams.push_back(gp);
2621+
}
26222622
}
26232623

26242624
return implicitGenericParams;

lib/AST/TypeRepr.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,25 @@ bool TypeRepr::hasOpaque() {
102102
findIf([](TypeRepr *ty) { return isa<OpaqueReturnTypeRepr>(ty); });
103103
}
104104

105+
CollectedOpaqueReprs TypeRepr::collectOpaqueReturnTypeReprs() {
106+
class Walker : public ASTWalker {
107+
CollectedOpaqueReprs &Reprs;
108+
109+
public:
110+
explicit Walker(CollectedOpaqueReprs &reprs) : Reprs(reprs) {}
111+
112+
bool walkToTypeReprPre(TypeRepr *repr) override {
113+
if (auto opaqueRepr = dyn_cast<OpaqueReturnTypeRepr>(repr))
114+
Reprs.push_back(opaqueRepr);
115+
return true;
116+
}
117+
};
118+
119+
CollectedOpaqueReprs reprs;
120+
walk(Walker(reprs));
121+
return reprs;
122+
}
123+
105124
SourceLoc TypeRepr::findUncheckedAttrLoc() const {
106125
auto typeRepr = this;
107126
while (auto attrTypeRepr = dyn_cast<AttributedTypeRepr>(typeRepr)) {

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -78,28 +78,6 @@ TypeChecker::gatherGenericParamBindingsText(
7878
return result.str().str();
7979
}
8080

81-
// An alias to avoid repeating the `SmallVector`'s size parameter.
82-
using CollectedOpaqueReprs = SmallVector<OpaqueReturnTypeRepr *, 2>;
83-
84-
/// Walk `repr` recursively, collecting any `OpaqueReturnTypeRepr`s.
85-
static CollectedOpaqueReprs collectOpaqueReturnTypeReprs(TypeRepr *repr) {
86-
class Walker : public ASTWalker {
87-
CollectedOpaqueReprs &Reprs;
88-
89-
public:
90-
explicit Walker(CollectedOpaqueReprs &reprs) : Reprs(reprs) {}
91-
92-
bool walkToTypeReprPre(TypeRepr *repr) override {
93-
if (auto opaqueRepr = dyn_cast<OpaqueReturnTypeRepr>(repr))
94-
Reprs.push_back(opaqueRepr);
95-
return true;
96-
}
97-
};
98-
99-
CollectedOpaqueReprs reprs;
100-
repr->walk(Walker(reprs));
101-
return reprs;
102-
}
10381

10482
//
10583
// Generic functions
@@ -206,7 +184,7 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
206184
return nullptr;
207185
}
208186
} else {
209-
opaqueReprs = collectOpaqueReturnTypeReprs(repr);
187+
opaqueReprs = repr->collectOpaqueReturnTypeReprs();
210188
SmallVector<GenericTypeParamType *, 2> genericParamTypes;
211189
SmallVector<Requirement, 2> requirements;
212190
for (unsigned i = 0; i < opaqueReprs.size(); ++i) {

test/type/opaque_parameters.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,22 @@ func testTakeMultiple(
5151
takeMultiple(d, arrayOfInts, arrayOfInts) // expected-error{{global function 'takeMultiple' requires that '[Int]' conform to 'P'}}
5252
}
5353

54+
// inout
55+
56+
func anyInOut(_: inout some P) { }
57+
58+
func testAnyInOut() {
59+
var i = 17
60+
anyInOut(&i)
61+
}
62+
63+
// In structural positions.
64+
func anyDictionary(_ dict: [some Hashable: some Any]) { }
65+
66+
func testAnyDictionary(numberNames: [Int: String]) {
67+
anyDictionary(numberNames)
68+
}
69+
5470
// Combine with parameterized protocol types
5571
protocol PrimaryCollection: Collection {
5672
@_primaryAssociatedType associatedtype Element

0 commit comments

Comments
 (0)