summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/slang-check-expr.cpp16
-rw-r--r--source/slang/slang-diagnostic-defs.h8
-rw-r--r--tests/language-feature/interface-as-rhs-error.slang73
3 files changed, 97 insertions, 0 deletions
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp
index 66c2f9796..f4c8cd847 100644
--- a/source/slang/slang-check-expr.cpp
+++ b/source/slang/slang-check-expr.cpp
@@ -4065,6 +4065,13 @@ Expr* SemanticsExprVisitor::visitIsTypeExpr(IsTypeExpr* expr)
expr->type = m_astBuilder->getBoolType();
expr->value = originalVal;
+ // Check if the right-hand side type is an interface type
+ if (isInterfaceType(expr->typeExpr.type))
+ {
+ getSink()->diagnose(expr, Diagnostics::isAsOperatorCannotUseInterfaceAsRHS);
+ return expr;
+ }
+
auto valueType = expr->value->type.type;
if (auto typeType = as<TypeType>(valueType))
valueType = typeType->getType();
@@ -4103,6 +4110,15 @@ Expr* SemanticsExprVisitor::visitAsTypeExpr(AsTypeExpr* expr)
TypeExp typeExpr;
typeExpr.exp = expr->typeExpr;
typeExpr = CheckProperType(typeExpr);
+
+ // Check if the right-hand side type is an interface type
+ if (isInterfaceType(typeExpr.type))
+ {
+ getSink()->diagnose(expr, Diagnostics::isAsOperatorCannotUseInterfaceAsRHS);
+ expr->type = m_astBuilder->getErrorType();
+ return expr;
+ }
+
expr->value = CheckTerm(expr->value);
auto optType = m_astBuilder->getOptionalType(typeExpr.type);
expr->type = optType;
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index bef32e20e..f4741ab04 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -842,7 +842,15 @@ DIAGNOSTIC(
isOperatorValueMustBeInterfaceType,
"'is'/'as' operator requires an interface-typed expression.")
+DIAGNOSTIC(
+ 30301,
+ Error,
+ isAsOperatorCannotUseInterfaceAsRHS,
+ "'is' and 'as' operators do not support interface types as the right-hand side. Use a concrete "
+ "type instead.")
+
DIAGNOSTIC(33070, Error, expectedFunction, "expected a function, got '$0'")
+
DIAGNOSTIC(33071, Error, expectedAStringLiteral, "expected a string literal")
// `dyn` and `some` errors
diff --git a/tests/language-feature/interface-as-rhs-error.slang b/tests/language-feature/interface-as-rhs-error.slang
new file mode 100644
index 000000000..9ad71afde
--- /dev/null
+++ b/tests/language-feature/interface-as-rhs-error.slang
@@ -0,0 +1,73 @@
+//TEST:SIMPLE(filecheck=CHECK): -target spirv
+
+interface IMyInterface
+{
+ int getValue();
+}
+
+struct ConcreteImpl : IMyInterface
+{
+ int getValue() { return 42; }
+}
+
+struct AnotherType
+{
+ float value;
+}
+
+// No error messages should show for concrete types above
+//CHECK-NOT:: error
+
+// These should produce errors - interface types as RHS
+bool testIsOperatorWithInterface<T>()
+{
+ //CHECK: ([[# @LINE+1]]): error 30301: 'is' and 'as' operators do not support interface types as the right-hand side
+ return (T is IMyInterface);
+}
+
+void testAsOperatorWithInterface<T>(T value)
+{
+ //CHECK: ([[# @LINE+1]]): error 30301: 'is' and 'as' operators do not support interface types as the right-hand side
+ let result = value as IMyInterface;
+}
+
+// No error messages should show for concrete types below
+//CHECK-NOT:: error
+
+// These should work - concrete types as RHS
+bool testIsOperatorWithConcreteType<T>()
+{
+ return (T is ConcreteImpl); // Should compile without error
+}
+
+void testAsOperatorWithConcreteType<T>(T value)
+{
+ // Test as operator with concrete types - should compile without error
+ let result = value as ConcreteImpl;
+}
+
+void main()
+{
+ ConcreteImpl impl;
+ AnotherType other;
+
+ // Test error cases - these should produce the errors checked above
+ bool result1 = testIsOperatorWithInterface<ConcreteImpl>();
+ testAsOperatorWithInterface<ConcreteImpl>(impl);
+
+ // Test success cases - these should compile without errors
+ // If ANY of these had errors, compilation would fail
+ bool result2 = testIsOperatorWithConcreteType<ConcreteImpl>();
+ testAsOperatorWithConcreteType<ConcreteImpl>(impl);
+
+ // Additional concrete type tests
+ bool isTest1 = (impl is ConcreteImpl);
+ bool isTest2 = (other is AnotherType);
+ bool isTest3 = (ConcreteImpl is ConcreteImpl);
+ bool isTest4 = (AnotherType is ConcreteImpl);
+
+ // Test as operator directly
+ let asTest1 = impl as AnotherType;
+ let asTest2 = other as ConcreteImpl;
+ let asTest3 = impl as ConcreteImpl;
+}