Repository: shader-slang/slang (2026-04-15T17:21:34Z)

Issue:
Internal compiler error when using groupshared with interface-typed variables

## Issue Description

Declaring a `groupshared` variable with an interface type causes an internal compiler error (ICE 99999) during code emission on both SPIRV and HLSL targets. The compiler should either support this pattern or produce a clear diagnostic during semantic checking.

## Reproducer Code

```hlsl
interface IFoo
{
    float getValue();
}

struct ImplA : IFoo
{
    float v;
    float getValue() { return v; }
}

struct ImplB : IFoo
{
    float v;
    float getValue() { return v * 2.0; }
}

groupshared IFoo sharedVal;

RWStructuredBuffer<float> outputBuffer;

[numthreads(64, 1, 1)]
void computeMain(uint3 tid : SV_DispatchThreadID)
{
    if (tid.x == 0)
        sharedVal = ImplA(42.0);
    GroupMemoryBarrierWithGroupSync();
    outputBuffer[tid.x] = sharedVal.getValue();
}
```

**Command:**
```bash
slangc test.slang -target spirv -stage compute -entry computeMain -o /dev/null
```

## Expected Behavior

Either a clear diagnostic error during semantic checking (e.g., "groupshared variables cannot have interface types"), or correct compilation if the pattern is intended to be supported.

## Actual Behavior

SPIRV target:
```
(0): error 99999: Slang compilation aborted due to an exception of N5Slang13InternalErrorE:
unimplemented: Unhandled local inst in spirv-emit:
let  %1 : %2 = lookupWitness(%3, %IFoox5FgetValue)
```

HLSL target:
```
test.slang(24): internal error 99999: unimplemented feature in Slang compiler:
unexpected IR opcode during code emit
    outputBuffer[tid.x] = sharedVal.getValue();
                                            ^
```

Arrays of interface types (`groupshared IFoo arr[4]`) produce the same ICE.

Note: wrapping the interface in a struct (`groupshared struct { IFoo member; }`) compiles and generates correct dynamic dispatch code, suggesting the underlying mechanism is feasible.

## Additional Context

Test issue #10145 
Test PR #10143 




Discussion:

Patch:
diff --git a/source/slang/slang-ir-typeflow-specialize.cpp b/source/slang/slang-ir-typeflow-specialize.cpp
index 07ba721ddc..bbc386f809 100644
--- a/source/slang/slang-ir-typeflow-specialize.cpp
+++ b/source/slang/slang-ir-typeflow-specialize.cpp
@@ -2377,8 +2377,21 @@ struct TypeFlowSpecializationContext
                 auto valueInfo = as<IRPtrTypeBase>(addrInfo)->getValueType();
                 return valueInfo;
             }
-            else
-                return none(); // No info for the address
+
+            // If there is no type flow info for the address but the loaded type
+            // is an interface, enumerate all conforming types globally.
+            // This handles groupshared global variables (and arrays thereof)
+            // with interface types, where the address traces back to a module-scope
+            // global variable that type flow analysis cannot track.
+            if (auto interfaceType = as<IRInterfaceType>(loadInst->getDataType()))
+            {
+                if (!isComInterfaceType(interfaceType))
+                {
+                    return findGlobalTables(interfaceType);
+                }
+            }
+
+            return none();
         }
         else if (as<IRRWStructuredBufferLoad>(inst) || as<IRStructuredBufferLoad>(inst))
         {


Test patch:
diff --git a/tests/language-feature/dynamic-dispatch/diagnose-groupshared-interface.slang b/tests/language-feature/dynamic-dispatch/diagnose-groupshared-interface.slang
index 0444ebf901..968ec40add 100644
--- a/tests/language-feature/dynamic-dispatch/diagnose-groupshared-interface.slang
+++ b/tests/language-feature/dynamic-dispatch/diagnose-groupshared-interface.slang
@@ -1,15 +1,16 @@
-// Direct groupshared variables with interface types currently trigger an
-// ICE because the existential lowering passes do not handle groupshared-rate
-// variables. The existential layout is known after compilation, so this may
-// be a fixable limitation rather than a fundamental incompatibility.
-// Disabled until the fix lands. See https://github.com/shader-slang/slang/issues/10144
+// Direct groupshared variables with interface types.
+// Verifies that the type flow analysis properly handles loads from
+// interface-typed global variables by enumerating conforming types,
+// enabling dynamic dispatch without requiring struct wrapping.
+//
+// See https://github.com/shader-slang/slang/issues/10144
 //
 // The struct-wrapping workaround is validated by
 // groupshared-struct-with-interface.slang.
 
 // --- Scenario 1: Direct groupshared interface variable ---
-//DISABLE_TEST:SIMPLE(filecheck=CHK1): -target spirv -stage compute -entry scenario1
-//DISABLE_TEST:SIMPLE(filecheck=CHK1): -target hlsl -stage compute -entry scenario1
+//TEST:SIMPLE(filecheck=SPV1):-target spirv-asm -stage compute -entry scenario1
+//TEST:SIMPLE(filecheck=HLSL1):-target hlsl -stage compute -entry scenario1
 
 interface IValue
 {
@@ -32,21 +33,27 @@ groupshared IValue sharedVal;
 
 RWStructuredBuffer<float> outputBuffer;
 
+// SPV1: OpEntryPoint
+// HLSL1: groupshared
 [numthreads(64, 1, 1)]
 void scenario1(uint3 tid : SV_DispatchThreadID)
 {
     if (tid.x == 0)
         sharedVal = ScalarValue(42.0);
+    else if (tid.x == 1)
+        sharedVal = DoubleValue(10.0);
     GroupMemoryBarrierWithGroupSync();
     outputBuffer[tid.x] = sharedVal.get();
 }
 
 // --- Scenario 2: Groupshared array of interface-typed values ---
-//DISABLE_TEST:SIMPLE(filecheck=CHK2): -target spirv -stage compute -entry scenario2
-//DISABLE_TEST:SIMPLE(filecheck=CHK2): -target hlsl -stage compute -entry scenario2
+//TEST:SIMPLE(filecheck=SPV2):-target spirv-asm -stage compute -entry scenario2
+//TEST:SIMPLE(filecheck=HLSL2):-target hlsl -stage compute -entry scenario2
 
 groupshared IValue sharedArray[4];
 
+// SPV2: OpEntryPoint
+// HLSL2: groupshared
 [numthreads(4, 1, 1)]
 void scenario2(uint3 tid : SV_DispatchThreadID)
 {