diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index cd8154c564909..644159e0f340e 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -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)); diff --git a/lib/SILGen/SILGenGlobalVariable.cpp b/lib/SILGen/SILGenGlobalVariable.cpp index 645ffdcadbc3e..79a0bacb4aa20 100644 --- a/lib/SILGen/SILGenGlobalVariable.cpp +++ b/lib/SILGen/SILGenGlobalVariable.cpp @@ -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); diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp index 418cadfbea511..7348f61482883 100644 --- a/lib/SILGen/SILGenLValue.cpp +++ b/lib/SILGen/SILGenLValue.cpp @@ -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()->getInstanceType(); - (void)baseMeta; - assert(!baseMeta->is() && - "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? diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp index a6a227b4d85a9..fb7a62477000b 100644 --- a/lib/SILGen/SILGenType.cpp +++ b/lib/SILGen/SILGenType.cpp @@ -299,10 +299,13 @@ class SILGenVTable : public Lowering::ASTVisitor { }; 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 @@ class SILGenType : public TypeMemberVisitor { // 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 @@ class SILGenExtension : public TypeMemberVisitor { assert(vd->isStatic() && "stored property in extension?!"); ExtensionDecl *ext = cast(vd->getDeclContext()); NominalTypeDecl *theType = ext->getExtendedType()->getAnyNominal(); - return emitTypeMemberGlobalVariable(SGM, ext->getGenericParams(), - theType, vd); + return emitTypeMemberGlobalVariable(SGM, vd); } visitAbstractStorageDecl(vd); } diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index e92a62a546eaf..8d625fb915e42 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -3701,7 +3701,8 @@ class DeclChecker : public DeclVisitor { // 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(); diff --git a/test/SILGen/static-stored-properties-in-concrete-contexts.swift b/test/SILGen/static-stored-properties-in-concrete-contexts.swift new file mode 100644 index 0000000000000..9880e3fe2859f --- /dev/null +++ b/test/SILGen/static-stored-properties-in-concrete-contexts.swift @@ -0,0 +1,21 @@ +// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s + +struct Foo { + 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.x) +Foo.y = 2 +Foo.y += 3 +print(Foo.y) +