1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Fixed constraint checks for inner types

This commit is contained in:
Brian Fiete 2022-06-23 13:55:34 -07:00
parent 439b34f7c2
commit bca82c231f
3 changed files with 76 additions and 6 deletions

View file

@ -119,6 +119,38 @@ namespace IDETest
{
}
public class TestExt<T> where T : struct
{
public struct InnerA
{
}
public struct InnerB<T2> where T2 : struct
{
}
}
extension TestExt<T>
where T : Int
{
public int a = 0;
public struct InnerC
{
}
}
static void TestExtMethod()
{
TestExt<String>.InnerA a; //FAIL
TestExt<String>.InnerB<int> b; //FAIL
TestExt<int>.InnerB<int> c;
TestExt<int>.InnerC d;
TestExt<float>.InnerC e; //FAIL
}
}
}

View file

@ -719,6 +719,18 @@ void BfAutoComplete::AddInnerTypes(BfTypeInstance* typeInst, const StringImpl& f
for (auto innerType : typeInst->mTypeDef->mNestedTypes)
{
if (innerType->mOuterType->mTypeCode == BfTypeCode_Extension)
{
if (typeInst->mDefineState < BfTypeDefineState_Defined)
mModule->PopulateType(typeInst);
if ((typeInst->mGenericTypeInfo != NULL) && (typeInst->mGenericTypeInfo->mGenericExtensionInfo != NULL))
{
if (!typeInst->mGenericTypeInfo->mGenericExtensionInfo->mConstraintsPassedSet.IsSet(innerType->mOuterType->mPartialIdx))
continue;
}
}
if (CheckProtection(innerType->mProtection, innerType, allowProtected, allowPrivate))
AddTypeDef(innerType, filter);
}

View file

@ -9429,8 +9429,25 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
Fail(StrFormat("'%s' is inaccessible due to its protection level", TypeToString(typeInstance).c_str()), typeRef); // CS0122
}
if ((populateType > BfPopulateType_IdentityNoRemapAlias) && (!ResolveTypeResult_Validate(typeRef, resolvedTypeRef)))
// If the inner type is definted in an extension then we need to make sure the constraints are good
if ((typeInstance != NULL) && (typeInstance->mTypeDef != NULL) && (typeInstance->mTypeDef->mOuterType != NULL) &&
(typeInstance->mTypeDef->mOuterType->mTypeCode == BfTypeCode_Extension))
{
auto outerType = GetOuterType(typeInstance);
if ((outerType->mGenericTypeInfo != NULL) && (outerType->mGenericTypeInfo->mGenericExtensionInfo != NULL))
{
if (!outerType->mGenericTypeInfo->mGenericExtensionInfo->mConstraintsPassedSet.IsSet(typeInstance->mTypeDef->mOuterType->mPartialIdx))
{
Fail(StrFormat("'%s' is declared inside a type extension whose constraints were not met", TypeToString(typeInstance).c_str()), typeRef);
}
}
}
if (populateType > BfPopulateType_IdentityNoRemapAlias)
{
if (!ResolveTypeResult_Validate(typeRef, resolvedTypeRef))
return NULL;
}
if ((populateType != BfPopulateType_TypeDef) && (populateType != BfPopulateType_IdentityNoRemapAlias))
{
@ -10827,7 +10844,16 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
if (leftType == NULL)
{
BfAutoParentNodeEntry autoParentNodeEntry(this, qualifiedTypeRef);
leftType = ResolveTypeRef(qualifiedTypeRef->mLeft, BfPopulateType_Identity, (BfResolveTypeRefFlags)((resolveFlags | BfResolveTypeRefFlag_IgnoreLookupError) & ~BfResolveTypeRefFlag_Attribute)); // We throw an error below if we can't find the type
auto leftPopulateType = BfPopulateType_Identity;
if ((resolveFlags & BfResolveTypeRefFlag_AllowUnboundGeneric) == 0)
{
// We can't just pass 'Identity' here because it won't validate a generic type ref on the left
leftPopulateType = BfPopulateType_Declaration;
}
leftType = ResolveTypeRef(qualifiedTypeRef->mLeft, leftPopulateType,
(BfResolveTypeRefFlags)((resolveFlags | BfResolveTypeRefFlag_IgnoreLookupError) & ~BfResolveTypeRefFlag_Attribute)); // We throw an error below if we can't find the type
}
if (leftType == NULL)