Skip to content

Commit a15628b

Browse files
committed
AST: Fix ReplaceOpaqueTypesWithUnderlyingTypes to handle nested types of opaque result types
Fixes rdar://problem/85137685.
1 parent efb3a49 commit a15628b

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

lib/AST/Type.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3215,7 +3215,14 @@ static bool canSubstituteTypeInto(Type ty, const DeclContext *dc,
32153215
bool isContextWholeModule) {
32163216
TypeDecl *typeDecl = ty->getAnyNominal();
32173217
if (!typeDecl) {
3218-
// We also need to check that the opaque type descriptor is accessible.
3218+
// The referenced type might be a different opaque result type.
3219+
3220+
// First, unwrap any nested associated types to get the root archetype.
3221+
while (auto nestedTy = ty->getAs<NestedArchetypeType>())
3222+
ty = nestedTy->getParent();
3223+
3224+
// If the root archetype is an opaque result type, check that its
3225+
// descriptor is accessible.
32193226
if (auto opaqueTy = ty->getAs<OpaqueTypeArchetypeType>())
32203227
typeDecl = opaqueTy->getDecl();
32213228
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
public protocol IteratorProtocol {
2+
associatedtype Element
3+
4+
func next() -> Element?
5+
}
6+
7+
public func doSomething() -> some IteratorProtocol {
8+
return doSomethingInternal()
9+
}
10+
11+
func doSomethingInternal() -> some IteratorProtocol {
12+
return SomeIterator()
13+
}
14+
15+
struct SomeIterator: IteratorProtocol {
16+
public typealias Element = Int
17+
18+
public func next() -> Int? {
19+
return nil
20+
}
21+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module %S/Inputs/opaque_result_type_private_assoc_type_other.swift -emit-module-path %t/opaque_result_type_private_assoc_type_other.swiftmodule -disable-availability-checking
3+
// RUN: %target-swift-emit-silgen -I %t %s | %FileCheck %s
4+
5+
import opaque_result_type_private_assoc_type_other
6+
7+
// CHECK-LABEL: sil hidden [ossa] @$s033opaque_result_type_private_assoc_C0028usesAssocTypeOfPrivateResultH0yyF : $@convention(thin) () -> () {
8+
func usesAssocTypeOfPrivateResultType() {
9+
// CHECK: [[BOX:%.*]] = alloc_stack $Optional<@_opaqueReturnTypeOf("$s033opaque_result_type_private_assoc_C6_other11doSomethingQryF", 0) __.Element>
10+
// CHECK: [[METHOD:%.*]] = witness_method $@_opaqueReturnTypeOf("$s033opaque_result_type_private_assoc_C6_other11doSomethingQryF", 0) __, #IteratorProtocol.next : <Self where Self : opaque_result_type_private_assoc_type_other.IteratorProtocol> (Self) -> () -> Self.Element? : $@convention(witness_method: IteratorProtocol) <τ_0_0 where τ_0_0 : IteratorProtocol> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0.Element>
11+
// CHECK: [[RESULT:%.*]] = apply [[METHOD]]<@_opaqueReturnTypeOf("$s033opaque_result_type_private_assoc_C6_other11doSomethingQryF", 0) __>([[BOX]], {{%.*}}) : $@convention(witness_method: IteratorProtocol) <τ_0_0 where τ_0_0 : IteratorProtocol> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0.Element>
12+
let iterator = doSomething()
13+
let _ = iterator.next()
14+
}

0 commit comments

Comments
 (0)