diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index e6cd1f49..7d74e192 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -2912,6 +2912,9 @@ BfType* BfExprEvaluator::BindGenericType(BfAstNode* node, BfType* bindType) if (!bindType->IsGenericParam()) return bindType; + if (genericTypeBindings == NULL) + return bindType; + (*genericTypeBindings)[nodeId] = bindType; return bindType; } @@ -5338,6 +5341,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* // This either generated an error already or this is just the non-const type check pass for a comptime-only method doConstReturn = true; } + else if ((mBfEvalExprFlags & BfEvalExprFlags_DisallowComptime) != 0) + { + doConstReturn = true; + } else { CeEvalFlags evalFlags = CeEvalFlags_None; diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 11dce7cd..4585bfb0 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -2890,6 +2890,7 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers return true; }; + bool hadMethodInstance = false; if (mCurMethodState != NULL) { auto checkMethodState = mCurMethodState; @@ -2902,12 +2903,14 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers continue; } + hadMethodInstance = true; if (!_CheckMethodInstance(methodInstance)) return NULL; checkMethodState = checkMethodState->mPrevMethodState; } } - else if (mCurMethodInstance != NULL) + + if ((!hadMethodInstance) && (mCurMethodInstance != NULL)) { if (!_CheckMethodInstance(mCurMethodInstance)) return NULL; @@ -7225,7 +7228,11 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar bfAutocomplete->CheckTypeRef(constraintTypeRef, true); //TODO: Constraints may refer to other generic params (of either type or method) // TO allow resolution, perhaps move this generic param initalization into GetMethodInstance (passing a genericPass bool) - auto constraintType = ResolveTypeRef(constraintTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowGenericMethodParamConstValue); + + BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_AllowGenericMethodParamConstValue; + if (isUnspecialized) + resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_DisallowComptime); + auto constraintType = ResolveTypeRef(constraintTypeRef, BfPopulateType_Declaration, resolveFlags); if (constraintType != NULL) { if ((constraintDef->mGenericParamFlags & BfGenericParamFlag_Const) != 0) @@ -17881,8 +17888,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } SetAndRestoreValue prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mWantsIRIgnoreWrites || methodInstance->mIsUnspecialized); - bool ignoreWrites = mBfIRBuilder->mIgnoreWrites; - + if ((HasCompiledOutput()) && (!mBfIRBuilder->mIgnoreWrites)) { BF_ASSERT(!methodInstance->mIRFunction.IsFake() || (methodInstance->GetImportCallKind() != BfImportCallKind_None)); @@ -17953,6 +17959,9 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) auto methodDef = methodInstance->mMethodDef; auto methodDeclaration = methodDef->GetMethodDeclaration(); + if ((methodDef->mHasComptime) && (!mIsComptimeModule)) + mBfIRBuilder->mIgnoreWrites = true; + if ((methodInstance->mIsReified) && (methodInstance->mVirtualTableIdx != -1)) { // If we reify a virtual method in a HotCompile then we need to make sure the type data gets written out @@ -18320,7 +18329,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } } - bool wantsDIData = (mBfIRBuilder->DbgHasInfo()) && (!methodDef->IsEmptyPartial()) && (!mCurMethodInstance->mIsUnspecialized) && (mHasFullDebugInfo); + bool wantsDIData = (mBfIRBuilder->DbgHasInfo()) && (!methodDef->IsEmptyPartial()) && (!mBfIRBuilder->mIgnoreWrites) && (mHasFullDebugInfo); if (methodDef->mMethodType == BfMethodType_Mixin) wantsDIData = false; @@ -19709,7 +19718,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) mBfIRBuilder->MoveBlockToEnd(mCurMethodState->mIRExitBlock); mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRExitBlock); - if (!mCurMethodState->mDIRetVal) + if ((!mCurMethodState->mDIRetVal) && (wantsDIData)) CreateDIRetVal(); } @@ -19807,8 +19816,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } // Avoid linking any internal funcs that were just supposed to be comptime-accessible - if ((methodDef->mHasComptime) && (!mIsComptimeModule)) - wantsRemoveBody = true; + /*if ((methodDef->mHasComptime) && (!mIsComptimeModule)) + wantsRemoveBody = true;*/ if ((hasExternSpecifier) && (!skipBody)) { diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index e9f01017..96e46852 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -73,9 +73,10 @@ enum BfEvalExprFlags BfEvalExprFlags_StringInterpolateFormat = 0x20000, BfEvalExprFlags_NoLookupError = 0x40000, BfEvalExprFlags_Comptime = 0x80000, - BfEvalExprFlags_InCascade = 0x100000, - BfEvalExprFlags_InferReturnType = 0x200000, - BfEvalExprFlags_WasMethodRef = 0x400000 + BfEvalExprFlags_DisallowComptime = 0x100000, + BfEvalExprFlags_InCascade = 0x200000, + BfEvalExprFlags_InferReturnType = 0x400000, + BfEvalExprFlags_WasMethodRef = 0x800000 }; enum BfCastFlags diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 67bac363..473ec2d0 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -9350,7 +9350,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula } BfResolvedTypeSet::LookupContext lookupCtx; - lookupCtx.mResolveFlags = (BfResolveTypeRefFlags)(resolveFlags & (BfResolveTypeRefFlag_NoCreate | BfResolveTypeRefFlag_IgnoreLookupError)); + lookupCtx.mResolveFlags = (BfResolveTypeRefFlags)(resolveFlags & (BfResolveTypeRefFlag_NoCreate | BfResolveTypeRefFlag_IgnoreLookupError | BfResolveTypeRefFlag_DisallowComptime)); lookupCtx.mRootTypeRef = typeRef; lookupCtx.mRootTypeDef = typeDef; lookupCtx.mModule = this; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 81ad6511..ec969725 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -3427,10 +3427,21 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash SetAndRestoreValue ignoreWrites(ctx->mModule->mBfIRBuilder->mIgnoreWrites, true); SetAndRestoreValue allowUninitReads(ctx->mModule->mCurMethodState->mAllowUinitReads, true); + BfEvalExprFlags exprFlags = BfEvalExprFlags_None; + if ((ctx->mResolveFlags & BfResolveTypeRefFlag_DisallowComptime) != 0) + { + exprFlags = (BfEvalExprFlags)(exprFlags | BfEvalExprFlags_DisallowComptime); + } + if (exprModTypeRef->mToken->mToken == BfToken_Comptype) - result = ctx->mModule->CreateValueFromExpression(exprModTypeRef->mTarget, ctx->mModule->ResolveTypeDef(ctx->mModule->mCompiler->mTypeTypeDef), BfEvalExprFlags_Comptime); + { + exprFlags = (BfEvalExprFlags)(exprFlags | BfEvalExprFlags_Comptime); + result = ctx->mModule->CreateValueFromExpression(exprModTypeRef->mTarget, ctx->mModule->ResolveTypeDef(ctx->mModule->mCompiler->mTypeTypeDef), exprFlags); + } else + { result = ctx->mModule->CreateValueFromExpression(exprModTypeRef->mTarget); + } } if ((result) && (exprModTypeRef->mToken->mToken == BfToken_Comptype)) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index fb18a6c6..929acfc9 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -31,7 +31,8 @@ enum BfResolveTypeRefFlags BfResolveTypeRefFlag_Attribute = 0x100, BfResolveTypeRefFlag_NoReify = 0x200, BfResolveTypeRefFlag_NoCreate = 0x400, - BfResolveTypeRefFlag_NoWarnOnMut = 0x800 + BfResolveTypeRefFlag_NoWarnOnMut = 0x800, + BfResolveTypeRefFlag_DisallowComptime = 0x1000 }; enum BfTypeNameFlags : uint16 diff --git a/IDEHelper/Tests/src/Comptime.bf b/IDEHelper/Tests/src/Comptime.bf index 49c93b6d..d6a290ac 100644 --- a/IDEHelper/Tests/src/Comptime.bf +++ b/IDEHelper/Tests/src/Comptime.bf @@ -74,38 +74,21 @@ namespace Tests } - struct DoublingEnumerator : IEnumerator - where TElem : operator TElem + TElem - where TEnum : concrete, IEnumerator + static Type GetBiggerType(Type t) { - TEnum mEnum; - - public this(TEnum e) + switch (t) { - mEnum = e; - } - - public Result GetNext() mut - { - switch (mEnum.GetNext()) - { - case .Ok(let val): return .Ok(val + val); - case .Err: return .Err; - } + case typeof(int8): return typeof(int16); + case typeof(int16): return typeof(int32); + case typeof(int32): return typeof(int64); + case typeof(float): return typeof(double); } + return null; } - static Type GetConcreteEnumerator() where TCollection : IEnumerable + static TTo GetBigger(TFrom val) where TTo : comptype(GetBiggerType(typeof(TFrom))), operator explicit TFrom { - TCollection col = ?; - return col.GetEnumerator().GetType(); - } - - public static DoublingEnumerator())> GetDoublingEnumerator(this TCollection it) - where TCollection: concrete, IEnumerable - where TElem : operator TElem + TElem - { - return .(it.GetEnumerator()); + return (.)val; } [Test] @@ -124,13 +107,8 @@ namespace Tests MethodA(34, 45); Debug.Assert(LogAttribute.gLog == "Called Tests.Comptime.MethodA(int a, int b) 34 45"); - List fList = scope .() { 1, 2, 3 }; - var e = fList.GetDoublingEnumerator(); - Test.Assert(e.GetNext().Value == 2); - Test.Assert(e.GetNext().Value == 4); - Test.Assert(e.GetNext().Value == 6); - - //Test.Assert(fList.DoubleVals() == 12); + var v0 = GetBigger((int8)123); + Test.Assert(v0.GetType() == typeof(int16)); } } } diff --git a/IDEHelper/Tests/src/Generics.bf b/IDEHelper/Tests/src/Generics.bf index 731764df..6a3ad18d 100644 --- a/IDEHelper/Tests/src/Generics.bf +++ b/IDEHelper/Tests/src/Generics.bf @@ -252,6 +252,34 @@ namespace Tests return result; } + struct DoublingEnumerator : IEnumerator + where TElem : operator TElem + TElem + where TEnum : concrete, IEnumerator + { + TEnum mEnum; + + public this(TEnum e) + { + mEnum = e; + } + + public Result GetNext() mut + { + switch (mEnum.GetNext()) + { + case .Ok(let val): return .Ok(val + val); + case .Err: return .Err; + } + } + } + + static DoublingEnumerator GetDoublingEnumerator(this TCollection it) + where TCollection: concrete, IEnumerable + where TElem : operator TElem + TElem + { + return .(it.GetEnumerator()); + } + [Test] public static void TestBasics() { @@ -306,6 +334,11 @@ namespace Tests Test.Assert(MethodF(floatList) == 0); Test.Assert(floatList.Sum((x) => x * 2) == 12); + + var e = floatList.GetDoublingEnumerator(); + Test.Assert(e.GetNext().Value == 2); + Test.Assert(e.GetNext().Value == 4); + Test.Assert(e.GetNext().Value == 6); } }