summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-03-28 16:57:53 -0700
committerGitHub <noreply@github.com>2024-03-28 16:57:53 -0700
commit75afa659e9a16589638083a1fcf9e879225619cd (patch)
tree1462b68a47f2f1b4856e298185ad24145a4acc83 /source
parent56928794d0800824dc91e150cb345b5fec24d930 (diff)
Fix type union logic in generic type inference. (#3852)
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-ast-support-types.h9
-rw-r--r--source/slang/slang-check-constraint.cpp12
-rw-r--r--source/slang/slang-check-conversion.cpp11
-rw-r--r--source/slang/slang-check-impl.h3
-rw-r--r--source/slang/slang-stdlib.cpp7
-rw-r--r--source/slang/slang.natvis10
6 files changed, 38 insertions, 14 deletions
diff --git a/source/slang/slang-ast-support-types.h b/source/slang/slang-ast-support-types.h
index 196a1d002..93fc3365d 100644
--- a/source/slang/slang-ast-support-types.h
+++ b/source/slang/slang-ast-support-types.h
@@ -140,12 +140,15 @@ namespace Slang
// Cost of converting a pointer to bool
kConversionCost_PtrToBool = 400,
+ // Cost of converting an integer to int16_t
+ kConversionCost_IntegerTruncate = 450,
+
+ // Cost of converting an integer to a half type
+ kConversionCost_IntegerToHalfConversion = 500,
+
// Default case (usable for user-defined conversions)
kConversionCost_Default = 500,
- // Cost of converting an integer to int16_t
- kConversionCost_IntegerTruncate = 700,
-
// Catch-all for conversions that should be discouraged
// (i.e., that really shouldn't be made implicitly)
//
diff --git a/source/slang/slang-check-constraint.cpp b/source/slang/slang-check-constraint.cpp
index 97dbbcfa3..6a9b0adfa 100644
--- a/source/slang/slang-check-constraint.cpp
+++ b/source/slang/slang-check-constraint.cpp
@@ -105,6 +105,7 @@ namespace Slang
// through types `X` that are also builtin scalar types.
//
Type* bestType = nullptr;
+ ConversionCost bestCost = kConversionCost_Explicit;
if(auto basicType = dynamicCast<BasicExpressionType>(type))
{
for(Int baseTypeFlavorIndex = 0; baseTypeFlavorIndex < Int(BaseType::CountOf); baseTypeFlavorIndex++)
@@ -123,7 +124,8 @@ namespace Slang
continue;
// We only want to consider types where we can implicitly convert from `type`
- if(!canConvertImplicitly(candidateType, type))
+ auto conversionCost = getConversionCost(candidateType, type);
+ if(!canConvertImplicitly(conversionCost))
continue;
// At this point, we have a candidate type that is usable.
@@ -139,18 +141,16 @@ namespace Slang
// Otherwise, we want to pick the "better" type between `candidateType`
// and `bestType`.
//
- // We are going to be a bit loose here, and not worry about the
- // case where conversion is allowed in both directions.
+ // The candidate type that has lower conversion cost from `type` is better.
//
- // TODO: make this completely robust.
- //
- if(canConvertImplicitly(bestType, candidateType))
+ if(conversionCost < bestCost)
{
// Our candidate can convert to the current "best" type, so
// it is logically a more specific type that satisfies our
// constraints, therefore we should keep it.
//
bestType = candidateType;
+ bestCost = conversionCost;
}
}
}
diff --git a/source/slang/slang-check-conversion.cpp b/source/slang/slang-check-conversion.cpp
index aeb964cc9..e55a88077 100644
--- a/source/slang/slang-check-conversion.cpp
+++ b/source/slang/slang-check-conversion.cpp
@@ -1389,13 +1389,22 @@ namespace Slang
}
bool SemanticsVisitor::canConvertImplicitly(
+ ConversionCost conversionCost)
+ {
+ // Is the conversion cheap enough to be done implicitly?
+ if (conversionCost >= kConversionCost_GeneralConversion)
+ return false;
+ return true;
+ }
+
+ bool SemanticsVisitor::canConvertImplicitly(
Type* toType,
QualType fromType)
{
auto conversionCost = getConversionCost(toType, fromType);
// Is the conversion cheap enough to be done implicitly?
- if (conversionCost >= kConversionCost_GeneralConversion)
+ if (canConvertImplicitly(conversionCost))
return false;
return true;
diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h
index a3ecc28b4..945618f36 100644
--- a/source/slang/slang-check-impl.h
+++ b/source/slang/slang-check-impl.h
@@ -2077,6 +2077,9 @@ namespace Slang
Type* toType,
QualType fromType);
+ bool canConvertImplicitly(
+ ConversionCost cost);
+
ConversionCost getConversionCost(Type* toType, QualType fromType);
Type* _tryJoinTypeWithInterface(
diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp
index 2bc24d8ec..3c8b48e00 100644
--- a/source/slang/slang-stdlib.cpp
+++ b/source/slang/slang-stdlib.cpp
@@ -222,7 +222,12 @@ namespace Slang
{
return kConversionCost_IntegerToFloatConversion;
}
-
+ else if (toInfo.conversionKind == kBaseTypeConversionKind_Float
+ && toInfo.conversionRank >= kBaseTypeConversionRank_Int16
+ && fromInfo.conversionRank >= kBaseTypeConversionRank_Int8)
+ {
+ return kConversionCost_IntegerToHalfConversion;
+ }
// All other cases are considered as "general" conversions,
// where we don't consider any one conversion better than
// any others.
diff --git a/source/slang/slang.natvis b/source/slang/slang.natvis
index b1b52bc5c..c86faa065 100644
--- a/source/slang/slang.natvis
+++ b/source/slang/slang.natvis
@@ -439,7 +439,6 @@
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ResourceType">(Slang::ResourceType*)&amp;astNodeType</ExpandedItem>
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureTypeBase">(Slang::TextureTypeBase*)&amp;astNodeType</ExpandedItem>
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureType">(Slang::TextureType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureSamplerType">(Slang::TextureSamplerType*)&amp;astNodeType</ExpandedItem>
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLImageType">(Slang::GLSLImageType*)&amp;astNodeType</ExpandedItem>
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::SamplerStateType">(Slang::SamplerStateType*)&amp;astNodeType</ExpandedItem>
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BuiltinGenericType">(Slang::BuiltinGenericType*)&amp;astNodeType</ExpandedItem>
@@ -504,6 +503,13 @@
<Item Name="[Raw View]">(Slang::Type*)this,!</Item>
</Expand>
</Type>
+ <Type Name="Slang::DirectDeclRef">
+ <DisplayString>DirectDeclRef{(Decl*)m_operands.m_buffer[0].values.nodeOperand}</DisplayString>
+ <Expand>
+ <ExpandedItem>(Decl*)m_operands.m_buffer[0].values.nodeOperand</ExpandedItem>
+
+ </Expand>
+ </Type>
<Type Name="Slang::SubstitutionSet">
<DisplayString>SubstitutionSet{declRef,en}</DisplayString>
<Expand>
@@ -581,7 +587,6 @@
<DisplayString Condition="astNodeType == Slang::ASTNodeType::ResourceType">{*(Slang::ResourceType*)this}</DisplayString>
<DisplayString Condition="astNodeType == Slang::ASTNodeType::TextureTypeBase">{*(Slang::TextureTypeBase*)this}</DisplayString>
<DisplayString Condition="astNodeType == Slang::ASTNodeType::TextureType">{*(Slang::TextureType*)this}</DisplayString>
- <DisplayString Condition="astNodeType == Slang::ASTNodeType::TextureSamplerType">{*(Slang::TextureSamplerType*)this}</DisplayString>
<DisplayString Condition="astNodeType == Slang::ASTNodeType::GLSLImageType">{*(Slang::GLSLImageType*)this}</DisplayString>
<DisplayString Condition="astNodeType == Slang::ASTNodeType::SamplerStateType">{*(Slang::SamplerStateType*)this}</DisplayString>
<DisplayString Condition="astNodeType == Slang::ASTNodeType::BuiltinGenericType">{*(Slang::BuiltinGenericType*)this}</DisplayString>
@@ -666,7 +671,6 @@
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ResourceType">(Slang::ResourceType*)&amp;astNodeType</ExpandedItem>
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureTypeBase">(Slang::TextureTypeBase*)&amp;astNodeType</ExpandedItem>
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureType">(Slang::TextureType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureSamplerType">(Slang::TextureSamplerType*)&amp;astNodeType</ExpandedItem>
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLImageType">(Slang::GLSLImageType*)&amp;astNodeType</ExpandedItem>
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::SamplerStateType">(Slang::SamplerStateType*)&amp;astNodeType</ExpandedItem>
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BuiltinGenericType">(Slang::BuiltinGenericType*)&amp;astNodeType</ExpandedItem>