From 3240799c00488858afc7eeac9d1dc479609a1040 Mon Sep 17 00:00:00 2001 From: kaizhangNV <149626564+kaizhangNV@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:49:00 -0500 Subject: Lower the priority of looking up the rank of scope (#5065) * Lower the priority of looking up the rank of scope In the previous change of #5060, we propose a way to resolve the ambiguous call when considering the scope of a function. But this rule should be considered as a low priority than "specialized candidate", aka. we should consider more "specialized candiate" first. * Count distance between reference site to declaration site Compare the candidate by calculating distance from reference site to declaration site via nearest common prefix in the scope tree. This will involve finding the common parent node of two child nodes and how sum the distance from the common parent to the two child nodes. * Change the priority higher than 'getOverloadRank' * Don't evaluate the scope rank algorithm on generic If the candidate is generic function, the function parameters won't be checked before 'CompareOverloadCandidates', so it will results in that the candidates this function could be invalid. We should not evaluate the distance algorithm in this case, instead we will evaluate later when the candidate is in flavor of Func or Expr since then all the type checks for the function will be done. --- tests/bugs/overload-ambiguous-1.slang | 65 +++++++++++++++++++++++++++++ tests/bugs/overload-ambiguous-2.slang | 67 ++++++++++++++++++++++++++++++ tests/bugs/overload-ambiguous.slang | 19 ++++++++- tests/diagnostics/overload-ambiguous.slang | 45 ++++++++++++++++++++ 4 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 tests/bugs/overload-ambiguous-1.slang create mode 100644 tests/bugs/overload-ambiguous-2.slang create mode 100644 tests/diagnostics/overload-ambiguous.slang (limited to 'tests') diff --git a/tests/bugs/overload-ambiguous-1.slang b/tests/bugs/overload-ambiguous-1.slang new file mode 100644 index 000000000..9f9c6e5bc --- /dev/null +++ b/tests/bugs/overload-ambiguous-1.slang @@ -0,0 +1,65 @@ +// https://github.com/shader-slang/slang/issues/4476 + +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-cuda -compute -shaderobj +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-cpu -compute -shaderobj +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-slang -compute -shaderobj +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-slang -compute -dx12 -shaderobj +//TEST(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-vk -compute -shaderobj + +//TEST_INPUT:ubuffer(data=[0 0 0], stride=4):out,name=outputBuffer +RWStructuredBuffer outputBuffer; + +namespace A1 +{ + uint func() + { + return 1u; + } + + namespace A2 + { + uint func() + { + return 2u; + } + + namespace A3 + { + uint func() + { + return 3u; + } + + uint test2() + { + return func(); // choose A3::func() + } + } + + namespace A4 + { + uint test() + { + return func(); // choose A2::func() + } + } + } +} + +[numthreads(1, 1, 1)] +[shader("compute")] +void computeMain(uint3 threadID: SV_DispatchThreadID) +{ + using namespace A1; + using namespace A1::A2; + using namespace A1::A2::A3; + using namespace A1::A2::A4; + outputBuffer[0] = test(); + // BUF: 2 + + outputBuffer[1] = func(); // choose the A1::func() + // BUF-NEXT: 1 + + outputBuffer[2] = test2(); + // BUF-NEXT: 3 +} diff --git a/tests/bugs/overload-ambiguous-2.slang b/tests/bugs/overload-ambiguous-2.slang new file mode 100644 index 000000000..46af9f091 --- /dev/null +++ b/tests/bugs/overload-ambiguous-2.slang @@ -0,0 +1,67 @@ +// https://github.com/shader-slang/slang/issues/4476 + +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-cuda -compute -shaderobj +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-cpu -compute -shaderobj +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-slang -compute -shaderobj +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-slang -compute -dx12 -shaderobj +//TEST(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-vk -compute -shaderobj + +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer +RWStructuredBuffer outputBuffer; + +namespace A +{ + struct Struct1 + { + uint data; + }; + + Struct1 myFunc(Struct1 inputS1) + { + Struct1 s1; + s1.data = inputS1.data + 2U; + return s1; + } +}; + + +A::Struct1 myFunc(A::Struct1 inputS1) +{ + A::Struct1 s1; + s1.data = inputS1.data + 5U; + return s1; +} + +namespace A +{ + struct Struct2 + { + Struct1 s1; + } + + Struct2 myFunc(Struct2 inputS2) + { + Struct2 s2; + // We want to cover a corner case in our compiler where: + // when looking up "myFunc", the compiler should find + // Struct1 A::myFunc(Struct1 inputS1) + // and it won't be ambiguous with the global "myFunc". + s2.s1 = myFunc(inputS2.s1); + return s2; + } +}; + +[numthreads(1, 1, 1)] +[shader("compute")] +void computeMain(uint3 threadID: SV_DispatchThreadID) +{ + using namespace A; + + Struct2<10> input = {threadID.x}; + + Struct2<20> output; + output = myFunc<10, 20>(input); + outputBuffer[0] = output.s1.data; + + // BUF: 2 +} diff --git a/tests/bugs/overload-ambiguous.slang b/tests/bugs/overload-ambiguous.slang index 1b74cb68c..d764f72e4 100644 --- a/tests/bugs/overload-ambiguous.slang +++ b/tests/bugs/overload-ambiguous.slang @@ -6,7 +6,7 @@ //TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-slang -compute -dx12 -shaderobj //TEST(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-vk -compute -shaderobj -//TEST_INPUT:ubuffer(data=[0 0], stride=4):out,name=outputBuffer +//TEST_INPUT:ubuffer(data=[0 0 0], stride=4):out,name=outputBuffer RWStructuredBuffer outputBuffer; @@ -34,7 +34,18 @@ struct DataObtainer } } -RWStructuredBuffer output; +uint myFunc(uint a) +{ + return a + 1u; +} + +__generic +uint myFunc(T a) +{ + uint b = __intCast(a); + return b + 2u; +} + [numthreads(1, 1, 1)] [shader("compute")] @@ -43,6 +54,10 @@ void computeMain(uint3 threadID: SV_DispatchThreadID) DataObtainer obtainer = {2u}; outputBuffer[0] = obtainer.getValue(); outputBuffer[1] = obtainer.getValue2(); + + uint a = 1u; + outputBuffer[2] = myFunc(a); // will call myFunc(uint) which more specialized // BUF: 2 // BUF-NEXT: 1 + // BUF-NEXT: 2 } diff --git a/tests/diagnostics/overload-ambiguous.slang b/tests/diagnostics/overload-ambiguous.slang new file mode 100644 index 000000000..0c8f7bd21 --- /dev/null +++ b/tests/diagnostics/overload-ambiguous.slang @@ -0,0 +1,45 @@ +// https://github.com/shader-slang/slang/issues/4476 + +//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK): +RWStructuredBuffer outputBuffer; + +namespace A1 +{ + uint func() + { + return 1u; + } + + namespace A2 + { + uint func() + { + return 2u; + } + } +} +namespace B1 +{ + uint func() + { + return 4u; + } +} + +[numthreads(1, 1, 1)] +[shader("compute")] +void computeMain(uint3 threadID: SV_DispatchThreadID) +{ + using namespace A1; + using namespace A1::A2; + using namespace B1; + using namespace C1; + + // Only A1::func() and B1::func() will cause ambiguity because the distance from + // the reference site to those two functions declaration are the same. + outputBuffer[0] = func(); + // CHECK-NOT: {{.*}}A2::func() -> uint + // CHECK: ambiguous call to 'func' with arguments of type () + // CHECK: candidate: func B1::func() -> uint + // CHECK: candidate: func A1::func() -> uint +} -- cgit v1.2.3