mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 19:48:20 +02:00
Added extern constraints to types
This commit is contained in:
parent
7724c6ae64
commit
c3bc2bc67c
10 changed files with 121 additions and 38 deletions
|
@ -4012,6 +4012,8 @@ void BfCompiler::ProcessAutocompleteTempType()
|
|||
module->HandleTypeGenericParamRef(nameNode, tempTypeDef, genericParamIdx);
|
||||
}
|
||||
|
||||
//TODO: Do extern constraint stuff here
|
||||
|
||||
for (auto fieldDef : tempTypeDef->mFields)
|
||||
{
|
||||
BP_ZONE("ProcessAutocompleteTempType.CheckField");
|
||||
|
|
|
@ -1629,7 +1629,7 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
|
|||
int outerGenericSize = 0;
|
||||
if (mCurTypeDef->mOuterType != NULL)
|
||||
outerGenericSize = (int)mCurTypeDef->mOuterType->mGenericParamDefs.size();
|
||||
ParseGenericParams(typeDeclaration->mGenericParams, typeDeclaration->mGenericConstraintsDeclaration, mCurTypeDef->mGenericParamDefs, NULL, outerGenericSize);
|
||||
ParseGenericParams(typeDeclaration->mGenericParams, typeDeclaration->mGenericConstraintsDeclaration, mCurTypeDef->mGenericParamDefs, &mCurTypeDef->mExternalConstraints, outerGenericSize);
|
||||
|
||||
BF_ASSERT(mCurTypeDef->mNameEx == NULL);
|
||||
|
||||
|
|
|
@ -13034,7 +13034,7 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc,
|
|||
BfTypeVector* typeGenericArguments = NULL;
|
||||
if (owner->mGenericTypeInfo != NULL)
|
||||
typeGenericArguments = &owner->mGenericTypeInfo->mTypeGenericArguments;
|
||||
genericArg = mModule->ResolveGenericType(genericArg, typeGenericArguments, checkMethodGenericArgs);
|
||||
//genericArg = mModule->ResolveGenericType(genericArg, typeGenericArguments, checkMethodGenericArgs);
|
||||
}
|
||||
|
||||
if (genericArg->IsVar())
|
||||
|
|
|
@ -3897,10 +3897,18 @@ void BfModule::FindSubTypes(BfTypeInstance* classType, SizedArrayImpl<int>* outV
|
|||
{
|
||||
bool needsExCheck = false;
|
||||
if (ifaceInst.mDeclaringType->mProject != classType->mTypeDef->mProject)
|
||||
{
|
||||
PopulateType(ifaceInst.mInterfaceType, BfPopulateType_DataAndMethods);
|
||||
if (ifaceInst.mInterfaceType->mVirtualMethodTableSize > 0)
|
||||
{
|
||||
exChecks->push_back(ifaceInst.mInterfaceType);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We can only do an 'exCheck' if we're actually going to slot this interface
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outVals->push_back(ifaceInst.mInterfaceType->mTypeId);
|
||||
|
@ -6878,8 +6886,9 @@ String BfModule::GenericParamSourceToString(const BfGenericParamSource & generic
|
|||
{
|
||||
if (genericParamSource.mMethodInstance != NULL)
|
||||
{
|
||||
auto methodInst = GetUnspecializedMethodInstance(genericParamSource.mMethodInstance);
|
||||
return MethodToString(methodInst);
|
||||
auto methodInst = GetUnspecializedMethodInstance(genericParamSource.mMethodInstance, false);
|
||||
SetAndRestoreValue<BfMethodInstance*> prevMethodInst(methodInst, NULL);
|
||||
return MethodToString(genericParamSource.mMethodInstance);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -9264,12 +9273,16 @@ BfMethodInstance* BfModule::GetRawMethodByName(BfTypeInstance* typeInstance, con
|
|||
return NULL;
|
||||
}
|
||||
|
||||
BfMethodInstance* BfModule::GetUnspecializedMethodInstance(BfMethodInstance* methodInstance)
|
||||
BfMethodInstance* BfModule::GetUnspecializedMethodInstance(BfMethodInstance* methodInstance, bool useUnspecializedType)
|
||||
{
|
||||
if ((methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mMethodGenericArguments.size() != 0))
|
||||
methodInstance = methodInstance->mMethodInstanceGroup->mDefault;
|
||||
|
||||
auto owner = methodInstance->mMethodInstanceGroup->mOwner;
|
||||
|
||||
if (!useUnspecializedType)
|
||||
return GetRawMethodInstanceAtIdx(owner, methodInstance->mMethodDef->mIdx);
|
||||
|
||||
if (!owner->IsGenericTypeInstance())
|
||||
return methodInstance;
|
||||
|
||||
|
@ -19861,15 +19874,18 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
}
|
||||
else
|
||||
{
|
||||
if (unspecializedTypeInstance == NULL)
|
||||
unspecializedTypeInstance = GetUnspecializedTypeInstance(mCurTypeInstance);
|
||||
|
||||
auto externConstraintDef = genericParam->GetExternConstraintDef();
|
||||
// Resolve in the unspecialized type, then resolve the generic later. This fixes ambiguity where the type is specialized by a method generic arg
|
||||
{
|
||||
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, unspecializedTypeInstance);
|
||||
|
||||
// if (unspecializedTypeInstance == NULL)
|
||||
// unspecializedTypeInstance = GetUnspecializedTypeInstance(mCurTypeInstance);
|
||||
//
|
||||
// // Resolve in the unspecialized type, then resolve the generic later. This fixes ambiguity where the type is specialized by a method generic arg
|
||||
// {
|
||||
// SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, unspecializedTypeInstance);
|
||||
// genericParam->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef);
|
||||
// }
|
||||
|
||||
genericParam->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef);
|
||||
}
|
||||
|
||||
auto autoComplete = mCompiler->GetAutoComplete();
|
||||
if (autoComplete != NULL)
|
||||
|
|
|
@ -1768,7 +1768,7 @@ public:
|
|||
BfMethodInstance* GetRawMethodInstanceAtIdx(BfTypeInstance* typeInstance, int methodIdx, const char* assertName = NULL);
|
||||
BfMethodInstance* GetRawMethodInstance(BfTypeInstance* typeInstance, BfMethodDef* methodDef);
|
||||
BfMethodInstance* GetRawMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount = -1, bool checkBase = false, bool allowMixin = false);
|
||||
BfMethodInstance* GetUnspecializedMethodInstance(BfMethodInstance* methodInstance); // Unspecialized owner type and unspecialized method type
|
||||
BfMethodInstance* GetUnspecializedMethodInstance(BfMethodInstance* methodInstance, bool useUnspecializedType = true); // Unspecialized owner type and unspecialized method type
|
||||
int GetGenericParamAndReturnCount(BfMethodInstance* methodInstance);
|
||||
BfModule* GetSpecializedMethodModule(const SizedArrayImpl<BfProject*>& projectList);
|
||||
BfModuleMethodInstance GetMethodInstanceAtIdx(BfTypeInstance* typeInstance, int methodIdx, const char* assertName = NULL, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None);
|
||||
|
|
|
@ -75,6 +75,12 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfTypeInstance* gen
|
|||
genericExEntry->mGenericParams.push_back(genericParamInstance);
|
||||
}
|
||||
|
||||
for (int externConstraintIdx = 0; externConstraintIdx < (int)partialTypeDef->mExternalConstraints.size(); externConstraintIdx++)
|
||||
{
|
||||
auto genericParamInstance = new BfGenericTypeParamInstance(partialTypeDef, externConstraintIdx + (int)partialTypeDef->mGenericParamDefs.size());
|
||||
genericExEntry->mGenericParams.push_back(genericParamInstance);
|
||||
}
|
||||
|
||||
for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size(); paramIdx++)
|
||||
{
|
||||
auto genericParamInstance = genericExEntry->mGenericParams[paramIdx];
|
||||
|
@ -124,6 +130,12 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
|
|||
genericTypeInst->mGenericTypeInfo->mGenericParams.push_back(genericParamInstance);
|
||||
}
|
||||
|
||||
for (int externConstraintIdx = 0; externConstraintIdx < (int)typeDef->mExternalConstraints.size(); externConstraintIdx++)
|
||||
{
|
||||
auto genericParamInstance = new BfGenericTypeParamInstance(typeDef, externConstraintIdx + (int)typeDef->mGenericParamDefs.size());
|
||||
genericTypeInst->mGenericTypeInfo->mGenericParams.push_back(genericParamInstance);
|
||||
}
|
||||
|
||||
if (!typeDef->mPartials.empty())
|
||||
{
|
||||
for (auto partialTypeDef : typeDef->mPartials)
|
||||
|
@ -172,6 +184,28 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
|
|||
for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mGenericParams.size(); paramIdx++)
|
||||
{
|
||||
auto genericParamInstance = genericTypeInst->mGenericTypeInfo->mGenericParams[paramIdx];
|
||||
|
||||
if (paramIdx < (int)typeDef->mGenericParamDefs.size())
|
||||
{
|
||||
genericParamInstance->mExternType = GetGenericParamType(BfGenericParamKind_Type, paramIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto externConstraintDef = genericParamInstance->GetExternConstraintDef();
|
||||
genericParamInstance->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef);
|
||||
|
||||
auto autoComplete = mCompiler->GetAutoComplete();
|
||||
if (autoComplete != NULL)
|
||||
autoComplete->CheckTypeRef(externConstraintDef->mTypeRef, false);
|
||||
|
||||
if (genericParamInstance->mExternType != NULL)
|
||||
{
|
||||
//
|
||||
}
|
||||
else
|
||||
genericParamInstance->mExternType = GetPrimitiveType(BfTypeCode_Var);
|
||||
}
|
||||
|
||||
ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType());
|
||||
auto genericParamDef = genericParamInstance->GetGenericParamDef();
|
||||
if (genericParamDef != NULL)
|
||||
|
@ -223,20 +257,30 @@ bool BfModule::ValidateGenericConstraints(BfTypeReference* typeRef, BfTypeInstan
|
|||
}
|
||||
|
||||
auto typeDef = genericTypeInst->mTypeDef;
|
||||
for (int paramIdx = 0; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size(); paramIdx++)
|
||||
//for (int paramIdx = 0; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size(); paramIdx++)
|
||||
|
||||
for (int paramIdx = 0; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mGenericParams.size(); paramIdx++)
|
||||
{
|
||||
auto genericParamInstance = genericTypeInst->mGenericTypeInfo->mGenericParams[paramIdx];
|
||||
// Why did we remove this line? This breaks determining compatibility of one unspecialized type to another unspecialized type, called from ResolveTypeResult
|
||||
//if (!genericTypeInst->mIsUnspecialized)
|
||||
|
||||
BfType* genericArg;
|
||||
if (paramIdx < (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size())
|
||||
{
|
||||
genericArg = genericTypeInst->mGenericTypeInfo->mTypeGenericArguments[paramIdx];
|
||||
}
|
||||
else
|
||||
{
|
||||
genericArg = genericParamInstance->mExternType;
|
||||
}
|
||||
|
||||
BfError* error = NULL;
|
||||
if (!CheckGenericConstraints(BfGenericParamSource(genericTypeInst), genericTypeInst->mGenericTypeInfo->mTypeGenericArguments[paramIdx], typeRef, genericParamInstance, NULL, &error))
|
||||
if (!CheckGenericConstraints(BfGenericParamSource(genericTypeInst), genericArg, typeRef, genericParamInstance, NULL, &error))
|
||||
{
|
||||
genericTypeInst->mGenericTypeInfo->mHadValidateErrors = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -10394,11 +10438,11 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit)))
|
||||
{
|
||||
// If we can convert OUR fromVal to the constraint's fromVal then we may match
|
||||
if (CanCast(typedVal, opConstraint.mRightType))
|
||||
if (CanCast(typedVal, opConstraint.mRightType, BfCastFlags_NoConversionOperator))
|
||||
{
|
||||
// .. and we can convert the constraint's toType to OUR toType then we're good
|
||||
auto opToVal = genericParam->mExternType;
|
||||
if (CanCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType))
|
||||
if (CanCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType, BfCastFlags_NoConversionOperator))
|
||||
return mBfIRBuilder->GetFakeVal();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1091,7 +1091,7 @@ public:
|
|||
{
|
||||
if (mGenericIdx < (int)mTypeDef->mGenericParamDefs.size())
|
||||
return mTypeDef->mGenericParamDefs[mGenericIdx];
|
||||
return NULL;
|
||||
return &mTypeDef->mExternalConstraints[mGenericIdx - (int)mTypeDef->mGenericParamDefs.size()];
|
||||
}
|
||||
|
||||
virtual BfGenericParamDef* GetGenericParamDef() override
|
||||
|
@ -1105,14 +1105,14 @@ public:
|
|||
{
|
||||
if (mGenericIdx < (int)mTypeDef->mGenericParamDefs.size())
|
||||
return NULL;
|
||||
return NULL;
|
||||
return &mTypeDef->mExternalConstraints[mGenericIdx - (int)mTypeDef->mGenericParamDefs.size()];
|
||||
}
|
||||
|
||||
virtual String GetName() override
|
||||
{
|
||||
if (mGenericIdx < (int)mTypeDef->mGenericParamDefs.size())
|
||||
return mTypeDef->mGenericParamDefs[mGenericIdx]->mName;
|
||||
return "???";
|
||||
return mTypeDef->mExternalConstraints[mGenericIdx - (int)mTypeDef->mGenericParamDefs.size()].mTypeRef->ToString();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -2662,6 +2662,7 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef)
|
|||
typeDef->mGenericParamDefs.Clear();
|
||||
|
||||
typeDef->mGenericParamDefs = nextTypeDef->mGenericParamDefs;
|
||||
typeDef->mExternalConstraints = nextTypeDef->mExternalConstraints;
|
||||
nextTypeDef->mGenericParamDefs.Clear();
|
||||
|
||||
typeDef->mBaseTypes = nextTypeDef->mBaseTypes;
|
||||
|
@ -2739,6 +2740,7 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
|
|||
*newGeneric = *generic;
|
||||
typeDef->mGenericParamDefs.push_back(newGeneric);
|
||||
}
|
||||
typeDef->mExternalConstraints = partialTypeDef->mExternalConstraints;
|
||||
|
||||
typeDef->mBaseTypes = partialTypeDef->mBaseTypes;
|
||||
|
||||
|
@ -2756,6 +2758,9 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
|
|||
typeDef->mTypeCode = partialTypeDef->mTypeCode;
|
||||
typeDef->mTypeDeclaration = partialTypeDef->mTypeDeclaration;
|
||||
}
|
||||
|
||||
for (auto& externConstraint : partialTypeDef->mExternalConstraints)
|
||||
typeDef->mExternalConstraints.Add(externConstraint);
|
||||
}
|
||||
|
||||
// Merge attributes together
|
||||
|
|
|
@ -880,6 +880,7 @@ public:
|
|||
Array<BfOperatorDef*> mOperators;
|
||||
BfMethodDef* mDtorDef;
|
||||
Array<BfGenericParamDef*> mGenericParamDefs;
|
||||
Array<BfExternalConstraintDef> mExternalConstraints;
|
||||
Array<BfTypeReference*> mBaseTypes;
|
||||
Array<BfTypeDef*> mNestedTypes;
|
||||
Array<BfDirectStrTypeReference*> mDirectAllocNodes;
|
||||
|
|
|
@ -176,17 +176,28 @@ namespace Tests
|
|||
return val + val2;
|
||||
}
|
||||
|
||||
public static T Complex<T, T2>(T val, T2 val2)
|
||||
where T : operator T + T2
|
||||
public static T Complex<T, T2, T3>(T val, T2 val2, T3 val3)
|
||||
where T : operator -T
|
||||
where T : operator implicit T2
|
||||
where T : operator T + T2
|
||||
where int32 : operator T + T3
|
||||
{
|
||||
T conv = val2;
|
||||
T result = val + val2;
|
||||
result = -result;
|
||||
int32 iRes = val + val3;
|
||||
return result;
|
||||
}
|
||||
|
||||
struct StructOp3<T, T2> where float : operator T + T2
|
||||
{
|
||||
public float Use(T lhs, T2 rhs)
|
||||
{
|
||||
float f = lhs + rhs;
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void TestBasics()
|
||||
{
|
||||
|
@ -212,7 +223,7 @@ namespace Tests
|
|||
float val = Op((int32)100, (int16)23);
|
||||
Test.Assert(val == 123);
|
||||
|
||||
int32 i32res = Complex((int32)100, (int16)23);
|
||||
int32 i32res = Complex((int32)100, (int16)23, (int8)4);
|
||||
Test.Assert(i32res == -123);
|
||||
|
||||
StructOp<StructA, StructB> sOp;
|
||||
|
@ -231,6 +242,10 @@ namespace Tests
|
|||
Test.Assert(rsc == rsc2);
|
||||
Test.Assert(rsc !== rsc2);
|
||||
|
||||
StructOp3<int16, int32> so3 = .();
|
||||
float f = so3.Use(1, 2);
|
||||
Test.Assert(f == 3);
|
||||
|
||||
/*let oai = OuterOp<float>.InnerOp<int>.Op(1.0f, 100);
|
||||
Test.Assert(oai == 101.0f);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue