Skip to content

Commit 11f4424

Browse files
Allow for implicit this expressions.
- When peforming ordinary lookup, if the container declaration for a scope is an aggregate type or `extension` decl, then use a "breadcrumb" to make sure that we use a `this` expression as the base of any resulting declaration reference - Add a test case for implicit `this` usage - Update constrained generic test case to use implicit `this` for member reference, as was originally intended
1 parent 42f1cff commit 11f4424

7 files changed

+106
-35
lines changed

source/slang/check.cpp

+34
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,16 @@ namespace Slang
196196
return derefExpr;
197197
}
198198

199+
RefPtr<Expr> createImplicitThisMemberExpr(
200+
Type* type,
201+
SourceLoc loc)
202+
{
203+
RefPtr<ThisExpr> expr = new ThisExpr();
204+
expr->type = type;
205+
expr->loc = loc;
206+
return expr;
207+
}
208+
199209
RefPtr<Expr> ConstructLookupResultExpr(
200210
LookupResultItem const& item,
201211
RefPtr<Expr> baseExpr,
@@ -228,6 +238,30 @@ namespace Slang
228238
}
229239
break;
230240

241+
case LookupResultItem::Breadcrumb::Kind::This:
242+
{
243+
// We expect a `this` to always come
244+
// at the start of a chain.
245+
SLANG_ASSERT(bb == nullptr);
246+
247+
// The member was looked up via a `this` expression,
248+
// so we need to create one here.
249+
if (auto extensionDeclRef = breadcrumb->declRef.As<ExtensionDecl>())
250+
{
251+
bb = createImplicitThisMemberExpr(
252+
GetTargetType(extensionDeclRef),
253+
loc);
254+
}
255+
else
256+
{
257+
auto type = DeclRefType::Create(getSession(), breadcrumb->declRef);
258+
bb = createImplicitThisMemberExpr(
259+
type,
260+
loc);
261+
}
262+
}
263+
break;
264+
231265
default:
232266
SLANG_UNREACHABLE("all cases handle");
233267
}

source/slang/lookup.cpp

+24-29
Original file line numberDiff line numberDiff line change
@@ -319,40 +319,35 @@ void DoLookupImpl(
319319
if(!containerDecl)
320320
continue;
321321

322-
// If the container is a generic, then we need to instantiate it
323-
// at the parameters themselves, so provide a fully-resolved
324-
// declaration reference for lookup.
325-
RefPtr<Substitutions> subst = nullptr;
326-
#if 1
327-
// Actually, the above rationale seems bogus. If we are looking
328-
// up from "inside" a generic declaration, we don't want to
329-
// get its members pre-specialized, right?
330-
#else
331-
if(auto parentGenericDecl = dynamic_cast<GenericDecl*>(containerDecl->ParentDecl))
322+
DeclRef<ContainerDecl> containerDeclRef =
323+
DeclRef<Decl>(containerDecl, nullptr).As<ContainerDecl>();
324+
325+
BreadcrumbInfo breadcrumb;
326+
BreadcrumbInfo* breadcrumbs = nullptr;
327+
328+
// Depending on the kind of container we are looking into,
329+
// we may need to insert something like a `this` expression
330+
// to resolve the lookup result.
331+
//
332+
// Note: We are checking for `AggTypeDeclBase` here, and not
333+
// just `AggTypeDecl`, because we want to catch `extension`
334+
// declarations as well.
335+
//
336+
if (auto aggTypeDeclRef = containerDeclRef.As<AggTypeDeclBase>())
332337
{
333-
subst = new Substitutions();
334-
subst->genericDecl = parentGenericDecl;
335-
336-
for( auto pp : parentGenericDecl->Members )
337-
{
338-
if( auto genericTypeParam = pp.As<GenericTypeParamDecl>() )
339-
{
340-
subst->args.Add(DeclRefType::Create(
341-
session,
342-
DeclRef<GenericTypeParamDecl>(genericTypeParam.Ptr(), nullptr)));
343-
}
344-
else if( auto genericValParam = pp.As<GenericValueParamDecl>() )
345-
{
346-
subst->args.Add(new GenericParamIntVal(DeclRef<GenericValueParamDecl>(genericValParam.Ptr(), nullptr)));
347-
}
348-
}
338+
breadcrumb.kind = LookupResultItem::Breadcrumb::Kind::This;
339+
breadcrumb.declRef = aggTypeDeclRef;
340+
breadcrumb.prev = nullptr;
341+
342+
breadcrumbs = &breadcrumb;
349343
}
350-
#endif
351344

352-
DeclRef<ContainerDecl> containerRef = DeclRef<Decl>(containerDecl, subst).As<ContainerDecl>();
345+
// Now perform "local" lookup in the context of the container,
346+
// as if we were looking up a member directly.
347+
//
353348
DoLocalLookupImpl(
354349
session,
355-
name, containerRef, request, result, nullptr);
350+
name, containerDeclRef, request, result, breadcrumbs);
356351
}
357352

358353
if (result.isValid())

source/slang/syntax.h

+6
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,12 @@ namespace Slang
859859
// lookup was able to find a member through type `U`
860860
// instead.
861861
Constraint,
862+
863+
// The lookup process considered a member of an
864+
// enclosing type as being in scope, so that any
865+
// reference to that member needs to use a `this`
866+
// expression as appropriate.
867+
This,
862868
};
863869

864870
// The kind of lookup step that was performed

tests/compute/generics-constrained.slang

+1-3
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ struct A : Helper
1717
// TODO: we should be able to reference a member variable here,
1818
// but the front-end isn't handling references through `this`
1919
// properly yet.
20-
// return a;
21-
22-
return 1.0f;
20+
return a;
2321
}
2422
};
2523

Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1+
0
12
3F800000
2-
3F800000
3-
3F800000
4-
3F800000
3+
40000000
4+
40400000
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//TEST(smoke,compute):COMPARE_COMPUTE:-xslang -use-ir
2+
//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out
3+
4+
// Access fields of a `struct` type from within a "method" by
5+
// using an implicit `this` expression.
6+
7+
struct A
8+
{
9+
float x;
10+
11+
float addWith(float y)
12+
{
13+
return x + y;
14+
}
15+
};
16+
17+
RWStructuredBuffer<float> outputBuffer : register(u0);
18+
19+
20+
float test(float inVal)
21+
{
22+
A a;
23+
a.x = inVal;
24+
return a.addWith(inVal*inVal);
25+
}
26+
27+
[numthreads(4, 1, 1)]
28+
void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
29+
{
30+
uint tid = dispatchThreadID.x;
31+
float inVal = float(tid);
32+
float outVal = test(inVal);
33+
outputBuffer[tid] = outVal;
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
0
2+
40000000
3+
40C00000
4+
41400000

0 commit comments

Comments
 (0)