diff --git a/lib/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp index a32423aeb18a9..0fc26a1c02f70 100644 --- a/lib/SIL/IR/SILFunctionType.cpp +++ b/lib/SIL/IR/SILFunctionType.cpp @@ -2955,8 +2955,10 @@ static CanSILFunctionType getSILFunctionTypeForInitAccessor( // Make a new 'self' parameter. if (!declContext->isLocalContext()) { - auto selfInterfaceType = - MetatypeType::get(declContext->getSelfInterfaceType()); + auto selfInterfaceType = MetatypeType::get( + (genericSig) + ? declContext->getSelfInterfaceType()->getReducedType(genericSig) + : declContext->getSelfTypeInContext()); AbstractionPattern origSelfType(genericSig, selfInterfaceType->getCanonicalType()); auto loweredSelfType = TC.getLoweredType( diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index 37b5205224f8b..e39ebbfc0b8e5 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -1931,11 +1931,6 @@ void SILGenFunction::emitAssignOrInit(SILLocation loc, ManagedValue selfValue, auto initTy = initFRef->getType().castTo(); - // If there are substitutions we need to emit partial apply to - // apply substitutions to the init accessor reference type. - initTy = initTy->substGenericArgs(SGM.M, substitutions, - getTypeExpansionContext()); - // Emit partial apply with self metatype argument to produce a substituted // init accessor reference. auto selfTy = selfValue.getType().getASTType(); @@ -1949,8 +1944,9 @@ void SILGenFunction::emitAssignOrInit(SILLocation loc, ManagedValue selfValue, selfMetatype = B.createMetatype(loc, getLoweredType(metatypeTy)); } - auto expectedSelfTy = initAccessor->getDeclContext()->getSelfInterfaceType() - .subst(substitutions); + auto expectedSelfTy = + initAccessor->getDeclContext()->getSelfInterfaceType().subst( + substitutions); // This should only happen in the invalid case where we attempt to initialize // superclass storage from a subclass initializer. However, we shouldn't @@ -1960,6 +1956,14 @@ void SILGenFunction::emitAssignOrInit(SILLocation loc, ManagedValue selfValue, selfMetatype = B.createUpcast(loc, selfMetatype, getLoweredType(MetatypeType::get(expectedSelfTy))); } + + if (auto invocationSig = initTy->getInvocationGenericSignature()) { + if (invocationSig->areAllParamsConcrete()) + substitutions = SubstitutionMap(); + } else { + substitutions = SubstitutionMap(); + } + PartialApplyInst *initPAI = B.createPartialApply(loc, initFRef, substitutions, selfMetatype, ParameterConvention::Direct_Guaranteed, diff --git a/test/SILOptimizer/init_accessor_in_constrained_extensions.swift b/test/SILOptimizer/init_accessor_in_constrained_extensions.swift new file mode 100644 index 0000000000000..a8337ee955b4b --- /dev/null +++ b/test/SILOptimizer/init_accessor_in_constrained_extensions.swift @@ -0,0 +1,73 @@ +// 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 + +struct S1 { +} + +extension S1 where T == Int { + class Test { + var test1: Int { + init(initialValue) { } + set {} + get { 0 } + } + + var test2: T { + init(initialValue) { } + set {} + get { 0 } + } + + // CHECK-LABEL: sil hidden [ossa] @$s23assign_or_init_lowering2S1VAASiRszlE4TestCAEySi_Gycfc : $@convention(method) (@owned S1.Test) -> @owned S1.Test + // + // CHECK: [[TEST1_INIT_REF:%.*]] = function_ref @$s23assign_or_init_lowering2S1VAASiRszlE4TestC5test1Sivi : $@convention(thin) (Int, @thick S1.Test.Type) -> () + // CHECK-NEXT: [[SELF:%.*]] = value_metatype $@thick S1.Test.Type, {{.*}} : $S1.Test + // CHECK-NEXT: [[TEST1_INIT_REF_WITH_SELF_APPLIED:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[TEST1_INIT_REF]]([[SELF]]) : $@convention(thin) (Int, @thick S1.Test.Type) -> () + // CHECK: assign_or_init [init] #S1.Test.test1, self {{.*}} : $S1.Test, value {{.*}} : $Int, init [[TEST1_INIT_REF_WITH_SELF_APPLIED]] : $@noescape @callee_guaranteed (Int) -> (), set {{.*}} : $@noescape @callee_guaranteed (Int) -> () + // + // CHECK: [[TEST2_INIT_REF:%.*]] = function_ref @$s23assign_or_init_lowering2S1VAASiRszlE4TestC5test2Sivi : $@convention(thin) (Int, @thick S1.Test.Type) -> () + // CHECK-NEXT: [[SELF:%.*]] = value_metatype $@thick S1.Test.Type, {{.*}} : $S1.Test + // CHECK-NEXT: [[TEST2_INIT_REF_WITH_SELF_APPLIED:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[TEST2_INIT_REF]]([[SELF]]) : $@convention(thin) (Int, @thick S1.Test.Type) -> () + // CHECK: assign_or_init [init] #S1.Test.test2, self {{.*}} : $S1.Test, value {{.*}} : $Int, init [[TEST2_INIT_REF_WITH_SELF_APPLIED]] : $@noescape @callee_guaranteed (Int) -> (), set {{.*}} : $@noescape @callee_guaranteed (Int) -> () + // CHECK: } // end sil function '$s23assign_or_init_lowering2S1VAASiRszlE4TestCAEySi_Gycfc' + init() { + test1 = 0 + test2 = 1 + } + } +} + +struct S2 { +} + +extension S2 where T == Int { + class Test { + var test1: T { + init(initialValue) { } + set {} + get { 0 } + } + + var test2: U { + init(initialValue) { } + set {} + get { fatalError() } + } + + // CHECK-LABEL: sil hidden [ossa] @$s23assign_or_init_lowering2S2VAASiRszrlE4TestC1uAEySiq__Gq__tcfc : $@convention(method) (@in U, @owned S2.Test) -> @owned S2.Test { + // + // CHECK: [[TEST1_INIT_REF:%.*]] = function_ref @$s23assign_or_init_lowering2S2VAASiRszrlE4TestC5test1Sivi : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 == Int> (Int, @thick S2.Test.Type) -> () + // CHECK-NEXT: [[SELF:%.*]] = value_metatype $@thick S2.Test.Type, {{.*}} : $S2.Test + // CHECK-NEXT: [[TEST1_INIT_REF_WITH_SELF_APPLIED:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[TEST1_INIT_REF]]([[SELF]]) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 == Int> (Int, @thick S2.Test.Type) -> () + // CHECK: assign_or_init [init] #S2.Test.test1, self {{.*}} : $S2.Test, value {{.*}} : $Int, init [[TEST1_INIT_REF_WITH_SELF_APPLIED]] : $@noescape @callee_guaranteed (Int) -> (), set {{.*}} : $@noescape @callee_guaranteed (Int) -> () + // + // 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.Test.Type) -> () + // CHECK-NEXT: [[SELF:%.*]] = value_metatype $@thick S2.Test.Type, {{.*}} : $S2.Test + // CHECK-NEXT: [[TEST2_INIT_REF_WITH_SELF_APPLIED:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[TEST2_INIT_REF]]([[SELF]]) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 == Int> (@in τ_0_1, @thick S2.Test.Type) -> () + // CHECK: assign_or_init [init] #S2.Test.test2, self {{.*}} : $S2.Test, value {{.*}} : $*U, init [[TEST2_INIT_REF_WITH_SELF_APPLIED]] : $@noescape @callee_guaranteed (@in U) -> (), set {{.*}} : $@noescape @callee_guaranteed (@in U) -> () + // CHECK: } // end sil function '$s23assign_or_init_lowering2S2VAASiRszrlE4TestC1uAEySiq__Gq__tcfc' + init(u: U) { + test1 = 0 + test2 = u + } + } +}