Skip to content

Commit f4f99ba

Browse files
committed
[SIL] Allow init accessor declarations in constrained extensions
While emitting a function type for init accessor reference "self" parameter should always be mapped into the context. When referencing an init accessor in an constrained extension context, substitution map for the original property cannot always be used when applying "self" parameter, emission logic eeds to check whether context makes the init accessor reference "concrete" and if so, avoid using the substitution map when forming partial application for "self" parameter. Resolves: rdar://160816474
1 parent 27598b4 commit f4f99ba

File tree

3 files changed

+88
-9
lines changed

3 files changed

+88
-9
lines changed

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2955,8 +2955,10 @@ static CanSILFunctionType getSILFunctionTypeForInitAccessor(
29552955

29562956
// Make a new 'self' parameter.
29572957
if (!declContext->isLocalContext()) {
2958-
auto selfInterfaceType =
2959-
MetatypeType::get(declContext->getSelfInterfaceType());
2958+
auto selfInterfaceType = MetatypeType::get(
2959+
(genericSig)
2960+
? declContext->getSelfInterfaceType()->getReducedType(genericSig)
2961+
: declContext->getSelfTypeInContext());
29602962
AbstractionPattern origSelfType(genericSig,
29612963
selfInterfaceType->getCanonicalType());
29622964
auto loweredSelfType = TC.getLoweredType(

lib/SILGen/SILGenFunction.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,11 +1931,6 @@ void SILGenFunction::emitAssignOrInit(SILLocation loc, ManagedValue selfValue,
19311931

19321932
auto initTy = initFRef->getType().castTo<SILFunctionType>();
19331933

1934-
// If there are substitutions we need to emit partial apply to
1935-
// apply substitutions to the init accessor reference type.
1936-
initTy = initTy->substGenericArgs(SGM.M, substitutions,
1937-
getTypeExpansionContext());
1938-
19391934
// Emit partial apply with self metatype argument to produce a substituted
19401935
// init accessor reference.
19411936
auto selfTy = selfValue.getType().getASTType();
@@ -1949,8 +1944,9 @@ void SILGenFunction::emitAssignOrInit(SILLocation loc, ManagedValue selfValue,
19491944
selfMetatype = B.createMetatype(loc, getLoweredType(metatypeTy));
19501945
}
19511946

1952-
auto expectedSelfTy = initAccessor->getDeclContext()->getSelfInterfaceType()
1953-
.subst(substitutions);
1947+
auto expectedSelfTy =
1948+
initAccessor->getDeclContext()->getSelfInterfaceType().subst(
1949+
substitutions);
19541950

19551951
// This should only happen in the invalid case where we attempt to initialize
19561952
// superclass storage from a subclass initializer. However, we shouldn't
@@ -1960,6 +1956,14 @@ void SILGenFunction::emitAssignOrInit(SILLocation loc, ManagedValue selfValue,
19601956
selfMetatype = B.createUpcast(loc, selfMetatype,
19611957
getLoweredType(MetatypeType::get(expectedSelfTy)));
19621958
}
1959+
1960+
if (auto invocationSig = initTy->getInvocationGenericSignature()) {
1961+
if (invocationSig->areAllParamsConcrete())
1962+
substitutions = SubstitutionMap();
1963+
} else {
1964+
substitutions = SubstitutionMap();
1965+
}
1966+
19631967
PartialApplyInst *initPAI =
19641968
B.createPartialApply(loc, initFRef, substitutions, selfMetatype,
19651969
ParameterConvention::Direct_Guaranteed,
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// RUN: %target-swift-frontend -Xllvm -sil-print-types -Xllvm -sil-print-after=definite-init -emit-sil -module-name assign_or_init_lowering %s -o /dev/null 2>&1 | %FileCheck %s
2+
3+
struct S1<T> {
4+
}
5+
6+
extension S1 where T == Int {
7+
class Test {
8+
var test1: Int {
9+
init(initialValue) { }
10+
set {}
11+
get { 0 }
12+
}
13+
14+
var test2: T {
15+
init(initialValue) { }
16+
set {}
17+
get { 0 }
18+
}
19+
20+
// CHECK-LABEL: sil hidden [ossa] @$s23assign_or_init_lowering2S1VAASiRszlE4TestCAEySi_Gycfc : $@convention(method) (@owned S1<Int>.Test) -> @owned S1<Int>.Test
21+
//
22+
// CHECK: [[TEST1_INIT_REF:%.*]] = function_ref @$s23assign_or_init_lowering2S1VAASiRszlE4TestC5test1Sivi : $@convention(thin) (Int, @thick S1<Int>.Test.Type) -> ()
23+
// CHECK-NEXT: [[SELF:%.*]] = value_metatype $@thick S1<Int>.Test.Type, {{.*}} : $S1<Int>.Test
24+
// CHECK-NEXT: [[TEST1_INIT_REF_WITH_SELF_APPLIED:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[TEST1_INIT_REF]]([[SELF]]) : $@convention(thin) (Int, @thick S1<Int>.Test.Type) -> ()
25+
// CHECK: assign_or_init [init] #S1.Test.test1, self {{.*}} : $S1<Int>.Test, value {{.*}} : $Int, init [[TEST1_INIT_REF_WITH_SELF_APPLIED]] : $@noescape @callee_guaranteed (Int) -> (), set {{.*}} : $@noescape @callee_guaranteed (Int) -> ()
26+
//
27+
// CHECK: [[TEST2_INIT_REF:%.*]] = function_ref @$s23assign_or_init_lowering2S1VAASiRszlE4TestC5test2Sivi : $@convention(thin) (Int, @thick S1<Int>.Test.Type) -> ()
28+
// CHECK-NEXT: [[SELF:%.*]] = value_metatype $@thick S1<Int>.Test.Type, {{.*}} : $S1<Int>.Test
29+
// CHECK-NEXT: [[TEST2_INIT_REF_WITH_SELF_APPLIED:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[TEST2_INIT_REF]]([[SELF]]) : $@convention(thin) (Int, @thick S1<Int>.Test.Type) -> ()
30+
// CHECK: assign_or_init [init] #S1.Test.test2, self {{.*}} : $S1<Int>.Test, value {{.*}} : $Int, init [[TEST2_INIT_REF_WITH_SELF_APPLIED]] : $@noescape @callee_guaranteed (Int) -> (), set {{.*}} : $@noescape @callee_guaranteed (Int) -> ()
31+
// CHECK: } // end sil function '$s23assign_or_init_lowering2S1VAASiRszlE4TestCAEySi_Gycfc'
32+
init() {
33+
test1 = 0
34+
test2 = 1
35+
}
36+
}
37+
}
38+
39+
struct S2<T, U> {
40+
}
41+
42+
extension S2 where T == Int {
43+
class Test {
44+
var test1: T {
45+
init(initialValue) { }
46+
set {}
47+
get { 0 }
48+
}
49+
50+
var test2: U {
51+
init(initialValue) { }
52+
set {}
53+
get { fatalError() }
54+
}
55+
56+
// CHECK-LABEL: sil hidden [ossa] @$s23assign_or_init_lowering2S2VAASiRszrlE4TestC1uAEySiq__Gq__tcfc : $@convention(method) <T, U where T == Int> (@in U, @owned S2<Int, U>.Test) -> @owned S2<Int, U>.Test {
57+
//
58+
// CHECK: [[TEST1_INIT_REF:%.*]] = function_ref @$s23assign_or_init_lowering2S2VAASiRszrlE4TestC5test1Sivi : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 == Int> (Int, @thick S2<Int, τ_0_1>.Test.Type) -> ()
59+
// CHECK-NEXT: [[SELF:%.*]] = value_metatype $@thick S2<Int, U>.Test.Type, {{.*}} : $S2<Int, U>.Test
60+
// CHECK-NEXT: [[TEST1_INIT_REF_WITH_SELF_APPLIED:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[TEST1_INIT_REF]]<Int, U>([[SELF]]) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 == Int> (Int, @thick S2<Int, τ_0_1>.Test.Type) -> ()
61+
// CHECK: assign_or_init [init] #S2.Test.test1, self {{.*}} : $S2<Int, U>.Test, value {{.*}} : $Int, init [[TEST1_INIT_REF_WITH_SELF_APPLIED]] : $@noescape @callee_guaranteed (Int) -> (), set {{.*}} : $@noescape @callee_guaranteed (Int) -> ()
62+
//
63+
// CHECK: [[TEST2_INIT_REF:%.*]] = function_ref @$s23assign_or_init_lowering2S2VAASiRszrlE4TestC5test2q_vi : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 == Int> (@in τ_0_1, @thick S2<Int, τ_0_1>.Test.Type) -> ()
64+
// CHECK-NEXT: [[SELF:%.*]] = value_metatype $@thick S2<Int, U>.Test.Type, {{.*}} : $S2<Int, U>.Test
65+
// CHECK-NEXT: [[TEST2_INIT_REF_WITH_SELF_APPLIED:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[TEST2_INIT_REF]]<Int, U>([[SELF]]) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 == Int> (@in τ_0_1, @thick S2<Int, τ_0_1>.Test.Type) -> ()
66+
// CHECK: assign_or_init [init] #S2.Test.test2, self {{.*}} : $S2<Int, U>.Test, value {{.*}} : $*U, init [[TEST2_INIT_REF_WITH_SELF_APPLIED]] : $@noescape @callee_guaranteed (@in U) -> (), set {{.*}} : $@noescape @callee_guaranteed (@in U) -> ()
67+
// CHECK: } // end sil function '$s23assign_or_init_lowering2S2VAASiRszrlE4TestC1uAEySiq__Gq__tcfc'
68+
init(u: U) {
69+
test1 = 0
70+
test2 = u
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)