Skip to content

Commit 626e6e0

Browse files
Merge pull request swiftlang#29912 from aschwaighofer/irgen_partial_apply_forwarder_specialized_conformance_with_abstract_conditional_requirements
IRGen: Fix specialized conformances with abstract conditional requirements in the partial apply forwarder
2 parents 79716ef + 6992712 commit 626e6e0

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
@@ -2738,9 +2738,43 @@ void NecessaryBindings::addTypeMetadata(CanType type) {
27382738
Requirements.insert({type, nullptr});
27392739
}
27402740

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

27462780
// TODO: pass something about the root conformance necessary to
@@ -2931,7 +2965,24 @@ NecessaryBindings
29312965
NecessaryBindings::forFunctionInvocations(IRGenModule &IGM,
29322966
CanSILFunctionType origType,
29332967
SubstitutionMap subs) {
2968+
return computeBindings(IGM, origType, subs,
2969+
false /*forPartialApplyForwarder*/);
2970+
}
2971+
2972+
NecessaryBindings
2973+
NecessaryBindings::forPartialApplyForwarder(IRGenModule &IGM,
2974+
CanSILFunctionType origType,
2975+
SubstitutionMap subs) {
2976+
return computeBindings(IGM, origType, subs,
2977+
true /*forPartialApplyForwarder*/);
2978+
}
2979+
2980+
NecessaryBindings NecessaryBindings::computeBindings(
2981+
IRGenModule &IGM, CanSILFunctionType origType, SubstitutionMap subs,
2982+
bool forPartialApplyForwarder) {
2983+
29342984
NecessaryBindings bindings;
2985+
bindings.forPartialApply = forPartialApplyForwarder;
29352986

29362987
// Bail out early if we don't have polymorphic parameters.
29372988
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)