Skip to content

Fix store to generic member from extension #3949

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1852,6 +1852,9 @@ class PatternBindingEntry {
InitCheckedAndRemoved.setInt(
InitCheckedAndRemoved.getInt() | Flags::Checked);
}

// Return the first variable initialized by this pattern.
VarDecl *getAnchoringVarDecl() const;
};

/// \brief This decl contains a pattern and optional initializer for a set
Expand Down
9 changes: 9 additions & 0 deletions include/swift/SIL/SILDeclRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ struct SILDeclRef {
/// References the generator for a default argument of a function.
DefaultArgGenerator,

/// References the initializer expression for a stored property
/// of a nominal type.
StoredPropertyInitializer,

/// References the ivar initializer for the ClassDecl in loc.
///
/// Only classes that are allocated using Objective-C's allocation
Expand Down Expand Up @@ -261,6 +265,11 @@ struct SILDeclRef {
bool isDefaultArgGenerator() const {
return kind == Kind::DefaultArgGenerator;
}
/// True if the SILDeclRef references the initializer for a stored property
/// of a nominal type.
bool isStoredPropertyInitializer() const {
return kind == Kind::StoredPropertyInitializer;
}

/// \brief True if the function should be treated as transparent.
bool isTransparent() const;
Expand Down
7 changes: 7 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,13 @@ void PatternBindingEntry::setInit(Expr *E) {
}
}

VarDecl *PatternBindingEntry::getAnchoringVarDecl() const {
SmallVector<VarDecl *, 8> variables;
getPattern()->collectVariables(variables);
assert(variables.size() > 0);
return variables[0];
}

SourceRange PatternBindingDecl::getSourceRange() const {
SourceLoc startLoc = getStartLoc();

Expand Down
1 change: 1 addition & 0 deletions lib/IRGen/GenObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ namespace {
Selector(SILDeclRef ref) {
switch (ref.kind) {
case SILDeclRef::Kind::DefaultArgGenerator:
case SILDeclRef::Kind::StoredPropertyInitializer:
case SILDeclRef::Kind::EnumElement:
case SILDeclRef::Kind::GlobalAccessor:
case SILDeclRef::Kind::GlobalGetter:
Expand Down
6 changes: 6 additions & 0 deletions lib/Parse/ParseSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,12 @@ bool SILParser::parseSILDeclRef(SILDeclRef &Result,
} else if (!ParseState && Id.str() == "ivarinitializer") {
Kind = SILDeclRef::Kind::IVarInitializer;
ParseState = 1;
} else if (!ParseState && Id.str() == "defaultarg") {
Kind = SILDeclRef::Kind::IVarInitializer;
ParseState = 1;
} else if (!ParseState && Id.str() == "propertyinit") {
Kind = SILDeclRef::Kind::StoredPropertyInitializer;
ParseState = 1;
} else if (Id.str() == "foreign") {
IsObjC = true;
break;
Expand Down
25 changes: 21 additions & 4 deletions lib/SIL/SILDeclRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,11 @@ SILDeclRef::SILDeclRef(ValueDecl *vd, SILDeclRef::Kind kind,
"can only create ivar initializer/destroyer SILDeclRef for class");
naturalUncurryLevel = 1;
} else if (auto *var = dyn_cast<VarDecl>(vd)) {
assert((kind == Kind::GlobalAccessor || kind == Kind::GlobalGetter) &&
"can only create GlobalAccessor or GlobalGetter SILDeclRef for var");
assert((kind == Kind::GlobalAccessor ||
kind == Kind::GlobalGetter ||
kind == Kind::StoredPropertyInitializer) &&
"can only create GlobalAccessor, GlobalGetter or "
"StoredPropertyInitializer SILDeclRef for var");

naturalUncurryLevel = 0;
assert(!var->getDeclContext()->isLocalContext() &&
Expand Down Expand Up @@ -316,9 +319,14 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {

// Enum constructors are essentially the same as thunks, they are
// emitted by need and have shared linkage.
if (kind == Kind::EnumElement)
if (isEnumElement())
return SILLinkage::Shared;

// Stored property initializers have hidden linkage, since they are
// not meant to be used from outside of their module.
if (isStoredPropertyInitializer())
return SILLinkage::Hidden;

// Declarations imported from Clang modules have shared linkage.
const SILLinkage ClangLinkage = SILLinkage::Shared;

Expand Down Expand Up @@ -353,6 +361,9 @@ bool SILDeclRef::isTransparent() const {
if (isEnumElement())
return true;

if (isStoredPropertyInitializer())
return true;

if (hasAutoClosureExpr())
return true;

Expand Down Expand Up @@ -576,12 +587,18 @@ static std::string mangleConstant(SILDeclRef c, StringRef prefix) {
mangler.mangleGlobalGetterEntity(c.getDecl());
return mangler.finalize();

// entity ::= context 'e' index // default arg generator
// entity ::= context 'e' index // default arg generator
case SILDeclRef::Kind::DefaultArgGenerator:
mangler.append(introducer);
mangler.mangleDefaultArgumentEntity(cast<AbstractFunctionDecl>(c.getDecl()),
c.defaultArgIndex);
return mangler.finalize();

// entity ::= 'I' declaration 'i' // stored property initializer
case SILDeclRef::Kind::StoredPropertyInitializer:
mangler.append(introducer);
mangler.mangleInitializerEntity(cast<VarDecl>(c.getDecl()));
return mangler.finalize();
}

llvm_unreachable("bad entity kind!");
Expand Down
4 changes: 4 additions & 0 deletions lib/SIL/SILFunctionType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,7 @@ static CanSILFunctionType getNativeSILFunctionType(SILModule &M,
case SILDeclRef::Kind::GlobalAccessor:
case SILDeclRef::Kind::GlobalGetter:
case SILDeclRef::Kind::DefaultArgGenerator:
case SILDeclRef::Kind::StoredPropertyInitializer:
case SILDeclRef::Kind::IVarInitializer:
case SILDeclRef::Kind::IVarDestroyer:
case SILDeclRef::Kind::EnumElement:
Expand Down Expand Up @@ -1472,6 +1473,7 @@ static SelectorFamily getSelectorFamily(SILDeclRef c) {
case SILDeclRef::Kind::GlobalGetter:
case SILDeclRef::Kind::IVarDestroyer:
case SILDeclRef::Kind::DefaultArgGenerator:
case SILDeclRef::Kind::StoredPropertyInitializer:
return SelectorFamily::None;
}
}
Expand Down Expand Up @@ -1653,6 +1655,7 @@ TypeConverter::getDeclRefRepresentation(SILDeclRef c) {
case SILDeclRef::Kind::GlobalAccessor:
case SILDeclRef::Kind::GlobalGetter:
case SILDeclRef::Kind::DefaultArgGenerator:
case SILDeclRef::Kind::StoredPropertyInitializer:
return SILFunctionTypeRepresentation::Thin;

case SILDeclRef::Kind::Func:
Expand Down Expand Up @@ -2319,6 +2322,7 @@ static AbstractFunctionDecl *getBridgedFunction(SILDeclRef declRef) {
case SILDeclRef::Kind::GlobalAccessor:
case SILDeclRef::Kind::GlobalGetter:
case SILDeclRef::Kind::DefaultArgGenerator:
case SILDeclRef::Kind::StoredPropertyInitializer:
case SILDeclRef::Kind::IVarInitializer:
case SILDeclRef::Kind::IVarDestroyer:
return nullptr;
Expand Down
3 changes: 3 additions & 0 deletions lib/SIL/SILPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,9 @@ void SILDeclRef::print(raw_ostream &OS) const {
case SILDeclRef::Kind::DefaultArgGenerator:
OS << "!defaultarg" << "." << defaultArgIndex;
break;
case SILDeclRef::Kind::StoredPropertyInitializer:
OS << "!propertyinit";
break;
}
if (uncurryLevel != 0)
OS << (isDot ? '.' : '!') << uncurryLevel;
Expand Down
35 changes: 33 additions & 2 deletions lib/SIL/TypeLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1671,6 +1671,27 @@ static CanAnyFunctionType getDefaultArgGeneratorInterfaceType(
return CanFunctionType::get(TupleType::getEmpty(context), resultTy);
}

/// Get the type of a stored property initializer, () -> T.
static CanAnyFunctionType getStoredPropertyInitializerInterfaceType(
TypeConverter &TC,
VarDecl *VD,
ASTContext &context) {
auto *DC = VD->getDeclContext();
CanType resultTy =
ArchetypeBuilder::mapTypeOutOfContext(
DC, VD->getParentInitializer()->getType())
->getCanonicalType();
GenericSignature *sig = DC->getGenericSignatureOfContext();

if (sig)
return CanGenericFunctionType::get(sig->getCanonicalSignature(),
TupleType::getEmpty(context),
resultTy,
GenericFunctionType::ExtInfo());

return CanFunctionType::get(TupleType::getEmpty(context), resultTy);
}

/// Get the type of a destructor function.
static CanAnyFunctionType getDestructorInterfaceType(DestructorDecl *dd,
bool isDeallocating,
Expand Down Expand Up @@ -1868,8 +1889,12 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
}
case SILDeclRef::Kind::DefaultArgGenerator:
return getDefaultArgGeneratorInterfaceType(*this,
cast<AbstractFunctionDecl>(vd),
c.defaultArgIndex, Context);
cast<AbstractFunctionDecl>(vd),
c.defaultArgIndex, Context);
case SILDeclRef::Kind::StoredPropertyInitializer:
return getStoredPropertyInitializerInterfaceType(*this,
cast<VarDecl>(vd),
Context);
case SILDeclRef::Kind::IVarInitializer:
return getIVarInitDestroyerInterfaceType(cast<ClassDecl>(vd),
c.isForeign, Context, false);
Expand Down Expand Up @@ -1926,6 +1951,12 @@ TypeConverter::getConstantContextGenericParams(SILDeclRef c) {
case SILDeclRef::Kind::DefaultArgGenerator:
// Use the context generic parameters of the original declaration.
return getConstantContextGenericParams(SILDeclRef(c.getDecl()));
case SILDeclRef::Kind::StoredPropertyInitializer:
// Use the context generic parameters of the containing type.
return {
c.getDecl()->getDeclContext()->getGenericParamsOfContext(),
nullptr,
};
}
}

Expand Down
15 changes: 15 additions & 0 deletions lib/SILGen/SILGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,21 @@ void SILGenModule::emitDefaultArgGenerator(SILDeclRef constant, Expr *arg) {
});
}

void SILGenModule::
emitStoredPropertyInitialization(PatternBindingDecl *pbd, unsigned i) {
const PatternBindingEntry &pbdEntry = pbd->getPatternList()[i];
auto *var = pbdEntry.getAnchoringVarDecl();
auto *init = pbdEntry.getInit();

SILDeclRef constant(var, SILDeclRef::Kind::StoredPropertyInitializer);
emitOrDelayFunction(*this, constant, [this,constant,init](SILFunction *f) {
preEmitFunction(constant, init, f, init);
PrettyStackTraceSILFunction X("silgen emitStoredPropertyInitialization", f);
SILGenFunction(*this, *f).emitGeneratorFunction(constant, init);
postEmitFunction(constant, f);
});
}

SILFunction *SILGenModule::emitLazyGlobalInitializer(StringRef funcName,
PatternBindingDecl *binding,
unsigned pbdEntry) {
Expand Down
5 changes: 4 additions & 1 deletion lib/SILGen/SILGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,10 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {

/// Emits the default argument generator with the given expression.
void emitDefaultArgGenerator(SILDeclRef constant, Expr *arg);


/// Emits the stored property initializer for the given pattern.
void emitStoredPropertyInitialization(PatternBindingDecl *pd, unsigned i);

/// Emits the default argument generator for the given function.
void emitDefaultArgGenerators(SILDeclRef::Loc decl,
ArrayRef<ParameterList*> paramLists);
Expand Down
49 changes: 41 additions & 8 deletions lib/SILGen/SILGenConstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,9 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {

// If this is not a delegating constructor, emit member initializers.
if (!isDelegating) {
auto nominal = ctor->getDeclContext()
->getAsNominalTypeOrNominalTypeExtensionContext();
emitMemberInitializers(selfDecl, nominal);
auto *dc = ctor->getDeclContext();
auto *nominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
emitMemberInitializers(dc, selfDecl, nominal);
}

emitProfilerIncrement(ctor->getBody());
Expand Down Expand Up @@ -526,7 +526,8 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
// TODO: If we could require Objective-C classes to have an attribute to get
// this behavior, we could avoid runtime overhead here.
VarDecl *selfDecl = ctor->getImplicitSelfDecl();
auto selfClassDecl = ctor->getDeclContext()->getAsClassOrClassExtensionContext();
auto *dc = ctor->getDeclContext();
auto selfClassDecl = dc->getAsClassOrClassExtensionContext();
bool NeedsBoxForSelf = isDelegating ||
(selfClassDecl->hasSuperclass() && !ctor->hasStubImplementation());
bool usesObjCAllocator = Lowering::usesObjCAllocator(selfClassDecl);
Expand Down Expand Up @@ -642,7 +643,7 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
// Note that 'self' has been fully initialized at this point.
} else {
// Emit the member initializers.
emitMemberInitializers(selfDecl, selfClassDecl);
emitMemberInitializers(dc, selfDecl, selfClassDecl);
}

emitProfilerIncrement(ctor->getBody());
Expand Down Expand Up @@ -841,7 +842,19 @@ static SILValue getBehaviorSetterFn(SILGenFunction &gen, VarDecl *behaviorVar) {
return gen.B.createFunctionRef(behaviorVar, setFn);
}

void SILGenFunction::emitMemberInitializers(VarDecl *selfDecl,
static Type getInitializationTypeInContext(
DeclContext *fromDC, DeclContext *toDC,
Expr *init) {
auto interfaceType =
ArchetypeBuilder::mapTypeOutOfContext(fromDC, init->getType());
auto resultType =
ArchetypeBuilder::mapTypeIntoContext(toDC, interfaceType);

return resultType;
}

void SILGenFunction::emitMemberInitializers(DeclContext *dc,
VarDecl *selfDecl,
NominalTypeDecl *nominal) {
for (auto member : nominal->getMembers()) {
// Find instance pattern binding declarations that have initializers.
Expand All @@ -854,7 +867,27 @@ void SILGenFunction::emitMemberInitializers(VarDecl *selfDecl,

// Cleanup after this initialization.
FullExpr scope(Cleanups, entry.getPattern());
emitMemberInit(*this, selfDecl, entry.getPattern(), emitRValue(init));

// Get the substitutions for the constructor context.
ArrayRef<Substitution> subs;
auto *genericParams = dc->getGenericParamsOfContext();
if (genericParams)
subs = genericParams->getForwardingSubstitutions(getASTContext());

// Get the type of the initialization result, in terms
// of the constructor context's archetypes.
CanType resultType = getInitializationTypeInContext(
pbd->getDeclContext(), dc, init)->getCanonicalType();
AbstractionPattern origResultType(resultType);

// FIXME: Can emitMemberInit() share code with
// InitializationForPattern in SILGenDecl.cpp?
RValue result = emitApplyOfStoredPropertyInitializer(
init, entry, subs,
resultType, origResultType,
SGFContext());

emitMemberInit(*this, selfDecl, entry.getPattern(), std::move(result));
}
}

Expand Down Expand Up @@ -913,7 +946,7 @@ void SILGenFunction::emitIVarInitializer(SILDeclRef ivarInitializer) {
prepareEpilog(TupleType::getEmpty(getASTContext()), false, cleanupLoc);

// Emit the initializers.
emitMemberInitializers(cd->getDestructor()->getImplicitSelfDecl(), cd);
emitMemberInitializers(cd, selfDecl, cd);

// Return 'self'.
B.createReturn(loc, selfArg);
Expand Down
23 changes: 23 additions & 0 deletions lib/SILGen/SILGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1724,6 +1724,29 @@ SILGenFunction::emitApplyOfDefaultArgGenerator(SILLocation loc,
ApplyOptions::None, None, None, C);
}

RValue SILGenFunction::emitApplyOfStoredPropertyInitializer(
SILLocation loc,
const PatternBindingEntry &entry,
ArrayRef<Substitution> subs,
CanType resultType,
AbstractionPattern origResultType,
SGFContext C) {

VarDecl *var = entry.getAnchoringVarDecl();
SILDeclRef constant(var, SILDeclRef::Kind::StoredPropertyInitializer);
auto fnRef = ManagedValue::forUnmanaged(emitGlobalFunctionRef(loc, constant));
auto fnType = fnRef.getType().castTo<SILFunctionType>();

auto substFnType = fnType->substGenericArgs(SGM.M, SGM.M.getSwiftModule(),
subs);

return emitApply(loc, fnRef, subs, {},
substFnType,
origResultType,
resultType,
ApplyOptions::None, None, None, C);
}

static void emitTupleShuffleExprInto(RValueEmitter &emitter,
TupleShuffleExpr *E,
Initialization *outerTupleInit) {
Expand Down
2 changes: 2 additions & 0 deletions lib/SILGen/SILGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ DeclName SILGenModule::getMagicFunctionName(SILDeclRef ref) {
return getMagicFunctionName(cast<VarDecl>(ref.getDecl())->getDeclContext());
case SILDeclRef::Kind::DefaultArgGenerator:
return getMagicFunctionName(cast<AbstractFunctionDecl>(ref.getDecl()));
case SILDeclRef::Kind::StoredPropertyInitializer:
return getMagicFunctionName(cast<VarDecl>(ref.getDecl())->getDeclContext());
case SILDeclRef::Kind::IVarInitializer:
return getMagicFunctionName(cast<ClassDecl>(ref.getDecl()));
case SILDeclRef::Kind::IVarDestroyer:
Expand Down
Loading