From ac00a8cd29be61d8a4c265bd95b2803c6ea14658 Mon Sep 17 00:00:00 2001 From: Angela Laar Date: Thu, 2 Mar 2023 10:58:17 -0800 Subject: [PATCH 1/3] [NameLookup] Collect implicit opaque GenericParams Plain protocols with generic type paramters should be collected as opaque types. --- include/swift/AST/TypeRepr.h | 3 ++- lib/AST/NameLookup.cpp | 26 ++++++++++++++------------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/include/swift/AST/TypeRepr.h b/include/swift/AST/TypeRepr.h index 6d189c7afb60..c649e52c23f8 100644 --- a/include/swift/AST/TypeRepr.h +++ b/include/swift/AST/TypeRepr.h @@ -125,7 +125,7 @@ class alignas(1 << TypeReprAlignInBits) TypeRepr } /// Is this type representation a protocol? - bool isProtocol(DeclContext *dc); + bool isProtocolOrProtocolComposition(DeclContext *dc); /// Is this type representation known to be invalid? bool isInvalid() const { return Bits.TypeRepr.Invalid; } @@ -408,6 +408,7 @@ class GenericIdentTypeRepr final return {getTrailingObjects(), Bits.GenericIdentTypeRepr.NumGenericArgs}; } + SourceRange getAngleBrackets() const { return AngleBrackets; } static bool classof(const TypeRepr *T) { diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index 145e623a531b..aea7df3d8d7a 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -2924,7 +2924,7 @@ static bool declsAreAssociatedTypes(ArrayRef decls) { /// Verify there is at least one protocols in the set of declarations. static bool declsAreProtocols(ArrayRef decls) { if (decls.empty()) - return false; + return false; // Below, check outer type repr is a protocol, if not bail early return llvm::any_of(decls, [&](const TypeDecl *decl) { if (auto *alias = dyn_cast(decl)) { auto ty = alias->getUnderlyingType(); @@ -2933,14 +2933,12 @@ static bool declsAreProtocols(ArrayRef decls) { return false; } return isa(decl); - });;; + }); } -bool TypeRepr::isProtocol(DeclContext *dc){ +bool TypeRepr::isProtocolOrProtocolComposition(DeclContext *dc){ auto &ctx = dc->getASTContext(); - return findIf([&ctx, dc](TypeRepr *ty) { - return declsAreProtocols(directReferencesForTypeRepr(ctx.evaluator, ctx, ty, dc)); - }); + return declsAreProtocols(directReferencesForTypeRepr(ctx.evaluator, ctx, this, dc)); } static GenericParamList * @@ -2993,15 +2991,19 @@ CollectedOpaqueReprs swift::collectOpaqueReturnTypeReprs(TypeRepr *r, ASTContext if (auto existential = dyn_cast(repr)) { return Action::SkipChildren(); - } else if (auto compositionRepr = dyn_cast(repr)) { - if (!compositionRepr->isTypeReprAny()) - Reprs.push_back(compositionRepr); + } else if (auto composition = dyn_cast(repr)) { + if (!composition->isTypeReprAny()) + Reprs.push_back(composition); return Action::SkipChildren(); } else if (auto generic = dyn_cast(repr)) { + if (generic->isProtocolOrProtocolComposition(dc)){ + Reprs.push_back(generic); + return Action::SkipChildren(); + } return Action::Continue(); - } else if (auto declRefTR = dyn_cast(repr)) { - if (declRefTR->isProtocol(dc)) - Reprs.push_back(declRefTR); + } else if (auto declRef = dyn_cast(repr)) { + if (declRef->isProtocolOrProtocolComposition(dc)) + Reprs.push_back(declRef); } return Action::Continue(); } From 3a20ff0826aecd2f3797a9ed090cd063a8785d57 Mon Sep 17 00:00:00 2001 From: Angela Laar Date: Wed, 15 Mar 2023 17:24:55 -0700 Subject: [PATCH 2/3] [NameLookup] Rename opaque type collector function --- include/swift/AST/NameLookup.h | 3 ++- include/swift/AST/TypeRepr.h | 1 - lib/AST/Decl.cpp | 5 ++--- lib/AST/NameLookup.cpp | 5 +++-- lib/Sema/TypeCheckGeneric.cpp | 4 ++-- lib/Sema/TypeCheckPattern.cpp | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h index 5e50a90cb514..422325a2d82f 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -45,7 +45,8 @@ class ASTScopeImpl; /// Walk the type representation recursively, collecting any /// \c OpaqueReturnTypeRepr, \c CompositionTypeRepr or \c DeclRefTypeRepr /// nodes. -CollectedOpaqueReprs collectOpaqueReturnTypeReprs(TypeRepr *, ASTContext &ctx, DeclContext *dc); +CollectedOpaqueReprs collectOpaqueTypeReprs(TypeRepr *, ASTContext &ctx, + DeclContext *dc); /// LookupResultEntry - One result of unqualified lookup. struct LookupResultEntry { diff --git a/include/swift/AST/TypeRepr.h b/include/swift/AST/TypeRepr.h index c649e52c23f8..2befb5a11fc9 100644 --- a/include/swift/AST/TypeRepr.h +++ b/include/swift/AST/TypeRepr.h @@ -408,7 +408,6 @@ class GenericIdentTypeRepr final return {getTrailingObjects(), Bits.GenericIdentTypeRepr.NumGenericArgs}; } - SourceRange getAngleBrackets() const { return AngleBrackets; } static bool classof(const TypeRepr *T) { diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index a808f71764b0..acb171ac1856 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -3301,9 +3301,8 @@ TypeRepr *ValueDecl::getOpaqueResultTypeRepr() const { if (returnRepr && returnRepr->hasOpaque()) { return returnRepr; } else if (returnRepr && ctx.LangOpts.hasFeature(Feature::ImplicitSome)) { - auto opaqueReprs = collectOpaqueReturnTypeReprs(returnRepr, - getASTContext(), - getDeclContext()); + auto opaqueReprs = + collectOpaqueTypeReprs(returnRepr, getASTContext(), getDeclContext()); return opaqueReprs.empty() ? nullptr : returnRepr; } else { return nullptr; diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index aea7df3d8d7a..21bd8f252301 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -2960,7 +2960,8 @@ createExtensionGenericParams(ASTContext &ctx, return toParams; } -CollectedOpaqueReprs swift::collectOpaqueReturnTypeReprs(TypeRepr *r, ASTContext &ctx, DeclContext *d) { +CollectedOpaqueReprs swift::collectOpaqueTypeReprs(TypeRepr *r, ASTContext &ctx, + DeclContext *d) { class Walker : public ASTWalker { CollectedOpaqueReprs &Reprs; ASTContext &Ctx; @@ -3045,7 +3046,7 @@ createOpaqueParameterGenericParams(GenericContext *genericContext, GenericParamL // Plain protocols should imply 'some' with experimetal feature CollectedOpaqueReprs typeReprs; - typeReprs = collectOpaqueReturnTypeReprs(typeRepr, ctx, dc); + typeReprs = collectOpaqueTypeReprs(typeRepr, ctx, dc); for (auto repr : typeReprs) { diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index b1502153b27c..72fe996c2b1e 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -136,8 +136,8 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator, return nullptr; } } else { - opaqueReprs = collectOpaqueReturnTypeReprs(repr, ctx, dc); - + opaqueReprs = collectOpaqueTypeReprs(repr, ctx, dc); + if (opaqueReprs.empty()) { return nullptr; } diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index 9b15982e35b6..946e86da0d85 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -704,7 +704,7 @@ validateTypedPattern(TypedPattern *TP, DeclContext *dc, auto *Repr = TP->getTypeRepr(); if (Repr && (Repr->hasOpaque() || (Context.LangOpts.hasFeature(Feature::ImplicitSome) && - !collectOpaqueReturnTypeReprs(Repr, Context, dc).empty()))) { + !collectOpaqueTypeReprs(Repr, Context, dc).empty()))) { auto named = dyn_cast( TP->getSubPattern()->getSemanticsProvidingPattern()); if (!named) { From c3eb22abda56e78f2c077587651d0162dca5cccf Mon Sep 17 00:00:00 2001 From: Angela Laar Date: Tue, 21 Mar 2023 14:41:15 -0700 Subject: [PATCH 3/3] [test] test generic params with implicit some --- test/type/implicit_some/opaque_parameters.swift | 8 +++----- test/type/implicit_some/opaque_return.swift | 11 +++++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/test/type/implicit_some/opaque_parameters.swift b/test/type/implicit_some/opaque_parameters.swift index 769da71b89e9..21bc7e6cfe59 100644 --- a/test/type/implicit_some/opaque_parameters.swift +++ b/test/type/implicit_some/opaque_parameters.swift @@ -62,10 +62,9 @@ func consumingA(fn: (P) -> Void) { } // expected-error{{'some' cannot appear in func consumingB(fn: FnType

) { } // expected-error{{'some' cannot appear in parameter position in parameter type '(P) -> Void'}} -// TO-DO Handle plain generic opaque parameters func takePrimaryCollections( - _ strings:some Collection, - _ ints : some Collection + _ strings: Collection, + _ ints : Collection ) { for s in strings { let _: String = s @@ -75,9 +74,8 @@ func takePrimaryCollections( let _: Int = i } } -// TO-DO Handle plain generic opaque parameters func takeMatchedPrimaryCollections( - _ first: some Collection, _ second: some Collection + _ first: Collection, _ second: Collection ) -> Bool { first.elementsEqual(second) } diff --git a/test/type/implicit_some/opaque_return.swift b/test/type/implicit_some/opaque_return.swift index 1c2ffe22f94b..cf2f758913d5 100644 --- a/test/type/implicit_some/opaque_return.swift +++ b/test/type/implicit_some/opaque_return.swift @@ -125,3 +125,14 @@ enum E { protocol Q { func f() -> Int } + +func findBiggerCollection( _ first: Collection, _ second: Collection) -> Collection { + // expected-error@-1 {{function declares an opaque return type 'Collection', but the return statements in its body do not have matching underlying types}} + if (first.count > second.count) { return first } //expected-note {{return statement has underlying type 'Collection'}} + return second //expected-note {{return statement has underlying type 'Collection'}} +} + +func createCollection() -> Collection { + let a = [9,2,0] + return a +}