1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 12:32:20 +02:00

Fixed errors for circular data references in member attributes

This commit is contained in:
Brian Fiete 2020-01-18 14:43:42 -08:00
parent 07a0972366
commit 3486251254
5 changed files with 124 additions and 61 deletions

View file

@ -119,7 +119,7 @@ public:
BfPopulateType mPopulateType;
BfTypeReference* mCurBaseTypeRef;
BfTypeReference* mCurAttributeTypeRef;
BfFieldDef* mCurFieldDef;
BfFieldDef* mCurFieldDef;
BfTypeDef* mCurTypeDef;
bool mBuildingGenericParams;

View file

@ -2066,6 +2066,7 @@ BfExprEvaluator::BfExprEvaluator(BfModule* module)
mIsHeapReference = false;
mResultIsTempComposite = false;
mAllowReadOnlyReference = false;
mInsidePendingNullable = false;
mReceivingValue = NULL;
}
@ -2167,6 +2168,7 @@ void BfExprEvaluator::Evaluate(BfAstNode* astNode, bool propogateNullConditional
if (!propogateNullConditional)
mModule->mCurMethodState->mPendingNullConditional = NULL;
}
mInsidePendingNullable = pendingNullCond != NULL;
astNode->Accept(this);
GetResult();
@ -5634,6 +5636,11 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType
bool isLet = variableDeclaration->mTypeRef->IsExact<BfLetTypeReference>();
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))
{
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));
BfExprEvaluator* exprEvaluator = argExprEvaluators.back();
exprEvaluator->mResolveGenericParam = false;
exprEvaluator->mResolveGenericParam = false;
exprEvaluator->mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator->mBfEvalExprFlags | BfEvalExprFlags_NoCast | BfEvalExprFlags_AllowRefExpr | BfEvalExprFlags_AllowOutExpr);
if (argExpr != NULL)
exprEvaluator->Evaluate(argExpr, false, false, true);
auto argValue = exprEvaluator->mResult;
@ -12634,6 +12642,37 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
{
// 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())
{
mModule->UpdateSrcPos(methodDeclaration->mNameNode);
@ -12707,7 +12746,7 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
if (!mModule->mBfIRBuilder->mIgnoreWrites)
{
if (newLocalVar->mIsSplat)
{
{
//TODO: Implement
}
else
@ -16635,7 +16674,13 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
return;
}
MarkResultAssigned();
if (mInsidePendingNullable)
{
// 'out' inside null conditionals never actually causes a definite assignment...
}
else
MarkResultAssigned();
MarkResultUsed();
ResolveGenericType();
mResult = BfTypedValue(mResult.mValue, mModule->CreateRefType(mResult.mType, BfRefType::RefKind_Out));

View file

@ -308,6 +308,7 @@ public:
bool mIsHeapReference;
bool mResultIsTempComposite;
bool mAllowReadOnlyReference;
bool mInsidePendingNullable;
public:
BfExprEvaluator(BfModule* module);

View file

@ -14327,7 +14327,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
}
else
{
AssertErrorState();
// Failed
}
auto assignValue = GetFieldInitializerValue(fieldInst);
if ((fieldAddr) && (assignValue))

View file

@ -57,6 +57,7 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfGenericTypeInstan
}
BfTypeState typeState;
typeState.mPrevState = mContext->mCurTypeState;
typeState.mTypeInstance = genericTypeInst;
typeState.mCurTypeDef = partialTypeDef;
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
@ -101,6 +102,7 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfGenericTypeInstan
bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
{
BfTypeState typeState;
typeState.mPrevState = mContext->mCurTypeState;
typeState.mBuildingGenericParams = true;
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
@ -1500,6 +1502,12 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
// into an errored state
SetAndRestoreValue<bool> prevReportErrors(mReportErrors, reportErrors);
if (typeInstance->mIsFinishingType)
{
// This type already failed
return true;
}
CheckCircularDataError();
bool underlyingTypeDeferred = false;
@ -2095,7 +2103,9 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (partialTypeDef->mTypeDeclaration->mAttributes == NULL)
continue;
BfTypeState typeState;
typeState.mPrevState = mContext->mCurTypeState;
typeState.mCurTypeDef = partialTypeDef;
typeState.mTypeInstance = typeInstance;
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
if (typeInstance->mCustomAttributes == NULL)
@ -2186,61 +2196,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
BfFieldDef* mFieldDef;
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;
for (auto field : typeDef->mFields)
@ -2417,7 +2373,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
BF_ASSERT(mContext->mCurTypeState == &typeState);
BF_ASSERT(!typeInstance->mIsFinishingType);
//BF_ASSERT(!typeInstance->mIsFinishingType);
typeInstance->mIsFinishingType = true;
// 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())
{
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();
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))
{
BfTypeState typeState;
typeState.mPrevState = mContext->mCurTypeState;
typeState.mCurFieldDef = fieldDef;
typeState.mCurTypeDef = fieldDef->mDeclaringType;
typeState.mTypeInstance = typeInstance;
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
fieldInstance->mCustomAttributes = GetCustomAttributes(fieldDef->mFieldDeclaration->mAttributes, fieldDef->mIsStatic ? BfAttributeTargets_StaticField : BfAttributeTargets_Field);
@ -2959,6 +2975,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
continue;
BfTypeState typeState;
typeState.mPrevState = mContext->mCurTypeState;
typeState.mCurTypeDef = propDef->mDeclaringType;
typeState.mTypeInstance = typeInstance;
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);