summaryrefslogtreecommitdiffstats
path: root/tests/experiments/generic
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2021-12-21 16:35:34 -0500
committerGitHub <noreply@github.com>2021-12-21 16:35:34 -0500
commit447b7e0e2be031409b1421b49c81f020353bf7c5 (patch)
tree721a1e892b4dc0bcc8c62d7b7e3f9dbb843bf958 /tests/experiments/generic
parentd7ed829c3f85514fc08a12a5701d64390b31040c (diff)
Language experiments (#2068)
* #include an absolute path didn't work - because paths were taken to always be relative. * Moved to experiments. Added some more tests. * More tests around associated types. * Return interface tests. * More tests.
Diffstat (limited to 'tests/experiments/generic')
-rw-r--r--tests/experiments/generic/README.md7
-rw-r--r--tests/experiments/generic/alternative-array-type.slang25
-rw-r--r--tests/experiments/generic/built-in-add.slang26
-rw-r--r--tests/experiments/generic/built-in-extension.slang38
-rw-r--r--tests/experiments/generic/byte-address-ptr-2.slang85
-rw-r--r--tests/experiments/generic/byte-address-ptr.slang87
-rw-r--r--tests/experiments/generic/constraint.slang35
-rw-r--r--tests/experiments/generic/enum-flags.slang46
-rw-r--r--tests/experiments/generic/enum-int-flags.slang42
-rw-r--r--tests/experiments/generic/equality-2.slang42
-rw-r--r--tests/experiments/generic/equality-3.slang40
-rw-r--r--tests/experiments/generic/equality-4.slang56
-rw-r--r--tests/experiments/generic/equality-5.slang44
-rw-r--r--tests/experiments/generic/equality.slang43
-rw-r--r--tests/experiments/generic/field-inheritance-2.slang38
-rw-r--r--tests/experiments/generic/field-inheritance.slang48
-rw-r--r--tests/experiments/generic/fixed-array-2.slang69
-rw-r--r--tests/experiments/generic/fixed-array-3.slang68
-rw-r--r--tests/experiments/generic/fixed-array-4.slang60
-rw-r--r--tests/experiments/generic/fixed-array-5.slang61
-rw-r--r--tests/experiments/generic/fixed-array.slang30
-rw-r--r--tests/experiments/generic/inheritance.slang37
-rw-r--r--tests/experiments/generic/int-generic-param.slang32
-rw-r--r--tests/experiments/generic/interface.slang31
-rw-r--r--tests/experiments/generic/matrix.slang25
-rw-r--r--tests/experiments/generic/meta-2.slang23
-rw-r--r--tests/experiments/generic/meta.slang25
-rw-r--r--tests/experiments/generic/mutating-interface.slang51
-rw-r--r--tests/experiments/generic/operator-overload.slang39
-rw-r--r--tests/experiments/generic/param-specialize-2.slang44
-rw-r--r--tests/experiments/generic/param-specialize.slang44
-rw-r--r--tests/experiments/generic/resource.slang35
-rw-r--r--tests/experiments/generic/return-generic-2.slang38
-rw-r--r--tests/experiments/generic/return-generic-3.slang26
-rw-r--r--tests/experiments/generic/return-generic-4.slang36
-rw-r--r--tests/experiments/generic/return-generic-5.slang30
-rw-r--r--tests/experiments/generic/return-generic.slang38
-rw-r--r--tests/experiments/generic/scope-type.slang36
-rw-r--r--tests/experiments/generic/scope-value-2.slang37
-rw-r--r--tests/experiments/generic/scope-value.slang34
-rw-r--r--tests/experiments/generic/tuple.slang55
-rw-r--r--tests/experiments/generic/type-inference-2.slang26
-rw-r--r--tests/experiments/generic/type-inference-3.slang29
-rw-r--r--tests/experiments/generic/type-inference-4.slang30
-rw-r--r--tests/experiments/generic/type-inference-5.slang26
-rw-r--r--tests/experiments/generic/type-inference.slang33
-rw-r--r--tests/experiments/generic/type-to-value-2.slang48
-rw-r--r--tests/experiments/generic/type-to-value-3.slang43
-rw-r--r--tests/experiments/generic/type-to-value-4.slang49
-rw-r--r--tests/experiments/generic/type-to-value-5.slang56
-rw-r--r--tests/experiments/generic/type-to-value-6.slang49
-rw-r--r--tests/experiments/generic/type-to-value.slang33
52 files changed, 2128 insertions, 0 deletions
diff --git a/tests/experiments/generic/README.md b/tests/experiments/generic/README.md
new file mode 100644
index 000000000..ae062bb11
--- /dev/null
+++ b/tests/experiments/generic/README.md
@@ -0,0 +1,7 @@
+Generic Experiments
+===================
+
+Experiement tests around generics.
+
+All tests are disabled.
+
diff --git a/tests/experiments/generic/alternative-array-type.slang b/tests/experiments/generic/alternative-array-type.slang
new file mode 100644
index 000000000..1e28a85f5
--- /dev/null
+++ b/tests/experiments/generic/alternative-array-type.slang
@@ -0,0 +1,25 @@
+//DISABLE_TEST:SIMPLE:-target hlsl -entry computeMain -profile cs_6_2
+
+/* The docs claim that for arrays we can use the 'alternate' style
+
+https://github.com/shader-slang/slang/blob/master/docs/language-reference/04-types.md
+
+> int[10] a;
+
+But that produces an error:
+
+.slang(18): error 20001: unexpected '[', expected identifier
+ int[4] a = { 1, 2, 3, 4 };
+*/
+
+RWStructuredBuffer<int> outputBuffer;
+
+[numthreads(4, 4, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int x = dispatchThreadID.x;
+
+ int[4] a = { 1, 4, 2, 1 };
+
+ outputBuffer[x] = a[x];
+}
diff --git a/tests/experiments/generic/built-in-add.slang b/tests/experiments/generic/built-in-add.slang
new file mode 100644
index 000000000..c5751fe69
--- /dev/null
+++ b/tests/experiments/generic/built-in-add.slang
@@ -0,0 +1,26 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test use of a generic with a built in doing something simple.
+
+Doesn't work because cannot find +.
+
+.slang(3): error 39999: no overload for '+' applicable to arguments of type (typeof(V), int)
+int doThing<V : int>(int b) { return V + b; }
+
+NOTE! We can fix by adding *let*
+
+int doThing<let V : int>(int b) { return V + b; }
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+int doThing<V : int>(int b) { return V + b; }
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ outputBuffer[dispatchThreadID.x] = doThing<2>(index);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/built-in-extension.slang b/tests/experiments/generic/built-in-extension.slang
new file mode 100644
index 000000000..b71e3eaa6
--- /dev/null
+++ b/tests/experiments/generic/built-in-extension.slang
@@ -0,0 +1,38 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test around extension to a built in, to allow associating types with builtins.
+
+Doesn't work
+
+.slang(22): internal error 99999: unexpected condition encountered in Slang compiler: should not appear in input syntax
+ int.Unsigned v = (int.Unsigned)10;
+
+*/
+
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+interface IIntegral
+{
+ associatedtype Unsigned;
+};
+
+extension int : IIntegral
+{
+ typedef uint Unsigned;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ // Works
+ int.Unsigned u = 10;
+
+ // Doesn't work
+ int.Unsigned v = (int.Unsigned)10;
+
+ outputBuffer[dispatchThreadID.x] = doThing<2>(index);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/byte-address-ptr-2.slang b/tests/experiments/generic/byte-address-ptr-2.slang
new file mode 100644
index 000000000..895c0dba4
--- /dev/null
+++ b/tests/experiments/generic/byte-address-ptr-2.slang
@@ -0,0 +1,85 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* The purpose of these tests is to use generics to be able to traverse
+a 'linked list' of different related types.
+
+tests/current-bugs/generic/byte-address-ptr-2.slang(75): note 99999: an internal error threw an exception while working on code near this location
+(0): error 99999: Slang compilation aborted due to an exception of class Slang::InternalError: assert failure: witnessTableVal->getOp() != kIROp_StructKey
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+
+//TEST_INPUT:ubuffer(data=[0]):name=gB
+ByteAddressBuffer gB;
+
+enum Type : int
+{
+ A,
+ B,
+ C,
+};
+
+interface IBase
+{
+ static bool isType(Type type);
+};
+
+struct Base : IBase
+{
+ static bool isType(Type type) { return true; }
+ Type type;
+};
+
+struct Ptr
+{
+ Type getType() { return gB.Load<Base>(offset).type; }
+
+ __generic<T : IBase>
+ bool isType() { return T::isType(getType()); }
+ // Changing to T : IBase causes an internal compiler crash
+ __generic<T>
+ T as()
+ {
+ // I want a way to assert if not an appropriate cast.
+ return gB.Load<T>(offset);
+ }
+ int offset;
+};
+
+struct A : Base
+{
+ static bool isType(Type type) { return type == Type::A; }
+ Ptr next;
+ int something;
+};
+
+struct B : Base
+{
+ static bool isType(Type type) { return type == Type::C || type == Type::B; }
+ int someData;
+};
+
+struct C : B
+{
+ static bool isType(Type type) { return type == Type::C; }
+ int somethingElse;
+};
+
+RWStructuredBuffer<int> outputBuffer;
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ Ptr ptr = { 0 };
+ int total = 0;
+
+ while (ptr.isType<A>())
+ {
+ A a = ptr.as<A>();
+ total += a.something;
+
+ ptr = a.next;
+ }
+
+ outputBuffer[dispatchThreadID.x] = total;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/byte-address-ptr.slang b/tests/experiments/generic/byte-address-ptr.slang
new file mode 100644
index 000000000..33096b70f
--- /dev/null
+++ b/tests/experiments/generic/byte-address-ptr.slang
@@ -0,0 +1,87 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* The purpose of these tests is to use generics to be able to traverse
+a 'linked list' of different related types.
+
+tests/current-bugs/generic/byte-address-ptr.slang(77): note 99999: an internal error threw an exception while working on code near this location
+(0): error 99999: Slang compilation aborted due to an exception of class Slang::InternalError: assert failure: witnessTableVal->getOp() != kIROp_StructKey
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+
+//TEST_INPUT:ubuffer(data=[0]):name=gB
+ByteAddressBuffer gB;
+
+enum Type : int
+{
+ A,
+ B,
+ C,
+};
+
+interface IBase
+{
+ static bool isType(Type type);
+};
+
+struct Base : IBase
+{
+ static bool isType(Type type) { return true; }
+ Type type;
+};
+
+struct Ptr
+{
+ Type getType() { return gB.Load<Base>(offset).type; }
+
+ __generic<T : IBase>
+ bool isType() { return T::isType(getType()); }
+ // Changing to T : IBase causes an internal compiler crash
+ __generic<T : IBase>
+ T as()
+ {
+ bool isOk = isType<T>();
+ // I want a way to assert!
+ // assert(isOk);
+ return gB.Load<T>(offset);
+ }
+ int offset;
+};
+
+struct A : Base
+{
+ static bool isType(Type type) { return type == Type::A; }
+ Ptr next;
+ int something;
+};
+
+struct B : Base
+{
+ static bool isType(Type type) { return type == Type::C || type == Type::B; }
+ int someData;
+};
+
+struct C : B
+{
+ static bool isType(Type type) { return type == Type::C; }
+ int somethingElse;
+};
+
+RWStructuredBuffer<int> outputBuffer;
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ Ptr ptr = { 0 };
+ int total = 0;
+
+ while (ptr.isType<A>())
+ {
+ A a = ptr.as<A>();
+ total += a.something;
+
+ ptr = a.next;
+ }
+
+ outputBuffer[dispatchThreadID.x] = total;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/constraint.slang b/tests/experiments/generic/constraint.slang
new file mode 100644
index 000000000..7143d3fd4
--- /dev/null
+++ b/tests/experiments/generic/constraint.slang
@@ -0,0 +1,35 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test is to try and see what effects type constraints have.
+
+This is a bit of a silly example.
+
+Fails with
+
+.slang(23): note 99999: an internal error threw an exception while working on code near this location
+(0): error 99999: Slang compilation aborted due to an exception of class Slang::InternalError: unimplemented: value lowering
+
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum XXX {};
+
+__generic<T : XXX>
+Enum getEnum(T i)
+{
+ return Enum::A;
+}
+
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ XXX x;
+ let e = getEnum(x);
+
+ outputBuffer[index] = int(e);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/enum-flags.slang b/tests/experiments/generic/enum-flags.slang
new file mode 100644
index 000000000..0ae992e6a
--- /dev/null
+++ b/tests/experiments/generic/enum-flags.slang
@@ -0,0 +1,46 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test to use generics to treat an enum as a set.
+
+.slang(15): error 30060: expected a type, got a '__BuiltinIntegerType'
+ B value = 0;
+
+.slang(23): error 30019: expected an expression of type 'int', got 'typeof(uint8_t)'
+ Flags<Enum, uint8_t> flags;
+ ^~~~~~~
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+enum Enum
+{
+ A = 0x1,
+ B = 0x2,
+ C = 0x4,
+};
+
+__generic<E, let B : __BuiltinIntegerType>
+struct Flags
+{
+ [mutating] void set(E e) { value |= (B)e; }
+ void isSet(E e) { return (((B)e) & value) != 0; }
+ B value = 0;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ Flags<Enum, uint8_t> flags;
+
+ if (index & 1)
+ {
+ flags.set(Enum::A);
+ }
+ bool isASet = flags.isSet(Enum::A);
+
+ outputBuffer[index] = isASet ? 2 : 1;
+}
+
diff --git a/tests/experiments/generic/enum-int-flags.slang b/tests/experiments/generic/enum-int-flags.slang
new file mode 100644
index 000000000..d35b7e6ab
--- /dev/null
+++ b/tests/experiments/generic/enum-int-flags.slang
@@ -0,0 +1,42 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test to use generics to treat an enum as a set. */
+/* Doesn't work because doesn't know can convert E into an int type.
+
+If E could be specified as any enum type then perhaps this could work.
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+enum Enum
+{
+ A = 0x1,
+ B = 0x2,
+ C = 0x4,
+};
+
+__generic<E>
+struct Flags
+{
+ [mutating] void set(E e) { value |= (int)e; }
+ void isSet(E e) { return (((int)e) & value) != 0; }
+ int value = 0;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ Flags<Enum> flags;
+
+ if (index & 1)
+ {
+ flags.set(Enum::A);
+ }
+ bool isASet = flags.isSet(Enum::A);
+
+ outputBuffer[index] = isASet ? 2 : 1;
+}
+
diff --git a/tests/experiments/generic/equality-2.slang b/tests/experiments/generic/equality-2.slang
new file mode 100644
index 000000000..8a1f87463
--- /dev/null
+++ b/tests/experiments/generic/equality-2.slang
@@ -0,0 +1,42 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test for equality around interface types
+
+This does work.
+
+It is here, because it seems like an awkward to do things, and only applys to struct like types.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+interface IEquality
+{
+ associatedtype Type;
+ bool isEqual(Type rhs);
+};
+
+struct A : IEquality
+{
+ typedef A Type;
+ bool isEqual(IEquality rhs)
+ {
+ return value == rhs.value;
+ }
+ int value;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ A a = { 1 };
+ A b = { 2 };
+
+ bool isEqual = a.isEqual(b);
+
+ outputBuffer[index] = 1 + int(isEqual);
+}
+
+
diff --git a/tests/experiments/generic/equality-3.slang b/tests/experiments/generic/equality-3.slang
new file mode 100644
index 000000000..e5e42aedf
--- /dev/null
+++ b/tests/experiments/generic/equality-3.slang
@@ -0,0 +1,40 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test for equality around interface types
+
+This style is discussed in the documentation here:
+
+Still has limitiation that it only works for an an implementation of an interface.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+interface IEquality
+{
+ bool isEqual(This other);
+}
+
+struct A : IEquality
+{
+ bool isEqual(This other)
+ {
+ return value == other.value;
+ }
+ int value;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ A a = { 1 };
+ A b = { 2 };
+
+ bool isEqual = a.isEqual(b);
+
+ outputBuffer[index] = 1 + int(isEqual);
+}
+
+
diff --git a/tests/experiments/generic/equality-4.slang b/tests/experiments/generic/equality-4.slang
new file mode 100644
index 000000000..44c049323
--- /dev/null
+++ b/tests/experiments/generic/equality-4.slang
@@ -0,0 +1,56 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test for equality around interface types
+
+Here again trying to apply equality *outside* of the types (MyStruct) definition.
+
+Doesn't work:
+
+.slang(24): error 30019: expected an expression of type 'Type', got 'T'
+ return T::isEqual(a, b);
+
+Note! This may be somewhat of a silly example for equality. We could get what we want here by just
+implementing 'isEqual(MyStruct a, MyStruct b)` as a free function and use overloading.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+struct MyStruct
+{
+ int a = 10;
+};
+
+interface IEquality
+{
+ associatedtype Type;
+ static bool isEqual(Type a, Type b);
+}
+
+extension MyStruct : IEquality
+{
+ // Do I need this? Is the type This?
+ typedef MyStruct Type;
+ static bool isEqual(Type a, Type b) { return a.a == b.a; }
+};
+
+__generic<T : IEquality>
+bool isEqual(T a, T b)
+{
+ return T::isEqual(a, b);
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ MyStruct a = { 1 };
+ MyStruct b = { 2 };
+
+ bool res = isEqual(a, b);
+
+ outputBuffer[index] = 1 + int(res);
+}
+
+
diff --git a/tests/experiments/generic/equality-5.slang b/tests/experiments/generic/equality-5.slang
new file mode 100644
index 000000000..41cadbbfc
--- /dev/null
+++ b/tests/experiments/generic/equality-5.slang
@@ -0,0 +1,44 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test for equality around interface types
+
+This is an attempt to get the *outside* impl of equality to work. The simple case does, but just to throw
+a spanner in the works, lets mix in some inheritance.
+
+An issue here (perhaps) is that this will compile - the isEqual implementation will just slice and probably not do what the implementer expected.
+
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+struct MyStruct
+{
+ int a = 10;
+};
+
+struct MyStruct2 : MyStruct
+{
+ int b;
+};
+
+bool isEqual(MyStruct a, MyStruct b)
+{
+ return a.a == b.a;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ // I *suppose* it could be argued that this is problematic - that the b field is uninitialized
+ // but there is no warning or an error.
+
+ MyStruct2 a = { 1 };
+ MyStruct2 b = { 2 };
+
+ bool res = isEqual(a, b);
+
+ outputBuffer[index] = 1 + int(res);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/equality.slang b/tests/experiments/generic/equality.slang
new file mode 100644
index 000000000..eb4569df5
--- /dev/null
+++ b/tests/experiments/generic/equality.slang
@@ -0,0 +1,43 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test for equality around interface types
+
+Doesn't work because
+
+.slang(8): error 38100: type 'A' does not provide required interface member 'isEqual'
+struct A : IEquality
+ ^~~~~~~~~
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+interface IEquality
+{
+ bool isEqual(IEquality rhs);
+};
+
+struct A : IEquality
+{
+ bool isEqual(IEquality rhs)
+ {
+ // Hmm. How can I cant query rhs, and then cast, so not clear how to implement
+ return true;
+ }
+ int value;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ A a = { 1 };
+ A b = { 2 };
+
+ bool isEqual = a.isEqual(b);
+
+ outputBuffer[index] = 1 + int(isEqual);
+}
+
+
diff --git a/tests/experiments/generic/field-inheritance-2.slang b/tests/experiments/generic/field-inheritance-2.slang
new file mode 100644
index 000000000..af3a153b4
--- /dev/null
+++ b/tests/experiments/generic/field-inheritance-2.slang
@@ -0,0 +1,38 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* The test is for behavior with inheritance and two fields with the same name.
+
+.slang(24): error 39999: no overload for 'int' applicable to arguments of type (overload group)
+ outputBuffer[index] = 1 + int(a.a);
+
+Looks like the problem is that it sees 'a' as 'overloaded' - which I guess is one way to look at it. It is then followed with ...
+
+core.meta.slang(230): note 39999: candidate: int.init(uint64_t)
+core.meta.slang(230): note 39999: candidate: int.init(uint)
+
+Which doesn't seem appropriate
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+struct MyStruct
+{
+ int a = 10;
+};
+
+struct MyStruct2 : MyStruct
+{
+ int a = 10;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ MyStruct2 a;
+
+ outputBuffer[index] = 1 + int(a.a);
+}
+
diff --git a/tests/experiments/generic/field-inheritance.slang b/tests/experiments/generic/field-inheritance.slang
new file mode 100644
index 000000000..593ee81f1
--- /dev/null
+++ b/tests/experiments/generic/field-inheritance.slang
@@ -0,0 +1,48 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* The test here uses struct inheritance but has a field with the same name in the derived type.
+
+This error is for the MyStruct2 version.
+
+.slang(20): error 39999: no overload for '==' applicable to arguments of type (overload group, overload group)
+ return a.a == b.a;
+
+No error/warning is given for the shadowing of MyStruct.a.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+struct MyStruct
+{
+ int a = 10;
+};
+
+struct MyStruct2 : MyStruct
+{
+ int a = 10;
+};
+
+bool isEqual(MyStruct a, MyStruct b)
+{
+ return a.a == b.a;
+}
+
+bool isEqual(MyStruct2 a, MyStruct2 b)
+{
+ return a.a == b.a;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ MyStruct a = { 1 };
+ MyStruct b = { 2 };
+
+ bool res = isEqual(a, b);
+
+ outputBuffer[index] = 1 + int(res);
+}
+
diff --git a/tests/experiments/generic/fixed-array-2.slang b/tests/experiments/generic/fixed-array-2.slang
new file mode 100644
index 000000000..00024f80e
--- /dev/null
+++ b/tests/experiments/generic/fixed-array-2.slang
@@ -0,0 +1,69 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test around use of an array like container.
+
+Here we just fix the array size, so can test out other characteristics.
+
+indexOf can't compile because v == elements[i] cannot determine equality.
+
+It would seem like I should have an IEquality interface, that I could then make
+a T require.
+
+Doesn't work because
+
+.slang(29): error 30019: expected an expression of type 'Type', got 'T'
+ if (T::isEqual(v, elements[i]))
+
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+interface IEquality
+{
+ associatedtype Type;
+ static bool isEqual(Type a, Type b);
+};
+
+extension int : IEquality
+{
+ typedef int Type;
+ static bool isEqual(Type a, Type b)
+ {
+ return a == b;
+ }
+};
+
+
+struct FixedArray<T : IEquality>
+{
+ static const int SIZE = 4;
+
+ [mutating] void setAt(int i, T value) { elements[i] = value; }
+ T getAt(int i) { return elements[i]; }
+ int indexOf(T v)
+ {
+ for (int i = 0; i < SIZE; ++i)
+ {
+ if (T::isEqual(v, elements[i]))
+ {
+ return i;
+ }
+ return -1;
+ }
+ }
+ T elements[SIZE];
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ FixedArray<int> arr;
+ arr.setAt(0, index);
+
+ outputBuffer[index] = 1 + arr.getAt(0);
+}
+
+
diff --git a/tests/experiments/generic/fixed-array-3.slang b/tests/experiments/generic/fixed-array-3.slang
new file mode 100644
index 000000000..16c4c9931
--- /dev/null
+++ b/tests/experiments/generic/fixed-array-3.slang
@@ -0,0 +1,68 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test around use of an array like container.
+
+Here we just fix the array size, so can test out other characteristics.
+
+indexOf can't compile because v == elements[i] cannot determine equality.
+
+It would seem like I should have an IEquality interface, that I could then make
+a T require.
+
+Doesn't work because
+
+.slang(29): error 30019: expected an expression of type 'Type', got 'T'
+ if (T::isEqual(v, elements[i]))
+
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+interface IEquality
+{
+ associatedtype Type;
+ static bool isEqual(Type a, Type b);
+};
+
+extension int : IEquality
+{
+ typedef int Type;
+ static bool isEqual(Type a, Type b)
+ {
+ return a == b;
+ }
+};
+
+
+struct FixedArray<T : IEquality>
+{
+ static const int SIZE = 4;
+
+ [mutating] void setAt(int i, T value) { elements[i] = value; }
+ T getAt(int i) { return elements[i]; }
+ int indexOf(T v)
+ {
+ for (int i = 0; i < SIZE; ++i)
+ {
+ if (T::isEqual(v, elements[i]))
+ {
+ return i;
+ }
+ return -1;
+ }
+ }
+ T elements[SIZE];
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ FixedArray<int> arr;
+ arr.setAt(0, index);
+
+ outputBuffer[index] = 1 + arr.getAt(0);
+}
+
diff --git a/tests/experiments/generic/fixed-array-4.slang b/tests/experiments/generic/fixed-array-4.slang
new file mode 100644
index 000000000..bf58398d0
--- /dev/null
+++ b/tests/experiments/generic/fixed-array-4.slang
@@ -0,0 +1,60 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test around use of an array like container.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+/* Here is an attempt to provide an interface to check equality.
+But is the definition right anyway? Really I want the This and Type to be
+the same type. I guess this enforces that but in an odd manner.
+*/
+interface IEquality
+{
+ associatedtype Type;
+ bool isEqual(Type rhs);
+};
+
+extension int : IEquality
+{
+ typedef int Type;
+ bool isEqual(Type rhs)
+ {
+ // This use of `this` is going to seem odd to a C++ programmer
+ return this == rhs;
+ }
+};
+
+struct FixedArray<T : IEquality>
+{
+ static const int SIZE = 4;
+
+ [mutating] void setAt(int i, T value) { elements[i] = value; }
+ T getAt(int i) { return elements[i]; }
+ int indexOf(T v)
+ {
+ for (int i = 0; i < SIZE; ++i)
+ {
+ if (v.isEqual(elements[i]))
+ {
+ return i;
+ }
+ return -1;
+ }
+ }
+ T elements[SIZE];
+};
+
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ FixedArray<int> arr;
+ arr.setAt(0, index);
+
+ outputBuffer[index] = 1 + arr.getAt(0);
+}
+
diff --git a/tests/experiments/generic/fixed-array-5.slang b/tests/experiments/generic/fixed-array-5.slang
new file mode 100644
index 000000000..6d0c6f8b9
--- /dev/null
+++ b/tests/experiments/generic/fixed-array-5.slang
@@ -0,0 +1,61 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test around use of an array like container.
+
+Here the attempt is to make the equality test separate from the type.
+This isn't a great answer because it relies on the right types set
+for T and E to work together.
+
+This doesn't work because...
+.slang(25): error 30019: expected an expression of type 'Type', got 'T'
+ if (E::isEqual(v, elements[i]))
+
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+interface IEquality
+{
+ associatedtype Type;
+ static bool isEqual(Type a, Type b);
+};
+
+struct IntEquality : IEquality
+{
+ typedef int Type;
+ static bool isEqual(Type a, Type b) { return a == b; }
+};
+
+struct FixedArray<T, E : IEquality>
+{
+ static const int SIZE = 4;
+
+ [mutating] void setAt(int i, T value) { elements[i] = value; }
+ T getAt(int i) { return elements[i]; }
+ int indexOf(T v)
+ {
+ for (int i = 0; i < SIZE; ++i)
+ {
+ if (E::isEqual(v, elements[i]))
+ {
+ return i;
+ }
+ return -1;
+ }
+ }
+ T elements[SIZE];
+};
+
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ FixedArray<int, IntEquality> arr;
+ arr.setAt(0, index);
+
+ outputBuffer[index] = 1 + arr.getAt(0);
+}
+
diff --git a/tests/experiments/generic/fixed-array.slang b/tests/experiments/generic/fixed-array.slang
new file mode 100644
index 000000000..8f8335aa2
--- /dev/null
+++ b/tests/experiments/generic/fixed-array.slang
@@ -0,0 +1,30 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test around use of an array like container.
+
+Has error:
+
+.slang(5): error 30019: expected an expression of type 'int', got 'typeof(SIZE)'
+ T elements[SIZE];
+
+Problem here is SIZE doesn't have *let* in front. The error doesn't provide any useful insight into that. It's also not entirely clear *why* let is needed. Presumably because it's not a type?
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+struct FixedArray<T, SIZE : int>
+{
+ T elements[SIZE];
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ FixedArray<int, 8> arr;
+
+ outputBuffer[index] = 1;
+}
+
diff --git a/tests/experiments/generic/inheritance.slang b/tests/experiments/generic/inheritance.slang
new file mode 100644
index 000000000..6374ccd7f
--- /dev/null
+++ b/tests/experiments/generic/inheritance.slang
@@ -0,0 +1,37 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Tests around inheritance.
+
+Works.
+
+Docs state inheritance isn't available (although states it might in the future).
+
+https://github.com/shader-slang/slang/blob/master/docs/language-reference/07-declarations.md
+
+> Currently only interface types may be named in the inheritance clause of a structure type. When a structure type declares that it inherits from an interface, the programmer asserts that the structure type implements the required members of the interface.
+
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+struct A<T>
+{
+ T a;
+};
+
+struct B : A<float>
+{
+ int b;
+};
+
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ B b = { 1, 2 + index };
+
+ outputBuffer[index] = b.b * b.a;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/int-generic-param.slang b/tests/experiments/generic/int-generic-param.slang
new file mode 100644
index 000000000..f2f5ebb14
--- /dev/null
+++ b/tests/experiments/generic/int-generic-param.slang
@@ -0,0 +1,32 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test around integer generic parameters.
+
+Fails with:
+
+.slang(7): error 30019: expected an expression of type 'int', got 'typeof(N)'
+ return N;
+
+This is like *fixed-array.slang*. It needs let.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+int getN<N : int>()
+{
+ return N;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float4 values = { 1, 2, 3, 4 };
+
+ let val = getN<10>();
+
+ outputBuffer[index] = val;
+}
+
diff --git a/tests/experiments/generic/interface.slang b/tests/experiments/generic/interface.slang
new file mode 100644
index 000000000..d1d8c60ab
--- /dev/null
+++ b/tests/experiments/generic/interface.slang
@@ -0,0 +1,31 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Tests around interface/generics
+
+.slang(7): error 20001: unexpected '<', expected '{'
+interface IThing<T>
+*/
+
+// Docs say this should work...
+// https://github.com/shader-slang/slang/blob/master/docs/language-reference/07-declarations.md
+
+interface IThing<T>
+{
+ T get();
+};
+
+struct X : IThing<int>
+{
+ int get() { return 10; }
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ X x;
+ IThing<int> i = x;
+
+ outputBuffer[index] = i.get();
+} \ No newline at end of file
diff --git a/tests/experiments/generic/matrix.slang b/tests/experiments/generic/matrix.slang
new file mode 100644
index 000000000..c55c7be33
--- /dev/null
+++ b/tests/experiments/generic/matrix.slang
@@ -0,0 +1,25 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test to use generics around resource/built in types.
+
+CRASHES the compiler.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+struct Another<let W : int, let H : int>
+{
+ matrix<float, W, H> values;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ Another<2, 4> a = {};
+
+ outputBuffer[index] = index;
+}
+
diff --git a/tests/experiments/generic/meta-2.slang b/tests/experiments/generic/meta-2.slang
new file mode 100644
index 000000000..98ae09ce5
--- /dev/null
+++ b/tests/experiments/generic/meta-2.slang
@@ -0,0 +1,23 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test meta programing.
+
+CRASHES the compiler(!). Stack overrun.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+struct GetValue<let N : int>
+{
+ static const int Value = N;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ outputBuffer[index] = GetValue<10>::Value;
+}
+
diff --git a/tests/experiments/generic/meta.slang b/tests/experiments/generic/meta.slang
new file mode 100644
index 000000000..8304593b5
--- /dev/null
+++ b/tests/experiments/generic/meta.slang
@@ -0,0 +1,25 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test meta programing.
+
+Works.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+struct GetVector4<T>
+{
+ typedef vector<T, 4> Value;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ GetVector4<float>::Value v = { 1, 2, 3, 4 };
+
+ outputBuffer[index] = dot(v, v);
+}
+
diff --git a/tests/experiments/generic/mutating-interface.slang b/tests/experiments/generic/mutating-interface.slang
new file mode 100644
index 000000000..2198b56b2
--- /dev/null
+++ b/tests/experiments/generic/mutating-interface.slang
@@ -0,0 +1,51 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test using interfaces with mutation.
+
+Doesn't work because
+
+.slang(18): error 30050: mutating method 'lock' cannot be called on an immutable value
+ lockable.lock();
+
+If that section is removed we get on `doThing(count)`
+
+.slang(31): error 30047: argument passed to parameter '0' must be l-value.
+
+Which perhaps means an inteface cannot be used as a lvalue?
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+interface ILockable
+{
+ [mutating] void lock();
+ [mutating] void unlock();
+};
+
+struct IntCount : ILockable
+{
+ [mutating] void lock() { count ++; }
+ [mutating] void unlock() { --count; }
+ int count = 0;
+};
+
+int doThing(inout ILockable lockable)
+{
+ lockable.lock();
+ // do something...
+
+ lockable.unlock();
+ return 0;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ IntCount count;
+ doThing(count);
+
+ outputBuffer[dispatchThreadID.x] = count.count;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/operator-overload.slang b/tests/experiments/generic/operator-overload.slang
new file mode 100644
index 000000000..590322171
--- /dev/null
+++ b/tests/experiments/generic/operator-overload.slang
@@ -0,0 +1,39 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is test out operator overloading. This may not be a feature
+that works in user code (it is used within the stdlib).
+
+This produces:
+.slang(10): error 30019: expected an expression of type 'Vec2d', got 'double'
+ return {a.x + b.x, a.y + b.y};
+
+Moreover...
+
+.slang(18): error 30019: expected an expression of type 'Vec2d', got 'int'
+ int a = 10 + 11;
+
+It's as if only this operator+ impl can now be seen.
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+struct Vec2d
+{
+ double x, y;
+};
+
+Vec2d operator+(Vec2d a, Vec2d b)
+{
+ return {a.x + b.x, a.y + b.y};
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ int a = 10 + 11;
+
+ outputBuffer[dispatchThreadID.x] = int(v);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/param-specialize-2.slang b/tests/experiments/generic/param-specialize-2.slang
new file mode 100644
index 000000000..04dc2f61c
--- /dev/null
+++ b/tests/experiments/generic/param-specialize-2.slang
@@ -0,0 +1,44 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* This test trys to specialize an algorithm through generic parameters.
+
+Using parameters in this way ensures the algorithm in function form
+will have those values known at compile time, and presumably lead to a specialized version.
+
+Here (with 1 == 1) it's testing if a compile time knowable expression can be used.
+
+Does not work because
+
+.slang(25): note 99999: an internal error threw an exception while working on code near this location
+(0): error 99999: Slang compilation aborted due to an exception of class Slang::InternalError: unexpected: ErrorType
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A, B
+};
+
+// NOTE! Here we don't have let!
+int doThing<a : bool, b : int, c : Enum>()
+{
+ //if (a)
+ {
+ return 1;
+ }
+ return 0;
+ //return a ? b + b + int(c) : b - int(c);
+}
+
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ let v = doThing<1 == 1, false, Enum::A>();
+
+ outputBuffer[dispatchThreadID.x] = v;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/param-specialize.slang b/tests/experiments/generic/param-specialize.slang
new file mode 100644
index 000000000..cff623827
--- /dev/null
+++ b/tests/experiments/generic/param-specialize.slang
@@ -0,0 +1,44 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* This test trys to specialize an algorithm through generic parameters.
+
+Using parameters in this way ensures the algorithm in function form
+will have those values known at compile time, and presumably lead to a specialized version.
+
+Does not work because
+
+.slang(24): error 30019: expected an expression of type 'int', got 'Enum'
+ let v = doThing<true, false, Enum::A>();
+ ^
+
+Note that docs say doesn't support any other than int, but error is a bit confusing. No error at declaration.
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A, B
+};
+
+int doThing<let a : bool, let b : int, let c : Enum>()
+{
+ if (a)
+ {
+ return 1;
+ }
+ return 0;
+ // A more complex scenario
+ //return a ? b + b + int(c) : b - int(c);
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ let v = doThing<true, false, Enum::A>();
+
+ outputBuffer[dispatchThreadID.x] = v;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/resource.slang b/tests/experiments/generic/resource.slang
new file mode 100644
index 000000000..51cd8a00f
--- /dev/null
+++ b/tests/experiments/generic/resource.slang
@@ -0,0 +1,35 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test to use generics around resource/built in types.
+
+This test shouldn't compile (wrong type for the Texture1D, but gives this error, which doesn't really explain the problem.
+
+.slang(19): error 30019: expected an expression of type 'Texture1D', got 'Texture1D'
+ a.tex = tex;
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+// NOTE! This is purposefully wrong to test tex type checking
+Texture1D<float> tex;
+
+struct Another<T>
+{
+ T z;
+ Texture1D<T> tex;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ Another<int> a;
+
+ a.z = index;
+ a.tex = tex;
+
+ outputBuffer[index] = a.z + a.tex.Load(index);
+}
+
diff --git a/tests/experiments/generic/return-generic-2.slang b/tests/experiments/generic/return-generic-2.slang
new file mode 100644
index 000000000..487b20e44
--- /dev/null
+++ b/tests/experiments/generic/return-generic-2.slang
@@ -0,0 +1,38 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic function returning a generic struct. types.
+
+Failed:
+
+.slang(20): note 99999: an internal error threw an exception while working on code near this location
+(0): error 99999: Slang compilation aborted due to an exception of class Slang::InternalError: unexpected: ErrorType
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+// NOTE, that really I'd prefer, but that won't work because
+// the : int doesn't currently allow
+// vector<T, SIZE> makeVector4<T, SIZE : int>(T values[SIZE])
+
+vector<T> makeVector4<T>(T values[4])
+{
+ vector<T, 4> v;
+ v.x = values[0];
+ v.y = values[1];
+ v.z = values[2];
+ v.w = values[3];
+ return v;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float values[] = { 1, 2, 3, 4};
+
+ let vec = makeVector4<float>(values);
+
+ outputBuffer[index] = dot(vec, vec);
+}
diff --git a/tests/experiments/generic/return-generic-3.slang b/tests/experiments/generic/return-generic-3.slang
new file mode 100644
index 000000000..9d6997deb
--- /dev/null
+++ b/tests/experiments/generic/return-generic-3.slang
@@ -0,0 +1,26 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic function returning a generic struct.
+
+Works, and deduces the input type of broadcast.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+vector<T, 4> broadcast4<T>(T v)
+{
+ vector<T, 4> vec;
+ vec.x = vec.y = vec.z = vec.w = v;
+ return vec;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ let vec = broadcast4(2.0f);
+
+ outputBuffer[index] = dot(vec, vec);
+}
diff --git a/tests/experiments/generic/return-generic-4.slang b/tests/experiments/generic/return-generic-4.slang
new file mode 100644
index 000000000..d9454169e
--- /dev/null
+++ b/tests/experiments/generic/return-generic-4.slang
@@ -0,0 +1,36 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic function returning a generic struct. types.
+
+Was unable to determine T
+
+Failed:
+
+.slang(35): error 39999: could not specialize generic for arguments of type (float[4])
+ let vec = makeVector4(values);
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+vector<T> makeVector4<T>(T values[4])
+{
+ vector<T, 4> v;
+ v.x = values[0];
+ v.y = values[1];
+ v.z = values[2];
+ v.w = values[3];
+ return v;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float values[] = { 1, 2, 3, 4};
+
+ let vec = makeVector4(values);
+
+ outputBuffer[index] = dot(vec, vec);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/return-generic-5.slang b/tests/experiments/generic/return-generic-5.slang
new file mode 100644
index 000000000..34b90605f
--- /dev/null
+++ b/tests/experiments/generic/return-generic-5.slang
@@ -0,0 +1,30 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic function returning a generic struct (of built in type).
+
+Note somewhat silly example because could just use float4(2.0f)
+
+Works.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+vector<T, N> broadcast<T, let N : int>(T v)
+{
+ vector<T, N> vec;
+ for (int i = 0; i < N; ++i)
+ {
+ vec[i] = v;
+ }
+
+ return vec;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+ let vec = broadcast<float, 4>(2.0f);
+ outputBuffer[index] = dot(vec, vec);
+}
diff --git a/tests/experiments/generic/return-generic.slang b/tests/experiments/generic/return-generic.slang
new file mode 100644
index 000000000..d107bdafe
--- /dev/null
+++ b/tests/experiments/generic/return-generic.slang
@@ -0,0 +1,38 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic function returning a generic struct. types.
+
+Since T could be any type, the compiler can't determine if it's convertable from an int. That may be surprising.
+
+Fails because:
+
+.slang(11): error 30019: expected an expression of type 'T', got 'int'
+ a.value = i;
+ ^
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+struct Another<T>
+{
+ T value;
+};
+
+Another<T> getAnother<T>(int i)
+{
+ Another<T> a;
+ a.value = i;
+ return a;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ Another<int> a = getAnother<int>(index);
+
+ outputBuffer[index] = a.value;
+}
+
diff --git a/tests/experiments/generic/scope-type.slang b/tests/experiments/generic/scope-type.slang
new file mode 100644
index 000000000..01c9bfc62
--- /dev/null
+++ b/tests/experiments/generic/scope-type.slang
@@ -0,0 +1,36 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+This may be a similar problem as with scope-value-2.slang.
+This doesn't work *only* if Thing derives from IIntegral. Remove that and it's fine.
+
+.slang(19): internal error 99999: unexpected condition encountered in Slang compiler: should not appear in input syntax
+ let v = (Thing::Unsigned)10;
+ ^~
+
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+interface IIntegral
+{
+ associatedtype Unsigned;
+};
+
+struct Thing : IIntegral
+{
+ typedef uint Unsigned;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ // Doesn't work
+ let v = (Thing::Unsigned)10;
+
+ outputBuffer[dispatchThreadID.x] = int(v);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/scope-value-2.slang b/tests/experiments/generic/scope-value-2.slang
new file mode 100644
index 000000000..9b30934b4
--- /dev/null
+++ b/tests/experiments/generic/scope-value-2.slang
@@ -0,0 +1,37 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+Doesn't work
+D:\local\Temp\a3393a41-6d61-4049-816b-4edcc04f47fb.slang(24): error 30027: 'kE' is not a member of 'overload group'.
+ let e = A::Type::kE;
+
+The only change here was to make A implement IHasType
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A, B
+};
+
+interface IHasType
+{
+ associatedtype Type;
+};
+
+struct A : IHasType
+{
+ typedef A Type;
+ static const Enum kE = Enum::A;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+ let e = A::Type::kE;
+ outputBuffer[index] = int(e);
+}
diff --git a/tests/experiments/generic/scope-value.slang b/tests/experiments/generic/scope-value.slang
new file mode 100644
index 000000000..8b71c7dcc
--- /dev/null
+++ b/tests/experiments/generic/scope-value.slang
@@ -0,0 +1,34 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+Works
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A, B
+};
+
+struct A
+{
+ typedef A Type;
+ static const Enum kE = Enum::A;
+};
+
+struct B
+{
+ typedef B Type;
+ static const Enum kE = Enum::B;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+ let e = B::Type::kE;
+ outputBuffer[index] = int(e);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/tuple.slang b/tests/experiments/generic/tuple.slang
new file mode 100644
index 000000000..e5362ed6e
--- /dev/null
+++ b/tests/experiments/generic/tuple.slang
@@ -0,0 +1,55 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Tuple experiment.
+
+Works.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+struct Tuple2<T0, T1>
+{
+ T0 _0;
+ T1 _1;
+};
+
+struct Tuple3<T0, T1, T2>
+{
+ T0 _0;
+ T1 _1;
+ T2 _2;
+};
+
+Tuple2<T0, T1> makeTuple<T0, T1>(T0 t0, T1 t1)
+{
+ Tuple2<T0, T1> t;
+ t._0 = t0;
+ t._1 = t1;
+ return t;
+}
+
+Tuple3<T0, T1, T2> makeTuple<T0, T1, T2>(T0 t0, T1 t1, T2 t2)
+{
+ Tuple3<T0, T1, T2> t;
+ t._0 = t0;
+ t._1 = t1;
+ t._2 = t2;
+ return t;
+}
+
+int doThing(Tuple2<float, int> v)
+{
+ return v._0 + v._1;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ let t = makeTuple(index + 1.0f, index - 1);
+
+ outputBuffer[index] = doThing(t);
+}
+
diff --git a/tests/experiments/generic/type-inference-2.slang b/tests/experiments/generic/type-inference-2.slang
new file mode 100644
index 000000000..5108ec90d
--- /dev/null
+++ b/tests/experiments/generic/type-inference-2.slang
@@ -0,0 +1,26 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic functions with type inference.
+
+Does work.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+T getFirst<T>(vector<T, 4> val)
+{
+ return val.x;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float4 values = { 1, 2, 3, 4 };
+
+ let val = getFirst(values);
+
+ outputBuffer[index] = val;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-inference-3.slang b/tests/experiments/generic/type-inference-3.slang
new file mode 100644
index 000000000..82691d8c3
--- /dev/null
+++ b/tests/experiments/generic/type-inference-3.slang
@@ -0,0 +1,29 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic functions with type inference.
+
+.slang(5): internal error 99999: unimplemented feature in Slang compiler: swizzle on vector of unknown size
+ return val.x;
+
+Sort of plausible and in general. But .x would work for any size of vector.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+T getFirst<T, let N : int>(vector<T, N> val)
+{
+ return val.x;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float4 values = { 1, 2, 3, 4 };
+
+ let val = getFirst(values);
+
+ outputBuffer[index] = val;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-inference-4.slang b/tests/experiments/generic/type-inference-4.slang
new file mode 100644
index 000000000..cee29e440
--- /dev/null
+++ b/tests/experiments/generic/type-inference-4.slang
@@ -0,0 +1,30 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic functions with type inference.
+
+Fails in glslang.
+
+glslang: .slang(13): error : '[' : vector index out of range '2'
+glslang: .slang(13): error : '' : compilation terminated
+glslang: note : ERROR: 2 compilation errors. No code generated.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+T getFirst<T, let N : int>(vector<T, N> val)
+{
+ return val[2];
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float2 values = { 1, 2 };
+
+ let val = getFirst(values);
+
+ outputBuffer[index] = val;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-inference-5.slang b/tests/experiments/generic/type-inference-5.slang
new file mode 100644
index 000000000..8254f6065
--- /dev/null
+++ b/tests/experiments/generic/type-inference-5.slang
@@ -0,0 +1,26 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic functions with type inference.
+
+Works(!) (even though any swizzle does not)
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+T getFirst<T, let N : int>(vector<T, N> val)
+{
+ return val[2];
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float4 values = { 1, 2, 3, 4 };
+
+ let val = getFirst(values);
+
+ outputBuffer[index] = val;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-inference.slang b/tests/experiments/generic/type-inference.slang
new file mode 100644
index 000000000..5c8d7efe7
--- /dev/null
+++ b/tests/experiments/generic/type-inference.slang
@@ -0,0 +1,33 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic functions with type inference.
+
+.slang(17): error 39999: could not specialize generic for arguments of type (float[4])
+ let val = get0(values);
+ ^
+.slang(5): note 39999: see declaration of func get0<T>(T[4]) -> T
+
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+T get0<T>(T values[4])
+{
+ return values[0];
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float values[] = { 1, 2, 3, 4};
+
+ // NOTE if we specify T then this works. Ie
+ // let val = get0<float>(values);
+
+ let val = get0(values);
+
+ outputBuffer[index] = val;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-to-value-2.slang b/tests/experiments/generic/type-to-value-2.slang
new file mode 100644
index 000000000..1be4e59fc
--- /dev/null
+++ b/tests/experiments/generic/type-to-value-2.slang
@@ -0,0 +1,48 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+Lets see if we can do something with a built in type
+
+Doesn't work because
+
+error 30052: invalid swizzle pattern 'getType' on type 'int'
+ let type = i.getType();
+
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Type
+{
+ Unknown,
+ Float,
+ Int,
+};
+
+interface IHasType
+{
+ Type getType()
+};
+
+extension int : IHasType
+{
+ Type getType() { return Type::Int; }
+};
+
+extension float : IHasType
+{
+ Type getType() { return Type::Float; }
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ int i;
+ let type = i.getType();
+
+ outputBuffer[dispatchThreadID.x] = int(type);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-to-value-3.slang b/tests/experiments/generic/type-to-value-3.slang
new file mode 100644
index 000000000..773c0fe5c
--- /dev/null
+++ b/tests/experiments/generic/type-to-value-3.slang
@@ -0,0 +1,43 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+This does work.
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Type
+{
+ Unknown,
+ Float,
+ Int,
+};
+
+interface IHasType
+{
+ static Type getType();
+};
+
+extension int : IHasType
+{
+ static Type getType() { return Type::Int; }
+};
+
+extension float : IHasType
+{
+ static Type getType() { return Type::Float; }
+};
+
+Type getType<T : IHasType>() { return T::getType(); }
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ let type = getType<float>();
+
+ outputBuffer[dispatchThreadID.x] = int(type);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-to-value-4.slang b/tests/experiments/generic/type-to-value-4.slang
new file mode 100644
index 000000000..986fffaf7
--- /dev/null
+++ b/tests/experiments/generic/type-to-value-4.slang
@@ -0,0 +1,49 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+This doesn't work - it produces dynamic dispatch code, that is uncompilable because cases
+are missing.
+
+.slang(24): error : control reaches end of non-void function [-Wreturn-type]
+dxc: note : }
+dxc: note : ^
+
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A, B
+};
+
+interface IGetE
+{
+ static Enum getE();
+};
+
+struct A : IGetE
+{
+ static Enum getE() { return Enum::A; }
+};
+
+struct B : IGetE
+{
+ static Enum getE() { return Enum::B; }
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ // Err.. even though IGetE doesn't require an instanciation, not clear how to set it. So lets try with instanciation
+ B b;
+ IGetE g = b;
+
+ let e = g.getE();
+
+ outputBuffer[dispatchThreadID.x] = int(e);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-to-value-5.slang b/tests/experiments/generic/type-to-value-5.slang
new file mode 100644
index 000000000..ce3271d47
--- /dev/null
+++ b/tests/experiments/generic/type-to-value-5.slang
@@ -0,0 +1,56 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+Here we try to associate by having a value defined on the type, and then set the type
+on the associated type.
+
+Doesn't work because ...
+
+.slang(29): error 30027: 'Type' is not a member of '.This'.
+ return e::Type::kE;
+
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A, B
+};
+
+interface IHasType
+{
+ associatedtype Type;
+};
+
+// This is a little perverse, because I'm defining as an associated type that is
+// the same as itself
+struct A : IHasType
+{
+ typedef A Type;
+ static const Enum kE = Enum::A;
+};
+
+struct B : IHasType
+{
+ typedef B Type;
+ static const Enum kE = Enum::B;
+};
+
+Enum getType(IHasType e)
+{
+ return e::Type::kE;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ B b;
+ let e = getType(b);
+
+ outputBuffer[dispatchThreadID.x] = int(e);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-to-value-6.slang b/tests/experiments/generic/type-to-value-6.slang
new file mode 100644
index 000000000..fa7b05cbd
--- /dev/null
+++ b/tests/experiments/generic/type-to-value-6.slang
@@ -0,0 +1,49 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+Here we try to associate by having a value defined on the type, and then set the type
+on the associated type.
+
+Doesn't work because ...
+
+.slang(34): error 30027: 'kE' is not a member of 'overload group'.
+ let e = B::Type::kE;
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A, B
+};
+
+interface IHasType
+{
+ associatedtype Type;
+};
+
+// This is a little perverse, because I'm defining as an associated type that is
+// the same as itself
+struct A : IHasType
+{
+ typedef A Type;
+ static const Enum kE = Enum::A;
+};
+
+struct B : IHasType
+{
+ typedef B Type;
+ static const Enum kE = Enum::B;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ let e = B::Type::kE;
+
+ outputBuffer[dispatchThreadID.x] = int(e);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-to-value.slang b/tests/experiments/generic/type-to-value.slang
new file mode 100644
index 000000000..65442212f
--- /dev/null
+++ b/tests/experiments/generic/type-to-value.slang
@@ -0,0 +1,33 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+This works.
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A,
+ B,
+};
+
+struct A
+{
+ static const Enum kE = Enum::A;
+};
+
+struct B
+{
+ static const Enum kE = Enum::B;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ outputBuffer[dispatchThreadID.x] = int(B::kE);
+} \ No newline at end of file