Skip to content

Commit 175e712

Browse files
authored
Merge pull request #64037 from angela-laar/fix-generic-type-paramters-implicit-some
[NameLookup] Collect implicit opaque GenericParams
2 parents 02c72cd + c3eb22a commit 175e712

File tree

8 files changed

+39
-27
lines changed

8 files changed

+39
-27
lines changed

include/swift/AST/NameLookup.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ class ASTScopeImpl;
4545
/// Walk the type representation recursively, collecting any
4646
/// \c OpaqueReturnTypeRepr, \c CompositionTypeRepr or \c DeclRefTypeRepr
4747
/// nodes.
48-
CollectedOpaqueReprs collectOpaqueReturnTypeReprs(TypeRepr *, ASTContext &ctx, DeclContext *dc);
48+
CollectedOpaqueReprs collectOpaqueTypeReprs(TypeRepr *, ASTContext &ctx,
49+
DeclContext *dc);
4950

5051
/// LookupResultEntry - One result of unqualified lookup.
5152
struct LookupResultEntry {

include/swift/AST/TypeRepr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ class alignas(1 << TypeReprAlignInBits) TypeRepr
125125
}
126126

127127
/// Is this type representation a protocol?
128-
bool isProtocol(DeclContext *dc);
128+
bool isProtocolOrProtocolComposition(DeclContext *dc);
129129

130130
/// Is this type representation known to be invalid?
131131
bool isInvalid() const { return Bits.TypeRepr.Invalid; }

lib/AST/Decl.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3307,9 +3307,8 @@ TypeRepr *ValueDecl::getOpaqueResultTypeRepr() const {
33073307
if (returnRepr && returnRepr->hasOpaque()) {
33083308
return returnRepr;
33093309
} else if (returnRepr && ctx.LangOpts.hasFeature(Feature::ImplicitSome)) {
3310-
auto opaqueReprs = collectOpaqueReturnTypeReprs(returnRepr,
3311-
getASTContext(),
3312-
getDeclContext());
3310+
auto opaqueReprs =
3311+
collectOpaqueTypeReprs(returnRepr, getASTContext(), getDeclContext());
33133312
return opaqueReprs.empty() ? nullptr : returnRepr;
33143313
} else {
33153314
return nullptr;

lib/AST/NameLookup.cpp

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2924,7 +2924,7 @@ static bool declsAreAssociatedTypes(ArrayRef<TypeDecl *> decls) {
29242924
/// Verify there is at least one protocols in the set of declarations.
29252925
static bool declsAreProtocols(ArrayRef<TypeDecl *> decls) {
29262926
if (decls.empty())
2927-
return false;
2927+
return false; // Below, check outer type repr is a protocol, if not bail early
29282928
return llvm::any_of(decls, [&](const TypeDecl *decl) {
29292929
if (auto *alias = dyn_cast<TypeAliasDecl>(decl)) {
29302930
auto ty = alias->getUnderlyingType();
@@ -2933,14 +2933,12 @@ static bool declsAreProtocols(ArrayRef<TypeDecl *> decls) {
29332933
return false;
29342934
}
29352935
return isa<ProtocolDecl>(decl);
2936-
});;;
2936+
});
29372937
}
29382938

2939-
bool TypeRepr::isProtocol(DeclContext *dc){
2939+
bool TypeRepr::isProtocolOrProtocolComposition(DeclContext *dc){
29402940
auto &ctx = dc->getASTContext();
2941-
return findIf([&ctx, dc](TypeRepr *ty) {
2942-
return declsAreProtocols(directReferencesForTypeRepr(ctx.evaluator, ctx, ty, dc));
2943-
});
2941+
return declsAreProtocols(directReferencesForTypeRepr(ctx.evaluator, ctx, this, dc));
29442942
}
29452943

29462944
static GenericParamList *
@@ -2962,7 +2960,8 @@ createExtensionGenericParams(ASTContext &ctx,
29622960
return toParams;
29632961
}
29642962

2965-
CollectedOpaqueReprs swift::collectOpaqueReturnTypeReprs(TypeRepr *r, ASTContext &ctx, DeclContext *d) {
2963+
CollectedOpaqueReprs swift::collectOpaqueTypeReprs(TypeRepr *r, ASTContext &ctx,
2964+
DeclContext *d) {
29662965
class Walker : public ASTWalker {
29672966
CollectedOpaqueReprs &Reprs;
29682967
ASTContext &Ctx;
@@ -2993,15 +2992,19 @@ CollectedOpaqueReprs swift::collectOpaqueReturnTypeReprs(TypeRepr *r, ASTContext
29932992

29942993
if (auto existential = dyn_cast<ExistentialTypeRepr>(repr)) {
29952994
return Action::SkipChildren();
2996-
} else if (auto compositionRepr = dyn_cast<CompositionTypeRepr>(repr)) {
2997-
if (!compositionRepr->isTypeReprAny())
2998-
Reprs.push_back(compositionRepr);
2995+
} else if (auto composition = dyn_cast<CompositionTypeRepr>(repr)) {
2996+
if (!composition->isTypeReprAny())
2997+
Reprs.push_back(composition);
29992998
return Action::SkipChildren();
30002999
} else if (auto generic = dyn_cast<GenericIdentTypeRepr>(repr)) {
3000+
if (generic->isProtocolOrProtocolComposition(dc)){
3001+
Reprs.push_back(generic);
3002+
return Action::SkipChildren();
3003+
}
30013004
return Action::Continue();
3002-
} else if (auto declRefTR = dyn_cast<DeclRefTypeRepr>(repr)) {
3003-
if (declRefTR->isProtocol(dc))
3004-
Reprs.push_back(declRefTR);
3005+
} else if (auto declRef = dyn_cast<DeclRefTypeRepr>(repr)) {
3006+
if (declRef->isProtocolOrProtocolComposition(dc))
3007+
Reprs.push_back(declRef);
30053008
}
30063009
return Action::Continue();
30073010
}
@@ -3043,7 +3046,7 @@ createOpaqueParameterGenericParams(GenericContext *genericContext, GenericParamL
30433046

30443047
// Plain protocols should imply 'some' with experimetal feature
30453048
CollectedOpaqueReprs typeReprs;
3046-
typeReprs = collectOpaqueReturnTypeReprs(typeRepr, ctx, dc);
3049+
typeReprs = collectOpaqueTypeReprs(typeRepr, ctx, dc);
30473050

30483051
for (auto repr : typeReprs) {
30493052

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
136136
return nullptr;
137137
}
138138
} else {
139-
opaqueReprs = collectOpaqueReturnTypeReprs(repr, ctx, dc);
140-
139+
opaqueReprs = collectOpaqueTypeReprs(repr, ctx, dc);
140+
141141
if (opaqueReprs.empty()) {
142142
return nullptr;
143143
}

lib/Sema/TypeCheckPattern.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,7 @@ validateTypedPattern(TypedPattern *TP, DeclContext *dc,
704704
auto *Repr = TP->getTypeRepr();
705705
if (Repr && (Repr->hasOpaque() ||
706706
(Context.LangOpts.hasFeature(Feature::ImplicitSome) &&
707-
!collectOpaqueReturnTypeReprs(Repr, Context, dc).empty()))) {
707+
!collectOpaqueTypeReprs(Repr, Context, dc).empty()))) {
708708
auto named = dyn_cast<NamedPattern>(
709709
TP->getSubPattern()->getSemanticsProvidingPattern());
710710
if (!named) {

test/type/implicit_some/opaque_parameters.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,9 @@ func consumingA(fn: (P) -> Void) { } // expected-error{{'some' cannot appear in
6262
func consumingB(fn: FnType<P>) { } // expected-error{{'some' cannot appear in parameter position in parameter type '(P) -> Void'}}
6363

6464

65-
// TO-DO Handle plain generic opaque parameters
6665
func takePrimaryCollections(
67-
_ strings:some Collection<String>,
68-
_ ints : some Collection<Int>
66+
_ strings: Collection<String>,
67+
_ ints : Collection<Int>
6968
) {
7069
for s in strings {
7170
let _: String = s
@@ -75,9 +74,8 @@ func takePrimaryCollections(
7574
let _: Int = i
7675
}
7776
}
78-
// TO-DO Handle plain generic opaque parameters
7977
func takeMatchedPrimaryCollections<T: Equatable>(
80-
_ first: some Collection<T>, _ second: some Collection<T>
78+
_ first: Collection<T>, _ second: Collection<T>
8179
) -> Bool {
8280
first.elementsEqual(second)
8381
}

test/type/implicit_some/opaque_return.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,14 @@ enum E {
125125
protocol Q {
126126
func f() -> Int
127127
}
128+
129+
func findBiggerCollection<T : Numeric>( _ first: Collection<T>, _ second: Collection<T>) -> Collection<T> {
130+
// expected-error@-1 {{function declares an opaque return type 'Collection<T>', but the return statements in its body do not have matching underlying types}}
131+
if (first.count > second.count) { return first } //expected-note {{return statement has underlying type 'Collection<T>'}}
132+
return second //expected-note {{return statement has underlying type 'Collection<T>'}}
133+
}
134+
135+
func createCollection() -> Collection<Int> {
136+
let a = [9,2,0]
137+
return a
138+
}

0 commit comments

Comments
 (0)