Skip to content

Commit 25789fd

Browse files
authored
Merge pull request #70768 from slavapestov/fix-119822466
SIL: Fix DynamicSelfType references from inside init accessor
2 parents 74fbae1 + 1a06313 commit 25789fd

File tree

8 files changed

+244
-138
lines changed

8 files changed

+244
-138
lines changed

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2434,6 +2434,16 @@ static CanSILFunctionType getSILFunctionTypeForInitAccessor(
24342434
ParameterConvention::Indirect_Inout));
24352435
}
24362436

2437+
// Make a new 'self' parameter.
2438+
auto selfInterfaceType = MetatypeType::get(
2439+
accessor->getDeclContext()->getSelfInterfaceType());
2440+
AbstractionPattern origSelfType(genericSig,
2441+
selfInterfaceType->getCanonicalType());
2442+
auto loweredSelfType = TC.getLoweredType(
2443+
origSelfType, selfInterfaceType->getCanonicalType(), context);
2444+
inputs.push_back(SILParameterInfo(loweredSelfType.getASTType(),
2445+
ParameterConvention::Direct_Unowned));
2446+
24372447
SmallVector<SILResultInfo, 8> results;
24382448

24392449
// initialized properties appear as `@out` results because they are

lib/SILGen/SILGenConstructor.cpp

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -91,29 +91,23 @@ static ManagedValue emitManagedParameter(SILGenFunction &SGF,
9191
}
9292

9393
static SILValue emitConstructorMetatypeArg(SILGenFunction &SGF,
94-
ValueDecl *ctor) {
94+
ValueDecl *decl) {
9595
// In addition to the declared arguments, the constructor implicitly takes
9696
// the metatype as its first argument, like a static function.
97-
auto ctorFnType = ctor->getInterfaceType()->castTo<AnyFunctionType>();
98-
assert(ctorFnType->getParams().size() == 1 &&
99-
"more than one self parameter?");
100-
auto param = ctorFnType->getParams()[0];
101-
assert(!param.isVariadic() && !param.isInOut());
102-
Type metatype = param.getPlainType();
103-
auto *DC = ctor->getInnermostDeclContext();
104-
auto &AC = SGF.getASTContext();
97+
auto metatypeTy = MetatypeType::get(
98+
decl->getDeclContext()->getSelfInterfaceType());
99+
auto *DC = decl->getInnermostDeclContext();
100+
auto &ctx = SGF.getASTContext();
105101
auto VD =
106-
new (AC) ParamDecl(SourceLoc(), SourceLoc(),
107-
AC.getIdentifier("$metatype"), SourceLoc(),
108-
AC.getIdentifier("$metatype"), DC);
102+
new (ctx) ParamDecl(SourceLoc(), SourceLoc(),
103+
ctx.getIdentifier("$metatype"), SourceLoc(),
104+
ctx.getIdentifier("$metatype"), DC);
109105
VD->setSpecifier(ParamSpecifier::Default);
110-
VD->setInterfaceType(metatype);
106+
VD->setInterfaceType(metatypeTy);
111107

112-
SGF.AllocatorMetatype = SGF.F.begin()->createFunctionArgument(
113-
SGF.getLoweredTypeForFunctionArgument(DC->mapTypeIntoContext(metatype)),
108+
return SGF.F.begin()->createFunctionArgument(
109+
SGF.getLoweredTypeForFunctionArgument(DC->mapTypeIntoContext(metatypeTy)),
114110
VD);
115-
116-
return SGF.AllocatorMetatype;
117111
}
118112

119113
// FIXME: Consolidate this with SILGenProlog
@@ -273,7 +267,8 @@ static RValue maybeEmitPropertyWrapperInitFromValue(
273267
static void
274268
emitApplyOfInitAccessor(SILGenFunction &SGF, SILLocation loc,
275269
AccessorDecl *accessor, SILValue selfValue,
276-
SILType selfTy, RValue &&initialValue) {
270+
Type selfIfaceTy, SILType selfTy,
271+
RValue &&initialValue) {
277272
SmallVector<SILValue> arguments;
278273

279274
auto emitFieldReference = [&](VarDecl *field, bool forInit = false) {
@@ -297,6 +292,10 @@ emitApplyOfInitAccessor(SILGenFunction &SGF, SILLocation loc,
297292
arguments.push_back(emitFieldReference(property));
298293
}
299294

295+
// The `self` metatype.
296+
auto metatypeTy = MetatypeType::get(accessor->mapTypeIntoContext(selfIfaceTy));
297+
arguments.push_back(SGF.B.createMetatype(loc, SGF.getLoweredType(metatypeTy)));
298+
300299
SubstitutionMap subs;
301300
if (auto *env =
302301
accessor->getDeclContext()->getGenericEnvironmentOfContext()) {
@@ -387,7 +386,7 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
387386
loweredParams));
388387
}
389388

390-
emitConstructorMetatypeArg(SGF, ctor);
389+
SGF.AllocatorMetatype = emitConstructorMetatypeArg(SGF, ctor);
391390
(void) loweredParams.claimNext();
392391
loweredParams.finish();
393392

@@ -418,8 +417,8 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
418417
assert(elti != eltEnd &&
419418
"number of args does not match number of fields");
420419

421-
emitApplyOfInitAccessor(SGF, Loc, initAccessor, resultSlot, selfTy,
422-
std::move(*elti));
420+
emitApplyOfInitAccessor(SGF, Loc, initAccessor, resultSlot,
421+
selfIfaceTy, selfTy, std::move(*elti));
423422
++elti;
424423
continue;
425424
}
@@ -666,7 +665,7 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
666665
ctor->getEffectiveThrownErrorType(),
667666
ctor->getThrowsLoc(),
668667
/*ignored parameters*/ 1);
669-
emitConstructorMetatypeArg(*this, ctor);
668+
AllocatorMetatype = emitConstructorMetatypeArg(*this, ctor);
670669

671670
// Make sure we've hopped to the right global actor, if any.
672671
if (ctor->hasAsync()) {
@@ -897,7 +896,7 @@ void SILGenFunction::emitEnumConstructor(EnumElementDecl *element) {
897896
}
898897

899898
// Emit the metatype argument.
900-
emitConstructorMetatypeArg(*this, element);
899+
AllocatorMetatype = emitConstructorMetatypeArg(*this, element);
901900
(void) loweredParams.claimNext();
902901
loweredParams.finish();
903902

@@ -957,7 +956,8 @@ void SILGenFunction::emitClassConstructorAllocator(ConstructorDecl *ctor) {
957956
if (ctor->requiresUnavailableDeclABICompatibilityStubs())
958957
emitApplyOfUnavailableCodeReached();
959958

960-
SILValue selfMetaValue = emitConstructorMetatypeArg(*this, ctor);
959+
AllocatorMetatype = emitConstructorMetatypeArg(*this, ctor);
960+
SILValue selfMetaValue = AllocatorMetatype;
961961

962962
// Allocate the "self" value.
963963
VarDecl *selfDecl = ctor->getImplicitSelfDecl();
@@ -1758,25 +1758,30 @@ void SILGenFunction::emitInitAccessor(AccessorDecl *accessor) {
17581758

17591759
// Emit `newValue` argument.
17601760
emitBasicProlog(accessor,
1761-
accessor->getParameters(), /*selfParam=*/nullptr,
1761+
accessor->getParameters(),
1762+
/*selfParam=*/nullptr,
17621763
TupleType::getEmpty(F.getASTContext()),
17631764
/*errorType=*/llvm::None,
17641765
/*throwsLoc=*/SourceLoc(),
17651766
/*ignored parameters*/
1766-
accessedProperties.size());
1767+
accessedProperties.size() + 1);
17671768

17681769
// Emit arguments for all `accesses` properties.
17691770
if (!accessedProperties.empty()) {
17701771
auto propertyIter = accessedProperties.begin();
17711772
auto propertyArgs = accessorTy->getParameters().slice(
1772-
accessorTy->getNumParameters() - accessedProperties.size());
1773+
accessorTy->getNumParameters() - accessedProperties.size() - 1,
1774+
accessedProperties.size());
17731775

17741776
for (const auto &argument : propertyArgs) {
17751777
createArgument(*propertyIter, getSILTypeInContext(argument, accessorTy));
17761778
++propertyIter;
17771779
}
17781780
}
17791781

1782+
// Emit `self` argument.
1783+
emitConstructorMetatypeArg(*this, accessor);
1784+
17801785
prepareEpilog(accessor,
17811786
accessor->getResultInterfaceType(),
17821787
accessor->getEffectiveThrownErrorType(),

lib/SILGen/SILGenFunction.cpp

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1882,26 +1882,49 @@ void SILGenFunction::emitAssignOrInit(SILLocation loc, ManagedValue selfValue,
18821882
if (!substitutions.empty())
18831883
fieldTy = fieldTy.subst(substitutions);
18841884

1885+
auto *initAccessor = field->getOpaqueAccessor(AccessorKind::Init);
1886+
18851887
// Emit the init accessor function partially applied to the base.
18861888
SILValue initFRef = emitGlobalFunctionRef(
1887-
loc, getAccessorDeclRef(field->getOpaqueAccessor(AccessorKind::Init)));
1889+
loc, getAccessorDeclRef(initAccessor));
18881890

18891891
auto initTy = initFRef->getType().castTo<SILFunctionType>();
18901892

1891-
if (!substitutions.empty()) {
1892-
// If there are substitutions we need to emit partial apply to
1893-
// apply substitutions to the init accessor reference type.
1894-
initTy = initTy->substGenericArgs(SGM.M, substitutions,
1895-
getTypeExpansionContext());
1893+
// If there are substitutions we need to emit partial apply to
1894+
// apply substitutions to the init accessor reference type.
1895+
initTy = initTy->substGenericArgs(SGM.M, substitutions,
1896+
getTypeExpansionContext());
1897+
1898+
// Emit partial apply with self metatype argument to produce a substituted
1899+
// init accessor reference.
1900+
auto selfTy = selfValue.getType().getASTType();
1901+
auto metatypeTy = MetatypeType::get(selfTy);
18961902

1897-
// Emit partial apply without argument to produce a substituted
1898-
// init accessor reference.
1899-
PartialApplyInst *initPAI =
1900-
B.createPartialApply(loc, initFRef, substitutions, ArrayRef<SILValue>(),
1901-
ParameterConvention::Direct_Guaranteed);
1902-
initFRef = emitManagedRValueWithCleanup(initPAI).getValue();
1903+
SILValue selfMetatype;
1904+
if (selfTy->getClassOrBoundGenericClass()) {
1905+
selfMetatype = B.createValueMetatype(loc, getLoweredType(metatypeTy),
1906+
selfValue).getValue();
1907+
} else {
1908+
selfMetatype = B.createMetatype(loc, getLoweredType(metatypeTy));
19031909
}
19041910

1911+
auto expectedSelfTy = initAccessor->getDeclContext()->getSelfInterfaceType()
1912+
.subst(substitutions);
1913+
1914+
// This should only happen in the invalid case where we attempt to initialize
1915+
// superclass storage from a subclass initializer. However, we shouldn't
1916+
// crash, so emit the appropriate cast so that we can recover and diagnose
1917+
// later.
1918+
if (!expectedSelfTy->isEqual(selfTy)) {
1919+
selfMetatype = B.createUpcast(loc, selfMetatype,
1920+
getLoweredType(MetatypeType::get(expectedSelfTy)));
1921+
}
1922+
PartialApplyInst *initPAI =
1923+
B.createPartialApply(loc, initFRef, substitutions, selfMetatype,
1924+
ParameterConvention::Direct_Guaranteed,
1925+
PartialApplyInst::OnStackKind::OnStack);
1926+
initFRef = emitManagedRValueWithCleanup(initPAI).getValue();
1927+
19051928
// Check whether value is supposed to be passed indirectly and
19061929
// materialize if required.
19071930
{
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-swift-frontend -emit-ir %s
2+
3+
public class C {
4+
private var _count: Int
5+
6+
var count: Int {
7+
@storageRestrictions(initializes: _count)
8+
init {
9+
print(Self.self) // crash here
10+
_count = newValue
11+
}
12+
get { _count }
13+
set { }
14+
}
15+
16+
init() {
17+
count = 0
18+
}
19+
}
20+
21+
let c = C()

test/Interpreter/init_accessors.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,3 +922,35 @@ do {
922922
// CHECK-NEXT: init accessor is called: 42
923923
// CHECK-NEXT: nonmutating set called: 0
924924
// CHECK-NEXT: test-nonmutating-set-4: TestNonMutatingSetCustom(_count: 42)
925+
926+
do {
927+
class Base {
928+
var _count: Int
929+
930+
var count: Int {
931+
@storageRestrictions(initializes: _count)
932+
init {
933+
print("init accessor with Self = \(Self.self)")
934+
_count = newValue
935+
}
936+
937+
get { _count }
938+
939+
set {}
940+
}
941+
942+
init() {
943+
count = 42
944+
}
945+
}
946+
947+
class Sub: Base {}
948+
949+
print("- init accessor vs dynamic Self")
950+
_ = Base()
951+
_ = Sub()
952+
}
953+
954+
// CHECK-NEXT: - init accessor vs dynamic Self
955+
// CHECK-NEXT: init accessor with Self = Base
956+
// CHECK-NEXT: init accessor with Self = Sub

0 commit comments

Comments
 (0)