Skip to content

Commit 1992741

Browse files
committed
[IRGen] Rearrange fix slightly and add a test case.
isDependentConformance() should always check for synthesized conformances, so do that further up the function. Also add a test. rdar://97290618
1 parent 5380bc8 commit 1992741

File tree

4 files changed

+330
-16
lines changed

4 files changed

+330
-16
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,7 @@ bool IRGenModule::isResilientConformance(
871871
// across module boundaries.
872872
if (conformanceModule == getSwiftModule() &&
873873
conformanceModule->getName().str() ==
874-
conformance->getProtocol()->getAlternateModuleName())
874+
conformance->getProtocol()->getAlternateModuleName())
875875
return false;
876876

877877
// If the protocol and the conformance are in the same module and the
@@ -946,8 +946,9 @@ static bool isDependentConformance(
946946
if (!visited.insert(conformance).second)
947947
return false;
948948

949-
// If the conformance is resilient, this is always true.
950-
if (IGM.isResilientConformance(conformance))
949+
// If the conformance is resilient or synthesized, this is always true.
950+
if (IGM.isResilientConformance(conformance)
951+
|| isSynthesizedNonUnique(conformance))
951952
return true;
952953

953954
// Check whether any of the conformances are dependent.
@@ -967,15 +968,11 @@ static bool isDependentConformance(
967968
if (assocConformance.isInvalid())
968969
return false;
969970

970-
if (assocConformance.isAbstract())
971-
return true;
972-
973-
auto rootConformance = assocConformance.getConcrete()->getRootConformance();
974-
975-
// [*] This condition must be true if getConformanceInfo() would return
976-
// an AccessorConformanceInfo().
977-
if (isSynthesizedNonUnique(rootConformance) ||
978-
isDependentConformance(IGM, rootConformance, visited))
971+
if (assocConformance.isAbstract() ||
972+
isDependentConformance(IGM,
973+
assocConformance.getConcrete()
974+
->getRootConformance(),
975+
visited))
979976
return true;
980977
}
981978

@@ -985,7 +982,7 @@ static bool isDependentConformance(
985982
// Check if there are any conditional conformances. Other forms of conditional
986983
// requirements don't exist in the witness table.
987984
return SILWitnessTable::enumerateWitnessTableConditionalConformances(
988-
conformance, [](unsigned, CanType, ProtocolDecl *) { return true; });
985+
conformance, [](unsigned, CanType, ProtocolDecl *) { return true; });
989986
}
990987

991988
/// Is there anything about the given conformance that requires witness
@@ -2146,9 +2143,6 @@ IRGenModule::getConformanceInfo(const ProtocolDecl *protocol,
21462143
// so in theory we could allocate them on a BumpPtrAllocator. But there's not
21472144
// a good one for us to use. (The ASTContext's outlives the IRGenModule in
21482145
// batch mode.)
2149-
//
2150-
// N.B. If you change this condition, you may need to update the condition
2151-
// marked [*] in isDependentConformance().
21522146
if (isDependentConformance(rootConformance) ||
21532147
// Foreign types need to go through the accessor to unique the witness
21542148
// table.

test/IRGen/Inputs/module.modulemap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,8 @@ module AtomicBoolModule {
2626
header "atomic_bool.h"
2727
export *
2828
}
29+
30+
module SynthesizedProtocol {
31+
header "synthesized_protocol.h"
32+
export *
33+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef SYNTHESIZED_PROTOCOL_H_
2+
#define SYNTHESIZED_PROTOCOL_H_
3+
4+
typedef enum __attribute__((flag_enum,enum_extensibility(open))) {
5+
One = 0x0001,
6+
Two = 0x0002,
7+
Four = 0x0004,
8+
Eight = 0x0008,
9+
Sixteen = 0x0010
10+
} Flags;
11+
12+
#endif /* SYNTHESIZED_PROTOCOL_H_ */

test/IRGen/protocol_synthesized.swift

Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
// RUN: %target-swift-frontend -emit-ir -parse-stdlib -module-name=Swift -I%S/Inputs %s | %FileCheck %s
2+
3+
// This module contains an enum that gets imported by the compiler as an
4+
// OptionSet. What we're trying to test here is that a *non-resilient*
5+
// synthesized protocol conformance works correctly; in particular, it needs
6+
// to emit a GenericWitnessTable in the ProtocolConformanceDescriptor so that
7+
// the initializer for the protocol witness table actually runs.
8+
// (see rdar://97290618)
9+
10+
import SynthesizedProtocol
11+
12+
// CHECK: @"$sSo5Flagsas9OptionSetSCMc" = linkonce_odr hidden constant { i32, i32, i32, i32, i16, i16, i32, i32 } { i32 trunc (i64 sub (i64 ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, %swift.protocol_requirement, %swift.protocol_requirement }>* @"$ss9OptionSetMp" to i64), i64 ptrtoint ({ i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc" to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32 }>* @"$sSo5FlagsaMn" to i64), i64 ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 1) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([3 x i8*]* @"$sSo5Flagsas9OptionSetSCWP" to i64), i64 ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 2) to i64)) to i32), i32 131200, i16 3, i16 1, i32 trunc (i64 sub (i64 ptrtoint (void (i8**, %swift.type*, i8**)* @"$sSo5Flagsas9OptionSetSCWI" to i64), i64 ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 6) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([16 x i8*]* @"$sSo5Flagsas9OptionSetSCMcMK" to i64), i64 ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 7) to i64)) to i32) }, section "__TEXT,__const", align 4
13+
14+
// Triggers the inclusion of the relevant ProtocolConformanceDescriptor
15+
public func doFlags(f: Flags) -> Any
16+
{
17+
return f.contains(.Two)
18+
}
19+
20+
// Because the standard library is usually resilient by default, we need to
21+
// implement a minimal subset of it for this test (so that it *isn't* resilient).
22+
// (If we use the resilient version, the compiler will always generate the
23+
// GenericWitnessTable because we're resilient, which invalidates this test.)
24+
25+
// .. Precedence ...............................................................
26+
27+
precedencegroup AssignmentPrecedence {
28+
assignment: true
29+
associativity: right
30+
}
31+
precedencegroup AdditionPrecedence {
32+
associativity: left
33+
higherThan: AssignmentPrecedence
34+
}
35+
precedencegroup MultiplicationPrecedence {
36+
associativity: left
37+
higherThan: AdditionPrecedence
38+
}
39+
40+
// .. Operators ................................................................
41+
42+
infix operator &: MultiplicationPrecedence
43+
infix operator |: AdditionPrecedence
44+
infix operator ^: AdditionPrecedence
45+
46+
infix operator &=: AssignmentPrecedence
47+
infix operator ^=: AssignmentPrecedence
48+
infix operator |=: AssignmentPrecedence
49+
50+
// .. ExpressibleByIntegerLiteral ..............................................
51+
52+
public protocol _ExpressibleByBuiltinIntegerLiteral {
53+
init(_builtinIntegerLiteral value: Builtin.IntLiteral)
54+
}
55+
56+
public protocol ExpressibleByIntegerLiteral {
57+
associatedtype IntegerLiteralType: _ExpressibleByBuiltinIntegerLiteral
58+
init(integerLiteral value: IntegerLiteralType)
59+
}
60+
61+
extension ExpressibleByIntegerLiteral
62+
where Self: _ExpressibleByBuiltinIntegerLiteral {
63+
@_transparent
64+
public init(integerLiteral value: Self) {
65+
self = value
66+
}
67+
}
68+
69+
// .. (U)Int32 .................................................................
70+
71+
@frozen
72+
public struct Int32 : FixedWidthInteger, _ExpressibleByBuiltinIntegerLiteral {
73+
public typealias IntegerLiteralType = Int32
74+
public var _value: Builtin.Int32
75+
76+
@_transparent
77+
public init(_builtinIntegerLiteral x: Builtin.IntLiteral) {
78+
_value = Builtin.s_to_s_checked_trunc_IntLiteral_Int32(x).0
79+
}
80+
81+
@_transparent
82+
public init(bitPattern x: UInt32) {
83+
_value = x._value
84+
}
85+
86+
@_transparent
87+
public init(_ _value: Builtin.Int32) {
88+
self._value = _value
89+
}
90+
91+
public static func |=(_ x: inout Int32, _ y: Int32) {
92+
x = Int32(Builtin.or_Int32(x._value, y._value))
93+
}
94+
public static func &=(_ x: inout Int32, _ y: Int32) {
95+
x = Int32(Builtin.and_Int32(x._value, y._value))
96+
}
97+
public static func ^=(_ x: inout Int32, _ y: Int32) {
98+
x = Int32(Builtin.xor_Int32(x._value, y._value))
99+
}
100+
}
101+
102+
@frozen
103+
public struct UInt32 : FixedWidthInteger, _ExpressibleByBuiltinIntegerLiteral {
104+
public typealias IntegerLiteralType = UInt32
105+
public var _value: Builtin.Int32
106+
107+
@_transparent
108+
public init(_builtinIntegerLiteral x: Builtin.IntLiteral) {
109+
_value = Builtin.s_to_u_checked_trunc_IntLiteral_Int32(x).0
110+
}
111+
112+
@_transparent
113+
public init(bitPattern x: Int32) {
114+
_value = x._value
115+
}
116+
117+
@_transparent
118+
public init(_ _value: Builtin.Int32) {
119+
self._value = _value
120+
}
121+
122+
public static func |=(x: inout UInt32, y: UInt32) {
123+
x = UInt32(Builtin.or_Int32(x._value, y._value))
124+
}
125+
public static func &=(x: inout UInt32, y: UInt32) {
126+
x = UInt32(Builtin.and_Int32(x._value, y._value))
127+
}
128+
public static func ^=(x: inout UInt32, y: UInt32) {
129+
x = UInt32(Builtin.xor_Int32(x._value, y._value))
130+
}
131+
}
132+
133+
// .. C types ..................................................................
134+
135+
typealias CInt = Int32
136+
typealias CUnsignedInt = UInt32
137+
138+
// .. SetAlgebra ...............................................................
139+
140+
public protocol SetAlgebra {
141+
associatedtype Element
142+
143+
func contains(_ member: Element) -> Any
144+
__consuming func union(_ other: __owned Self) -> Self
145+
__consuming func intersection(_ other: Self) -> Self
146+
__consuming func symmetricDifference(_ other: __owned Self) -> Self
147+
mutating func insert(_ newMember: __owned Element)
148+
mutating func remove(_ member: Element)
149+
mutating func update(with newMember: __owned Element)
150+
mutating func formUnion(_ other: __owned Self)
151+
mutating func formIntersection(_ other: Self)
152+
mutating func formSymmetricDifference(_ other: __owned Self)
153+
154+
static func |(_ lhs: Self, _ rhs: Self) -> Self
155+
static func &(_ lhs: Self, _ rhs: Self) -> Self
156+
static func ^(_ lhs: Self, _ rhs: Self) -> Self
157+
static func |=(_ lhs: inout Self, _ rhs: Self)
158+
static func &=(_ lhs: inout Self, _ rhs: Self)
159+
static func ^=(_ lhs: inout Self, _ rhs: Self)
160+
}
161+
162+
extension SetAlgebra {
163+
@_transparent
164+
public static func & (_ lhs: Self, _ rhs: Self) -> Self {
165+
return lhs.intersection(rhs)
166+
}
167+
168+
@_transparent
169+
public static func | (_ lhs: Self, _ rhs: Self) -> Self {
170+
return lhs.union(rhs)
171+
}
172+
173+
@_transparent
174+
public static func ^ (_ lhs: Self, _ rhs: Self) -> Self {
175+
return lhs.symmetricDifference(rhs)
176+
}
177+
178+
public static func &=(_ lhs: inout Self, _ rhs: Self) {
179+
lhs.formIntersection(rhs)
180+
}
181+
182+
public static func |=(_ lhs: inout Self, _ rhs: Self) {
183+
lhs.formUnion(rhs)
184+
}
185+
186+
public static func ^=(_ lhs: inout Self, _ rhs: Self) {
187+
lhs.formSymmetricDifference(rhs)
188+
}
189+
}
190+
191+
// .. RawRepresentable .........................................................
192+
193+
public protocol RawRepresentable<RawValue> {
194+
associatedtype RawValue
195+
init(rawValue: RawValue)
196+
var rawValue: RawValue { get }
197+
}
198+
199+
// .. OptionSet ................................................................
200+
201+
public protocol OptionSet: SetAlgebra, RawRepresentable {
202+
associatedtype Element = Self
203+
init(rawValue: RawValue)
204+
}
205+
206+
extension OptionSet {
207+
@inlinable
208+
public func union(_ other: Self) -> Self {
209+
var r = Self(rawValue: self.rawValue)
210+
r.formUnion(other)
211+
return r
212+
}
213+
214+
@inlinable
215+
public func intersection(_ other: Self) -> Self {
216+
var r = Self(rawValue: self.rawValue)
217+
r.formIntersection(other)
218+
return r
219+
}
220+
221+
@inlinable
222+
public func symmetricDifference(_ other: Self) -> Self {
223+
var r = Self(rawValue: self.rawValue)
224+
r.formSymmetricDifference(other)
225+
return r
226+
}
227+
}
228+
229+
extension OptionSet where Element == Self {
230+
public func contains(_ member: Self) -> Any {
231+
return self
232+
}
233+
234+
public mutating func insert(_ newMember: Element) {
235+
}
236+
237+
public mutating func remove(_ member: Element) {
238+
}
239+
240+
public mutating func update(with newMember: Element) {
241+
}
242+
}
243+
244+
extension OptionSet where RawValue: FixedWidthInteger {
245+
@inlinable
246+
public mutating func formUnion(_ other: Self) {
247+
self = Self(rawValue: self.rawValue | other.rawValue)
248+
}
249+
250+
@inlinable
251+
public mutating func formIntersection(_ other: Self) {
252+
self = Self(rawValue: self.rawValue & other.rawValue)
253+
}
254+
255+
@inlinable
256+
public mutating func formSymmetricDifference(_ other: Self) {
257+
self = Self(rawValue: self.rawValue ^ other.rawValue)
258+
}
259+
}
260+
261+
// .. FixedWidthInteger ........................................................
262+
263+
public protocol FixedWidthInteger {
264+
static func |(_ lhs: Self, _ rhs: Self) -> Self
265+
static func &(_ lhs: Self, _ rhs: Self) -> Self
266+
static func ^(_ lhs: Self, _ rhs: Self) -> Self
267+
static func |=(_ lhs: inout Self, _ rhs: Self)
268+
static func &=(_ lhs: inout Self, _ rhs: Self)
269+
static func ^=(_ lhs: inout Self, _ rhs: Self)
270+
}
271+
272+
extension FixedWidthInteger {
273+
@_transparent
274+
public static func & (_ lhs: Self, _ rhs: Self) -> Self {
275+
var lhs = lhs
276+
lhs &= rhs
277+
return lhs
278+
}
279+
280+
@_transparent
281+
public static func | (_ lhs: Self, _ rhs: Self) -> Self {
282+
var lhs = lhs
283+
lhs |= rhs
284+
return lhs
285+
}
286+
287+
@_transparent
288+
public static func ^ (_ lhs: Self, _ rhs: Self) -> Self {
289+
var lhs = lhs
290+
lhs ^= rhs
291+
return lhs
292+
}
293+
}
294+
295+
// .. ExpressibleByArrayLiteral ................................................
296+
297+
public protocol ExpressibleByArrayLiteral {
298+
}
299+
300+
// .. Equatable ................................................................
301+
302+
public protocol Equatable {
303+
}

0 commit comments

Comments
 (0)