Browse Source

Anonymous subclassing in initializer blocks

Brian Fiete 6 months ago
parent
commit
a5e9a33f64

+ 5 - 0
IDEHelper/Compiler/BfAst.cpp

@@ -1243,6 +1243,11 @@ bool BfTypeDeclaration::IsAnonymous()
 	return (mAnonymousName != NULL);
 }
 
+bool BfTypeDeclaration::IsAnonymousInitializerType()
+{
+	return (mAnonymousName != NULL) && (mTypeNode == NULL);
+}
+
 //////////////////////////////////////////////////////////////////////////
 
 bool BfTypeReference::IsNamedTypeReference()

+ 18 - 0
IDEHelper/Compiler/BfAst.h

@@ -358,6 +358,7 @@ class BfAttributedIdentifierNode;
 class BfQualifiedNameNode;
 class BfNamespaceDeclaration;
 class BfTypeDeclaration;
+class BfInitializerTypeDeclaration;
 class BfTypeAliasDeclaration;
 class BfMethodDeclaration;
 class BfOperatorDeclaration;
@@ -1809,6 +1810,7 @@ public:
 	ASTREF(BfTokenNode*) mCloseBrace;
 	//BfDebugArray<BfAstNode*> mChildArr;
 	BfSizedArray<ASTREF(BfAstNode*)> mChildArr;
+	int mParserBlockId;
 
 public:
 	using BfAstNode::Init;
@@ -2282,6 +2284,7 @@ public:
 
 	BfAstNode* mTarget;
 	BfTokenNode* mOpenBrace;
+	BfInlineTypeReference* mInlineTypeRef;
 	BfSizedArray<BfExpression*> mValues;
 	BfSizedArray<BfTokenNode*> mCommas;
 	BfTokenNode* mCloseBrace;
@@ -2453,9 +2456,16 @@ public:
 	BfSizedArray<BfTypeDeclaration*> mAnonymousTypes;
 	
 	bool IsAnonymous();	
+	bool IsAnonymousInitializerType();
 
 };	BF_AST_DECL(BfTypeDeclaration, BfAstNode);
 
+class BfInitializerTypeDeclaration : public BfTypeDeclaration
+{
+public:
+	BF_AST_TYPE(BfInitializerTypeDeclaration, BfTypeDeclaration);
+};	BF_AST_DECL(BfInitializerTypeDeclaration, BfTypeDeclaration);
+
 class BfTypeAliasDeclaration : public BfTypeDeclaration
 {
 public:
@@ -2965,6 +2975,14 @@ public:
 	BfSizedArray<BfTokenNode*> mCommas;
 };	BF_AST_DECL(BfObjectCreateExpression, BfMethodBoundExpression);
 
+class BfExtendExpression : public BfExpression
+{
+public:
+	BF_AST_TYPE(BfExtendExpression, BfExpression);
+	BfAstNode* mTarget;
+	BfTypeDeclaration* mTypeDecl;
+};	BF_AST_DECL(BfExtendExpression, BfExpression);
+
 class BfBoxExpression : public BfExpression
 {
 public:

+ 3 - 3
IDEHelper/Compiler/BfAutoComplete.cpp

@@ -2759,7 +2759,7 @@ bool BfAutoComplete::GetMethodInfo(BfMethodInstance* methodInst, StringImpl* sho
 	return false;
 }
 
-void BfAutoComplete::AddOverrides(const StringImpl& filter)
+void BfAutoComplete::AddOverrides(const StringImpl& filter, bool forceAll)
 {
 	if (!mIsAutoComplete)
 		return;
@@ -2780,7 +2780,7 @@ void BfAutoComplete::AddOverrides(const StringImpl& filter)
 			if (curType == mModule->mCurTypeInstance)
 			{
 				// The "normal" case, and only case for types without extensions
-				if (methodDef->mDeclaringType == activeTypeDef)
+				if ((methodDef->mDeclaringType == activeTypeDef) && (!forceAll))
 					continue;
 
 				if ((methodDef->mDeclaringType->IsExtension()) && (methodDef->mDeclaringType->mProject == activeTypeDef->mProject))
@@ -2812,7 +2812,7 @@ void BfAutoComplete::AddOverrides(const StringImpl& filter)
 				(methodDef->mMethodType != BfMethodType_PropertySetter))
 				continue;
 
-			if ((methodInst->mVirtualTableIdx >= 0) && (methodInst->mVirtualTableIdx < mModule->mCurTypeInstance->mVirtualMethodTable.size()))
+			if ((methodInst->mVirtualTableIdx >= 0) && (methodInst->mVirtualTableIdx < mModule->mCurTypeInstance->mVirtualMethodTable.size()) && (!forceAll))
 			{
 				auto& vEntry = mModule->mCurTypeInstance->mVirtualMethodTable[methodInst->mVirtualTableIdx];
 				if (vEntry.mImplementingMethod.mTypeInstance == mModule->mCurTypeInstance)

+ 1 - 1
IDEHelper/Compiler/BfAutoComplete.h

@@ -236,7 +236,7 @@ public:
 	void AddExtensionMethods(BfTypeInstance* targetType, BfTypeInstance* extensionContainer, const StringImpl& filter, bool allowProtected, bool allowPrivate);
 	void AddTopLevelNamespaces(BfAstNode* identifierNode);
 	void AddTopLevelTypes(BfAstNode* identifierNode, bool onlyAttribute = false);
-	void AddOverrides(const StringImpl& filter);
+	void AddOverrides(const StringImpl& filter, bool forceAll = false);
 	void AddCtorPassthroughs();
 	void UpdateReplaceData();
 	void AddTypeInstanceEntry(BfTypeInstance* typeInst);

+ 8 - 5
IDEHelper/Compiler/BfCompiler.cpp

@@ -4442,7 +4442,7 @@ void BfCompiler::ProcessAutocompleteTempType()
 		{
 			auto checkTypeDef = *actualTypeDefItr;
 			if ((!checkTypeDef->mIsPartial) /*&& (checkTypeDef->mTypeCode != BfTypeCode_Extension)*/ &&
-				((checkTypeDef->mTypeCode == tempTypeDef->mTypeCode) || (tempTypeDef->mTypeCode == BfTypeCode_Extension)))
+				((checkTypeDef->mTypeCode == tempTypeDef->mTypeCode) || (tempTypeDef->mTypeCode == BfTypeCode_Extension) || (tempTypeDef->mTypeCode == BfTypeCode_Inferred)))
 			{
 				if ((checkTypeDef->NameEquals(tempTypeDef)) && (checkTypeDef->mIsCombinedPartial) &&
 					(checkTypeDef->mGenericParamDefs.size() == tempTypeDef->mGenericParamDefs.size()) &&
@@ -4831,8 +4831,8 @@ void BfCompiler::ProcessAutocompleteTempType()
 	{
 		for (auto baseType : checkTypeDef->mBaseTypes)
 		{
-			autoComplete->CheckTypeRef(baseType, false);
-			module->ResolveTypeRef(baseType);
+			autoComplete->CheckTypeRef(BfNodeDynCast<BfTypeReference>(baseType), false);
+			module->ResolveTypeRef_Ref(baseType, BfPopulateType_Identity);
 		}
 		checkTypeDef = checkTypeDef->mOuterType;
 	}
@@ -5055,6 +5055,9 @@ void BfCompiler::ProcessAutocompleteTempType()
 
 BfType* BfCompiler::CheckSymbolReferenceTypeRef(BfModule* module, BfTypeReference* typeRef)
 {
+	if (typeRef == NULL)
+		return NULL;
+
 	//auto resolvedType = module->ResolveTypeRef(typeRef, BfPopulateType_Declaration,
 		//(BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue | BfResolveTypeRefFlag_AllowGenericTypeParamConstValue));
 	auto resolvedType = module->ResolveTypeRef(typeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowRef);
@@ -5271,7 +5274,7 @@ void BfCompiler::GetSymbolReferences()
 							SetAndRestoreValue<BfTypeState*> prevTypeState(module->mContext->mCurTypeState, &typeState);
 
 							for (auto baseTypeRef : checkTypeDef->mBaseTypes)
-								CheckSymbolReferenceTypeRef(module, baseTypeRef);
+								CheckSymbolReferenceTypeRef(module, BfNodeDynCast<BfTypeReference>(baseTypeRef));
 
 							for (auto genericParam : checkTypeDef->mGenericParamDefs)
 							{
@@ -5343,7 +5346,7 @@ void BfCompiler::GetSymbolReferences()
 		if (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Type)
 		{
 			for (auto baseTypeRef : typeDef->mBaseTypes)
-				CheckSymbolReferenceTypeRef(module, baseTypeRef);
+				CheckSymbolReferenceTypeRef(module, BfNodeDynCast<BfTypeReference>(baseTypeRef));
 		}
 
 		BfTypeState typeState;

+ 1 - 1
IDEHelper/Compiler/BfContext.cpp

@@ -1293,7 +1293,7 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
 	typeInst->mHasStaticInitMethod = false;
 	typeInst->mHasStaticMarkMethod = false;
 	typeInst->mHasStaticDtorMethod = false;
-	typeInst->mHasTLSFindMethod = false;
+	typeInst->mHasTLSFindMethod = false;	
 	typeInst->mBaseType = NULL;
 	delete typeInst->mCustomAttributes;
 	typeInst->mCustomAttributes = NULL;

+ 3 - 0
IDEHelper/Compiler/BfContext.h

@@ -166,6 +166,7 @@ public:
 	ResolveKind mResolveKind;
 	BfAstNode* mCurVarInitializer;
 	int mArrayInitializerSize;
+	BfTypeInstance* mInitializerBaseType;
 
 public:
 	BfTypeState()
@@ -185,6 +186,7 @@ public:
 		mCurVarInitializer = NULL;
 		mArrayInitializerSize = -1;
 		mResolveKind = ResolveKind_None;
+		mInitializerBaseType = NULL;
 	}
 
 	BfTypeState(BfType* type, BfTypeState* prevState = NULL)
@@ -203,6 +205,7 @@ public:
 		mCurVarInitializer = NULL;
 		mArrayInitializerSize = -1;
 		mResolveKind = ResolveKind_None;
+		mInitializerBaseType = NULL;
 	}
 };
 

+ 13 - 5
IDEHelper/Compiler/BfDefBuilder.cpp

@@ -1508,7 +1508,7 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
 	mCurTypeDef->mProject = mCurSource->mProject;
 	mCurTypeDef->mNamespace = mNamespace;
 	mSystem->AddNamespaceUsage(mCurTypeDef->mNamespace, mCurTypeDef->mProject);
-	if (typeDeclaration->mTypeNode == NULL)
+	if ((typeDeclaration->mTypeNode == NULL) && (!isAnonymous))
 	{
 		mCurTypeDef->mIsPartial = true;
 		mCurTypeDef->mIsExplicitPartial = true;
@@ -1750,7 +1750,11 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
 	if (typeDeclaration->mTypeNode != NULL)
 		typeToken = typeDeclaration->mTypeNode->GetToken();
 
-	if (typeDeclaration->mTypeNode == NULL)
+	if (typeDeclaration->IsAnonymousInitializerType())
+	{
+		mCurTypeDef->mTypeCode = BfTypeCode_Inferred;
+	}
+	else if (typeDeclaration->mTypeNode == NULL)
 	{
 		// Globals
 		mCurTypeDef->mTypeCode = BfTypeCode_Struct;
@@ -1852,6 +1856,9 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
 							(checkTypeDef->mIsFunction == mCurTypeDef->mIsFunction) &&
 							(checkTypeDef->mOuterType == actualOuterTypeDef);
 
+						if ((mCurTypeDef->mTypeCode == BfTypeCode_Inferred) && (checkTypeDef->mTypeDeclaration->IsAnonymousInitializerType()))
+							isCompatible = true;
+
 						if (isCompatible)
 						{
 							if (prevRevisionTypeDef == NULL)
@@ -1977,7 +1984,7 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
 	// Map methods into the correct index from previous revision
 	if (prevRevisionTypeDef != NULL)
 	{
-		BF_ASSERT(mCurTypeDef->mTypeCode == prevRevisionTypeDef->mTypeCode);
+		BF_ASSERT((mCurTypeDef->mTypeCode == prevRevisionTypeDef->mTypeCode) || (mCurTypeDef->mTypeCode == BfTypeCode_Inferred));
 
 		if (mCurTypeDef->mFullHash == prevRevisionTypeDef->mFullHash)
 		{
@@ -2280,7 +2287,8 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
 		needsDynamicCastMethod = false;
 	}
 
-	if ((mCurTypeDef->mTypeCode == BfTypeCode_Object) && (!mCurTypeDef->mIsStatic) && (ctorClear == NULL))
+	if (((mCurTypeDef->mTypeCode == BfTypeCode_Object) || (mCurTypeDef->mTypeCode == BfTypeCode_Inferred)) &&
+		(!mCurTypeDef->mIsStatic) && (ctorClear == NULL))
 	{
 		auto methodDef = AddMethod(mCurTypeDef, BfMethodType_CtorClear, BfProtection_Private, false, "", mIsComptime);
 		methodDef->mIsMutating = true;
@@ -2299,7 +2307,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
 	if ((needsStaticInit) && (staticCtor == NULL))
 	{
 		auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Ctor, BfProtection_Public, true, "", mIsComptime);
-	}
+	}	
 
 	bool makeCtorPrivate = hasCtor;
 

+ 1 - 0
IDEHelper/Compiler/BfElementVisitor.cpp

@@ -301,6 +301,7 @@ void BfElementVisitor::Visit(BfInitializerExpression* initExpr)
 
 	VisitChild(initExpr->mTarget);
 	VisitChild(initExpr->mOpenBrace);
+	VisitChild(initExpr->mInlineTypeRef);
 	for (auto& val : initExpr->mValues)
 		VisitChild(val);
 	for (auto& val : initExpr->mCommas)

+ 182 - 23
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -4184,7 +4184,7 @@ void BfExprEvaluator::Visit(BfStringInterpolationExpression* stringInterpolation
 		//
 		{
 			SetAndRestoreValue<BfEvalExprFlags> prevFlags(mBfEvalExprFlags, (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_NoAutoComplete));
-			CreateObject(NULL, stringInterpolationExpression->mAllocNode, stringType);
+			CreateObject(NULL, stringInterpolationExpression->mAllocNode, stringType, NULL);
 		}
 		BfTypedValue newString = mResult;
 		BF_ASSERT(newString);
@@ -8159,6 +8159,9 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
 					}
 				}
 
+				if (refNode == NULL)
+					refNode = methodInstance->GetOwner()->mTypeDef->GetRefNode();
+
 				if ((autoComplete != NULL) && (prevNode != NULL))
 					autoComplete->CheckEmptyStart(prevNode, wantType);
 
@@ -10128,6 +10131,8 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
 
 		if (resolvedTypeInstance != NULL)
 		{
+			auto origTypeInstance = resolvedTypeInstance;
+
 			if ((mBfEvalExprFlags & BfEvalExprFlags_AppendFieldInitializer) == 0)
 			{
 				if ((!resolvedTypeInstance->IsStruct()) && (!resolvedTypeInstance->IsTypedPrimitive()))
@@ -10173,10 +10178,12 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
 				structInst = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), resolvedTypeInstance, true);
 			}
 
+			bool doBind = false;
+
 			mResultLocalVar = NULL;
 			mResultFieldInstance = NULL;
 			mResultLocalVarRefNode = NULL;
-			auto result = MatchConstructor(targetSrc, methodBoundExpr, structInst, resolvedTypeInstance, argValues, false, BfMethodGenericArguments(), resolvedTypeInstance->IsObject());
+			BfTypedValue result = MatchConstructor(targetSrc, methodBoundExpr, structInst, resolvedTypeInstance, argValues, false, BfMethodGenericArguments(), resolvedTypeInstance->IsObject());
 			if ((result) && (!result.mType->IsVoid()))
 				return result;
 			mModule->ValidateAllocation(resolvedTypeInstance, targetSrc);
@@ -11297,7 +11304,7 @@ void BfExprEvaluator::LookupQualifiedStaticField(BfQualifiedNameNode* nameNode,
 	{
  		BfType* type = NULL;
 		{
-			type = mModule->ResolveTypeRef(nameNode->mLeft, NULL, BfPopulateType_Data, BfResolveTypeRefFlag_AllowRef);
+			type = mModule->ResolveTypeRef(nameNode->mLeft, NULL, BfPopulateType_Data, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_IgnoreLookupError));
 			mModule->CheckTypeRefFixit(nameNode->mLeft);
 		}
 		if (type != NULL)
@@ -11690,6 +11697,10 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
 			}
 		}
 	}
+	else if (auto objCreateExpr = BfNodeDynCast<BfObjectCreateExpression>(initExpr->mTarget))
+	{
+		CreateObject(objCreateExpr, objCreateExpr->mNewNode, NULL, initExpr->mInlineTypeRef);
+	}	
 	else
 		VisitChild(initExpr->mTarget);
 	if (!mResult)
@@ -11789,6 +11800,37 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
 		}
 		else
 		{
+			BfBlock* block = BfNodeDynCast<BfBlock>(elementExpr);
+			bool handled = false;
+
+			BfScopeData newScope;
+
+			if (block != NULL)
+			{
+				newScope.mInnerIsConditional = true;
+				newScope.mCloseNode = block;
+				if (block->mCloseBrace != NULL)
+					newScope.mCloseNode = block->mCloseBrace;					
+				mModule->mCurMethodState->AddScope(&newScope);
+				mModule->NewScopeState();
+
+				BfLocalVariable* localDef = new BfLocalVariable();
+				localDef->mName = "_";
+				localDef->mResolvedType = initValue.mType;					
+				localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
+				if (initValue.IsAddr())
+				{
+					localDef->mAddr = initValue.mValue;
+				}
+				else
+				{
+					localDef->mValue = initValue.mValue;
+					localDef->mIsSplat = initValue.IsSplat();
+				}
+				if (!localDef->mResolvedType->IsVar())
+					mModule->AddLocalVariableDef(localDef, true, true);	
+			}
+
 			auto autoComplete = GetAutoComplete();
 			if ((autoComplete != NULL) && (autoComplete->IsAutocompleteNode(elementExpr)))
 			{
@@ -11804,13 +11846,26 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
 				}
 			}
 
-			BfExprEvaluator exprEvaluator(mModule);
-			SizedArray<BfExpression*, 2> argExprs;
-			argExprs.push_back(elementExpr);
-			BfSizedArray<BfExpression*> sizedArgExprs(argExprs);
-			BfResolvedArgs argValues(&sizedArgExprs);
-			exprEvaluator.ResolveArgValues(argValues, BfResolveArgsFlag_DeferParamEval);
-			exprEvaluator.MatchMethod(elementExpr, NULL, initValue, false, false, "Add", argValues, BfMethodGenericArguments());
+			if ((block != NULL) && (!block->IsExpression()))
+			{
+				mModule->VisitCodeBlock(block);
+			}
+			else
+			{
+				BfExprEvaluator exprEvaluator(mModule);
+				SizedArray<BfExpression*, 2> argExprs;
+				argExprs.push_back(elementExpr);
+				BfSizedArray<BfExpression*> sizedArgExprs(argExprs);
+				BfResolvedArgs argValues(&sizedArgExprs);
+				exprEvaluator.ResolveArgValues(argValues, BfResolveArgsFlag_DeferParamEval);
+				exprEvaluator.MatchMethod(elementExpr, NULL, initValue, false, false, "Add", argValues, BfMethodGenericArguments());
+			}			
+
+			if (block != NULL)
+			{
+				mModule->RestoreScopeState();
+				handled = true;
+			}
 
 			wasValidInitKind = true;
 		}
@@ -11821,6 +11876,53 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
 		}
 	}
 
+	if (initExpr->mValues.IsEmpty())
+	{	
+		// When we are first typing out 'override', we 
+		if (initExpr->mInlineTypeRef != NULL)
+		{
+			if (auto defineBlock = BfNodeDynCast<BfBlock>(initExpr->mInlineTypeRef->mTypeDeclaration->mDefineNode))
+			{
+				if (defineBlock->mChildArr.mSize == 1)
+				{
+					auto lastNode = defineBlock->mChildArr[0];
+					if (lastNode->Equals("override"))
+					{
+						auto autoComplete = mModule->mCompiler->GetAutoComplete();
+						if (autoComplete != NULL)
+						{
+							int cursorIdx = autoComplete->GetCursorIdx(lastNode);
+							if ((autoComplete->IsAutocompleteNode(lastNode, 1)) && (cursorIdx == lastNode->GetSrcEnd()))
+							{
+								auto typeInst = initValue.mType->ToTypeInstance();
+								if (typeInst != NULL)
+								{
+									SetAndRestoreValue<BfTypeInstance*> prevTypeInst(mModule->mCurTypeInstance, typeInst);
+									SetAndRestoreValue<BfMethodInstance*> prevMethodInst(mModule->mCurMethodInstance, NULL);
+									autoComplete->AddOverrides("", true);
+									autoComplete->mInsertStartIdx = lastNode->mSrcStart;
+									autoComplete->mInsertEndIdx = lastNode->mSrcEnd;
+								}
+							}
+						}						
+					}
+				}
+			}
+		}
+	}
+	else
+	{
+		auto lastNode = initExpr->mValues.back();
+		if (auto lastIdentifier = BfNodeDynCast<BfIdentifierNode>(lastNode))
+		{
+			auto autoComplete = mModule->mCompiler->GetAutoComplete();
+			if (autoComplete != NULL)
+			{
+				autoComplete->CheckIdentifier(lastIdentifier, false, false);				
+			}
+		}		
+	}
+
 	if (unassignedFieldFlags != 0)
 	{
 		auto curBlock = mModule->mBfIRBuilder->GetInsertBlock();
@@ -15500,17 +15602,17 @@ void BfExprEvaluator::CheckObjectCreateTypeRef(BfType* expectingType, BfAstNode*
 
 void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr)
 {
-	CreateObject(objCreateExpr, objCreateExpr->mNewNode, NULL);
+	CreateObject(objCreateExpr, objCreateExpr->mNewNode, NULL, NULL);
 }
 
-void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAstNode* allocNode, BfType* wantAllocType)
-{
+void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAstNode* allocNode, BfType* wantAllocType, BfInlineTypeReference* inlineTypeRef)
+{	
 	auto autoComplete = GetAutoComplete();
 	if ((autoComplete != NULL) && (objCreateExpr != NULL) && (objCreateExpr->mTypeRef != NULL))
 	{
 		autoComplete->CheckTypeRef(objCreateExpr->mTypeRef, false, true);
 	}
-
+		
 	if ((autoComplete != NULL) && (objCreateExpr != NULL) && (objCreateExpr->mOpenToken != NULL) && (objCreateExpr->mCloseToken != NULL) &&
 		(objCreateExpr->mOpenToken->mToken == BfToken_LBrace) && (autoComplete->CheckFixit(objCreateExpr->mOpenToken)))
 	{
@@ -15744,6 +15846,16 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
 			resolvedTypeRef = unresolvedTypeRef;
 	}
 
+	if (inlineTypeRef != NULL)
+	{
+		auto inlineType = mModule->ResolveTypeRef(inlineTypeRef);
+		if (inlineType != NULL)
+		{
+			unresolvedTypeRef = inlineType;
+			resolvedTypeRef = inlineType;
+		}
+	}
+
 	if (resolvedTypeRef == NULL)
 	{
 		unresolvedTypeRef = mModule->GetPrimitiveType(BfTypeCode_Var);
@@ -16346,7 +16458,10 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
 		BfAstNode* refNode = objCreateExpr->mTypeRef;
 		if ((objCreateExpr->mCtorExplicit != NULL) && (objCreateExpr->mCtorExplicit->mThisToken != NULL))
 			refNode = objCreateExpr->mCtorExplicit->mThisToken;
-		MatchConstructor(refNode, objCreateExpr, emtpyThis, typeInstance, argValues, false, methodGenericArguments, true);
+		auto checkTypeInst = typeInstance;
+		if (checkTypeInst->IsAnonymousInitializerType())
+			checkTypeInst = checkTypeInst->mBaseType;
+		MatchConstructor(refNode, objCreateExpr, emtpyThis, checkTypeInst, argValues, false, methodGenericArguments, true);
 		if ((wasCapturingMethodInfo) && (!autoComplete->mIsCapturingMethodMatchInfo))
 		{
 			if (autoComplete->mMethodMatchInfo != NULL)
@@ -16360,7 +16475,11 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
 		auto refNode = allocNode;
 		if (objCreateExpr != NULL)
 			refNode = objCreateExpr->mTypeRef;
-		MatchConstructor(refNode, objCreateExpr, emtpyThis, typeInstance, argValues, false, methodGenericArguments, true);
+
+		auto checkTypeInst = typeInstance;
+		if (checkTypeInst->IsAnonymousInitializerType())
+			checkTypeInst = checkTypeInst->mBaseType;
+		MatchConstructor(refNode, objCreateExpr, emtpyThis, checkTypeInst, argValues, false, methodGenericArguments, true);
 	}
 	if (objCreateExpr != NULL)
 		mModule->ValidateAllocation(typeInstance, objCreateExpr->mTypeRef);
@@ -16471,10 +16590,9 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
 		}
 		else if (bindResult.mFunc)
 		{
-			if (typeInstance->IsObject())
+			bool hasRealtimeLeakCheck = (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!IsComptime());
+			if ((typeInstance->IsObject()) || (typeInstance->IsAnonymousInitializerType()))
 			{
-				bool hasRealtimeLeakCheck = (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!IsComptime());
-
 				bool wantsCtorClear = true;
 				if (hasRealtimeLeakCheck)
 				{
@@ -16497,7 +16615,10 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
 						CreateCall(objCreateExpr, ctorClear.mMethodInstance, ctorClear.mFunc, false, irArgs);
 					}
 				}
+			}
 
+			if (typeInstance->IsObject())
+			{				
 				if ((!mModule->mIsComptimeModule) && (isStackAlloc) && (hasRealtimeLeakCheck))
 				{
 					BfMethodInstance* markMethod = mModule->GetRawMethodByName(mModule->mContext->mBfObjectType, "GCMarkMembers");
@@ -16560,23 +16681,56 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
 				}
 			}
 
+			auto origThisTypedValue = mResult;
+			auto thisTypedValue = mResult;			
+			if (inlineTypeRef != NULL)
+			{
+				BfType* wantType = bindResult.mMethodInstance->GetOwner();
+				if (thisTypedValue.mType->IsPointer())
+					wantType = mModule->CreatePointerType(wantType);
+				thisTypedValue = mModule->Cast(allocNode, thisTypedValue, wantType);
+			}
+
 			if ((bindResult.mMethodInstance->mMethodDef->mHasAppend) && (mResult.mType->IsObject()))
 			{
 				BF_ASSERT(bindResult.mIRArgs[0].IsFake());
 				auto typeInst = mResult.mType->ToTypeInstance();
-				auto intPtrType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
-				auto thisVal = mResult;
+				auto intPtrType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);				
 				BfIRValue intPtrVal = mModule->CreateAlloca(intPtrType);
-				auto intPtrThisVal = mModule->mBfIRBuilder->CreatePtrToInt(thisVal.mValue, (intPtrType->mSize == 4) ? BfTypeCode_Int32 : BfTypeCode_Int64);
+				auto intPtrThisVal = mModule->mBfIRBuilder->CreatePtrToInt(thisTypedValue.mValue, (intPtrType->mSize == 4) ? BfTypeCode_Int32 : BfTypeCode_Int64);
 				auto curValPtr = mModule->mBfIRBuilder->CreateAdd(intPtrThisVal, mModule->GetConstValue(typeInst->mInstSize, intPtrType));
 				mModule->mBfIRBuilder->CreateStore(curValPtr, intPtrVal);
 				bindResult.mIRArgs[0] = intPtrVal;
 			}
 			if (!typeInstance->IsValuelessType())
-				bindResult.mIRArgs.Insert(0, mResult.mValue);
+				bindResult.mIRArgs.Insert(0, thisTypedValue.mValue);
 			auto result = CreateCall(objCreateExpr, bindResult.mMethodInstance, bindResult.mFunc, false, bindResult.mIRArgs);
 			if ((result) && (!result.mType->IsVoid()))
 				mResult = result;
+
+			if (origThisTypedValue.mType != thisTypedValue.mType)
+			{
+				auto origThisType = origThisTypedValue.mType;
+				if (origThisType->IsPointer())
+					origThisType = origThisType->GetUnderlyingType();
+				auto origThisTypeInst = origThisType->ToTypeInstance();
+				if (origThisTypeInst != NULL)
+				{
+					BF_ASSERT(origThisTypeInst->IsAnonymousInitializerType());
+
+					auto ctorMethod = mModule->GetMethodByName(origThisTypeInst, "__BfCtor", 0);
+					if (!ctorMethod)
+					{
+						mModule->AssertErrorState();
+					}
+					else if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) == 0)
+					{
+						SizedArray<BfIRValue, 1> irArgs;
+						irArgs.push_back(origThisTypedValue.mValue);
+						CreateCall(objCreateExpr, ctorMethod.mMethodInstance, ctorMethod.mFunc, false, irArgs);
+					}
+				}
+			}
 		}
 	}
 
@@ -19114,6 +19268,11 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
 }
 
 void BfExprEvaluator::Visit(BfInvocationExpression* invocationExpr)
+{
+	DoInvocation(invocationExpr);
+}
+
+void BfExprEvaluator::DoInvocation(BfInvocationExpression* invocationExpr)
 {
 	BfAutoParentNodeEntry autoParentNodeEntry(mModule, invocationExpr);
 

+ 2 - 1
IDEHelper/Compiler/BfExprEvaluator.h

@@ -506,6 +506,7 @@ public:
 	BfModuleMethodInstance GetSelectedMethod(BfMethodMatcher& methodMatcher);
 	bool CheckVariableDeclaration(BfAstNode* checkNode, bool requireSimpleIfExpr, bool exprMustBeTrue, bool silentFail);
 	bool HasVariableDeclaration(BfAstNode* checkNode);
+	void DoInvocation(BfInvocationExpression* invocationExpr);
 	void DoInvocation(BfAstNode* target, BfMethodBoundExpression* methodBoundExpr, const BfSizedArray<BfExpression*>& args, const BfMethodGenericArguments& methodGenericArgs, BfTypedValue* outCascadeValue = NULL);
 	int GetMixinVariable();
 	void CheckLocalMethods(BfAstNode* targetSrc, BfTypeInstance* typeInstance, const StringImpl& methodName, BfMethodMatcher& methodMatcher, BfMethodType methodType);
@@ -538,7 +539,7 @@ public:
 	void InitializedSizedArray(BfSizedArrayType* sizedArrayType, BfTokenNode* openToken, const BfSizedArray<BfExpression*>& values, const BfSizedArray<BfTokenNode*>& commas, BfTokenNode* closeToken, BfTypedValue* receivingValue = NULL);
 	void CheckDotToken(BfTokenNode* tokenNode);
 	void DoMemberReference(BfMemberReferenceExpression* memberRefExpr, BfTypedValue* outCascadeValue);
-	void CreateObject(BfObjectCreateExpression* objCreateExpr, BfAstNode* allocNode, BfType* allocType);
+	void CreateObject(BfObjectCreateExpression* objCreateExpr, BfAstNode* allocNode, BfType* allocType, BfInlineTypeReference* inlineTypeRef);
 	void HandleIndexerExpression(BfIndexerExpression* indexerExpr, BfTypedValue target);
 
 	//////////////////////////////////////////////////////////////////////////

+ 2 - 1
IDEHelper/Compiler/BfIRBuilder.h

@@ -118,7 +118,8 @@ enum BfTypeCode : uint8
 	BfTypeCode_Int64X2,
 	BfTypeCode_Int64X3,
 	BfTypeCode_Int64X4,
-	BfTypeCode_Length
+	BfTypeCode_Length,
+	BfTypeCode_Inferred
 };
 
 enum BfConstType

+ 11 - 6
IDEHelper/Compiler/BfModule.cpp

@@ -18194,7 +18194,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
 	auto methodDeclaration = methodDef->mMethodDeclaration;
 	auto ctorDeclaration = (BfConstructorDeclaration*)methodDef->mMethodDeclaration;
 	auto typeDef = mCurTypeInstance->mTypeDef;
-
+		
 	BfCustomAttributes* customAttributes = NULL;
 	defer(delete customAttributes);
 	BfInvocationExpression* ctorInvocation = NULL;
@@ -18230,7 +18230,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
 	}
 
 	// Zero out memory for default ctor
-	if ((methodDeclaration == NULL) && (mCurTypeInstance->IsStruct()) && (methodInstance->mChainType != BfMethodChainType_ChainMember) &&
+	if ((methodDeclaration == NULL) && (mCurTypeInstance->IsStruct()) && (!mCurTypeInstance->IsAnonymousInitializerType()) && (methodInstance->mChainType != BfMethodChainType_ChainMember) &&
 		(!mCurMethodState->mLocals.IsEmpty()))
 	{
 		if (mCurTypeInstance->IsTypedPrimitive())
@@ -18593,6 +18593,8 @@ void BfModule::EmitCtorBody(bool& skipBody)
     	targetRefNode = ctorDeclaration->mInitializer;
 	if (auto invocationExpr = BfNodeDynCast<BfInvocationExpression>(targetRefNode))
 		targetRefNode = invocationExpr->mTarget;
+	if (targetRefNode == NULL)
+		targetRefNode = mCurTypeInstance->mTypeDef->GetRefNode();
 
 	if (baseCtorNode != NULL)
 	{
@@ -18687,7 +18689,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
 				targetType = mCurTypeInstance->mBaseType;
 				if (ctorDeclaration != NULL)
 					targetRefNode = ctorDeclaration->mThisToken;
-				else if (typeDef->mTypeDeclaration != NULL)
+				else if ((typeDef->mTypeDeclaration != NULL) && (typeDef->mTypeDeclaration->mNameNode != NULL))
 					targetRefNode = typeDef->mTypeDeclaration->mNameNode;
 			}
 		}
@@ -18717,7 +18719,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
 	}
 
 	auto autoComplete = mCompiler->GetAutoComplete();
-	if (targetType != NULL)
+	if ((targetType != NULL) && (!mCurTypeInstance->IsAnonymousInitializerType()))
 	{
 		BfAstNode* refNode = methodDeclaration;
 		if (refNode == NULL)
@@ -20615,7 +20617,10 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
 		if ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule) && (methodDef->mBody != NULL) && (!mCurTypeInstance->IsBoxed()))
 		{
 			if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(methodDef->mBody))
+			{
+				SetAndRestoreValue<bool> prevSkipAnonTypes(sourceClassifier->mSkipAnonymousTypes, true);
 				sourceClassifier->VisitChildNoRef(methodDef->mBody);
+			}
 		}
 	}
 
@@ -21727,13 +21732,13 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
 		mCurMethodState->mLeftBlockUncond = true;
 	}
 	else if (methodDef->mMethodType == BfMethodType_CtorClear)
-	{
+	{		
 		SetIllegalSrcPos();
 		mBfIRBuilder->ClearDebugLocation();
 		PopulateType(mCurTypeInstance, BfPopulateType_Data);
 		auto thisVal = GetThis();
 		int prevSize = 0;
-		if (mContext->mBfObjectType != NULL)
+		if ((mContext->mBfObjectType != NULL) && (mCurTypeInstance->IsObject()))
 		{
 			prevSize = mContext->mBfObjectType->mInstSize;
 			PopulateType(mContext->mBfObjectType);

+ 1 - 0
IDEHelper/Compiler/BfModule.h

@@ -1981,6 +1981,7 @@ public:
 	BfType* ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0, bool resolveGenericParam = true);
 	BfType* ResolveTypeRef_Type(BfAstNode* astNode, const BfSizedArray<BfAstNode*>* genericArgs, BfPopulateType populateType, BfResolveTypeRefFlags& resolveFlags);
 	BfType* ResolveTypeRef_Ref(BfAstNode* astNode, const BfSizedArray<BfAstNode*>* genericArgs, BfPopulateType populateType, BfResolveTypeRefFlags& resolveFlags);
+	BfType* ResolveTypeRef_Ref(BfAstNode* astNode, BfPopulateType populateType);
 	BfType* ResolveTypeRef(BfAstNode* astNode, const BfSizedArray<BfAstNode*>* genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0);
 
 	BfType* ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None);

+ 16 - 2
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -1660,6 +1660,7 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
 		case BfTypeCode_Interface:
 		case BfTypeCode_Enum:
 		case BfTypeCode_TypeAlias:
+		case BfTypeCode_Inferred:
 			// Implemented below
 			break;
 		case BfTypeCode_Extension:
@@ -4179,6 +4180,8 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 	{
 		baseType = ResolveTypeDef(mCompiler->mValueTypeTypeDef, BfPopulateType_Data)->ToTypeInstance();
 	}
+	else if (typeDef->mTypeCode == BfTypeCode_Inferred)
+		baseType = mContext->mBfObjectType;
 
 	if (baseType != NULL)
 		defaultBaseTypeInst = baseType->ToTypeInstance();
@@ -4193,7 +4196,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 
 	bool wantPopulateInterfaces = false;
 
-	BfTypeReference* baseTypeRef = NULL;
+	BfAstNode* baseTypeRef = NULL;
 	if ((typeDef->mIsDelegate) && (!typeInstance->IsClosure()))
 	{
 		if (mCompiler->mDelegateTypeDef == NULL)
@@ -4229,7 +4232,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 			SetAndRestoreValue<BfTypeDefineState> prevDefineState(typeInstance->mDefineState, BfTypeDefineState_ResolvingBaseType);
 
 			bool populateBase = !typeInstance->mTypeFailed;
-			BfType* checkType = checkType = ResolveTypeRef(checkTypeRef, BfPopulateType_Declaration);
+			BfType* checkType = checkType = ResolveTypeRef_Ref(checkTypeRef, BfPopulateType_Declaration);
 
 			if ((checkType != NULL) && (!checkType->IsInterface()) && (populateBase))
 			{
@@ -4415,6 +4418,8 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 	if (baseType != NULL)
 	{
 		baseTypeInst = baseType->ToTypeInstance();
+		if ((baseTypeInst != NULL) && (typeDef->mTypeCode == BfTypeCode_Inferred))
+			typeDef->mTypeCode = baseTypeInst->mTypeDef->mTypeCode;
 	}
 
 	if (typeInstance->mBaseType != NULL)
@@ -12967,6 +12972,9 @@ BfType* BfModule::ResolveTypeRef_Ref(BfAstNode* astNode, const BfSizedArray<BfAs
 	if (auto typeRef = BfNodeDynCast<BfTypeReference>(astNode))
 		return ResolveTypeRef_Ref(typeRef, populateType, resolveFlags, 0);
 
+	if (astNode->IsTemporary())
+		return ResolveTypeRef((BfTypeReference*)astNode, populateType, resolveFlags);
+
 	if ((resolveFlags & BfResolveTypeRefFlag_AllowImplicitConstExpr) != 0)
 	{
 		if (auto expr = BfNodeDynCast<BfExpression>(astNode))
@@ -12993,6 +13001,12 @@ BfType* BfModule::ResolveTypeRef_Ref(BfAstNode* astNode, const BfSizedArray<BfAs
 	return ResolveTypeRef_Type(astNode, genericArgs, populateType, resolveFlags);
 }
 
+BfType* BfModule::ResolveTypeRef_Ref(BfAstNode* astNode, BfPopulateType populateType)
+{
+	BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None;
+	return ResolveTypeRef_Ref(astNode, NULL, populateType, resolveFlags);
+}
+
 // This flow should mirror CastToValue
 bool BfModule::CanCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags)
 {

+ 14 - 7
IDEHelper/Compiler/BfParser.cpp

@@ -112,17 +112,19 @@ static int gCurFreeId;
 int BfParseFileData::GetUniqueId(int idx)
 {
 	AutoCrit autoCrit(gParseFileDataCrit);
-	while (idx >= mUniqueIDList.size())
+
+	int* valuePtr = NULL;
+	if (mUniqueIDList.TryAdd(idx, NULL, &valuePtr))
 	{
 		if (!gFreeIds.IsEmpty())
 		{
-			mUniqueIDList.Add(gFreeIds.back());
+			*valuePtr = gFreeIds.back();
 			gFreeIds.pop_back();
 		}
 		else
-			mUniqueIDList.Add(gCurFreeId++);
-	}
-	return mUniqueIDList[idx];
+			*valuePtr = gCurFreeId++;
+	}	
+	return *valuePtr;
 }
 
 BfParseFileData::~BfParseFileData()
@@ -130,8 +132,8 @@ BfParseFileData::~BfParseFileData()
 	if (!mUniqueIDList.IsEmpty())
 	{
 		AutoCrit autoCrit(gParseFileDataCrit);
-		for (auto id : mUniqueIDList)
-			gFreeIds.Add(id);
+		for (auto kv : mUniqueIDList)
+			gFreeIds.Add(kv.mValue);
 	}
 }
 
@@ -442,6 +444,7 @@ BfParser::BfParser(BfSystem* bfSystem, BfProject* bfProject) : BfSource(bfSystem
 	mTriviaStart = 0;
 	mParsingFailed = false;
 	mInAsmBlock = false;
+	mCurBlockId = 0;
 	mPreprocessorIgnoredSectionNode = NULL;
 	mPreprocessorIgnoreDepth = 0;
 	mAddedDependsDefines = false;
@@ -856,7 +859,10 @@ BfBlock* BfParser::ParseInlineBlock(int spaceIdx, int endIdx)
 		if (startNode == NULL)
 			startNode = childNode;
 		if (block == NULL)
+		{
 			block = mAlloc->Alloc<BfBlock>();
+			block->mParserBlockId = ++mCurBlockId;
+		}
 		block->Add(childNode);
 		childArr.push_back(childNode);
 		//block->mChildArr.Add(childNode, &mAlloc);
@@ -3644,6 +3650,7 @@ void BfParser::ParseBlock(BfBlock* astNode, int depth, bool isInterpolate)
 			else*/
 			{
 				genBlock = mAlloc->Alloc<BfBlock>();
+				genBlock->mParserBlockId = ++mCurBlockId;
 				genBlock->mOpenBrace = (BfTokenNode*)CreateNode();
 				newBlock = genBlock;
 			}

+ 2 - 1
IDEHelper/Compiler/BfParser.h

@@ -65,7 +65,7 @@ enum MaybeBool
 class BfParseFileData
 {
 public:
-	Array<int> mUniqueIDList;
+	Dictionary<int, int> mUniqueIDList;
 	int mRefCount;
 
 public:
@@ -198,6 +198,7 @@ public:
 	int mLineStart;
 	int mLineNum;
 	bool mInAsmBlock;
+	int mCurBlockId;
 
 	BfParserFlag mParserFlags;
 	int mCursorIdx;

File diff suppressed because it is too large
+ 744 - 521
IDEHelper/Compiler/BfReducer.cpp


+ 7 - 3
IDEHelper/Compiler/BfReducer.h

@@ -170,8 +170,7 @@ public:
 	BfResolvePassData* mResolvePassData;
 	BfAstNode* mTypeMemberNodeStart;
 	int mClassDepth;
-	int mMethodDepth;
-	int mCurUniqueIdx;
+	int mMethodDepth;	
 	BfTypeDeclaration* mCurTypeDecl;
 	CurTypeState* mCurTypeState;
 	BfTypeDeclaration* mLastTypeDecl;
@@ -211,10 +210,12 @@ public:
 
 	void AssertCurrentNode(BfAstNode* node);
 	bool IsNodeRelevant(BfAstNode* astNode);
+	bool IsCursorInside(BfAstNode* astNode);
 	bool IsNodeRelevant(BfAstNode* startNode, BfAstNode* endNode);
 	void MoveNode(BfAstNode* srcNode, BfAstNode* newOwner);
 	void ReplaceNode(BfAstNode* prevNode, BfAstNode* newNode);
 	
+	void InitAnonymousType(BfTypeDeclaration* typeDecl);
 	bool CheckInlineTypeRefAttribute(BfAstNode* typeRef, BfAttributeDirective* attributes);
 	void CheckMultiuseAttributeTypeRef(BfAstNode* typeRef);
 	bool SetProtection(BfAstNode* parentNode, BfAstNode*& protectionNodeRef, BfTokenNode* tokenNode);
@@ -280,7 +281,10 @@ public:
 	BfInlineAsmStatement* CreateInlineAsmStatement(BfAstNode* asmNode);
 
 	void HandleBlock(BfBlock* block, bool allowEndingExpression = false);
-	void HandleTypeDeclaration(BfTypeDeclaration* typeDecl, BfAttributeDirective* attributes, BfAstNode* deferredHeadNode = NULL);
+	bool IsInitializerStatement(int checkIdx);
+	bool IsInitializerStatement(BfAstNode* node);
+	bool InitializerBlockHasInlineTypeDecl(BfBlock* block);
+	void HandleTypeDeclaration(BfTypeDeclaration* typeDecl, BfAttributeDirective* attributes, BfAstNode* deferredHeadNode = NULL, bool findInitializer = false);
 
 public:
 	BfReducer();

+ 5 - 0
IDEHelper/Compiler/BfResolvedTypeUtils.cpp

@@ -2455,6 +2455,11 @@ bool BfTypeInstance::IsAnonymous()
 	return (mTypeDef->mTypeDeclaration != NULL) && (mTypeDef->mTypeDeclaration->IsAnonymous());
 }
 
+bool BfTypeInstance::IsAnonymousInitializerType()
+{
+	return (mTypeDef->mTypeDeclaration != NULL) && (mTypeDef->mTypeDeclaration->IsAnonymousInitializerType());
+}
+
 void BfTypeInstance::ReportMemory(MemReporter* memReporter)
 {
 	if (mGenericTypeInfo != NULL)

+ 1 - 0
IDEHelper/Compiler/BfResolvedTypeUtils.h

@@ -2206,6 +2206,7 @@ public:
 	bool IncludeAllMethods() { return ((mAlwaysIncludeFlags & BfAlwaysIncludeFlag_IncludeAllMethods) != 0); }
 	bool DefineStateAllowsStaticMethods() { return mDefineState >= BfTypeDefineState_HasInterfaces_Direct; }
 	bool IsAnonymous();
+	bool IsAnonymousInitializerType();
 
 	virtual void ReportMemory(MemReporter* memReporter) override;
 };

+ 4 - 0
IDEHelper/Compiler/BfSourceClassifier.cpp

@@ -18,6 +18,7 @@ BfSourceClassifier::BfSourceClassifier(BfParser* bfParser, CharData* charData)
 	mPrevNode = NULL;
 	mCurMember = NULL;
 	mCurLocalMethodDeclaration = NULL;
+	mSkipAnonymousTypes = false;
 }
 
 void BfSourceClassifier::ModifyFlags(BfAstNode* node, uint8 andFlags, uint8 orFlags)
@@ -657,6 +658,9 @@ void BfSourceClassifier::Visit(BfPropertyDeclaration* propertyDeclaration)
 
 void BfSourceClassifier::Visit(BfTypeDeclaration* typeDeclaration)
 {
+	if ((mSkipAnonymousTypes) && (typeDeclaration->IsAnonymous()))
+		return;
+
 	if (typeDeclaration->mIgnoreDeclaration)
 		return;
 

+ 1 - 0
IDEHelper/Compiler/BfSourceClassifier.h

@@ -69,6 +69,7 @@ public:
 	bool mSkipAttributes;
 	bool mIsSideChannel;
 	bool mPreserveFlags;
+	bool mSkipAnonymousTypes;
 	uint8 mClassifierPassId;
 	BfAstNode* mPrevNode;
 	BfAstNode* mCurMember;

+ 1 - 1
IDEHelper/Compiler/BfSystem.cpp

@@ -3044,7 +3044,7 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef)
 
 	typeDef->mProtection = nextTypeDef->mProtection;
 
-	BF_ASSERT(typeDef->mTypeCode == nextTypeDef->mTypeCode);
+	BF_ASSERT((typeDef->mTypeCode == nextTypeDef->mTypeCode) || (nextTypeDef->mTypeCode == BfTypeCode_Inferred));
 
 	typeDef->mTypeCode = nextTypeDef->mTypeCode;
 	typeDef->mShow = nextTypeDef->mShow;

+ 38 - 0
IDEHelper/Tests/src/Anonymous.bf

@@ -30,6 +30,21 @@ class Anonymous
 		} mCoords;
 	}
 
+	struct StructC
+	{
+		public int mA;
+
+		public this(int a)
+		{
+			mA = a;
+		}
+	}
+
+	class ClassA
+	{
+		public int Val = 123;
+	}
+
 	[Test]
 	public static void TestBasics()
 	{
@@ -47,5 +62,28 @@ class Anonymous
 		StructB sb = default;
 		sb.mX = 345;
 		Test.Assert(sb.mY == 345);
+
+		var sc = StructC(456)
+			{
+				public int mB = 567;
+
+				{
+					_.mB += 1000;
+				},
+				mB += 10000
+			};
+		Test.Assert(sc.mA == 456);
+		Test.Assert(sc.mB == 11567);
+
+		var ca = scope ClassA()
+			{
+				public override void ToString(String strBuffer)
+				{
+					strBuffer.Append("ClassA override");
+				}
+			};
+
+		var str = ca.ToString(.. scope .());
+		Test.Assert(str == "ClassA override");
 	}
 }

Some files were not shown because too many files changed in this diff