diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index 2de7a71a..f338c2f1 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -892,6 +892,9 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild return; } + if ((typeInst->IsBoxed()) && (typeInst->mTypeDef->mEmitParent != NULL)) + typeInst->mTypeDef = typeInst->mTypeDef->mEmitParent; + if (mSystem->mWorkspaceConfigChanged) { typeInst->mTypeOptionsIdx = -2; @@ -1060,8 +1063,12 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild if (typeInst->mTypeDef->mEmitParent != NULL) { auto emitTypeDef = typeInst->mTypeDef; - typeInst->mTypeDef = emitTypeDef->mEmitParent; - delete emitTypeDef; + typeInst->mTypeDef = emitTypeDef->mEmitParent; + BfLogSysM("Type %p queueing delete of typeDef %p, resetting typeDef to %p\n", typeInst, emitTypeDef, typeInst->mTypeDef); + emitTypeDef->mDefState = BfTypeDef::DefState_Deleted; + AutoCrit autoCrit(mSystem->mDataLock); + BF_ASSERT(!mSystem->mTypeDefDeleteQueue.Contains(emitTypeDef)); + mSystem->mTypeDefDeleteQueue.push_back(emitTypeDef); } //typeInst->mTypeDef->ClearEmitted(); @@ -1912,10 +1919,17 @@ void BfContext::UpdateRevisedTypes() if (typeDef->mEmitParent != NULL) { - auto emitTypeDef = typeDef; - typeDef = typeDef->mEmitParent; - if (typeDef->mNextRevision != NULL) - emitTypeDef->mDefState = BfTypeDef::DefState_EmittedDirty; + if (typeDef->mDefState == BfTypeDef::DefState_Deleted) + { + typeInst->mTypeDef = typeDef->mEmitParent; + } + else + { + auto emitTypeDef = typeDef; + typeDef = typeDef->mEmitParent; + if (typeDef->mNextRevision != NULL) + emitTypeDef->mDefState = BfTypeDef::DefState_EmittedDirty; + } } if (typeDef->mProject->mDisabled) diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 17fb80af..da894da9 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -15286,7 +15286,7 @@ void BfModule::AssertErrorState() { if (mCurTypeInstance->mTypeFailed) return; - if ((mCurTypeInstance->mTypeDef->mSource != NULL) && (mCurTypeInstance->mTypeDef->mSource->mParsingFailed)) + if ((mCurTypeInstance->mTypeDef->GetDefinition()->mSource != NULL) && (mCurTypeInstance->mTypeDef->GetDefinition()->mSource->mParsingFailed)) return; } if (mCurMethodInstance != NULL) @@ -19762,12 +19762,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) mBfIRBuilder->CreateRetVoid(); } else - { - BF_ASSERT(!innerMethodInstance.mMethodInstance->mMethodDef->mDeclaringType->IsEmitted()); + { auto innerMethodDef = innerMethodInstance.mMethodInstance->mMethodDef; - if (innerType->mTypeDef->IsEmitted()) - innerMethodDef = innerType->mTypeDef->mEmitParent->mMethods[innerMethodDef->mIdx]; - BF_ASSERT(innerMethodDef == methodDef); SizedArray innerParams; diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 79ed59ae..d42ece83 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -2747,7 +2747,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy resolvedTypeRef->mSize = typeInstance->mAlign = mSystem->mPtrSize; } - BF_ASSERT((typeInstance->mMethodInstanceGroups.size() == 0) || (typeInstance->mMethodInstanceGroups.size() == typeDef->mMethods.size()) || (typeInstance->mCeTypeInfo != NULL)); + BF_ASSERT((typeInstance->mMethodInstanceGroups.size() == 0) || (typeInstance->mMethodInstanceGroups.size() == typeDef->mMethods.size()) || (typeInstance->mCeTypeInfo != NULL) || (typeInstance->IsBoxed())); typeInstance->mMethodInstanceGroups.Resize(typeDef->mMethods.size()); for (int i = 0; i < (int)typeInstance->mMethodInstanceGroups.size(); i++) { @@ -3702,6 +3702,15 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if (innerType->IsIncomplete()) PopulateType(innerType, BfPopulateType_Data); + auto innerTypeInst = innerType->ToTypeInstance(); + if ((innerTypeInst != NULL) && (typeInstance->mTypeDef != innerTypeInst->mTypeDef)) + { + // Rebuild with proper typedef (generally from inner type comptime emission) + typeInstance->mTypeDef = innerTypeInst->mTypeDef; + DoPopulateType(resolvedTypeRef, populateType); + return; + } + auto baseType = typeInstance->mBaseType; dataPos = baseType->mInstSize; int alignSize = BF_MAX(innerType->mAlign, baseType->mInstAlign); @@ -5666,15 +5675,15 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) } else { - auto matchedMethodDef = matchedMethod->mMethodDef; - if (matchedMethodDef->mDeclaringType->IsEmitted()) - { - Fail("Boxed interface binding error to emitted method", mCurTypeInstance->mTypeDef->GetRefNode()); - continue; - } - - if (underlyingTypeInstance->mTypeDef->IsEmitted()) - matchedMethodDef = underlyingTypeInstance->mTypeDef->mEmitParent->mMethods[matchedMethodDef->mIdx]; + auto matchedMethodDef = matchedMethod->mMethodDef; +// if (matchedMethodDef->mDeclaringType->IsEmitted()) +// { +// Fail("Boxed interface binding error to emitted method", mCurTypeInstance->mTypeDef->GetRefNode()); +// continue; +// } +// +// if (underlyingTypeInstance->mTypeDef->IsEmitted()) +// matchedMethodDef = underlyingTypeInstance->mTypeDef->mEmitParent->mMethods[matchedMethodDef->mIdx]; if (!matchedMethod->mIsForeignMethodDef) { diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index c99a4e77..93939bec 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -1554,6 +1554,7 @@ BfTypeInstance::~BfTypeInstance() if ((mTypeDef != NULL) && (mTypeDef->mEmitParent != NULL)) { mMethodInstanceGroups.Clear(); + BfLogSys(mModule->mSystem, "Type %p dtor deleting typeDef %p\n", this, mTypeDef); delete mTypeDef; } } @@ -2627,6 +2628,12 @@ void BfTupleType::Finish() ////////////////////////////////////////////////////////////////////////// +BfBoxedType::~BfBoxedType() +{ + if (mTypeDef->mEmitParent != NULL) + mTypeDef = mTypeDef->mEmitParent; +} + BfType* BfBoxedType::GetModifiedElementType() { if ((mBoxedFlags & BoxedFlags_StructPtr) != 0) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 7563609d..858fc5d0 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -2110,6 +2110,7 @@ public: mBoxedBaseType = NULL; mBoxedFlags = BoxedFlags_None; } + ~BfBoxedType(); virtual bool IsBoxed() override { return true; } diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index 0f0419bd..78f16b8f 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -793,11 +793,6 @@ BfTypeDef::~BfTypeDef() { BfLogSysM("BfTypeDef::~BfTypeDef %p\n", this); - if ((mHash == -1330357811) && (IsEmitted())) - { - NOP; - } - delete mNextRevision; FreeMembers(); @@ -3728,10 +3723,14 @@ void BfSystem::RemoveOldData() { AutoCrit autoCrit(mDataLock); - for (auto typeDef : mTypeDefDeleteQueue) + for (int i = 0; i < (int)mTypeDefDeleteQueue.size(); i++) + { + auto typeDef = mTypeDefDeleteQueue[i]; + mTypeDefDeleteQueue[i] = NULL; + BfLogSys(this, "RemoveOldData deleting from mTypeDefDeleteQueue %p\n", typeDef); delete typeDef; + } mTypeDefDeleteQueue.Clear(); - if (!mProjectDeleteQueue.IsEmpty()) { diff --git a/IDEHelper/Tests/src/Comptime.bf b/IDEHelper/Tests/src/Comptime.bf index 385b6fa7..97be881c 100644 --- a/IDEHelper/Tests/src/Comptime.bf +++ b/IDEHelper/Tests/src/Comptime.bf @@ -174,7 +174,60 @@ namespace Tests public float mY; public float mZ; } + + class SerializationContext + { + public String mStr = new String() ~ delete _; + public void Serialize(String name, T val) where T : struct + { + mStr.AppendF($"{name} {val}\n"); + } + } + interface ISerializable + { + void Serialize(SerializationContext ctx); + } + + [AttributeUsage(.Enum | .Struct | .Class, .NotInherited | .ReflectAttribute | .DisallowAllowMultiple)] + struct SerializableAttribute : Attribute, IComptimeTypeApply + { + [Comptime] + public void ApplyToType(Type type) + { + const String SERIALIZE_NAME = "void ISerializable.Serialize(SerializationContext ctx)\n"; + + String serializeBuffer = new .(); + + Compiler.Assert(!type.IsUnion); + + for (let field in type.GetFields()) + { + if (!field.IsInstanceField || field.DeclaringType != type) + continue; + + serializeBuffer.AppendF($"\n\tctx.Serialize(\"{field.Name}\", {field.Name});"); + } + + Compiler.EmitTypeBody(type, scope $"{SERIALIZE_NAME}{{{serializeBuffer}\n}}\n"); + } + } + + [Serializable] + struct Foo : this(float x, float y), ISerializable + { + } + + public class ComponentHandler + where T : struct + { + uint8* data; + protected override void GCMarkMembers() + { + T* ptr = (T*)data; + GC.Mark!((*ptr)); + } + } [Test] public static void TestBasics() { @@ -209,6 +262,12 @@ namespace Tests 4 mY 8 mZ """); + + Foo bar = .(10, 2); + ISerializable iSer = bar; + SerializationContext serCtx = scope .(); + iSer.Serialize(serCtx); + Test.Assert(serCtx.mStr == "x 10\ny 2\n"); } } }