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

Refactoring of operator constraints, generic param population

This commit is contained in:
Brian Fiete 2020-09-18 17:00:33 -07:00
parent b975acb711
commit 75eeb25555
9 changed files with 301 additions and 85 deletions

View file

@ -1551,7 +1551,7 @@ bool BfAutoComplete::CheckMemberReference(BfAstNode* target, BfAstNode* dotToken
// We need this for Result<T> // We need this for Result<T>
SetAndRestoreValue<bool> prevIgnore(mModule->mBfIRBuilder->mIgnoreWrites, true); SetAndRestoreValue<bool> prevIgnore(mModule->mBfIRBuilder->mIgnoreWrites, true);
BfExprEvaluator exprEvaluator(mModule); BfExprEvaluator exprEvaluator(mModule);
auto opResult = exprEvaluator.PerformUnaryOperation_TryOperator(targetValue, NULL, BfUnaryOp_NullConditional, dotTokenNode); auto opResult = exprEvaluator.PerformUnaryOperation_TryOperator(targetValue, NULL, BfUnaryOp_NullConditional, dotTokenNode, BfUnaryOpFlag_None);
if (opResult) if (opResult)
targetValue = opResult; targetValue = opResult;
} }

View file

@ -1028,6 +1028,8 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
genericTypeInstance->mGenericTypeInfo->mTypeGenericArgumentRefs.Clear(); genericTypeInstance->mGenericTypeInfo->mTypeGenericArgumentRefs.Clear();
for (auto genericParam : genericTypeInstance->mGenericTypeInfo->mGenericParams) for (auto genericParam : genericTypeInstance->mGenericTypeInfo->mGenericParams)
genericParam->Release(); genericParam->Release();
genericTypeInstance->mGenericTypeInfo->mInitializedGenericParams = false;
genericTypeInstance->mGenericTypeInfo->mFinishedGenericParams = false;
genericTypeInstance->mGenericTypeInfo->mGenericParams.Clear(); genericTypeInstance->mGenericTypeInfo->mGenericParams.Clear();
genericTypeInstance->mGenericTypeInfo->mValidatedGenericConstraints = false; genericTypeInstance->mGenericTypeInfo->mValidatedGenericConstraints = false;
genericTypeInstance->mGenericTypeInfo->mHadValidateErrors = false; genericTypeInstance->mGenericTypeInfo->mHadValidateErrors = false;

View file

@ -1313,7 +1313,7 @@ bool BfMethodMatcher::InferFromGenericConstraints(BfGenericParamInstance* generi
{ {
BfExprEvaluator exprEvaluator(mModule); BfExprEvaluator exprEvaluator(mModule);
exprEvaluator.mResult = rightValue; exprEvaluator.mResult = rightValue;
exprEvaluator.PerformUnaryOperation(NULL, checkOpConstraint.mUnaryOp, NULL); exprEvaluator.PerformUnaryOperation(NULL, checkOpConstraint.mUnaryOp, NULL, BfUnaryOpFlag_IsConstraintCheck);
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Equals_Op) != 0) if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Equals_Op) != 0)
checkArgType = exprEvaluator.mResult.mType; checkArgType = exprEvaluator.mResult.mType;
@ -17128,7 +17128,7 @@ BfTypedValue BfExprEvaluator::SetupNullConditional(BfTypedValue thisValue, BfTok
return thisValue; return thisValue;
} }
auto opResult = PerformUnaryOperation_TryOperator(thisValue, NULL, BfUnaryOp_NullConditional, dotToken); auto opResult = PerformUnaryOperation_TryOperator(thisValue, NULL, BfUnaryOp_NullConditional, dotToken, BfUnaryOpFlag_None);
if (opResult) if (opResult)
thisValue = opResult; thisValue = opResult;
@ -17858,10 +17858,10 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
void BfExprEvaluator::Visit(BfUnaryOperatorExpression* unaryOpExpr) void BfExprEvaluator::Visit(BfUnaryOperatorExpression* unaryOpExpr)
{ {
BfAutoParentNodeEntry autoParentNodeEntry(mModule, unaryOpExpr); BfAutoParentNodeEntry autoParentNodeEntry(mModule, unaryOpExpr);
PerformUnaryOperation(unaryOpExpr->mExpression, unaryOpExpr->mOp, unaryOpExpr->mOpToken); PerformUnaryOperation(unaryOpExpr->mExpression, unaryOpExpr->mOp, unaryOpExpr->mOpToken, BfUnaryOpFlag_None);
} }
void BfExprEvaluator::PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken) void BfExprEvaluator::PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken, BfUnaryOpFlags opFlags)
{ {
{ {
// If this is a cast, we don't want the value to be coerced before the unary operator is applied. // If this is a cast, we don't want the value to be coerced before the unary operator is applied.
@ -17888,10 +17888,10 @@ void BfExprEvaluator::PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp
} }
BfExprEvaluator::PerformUnaryOperation_OnResult(unaryOpExpr, unaryOp, opToken); BfExprEvaluator::PerformUnaryOperation_OnResult(unaryOpExpr, unaryOp, opToken, opFlags);
} }
BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedValue& inValue, BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken) BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedValue& inValue, BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken, BfUnaryOpFlags opFlags)
{ {
if ((!inValue.mType->IsTypeInstance()) && (!inValue.mType->IsGenericParam())) if ((!inValue.mType->IsTypeInstance()) && (!inValue.mType->IsGenericParam()))
return BfTypedValue(); return BfTypedValue();
@ -17918,6 +17918,9 @@ BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedVal
isPostOp = true; isPostOp = true;
} }
bool isConstraintCheck = ((opFlags & BfUnaryOpFlag_IsConstraintCheck) != 0);
BfType* operatorConstraintReturnType = NULL;
BfType* bestSelfType = NULL; BfType* bestSelfType = NULL;
while (true) while (true)
{ {
@ -17938,8 +17941,17 @@ BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedVal
// Try without arg // Try without arg
args.mSize = 0; args.mSize = 0;
} }
if (methodMatcher.CheckMethod(NULL, checkType, operatorDef, false)) if (isConstraintCheck)
methodMatcher.mSelfType = entry.mSrcType; {
operatorConstraintReturnType = mModule->CheckOperator(checkType, operatorDef, inValue, BfTypedValue());
if (operatorConstraintReturnType != NULL)
methodMatcher.mBestMethodDef = operatorDef;
}
else
{
if (methodMatcher.CheckMethod(NULL, checkType, operatorDef, false))
methodMatcher.mSelfType = entry.mSrcType;
}
args.mSize = prevArgSize; args.mSize = prevArgSize;
} }
} }
@ -17957,7 +17969,7 @@ BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedVal
{ {
if (opConstraint.mUnaryOp == findOp) if (opConstraint.mUnaryOp == findOp)
{ {
if (mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType)) if (mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType, isConstraintCheck ? BfCastFlags_NoConversionOperator : BfCastFlags_None))
{ {
return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType); return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
} }
@ -17977,7 +17989,7 @@ BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedVal
{ {
if (opConstraint.mUnaryOp == findOp) if (opConstraint.mUnaryOp == findOp)
{ {
if (mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType)) if (mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType, isConstraintCheck ? BfCastFlags_NoConversionOperator : BfCastFlags_None))
{ {
return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType); return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
} }
@ -17989,7 +18001,7 @@ BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedVal
return BfTypedValue(); return BfTypedValue();
} }
if (!baseClassWalker.mMayBeFromInterface) if ((!baseClassWalker.mMayBeFromInterface) && (opToken != NULL))
mModule->SetElementType(opToken, BfSourceElementType_Method); mModule->SetElementType(opToken, BfSourceElementType_Method);
auto methodDef = methodMatcher.mBestMethodDef; auto methodDef = methodMatcher.mBestMethodDef;
@ -18015,8 +18027,14 @@ BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedVal
callTarget = targetVal; callTarget = targetVal;
args.Clear(); args.Clear();
} }
auto result = CreateCall(&methodMatcher, callTarget); BfTypedValue result;
if (isConstraintCheck)
{
result = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), operatorConstraintReturnType);
}
else
result = CreateCall(&methodMatcher, callTarget);
if (!methodMatcher.mBestMethodDef->mIsStatic) if (!methodMatcher.mBestMethodDef->mIsStatic)
{ {
@ -18045,7 +18063,7 @@ BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedVal
return result; return result;
} }
void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken) void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken, BfUnaryOpFlags opFlags)
{ {
BfAstNode* propSrc = mPropSrc; BfAstNode* propSrc = mPropSrc;
BfTypedValue propTarget = mPropTarget; BfTypedValue propTarget = mPropTarget;
@ -18068,7 +18086,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
if (BfCanOverloadOperator(unaryOp)) if (BfCanOverloadOperator(unaryOp))
{ {
auto opResult = PerformUnaryOperation_TryOperator(mResult, unaryOpExpr, unaryOp, opToken); auto opResult = PerformUnaryOperation_TryOperator(mResult, unaryOpExpr, unaryOp, opToken, opFlags);
if (opResult) if (opResult)
{ {
mResult = opResult; mResult = opResult;
@ -18086,7 +18104,10 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
auto value = mModule->LoadValue(mResult); auto value = mModule->LoadValue(mResult);
value = mModule->Cast(unaryOpExpr, value, boolType); value = mModule->Cast(unaryOpExpr, value, boolType);
if (!value) if (!value)
{
mResult = BfTypedValue();
return; return;
}
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateNot(value.mValue), boolType); mResult = BfTypedValue(mModule->mBfIRBuilder->CreateNot(value.mValue), boolType);
} }
break; break;
@ -18097,7 +18118,10 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
CheckResultForReading(mResult); CheckResultForReading(mResult);
auto value = mModule->LoadValue(mResult); auto value = mModule->LoadValue(mResult);
if (!value) if (!value)
{
mResult = BfTypedValue();
return; return;
}
BfType* origType = value.mType; BfType* origType = value.mType;
if (value.mType->IsTypedPrimitive()) if (value.mType->IsTypedPrimitive())
@ -18151,7 +18175,10 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
{ {
value = mModule->Cast(unaryOpExpr, value, wantType, BfCastFlags_Explicit); value = mModule->Cast(unaryOpExpr, value, wantType, BfCastFlags_Explicit);
if (!value) if (!value)
{
mResult = BfTypedValue();
return; return;
}
} }
if (origType->mSize == wantType->mSize) // Allow negative of primitive typed but not if we had to upsize if (origType->mSize == wantType->mSize) // Allow negative of primitive typed but not if we had to upsize
@ -18176,6 +18203,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
isInteger = value.mType->GetUnderlyingType()->IsIntegral(); isInteger = value.mType->GetUnderlyingType()->IsIntegral();
if (!isInteger) if (!isInteger)
{ {
mResult = BfTypedValue();
mModule->Fail("Operator can only be used on integer types", opToken); mModule->Fail("Operator can only be used on integer types", opToken);
return; return;
} }
@ -18276,6 +18304,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
constValue = mModule->GetConstValue(1, ptr.mType); constValue = mModule->GetConstValue(1, ptr.mType);
if (!constValue) if (!constValue)
{ {
mResult = BfTypedValue();
numericFail = true; numericFail = true;
break; break;
} }
@ -18285,6 +18314,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
} }
else else
{ {
mResult = BfTypedValue();
numericFail = true; numericFail = true;
break; break;
} }
@ -18384,6 +18414,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
if ((mBfEvalExprFlags & BfEvalExprFlags_AllowRefExpr) == 0) if ((mBfEvalExprFlags & BfEvalExprFlags_AllowRefExpr) == 0)
{ {
mResult = BfTypedValue();
mModule->Fail(StrFormat("Invalid usage of '%s' expression", BfGetOpName(unaryOp)), opToken); mModule->Fail(StrFormat("Invalid usage of '%s' expression", BfGetOpName(unaryOp)), opToken);
return; return;
} }
@ -19269,6 +19300,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
BfBaseClassWalker baseClassWalker(leftValue.mType, rightValue.mType, mModule); BfBaseClassWalker baseClassWalker(leftValue.mType, rightValue.mType, mModule);
bool invertResult = false; bool invertResult = false;
BfType* operatorConstraintReturnType = NULL;
while (true) while (true)
{ {
@ -19278,7 +19310,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
break; break;
bool foundExactMatch = false; bool foundExactMatch = false;
Array<BfMethodDef*> oppositeOperatorDefs; Array<BfOperatorDef*> oppositeOperatorDefs;
for (auto operatorDef : checkType->mTypeDef->mOperators) for (auto operatorDef : checkType->mTypeDef->mOperators)
{ {
@ -19293,29 +19325,55 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
if (!methodMatcher.IsMemberAccessible(checkType, operatorDef->mDeclaringType)) if (!methodMatcher.IsMemberAccessible(checkType, operatorDef->mDeclaringType))
continue; continue;
if (methodMatcher.CheckMethod(NULL, checkType, operatorDef, false)) if ((flags & BfBinOpFlag_IsConstraintCheck) != 0)
{ {
methodMatcher.mSelfType = entry.mSrcType; // We can't do CheckMethod because circular referencing means we may have to evaluate this before our type is complete,
if (operatorDef->mOperatorDeclaration->mBinOp == findBinaryOp) // which means before method processing has occurred
operatorConstraintReturnType = mModule->CheckOperator(checkType, operatorDef, leftValue, rightValue);
if (operatorConstraintReturnType != NULL)
{
methodMatcher.mBestMethodDef = operatorDef;
foundExactMatch = true; foundExactMatch = true;
}
}
else
{
if (methodMatcher.CheckMethod(NULL, checkType, operatorDef, false))
{
methodMatcher.mSelfType = entry.mSrcType;
if (operatorDef->mOperatorDeclaration->mBinOp == findBinaryOp)
foundExactMatch = true;
}
} }
} }
else if (operatorDef->mOperatorDeclaration->mBinOp == oppositeBinaryOp) else if (operatorDef->mOperatorDeclaration->mBinOp == oppositeBinaryOp)
oppositeOperatorDefs.Add(operatorDef); oppositeOperatorDefs.Add(operatorDef);
} }
if (((methodMatcher.mBestMethodDef == NULL) || (!foundExactMatch)) && (!oppositeOperatorDefs.IsEmpty())) if ((((methodMatcher.mBestMethodDef == NULL) && (operatorConstraintReturnType == NULL)) || (!foundExactMatch)) && (!oppositeOperatorDefs.IsEmpty()))
{ {
foundOp = true; foundOp = true;
for (auto oppositeOperatorDef : oppositeOperatorDefs) for (auto oppositeOperatorDef : oppositeOperatorDefs)
{ {
if (methodMatcher.CheckMethod(NULL, checkType, oppositeOperatorDef, false)) if ((flags & BfBinOpFlag_IsConstraintCheck) != 0)
methodMatcher.mSelfType = entry.mSrcType; {
operatorConstraintReturnType = mModule->CheckOperator(checkType, oppositeOperatorDef, leftValue, rightValue);
if (operatorConstraintReturnType != NULL)
{
methodMatcher.mBestMethodDef = oppositeOperatorDef;
methodMatcher.mSelfType = entry.mSrcType;
}
}
else
{
if (methodMatcher.CheckMethod(NULL, checkType, oppositeOperatorDef, false))
methodMatcher.mSelfType = entry.mSrcType;
}
} }
} }
} }
bool hadMatch = methodMatcher.mBestMethodDef != NULL; bool hadMatch = (methodMatcher.mBestMethodDef != NULL);
if ((methodMatcher.mBestMethodDef != NULL) && ((flags & BfBinOpFlag_IgnoreOperatorWithWrongResult) != 0)) if ((methodMatcher.mBestMethodDef != NULL) && ((flags & BfBinOpFlag_IgnoreOperatorWithWrongResult) != 0))
{ {
@ -19355,7 +19413,14 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
if ((opToken->IsA<BfTokenNode>()) && (!noClassify) && (!baseClassWalker.mMayBeFromInterface)) if ((opToken->IsA<BfTokenNode>()) && (!noClassify) && (!baseClassWalker.mMayBeFromInterface))
mModule->SetElementType(opToken, BfSourceElementType_Method); mModule->SetElementType(opToken, BfSourceElementType_Method);
} }
mResult = CreateCall(&methodMatcher, BfTypedValue()); if ((flags & BfBinOpFlag_IsConstraintCheck) != 0)
{
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), operatorConstraintReturnType);
}
else
{
mResult = CreateCall(&methodMatcher, BfTypedValue());
}
if ((mResult.mType != NULL) && (methodMatcher.mSelfType != NULL) && (mResult.mType->IsSelf())) if ((mResult.mType != NULL) && (methodMatcher.mSelfType != NULL) && (mResult.mType->IsSelf()))
{ {
BF_ASSERT(mModule->IsInGeneric()); BF_ASSERT(mModule->IsInGeneric());
@ -20276,7 +20341,7 @@ void BfExprEvaluator::Visit(BfBinaryOperatorExpression* binOpExpr)
} }
} }
PerformUnaryOperation(binOpExpr->mRight, unaryOp, binOpExpr->mOpToken); PerformUnaryOperation(binOpExpr->mRight, unaryOp, binOpExpr->mOpToken, BfUnaryOpFlag_None);
if (mResult) if (mResult)
{ {
mResult = mModule->LoadValue(mResult); mResult = mModule->LoadValue(mResult);

View file

@ -290,12 +290,19 @@ enum BfLookupFieldFlags
BfLookupFieldFlag_IgnoreProtection = 4 BfLookupFieldFlag_IgnoreProtection = 4
}; };
enum BfUnaryOpFlags
{
BfUnaryOpFlag_None = 0,
BfUnaryOpFlag_IsConstraintCheck = 1
};
enum BfBinOpFlags enum BfBinOpFlags
{ {
BfBinOpFlag_None = 0, BfBinOpFlag_None = 0,
BfBinOpFlag_NoClassify = 1, BfBinOpFlag_NoClassify = 1,
BfBinOpFlag_ForceLeftType = 2, BfBinOpFlag_ForceLeftType = 2,
BfBinOpFlag_IgnoreOperatorWithWrongResult = 4, BfBinOpFlag_IgnoreOperatorWithWrongResult = 4,
BfBinOpFlag_IsConstraintCheck = 8
}; };
class BfExprEvaluator : public BfStructuralVisitor class BfExprEvaluator : public BfStructuralVisitor
@ -409,9 +416,9 @@ public:
BfLambdaInstance* GetLambdaInstance(BfLambdaBindExpression* lambdaBindExpr, BfAllocTarget& allocTarget); BfLambdaInstance* GetLambdaInstance(BfLambdaBindExpression* lambdaBindExpr, BfAllocTarget& allocTarget);
void VisitLambdaBodies(BfAstNode* body, BfFieldDtorDeclaration* fieldDtor); void VisitLambdaBodies(BfAstNode* body, BfFieldDtorDeclaration* fieldDtor);
void FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, const StringImpl& fieldName, bool isStatic); void FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, const StringImpl& fieldName, bool isStatic);
void PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken); void PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken, BfUnaryOpFlags opFlags);
BfTypedValue PerformUnaryOperation_TryOperator(const BfTypedValue& inValue, BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken); BfTypedValue PerformUnaryOperation_TryOperator(const BfTypedValue& inValue, BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken, BfUnaryOpFlags opFlags);
void PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken); void PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken, BfUnaryOpFlags opFlags);
void PerformAssignment(BfAssignmentExpression* assignExpr, bool evaluatedLeft, BfTypedValue rightValue, BfTypedValue* outCascadeValue = NULL); void PerformAssignment(BfAssignmentExpression* assignExpr, bool evaluatedLeft, BfTypedValue rightValue, BfTypedValue* outCascadeValue = NULL);
void PopulateDeferrredTupleAssignData(BfTupleExpression* tupleExr, DeferredTupleAssignData& deferredTupleAssignData); void PopulateDeferrredTupleAssignData(BfTupleExpression* tupleExr, DeferredTupleAssignData& deferredTupleAssignData);
void AssignDeferrredTupleAssignData(BfAssignmentExpression* assignExpr, DeferredTupleAssignData& deferredTupleAssignData, BfTypedValue rightValue); void AssignDeferrredTupleAssignData(BfAssignmentExpression* assignExpr, DeferredTupleAssignData& deferredTupleAssignData, BfTypedValue rightValue);

View file

@ -6799,7 +6799,7 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar
{ {
if (bfAutocomplete != NULL) if (bfAutocomplete != NULL)
bfAutocomplete->CheckTypeRef(opConstraint->mLeftType, false); bfAutocomplete->CheckTypeRef(opConstraint->mLeftType, false);
opConstraintInstance.mLeftType = ResolveTypeRef(opConstraint->mLeftType); opConstraintInstance.mLeftType = ResolveTypeRef(opConstraint->mLeftType, BfPopulateType_Interfaces);
if (opConstraintInstance.mLeftType == NULL) if (opConstraintInstance.mLeftType == NULL)
continue; continue;
} }
@ -6814,7 +6814,7 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar
{ {
if (bfAutocomplete != NULL) if (bfAutocomplete != NULL)
bfAutocomplete->CheckTypeRef(opConstraint->mRightType, false); bfAutocomplete->CheckTypeRef(opConstraint->mRightType, false);
opConstraintInstance.mRightType = ResolveTypeRef(opConstraint->mRightType); opConstraintInstance.mRightType = ResolveTypeRef(opConstraint->mRightType, BfPopulateType_Interfaces);
if (opConstraintInstance.mRightType == NULL) if (opConstraintInstance.mRightType == NULL)
continue; continue;
} }
@ -7405,11 +7405,11 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
{ {
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true); SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true); SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
exprEvaluator.PerformBinaryOperation(NULL, NULL, checkOpConstraint.mBinaryOp, NULL, BfBinOpFlag_NoClassify, leftValue, rightValue); exprEvaluator.PerformBinaryOperation(NULL, NULL, checkOpConstraint.mBinaryOp, NULL, (BfBinOpFlags)(BfBinOpFlag_NoClassify | BfBinOpFlag_IsConstraintCheck), leftValue, rightValue);
} }
if ((!exprEvaluator.mResult) || if ((!exprEvaluator.mResult) ||
(!CanCast(exprEvaluator.mResult, origCheckArgType))) (!CanCast(exprEvaluator.mResult, origCheckArgType, BfCastFlags_NoConversionOperator)))
{ {
if (!ignoreErrors) if (!ignoreErrors)
{ {
@ -7436,7 +7436,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
if (checkOpConstraint.mCastToken == BfToken_Implicit) if (checkOpConstraint.mCastToken == BfToken_Implicit)
{ {
if (!CanCast(rightValue, origCheckArgType, BfCastFlags_SilentFail)) if (!CanCast(rightValue, origCheckArgType, (BfCastFlags)(BfCastFlags_SilentFail | BfCastFlags_IsConstraintCheck)))
failedOpName = "implicit conversion from '"; failedOpName = "implicit conversion from '";
} }
else else
@ -7446,14 +7446,14 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
if (checkOpConstraint.mCastToken == BfToken_Explicit) if (checkOpConstraint.mCastToken == BfToken_Explicit)
{ {
if (!CastToValue(NULL, rightValue, origCheckArgType, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_SilentFail))) if (!CastToValue(NULL, rightValue, origCheckArgType, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_SilentFail | BfCastFlags_IsConstraintCheck)))
failedOpName = "explicit conversion from '"; failedOpName = "explicit conversion from '";
} }
else else
{ {
BfExprEvaluator exprEvaluator(this); BfExprEvaluator exprEvaluator(this);
exprEvaluator.mResult = rightValue; exprEvaluator.mResult = rightValue;
exprEvaluator.PerformUnaryOperation(NULL, checkOpConstraint.mUnaryOp, NULL); exprEvaluator.PerformUnaryOperation(NULL, checkOpConstraint.mUnaryOp, NULL, BfUnaryOpFlag_IsConstraintCheck);
if ((!exprEvaluator.mResult) || if ((!exprEvaluator.mResult) ||
(!CanCast(exprEvaluator.mResult, origCheckArgType))) (!CanCast(exprEvaluator.mResult, origCheckArgType)))
@ -9652,6 +9652,55 @@ BfModuleMethodInstance BfModule::GetInternalMethod(const StringImpl& methodName,
return moduleMethodInstance; return moduleMethodInstance;
} }
BfOperatorInfo* BfModule::GetOperatorInfo(BfTypeInstance* typeInstance, BfOperatorDef* operatorDef)
{
while (operatorDef->mIdx >= typeInstance->mOperatorInfo.size())
typeInstance->mOperatorInfo.Add(NULL);
if (typeInstance->mOperatorInfo[operatorDef->mIdx] == NULL)
{
SetAndRestoreValue<bool> ignoreErrors(mIgnoreErrors, true);
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance);
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL);
BfOperatorInfo* operatorInfo = new BfOperatorInfo();
if (operatorDef->mReturnTypeRef != NULL)
operatorInfo->mReturnType = ResolveTypeRef(operatorDef->mReturnTypeRef, BfPopulateType_Identity);
if (operatorDef->mParams.size() >= 1)
operatorInfo->mLHSType = ResolveTypeRef(operatorDef->mParams[0]->mTypeRef, BfPopulateType_Identity);
if (operatorDef->mParams.size() >= 2)
operatorInfo->mRHSType = ResolveTypeRef(operatorDef->mParams[1]->mTypeRef, BfPopulateType_Identity);
typeInstance->mOperatorInfo[operatorDef->mIdx] = operatorInfo;
}
return typeInstance->mOperatorInfo[operatorDef->mIdx];
}
BfType* BfModule::CheckOperator(BfTypeInstance* typeInstance, BfOperatorDef* operatorDef, const BfTypedValue& lhs, const BfTypedValue& rhs)
{
auto operatorInfo = GetOperatorInfo(typeInstance, operatorDef);
if (operatorInfo == NULL)
return NULL;
if (operatorInfo->mReturnType == NULL)
return NULL;
if (lhs)
{
if (operatorInfo->mLHSType == NULL)
return NULL;
// TODO: Make this be a special flag to do CheckOperator conversion checks?
if (!CanCast(lhs, operatorInfo->mLHSType, BfCastFlags_NoConversionOperator))
return NULL;
}
if (rhs)
{
if (operatorInfo->mRHSType == NULL)
return NULL;
// TODO: Make this be a special flag to do CheckOperator conversion checks?
if (!CanCast(rhs, operatorInfo->mRHSType, BfCastFlags_NoConversionOperator))
return NULL;
}
return operatorInfo->mReturnType;
}
bool BfModule::IsMethodImplementedAndReified(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount, bool checkBase) bool BfModule::IsMethodImplementedAndReified(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount, bool checkBase)
{ {
while (typeInstance != NULL) while (typeInstance != NULL)

View file

@ -83,7 +83,8 @@ enum BfCastFlags
BfCastFlags_Force = 0x100, BfCastFlags_Force = 0x100,
BfCastFlags_PreferAddr = 0x200, BfCastFlags_PreferAddr = 0x200,
BfCastFlags_WarnOnBox = 0x400, BfCastFlags_WarnOnBox = 0x400,
BfCastFlags_IsCastCheck = 0x800 BfCastFlags_IsCastCheck = 0x800,
BfCastFlags_IsConstraintCheck = 0x1000
}; };
enum BfCastResultFlags enum BfCastResultFlags
@ -1600,7 +1601,8 @@ public:
// Type helpers // Type helpers
BfGenericExtensionEntry* BuildGenericExtensionInfo(BfTypeInstance* genericTypeInst, BfTypeDef* partialTypeDef); BfGenericExtensionEntry* BuildGenericExtensionInfo(BfTypeInstance* genericTypeInst, BfTypeDef* partialTypeDef);
bool BuildGenericParams(BfType* resolvedTypeRef); bool InitGenericParams(BfType* resolvedTypeRef);
bool FinishGenericParams(BfType* resolvedTypeRef);
bool ValidateGenericConstraints(BfTypeReference* typeRef, BfTypeInstance* genericTypeInstance, bool ignoreErrors); bool ValidateGenericConstraints(BfTypeReference* typeRef, BfTypeInstance* genericTypeInstance, bool ignoreErrors);
bool AreConstraintsSubset(BfGenericParamInstance* checkInner, BfGenericParamInstance* checkOuter); bool AreConstraintsSubset(BfGenericParamInstance* checkInner, BfGenericParamInstance* checkOuter);
bool CheckConstraintState(BfAstNode* refNode); bool CheckConstraintState(BfAstNode* refNode);
@ -1794,6 +1796,8 @@ public:
BfModuleMethodInstance GetMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount = -1, bool checkBase = false); BfModuleMethodInstance GetMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount = -1, bool checkBase = false);
BfModuleMethodInstance GetMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, const Array<BfType*>& paramTypes, bool checkBase = false); BfModuleMethodInstance GetMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, const Array<BfType*>& paramTypes, bool checkBase = false);
BfModuleMethodInstance GetInternalMethod(const StringImpl& methodName, int paramCount = -1); BfModuleMethodInstance GetInternalMethod(const StringImpl& methodName, int paramCount = -1);
BfOperatorInfo* GetOperatorInfo(BfTypeInstance* typeInstance, BfOperatorDef* operatorDef);
BfType* CheckOperator(BfTypeInstance* typeInstance, BfOperatorDef* operatorDef, const BfTypedValue& lhs, const BfTypedValue& rhs);
bool IsMethodImplementedAndReified(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount = -1, bool checkBase = false); bool IsMethodImplementedAndReified(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount = -1, bool checkBase = false);
bool HasMixin(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount, bool checkBase = false); bool HasMixin(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount, bool checkBase = false);
bool CompareMethodSignatures(BfMethodInstance* methodA, BfMethodInstance* methodB); // Doesn't compare return types nor static bool CompareMethodSignatures(BfMethodInstance* methodA, BfMethodInstance* methodB); // Doesn't compare return types nor static

View file

@ -80,7 +80,7 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfTypeInstance* gen
auto& genericConstraint = partialTypeDef->mExternalConstraints[externConstraintIdx]; auto& genericConstraint = partialTypeDef->mExternalConstraints[externConstraintIdx];
auto genericParamInstance = new BfGenericTypeParamInstance(partialTypeDef, externConstraintIdx + (int)partialTypeDef->mGenericParamDefs.size()); auto genericParamInstance = new BfGenericTypeParamInstance(partialTypeDef, externConstraintIdx + (int)partialTypeDef->mGenericParamDefs.size());
genericParamInstance->mExternType = ResolveTypeRef(genericConstraint.mTypeRef); genericParamInstance->mExternType = ResolveTypeRef(genericConstraint.mTypeRef, BfPopulateType_Identity);
auto autoComplete = mCompiler->GetAutoComplete(); auto autoComplete = mCompiler->GetAutoComplete();
if (autoComplete != NULL) if (autoComplete != NULL)
@ -116,17 +116,18 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfTypeInstance* gen
return genericExEntry; return genericExEntry;
} }
bool BfModule::BuildGenericParams(BfType* resolvedTypeRef) bool BfModule::InitGenericParams(BfType* resolvedTypeRef)
{ {
BfTypeState typeState; BfTypeState typeState;
typeState.mPrevState = mContext->mCurTypeState; typeState.mPrevState = mContext->mCurTypeState;
typeState.mResolveKind = BfTypeState::ResolveKind_BuildingGenericParams; typeState.mResolveKind = BfTypeState::ResolveKind_BuildingGenericParams;
typeState.mTypeInstance = resolvedTypeRef->ToTypeInstance(); typeState.mTypeInstance = resolvedTypeRef->ToTypeInstance();
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState); SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
BF_ASSERT(mCurMethodInstance == NULL); BF_ASSERT(mCurMethodInstance == NULL);
auto genericTypeInst = resolvedTypeRef->ToGenericTypeInstance(); auto genericTypeInst = resolvedTypeRef->ToGenericTypeInstance();
genericTypeInst->mGenericTypeInfo->mInitializedGenericParams = true;
if (genericTypeInst->mGenericTypeInfo->mTypeGenericArguments[0]->IsGenericParam()) if (genericTypeInst->mGenericTypeInfo->mTypeGenericArguments[0]->IsGenericParam())
{ {
@ -147,6 +148,38 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
auto genericParamInstance = new BfGenericTypeParamInstance(typeDef, externConstraintIdx + (int)typeDef->mGenericParamDefs.size()); auto genericParamInstance = new BfGenericTypeParamInstance(typeDef, externConstraintIdx + (int)typeDef->mGenericParamDefs.size());
genericTypeInst->mGenericTypeInfo->mGenericParams.push_back(genericParamInstance); genericTypeInst->mGenericTypeInfo->mGenericParams.push_back(genericParamInstance);
} }
return true;
}
bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
{
BfTypeState typeState;
typeState.mPrevState = mContext->mCurTypeState;
typeState.mResolveKind = BfTypeState::ResolveKind_BuildingGenericParams;
typeState.mTypeInstance = resolvedTypeRef->ToTypeInstance();
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
BF_ASSERT(mCurMethodInstance == NULL);
auto genericTypeInst = resolvedTypeRef->ToGenericTypeInstance();
genericTypeInst->mGenericTypeInfo->mFinishedGenericParams = true;
if (genericTypeInst->mGenericTypeInfo->mTypeGenericArguments[0]->IsGenericParam())
{
BF_ASSERT(genericTypeInst->mGenericTypeInfo->mIsUnspecialized);
}
auto typeDef = genericTypeInst->mTypeDef;
int startDefGenericParamIdx = (int)genericTypeInst->mGenericTypeInfo->mGenericParams.size();
if ((!resolvedTypeRef->IsTuple()) && (!resolvedTypeRef->IsDelegateFromTypeRef()) && (!resolvedTypeRef->IsFunctionFromTypeRef()))
{
startDefGenericParamIdx = startDefGenericParamIdx -
(int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size() -
(int)typeDef->mExternalConstraints.size();
}
BF_ASSERT(startDefGenericParamIdx >= 0);
if (!typeDef->mPartials.empty()) if (!typeDef->mPartials.empty())
{ {
@ -156,7 +189,7 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
{ {
typeState.mCurTypeDef = partialTypeDef; typeState.mCurTypeDef = partialTypeDef;
for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mGenericParams.size(); paramIdx++) for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mGenericParams.size(); paramIdx++)
{ {
auto genericParamInstance = genericTypeInst->mGenericTypeInfo->mGenericParams[paramIdx]; auto genericParamInstance = genericTypeInst->mGenericTypeInfo->mGenericParams[paramIdx];
auto genericParamDef = genericParamInstance->GetGenericParamDef(); auto genericParamDef = genericParamInstance->GetGenericParamDef();
@ -168,7 +201,7 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
{ {
auto externConstraintDef = genericParamInstance->GetExternConstraintDef(); auto externConstraintDef = genericParamInstance->GetExternConstraintDef();
genericParamInstance->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef); genericParamInstance->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef);
if (genericParamInstance->mExternType == NULL) if (genericParamInstance->mExternType == NULL)
genericParamInstance->mExternType = GetPrimitiveType(BfTypeCode_Var); genericParamInstance->mExternType = GetPrimitiveType(BfTypeCode_Var);
} }
@ -232,7 +265,7 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
{ {
auto externConstraintDef = genericParamInstance->GetExternConstraintDef(); auto externConstraintDef = genericParamInstance->GetExternConstraintDef();
genericParamInstance->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef); genericParamInstance->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef);
auto autoComplete = mCompiler->GetAutoComplete(); auto autoComplete = mCompiler->GetAutoComplete();
if (autoComplete != NULL) if (autoComplete != NULL)
autoComplete->CheckTypeRef(externConstraintDef->mTypeRef, false); autoComplete->CheckTypeRef(externConstraintDef->mTypeRef, false);
@ -264,7 +297,7 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
if (genericParam->mTypeConstraint != NULL) if (genericParam->mTypeConstraint != NULL)
AddDependency(genericParam->mTypeConstraint, mCurTypeInstance, BfDependencyMap::DependencyFlag_Constraint); AddDependency(genericParam->mTypeConstraint, mCurTypeInstance, BfDependencyMap::DependencyFlag_Constraint);
} }
return true; return true;
} }
@ -566,8 +599,8 @@ void BfModule::InitType(BfType* resolvedTypeRef, BfPopulateType populateType)
#endif #endif
// Do it here so the location we attempted to specialize this type will throw the failure if there is one // Do it here so the location we attempted to specialize this type will throw the failure if there is one
if (!BuildGenericParams(resolvedTypeRef)) if (!InitGenericParams(resolvedTypeRef))
return; return;
} }
BfLogSysM("%p InitType: %s Type: %p TypeDef: %p Revision:%d\n", mContext, TypeToString(resolvedTypeRef).c_str(), resolvedTypeRef, (typeInst != NULL) ? typeInst->mTypeDef : NULL, mCompiler->mRevision); BfLogSysM("%p InitType: %s Type: %p TypeDef: %p Revision:%d\n", mContext, TypeToString(resolvedTypeRef).c_str(), resolvedTypeRef, (typeInst != NULL) ? typeInst->mTypeDef : NULL, mCompiler->mRevision);
@ -1895,12 +1928,12 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
BfTypeState typeState(mCurTypeInstance, mContext->mCurTypeState); BfTypeState typeState(mCurTypeInstance, mContext->mCurTypeState);
typeState.mPopulateType = populateType; typeState.mPopulateType = populateType;
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState); SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
if (typeInstance->IsGenericTypeInstance()) if (typeInstance->IsGenericTypeInstance())
{ {
auto genericTypeInst = (BfTypeInstance*)typeInstance; auto genericTypeInst = (BfTypeInstance*)typeInstance;
if (genericTypeInst->mGenericTypeInfo->mGenericParams.size() == 0) if (!genericTypeInst->mGenericTypeInfo->mInitializedGenericParams)
BuildGenericParams(resolvedTypeRef); InitGenericParams(resolvedTypeRef);
} }
if (resolvedTypeRef->IsTypeAlias()) if (resolvedTypeRef->IsTypeAlias())
@ -2142,7 +2175,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
{ {
return; return;
} }
if ((!mCompiler->mIsResolveOnly) && (!typeInstance->mHasBeenInstantiated)) if ((!mCompiler->mIsResolveOnly) && (!typeInstance->mHasBeenInstantiated))
{ {
for (auto& dep : typeInstance->mDependencyMap) for (auto& dep : typeInstance->mDependencyMap)
@ -2228,6 +2261,8 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
}; };
Array<_DeferredValidate> deferredTypeValidateList; Array<_DeferredValidate> deferredTypeValidateList;
bool wantPopulateInterfaces = false;
BfTypeReference* baseTypeRef = NULL; BfTypeReference* baseTypeRef = NULL;
if ((typeDef->mIsDelegate) && (!typeInstance->IsClosure())) if ((typeDef->mIsDelegate) && (!typeInstance->IsClosure()))
{ {
@ -2250,7 +2285,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
baseType = ResolveTypeDef(mCompiler->mFunctionTypeDef)->ToTypeInstance(); baseType = ResolveTypeDef(mCompiler->mFunctionTypeDef)->ToTypeInstance();
} }
else else
{ {
for (auto checkTypeRef : typeDef->mBaseTypes) for (auto checkTypeRef : typeDef->mBaseTypes)
{ {
auto declTypeDef = typeDef; auto declTypeDef = typeDef;
@ -2356,36 +2391,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
} }
} }
for (auto partialTypeDef : typeDef->mPartials) wantPopulateInterfaces = true;
{
if (!typeInstance->IsTypeMemberIncluded(partialTypeDef))
continue;
if (partialTypeDef->mTypeDeclaration == typeInstance->mTypeDef->mTypeDeclaration)
continue;
for (auto checkTypeRef : partialTypeDef->mBaseTypes)
{
SetAndRestoreValue<BfTypeReference*> prevTypeRef(mContext->mCurTypeState->mCurBaseTypeRef, checkTypeRef);
SetAndRestoreValue<BfTypeDef*> prevTypeDef(mContext->mCurTypeState->mCurTypeDef, partialTypeDef);
bool populateBase = !typeInstance->mTypeFailed;
auto checkType = ResolveTypeRef(checkTypeRef, BfPopulateType_Declaration);
if (checkType != NULL)
{
if (checkType->IsInterface())
{
BfInterfaceDecl ifaceDecl;
ifaceDecl.mIFaceTypeInst = checkType->ToTypeInstance();
ifaceDecl.mTypeRef = checkTypeRef;
ifaceDecl.mDeclaringType = partialTypeDef;
interfaces.push_back(ifaceDecl);
}
else
{
Fail(StrFormat("Extensions can only specify new interfaces, type '%s' is not a valid ", TypeToString(checkType).c_str()), checkTypeRef);
}
}
}
}
} }
if (resolvedTypeRef->IsBoxed()) if (resolvedTypeRef->IsBoxed())
@ -2504,6 +2510,49 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (populateType <= BfPopulateType_BaseType) if (populateType <= BfPopulateType_BaseType)
return; return;
if (typeInstance->IsGenericTypeInstance())
{
auto genericTypeInst = (BfTypeInstance*)typeInstance;
// if (!genericTypeInst->mGenericTypeInfo->mInitializedGenericParams)
// InitGenericParams(resolvedTypeRef);
if (!genericTypeInst->mGenericTypeInfo->mFinishedGenericParams)
FinishGenericParams(resolvedTypeRef);
}
if (wantPopulateInterfaces)
{
for (auto partialTypeDef : typeDef->mPartials)
{
if (!typeInstance->IsTypeMemberIncluded(partialTypeDef))
continue;
if (partialTypeDef->mTypeDeclaration == typeInstance->mTypeDef->mTypeDeclaration)
continue;
for (auto checkTypeRef : partialTypeDef->mBaseTypes)
{
SetAndRestoreValue<BfTypeReference*> prevTypeRef(mContext->mCurTypeState->mCurBaseTypeRef, checkTypeRef);
SetAndRestoreValue<BfTypeDef*> prevTypeDef(mContext->mCurTypeState->mCurTypeDef, partialTypeDef);
bool populateBase = !typeInstance->mTypeFailed;
auto checkType = ResolveTypeRef(checkTypeRef, BfPopulateType_Declaration);
if (checkType != NULL)
{
if (checkType->IsInterface())
{
BfInterfaceDecl ifaceDecl;
ifaceDecl.mIFaceTypeInst = checkType->ToTypeInstance();
ifaceDecl.mTypeRef = checkTypeRef;
ifaceDecl.mDeclaringType = partialTypeDef;
interfaces.push_back(ifaceDecl);
}
else
{
Fail(StrFormat("Extensions can only specify new interfaces, type '%s' is not a valid ", TypeToString(checkType).c_str()), checkTypeRef);
}
}
}
}
}
if ((typeInstance->mBaseType != NULL) && (!typeInstance->IsTypedPrimitive())) if ((typeInstance->mBaseType != NULL) && (!typeInstance->IsTypedPrimitive()))
{ {
curFieldDataIdx++; curFieldDataIdx++;
@ -2863,7 +2912,8 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
bool populateChildType = !typeInstance->mTypeFailed; bool populateChildType = !typeInstance->mTypeFailed;
//bool populateChildType = true; //bool populateChildType = true;
PopulateType(resolvedFieldType, populateChildType ? BfPopulateType_Data : BfPopulateType_Declaration); PopulateType(resolvedFieldType, populateChildType ? BfPopulateType_Data : BfPopulateType_Declaration);
BF_ASSERT(!typeInstance->mNeedsMethodProcessing);
if (populateChildType) if (populateChildType)
{ {
BF_ASSERT(!resolvedFieldType->IsDataIncomplete()); BF_ASSERT(!resolvedFieldType->IsDataIncomplete());
@ -3790,6 +3840,13 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
_HandleTypeDeclaration(partial->mTypeDeclaration); _HandleTypeDeclaration(partial->mTypeDeclaration);
} }
if (typeInstance->IsGenericTypeInstance())
{
auto genericTypeInst = (BfTypeInstance*)typeInstance;
if (!genericTypeInst->mGenericTypeInfo->mFinishedGenericParams)
FinishGenericParams(resolvedTypeRef);
}
if (populateType == BfPopulateType_Data) if (populateType == BfPopulateType_Data)
return; return;
@ -6293,7 +6350,7 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
auto actualTupleType = mContext->mTupleTypePool.Get(); auto actualTupleType = mContext->mTupleTypePool.Get();
delete actualTupleType->mGenericTypeInfo; delete actualTupleType->mGenericTypeInfo;
actualTupleType->mGenericTypeInfo = new BfGenericTypeInfo(); actualTupleType->mGenericTypeInfo = new BfGenericTypeInfo();
actualTupleType->mGenericTypeInfo->mIsUnspecialized = false; actualTupleType->mGenericTypeInfo->mIsUnspecialized = false;
actualTupleType->mGenericTypeInfo->mIsUnspecializedVariation = false; actualTupleType->mGenericTypeInfo->mIsUnspecializedVariation = false;
actualTupleType->mGenericTypeInfo->mTypeGenericArguments = genericArgs; actualTupleType->mGenericTypeInfo->mTypeGenericArguments = genericArgs;
@ -6432,6 +6489,7 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
auto dlgType = mContext->mDelegateTypePool.Get(); auto dlgType = mContext->mDelegateTypePool.Get();
delete dlgType->mGenericTypeInfo; delete dlgType->mGenericTypeInfo;
dlgType->mGenericTypeInfo = new BfGenericTypeInfo(); dlgType->mGenericTypeInfo = new BfGenericTypeInfo();
dlgType->mGenericTypeInfo->mFinishedGenericParams = true;
dlgType->mGenericTypeInfo->mIsUnspecialized = false; dlgType->mGenericTypeInfo->mIsUnspecialized = false;
dlgType->mGenericTypeInfo->mIsUnspecializedVariation = false; dlgType->mGenericTypeInfo->mIsUnspecializedVariation = false;
dlgType->mGenericTypeInfo->mTypeGenericArguments = genericArgs; dlgType->mGenericTypeInfo->mTypeGenericArguments = genericArgs;
@ -8803,6 +8861,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
{ {
BfTupleType* actualTupleType = new BfTupleType(); BfTupleType* actualTupleType = new BfTupleType();
actualTupleType->mGenericTypeInfo = new BfGenericTypeInfo(); actualTupleType->mGenericTypeInfo = new BfGenericTypeInfo();
actualTupleType->mGenericTypeInfo->mFinishedGenericParams = true;
actualTupleType->Init(baseType->mTypeDef->mProject, baseType); actualTupleType->Init(baseType->mTypeDef->mProject, baseType);
for (int fieldIdx = 0; fieldIdx < (int)types.size(); fieldIdx++) for (int fieldIdx = 0; fieldIdx < (int)types.size(); fieldIdx++)
{ {
@ -8852,10 +8911,15 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
BF_ASSERT(!types[fieldIdx]->IsVar()); BF_ASSERT(!types[fieldIdx]->IsVar());
fieldInstance->mOwner = tupleType; fieldInstance->mOwner = tupleType;
} }
resolvedEntry->mValue = tupleType; resolvedEntry->mValue = tupleType;
BF_ASSERT(BfResolvedTypeSet::Hash(tupleType, &lookupCtx) == resolvedEntry->mHash); BF_ASSERT(BfResolvedTypeSet::Hash(tupleType, &lookupCtx) == resolvedEntry->mHash);
populateModule->InitType(tupleType, populateType); populateModule->InitType(tupleType, populateType);
#ifdef _DEBUG
BF_ASSERT(ResolveType(tupleType, BfPopulateType_Identity) == tupleType);
#endif
return ResolveTypeResult(typeRef, tupleType, populateType, resolveFlags); return ResolveTypeResult(typeRef, tupleType, populateType, resolveFlags);
} }
else if (auto nullableTypeRef = BfNodeDynCast<BfNullableTypeRef>(typeRef)) else if (auto nullableTypeRef = BfNodeDynCast<BfNullableTypeRef>(typeRef))
@ -9010,6 +9074,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
{ {
BfDelegateType* genericTypeInst = new BfDelegateType(); BfDelegateType* genericTypeInst = new BfDelegateType();
genericTypeInst->mGenericTypeInfo = new BfGenericTypeInfo(); genericTypeInst->mGenericTypeInfo = new BfGenericTypeInfo();
genericTypeInst->mGenericTypeInfo->mFinishedGenericParams = true;
delegateType = genericTypeInst; delegateType = genericTypeInst;
delegateInfo = delegateType->GetDelegateInfo(); delegateInfo = delegateType->GetDelegateInfo();
auto parentTypeInstance = (BfTypeInstance*)mCurTypeInstance; auto parentTypeInstance = (BfTypeInstance*)mCurTypeInstance;

View file

@ -1382,6 +1382,8 @@ BfTypeInstance::~BfTypeInstance()
delete mAttributeData; delete mAttributeData;
for (auto methodInst : mInternalMethods) for (auto methodInst : mInternalMethods)
delete methodInst; delete methodInst;
for (auto operatorInfo : mOperatorInfo)
delete operatorInfo;
delete mHotTypeData; delete mHotTypeData;
delete mConstHolder; delete mConstHolder;
} }

View file

@ -940,6 +940,23 @@ public:
void ReportMemory(MemReporter* memReporter); void ReportMemory(MemReporter* memReporter);
}; };
class BfOperatorInfo
{
public:
BfMethodDef* mMethodDef;
BfType* mReturnType;
BfType* mLHSType;
BfType* mRHSType;
BfOperatorInfo()
{
mMethodDef = NULL;
mReturnType = NULL;
mLHSType = NULL;
mRHSType = NULL;
}
};
class BfDllImportEntry class BfDllImportEntry
{ {
public: public:
@ -1681,6 +1698,8 @@ public:
bool mIsUnspecializedVariation; bool mIsUnspecializedVariation;
bool mValidatedGenericConstraints; bool mValidatedGenericConstraints;
bool mHadValidateErrors; bool mHadValidateErrors;
bool mInitializedGenericParams;
bool mFinishedGenericParams;
Array<BfProject*> mProjectsReferenced; // Generic methods that only refer to these projects don't need a specialized extension Array<BfProject*> mProjectsReferenced; // Generic methods that only refer to these projects don't need a specialized extension
public: public:
@ -1691,6 +1710,8 @@ public:
mIsUnspecialized = false; mIsUnspecialized = false;
mIsUnspecializedVariation = false; mIsUnspecializedVariation = false;
mValidatedGenericConstraints = false; mValidatedGenericConstraints = false;
mInitializedGenericParams = false;
mFinishedGenericParams = false;
} }
~BfGenericTypeInfo(); ~BfGenericTypeInfo();
@ -1719,6 +1740,7 @@ public:
Array<BfTypeInterfaceEntry> mInterfaces; Array<BfTypeInterfaceEntry> mInterfaces;
Array<BfTypeInterfaceMethodEntry> mInterfaceMethodTable; Array<BfTypeInterfaceMethodEntry> mInterfaceMethodTable;
Array<BfMethodInstanceGroup> mMethodInstanceGroups; Array<BfMethodInstanceGroup> mMethodInstanceGroups;
Array<BfOperatorInfo*> mOperatorInfo;
Array<BfVirtualMethodEntry> mVirtualMethodTable; Array<BfVirtualMethodEntry> mVirtualMethodTable;
BfHotTypeData* mHotTypeData; BfHotTypeData* mHotTypeData;
int mVirtualMethodTableSize; // With hot reloading, mVirtualMethodTableSize can be larger than mInterfaceMethodTable (live vtable versioning) int mVirtualMethodTableSize; // With hot reloading, mVirtualMethodTableSize can be larger than mInterfaceMethodTable (live vtable versioning)