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

Fixes for type dependencies and tests for type deletion bug

This commit is contained in:
Brian Fiete 2020-06-04 11:47:55 -07:00
parent 198acef1c6
commit 03fbc9d468
16 changed files with 309 additions and 55 deletions

View file

@ -0,0 +1,5 @@
FileVersion = 1
[Project]
Name = "Bug"
StartupObject = "Bug.Program"

View file

@ -0,0 +1,6 @@
FileVersion = 1
Projects = {Bug = {Path = "."}}
[Workspace]
StartupProject = "Bug"

View file

@ -0,0 +1,21 @@
# This tests that types that fail generic tests don't create types referenced in methods
# and also that they get deleted immediately when they are dereferenced.
ShowFile("src/Program.bf")
SetExpectError("Generic argument")
Compile()
ExpectError()
AssertTypeInfo(1, "System.Collections.Dictionary<System.Collections.Dictionary<int, float>.Enumerator, (int key, float value)>", "Found Reified ValidateErrors")
AssertTypeInfo(1, "System.Collections.Dictionary<System.Collections.Dictionary<int, float>.Enumerator, (int key, float value)>.Entry", "Found Reified ValidateErrors")
ToggleCommentAt("Method3_BadCall")
ToggleCommentAt("Method3_GoodCall")
Compile()
AssertTypeInfo(0, "System.Collections.Dictionary<System.Collections.Dictionary<int, float>.Enumerator, (int key, float value)>", "")
AssertTypeInfo(0, "System.Collections.Dictionary<System.Collections.Dictionary<int, float>.Enumerator, (int key, float value)>.Entry", "")
AssertTypeInfo(0, "System.Collections.Dictionary<System.Collections.Dictionary<int, float>.Enumerator, (int key, float value)>", "")
AssertTypeInfo(0, "System.Collections.Dictionary<System.Collections.Dictionary<int, float>.Enumerator, (int key, float value)>.Entry", "")

View file

@ -0,0 +1,49 @@
#pragma warning disable 168
using System;
using System.Collections;
namespace Bug
{
class Program
{
class Dicto : Dictionary<int, float>
{
}
public static bool Method1<T>(IEnumerator<T> param1)
{
return true;
}
public static bool Method2<TEnumerator, TElement>(TEnumerator param1) where TEnumerator : IEnumerator<TElement>
{
for (let val in param1)
{
}
return true;
}
public static bool Method3<K, V>(Dictionary<K, V> param1) where K : IHashable
{
Method1(param1.GetEnumerator());
Method1((IEnumerator<(K key, V value)>)param1.GetEnumerator());
//*Method3_BadCall
return Method3<Dictionary<K, V>.Enumerator, (K key, V value)>(param1.GetEnumerator());
/*@*/
/*Method3_GoodCall
return Method2<Dictionary<K, V>.Enumerator, (K key, V value)>(param1.GetEnumerator());
*/
}
static void Main()
{
Dicto dicto = scope .();
Method3(dicto);
}
}
}

View file

@ -99,6 +99,9 @@ namespace IDE.Compiler
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
static extern char8* BfCompiler_GetTypeDefInfo(void* bfCompiler, char8* typeDefName); static extern char8* BfCompiler_GetTypeDefInfo(void* bfCompiler, char8* typeDefName);
[CallingConvention(.Stdcall), CLink]
static extern char8* BfCompiler_GetTypeInfo(void* bfCompiler, char8* typeName);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
static extern void BfCompiler_SetOptions(void* bfCompiler, static extern void BfCompiler_SetOptions(void* bfCompiler,
void* hotProject, int32 hotIdx, char8* targetTriple, int32 toolsetType, int32 simdSetting, int32 allocStackCount, int32 maxWorkerThreads, void* hotProject, int32 hotIdx, char8* targetTriple, int32 toolsetType, int32 simdSetting, int32 allocStackCount, int32 maxWorkerThreads,
@ -682,6 +685,11 @@ namespace IDE.Compiler
outStr.Append(BfCompiler_GetTypeDefInfo(mNativeBfCompiler, typeDefName)); outStr.Append(BfCompiler_GetTypeDefInfo(mNativeBfCompiler, typeDefName));
} }
public void GetTypeInfo(String typeDefName, String outStr)
{
outStr.Append(BfCompiler_GetTypeInfo(mNativeBfCompiler, typeDefName));
}
public void ClearBuildCache() public void ClearBuildCache()
{ {
BfCompiler_ClearBuildCache(mNativeBfCompiler); BfCompiler_ClearBuildCache(mNativeBfCompiler);

View file

@ -4417,7 +4417,8 @@ namespace IDE
if (!mInitialized) if (!mInitialized)
return; return;
#if !CLI #if !CLI
mLastActivePanel = panel; if (setFocus)
mLastActivePanel = panel;
RecordHistoryLocation(); RecordHistoryLocation();
ShowTab(panel, label, false, setFocus); ShowTab(panel, label, false, setFocus);
if (setFocus) if (setFocus)
@ -4580,7 +4581,7 @@ namespace IDE
[IDECommand] [IDECommand]
public void ShowOutput() public void ShowOutput()
{ {
ShowPanel(mOutputPanel, "Output"); ShowPanel(mOutputPanel, "Output", false);
} }
[IDECommand] [IDECommand]

View file

@ -1513,6 +1513,17 @@ namespace IDE
} }
} }
[IDECommand]
public void AssertTypeInfo(int compilerId, String typeName, String wantTypeInfo)
{
String typeInfo = scope String();
var compiler = (compilerId == 0) ? gApp.mBfResolveCompiler : gApp.mBfBuildCompiler;
compiler.GetTypeInfo(typeName, typeInfo);
if (typeInfo != wantTypeInfo)
mScriptManager.Fail("Assert failed: {0} == {1}", typeInfo, wantTypeInfo);
}
[IDECommand] [IDECommand]
public void AddWatch(String evalStr) public void AddWatch(String evalStr)
{ {

View file

@ -2052,6 +2052,8 @@ void BfCompiler::UpdateDependencyMap(bool deleteUnusued, bool& didWork)
if ((mResolvePassData != NULL) && (mResolvePassData->mParser != NULL)) if ((mResolvePassData != NULL) && (mResolvePassData->mParser != NULL))
madeFullPass = false; madeFullPass = false;
SetAndRestoreValue<bool> prevAssertOnPopulateType(mContext->mAssertOnPopulateType, deleteUnusued && madeFullPass);
if ((deleteUnusued) && (madeFullPass)) if ((deleteUnusued) && (madeFullPass))
{ {
// Work queues should be empty if we're not canceling // Work queues should be empty if we're not canceling
@ -2077,7 +2079,12 @@ void BfCompiler::UpdateDependencyMap(bool deleteUnusued, bool& didWork)
auto typeInst = type->ToTypeInstance(); auto typeInst = type->ToTypeInstance();
if (depType != NULL) if (depType != NULL)
{ {
if ((depType->mTypeId == 2574) && (!mIsResolveOnly) && (deleteUnusued))
{
NOP;
}
extern BfModule* gLastCreatedModule; extern BfModule* gLastCreatedModule;
for (auto itr = depType->mDependencyMap.begin(); itr != depType->mDependencyMap.end(); ++itr) for (auto itr = depType->mDependencyMap.begin(); itr != depType->mDependencyMap.end(); ++itr)
@ -2145,12 +2152,9 @@ void BfCompiler::UpdateDependencyMap(bool deleteUnusued, bool& didWork)
if ((depTypeInst != NULL) && (typeInst->mLastNonGenericUsedRevision != mRevision) && (isDependentUsage) && if ((depTypeInst != NULL) && (typeInst->mLastNonGenericUsedRevision != mRevision) && (isDependentUsage) &&
((isDirectReference) || (dependentType->IsUnspecializedType()) || (depTypeInst->mLastNonGenericUsedRevision == mRevision))) ((isDirectReference) || (dependentType->IsUnspecializedType()) || (depTypeInst->mLastNonGenericUsedRevision == mRevision)))
{ {
//if (deleteUnusued) typeInst->mLastNonGenericUsedRevision = mRevision;
{ foundNew = true;
typeInst->mLastNonGenericUsedRevision = mRevision;
foundNew = true;
}
if (!typeInst->HasBeenReferenced()) if (!typeInst->HasBeenReferenced())
{ {
@ -8250,6 +8254,92 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeDefInfo(BfCompiler* bfCompil
return outString.c_str(); return outString.c_str();
} }
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeInfo(BfCompiler* bfCompiler, const char* name)
{
String& outString = *gTLStrReturn.Get();
outString = "";
String typeName = name;
auto system = bfCompiler->mSystem;
AutoCrit autoCrit(system->mSystemLock);
String& autoCompleteResultString = *gTLStrReturn.Get();
autoCompleteResultString.Clear();
BfPassInstance passInstance(bfCompiler->mSystem);
BfParser parser(bfCompiler->mSystem);
parser.SetSource(typeName.c_str(), (int)typeName.length());
parser.Parse(&passInstance);
BfReducer reducer;
reducer.mAlloc = parser.mAlloc;
reducer.mPassInstance = &passInstance;
reducer.mAllowTypeWildcard = true;
if (parser.mRootNode->mChildArr.mSize == 0)
return false;
bool attribWasClosed = false;
bool isAttributeRef = false;
auto firstNode = parser.mRootNode->mChildArr[0];
auto endIdx = parser.mRootNode->mSrcEnd;
reducer.mVisitorPos = BfReducer::BfVisitorPos(parser.mRootNode);
if (auto tokenNode = BfNodeDynCast<BfTokenNode>(firstNode))
{
if (tokenNode->mToken == BfToken_LBracket)
{
if (auto lastToken = BfNodeDynCast<BfTokenNode>(parser.mRootNode->mChildArr.back()))
{
if (lastToken->mToken == BfToken_RBracket)
{
attribWasClosed = true;
endIdx = lastToken->mSrcStart;
}
}
isAttributeRef = true;
if (parser.mRootNode->mChildArr.mSize < 2)
return false;
firstNode = parser.mRootNode->mChildArr[1];
reducer.mVisitorPos.MoveNext();
}
}
reducer.mVisitorPos.MoveNext();
auto typeRef = reducer.CreateTypeRef(firstNode);
if (typeRef == NULL)
return "";
BfResolvePassData resolvePass;
SetAndRestoreValue<bool> prevIgnoreError(bfCompiler->mContext->mScratchModule->mIgnoreErrors, true);
SetAndRestoreValue<bool> prevIgnoreWarnings(bfCompiler->mContext->mScratchModule->mIgnoreWarnings, true);
SetAndRestoreValue<BfResolvePassData*> prevResolvePass(bfCompiler->mResolvePassData, &resolvePass);
auto type = bfCompiler->mContext->mScratchModule->ResolveTypeRef(typeRef, BfPopulateType_Data, BfResolveTypeRefFlag_NoCreate);
if (type != NULL)
{
outString += "Found";
if (auto typeInst = type->ToTypeInstance())
{
if (typeInst->mIsReified)
outString += " Reified";
if (typeInst->mHasBeenInstantiated)
outString += " Instantiated";
if (typeInst->mTypeFailed)
outString += " TypeFailed";
if (auto genericTypeInst = typeInst->ToGenericTypeInstance())
{
if (genericTypeInst->mHadValidateErrors)
outString += " ValidateErrors";
}
}
}
return outString.c_str();
}
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetOutputFileNames(BfCompiler* bfCompiler, BfProject* bfProject, bool* hadOutputChanges) BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetOutputFileNames(BfCompiler* bfCompiler, BfProject* bfProject, bool* hadOutputChanges)
{ {
BF_FATAL("not used ?"); BF_FATAL("not used ?");

View file

@ -48,6 +48,7 @@ BfContext::BfContext(BfCompiler* compiler) :
mCurTypeState = NULL; mCurTypeState = NULL;
mCurConstraintState = NULL; mCurConstraintState = NULL;
mResolvingVarField = false; mResolvingVarField = false;
mAssertOnPopulateType = false;
for (int i = 0; i < BfTypeCode_Length; i++) for (int i = 0; i < BfTypeCode_Length; i++)
{ {
@ -762,6 +763,8 @@ BfType * BfContext::FindTypeById(int typeId)
void BfContext::AddTypeToWorkList(BfType* type) void BfContext::AddTypeToWorkList(BfType* type)
{ {
BF_ASSERT(!mAssertOnPopulateType);
BF_ASSERT((type->mRebuildFlags & BfTypeRebuildFlag_InTempPool) == 0); BF_ASSERT((type->mRebuildFlags & BfTypeRebuildFlag_InTempPool) == 0);
if ((type->mRebuildFlags & BfTypeRebuildFlag_AddedToWorkList) == 0) if ((type->mRebuildFlags & BfTypeRebuildFlag_AddedToWorkList) == 0)
{ {
@ -1464,8 +1467,8 @@ void BfContext::DeleteType(BfType* type, bool deferDepRebuilds)
} }
} }
} }
} }
type->mRebuildFlags = (BfTypeRebuildFlags)((type->mRebuildFlags | BfTypeRebuildFlag_Deleted) & ~BfTypeRebuildFlag_DeleteQueued); type->mRebuildFlags = (BfTypeRebuildFlags)((type->mRebuildFlags | BfTypeRebuildFlag_Deleted) & ~BfTypeRebuildFlag_DeleteQueued);
SaveDeletingType(type); SaveDeletingType(type);
@ -1530,6 +1533,19 @@ void BfContext::DeleteType(BfType* type, bool deferDepRebuilds)
if ((dependencyEntry.mFlags & ~(BfDependencyMap::DependencyFlag_UnspecializedType | BfDependencyMap::DependencyFlag_WeakReference)) == 0) if ((dependencyEntry.mFlags & ~(BfDependencyMap::DependencyFlag_UnspecializedType | BfDependencyMap::DependencyFlag_WeakReference)) == 0)
continue; // Not a cause for rebuilding continue; // Not a cause for rebuilding
if (dependentTypeInst->IsOnDemand())
{
// Force on-demand dependencies to rebuild themselves
DeleteType(dependentType, deferDepRebuilds);
continue;
}
if (dType->IsBoxed())
{
// Allow these to just be implicitly used. This solves some issues with switching between ignoreWrites settings in resolveOnly compilation
continue;
}
if ((deferDepRebuilds) && (dependentTypeInst != NULL)) if ((deferDepRebuilds) && (dependentTypeInst != NULL))
mFailTypes.Add(dependentTypeInst); mFailTypes.Add(dependentTypeInst);
else else

View file

@ -317,6 +317,7 @@ public:
BfConstraintState* mCurConstraintState; BfConstraintState* mCurConstraintState;
bool mResolvingVarField; bool mResolvingVarField;
int mMappedObjectRevision; int mMappedObjectRevision;
bool mAssertOnPopulateType;
BfSystem* mSystem; BfSystem* mSystem;
BfCompiler* mCompiler; BfCompiler* mCompiler;

View file

@ -1369,9 +1369,9 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
if (checkMethod->mMethodType == BfMethodType_Extension) if (checkMethod->mMethodType == BfMethodType_Extension)
{ {
argIdx--; argIdx--;
paramOfs++;
} }
paramIdx += paramOfs;
for ( ; argIdx < (int)mArguments.size(); argIdx++) for ( ; argIdx < (int)mArguments.size(); argIdx++)
{ {
@ -1845,7 +1845,8 @@ bool BfMethodMatcher::IsType(BfTypedValue& typedVal, BfType* type)
// This method checks all base classes before checking interfaces. Is that correct? // This method checks all base classes before checking interfaces. Is that correct?
bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue target, bool isFailurePass, bool forceOuterCheck) bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue target, bool isFailurePass, bool forceOuterCheck)
{ {
BfMethodDef* prevBesstMethodDef = mBestMethodDef;
auto curTypeInst = typeInstance; auto curTypeInst = typeInstance;
auto curTypeDef = typeInstance->mTypeDef; auto curTypeDef = typeInstance->mTypeDef;
@ -2041,7 +2042,7 @@ bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue targe
if (mAutoFlushAmbiguityErrors) if (mAutoFlushAmbiguityErrors)
FlushAmbiguityError(); FlushAmbiguityError();
return mBestMethodDef != NULL; return mBestMethodDef != prevBesstMethodDef;
} }
void BfMethodMatcher::TryDevirtualizeCall(BfTypedValue target, BfTypedValue* origTarget, BfTypedValue* staticResult) void BfMethodMatcher::TryDevirtualizeCall(BfTypedValue target, BfTypedValue* origTarget, BfTypedValue* staticResult)
@ -7155,9 +7156,8 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
{ {
auto checkTypeInst = mModule->mCurTypeInstance; auto checkTypeInst = mModule->mCurTypeInstance;
methodMatcher.mMethodType = BfMethodType_Extension; methodMatcher.mMethodType = BfMethodType_Extension;
methodMatcher.CheckType(checkTypeInst, BfTypedValue(), false, true); if (methodMatcher.CheckType(checkTypeInst, BfTypedValue(), false, true))
if (methodMatcher.mBestMethodDef != NULL) {
{
isFailurePass = false; isFailurePass = false;
curTypeInst = methodMatcher.mBestMethodTypeInstance; curTypeInst = methodMatcher.mBestMethodTypeInstance;
methodDef = methodMatcher.mBestMethodDef; methodDef = methodMatcher.mBestMethodDef;
@ -7178,9 +7178,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
if (globalContainer.mTypeInst == NULL) if (globalContainer.mTypeInst == NULL)
continue; continue;
methodMatcher.mMethodType = wantsExtensionCheck ? BfMethodType_Extension : BfMethodType_Normal; methodMatcher.mMethodType = wantsExtensionCheck ? BfMethodType_Extension : BfMethodType_Normal;
methodMatcher.CheckType(globalContainer.mTypeInst, BfTypedValue(), false); if (methodMatcher.CheckType(globalContainer.mTypeInst, BfTypedValue(), false))
if (methodMatcher.mBestMethodDef != NULL)
{ {
isFailurePass = false; isFailurePass = false;
curTypeInst = methodMatcher.mBestMethodTypeInstance; curTypeInst = methodMatcher.mBestMethodTypeInstance;
@ -7202,8 +7200,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
for (auto typeInst : staticSearch->mStaticTypes) for (auto typeInst : staticSearch->mStaticTypes)
{ {
methodMatcher.mMethodType = wantsExtensionCheck ? BfMethodType_Extension : BfMethodType_Normal; methodMatcher.mMethodType = wantsExtensionCheck ? BfMethodType_Extension : BfMethodType_Normal;
methodMatcher.CheckType(typeInst, BfTypedValue(), false); if (methodMatcher.CheckType(typeInst, BfTypedValue(), false))
if (methodMatcher.mBestMethodDef != NULL)
{ {
isFailurePass = false; isFailurePass = false;
curTypeInst = methodMatcher.mBestMethodTypeInstance; curTypeInst = methodMatcher.mBestMethodTypeInstance;
@ -11995,7 +11992,11 @@ void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr)
} }
else else
{ {
if ((!resolvedTypeRef->IsObjectOrInterface()) && (!resolvedTypeRef->IsGenericParam())) if (resolvedTypeRef->IsVar())
{
// Leave as a var
}
else if ((!resolvedTypeRef->IsObjectOrInterface()) && (!resolvedTypeRef->IsGenericParam()))
{ {
resultType = mModule->CreatePointerType(resolvedTypeRef); resultType = mModule->CreatePointerType(resolvedTypeRef);
} }

View file

@ -2991,6 +2991,16 @@ void BfModule::AddDependency(BfType* usedType, BfType* userType, BfDependencyMap
if (usedType->IsSpecializedByAutoCompleteMethod()) if (usedType->IsSpecializedByAutoCompleteMethod())
return; return;
// if (usedType->IsBoxed())
// {
// NOP;
// auto underlyingType = usedType->GetUnderlyingType()->ToTypeInstance();
// if ((underlyingType != NULL) && (underlyingType->IsInstanceOf(mCompiler->mSizedArrayTypeDef)))
// {
// BfLogSysM("AddDependency UsedType:%p UserType:%p Method:%p\n", usedType, userType, mCurMethodInstance);
// }
// }
BfType* origUsedType = usedType; BfType* origUsedType = usedType;
bool isDataAccess = ((flags & (BfDependencyMap::DependencyFlag_ReadFields | BfDependencyMap::DependencyFlag_LocalUsage | BfDependencyMap::DependencyFlag_Allocates)) != 0); bool isDataAccess = ((flags & (BfDependencyMap::DependencyFlag_ReadFields | BfDependencyMap::DependencyFlag_LocalUsage | BfDependencyMap::DependencyFlag_Allocates)) != 0);
if (isDataAccess) if (isDataAccess)
@ -18581,6 +18591,7 @@ BfModuleMethodInstance BfModule::GetLocalMethodInstance(BfLocalMethod* localMeth
BF_ASSERT(methodInstance->mMethodInfoEx != NULL); BF_ASSERT(methodInstance->mMethodInfoEx != NULL);
methodState.mGenericTypeBindings = &methodInstance->mMethodInfoEx->mGenericTypeBindings; methodState.mGenericTypeBindings = &methodInstance->mMethodInfoEx->mGenericTypeBindings;
methodState.mMethodInstance = methodInstance;
NewScopeState(); NewScopeState();
ProcessMethod_SetupParams(methodInstance, NULL, false, NULL); ProcessMethod_SetupParams(methodInstance, NULL, false, NULL);

View file

@ -1268,22 +1268,6 @@ public:
String mName; String mName;
}; };
enum BfResolveTypeRefFlags
{
BfResolveTypeRefFlag_None = 0,
BfResolveTypeRefFlag_NoResolveGenericParam = 1,
BfResolveTypeRefFlag_AllowRef = 2,
BfResolveTypeRefFlag_AllowRefGeneric = 4,
BfResolveTypeRefFlag_IgnoreLookupError = 8,
BfResolveTypeRefFlag_AllowGenericTypeParamConstValue = 0x10,
BfResolveTypeRefFlag_AllowGenericMethodParamConstValue = 0x20,
BfResolveTypeRefFlag_AllowGenericParamConstValue = 0x10 | 0x20,
BfResolveTypeRefFlag_AutoComplete = 0x40,
BfResolveTypeRefFlag_FromIndirectSource = 0x80, // Such as a type alias or a generic parameter
BfResolveTypeRefFlag_Attribute = 0x100,
BfResolveTypeRefFlag_NoReify = 0x200
};
enum BfSrcPosFlags enum BfSrcPosFlags
{ {
BfSrcPosFlag_None = 0, BfSrcPosFlag_None = 0,

View file

@ -881,6 +881,11 @@ bool BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
else else
resolvedTypeRef->mTypeId = mCompiler->mCurTypeId++; resolvedTypeRef->mTypeId = mCompiler->mCurTypeId++;
if ((resolvedTypeRef->mTypeId == 2599) && (!mCompiler->mIsResolveOnly))
{
NOP;
}
while (resolvedTypeRef->mTypeId >= (int)mContext->mTypes.size()) while (resolvedTypeRef->mTypeId >= (int)mContext->mTypes.size())
mContext->mTypes.Add(NULL); mContext->mTypes.Add(NULL);
mContext->mTypes[resolvedTypeRef->mTypeId] = resolvedTypeRef; mContext->mTypes[resolvedTypeRef->mTypeId] = resolvedTypeRef;
@ -3648,6 +3653,13 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
} }
} }
bool isFailedType = mCurTypeInstance->mTypeFailed;
if (auto genericTypeInst = mCurTypeInstance->ToGenericTypeInstance())
{
if (genericTypeInst->mHadValidateErrors)
isFailedType = true;
}
// Generate all methods. Pass 1 // Generate all methods. Pass 1
for (auto methodDef : typeDef->mMethods) for (auto methodDef : typeDef->mMethods)
{ {
@ -3656,6 +3668,12 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude)
continue; continue;
if (isFailedType)
{
// We don't want method decls from failed generic types to clog up our type system
continue;
}
// This should still be set to the default value // This should still be set to the default value
BF_ASSERT(methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet); BF_ASSERT(methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet);
@ -4014,7 +4032,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
mCompiler->mHotState->mHasNewInterfaceTypes = true; mCompiler->mHotState->mHasNewInterfaceTypes = true;
} }
if ((!typeInstance->IsInterface()) && (!typeInstance->IsUnspecializedTypeVariation()) && (!isBoxed)) if ((!typeInstance->IsInterface()) && (!typeInstance->IsUnspecializedTypeVariation()) && (!isBoxed) && (!isFailedType))
{ {
if (!typeInstance->mTypeDef->mIsAbstract) if (!typeInstance->mTypeDef->mIsAbstract)
{ {
@ -4542,6 +4560,8 @@ BfUnknownSizedArrayType* BfModule::CreateUnknownSizedArrayType(BfType* resolvedT
BfPointerType* BfModule::CreatePointerType(BfType* resolvedType) BfPointerType* BfModule::CreatePointerType(BfType* resolvedType)
{ {
BF_ASSERT(!resolvedType->IsVar());
auto pointerType = mContext->mPointerTypePool.Get(); auto pointerType = mContext->mPointerTypePool.Get();
pointerType->mContext = mContext; pointerType->mContext = mContext;
pointerType->mElementType = resolvedType; pointerType->mElementType = resolvedType;
@ -6273,16 +6293,20 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
} }
if (resolvedTypeRef == NULL) if (resolvedTypeRef == NULL)
return NULL; return NULL;
if (resolvedTypeRef->IsTuple()) if (mCurTypeInstance == NULL)
{
// No deps
}
else if (resolvedTypeRef->IsTuple())
{ {
// Add the fields from the tuple as references since those inner fields types would have been explicitly stated, so we need // Add the fields from the tuple as references since those inner fields types would have been explicitly stated, so we need
// to make sure to record the current type instance as a referring type. This mostly matters for symbol renaming. // to make sure to record the current type instance as a referring type. This mostly matters for symbol renaming.
BfTupleType* payloadTupleType = (BfTupleType*)resolvedTypeRef; BfTupleType* payloadTupleType = (BfTupleType*)resolvedTypeRef;
for (auto& payloadFieldInst : payloadTupleType->mFieldInstances) for (auto& payloadFieldInst : payloadTupleType->mFieldInstances)
{ {
auto payloadFieldType = payloadFieldInst.mResolvedType; auto payloadFieldType = payloadFieldInst.mResolvedType;
AddDependency(payloadFieldType, mCurTypeInstance, BfDependencyMap::DependencyFlag_TypeReference); AddDependency(payloadFieldType, mCurTypeInstance, BfDependencyMap::DependencyFlag_TypeReference);
} }
} }
@ -7408,7 +7432,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
if (leftType == NULL) if (leftType == NULL)
{ {
BfAutoParentNodeEntry autoParentNodeEntry(this, qualifiedTypeRef); BfAutoParentNodeEntry autoParentNodeEntry(this, qualifiedTypeRef);
leftType = ResolveTypeRef(qualifiedTypeRef->mLeft, BfPopulateType_Declaration, BfResolveTypeRefFlag_IgnoreLookupError); // We throw an error below if we can't find the type leftType = ResolveTypeRef(qualifiedTypeRef->mLeft, BfPopulateType_Identity, (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_IgnoreLookupError)); // We throw an error below if we can't find the type
} }
if (leftType == NULL) if (leftType == NULL)
@ -7582,6 +7606,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
} }
BfResolvedTypeSet::LookupContext lookupCtx; BfResolvedTypeSet::LookupContext lookupCtx;
lookupCtx.mResolveFlags = (BfResolveTypeRefFlags)(resolveFlags & BfResolveTypeRefFlag_NoCreate);
lookupCtx.mRootTypeRef = typeRef; lookupCtx.mRootTypeRef = typeRef;
lookupCtx.mRootTypeDef = typeDef; lookupCtx.mRootTypeDef = typeDef;
lookupCtx.mModule = this; lookupCtx.mModule = this;
@ -7599,6 +7624,12 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
return ResolveTypeResult(typeRef, resolvedEntry->mValue, populateType, resolveFlags); return ResolveTypeResult(typeRef, resolvedEntry->mValue, populateType, resolveFlags);
} }
if ((resolveFlags & BfResolveTypeRefFlag_NoCreate) != 0)
{
mContext->mResolvedTypes.RemoveEntry(resolvedEntry);
return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags);
}
BfModule* populateModule = this; BfModule* populateModule = this;
if ((resolveFlags & BfResolveTypeRefFlag_NoReify) != 0) if ((resolveFlags & BfResolveTypeRefFlag_NoReify) != 0)
populateModule = mContext->mUnreifiedModule; populateModule = mContext->mUnreifiedModule;
@ -9724,7 +9755,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
} }
// Check type generic constraints // Check type generic constraints
if ((mCurTypeInstance->IsGenericTypeInstance()) && (mCurTypeInstance->IsUnspecializedType())) if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsGenericTypeInstance()) && (mCurTypeInstance->IsUnspecializedType()))
{ {
auto genericTypeInst = (BfGenericTypeInstance*)mCurTypeInstance; auto genericTypeInst = (BfGenericTypeInstance*)mCurTypeInstance;
for (int genericParamIdx = 0; genericParamIdx < genericTypeInst->mGenericParams.size(); genericParamIdx++) for (int genericParamIdx = 0; genericParamIdx < genericTypeInst->mGenericParams.size(); genericParamIdx++)

View file

@ -2335,7 +2335,7 @@ int BfResolvedTypeSet::DirectHash(BfTypeReference* typeRef, LookupContext* ctx,
{ {
bool isHeadType = typeRef == ctx->mRootTypeRef; bool isHeadType = typeRef == ctx->mRootTypeRef;
BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None; BfResolveTypeRefFlags resolveFlags = ctx->mResolveFlags;
if ((flags & BfHashFlag_AllowGenericParamConstValue) != 0) if ((flags & BfHashFlag_AllowGenericParamConstValue) != 0)
resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_AllowGenericParamConstValue); resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_AllowGenericParamConstValue);
@ -2410,7 +2410,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
BfTypeVector genericArgs; BfTypeVector genericArgs;
for (auto genericArgTypeRef : genericInstTypeRef->mGenericArguments) for (auto genericArgTypeRef : genericInstTypeRef->mGenericArguments)
{ {
auto argType = ctx->mModule->ResolveTypeRef(genericArgTypeRef, BfPopulateType_Identity); auto argType = ctx->mModule->ResolveTypeRef(genericArgTypeRef, BfPopulateType_Identity, ctx->mResolveFlags);
if (argType != NULL) if (argType != NULL)
genericArgs.Add(argType); genericArgs.Add(argType);
else else
@ -2602,7 +2602,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
} }
else else
{ {
ctx->mModule->ResolveTypeRef(typeRef); // To throw an error... ctx->mModule->ResolveTypeRef(typeRef, BfPopulateType_Identity, ctx->mResolveFlags); // To throw an error...
ctx->mFailed = true; ctx->mFailed = true;
return 0; return 0;
//return Hash(refType->mElementType, ctx); //return Hash(refType->mElementType, ctx);
@ -2635,7 +2635,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
} }
return Hash(rightType, ctx);*/ return Hash(rightType, ctx);*/
auto resolvedType = ctx->mModule->ResolveTypeRef(typeRef, BfPopulateType_Identity); auto resolvedType = ctx->mModule->ResolveTypeRef(typeRef, BfPopulateType_Identity, ctx->mResolveFlags);
if (resolvedType == NULL) if (resolvedType == NULL)
{ {
ctx->mFailed = true; ctx->mFailed = true;
@ -2663,7 +2663,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
// Only use the HAS_RETTYPE for root-level rettype insertions // Only use the HAS_RETTYPE for root-level rettype insertions
if (ctx->mRootTypeRef != retTypeTypeRef) if (ctx->mRootTypeRef != retTypeTypeRef)
{ {
auto type = ctx->mModule->ResolveTypeRef(retTypeTypeRef); auto type = ctx->mModule->ResolveTypeRef(retTypeTypeRef, BfPopulateType_Identity, ctx->mResolveFlags);
return Hash(type, ctx, flags); return Hash(type, ctx, flags);
} }
@ -2750,7 +2750,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
} }
else if (auto dotTypeRef = BfNodeDynCastExact<BfDotTypeReference>(typeRef)) else if (auto dotTypeRef = BfNodeDynCastExact<BfDotTypeReference>(typeRef))
{ {
ctx->mModule->ResolveTypeRef(dotTypeRef); ctx->mModule->ResolveTypeRef(dotTypeRef, BfPopulateType_Identity, ctx->mResolveFlags);
ctx->mFailed = true; ctx->mFailed = true;
return 0; return 0;
} }
@ -3016,7 +3016,7 @@ bool BfResolvedTypeSet::GenericTypeEquals(BfGenericTypeInstance* lhsGenericType,
if (lhsGenericType->mTypeDef != ctx->mModule->mContext->mCompiler->mNullableTypeDef) if (lhsGenericType->mTypeDef != ctx->mModule->mContext->mCompiler->mNullableTypeDef)
return false; return false;
auto rhsElemType = ctx->mModule->ResolveTypeRef(rhsNullableTypeRef->mElementType, BfPopulateType_Identity); auto rhsElemType = ctx->mModule->ResolveTypeRef(rhsNullableTypeRef->mElementType, BfPopulateType_Identity, ctx->mResolveFlags);
return lhsGenericType->mTypeGenericArguments[0] == rhsElemType; return lhsGenericType->mTypeGenericArguments[0] == rhsElemType;
} }
} }
@ -3046,7 +3046,7 @@ bool BfResolvedTypeSet::GenericTypeEquals(BfGenericTypeInstance* lhsGenericType,
if (auto rhsQualifiedTypeRef = BfNodeDynCastExact<BfQualifiedTypeReference>(rhs)) if (auto rhsQualifiedTypeRef = BfNodeDynCastExact<BfQualifiedTypeReference>(rhs))
{ {
auto rhsRightType = ctx->mModule->ResolveTypeRef(rhs, BfPopulateType_Identity); auto rhsRightType = ctx->mModule->ResolveTypeRef(rhs, BfPopulateType_Identity, ctx->mResolveFlags);
return rhsRightType == lhsGenericType; return rhsRightType == lhsGenericType;
} }

View file

@ -16,6 +16,23 @@ class BfTypeInstance;
class BfContext; class BfContext;
class BfCustomAttributes; class BfCustomAttributes;
enum BfResolveTypeRefFlags
{
BfResolveTypeRefFlag_None = 0,
BfResolveTypeRefFlag_NoResolveGenericParam = 1,
BfResolveTypeRefFlag_AllowRef = 2,
BfResolveTypeRefFlag_AllowRefGeneric = 4,
BfResolveTypeRefFlag_IgnoreLookupError = 8,
BfResolveTypeRefFlag_AllowGenericTypeParamConstValue = 0x10,
BfResolveTypeRefFlag_AllowGenericMethodParamConstValue = 0x20,
BfResolveTypeRefFlag_AllowGenericParamConstValue = 0x10 | 0x20,
BfResolveTypeRefFlag_AutoComplete = 0x40,
BfResolveTypeRefFlag_FromIndirectSource = 0x80, // Such as a type alias or a generic parameter
BfResolveTypeRefFlag_Attribute = 0x100,
BfResolveTypeRefFlag_NoReify = 0x200,
BfResolveTypeRefFlag_NoCreate = 0x400
};
enum BfTypeNameFlags : uint16 enum BfTypeNameFlags : uint16
{ {
BfTypeNameFlags_None = 0, BfTypeNameFlags_None = 0,
@ -2348,16 +2365,18 @@ public:
BfTypeReference* mRootTypeRef; BfTypeReference* mRootTypeRef;
BfTypeDef* mRootTypeDef; BfTypeDef* mRootTypeDef;
BfType* mResolvedType; BfType* mResolvedType;
BfResolveTypeRefFlags mResolveFlags;
bool mFailed; bool mFailed;
public: public:
LookupContext() LookupContext()
{ {
mRootTypeRef = NULL; mRootTypeRef = NULL;
mRootTypeDef = NULL; mRootTypeDef = NULL;
mModule = NULL; mModule = NULL;
mResolvedType = NULL; mResolvedType = NULL;
mFailed = false; mFailed = false;
mResolveFlags = BfResolveTypeRefFlag_None;
} }
BfType* ResolveTypeRef(BfTypeReference* typeReference); BfType* ResolveTypeRef(BfTypeReference* typeReference);