mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 04:22:20 +02:00
Fixed errors for circular data references in member attributes
This commit is contained in:
parent
07a0972366
commit
3486251254
5 changed files with 124 additions and 61 deletions
|
@ -119,7 +119,7 @@ public:
|
||||||
BfPopulateType mPopulateType;
|
BfPopulateType mPopulateType;
|
||||||
BfTypeReference* mCurBaseTypeRef;
|
BfTypeReference* mCurBaseTypeRef;
|
||||||
BfTypeReference* mCurAttributeTypeRef;
|
BfTypeReference* mCurAttributeTypeRef;
|
||||||
BfFieldDef* mCurFieldDef;
|
BfFieldDef* mCurFieldDef;
|
||||||
BfTypeDef* mCurTypeDef;
|
BfTypeDef* mCurTypeDef;
|
||||||
bool mBuildingGenericParams;
|
bool mBuildingGenericParams;
|
||||||
|
|
||||||
|
|
|
@ -2066,6 +2066,7 @@ BfExprEvaluator::BfExprEvaluator(BfModule* module)
|
||||||
mIsHeapReference = false;
|
mIsHeapReference = false;
|
||||||
mResultIsTempComposite = false;
|
mResultIsTempComposite = false;
|
||||||
mAllowReadOnlyReference = false;
|
mAllowReadOnlyReference = false;
|
||||||
|
mInsidePendingNullable = false;
|
||||||
mReceivingValue = NULL;
|
mReceivingValue = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2167,6 +2168,7 @@ void BfExprEvaluator::Evaluate(BfAstNode* astNode, bool propogateNullConditional
|
||||||
if (!propogateNullConditional)
|
if (!propogateNullConditional)
|
||||||
mModule->mCurMethodState->mPendingNullConditional = NULL;
|
mModule->mCurMethodState->mPendingNullConditional = NULL;
|
||||||
}
|
}
|
||||||
|
mInsidePendingNullable = pendingNullCond != NULL;
|
||||||
|
|
||||||
astNode->Accept(this);
|
astNode->Accept(this);
|
||||||
GetResult();
|
GetResult();
|
||||||
|
@ -5634,6 +5636,11 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType
|
||||||
bool isLet = variableDeclaration->mTypeRef->IsExact<BfLetTypeReference>();
|
bool isLet = variableDeclaration->mTypeRef->IsExact<BfLetTypeReference>();
|
||||||
bool isVar = variableDeclaration->mTypeRef->IsExact<BfVarTypeReference>();
|
bool isVar = variableDeclaration->mTypeRef->IsExact<BfVarTypeReference>();
|
||||||
|
|
||||||
|
if (mModule->mCurMethodState->mPendingNullConditional != NULL)
|
||||||
|
{
|
||||||
|
mModule->Fail("Variables cannot be declared in method arguments inside null conditional expressions", variableDeclaration);
|
||||||
|
}
|
||||||
|
|
||||||
if ((!isLet) && (!isVar))
|
if ((!isLet) && (!isVar))
|
||||||
{
|
{
|
||||||
mModule->Fail("Only 'ref' or 'var' variables can be declared in method arguments", variableDeclaration);
|
mModule->Fail("Only 'ref' or 'var' variables can be declared in method arguments", variableDeclaration);
|
||||||
|
@ -12237,7 +12244,8 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
|
||||||
|
|
||||||
argExprEvaluators.push_back(new BfExprEvaluator(mModule));
|
argExprEvaluators.push_back(new BfExprEvaluator(mModule));
|
||||||
BfExprEvaluator* exprEvaluator = argExprEvaluators.back();
|
BfExprEvaluator* exprEvaluator = argExprEvaluators.back();
|
||||||
exprEvaluator->mResolveGenericParam = false;
|
exprEvaluator->mResolveGenericParam = false;
|
||||||
|
exprEvaluator->mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator->mBfEvalExprFlags | BfEvalExprFlags_NoCast | BfEvalExprFlags_AllowRefExpr | BfEvalExprFlags_AllowOutExpr);
|
||||||
if (argExpr != NULL)
|
if (argExpr != NULL)
|
||||||
exprEvaluator->Evaluate(argExpr, false, false, true);
|
exprEvaluator->Evaluate(argExpr, false, false, true);
|
||||||
auto argValue = exprEvaluator->mResult;
|
auto argValue = exprEvaluator->mResult;
|
||||||
|
@ -12634,6 +12642,37 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
|
||||||
{
|
{
|
||||||
// Already handled
|
// Already handled
|
||||||
}
|
}
|
||||||
|
else if (newLocalVar->mIsSplat)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
auto checkMethodState = mModule->mCurMethodState;
|
||||||
|
while ((checkMethodState != NULL) && (!found))
|
||||||
|
{
|
||||||
|
for (auto localVar : checkMethodState->mLocals)
|
||||||
|
{
|
||||||
|
if (localVar == newLocalVar)
|
||||||
|
continue;
|
||||||
|
if (newLocalVar->mValue != localVar->mValue)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
String name = newLocalVar->mName;
|
||||||
|
name += "$alias$";
|
||||||
|
name += localVar->mName;
|
||||||
|
|
||||||
|
auto fakeValue = mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 0);
|
||||||
|
auto diType = mModule->mBfIRBuilder->DbgGetType(mModule->GetPrimitiveType(BfTypeCode_Int32));
|
||||||
|
auto diVariable = mModule->mBfIRBuilder->DbgCreateAutoVariable(mModule->mCurMethodState->mCurScope->mDIScope,
|
||||||
|
newLocalVar->mName, mModule->mCurFilePosition.mFileInstance->mDIFile, mModule->mCurFilePosition.mCurLine, diType);
|
||||||
|
mModule->mBfIRBuilder->DbgInsertValueIntrinsic(fakeValue, diVariable);
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkMethodState = checkMethodState->mPrevMethodState;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (mModule->IsTargetingBeefBackend())
|
else if (mModule->IsTargetingBeefBackend())
|
||||||
{
|
{
|
||||||
mModule->UpdateSrcPos(methodDeclaration->mNameNode);
|
mModule->UpdateSrcPos(methodDeclaration->mNameNode);
|
||||||
|
@ -12707,7 +12746,7 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
|
||||||
if (!mModule->mBfIRBuilder->mIgnoreWrites)
|
if (!mModule->mBfIRBuilder->mIgnoreWrites)
|
||||||
{
|
{
|
||||||
if (newLocalVar->mIsSplat)
|
if (newLocalVar->mIsSplat)
|
||||||
{
|
{
|
||||||
//TODO: Implement
|
//TODO: Implement
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -16635,7 +16674,13 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkResultAssigned();
|
if (mInsidePendingNullable)
|
||||||
|
{
|
||||||
|
// 'out' inside null conditionals never actually causes a definite assignment...
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MarkResultAssigned();
|
||||||
|
|
||||||
MarkResultUsed();
|
MarkResultUsed();
|
||||||
ResolveGenericType();
|
ResolveGenericType();
|
||||||
mResult = BfTypedValue(mResult.mValue, mModule->CreateRefType(mResult.mType, BfRefType::RefKind_Out));
|
mResult = BfTypedValue(mResult.mValue, mModule->CreateRefType(mResult.mType, BfRefType::RefKind_Out));
|
||||||
|
|
|
@ -308,6 +308,7 @@ public:
|
||||||
bool mIsHeapReference;
|
bool mIsHeapReference;
|
||||||
bool mResultIsTempComposite;
|
bool mResultIsTempComposite;
|
||||||
bool mAllowReadOnlyReference;
|
bool mAllowReadOnlyReference;
|
||||||
|
bool mInsidePendingNullable;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BfExprEvaluator(BfModule* module);
|
BfExprEvaluator(BfModule* module);
|
||||||
|
|
|
@ -14327,7 +14327,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AssertErrorState();
|
// Failed
|
||||||
}
|
}
|
||||||
auto assignValue = GetFieldInitializerValue(fieldInst);
|
auto assignValue = GetFieldInitializerValue(fieldInst);
|
||||||
if ((fieldAddr) && (assignValue))
|
if ((fieldAddr) && (assignValue))
|
||||||
|
|
|
@ -57,6 +57,7 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfGenericTypeInstan
|
||||||
}
|
}
|
||||||
|
|
||||||
BfTypeState typeState;
|
BfTypeState typeState;
|
||||||
|
typeState.mPrevState = mContext->mCurTypeState;
|
||||||
typeState.mTypeInstance = genericTypeInst;
|
typeState.mTypeInstance = genericTypeInst;
|
||||||
typeState.mCurTypeDef = partialTypeDef;
|
typeState.mCurTypeDef = partialTypeDef;
|
||||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||||
|
@ -101,6 +102,7 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfGenericTypeInstan
|
||||||
bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
|
bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
|
||||||
{
|
{
|
||||||
BfTypeState typeState;
|
BfTypeState typeState;
|
||||||
|
typeState.mPrevState = mContext->mCurTypeState;
|
||||||
typeState.mBuildingGenericParams = true;
|
typeState.mBuildingGenericParams = true;
|
||||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||||
|
|
||||||
|
@ -1500,6 +1502,12 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
// into an errored state
|
// into an errored state
|
||||||
SetAndRestoreValue<bool> prevReportErrors(mReportErrors, reportErrors);
|
SetAndRestoreValue<bool> prevReportErrors(mReportErrors, reportErrors);
|
||||||
|
|
||||||
|
if (typeInstance->mIsFinishingType)
|
||||||
|
{
|
||||||
|
// This type already failed
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
CheckCircularDataError();
|
CheckCircularDataError();
|
||||||
|
|
||||||
bool underlyingTypeDeferred = false;
|
bool underlyingTypeDeferred = false;
|
||||||
|
@ -2095,7 +2103,9 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
if (partialTypeDef->mTypeDeclaration->mAttributes == NULL)
|
if (partialTypeDef->mTypeDeclaration->mAttributes == NULL)
|
||||||
continue;
|
continue;
|
||||||
BfTypeState typeState;
|
BfTypeState typeState;
|
||||||
|
typeState.mPrevState = mContext->mCurTypeState;
|
||||||
typeState.mCurTypeDef = partialTypeDef;
|
typeState.mCurTypeDef = partialTypeDef;
|
||||||
|
typeState.mTypeInstance = typeInstance;
|
||||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||||
|
|
||||||
if (typeInstance->mCustomAttributes == NULL)
|
if (typeInstance->mCustomAttributes == NULL)
|
||||||
|
@ -2186,61 +2196,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
BfFieldDef* mFieldDef;
|
BfFieldDef* mFieldDef;
|
||||||
int mTypeArrayIdx;
|
int mTypeArrayIdx;
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto propDef : typeDef->mProperties)
|
|
||||||
{
|
|
||||||
if (!typeInstance->IsTypeMemberIncluded(propDef->mDeclaringType))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (propDef->mFieldDeclaration != NULL)
|
|
||||||
{
|
|
||||||
BfTypeState typeState;
|
|
||||||
typeState.mCurTypeDef = propDef->mDeclaringType;
|
|
||||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
|
||||||
|
|
||||||
if (propDef->mFieldDeclaration->mAttributes != NULL)
|
|
||||||
{
|
|
||||||
auto customAttrs = GetCustomAttributes(propDef->mFieldDeclaration->mAttributes, BfAttributeTargets_Property);
|
|
||||||
delete customAttrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (propDef->mFieldDeclaration->mAttributes != NULL)
|
|
||||||
{
|
|
||||||
auto customAttrs = GetCustomAttributes(propDef->mFieldDeclaration->mAttributes, BfAttributeTargets_Property);
|
|
||||||
delete customAttrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto propDecl = (BfPropertyDeclaration*)propDef->mFieldDeclaration;
|
|
||||||
if (propDecl->mExplicitInterface != NULL)
|
|
||||||
{
|
|
||||||
if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL))
|
|
||||||
mCompiler->mResolvePassData->mAutoComplete->CheckTypeRef(propDecl->mExplicitInterface, false);
|
|
||||||
auto explicitInterface = ResolveTypeRef(propDecl->mExplicitInterface, BfPopulateType_Declaration);
|
|
||||||
if (explicitInterface != NULL)
|
|
||||||
{
|
|
||||||
bool interfaceFound = false;
|
|
||||||
for (auto ifaceInst : typeInstance->mInterfaces)
|
|
||||||
interfaceFound |= ifaceInst.mInterfaceType == explicitInterface;
|
|
||||||
if (!interfaceFound)
|
|
||||||
{
|
|
||||||
Fail("Containing class has not declared to implement this interface", propDecl->mExplicitInterface, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (propDef->mMethods.IsEmpty())
|
|
||||||
{
|
|
||||||
auto nameNode = ((BfPropertyDeclaration*)propDef->mFieldDeclaration)->mNameNode;
|
|
||||||
|
|
||||||
if (nameNode != NULL)
|
|
||||||
{
|
|
||||||
Fail(StrFormat("Property or indexer '%s.%s' must have at least one accessor", TypeToString(typeInstance).c_str(), propDef->mName.c_str()),
|
|
||||||
nameNode, true); // CS0548
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BfSizedVector<DeferredResolveEntry, 8> deferredVarResolves;
|
BfSizedVector<DeferredResolveEntry, 8> deferredVarResolves;
|
||||||
|
|
||||||
for (auto field : typeDef->mFields)
|
for (auto field : typeDef->mFields)
|
||||||
|
@ -2417,7 +2373,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
|
|
||||||
BF_ASSERT(mContext->mCurTypeState == &typeState);
|
BF_ASSERT(mContext->mCurTypeState == &typeState);
|
||||||
|
|
||||||
BF_ASSERT(!typeInstance->mIsFinishingType);
|
//BF_ASSERT(!typeInstance->mIsFinishingType);
|
||||||
typeInstance->mIsFinishingType = true;
|
typeInstance->mIsFinishingType = true;
|
||||||
|
|
||||||
// No re-entry is allowed below here -- we will run all the way to the end at this point
|
// No re-entry is allowed below here -- we will run all the way to the end at this point
|
||||||
|
@ -2427,6 +2383,63 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
|
|
||||||
if (!resolvedTypeRef->IsBoxed())
|
if (!resolvedTypeRef->IsBoxed())
|
||||||
{
|
{
|
||||||
|
for (auto propDef : typeDef->mProperties)
|
||||||
|
{
|
||||||
|
if (!typeInstance->IsTypeMemberIncluded(propDef->mDeclaringType))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (propDef->mFieldDeclaration != NULL)
|
||||||
|
{
|
||||||
|
BfTypeState typeState;
|
||||||
|
typeState.mPrevState = mContext->mCurTypeState;
|
||||||
|
typeState.mCurTypeDef = propDef->mDeclaringType;
|
||||||
|
typeState.mCurFieldDef = propDef;
|
||||||
|
typeState.mTypeInstance = typeInstance;
|
||||||
|
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||||
|
|
||||||
|
if (propDef->mFieldDeclaration->mAttributes != NULL)
|
||||||
|
{
|
||||||
|
auto customAttrs = GetCustomAttributes(propDef->mFieldDeclaration->mAttributes, BfAttributeTargets_Property);
|
||||||
|
delete customAttrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propDef->mFieldDeclaration->mAttributes != NULL)
|
||||||
|
{
|
||||||
|
auto customAttrs = GetCustomAttributes(propDef->mFieldDeclaration->mAttributes, BfAttributeTargets_Property);
|
||||||
|
delete customAttrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto propDecl = (BfPropertyDeclaration*)propDef->mFieldDeclaration;
|
||||||
|
if (propDecl->mExplicitInterface != NULL)
|
||||||
|
{
|
||||||
|
if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL))
|
||||||
|
mCompiler->mResolvePassData->mAutoComplete->CheckTypeRef(propDecl->mExplicitInterface, false);
|
||||||
|
auto explicitInterface = ResolveTypeRef(propDecl->mExplicitInterface, BfPopulateType_Declaration);
|
||||||
|
if (explicitInterface != NULL)
|
||||||
|
{
|
||||||
|
bool interfaceFound = false;
|
||||||
|
for (auto ifaceInst : typeInstance->mInterfaces)
|
||||||
|
interfaceFound |= ifaceInst.mInterfaceType == explicitInterface;
|
||||||
|
if (!interfaceFound)
|
||||||
|
{
|
||||||
|
Fail("Containing class has not declared to implement this interface", propDecl->mExplicitInterface, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propDef->mMethods.IsEmpty())
|
||||||
|
{
|
||||||
|
auto nameNode = ((BfPropertyDeclaration*)propDef->mFieldDeclaration)->mNameNode;
|
||||||
|
|
||||||
|
if (nameNode != NULL)
|
||||||
|
{
|
||||||
|
Fail(StrFormat("Property or indexer '%s.%s' must have at least one accessor", TypeToString(typeInstance).c_str(), propDef->mName.c_str()),
|
||||||
|
nameNode, true); // CS0548
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool isGlobalContainer = typeDef->IsGlobalsContainer();
|
bool isGlobalContainer = typeDef->IsGlobalsContainer();
|
||||||
|
|
||||||
if (typeInstance->mBaseType != NULL)
|
if (typeInstance->mBaseType != NULL)
|
||||||
|
@ -2478,7 +2491,10 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
if ((fieldDef != NULL) && (fieldDef->mFieldDeclaration != NULL) && (fieldDef->mFieldDeclaration->mAttributes != NULL))
|
if ((fieldDef != NULL) && (fieldDef->mFieldDeclaration != NULL) && (fieldDef->mFieldDeclaration->mAttributes != NULL))
|
||||||
{
|
{
|
||||||
BfTypeState typeState;
|
BfTypeState typeState;
|
||||||
|
typeState.mPrevState = mContext->mCurTypeState;
|
||||||
|
typeState.mCurFieldDef = fieldDef;
|
||||||
typeState.mCurTypeDef = fieldDef->mDeclaringType;
|
typeState.mCurTypeDef = fieldDef->mDeclaringType;
|
||||||
|
typeState.mTypeInstance = typeInstance;
|
||||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||||
|
|
||||||
fieldInstance->mCustomAttributes = GetCustomAttributes(fieldDef->mFieldDeclaration->mAttributes, fieldDef->mIsStatic ? BfAttributeTargets_StaticField : BfAttributeTargets_Field);
|
fieldInstance->mCustomAttributes = GetCustomAttributes(fieldDef->mFieldDeclaration->mAttributes, fieldDef->mIsStatic ? BfAttributeTargets_StaticField : BfAttributeTargets_Field);
|
||||||
|
@ -2959,6 +2975,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
BfTypeState typeState;
|
BfTypeState typeState;
|
||||||
|
typeState.mPrevState = mContext->mCurTypeState;
|
||||||
typeState.mCurTypeDef = propDef->mDeclaringType;
|
typeState.mCurTypeDef = propDef->mDeclaringType;
|
||||||
typeState.mTypeInstance = typeInstance;
|
typeState.mTypeInstance = typeInstance;
|
||||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue