Skip to content

Commit eaf3d84

Browse files
committed
Using a visitor to systematically replace lookup scopes of generic function's return type expression.
fixes shader-slang#336 Add a `ReplaceScopeVisitor` to replace the scopes of the return type expression tree to use the generic decl's scope instead of module's scope after parser has determined the decl is a generic function header decl.
1 parent d55b56b commit eaf3d84

File tree

3 files changed

+70
-2
lines changed

3 files changed

+70
-2
lines changed

source/slang/parser.cpp

+38-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "compiler.h"
66
#include "lookup.h"
7+
#include "visitor.h"
78

89
namespace Slang
910
{
@@ -1099,6 +1100,40 @@ namespace Slang
10991100
}
11001101
}
11011102

1103+
// systematically replace all scopes in an expression tree
1104+
class ReplaceScopeVisitor : public ExprVisitor<ReplaceScopeVisitor>
1105+
{
1106+
public:
1107+
RefPtr<Scope> scope;
1108+
void visitDeclRefExpr(DeclRefExpr* expr)
1109+
{
1110+
expr->scope = scope;
1111+
}
1112+
void visitGenericAppExpr(GenericAppExpr * expr)
1113+
{
1114+
expr->FunctionExpr->accept(this, nullptr);
1115+
for (auto arg : expr->Arguments)
1116+
arg->accept(this, nullptr);
1117+
}
1118+
void visitIndexExpr(IndexExpr * expr)
1119+
{
1120+
expr->BaseExpression->accept(this, nullptr);
1121+
expr->IndexExpression->accept(this, nullptr);
1122+
}
1123+
void visitMemberExpr(MemberExpr * expr)
1124+
{
1125+
expr->BaseExpression->accept(this, nullptr);
1126+
expr->scope = scope;
1127+
}
1128+
void visitStaticMemberExpr(StaticMemberExpr * expr)
1129+
{
1130+
expr->BaseExpression->accept(this, nullptr);
1131+
expr->scope = scope;
1132+
}
1133+
void visitExpr(Expr* /*expr*/)
1134+
{}
1135+
};
1136+
11021137
static RefPtr<Decl> ParseFuncDeclHeader(
11031138
Parser* parser,
11041139
DeclaratorInfo const& declaratorInfo,
@@ -1114,8 +1149,9 @@ namespace Slang
11141149

11151150
// if return type is a DeclRef type, we need to update its scope to use this function decl's scope
11161151
// so that LookUp can find the generic type parameters declared after the function name
1117-
if (auto declRefRetType = declaratorInfo.typeSpec.As<DeclRefExpr>())
1118-
declRefRetType->scope = parser->currentScope;
1152+
ReplaceScopeVisitor replaceScopeVisitor;
1153+
replaceScopeVisitor.scope = parser->currentScope;
1154+
declaratorInfo.typeSpec->accept(&replaceScopeVisitor, nullptr);
11191155

11201156
decl->ReturnType = TypeExp(declaratorInfo.typeSpec);
11211157
auto parseFuncDeclHeaderInner = [&](GenericDecl *)

tests/compute/generics-syntax-2.slang

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//TEST(compute):COMPARE_COMPUTE:-xslang -use-ir
2+
//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out
3+
// Confirm that generics syntax can be used in user
4+
// code and generates valid output.
5+
6+
RWStructuredBuffer<float> outputBuffer;
7+
8+
struct GenStruct<T>
9+
{
10+
T x;
11+
};
12+
13+
GenStruct<T> test<T>(T val)
14+
{
15+
GenStruct<T> rs;
16+
rs.x = val;
17+
return rs;
18+
}
19+
20+
21+
[numthreads(4, 1, 1)]
22+
void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
23+
{
24+
uint tid = dispatchThreadID.x;
25+
float inVal = float(tid);
26+
GenStruct<float> outVal = test(inVal);
27+
outputBuffer[tid] = outVal.x;
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
0
2+
3F800000
3+
40000000
4+
40400000

0 commit comments

Comments
 (0)