From 05f9aaf6a4ef246dcf89b00000a8e59e90c47662 Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 13 Sep 2022 18:58:05 -0700 Subject: Allow interface requirements to reference to the interface type itself. (#2398) * Allow interface requirements to reference to the interface type itself. * add comment explaining the change. Co-authored-by: Yong He --- source/slang/slang-check-expr.cpp | 2 - source/slang/slang-syntax.cpp | 46 ++++++++++++++-------- source/slang/slang.natvis | 11 ++++++ tests/bugs/interface-type-self-ref.slang | 32 +++++++++++++++ .../interface-type-self-ref.slang.expected.txt | 5 +++ 5 files changed, 77 insertions(+), 19 deletions(-) create mode 100644 tests/bugs/interface-type-self-ref.slang create mode 100644 tests/bugs/interface-type-self-ref.slang.expected.txt diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index 4d55669e2..b988fac60 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -157,8 +157,6 @@ namespace Slang openedType->originalInterfaceType = expr->type.type; openedType->originalInterfaceDeclRef = interfaceDeclRef; - DeclRef substDeclRef = openedType->getSpecializedInterfaceDeclRef(); - ExtractExistentialValueExpr* openedValue = m_astBuilder->create(); openedValue->declRef = varDeclRef; openedValue->type = QualType(openedType); diff --git a/source/slang/slang-syntax.cpp b/source/slang/slang-syntax.cpp index 9a7200e9d..5b4b61849 100644 --- a/source/slang/slang-syntax.cpp +++ b/source/slang/slang-syntax.cpp @@ -838,28 +838,40 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt // Otherwise, check if we are trying to apply // a this-type substitution to the given interface // - for(auto s = substsToApply; s; s = s->outer) + // Note: We want to skip the ThisTypeSubstitution that specializes + // declToSpecialize itself (when declToSpecialize is an interface + // decl and the subst specializes it), and only pull the + // ThisTypeSubstitution when the decl is referencing a child of + // the interface decl being specialized. This is because + // by default an interface declref type is a "free" existential + // type that shouldn't be specialized by someone else, unless + // there is an "implicit" ThisType reference preceeding a child + // reference. + if (declToSpecialize != ancestorInterfaceDecl) { - auto appThisTypeSubst = as(s); - if(!appThisTypeSubst) - continue; + for (auto s = substsToApply; s; s = s->outer) + { + auto appThisTypeSubst = as(s); + if (!appThisTypeSubst) + continue; - if(appThisTypeSubst->interfaceDecl != ancestorInterfaceDecl) - continue; + if (appThisTypeSubst->interfaceDecl != ancestorInterfaceDecl) + continue; - int diff = 0; - auto restSubst = specializeSubstitutions( - astBuilder, - ancestorInterfaceDecl->parentDecl, - substsToSpecialize, - substsToApply, - &diff); + int diff = 0; + auto restSubst = specializeSubstitutions( + astBuilder, + ancestorInterfaceDecl->parentDecl, + substsToSpecialize, + substsToApply, + &diff); - ThisTypeSubstitution* firstSubst = astBuilder->getOrCreateThisTypeSubstitution( - ancestorInterfaceDecl, appThisTypeSubst->witness, restSubst); + ThisTypeSubstitution* firstSubst = astBuilder->getOrCreateThisTypeSubstitution( + ancestorInterfaceDecl, appThisTypeSubst->witness, restSubst); - (*ioDiff)++; - return firstSubst; + (*ioDiff)++; + return firstSubst; + } } } } diff --git a/source/slang/slang.natvis b/source/slang/slang.natvis index 4d5bad2d3..6c8f15ec9 100644 --- a/source/slang/slang.natvis +++ b/source/slang/slang.natvis @@ -239,6 +239,7 @@ (Slang::AndTypeExpr*)&astNodeType (Slang::ModifiedTypeExpr*)&astNodeType (Slang::PointerTypeExpr*)&astNodeType + type (Slang::Expr*)this,nd @@ -477,4 +478,14 @@ members + + {astNodeType} + + (Slang::ConstantIntVal*)&astNodeType + (Slang::PolynomialIntVal*)&astNodeType + (Slang::GenericParamIntVal*)&astNodeType + (Slang::DeclaredSubtypeWitness*)&astNodeType + (Slang::TransitiveSubtypeWitness*)&astNodeType + + \ No newline at end of file diff --git a/tests/bugs/interface-type-self-ref.slang b/tests/bugs/interface-type-self-ref.slang new file mode 100644 index 000000000..e3b1fe7cc --- /dev/null +++ b/tests/bugs/interface-type-self-ref.slang @@ -0,0 +1,32 @@ +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj -output-using-type + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer +RWStructuredBuffer outputBuffer; + +interface IFoo +{ + int compute(out IFoo param); +} + +struct Impl : IFoo +{ + int compute(out IFoo param) + { + param = this; + return 0; + } +} + +int f(IFoo p) +{ + IFoo r; + return p.compute(r); +} + +[numthreads(4, 1, 1)] +void computeMain(int3 dispatchThreadID: SV_DispatchThreadID) +{ + int index = dispatchThreadID.x; + Impl impl; + outputBuffer[index] = f(impl); +} diff --git a/tests/bugs/interface-type-self-ref.slang.expected.txt b/tests/bugs/interface-type-self-ref.slang.expected.txt new file mode 100644 index 000000000..b9efb5a97 --- /dev/null +++ b/tests/bugs/interface-type-self-ref.slang.expected.txt @@ -0,0 +1,5 @@ +type: int32_t +0 +0 +0 +0 -- cgit v1.2.3