Skip to content

Commit 203ca6e

Browse files
committed
AST: Fix accessibility checking in opaque type archetype substitution logic
We were failing to replace opaque types with their underlying type upon encountering an internal type from the current module. This could happen when the internal type appeared in generic substitutions, for example when calling a protocol extension method. Fixes <rdar://problem/60951353>.
1 parent a543bfb commit 203ca6e

File tree

5 files changed

+102
-23
lines changed

5 files changed

+102
-23
lines changed

lib/AST/Type.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2828,10 +2828,14 @@ static bool canSubstituteTypeInto(Type ty, const DeclContext *dc,
28282828
nominal->getDeclContext()->getParentSourceFile() ==
28292829
dc->getParentSourceFile())
28302830
return true;
2831+
28312832
return nominal->getEffectiveAccess() > AccessLevel::FilePrivate;
28322833

28332834
case OpaqueSubstitutionKind::SubstituteNonResilientModule:
28342835
// Can't access types that are not public from a different module.
2836+
if (dc->getParentModule() == nominal->getDeclContext()->getParentModule())
2837+
return true;
2838+
28352839
return nominal->getEffectiveAccess() > AccessLevel::Internal;
28362840
}
28372841
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
public protocol View {}
2+
3+
struct InternalView : View {}
4+
struct InternalGenericView<T> : View {}
5+
6+
public struct PublicView : View {}
7+
public struct PublicGenericView<T> : View {}
8+
9+
extension View {
10+
public func passThrough() -> some View {
11+
return self
12+
}
13+
14+
public func wrapWithInternalView() -> some View {
15+
return InternalView()
16+
}
17+
18+
public func wrapWithInternalGenericView() -> some View {
19+
return InternalGenericView<Self>()
20+
}
21+
22+
public func wrapWithPublicView() -> some View {
23+
return PublicView()
24+
}
25+
26+
public func wrapWithPublicGenericView() -> some View {
27+
return PublicGenericView<Self>()
28+
}
29+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -disable-availability-checking -emit-module %S/Inputs/opaque_result_type_fragile_other.swift -emit-module-path %t/opaque_result_type_fragile_other.swiftmodule
3+
// RUN: %target-swift-frontend -disable-availability-checking -emit-silgen -I%t %s | %FileCheck %s
4+
5+
import opaque_result_type_fragile_other
6+
7+
struct InternalView: View {}
8+
public struct PublicView: View {}
9+
10+
public func testInternalView() {
11+
let v = InternalView()
12+
13+
// CHECK: function_ref @$s32opaque_result_type_fragile_other4ViewPAAE11passThroughQryF : $@convention(method) <τ_0_0 where τ_0_0 : View> (@in_guaranteed τ_0_0) -> @out τ_0_0
14+
_ = v.passThrough()
15+
16+
// CHECK: function_ref @$s32opaque_result_type_fragile_other4ViewPAAE016wrapWithInternalF0QryF : $@convention(method) <τ_0_0 where τ_0_0 : View> (@in_guaranteed τ_0_0) -> @out @_opaqueReturnTypeOf("$s32opaque_result_type_fragile_other4ViewPAAE016wrapWithInternalF0QryF", 0) 🦸<τ_0_0>
17+
_ = v.wrapWithInternalView()
18+
19+
// CHECK: function_ref @$s32opaque_result_type_fragile_other4ViewPAAE023wrapWithInternalGenericF0QryF : $@convention(method) <τ_0_0 where τ_0_0 : View> (@in_guaranteed τ_0_0) -> @out @_opaqueReturnTypeOf("$s32opaque_result_type_fragile_other4ViewPAAE023wrapWithInternalGenericF0QryF", 0) 🦸<τ_0_0>
20+
_ = v.wrapWithInternalGenericView()
21+
22+
// CHECK: function_ref @$s32opaque_result_type_fragile_other4ViewPAAE014wrapWithPublicF0QryF : $@convention(method) <τ_0_0 where τ_0_0 : View> (@in_guaranteed τ_0_0) -> @out PublicView
23+
_ = v.wrapWithPublicView()
24+
25+
//CHECK: function_ref @$s32opaque_result_type_fragile_other4ViewPAAE021wrapWithPublicGenericF0QryF : $@convention(method) <τ_0_0 where τ_0_0 : View> (@in_guaranteed τ_0_0) -> @out PublicGenericView<τ_0_0>
26+
_ = v.wrapWithPublicGenericView()
27+
}
28+
29+
public func testPublicView() {
30+
let v = PublicView()
31+
32+
// CHECK: function_ref @$s32opaque_result_type_fragile_other4ViewPAAE11passThroughQryF : $@convention(method) <τ_0_0 where τ_0_0 : View> (@in_guaranteed τ_0_0) -> @out τ_0_0
33+
_ = v.passThrough()
34+
35+
// CHECK: function_ref @$s32opaque_result_type_fragile_other4ViewPAAE016wrapWithInternalF0QryF : $@convention(method) <τ_0_0 where τ_0_0 : View> (@in_guaranteed τ_0_0) -> @out @_opaqueReturnTypeOf("$s32opaque_result_type_fragile_other4ViewPAAE016wrapWithInternalF0QryF", 0) 🦸<τ_0_0>
36+
_ = v.wrapWithInternalView()
37+
38+
// CHECK: function_ref @$s32opaque_result_type_fragile_other4ViewPAAE023wrapWithInternalGenericF0QryF : $@convention(method) <τ_0_0 where τ_0_0 : View> (@in_guaranteed τ_0_0) -> @out @_opaqueReturnTypeOf("$s32opaque_result_type_fragile_other4ViewPAAE023wrapWithInternalGenericF0QryF", 0) 🦸<τ_0_0>
39+
_ = v.wrapWithInternalGenericView()
40+
41+
// CHECK: function_ref @$s32opaque_result_type_fragile_other4ViewPAAE014wrapWithPublicF0QryF : $@convention(method) <τ_0_0 where τ_0_0 : View> (@in_guaranteed τ_0_0) -> @out PublicView
42+
_ = v.wrapWithPublicView()
43+
44+
//CHECK: function_ref @$s32opaque_result_type_fragile_other4ViewPAAE021wrapWithPublicGenericF0QryF : $@convention(method) <τ_0_0 where τ_0_0 : View> (@in_guaranteed τ_0_0) -> @out PublicGenericView<τ_0_0>
45+
_ = v.wrapWithPublicGenericView()
46+
}

test/SILOptimizer/cast_folding.swift

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
// RUN: %target-swift-frontend -disable-availability-checking -O -emit-sil %s | %FileCheck %s
2-
// RUN: %target-swift-frontend -disable-availability-checking -Onone -emit-sil %s | %FileCheck %s --check-prefix=MANDATORY
3-
// RUN: %target-swift-frontend -Xllvm -sil-disable-pass=FunctionSignatureOpts -Xllvm -sil-disable-pass=PerfInliner -enable-ownership-stripping-after-serialization -disable-availability-checking -O -emit-sil %s | %FileCheck %s
4-
// RUN: %target-swift-frontend -enable-ownership-stripping-after-serialization -disable-availability-checking -Onone -emit-sil %s | %FileCheck %s --check-prefix=MANDATORY
1+
// RUN: %target-swift-frontend -O -emit-sil %s | %FileCheck %s
2+
// RUN: %target-swift-frontend -Xllvm -sil-disable-pass=FunctionSignatureOpts -Xllvm -sil-disable-pass=PerfInliner -enable-ownership-stripping-after-serialization -O -emit-sil %s | %FileCheck %s
53

64
// We want to check two things here:
75
// - Correctness
@@ -1069,25 +1067,6 @@ public func testCastToPForOptionalFailure() -> Bool {
10691067
return testCastToPForOptional(t)
10701068
}
10711069

1072-
struct Underlying : P {
1073-
}
1074-
1075-
public func returnOpaque() -> some P {
1076-
return Underlying()
1077-
}
1078-
1079-
// MANDATORY-LABEL: sil{{.*}} @$s12cast_folding23testCastOpaqueArchetypeyyF
1080-
// MANDATORY: [[O:%.*]] = alloc_stack $@_opaqueReturnTypeOf("$s12cast_folding12returnOpaqueQryF", 0)
1081-
// MANDATORY: [[F:%.*]] = function_ref @$s12cast_folding12returnOpaqueQryF
1082-
// MANDATORY: apply [[F]]([[O]])
1083-
// MANDATORY: [[U:%.*]] = alloc_stack $Underlying
1084-
// MANDATORY: unconditional_checked_cast_addr @_opaqueReturnTypeOf{{.*}}in [[O]] : $*@_opaqueReturnTypeOf{{.*}}to Underlying in [[U]] : $*Underlying
1085-
// MANDATORY: load [[U]] : $*Underlying
1086-
@inlinable
1087-
public func testCastOpaqueArchetype() {
1088-
let o = returnOpaque() as! Underlying
1089-
}
1090-
10911070
print("test0=\(test0())")
10921071

10931072
print("test1=\(test1())")
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-swift-frontend -enable-library-evolution -disable-availability-checking -O -emit-sil %s
2+
// RUN: %target-swift-frontend -enable-library-evolution -disable-availability-checking -Onone -emit-sil %s | %FileCheck %s
3+
4+
public protocol P {}
5+
6+
public struct Underlying : P {
7+
}
8+
9+
public func returnOpaque() -> some P {
10+
return Underlying()
11+
}
12+
13+
// CHECK-LABEL: sil [serialized] @$s19cast_folding_opaque23testCastOpaqueArchetypeAA10UnderlyingVyF
14+
// CHECK: [[O:%.*]] = alloc_stack $@_opaqueReturnTypeOf("$s19cast_folding_opaque12returnOpaqueQryF", 0)
15+
// CHECK: [[F:%.*]] = function_ref @$s19cast_folding_opaque12returnOpaqueQryF
16+
// CHECK: apply [[F]]([[O]])
17+
// CHECK: unconditional_checked_cast_addr @_opaqueReturnTypeOf{{.*}}in [[O]] : $*@_opaqueReturnTypeOf{{.*}}to Underlying in %0 : $*Underlying
18+
@inlinable
19+
public func testCastOpaqueArchetype() -> Underlying {
20+
return returnOpaque() as! Underlying
21+
}

0 commit comments

Comments
 (0)