diff --git a/BeefLibs/corlib/src/GC.bf b/BeefLibs/corlib/src/GC.bf index dc32f4e2..231642a3 100644 --- a/BeefLibs/corlib/src/GC.bf +++ b/BeefLibs/corlib/src/GC.bf @@ -173,6 +173,10 @@ namespace System // or the memory would already be registered with the GC } + public static mixin Mark(T val) + { + } + public static mixin Mark(TSizedArray val) where Size : const int where TSizedArray : SizedArray { #if BF_ENABLE_REALTIME_LEAK_CHECK diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 81cd3ef3..5e30a337 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -2844,6 +2844,102 @@ bool BfModule::IsSkippingExtraResolveChecks() return mCompiler->IsSkippingExtraResolveChecks(); } +bool BfModule::AddErrorContext(StringImpl& errorString, BfAstNode* refNode, bool& isWhileSpecializing) +{ + bool isWhileSpecializingMethod = false; + if ((mIsSpecialModule) && (mModuleName == "vdata")) + errorString += StrFormat("\n while generating vdata for project '%s'", mProject->mName.c_str()); + if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend)) + errorString += StrFormat("\n while generating append size calculating method"); + else if (refNode == NULL) + { + if (mCurTypeInstance != NULL) + errorString += StrFormat("\n while compiling '%s'", TypeToString(mCurTypeInstance, BfTypeNameFlags_None).c_str()); + else if (mProject != NULL) + errorString += StrFormat("\n while compiling project '%s'", mProject->mName.c_str()); + } + + if (mCurTypeInstance != NULL) + { + auto _CheckMethodInstance = [&](BfMethodInstance* methodInstance) + { + // Propogate the fail all the way to the main method (assuming we're in a local method or lambda) + methodInstance->mHasFailed = true; + + bool isSpecializedMethod = ((methodInstance != NULL) && (!methodInstance->mIsUnspecialized) && (methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mMethodGenericArguments.size() != 0)); + if (isSpecializedMethod) + { + //auto unspecializedMethod = &mCurMethodInstance->mMethodInstanceGroup->mMethodSpecializationMap.begin()->second; + auto unspecializedMethod = methodInstance->mMethodInstanceGroup->mDefault; + if (unspecializedMethod == methodInstance) + { + // This is a local method inside a generic method + BF_ASSERT(methodInstance->mMethodDef->mIsLocalMethod); + } + else + { + if (unspecializedMethod->mHasFailed) + return false; // At least SOME error has already been reported + } + } + + if (isSpecializedMethod) + { + errorString += StrFormat("\n while specializing method '%s'", MethodToString(methodInstance).c_str()); + isWhileSpecializing = true; + isWhileSpecializingMethod = true; + } + else if ((methodInstance != NULL) && (methodInstance->mIsForeignMethodDef)) + { + errorString += StrFormat("\n while implementing default interface method '%s'", MethodToString(methodInstance).c_str()); + isWhileSpecializing = true; + isWhileSpecializingMethod = true; + } + else if ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType())) + { + errorString += StrFormat("\n while specializing type '%s'", TypeToString(mCurTypeInstance).c_str()); + isWhileSpecializing = true; + } + + return true; + }; + + bool hadMethodInstance = false; + if (mCurMethodState != NULL) + { + auto checkMethodState = mCurMethodState; + while (checkMethodState != NULL) + { + auto methodInstance = checkMethodState->mMethodInstance; + if (methodInstance == NULL) + { + checkMethodState = checkMethodState->mPrevMethodState; + continue; + } + + hadMethodInstance = true; + if (!_CheckMethodInstance(methodInstance)) + return false; + checkMethodState = checkMethodState->mPrevMethodState; + } + } + + if ((!hadMethodInstance) && (mCurMethodInstance != NULL)) + { + if (!_CheckMethodInstance(mCurMethodInstance)) + return false; + } + } + + if ((!isWhileSpecializing) && (mCurTypeInstance != NULL) && ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType()))) + { + errorString += StrFormat("\n while specializing type '%s'", TypeToString(mCurTypeInstance).c_str()); + isWhileSpecializing = true; + } + + return true; +} + BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPersistent, bool deferError) { BP_ZONE("BfModule::Fail"); @@ -2899,105 +2995,15 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers BfLogSysM("BfModule::Fail module %p type %p %s\n", this, mCurTypeInstance, error.c_str()); - String errorString = error; - bool isWhileSpecializing = false; - bool isWhileSpecializingMethod = false; - - if ((mIsSpecialModule) && (mModuleName == "vdata")) - errorString += StrFormat("\n while generating vdata for project '%s'", mProject->mName.c_str()); - if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend)) - errorString += StrFormat("\n while generating append size calculating method"); - else if (refNode == NULL) - { - if (mCurTypeInstance != NULL) - errorString += StrFormat("\n while compiling '%s'", TypeToString(mCurTypeInstance, BfTypeNameFlags_None).c_str()); - else if (mProject != NULL) - errorString += StrFormat("\n while compiling project '%s'", mProject->mName.c_str()); - } - - if (mCurTypeInstance != NULL) - { - auto _CheckMethodInstance = [&](BfMethodInstance* methodInstance) - { - // Propogate the fail all the way to the main method (assuming we're in a local method or lambda) - methodInstance->mHasFailed = true; - - bool isSpecializedMethod = ((methodInstance != NULL) && (!methodInstance->mIsUnspecialized) && (methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mMethodGenericArguments.size() != 0)); - if (isSpecializedMethod) - { - //auto unspecializedMethod = &mCurMethodInstance->mMethodInstanceGroup->mMethodSpecializationMap.begin()->second; - auto unspecializedMethod = methodInstance->mMethodInstanceGroup->mDefault; - if (unspecializedMethod == methodInstance) - { - // This is a local method inside a generic method - BF_ASSERT(methodInstance->mMethodDef->mIsLocalMethod); - } - else - { - if (unspecializedMethod->mHasFailed) - return false; // At least SOME error has already been reported - } - } - - if (isSpecializedMethod) - { - errorString += StrFormat("\n while specializing method '%s'", MethodToString(methodInstance).c_str()); - isWhileSpecializing = true; - isWhileSpecializingMethod = true; - } - else if ((methodInstance != NULL) && (methodInstance->mIsForeignMethodDef)) - { - errorString += StrFormat("\n while implementing default interface method '%s'", MethodToString(methodInstance).c_str()); - isWhileSpecializing = true; - isWhileSpecializingMethod = true; - } - else if ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType())) - { - errorString += StrFormat("\n while specializing type '%s'", TypeToString(mCurTypeInstance).c_str()); - isWhileSpecializing = true; - } - - return true; - }; - - bool hadMethodInstance = false; - if (mCurMethodState != NULL) - { - auto checkMethodState = mCurMethodState; - while (checkMethodState != NULL) - { - auto methodInstance = checkMethodState->mMethodInstance; - if (methodInstance == NULL) - { - checkMethodState = checkMethodState->mPrevMethodState; - continue; - } - - hadMethodInstance = true; - if (!_CheckMethodInstance(methodInstance)) - return NULL; - checkMethodState = checkMethodState->mPrevMethodState; - } - } - - if ((!hadMethodInstance) && (mCurMethodInstance != NULL)) - { - if (!_CheckMethodInstance(mCurMethodInstance)) - return NULL; - } - } - + String errorString = error; + bool isWhileSpecializing = false; + if (!AddErrorContext(errorString, refNode, isWhileSpecializing)) + return false; + BfError* bfError = NULL; - if (isWhileSpecializing) deferError = true; - if ((!isWhileSpecializing) && (mCurTypeInstance != NULL) && ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType()))) - { - errorString += StrFormat("\n while specializing type '%s'", TypeToString(mCurTypeInstance).c_str()); - isWhileSpecializing = true; - } - if (!mHadBuildError) mHadBuildError = true; @@ -3085,7 +3091,7 @@ BfError* BfModule::FailAfter(const StringImpl& error, BfAstNode* refNode) return bfError; } -BfError* BfModule::Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode, bool isPersistent) +BfError* BfModule::Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode, bool isPersistent, bool showInSpecialized) { if (mIgnoreErrors || mIgnoreWarnings) return NULL; @@ -3113,21 +3119,33 @@ BfError* BfModule::Warn(int warningNum, const StringImpl& warning, BfAstNode* re { return NULL; } - + // Right now we're only warning on the unspecialized declarations, we may revisit this if (mCurMethodInstance != NULL) { if (mCurMethodInstance->IsSpecializedGenericMethodOrType()) - return NULL; + { + if (!showInSpecialized) + return NULL; + } if (mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend) return NULL; // No ctorCalcAppend warnings } if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsSpecializedType())) - return NULL; + { + if (!showInSpecialized) + return NULL; + } if (refNode != NULL) refNode = BfNodeToNonTemporary(refNode); + String warningString = warning; + bool isWhileSpecializing = false; + if (!AddErrorContext(warningString, refNode, isWhileSpecializing)) + return false; + bool deferWarning = isWhileSpecializing; + if ((mCurMethodState != NULL) && (mCurMethodState->mMixinState != NULL)) { // We used to bubble up warnings into the mixin injection site, BUT @@ -3139,17 +3157,18 @@ BfError* BfModule::Warn(int warningNum, const StringImpl& warning, BfAstNode* re { BfError* bfError = mCompiler->mPassInstance->Warn(warningNum, "Emitted code had errors", mCurMethodState->mEmitRefNode); if (bfError != NULL) - mCompiler->mPassInstance->MoreInfo(warning, refNode); + mCompiler->mPassInstance->MoreInfo(warningString, refNode); return bfError; } BfError* bfError; if (refNode != NULL) - bfError = mCompiler->mPassInstance->WarnAt(warningNum, warning, refNode->GetSourceData(), refNode->GetSrcStart(), refNode->GetSrcLength()); + bfError = mCompiler->mPassInstance->WarnAt(warningNum, warningString, refNode->GetSourceData(), refNode->GetSrcStart(), refNode->GetSrcLength()); else - bfError = mCompiler->mPassInstance->Warn(warningNum, warning); + bfError = mCompiler->mPassInstance->Warn(warningNum, warningString); if (bfError != NULL) { + bfError->mIsWhileSpecializing = isWhileSpecializing; bfError->mProject = mProject; AddFailType(mCurTypeInstance); @@ -3229,7 +3248,7 @@ void BfModule::CheckErrorAttributes(BfTypeInstance* typeInstance, BfMethodInstan if (isError) error = Fail(err, targetSrc); else - error = Warn(0, err, targetSrc); + error = Warn(0, err, targetSrc, false, true); if (error != NULL) _AddDeclarationMoreInfo(); } @@ -3262,7 +3281,7 @@ void BfModule::CheckErrorAttributes(BfTypeInstance* typeInstance, BfMethodInstan if (str != NULL) err += *str; err += "'"; - if (Warn(0, err, targetSrc) != NULL) + if (Warn(0, err, targetSrc, false, true) != NULL) _AddDeclarationMoreInfo(); } } @@ -7590,7 +7609,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS if (origCheckArgType->IsRef()) origCheckArgType = origCheckArgType->GetUnderlyingType(); - bool argMayBeReferenceType = false; + bool argIsReferenceType = false; int checkGenericParamFlags = 0; if (checkArgType->IsGenericParam()) @@ -7600,18 +7619,18 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS if (checkGenericParamInst->mTypeConstraint != NULL) checkArgType = checkGenericParamInst->mTypeConstraint; - if ((checkGenericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr)) != 0) - { - argMayBeReferenceType = false; - } - else - { - argMayBeReferenceType = true; - } +// if ((checkGenericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr)) != 0) +// { +// argMayBeReferenceType = false; +// } +// else +// { +// argMayBeReferenceType = true; +// } } if (checkArgType->IsObjectOrInterface()) - argMayBeReferenceType = true; + argIsReferenceType = true; BfTypeInstance* typeConstraintInst = NULL; if (genericParamInst->mTypeConstraint != NULL) @@ -7636,7 +7655,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS } if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Class) && - ((checkGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_Var)) == 0) && (!argMayBeReferenceType)) + ((checkGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_Var)) == 0) && (!argIsReferenceType)) { if ((!ignoreErrors) && (PreFail())) *errorOut = Fail(StrFormat("The type '%s' must be a reference type in order to use it as parameter '%s' for '%s'", diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 61478905..62a2133d 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1517,10 +1517,11 @@ public: void SetFail(); void VerifyOnDemandMethods(); bool IsSkippingExtraResolveChecks(); + bool AddErrorContext(StringImpl& errorString, BfAstNode* refNode, bool& isWhileSpecializing); BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false, bool deferError = false); BfError* FailInternal(const StringImpl& error, BfAstNode* refNode = NULL); BfError* FailAfter(const StringImpl& error, BfAstNode* refNode); - BfError* Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode = NULL, bool isPersistent = false); + BfError* Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode = NULL, bool isPersistent = false, bool showInSpecialized = false); void CheckErrorAttributes(BfTypeInstance* typeInstance, BfMethodInstance* methodInstance, BfCustomAttributes* customAttributes, BfAstNode* targetSrc); void CheckRangeError(BfType* type, BfAstNode* refNode); bool CheckCircularDataError(); diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index f1c9e149..bebb2f17 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -1589,7 +1589,7 @@ void BfPassInstance::SilentFail() mFailedIdx++; } -BfError* BfPassInstance::WarnAt(int warningNumber, const StringImpl& warning, BfSourceData* bfSource, int srcIdx, int srcLen) +BfError* BfPassInstance::WarnAt(int warningNumber, const StringImpl& warning, BfSourceData* bfSource, int srcIdx, int srcLen, bool isDeferred) { mLastWasAdded = false; if ((int) mErrors.size() >= sMaxErrors) @@ -1599,7 +1599,7 @@ BfError* BfPassInstance::WarnAt(int warningNumber, const StringImpl& warning, Bf if ((bfParser != NULL) && (warningNumber > 0) && (!bfParser->IsWarningEnabledAtSrcIndex(warningNumber, srcIdx))) return NULL; - if (!WantsRangeRecorded(bfParser, srcIdx, srcLen, true)) + if (!WantsRangeRecorded(bfParser, srcIdx, srcLen, true, isDeferred)) return NULL; mWarnIdx++; @@ -1614,21 +1614,25 @@ BfError* BfPassInstance::WarnAt(int warningNumber, const StringImpl& warning, Bf errorVal->mError = warning; errorVal->mSrcStart = srcIdx; errorVal->mSrcEnd = srcIdx + srcLen; + errorVal->mIsDeferred = isDeferred; FixSrcStartAndEnd(bfSource, errorVal->mSrcStart, errorVal->mSrcEnd); mErrorSet.Add(BfErrorEntry(errorVal)); mErrors.push_back(errorVal); ++mWarningCount; mLastWasAdded = true; - mLastWasDisplayed = WantsRangeDisplayed(bfParser, srcIdx, srcLen, true); - if (mLastWasDisplayed) + if (!isDeferred) { - String errorStart = "WARNING"; - if ((int)mErrors.size() > 1) - errorStart += StrFormat("(%d)", mErrors.size()); - if (warningNumber > 0) - errorStart += StrFormat(": BF%04d", warningNumber); - MessageAt(":warn", errorStart + ": " + warning, bfParser, srcIdx); + mLastWasDisplayed = WantsRangeDisplayed(bfParser, srcIdx, srcLen, true); + if (mLastWasDisplayed) + { + String errorStart = "WARNING"; + if ((int)mErrors.size() > 1) + errorStart += StrFormat("(%d)", mErrors.size()); + if (warningNumber > 0) + errorStart += StrFormat(": BF%04d", warningNumber); + MessageAt(":warn", errorStart + ": " + warning, bfParser, srcIdx); + } } return errorVal; } @@ -1645,7 +1649,7 @@ BfError* BfPassInstance::Warn(int warningNumber, const StringImpl& warning) return NULL; } -BfError* BfPassInstance::Warn(int warningNumber, const StringImpl& warning, BfAstNode* refNode) +BfError* BfPassInstance::Warn(int warningNumber, const StringImpl& warning, BfAstNode* refNode, bool isDeferred) { BP_ZONE("BfPassInstance::Warn"); @@ -1666,7 +1670,7 @@ BfError* BfPassInstance::Warn(int warningNumber, const StringImpl& warning, BfAs } if (refNode != NULL) - return WarnAt(warningNumber, warning, refNode->GetSourceData(), refNode->GetSrcStart(), refNode->GetSrcLength()); + return WarnAt(warningNumber, warning, refNode->GetSourceData(), refNode->GetSrcStart(), refNode->GetSrcLength(), isDeferred); else return Warn(warningNumber, warning); } @@ -1798,15 +1802,39 @@ void BfPassInstance::TryFlushDeferredError() // This can happen in the case of an internal compiler error, where we believe we've satisfied // generic constraints but we generate an error on the specialization but not the unspecialized version bool hasDisplayedError = false; - for (int pass = 0; pass < 2; pass++) + bool hasDisplayedWarning = false; + for (int pass = 0; pass < 2; pass++) { for (auto& error : mErrors) { - if (!error->mIsWarning) + if (error->mIsWarning) + { + if (!error->mIsDeferred) + hasDisplayedWarning = true; + else if ((pass == 1) && (!hasDisplayedWarning)) + { + String errorText = "WARNING "; + if (error->mWarningNumber > 0) + errorText += StrFormat(": BF%04d", error->mWarningNumber); + errorText += ": "; + errorText += error->mError; + + MessageAt(":warning", errorText, error->mSource, error->mSrcStart, error->mSrcEnd - error->mSrcStart); + + for (auto moreInfo : error->mMoreInfo) + { + if (moreInfo->mSource != NULL) + MessageAt(":warning", " > " + moreInfo->mInfo, moreInfo->mSource, moreInfo->mSrcStart, moreInfo->mSrcEnd - moreInfo->mSrcStart); + else + OutputLine(":warning " + moreInfo->mInfo); + } + } + } + else { if (!error->mIsDeferred) hasDisplayedError = true; - else if (pass == 1) + else if ((pass == 1) && (!hasDisplayedError)) { MessageAt(":error", "ERROR: " + error->mError, error->mSource, error->mSrcStart, error->mSrcEnd - error->mSrcStart); @@ -1819,10 +1847,7 @@ void BfPassInstance::TryFlushDeferredError() } } } - } - - if ((pass == 0) && (hasDisplayedError)) - break; + } } } diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index 7b6f88e5..88be0fe5 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -1383,11 +1383,12 @@ public: void MessageAt(const StringImpl& msgPrefix, const StringImpl& error, BfSourceData* bfSource, int srcIdx, int srcLen = 1, BfFailFlags flags = BfFailFlag_None); void FixSrcStartAndEnd(BfSourceData* source, int& startIdx, int& endIdx); - BfError* WarnAt(int warningNumber, const StringImpl& warning, BfSourceData* bfSource, int srcIdx, int srcLen = 1); + BfError* WarnAt(int warningNumber, const StringImpl& warning, BfSourceData* bfSource, int srcIdx, int srcLen = 1, bool isDeferred = false); BfError* Warn(int warningNumber, const StringImpl& warning); - BfError* Warn(int warningNumber, const StringImpl& warning, BfAstNode* refNode); + BfError* Warn(int warningNumber, const StringImpl& warning, BfAstNode* refNode, bool isDeferred = false); + BfError* DeferWarn(int warningNumber, const StringImpl& warning, BfAstNode* refNode); BfError* WarnAfter(int warningNumber, const StringImpl& warning, BfAstNode* refNode); - BfError* WarnAfterAt(int warningNumber, const StringImpl& error, BfSourceData* bfSource, int srcIdx); + BfError* WarnAfterAt(int warningNumber, const StringImpl& error, BfSourceData* bfSource, int srcIdx); BfMoreInfo* MoreInfoAt(const StringImpl& info, BfSourceData* bfSource, int srcIdx, int srcLen, BfFailFlags flags = BfFailFlag_None); BfMoreInfo* MoreInfo(const StringImpl& info, bool forceQueue = false);