SILGen: Allow static stored properties in fully-concrete extensions of generic types.

There's no need for per-instantiation storage in this case, so we can relax the implementation limitation for them.
This commit is contained in:
Joe Groff
2017-02-24 14:55:56 -08:00
parent 73b1df31f5
commit 886c83f6e7
6 changed files with 39 additions and 17 deletions

View File

@@ -594,7 +594,8 @@ void SILGenModule::preEmitFunction(SILDeclRef constant,
assert(F->empty() && "already emitted function?!");
F->setGenericEnvironment(Types.getConstantInfo(constant).GenericEnv);
if (F->getLoweredFunctionType()->isPolymorphic())
F->setGenericEnvironment(Types.getConstantInfo(constant).GenericEnv);
// Create a debug scope for the function using astNode as source location.
F->setDebugScope(new (M) SILDebugScope(Loc, F));

View File

@@ -201,8 +201,11 @@ void SILGenModule::emitGlobalInitialization(PatternBindingDecl *pd,
unsigned pbdEntry) {
// Generic and dynamic static properties require lazy initialization, which
// isn't implemented yet.
if (pd->isStatic())
assert(!pd->getDeclContext()->isGenericContext());
if (pd->isStatic()) {
assert(!pd->getDeclContext()->isGenericContext()
|| pd->getDeclContext()->getGenericSignatureOfContext()
->areAllParamsConcrete());
}
// Emit the lazy initialization token for the initialization expression.
auto counter = anonymousSymbolCounter++;
@@ -248,7 +251,7 @@ void SILGenModule::emitGlobalInitialization(PatternBindingDecl *pd,
NewMangling::ASTMangler NewMangler;
std::string New = NewMangler.mangleGlobalInit(varDecl, counter, true);
onceFuncBuffer = NewMangling::selectMangling(Old, New);
}
}
SILFunction *onceFunc = emitLazyGlobalInitializer(onceFuncBuffer, pd,
pbdEntry);

View File

@@ -1735,11 +1735,6 @@ void LValue::addMemberVarComponent(SILGenFunction &gen, SILLocation loc,
// FIXME: This has to be dynamically looked up for classes, and
// dynamically instantiated for generics.
if (strategy == AccessStrategy::Storage && var->isStatic()) {
auto baseMeta = baseFormalType->castTo<MetatypeType>()->getInstanceType();
(void)baseMeta;
assert(!baseMeta->is<BoundGenericType>() &&
"generic static stored properties not implemented");
// FIXME: this implicitly drops the earlier components, but maybe
// we ought to evaluate them for side-effects even during the
// formal access?

View File

@@ -299,10 +299,13 @@ public:
};
static void emitTypeMemberGlobalVariable(SILGenModule &SGM,
GenericParamList *generics,
NominalTypeDecl *theType,
VarDecl *var) {
assert(!generics && "generic static properties not implemented");
if (var->getDeclContext()->isGenericContext()) {
assert(var->getDeclContext()->getGenericSignatureOfContext()
->areAllParamsConcrete()
&& "generic static vars are not implemented yet");
}
if (var->getDeclContext()->getAsClassOrClassExtensionContext()) {
assert(var->isFinal() && "only 'static' ('class final') stored properties are implemented in classes");
}
@@ -405,8 +408,7 @@ public:
// Collect global variables for static properties.
// FIXME: We can't statically emit a global variable for generic properties.
if (vd->isStatic() && vd->hasStorage()) {
return emitTypeMemberGlobalVariable(SGM, theType->getGenericParams(),
theType, vd);
return emitTypeMemberGlobalVariable(SGM, vd);
}
visitAbstractStorageDecl(vd);
@@ -494,8 +496,7 @@ public:
assert(vd->isStatic() && "stored property in extension?!");
ExtensionDecl *ext = cast<ExtensionDecl>(vd->getDeclContext());
NominalTypeDecl *theType = ext->getExtendedType()->getAnyNominal();
return emitTypeMemberGlobalVariable(SGM, ext->getGenericParams(),
theType, vd);
return emitTypeMemberGlobalVariable(SGM, vd);
}
visitAbstractStorageDecl(vd);
}

View File

@@ -3701,7 +3701,8 @@ public:
// Stored type variables in a generic context need to logically
// occur once per instantiation, which we don't yet handle.
} else if (DC->isGenericContext()) {
} else if (DC->isGenericContext()
&& !DC->getGenericSignatureOfContext()->areAllParamsConcrete()) {
unimplementedStatic(GenericTypes);
} else if (DC->getAsClassOrClassExtensionContext()) {
auto StaticSpelling = PBD->getStaticSpelling();

View File

@@ -0,0 +1,21 @@
// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
struct Foo<T> {
static var foo: T { return (0 as Int) as! T }
}
extension Foo where T == Int {
// CHECK: sil_global private [[X_TOKEN:@.*]] : $Builtin.Word
// CHECK: sil_global hidden [let] @_TZve4mainRxzSirVS_3Foo1xSi : $Int
static let x = foo
// CHECK: sil_global private [[Y_TOKEN:@.*]] : $Builtin.Word
// CHECK: sil_global hidden @_TZve4mainRxzSirVS_3Foo1ySi : $Int
static var y = foo
}
print(Foo<Int>.x)
Foo<Int>.y = 2
Foo<Int>.y += 3
print(Foo<Int>.y)