summaryrefslogtreecommitdiffstats
path: root/tests/language-feature/extensions/extension-override.slang
blob: 30fa6496590db93523578b45ff669ed2d6f6355f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// Test that the override behavior around extensions and generic extensions works as expected.

// When there are multiple ways for a type to conform to an interface, then the expected behavior
// is that:
// 1. If the type directly implements an interface, use that conformance.
// 2. Otherwise, if there is a direct extension on the type that makes it conform to the interface, use that
//    extension.
// 3. Otherwise, if there is a generic extension that makes the type conform to the interface, use that.

//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK): -shaderobj
interface IFoo
{
    int getVal();
}

interface IBar
{
    int getValPlusOne();
}

interface IBaz
{
    int getValPlusTwo();
}

struct MyInt
{
    int v;
}

extension MyInt : IFoo
{
    int getVal() { return v; }
}

extension MyInt : IBar
{
    int getValPlusOne() { return this.getVal() + 2; }
}

extension<T: IFoo> T : IBar
{
    int getValPlusOne() { return this.getVal() + 1; }
}

int helper1<T:IBar>(T v){ return v.getValPlusOne();}
int helper2<T:IFoo>(T v){ return v.getValPlusOne();}

//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer
RWStructuredBuffer<int> outputBuffer;

[numthreads(1,1,1)]
void computeMain()
{
    MyInt v = {1};

    // CHECK: 3
    outputBuffer[0] = v.getValPlusOne(); // should call MyInt::ext::getValPlusOne();

    // CHECK: 3
    outputBuffer[1] = helper1(v); // should call MyInt::ext::getValPlusOne();

    // CHECK: 2
    outputBuffer[2] = helper2(v); // should call T::ext::getValPlusOne();
}