summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-ast-expr.h3
-rw-r--r--source/slang/slang-check-expr.cpp23
-rw-r--r--source/slang/slang-diagnostic-defs.h4
-rw-r--r--source/slang/slang-language-server.cpp7
-rw-r--r--source/slang/slang-lower-to-ir.cpp4
-rw-r--r--source/slang/slang-parser.cpp2
6 files changed, 28 insertions, 15 deletions
diff --git a/source/slang/slang-ast-expr.h b/source/slang/slang-ast-expr.h
index 6f10f2d82..828ca035f 100644
--- a/source/slang/slang-ast-expr.h
+++ b/source/slang/slang-ast-expr.h
@@ -316,7 +316,8 @@ class IsTypeExpr : public Expr
// A witness showing that `typeExpr.type` is a subtype of `typeof(value)`.
Val* witnessArg = nullptr;
- bool isAlwaysTrue = false;
+ // non-null if evaluates to a constant.
+ BoolLiteralExpr* constantVal = nullptr;
};
/// A `value as Type` expression that casts `value` to `Type` within type hierarchy.
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp
index cb75e3078..2ac02b978 100644
--- a/source/slang/slang-check-expr.cpp
+++ b/source/slang/slang-check-expr.cpp
@@ -1771,30 +1771,35 @@ namespace Slang
{
// Instead of returning a BoolLiteralExpr, we use a field to indicate this scenario,
// so that the language server can still see the original syntax tree.
- expr->isAlwaysTrue = true;
+ expr->constantVal = m_astBuilder->create<BoolLiteralExpr>();
+ expr->constantVal->type = m_astBuilder->getBoolType();
+ expr->constantVal->value = true;
+ expr->constantVal->loc = expr->loc;
return expr;
}
// Otherwise, we need to ensure the target type is a subtype of value->type.
- // For now we can only support the scenario where `expr->value` is an interface type.
- if (!isInterfaceType(originalVal->type))
- {
- getSink()->diagnose(expr, Diagnostics::isOperatorValueMustBeInterfaceType);
- }
expr->value = maybeOpenExistential(originalVal);
expr->witnessArg = tryGetSubtypeWitness(expr->typeExpr.type, originalVal->type.type);
if (expr->witnessArg)
{
+ // For now we can only support the scenario where `expr->value` is an interface type.
+ if (!isInterfaceType(originalVal->type))
+ {
+ getSink()->diagnose(expr, Diagnostics::isOperatorValueMustBeInterfaceType);
+ }
return expr;
}
if (!as<ErrorType>(expr->typeExpr.type) && !as<ErrorType>(expr->value->type.type))
{
- getSink()->diagnose(expr, Diagnostics::typeNotInTheSameHierarchy, expr->value->type.type, expr->typeExpr.type);
+ // The type is not in the same hierarchy, so we evaluate to false.
+ expr->constantVal = m_astBuilder->create<BoolLiteralExpr>();
+ expr->constantVal->type = m_astBuilder->getBoolType();
+ expr->constantVal->value = false;
+ expr->constantVal->loc = expr->loc;
}
-
- expr->type = m_astBuilder->getErrorType();
return expr;
}
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 54d81da7d..cbbb284cb 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -250,10 +250,8 @@ DIAGNOSTIC(30012, Error, noOverloadFoundForBinOperatorOnTypes, "no overload foun
DIAGNOSTIC(30013, Error, subscriptNonArray, "no subscript operation found for type '$0'")
DIAGNOSTIC(30014, Error, subscriptIndexNonInteger, "index expression must evaluate to int.")
DIAGNOSTIC(30015, Error, undefinedIdentifier2, "undefined identifier '$0'.")
-DIAGNOSTIC(30017, Error, componentNotAccessibleFromShader, "component '$0' is not accessible from shader '$1'.")
-DIAGNOSTIC(30018, Error, typeNotInTheSameHierarchy, "as/is operator requires '$0' and '$1' to be in the same type hierarchy.")
+DIAGNOSTIC(30018, Error, typeNotInTheSameHierarchy, "invalid use of 'as' operator: expression evaluates to '$0', which is not in the same type hierarchy as target type '$1'.")
DIAGNOSTIC(30019, Error, typeMismatch, "expected an expression of type '$0', got '$1'")
-DIAGNOSTIC(30020, Error, importOperatorReturnTypeMismatch, "import operator should return '$1', but the expression has type '$0''. do you forget 'project'?")
DIAGNOSTIC(30021, Error, noApplicationFunction, "$0: no overload takes arguments ($1)")
DIAGNOSTIC(30022, Error, invalidTypeCast, "invalid type cast between \"$0\" and \"$1\".")
DIAGNOSTIC(30023, Error, typeHasNoPublicMemberOfName, "\"$0\" does not have public member \"$1\".")
diff --git a/source/slang/slang-language-server.cpp b/source/slang/slang-language-server.cpp
index 768fee9e5..f209a4955 100644
--- a/source/slang/slang-language-server.cpp
+++ b/source/slang/slang-language-server.cpp
@@ -217,6 +217,13 @@ String getDeclSignatureString(DeclRef<Decl> declRef, ASTBuilder* astBuilder)
{
sb << " = " << litExpr->token.getContent();
}
+ else if (auto isTypeDecl = as<IsTypeExpr>(varDecl->initExpr))
+ {
+ if (isTypeDecl->constantVal)
+ {
+ sb << " = " << (isTypeDecl->constantVal->value ? "true" : "false");
+ }
+ }
}
return printer.getString();
}
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index c7fbfda77..81ea93f77 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -3966,9 +3966,9 @@ struct ExprLoweringVisitorBase : ExprVisitor<Derived, LoweredValInfo>
LoweredValInfo visitIsTypeExpr(IsTypeExpr* expr)
{
- if (expr->isAlwaysTrue)
+ if (expr->constantVal)
{
- return LoweredValInfo::simple(getBuilder()->getBoolValue(true));
+ return LoweredValInfo::simple(getBuilder()->getBoolValue(expr->constantVal->value));
}
auto value = lowerLValueExpr(context, expr->value);
auto type = lowerType(context, expr->type);
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp
index 7447859c7..33f2e251b 100644
--- a/source/slang/slang-parser.cpp
+++ b/source/slang/slang-parser.cpp
@@ -4858,6 +4858,7 @@ namespace Slang
isExpr->value = expr;
parser->ReadToken();
isExpr->typeExpr = parser->ParseTypeExp();
+ isExpr->loc = opToken.loc;
expr = isExpr;
continue;
}
@@ -4867,6 +4868,7 @@ namespace Slang
asExpr->value = expr;
parser->ReadToken();
asExpr->typeExpr = parser->ParseType();
+ asExpr->loc = opToken.loc;
expr = asExpr;
continue;
}