Skip to content

Commit 6992712

Browse files
committed
IRGen: Fix specialized conformances with abstract conditional requirements in the partial apply forwarder
We need to add abstract requirements of the conditional requirements. rdar://59456064
1 parent 6c19d6f commit 6992712

File tree

4 files changed

+108
-5
lines changed

4 files changed

+108
-5
lines changed

lib/IRGen/GenFunc.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,8 +1292,9 @@ Optional<StackAddress> irgen::emitFunctionPartialApplication(
12921292
SmallVector<ParameterConvention, 4> argConventions;
12931293

12941294
// Reserve space for polymorphic bindings.
1295-
auto bindings = NecessaryBindings::forFunctionInvocations(IGF.IGM,
1296-
origType, subs);
1295+
auto bindings =
1296+
NecessaryBindings::forPartialApplyForwarder(IGF.IGM, origType, subs);
1297+
12971298
if (!bindings.empty()) {
12981299
hasSingleSwiftRefcountedContext = No;
12991300
auto bindingsSize = bindings.getBufferSize(IGF.IGM);

lib/IRGen/GenProto.cpp

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2732,9 +2732,43 @@ void NecessaryBindings::addTypeMetadata(CanType type) {
27322732
Requirements.insert({type, nullptr});
27332733
}
27342734

2735+
/// Add all the abstract conditional conformances in the specialized
2736+
/// conformance to the \p requirements.
2737+
static void addAbstractConditionalRequirements(
2738+
SpecializedProtocolConformance *specializedConformance,
2739+
llvm::SetVector<GenericRequirement> &requirements) {
2740+
auto module = specializedConformance->getDeclContext()->getParentModule();
2741+
auto subMap = specializedConformance->getSubstitutions(module);
2742+
auto condRequirements =
2743+
specializedConformance->getConditionalRequirementsIfAvailable();
2744+
if (!condRequirements)
2745+
return;
2746+
2747+
for (auto req : *condRequirements) {
2748+
if (req.getKind() != RequirementKind::Conformance)
2749+
continue;
2750+
auto *proto =
2751+
req.getSecondType()->castTo<ProtocolType>()->getDecl();
2752+
auto ty = req.getFirstType()->getCanonicalType();
2753+
auto conformance = subMap.lookupConformance(ty, proto);
2754+
if (!conformance.isAbstract())
2755+
continue;
2756+
requirements.insert({ty, conformance.getAbstract()});
2757+
}
2758+
}
2759+
27352760
void NecessaryBindings::addProtocolConformance(CanType type,
27362761
ProtocolConformanceRef conf) {
2737-
if (!conf.isAbstract()) return;
2762+
if (!conf.isAbstract()) {
2763+
auto specializedConf =
2764+
dyn_cast<SpecializedProtocolConformance>(conf.getConcrete());
2765+
// The partial apply forwarder does not have the context to reconstruct
2766+
// abstract conditional conformance requirements.
2767+
if (forPartialApply && specializedConf) {
2768+
addAbstractConditionalRequirements(specializedConf, Requirements);
2769+
}
2770+
return;
2771+
}
27382772
assert(isa<ArchetypeType>(type));
27392773

27402774
// TODO: pass something about the root conformance necessary to
@@ -2925,7 +2959,24 @@ NecessaryBindings
29252959
NecessaryBindings::forFunctionInvocations(IRGenModule &IGM,
29262960
CanSILFunctionType origType,
29272961
SubstitutionMap subs) {
2962+
return computeBindings(IGM, origType, subs,
2963+
false /*forPartialApplyForwarder*/);
2964+
}
2965+
2966+
NecessaryBindings
2967+
NecessaryBindings::forPartialApplyForwarder(IRGenModule &IGM,
2968+
CanSILFunctionType origType,
2969+
SubstitutionMap subs) {
2970+
return computeBindings(IGM, origType, subs,
2971+
true /*forPartialApplyForwarder*/);
2972+
}
2973+
2974+
NecessaryBindings NecessaryBindings::computeBindings(
2975+
IRGenModule &IGM, CanSILFunctionType origType, SubstitutionMap subs,
2976+
bool forPartialApplyForwarder) {
2977+
29282978
NecessaryBindings bindings;
2979+
bindings.forPartialApply = forPartialApplyForwarder;
29292980

29302981
// Bail out early if we don't have polymorphic parameters.
29312982
if (!hasPolymorphicParameters(origType))

lib/IRGen/NecessaryBindings.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ namespace irgen {
4242
class NecessaryBindings {
4343
llvm::SetVector<GenericRequirement> Requirements;
4444

45+
46+
/// Are the bindings to be computed for a partial apply forwarder.
47+
/// In the case this is true we need to store/restore the conformance of a
48+
/// specialized type with conditional conformance because the conditional
49+
/// requirements are not available in the partial apply forwarder.
50+
bool forPartialApply = false;
51+
4552
public:
4653
NecessaryBindings() = default;
4754

@@ -50,7 +57,10 @@ class NecessaryBindings {
5057
static NecessaryBindings forFunctionInvocations(IRGenModule &IGM,
5158
CanSILFunctionType origType,
5259
SubstitutionMap subs);
53-
60+
static NecessaryBindings forPartialApplyForwarder(IRGenModule &IGM,
61+
CanSILFunctionType origType,
62+
SubstitutionMap subs);
63+
5464
/// Add whatever information is necessary to reconstruct type metadata
5565
/// for the given type.
5666
void addTypeMetadata(CanType type);
@@ -84,6 +94,11 @@ class NecessaryBindings {
8494
const llvm::SetVector<GenericRequirement> &getRequirements() const {
8595
return Requirements;
8696
}
97+
private:
98+
static NecessaryBindings computeBindings(IRGenModule &IGM,
99+
CanSILFunctionType origType,
100+
SubstitutionMap subs,
101+
bool forPartialApplyForwarder);
87102
};
88103

89104
} // end namespace irgen

test/IRGen/partial_apply_forwarder.sil

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ sil hidden_external @takingQAndS : $@convention(thin) <τ_0_0 where τ_0_0 : Q>
205205
// CHECK: [[WBREF:%.*]] = bitcast %T23partial_apply_forwarder7WeakBoxC* [[WB]] to %swift.refcounted*
206206
// CHECK: call %swift.refcounted* @swift_retain(%swift.refcounted* returned [[WBREF]])
207207
// CHECK: [[TYADDR:%.*]] = getelementptr inbounds %T23partial_apply_forwarder7WeakBoxC, %T23partial_apply_forwarder7WeakBoxC* [[WB]], i32 0, i32 0, i32 0
208-
// CHECK: [[TY:%.*]] = load %swift.type*, %swift.type** [[TYADDR]]
208+
// CHECK: [[TY:%.*]] = load %swift.type*, %swift.type** [[TYADDR]]
209209
// CHECK: %.asUnsubstituted = bitcast %T23partial_apply_forwarder7WeakBoxC* [[WB]] to %T23partial_apply_forwarder7WeakBoxC.1*
210210
// CHECK: call void @swift_release(%swift.refcounted* %0)
211211
// CHECK: [[GENPARAMSADDR:%.*]] = bitcast %swift.type* [[TY]] to %swift.type**
@@ -248,6 +248,42 @@ bb0:
248248
// CHECK: entry:
249249
// CHECK: ret { i8*, %swift.refcounted* } { i8* bitcast ({ %{{.*}}Empty{{.*}}*, i8*, %swift.refcounted* } (%{{.*}}Empty{{.*}}*, %swift.refcounted*)* @"{{.*}}returns_closure{{.*}}" to i8*), %swift.refcounted* null }
250250

251+
protocol MyEquatable {
252+
static func isEqual (lhs: Self, rhs: Self) -> Builtin.Int1
253+
}
254+
255+
public struct Inner<Element> {
256+
public init()
257+
public init(_ e: Element)
258+
}
259+
260+
extension Inner : MyEquatable where Element : MyEquatable {
261+
public static func isEqual (lhs: Inner<Element>, rhs: Inner<Element>) -> Builtin.Int1
262+
}
263+
264+
public struct Outer<Value> {
265+
init()
266+
}
267+
268+
extension Outer : MyEquatable where Value : MyEquatable {
269+
public static func isEqual (lhs: Outer<Value>, rhs: Outer<Value>) -> Builtin.Int1
270+
}
271+
272+
sil @$closure : $@convention(method) <Value where Value : MyEquatable> (Outer<Value>, Outer<Value>, @thin Outer<Value>.Type) -> Builtin.Int1
273+
274+
sil @$dont_crash_test_caputre_specialized_conditional_conformance : $@convention(thin) <Element where Element : MyEquatable> (Outer<Inner<Element>>) -> () {
275+
bb0(%0 : $Outer<Inner<Element>>):
276+
%2 = alloc_stack $Outer<Inner<Element>>
277+
store %0 to %2 : $*Outer<Inner<Element>>
278+
%4 = metatype $@thin Outer<Inner<Element>>.Type
279+
%5 = function_ref @$closure : $@convention(method) <τ_0_0 where τ_0_0 : MyEquatable> (Outer<τ_0_0>, Outer<τ_0_0>, @thin Outer<τ_0_0>.Type) -> Builtin.Int1
280+
%6 = partial_apply [callee_guaranteed] %5<Inner<Element>>(%4) : $@convention(method) <τ_0_0 where τ_0_0 : MyEquatable> (Outer<τ_0_0>, Outer<τ_0_0>, @thin Outer<τ_0_0>.Type) -> Builtin.Int1
281+
strong_release %6 : $@callee_guaranteed (Outer<Inner<Element>>, Outer<Inner<Element>>) -> Builtin.Int1
282+
dealloc_stack %2 : $*Outer<Inner<Element>>
283+
%15 = tuple ()
284+
return %15 : $()
285+
}
286+
251287
sil_vtable WeakBox {}
252288
sil_vtable C {}
253289
sil_vtable D {}

0 commit comments

Comments
 (0)