Skip to content

Commit 1acb61d

Browse files
committed
SIL: Fix SILType::isLoweringOf() to correctly handle opaque archetypes
This predicate is meant to ask if the loweredType is equal to `getLoweredType(pattern, formalType)` for *some* abstraction pattern. If the formal type contained an opaque archetype, we performed a different check, because we asked if loweredEqual is equal to `getLoweredType(AbstractionPattern(formalType), formalType)`. This caused a spurious SIL verifier failure when the payload of an existential contained an opaque archetype, because we lower the payload with the most general AbstractionPattern, so that @thin metatypes become @thick, etc. The regression test exercises this bug, and also another bug that was present in 6.0 but was already fixed on main by one of my earlier refactorings. Fixes rdar://problem/138655637.
1 parent 8f66bf1 commit 1acb61d

File tree

3 files changed

+134
-6
lines changed

3 files changed

+134
-6
lines changed

lib/SIL/IR/SILType.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -778,12 +778,11 @@ bool SILType::hasAbstractionDifference(SILFunctionTypeRepresentation rep,
778778

779779
bool SILType::isLoweringOf(TypeExpansionContext context, SILModule &Mod,
780780
CanType formalType) {
781+
formalType =
782+
substOpaqueTypesWithUnderlyingTypes(formalType, context)
783+
->getCanonicalType();
784+
781785
SILType loweredType = *this;
782-
if (formalType->hasOpaqueArchetype() &&
783-
context.shouldLookThroughOpaqueTypeArchetypes() &&
784-
loweredType.getASTType() ==
785-
Mod.Types.getLoweredRValueType(context, formalType))
786-
return true;
787786

788787
// Optional lowers its contained type.
789788
SILType loweredObjectType = loweredType.getOptionalObjectType();

test/SILGen/opaque_result_type_structural.swift

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-emit-silgen -disable-availability-checking %s
1+
// RUN: %target-swift-emit-silgen -target %target-swift-5.1-abi-triple %s | %FileCheck %s
22

33
public protocol P {}
44

@@ -36,3 +36,22 @@ extension P {
3636
}
3737
}
3838

39+
// Issues with metatypes
40+
struct G<T> {}
41+
struct S: P {}
42+
extension G: P where T: P {}
43+
44+
func f2() -> G<some P>.Type {
45+
return G<S>.self
46+
}
47+
48+
func g() -> Any {
49+
return f2()
50+
}
51+
52+
// CHECK-LABEL: sil hidden [ossa] @$s29opaque_result_type_structural1gypyF : $@convention(thin) () -> @out Any {
53+
// CHECK: bb0(%0 : $*Any):
54+
// CHECK: [[METATYPE:%.*]] = metatype $@thick G<S>.Type
55+
// CHECK: [[ADDR:%.*]] = init_existential_addr %0 : $*Any, $G<@_opaqueReturnTypeOf("$s29opaque_result_type_structural2f2AA1GVyQrGmyF", 0) __>.Type
56+
// CHECK: store [[METATYPE]] to [trivial] [[ADDR]] : $*@thick G<S>.Type
57+
// CHECK: return
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// RUN: %target-swift-frontend -emit-ir -target %target-swift-5.9-abi-triple %s
2+
3+
protocol P {
4+
var p: Int { get }
5+
}
6+
7+
protocol Q {
8+
func p(content: Int) -> Int
9+
}
10+
11+
struct Zero: P {
12+
var p: Int { 0 }
13+
}
14+
15+
struct One: P {
16+
var p: Int { 1 }
17+
}
18+
19+
struct Add: Q {
20+
let rhs: Int
21+
22+
func p(content: Int) -> Int {
23+
content + rhs
24+
}
25+
}
26+
27+
struct Multiply: Q {
28+
let rhs: Int
29+
30+
func p(content: Int) -> Int {
31+
content * rhs
32+
}
33+
}
34+
35+
struct G<Content: P, each Modifier: Q>: P {
36+
var content: Content
37+
var modifiers: (repeat each Modifier)
38+
39+
init(content: Content, modifiers: (repeat each Modifier)) {
40+
self.content = content
41+
self.modifiers = modifiers
42+
}
43+
44+
var p: Int {
45+
var r = content.p
46+
for m in repeat each modifiers {
47+
r = m.p(content: r)
48+
}
49+
return r
50+
}
51+
}
52+
53+
extension G: Equatable where Content: Equatable,
54+
repeat each Modifier: Equatable
55+
{
56+
static func ==(lhs: Self, rhs: Self) -> Bool {
57+
guard lhs.content == rhs.content else { return false}
58+
for (left, right) in repeat (each lhs.modifiers, each rhs.modifiers) {
59+
guard left == right else { return false }
60+
}
61+
return true
62+
}
63+
}
64+
65+
66+
extension G {
67+
func modifier<T>(_ modifier: T) -> G<Content, repeat each Modifier, T> {
68+
.init(content: content, modifiers: (repeat each modifiers, modifier))
69+
}
70+
71+
func add(_ rhs: Int) -> G<Content, repeat each Modifier, some Q> {
72+
modifier(Add(rhs: rhs))
73+
}
74+
75+
func multiply(_ rhs: Int) -> G<Content, repeat each Modifier, some Q> {
76+
modifier(Multiply(rhs: rhs))
77+
}
78+
}
79+
80+
extension P {
81+
func modifier<T>(_ modifier: T) -> G<Self, T> {
82+
return G(content: self, modifiers: modifier)
83+
}
84+
85+
func add(_ rhs: Int) -> G<Self, some Q> {
86+
modifier(Add(rhs: rhs))
87+
}
88+
89+
func multiply(_ rhs: Int) -> G<Self, some Q> {
90+
modifier(Multiply(rhs: rhs))
91+
}
92+
}
93+
94+
public func test() {
95+
let r = Zero()
96+
.multiply(1)
97+
.multiply(2)
98+
.add(3)
99+
.multiply(4)
100+
.add(2)
101+
.multiply(6)
102+
.add(2)
103+
.multiply(6)
104+
.add(2)
105+
.multiply(6)
106+
107+
print(type(of: r))
108+
}
109+
110+
test()

0 commit comments

Comments
 (0)