diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index ad826656..d6e3bd72 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -7986,7 +7986,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS { if (BfIRConstHolder::IsInt(primType->mTypeDef->mTypeCode)) { - if (!mCompiler->mSystem->DoesLiteralFit(primType->mTypeDef->mTypeCode, constExprValueType->mValue.mUInt64)) + if (!mCompiler->mSystem->DoesLiteralFit(primType->mTypeDef->mTypeCode, constExprValueType->mValue)) { if ((!ignoreErrors) && (PreFail())) *errorOut = Fail(StrFormat("Const generic argument '%s', declared with const '%lld', does not fit into const constraint '%s' for '%s'", genericParamInst->GetName().c_str(), @@ -17051,7 +17051,10 @@ void BfModule::EmitCtorBody(bool& skipBody) mCompiler->mResolvePassData->mSourceClassifier->SetElementType(fieldDef->mInitializer, BfSourceElementType_Normal); mCompiler->mResolvePassData->mSourceClassifier->VisitChild(fieldDef->mInitializer); - auto wantType = ResolveTypeRef(fieldDef->mTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowInferredSizedArray); + BfType* wantType = NULL; + if ((!BfNodeIsA(fieldDef->mTypeRef)) && + (!BfNodeIsA(fieldDef->mTypeRef))) + wantType = ResolveTypeRef(fieldDef->mTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowInferredSizedArray); if ((wantType != NULL) && ((wantType->IsVar()) || (wantType->IsLet()) || (wantType->IsRef()))) wantType = NULL; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 77f011e7..876ee18e 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -2770,13 +2770,26 @@ BfResolvedTypeSet::~BfResolvedTypeSet() BfVariant BfResolvedTypeSet::EvaluateToVariant(LookupContext* ctx, BfExpression* expr, BfType*& outType) { + outType = NULL; + BfConstResolver constResolver(ctx->mModule); BfVariant variant = { BfTypeCode_None }; constResolver.mAllowGenericConstValue = true; - auto result = constResolver.Resolve(expr); - outType = result.mType; - if (result) - { + constResolver.mBfEvalExprFlags = BfEvalExprFlags_NoCast; + constResolver.mExpectingType = ctx->mModule->GetPrimitiveType(BfTypeCode_Int64); + auto result = constResolver.Resolve(expr); + if (result) + { + // Limit the types of constants to prevent duplicate values with different types - we don't want to hash a typeref with an int32 + // when the constraint requirement is int64 (but we don't know that at hash time) + if ((result.mType->IsInteger()) && ((result.mType->mSize < 8) || (result.mType->GetTypeCode() == BfTypeCode_IntPtr))) + result = ctx->mModule->Cast(expr, result, ctx->mModule->GetPrimitiveType(BfTypeCode_Int64)); + else if ((result.mType->IsFloat()) && (result.mType->mSize < 8)) + result = ctx->mModule->Cast(expr, result, ctx->mModule->GetPrimitiveType(BfTypeCode_Double)); + else if ((result.mType->IsChar()) && (result.mType->mSize < 4)) + result = ctx->mModule->Cast(expr, result, ctx->mModule->GetPrimitiveType(BfTypeCode_Char32)); + outType = result.mType; + if (result.mKind == BfTypedValueKind_GenericConstValue) { return variant; @@ -2784,18 +2797,6 @@ BfVariant BfResolvedTypeSet::EvaluateToVariant(LookupContext* ctx, BfExpression* else { variant = ctx->mModule->TypedValueToVariant(expr, result, true); - - // Limit the types of constants to prevent duplicate values with different types - we don't want to hash a typeref with an int32 - // when the constraint requirement is int64 (but we don't know that at hash time) - if (BfIRConstHolder::IsChar(variant.mTypeCode)) - variant.mTypeCode = BfTypeCode_Char32; - else if (BfIRConstHolder::IsInt(variant.mTypeCode)) - variant.mTypeCode = BfTypeCode_Int64; - else if (variant.mTypeCode == BfTypeCode_Float) - { - variant.mTypeCode = BfTypeCode_Double; - variant.mDouble = variant.mSingle; - } } } return variant; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 925ff5f8..bc8142cf 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -568,6 +568,7 @@ public: virtual bool IsValueTypeOrValueTypePtr() { return false; } virtual bool IsWrappableType() { return false; } virtual bool IsPrimitiveType() { return false; } + virtual BfTypeCode GetTypeCode() { return BfTypeCode_None; } virtual bool IsBoolean() { return false; } virtual bool IsInteger() { return false; } virtual bool IsIntegral() { return false; } @@ -620,6 +621,7 @@ public: public: virtual bool IsPrimitiveType() override { return true; } + virtual BfTypeCode GetTypeCode() override { return mTypeDef->mTypeCode; } virtual bool IsWrappableType() override { return (mTypeDef->mTypeCode >= BfTypeCode_Boolean) && (mTypeDef->mTypeCode <= BfTypeCode_Double); } virtual BfPrimitiveType* ToPrimitiveType() override { return this; } //virtual bool IsValueType() override { return mTypeDef->mTypeCode != BfTypeCode_None; } @@ -1969,7 +1971,7 @@ public: virtual BfPrimitiveType* ToPrimitiveType() override { return GetUnderlyingType()->ToPrimitiveType(); } virtual bool HasWrappedRepresentation() override { return IsTypedPrimitive(); } - int GetEndingInstanceAlignment() { if (mInstSize % mInstAlign == 0) return mInstAlign; return mInstSize % mInstAlign; } + int GetEndingInstanceAlignment() { if (mInstSize % mInstAlign == 0) return mInstAlign; return mInstSize % mInstAlign; } virtual bool HasTypeFailed() override { return mTypeFailed; } virtual bool IsReified() override { return mIsReified; } virtual bool NeedsExplicitAlignment() override { return !IsSizeAligned() || mIsPacked; } @@ -1979,6 +1981,7 @@ public: virtual bool IsSplattable() override { BF_ASSERT((mInstSize >= 0) || (!IsComposite())); return mIsSplattable; } virtual int GetSplatCount() override; virtual bool IsTypeInstance() override { return true; } + virtual BfTypeCode GetTypeCode() override { return mTypeDef->mTypeCode; } virtual bool IsInterface() override { return mTypeDef->mTypeCode == BfTypeCode_Interface; } virtual bool IsValueType() override { return (mTypeDef->mTypeCode == BfTypeCode_Struct) || (mTypeDef->mTypeCode == BfTypeCode_Enum); } virtual bool IsOpaque() override { return mTypeDef->mIsOpaque; } diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index 347e88a4..80728e79 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -10,6 +10,7 @@ #include "BfResolvePass.h" #include "MemReporter.h" #include "BfIRCodeGen.h" +#include "BfIRBuilder.h" #include "BeefySysLib/util/AllocDebug.h" @@ -2300,6 +2301,20 @@ bool BfSystem::DoesLiteralFit(BfTypeCode typeCode, uint64 value) return false; } +bool BfSystem::DoesLiteralFit(BfTypeCode typeCode, const BfVariant& variant) +{ + if ((BfIRConstHolder::IsIntable(typeCode)) && (BfIRConstHolder::IsIntable(variant.mTypeCode))) + { + if (BfIRConstHolder::IsSigned(variant.mTypeCode)) + return DoesLiteralFit(typeCode, variant.mInt64); + else + return DoesLiteralFit(typeCode, variant.mUInt64); + } + if ((BfIRConstHolder::IsFloat(typeCode)) && (BfIRConstHolder::IsFloat(variant.mTypeCode))) + return true; + return typeCode == variant.mTypeCode; +} + BfParser* BfSystem::CreateParser(BfProject* bfProject) { AutoCrit crit(mDataLock); diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index b26fb876..0d64aff4 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -1630,6 +1630,7 @@ public: void CreateBasicTypes(); bool DoesLiteralFit(BfTypeCode typeCode, int64 value); bool DoesLiteralFit(BfTypeCode typeCode, uint64 value); + bool DoesLiteralFit(BfTypeCode typeCode, const BfVariant& variant); BfParser* CreateParser(BfProject* bfProject); BfCompiler* CreateCompiler(bool isResolveOnly); BfProject* GetProject(const StringImpl& projName); diff --git a/IDEHelper/Tests/src/ConstExprs.bf b/IDEHelper/Tests/src/ConstExprs.bf index 33b28ffa..780e3742 100644 --- a/IDEHelper/Tests/src/ConstExprs.bf +++ b/IDEHelper/Tests/src/ConstExprs.bf @@ -19,14 +19,14 @@ namespace Tests } } - class ClassB where TSize : const int + class ClassB where TSize : const int8 { ClassA mVal = new ClassA() ~ delete _; var mVal2 = new ClassA() ~ delete _; - + public int GetVal() { - return mVal.GetVal(); + return mVal.GetVal(); } public int GetVal2() @@ -55,6 +55,10 @@ namespace Tests Test.Assert(cb.GetVal() == 123); Test.Assert(cb.GetVal2() == 223); + ClassB cb2 = scope .(); + Test.Assert(cb2.GetVal() == -45); + Test.Assert(cb2.GetVal2() == 55); + ClassC cc = scope .(); Test.Assert(cc.Test() == 1); } diff --git a/IDEHelper/Tests/src/Operators.bf b/IDEHelper/Tests/src/Operators.bf index 3e2f3f6a..9dae0b52 100644 --- a/IDEHelper/Tests/src/Operators.bf +++ b/IDEHelper/Tests/src/Operators.bf @@ -499,6 +499,10 @@ namespace Tests const int32 c1 = 1; int i0 = 0; var tVal = Vector2((i0 % c0) * (c1 + c1), 1); + + int8 a = 123; + int32 b = a + 100; + Test.Assert(b == 223); } struct IntStruct