Skip to content

Commit 4f3dff4

Browse files
committed
[Sema] Create Opaque Decls from Composition Types
1 parent a7171c0 commit 4f3dff4

File tree

3 files changed

+78
-41
lines changed

3 files changed

+78
-41
lines changed

lib/AST/NameLookup.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2774,7 +2774,10 @@ static bool declsAreProtocols(ArrayRef<TypeDecl *> decls) {
27742774

27752775
bool TypeRepr::isProtocol(DeclContext *dc){
27762776
auto &ctx = dc->getASTContext();
2777-
return findIf([&ctx, dc](TypeRepr *ty) { return declsAreProtocols(directReferencesForTypeRepr(ctx.evaluator, ctx, ty, dc)); });
2777+
return findIf([&ctx, dc](TypeRepr *ty) {
2778+
return declsAreProtocols(directReferencesForTypeRepr(ctx.evaluator, ctx, ty, dc));
2779+
2780+
});
27782781
}
27792782

27802783

@@ -2819,7 +2822,6 @@ CollectedOpaqueReprs swift::collectOpaqueReturnTypeReprs(TypeRepr *r, ASTContext
28192822
}
28202823

28212824
if (Ctx.LangOpts.hasFeature(Feature::ImplicitSome)) {
2822-
28232825
if (auto existential = dyn_cast<ExistentialTypeRepr>(repr)) {
28242826
auto generic = dyn_cast<GenericIdentTypeRepr>(existential->getConstraint());
28252827
if(generic)
@@ -2833,11 +2835,9 @@ CollectedOpaqueReprs swift::collectOpaqueReturnTypeReprs(TypeRepr *r, ASTContext
28332835
Reprs.push_back(compositionRepr);
28342836
return Action::SkipChildren();
28352837
} else if (auto generic = dyn_cast<GenericIdentTypeRepr>(repr)) {
2836-
if (!Reprs.empty()){
2837-
if(isa<ExistentialTypeRepr>(Reprs.front())){
2838+
if (!Reprs.empty() && isa<ExistentialTypeRepr>(Reprs.front())){
28382839
Reprs.clear();
28392840
Action::Continue();
2840-
}
28412841
}
28422842
Reprs.push_back(generic);
28432843
} else if (auto identRepr = dyn_cast<IdentTypeRepr>(repr)) {

lib/Sema/TypeCheckType.cpp

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2260,21 +2260,23 @@ NeverNullType TypeResolver::resolveType(TypeRepr *repr,
22602260
return ty;
22612261
};
22622262

2263-
if (auto opaqueDecl = dyn_cast<OpaqueTypeDecl>(DC)) {
2264-
if (auto ordinal = opaqueDecl->getAnonymousOpaqueParamOrdinal(repr))
2265-
return diagnoseDisallowedExistential(getIdentityOpaqueTypeArchetypeType(opaqueDecl, *ordinal));
2266-
}
2267-
2268-
// Check whether any of the generic parameters in the context represents
2269-
// this opaque type. If so, return that generic parameter.
2270-
if (options.isConstraintImplicitExistential()) {
2271-
if (auto declDC = DC->getAsDecl()) {
2272-
if (auto genericContext = declDC->getAsGenericContext()) {
2273-
if (auto genericParams = genericContext->getGenericParams()) {
2274-
for (auto genericParam : *genericParams) {
2275-
if (genericParam->getOpaqueTypeRepr() == repr)
2276-
return diagnoseDisallowedExistential(
2277-
genericParam->getDeclaredInterfaceType());
2263+
if(getASTContext().LangOpts.hasFeature(Feature::ImplicitSome)){
2264+
if (auto opaqueDecl = dyn_cast<OpaqueTypeDecl>(DC)) {
2265+
if (auto ordinal = opaqueDecl->getAnonymousOpaqueParamOrdinal(repr))
2266+
return diagnoseDisallowedExistential(getIdentityOpaqueTypeArchetypeType(opaqueDecl, *ordinal));
2267+
}
2268+
2269+
// Check whether any of the generic parameters in the context represents
2270+
// this opaque type. If so, return that generic parameter.
2271+
if (options.isConstraintImplicitExistential()) {
2272+
if (auto declDC = DC->getAsDecl()) {
2273+
if (auto genericContext = declDC->getAsGenericContext()) {
2274+
if (auto genericParams = genericContext->getGenericParams()) {
2275+
for (auto genericParam : *genericParams) {
2276+
if (genericParam->getOpaqueTypeRepr() == repr)
2277+
return diagnoseDisallowedExistential(
2278+
genericParam->getDeclaredInterfaceType());
2279+
}
22782280
}
22792281
}
22802282
}
@@ -2321,8 +2323,32 @@ NeverNullType TypeResolver::resolveType(TypeRepr *repr,
23212323
case TypeReprKind::Tuple:
23222324
return resolveTupleType(cast<TupleTypeRepr>(repr), options);
23232325

2324-
case TypeReprKind::Composition:
2325-
return resolveCompositionType(cast<CompositionTypeRepr>(repr), options);
2326+
case TypeReprKind::Composition: {
2327+
auto *DC = getDeclContext();
2328+
auto diagnoseDisallowedExistential = [&](Type ty) {
2329+
if (!(options & TypeResolutionFlags::SilenceErrors) &&
2330+
options.contains(TypeResolutionFlags::DisallowOpaqueTypes)) {
2331+
// We're specifically looking at an existential type `any P<some Q>`,
2332+
// so emit a tailored diagnostic. We don't emit an ErrorType here
2333+
// for better recovery.
2334+
diagnose(repr->getLoc(),
2335+
diag::unsupported_opaque_type_in_existential);
2336+
// FIXME: We shouldn't have to invalid the type repr here, but not
2337+
// doing so causes a double-diagnostic.
2338+
repr->setInvalid();
2339+
}
2340+
return ty;
2341+
};
2342+
2343+
if(getASTContext().LangOpts.hasFeature(Feature::ImplicitSome)){
2344+
if (auto opaqueDecl = dyn_cast<OpaqueTypeDecl>(DC)) {
2345+
if (auto ordinal = opaqueDecl->getAnonymousOpaqueParamOrdinal(repr))
2346+
return diagnoseDisallowedExistential(getIdentityOpaqueTypeArchetypeType(opaqueDecl, *ordinal));
2347+
}
2348+
}
2349+
2350+
return resolveCompositionType(cast<CompositionTypeRepr>(repr), options);
2351+
}
23262352

23272353
case TypeReprKind::Metatype:
23282354
return resolveMetatypeType(cast<MetatypeTypeRepr>(repr), options);

test/type/implicit_some/opaque_return.swift

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
// RUN: %target-typecheck-verify-swift -disable-availability-checking -warn-redundant-requirements -enable-experimental-implicit-some
22

3+
protocol Eatery {
4+
func lunch()
5+
func dinner()
6+
func dessert()
7+
}
8+
9+
protocol Shop {
10+
func coffee ()
11+
}
12+
313
// Access Return Type Constraint
414
protocol Cafe {
515
func breakfast()
@@ -23,7 +33,7 @@ cafe.treats()
2333
typealias Snack = Shop & Cafe
2434
typealias Meal = Eatery
2535

26-
struct CoffeeBar: Snack {
36+
struct CoffeeShop(): Snack {
2737
func coffee(){ }
2838
func breakfast() { }
2939
func treats(){ }
@@ -41,33 +51,34 @@ class TopTier: Eatery {
4151
func dessert() { }
4252
}
4353

44-
func list(_: Snack) {}
45-
46-
func find( _: Snack) -> Snack { } // expected-error {{function declares an opaque return type, but has no return statements in its body from which to infer an underlying type}}
54+
func find() -> Eatery { } // expected-error {{function declares an opaque return type, but has no return statements in its body from which to infer an underlying type}}
4755

48-
// tuple types
49-
func list(_: (Meal, Meal)) {}
56+
func find() -> AnyObject {
57+
return CoffeeShop() // expected-error {{return expression of type 'CoffeeBar' expected to be an instance of a class or class-constrained type}}
58+
}
5059

51-
func highestRated() -> (Eatery, Eatery) {
52-
return (Best(), TopTier())
60+
func find() -> Any {
61+
return CoffeeShop()
5362
}
5463

55-
func highestRated() -> (some Snack, some Snack) { } // expected-error {{function declares an opaque return type, but has no return statements in its body from which to infer an underlying type}}
64+
// tuple types
65+
func highestRated() -> (Eatery, Eatery) { } // expected-error {{function declares an opaque return type, but has no return statements in its body from which to infer an underlying type}}
5666

57-
// opaque compostion types
58-
func find() -> Shop & Cafe {
59-
return CoffeeBar()
67+
// type alias
68+
func inspect( _ snack: some Snack) -> some Snack {
69+
return CoffeeShop();
6070
}
71+
// tuple type alias
72+
func highestRated() -> (some Snack, some Snack) { } // expected-error {{function declares an opaque return type, but has no return statements in its body from which to infer an underlying type}}
6173

62-
func find() -> AnyObject {
63-
return CoffeeBar() // expected-error {{Return expression of type 'CoffeeBar' expected to be an instance of a class or class-constrained type}}
64-
}
74+
// TO-DO: Fix type alias for plain protocols; resolves as an existential type
75+
func list(_: (Meal, Meal)) -> (Meal, Meal){ }
76+
func find() -> Snack { }
6577

66-
func find() -> Any {
67-
return CoffeeBar()
68-
}
78+
// opaque compostion types
79+
func search() -> Shop & Cafe { } // expected-error {{function declares an opaque return type, but has no return statements in its body from which to infer an underlying type}}
6980

70-
// protocol with associated type constraint
81+
// associated type constraint
7182
protocol Basket {
7283
associatedtype Fruit
7384
associatedtype MiniBasket: Basket where MiniBasket.Fruit == Fruit

0 commit comments

Comments
 (0)