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?!");
|
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.
|
// Create a debug scope for the function using astNode as source location.
|
||||||
F->setDebugScope(new (M) SILDebugScope(Loc, F));
|
F->setDebugScope(new (M) SILDebugScope(Loc, F));
|
||||||
|
|||||||
@@ -201,8 +201,11 @@ void SILGenModule::emitGlobalInitialization(PatternBindingDecl *pd,
|
|||||||
unsigned pbdEntry) {
|
unsigned pbdEntry) {
|
||||||
// Generic and dynamic static properties require lazy initialization, which
|
// Generic and dynamic static properties require lazy initialization, which
|
||||||
// isn't implemented yet.
|
// isn't implemented yet.
|
||||||
if (pd->isStatic())
|
if (pd->isStatic()) {
|
||||||
assert(!pd->getDeclContext()->isGenericContext());
|
assert(!pd->getDeclContext()->isGenericContext()
|
||||||
|
|| pd->getDeclContext()->getGenericSignatureOfContext()
|
||||||
|
->areAllParamsConcrete());
|
||||||
|
}
|
||||||
|
|
||||||
// Emit the lazy initialization token for the initialization expression.
|
// Emit the lazy initialization token for the initialization expression.
|
||||||
auto counter = anonymousSymbolCounter++;
|
auto counter = anonymousSymbolCounter++;
|
||||||
@@ -248,7 +251,7 @@ void SILGenModule::emitGlobalInitialization(PatternBindingDecl *pd,
|
|||||||
NewMangling::ASTMangler NewMangler;
|
NewMangling::ASTMangler NewMangler;
|
||||||
std::string New = NewMangler.mangleGlobalInit(varDecl, counter, true);
|
std::string New = NewMangler.mangleGlobalInit(varDecl, counter, true);
|
||||||
onceFuncBuffer = NewMangling::selectMangling(Old, New);
|
onceFuncBuffer = NewMangling::selectMangling(Old, New);
|
||||||
}
|
}
|
||||||
|
|
||||||
SILFunction *onceFunc = emitLazyGlobalInitializer(onceFuncBuffer, pd,
|
SILFunction *onceFunc = emitLazyGlobalInitializer(onceFuncBuffer, pd,
|
||||||
pbdEntry);
|
pbdEntry);
|
||||||
|
|||||||
@@ -1735,11 +1735,6 @@ void LValue::addMemberVarComponent(SILGenFunction &gen, SILLocation loc,
|
|||||||
// FIXME: This has to be dynamically looked up for classes, and
|
// FIXME: This has to be dynamically looked up for classes, and
|
||||||
// dynamically instantiated for generics.
|
// dynamically instantiated for generics.
|
||||||
if (strategy == AccessStrategy::Storage && var->isStatic()) {
|
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
|
// FIXME: this implicitly drops the earlier components, but maybe
|
||||||
// we ought to evaluate them for side-effects even during the
|
// we ought to evaluate them for side-effects even during the
|
||||||
// formal access?
|
// formal access?
|
||||||
|
|||||||
@@ -299,10 +299,13 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void emitTypeMemberGlobalVariable(SILGenModule &SGM,
|
static void emitTypeMemberGlobalVariable(SILGenModule &SGM,
|
||||||
GenericParamList *generics,
|
|
||||||
NominalTypeDecl *theType,
|
|
||||||
VarDecl *var) {
|
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()) {
|
if (var->getDeclContext()->getAsClassOrClassExtensionContext()) {
|
||||||
assert(var->isFinal() && "only 'static' ('class final') stored properties are implemented in classes");
|
assert(var->isFinal() && "only 'static' ('class final') stored properties are implemented in classes");
|
||||||
}
|
}
|
||||||
@@ -405,8 +408,7 @@ public:
|
|||||||
// Collect global variables for static properties.
|
// Collect global variables for static properties.
|
||||||
// FIXME: We can't statically emit a global variable for generic properties.
|
// FIXME: We can't statically emit a global variable for generic properties.
|
||||||
if (vd->isStatic() && vd->hasStorage()) {
|
if (vd->isStatic() && vd->hasStorage()) {
|
||||||
return emitTypeMemberGlobalVariable(SGM, theType->getGenericParams(),
|
return emitTypeMemberGlobalVariable(SGM, vd);
|
||||||
theType, vd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
visitAbstractStorageDecl(vd);
|
visitAbstractStorageDecl(vd);
|
||||||
@@ -494,8 +496,7 @@ public:
|
|||||||
assert(vd->isStatic() && "stored property in extension?!");
|
assert(vd->isStatic() && "stored property in extension?!");
|
||||||
ExtensionDecl *ext = cast<ExtensionDecl>(vd->getDeclContext());
|
ExtensionDecl *ext = cast<ExtensionDecl>(vd->getDeclContext());
|
||||||
NominalTypeDecl *theType = ext->getExtendedType()->getAnyNominal();
|
NominalTypeDecl *theType = ext->getExtendedType()->getAnyNominal();
|
||||||
return emitTypeMemberGlobalVariable(SGM, ext->getGenericParams(),
|
return emitTypeMemberGlobalVariable(SGM, vd);
|
||||||
theType, vd);
|
|
||||||
}
|
}
|
||||||
visitAbstractStorageDecl(vd);
|
visitAbstractStorageDecl(vd);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3701,7 +3701,8 @@ public:
|
|||||||
|
|
||||||
// Stored type variables in a generic context need to logically
|
// Stored type variables in a generic context need to logically
|
||||||
// occur once per instantiation, which we don't yet handle.
|
// occur once per instantiation, which we don't yet handle.
|
||||||
} else if (DC->isGenericContext()) {
|
} else if (DC->isGenericContext()
|
||||||
|
&& !DC->getGenericSignatureOfContext()->areAllParamsConcrete()) {
|
||||||
unimplementedStatic(GenericTypes);
|
unimplementedStatic(GenericTypes);
|
||||||
} else if (DC->getAsClassOrClassExtensionContext()) {
|
} else if (DC->getAsClassOrClassExtensionContext()) {
|
||||||
auto StaticSpelling = PBD->getStaticSpelling();
|
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