mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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:
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user