Skip to content

Commit 7724675

Browse files
committed
Canonicalize generic app member decl refs
1 parent 49e3775 commit 7724675

3 files changed

Lines changed: 22 additions & 98 deletions

File tree

source/slang/slang-ast-builder.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,21 @@ class ASTBuilder : public RefObject
344344
{
345345
return DeclRef<T>(getMemberDeclRef(parentMemberDeclRef->getParent(), memberDecl));
346346
}
347+
else if (auto genericAppDeclRef = as<GenericAppDeclRef>(parent.declRefBase))
348+
{
349+
// For a generic `G<T>`, a direct member declared under `G` should be represented as
350+
// `GenericAppDeclRef(G, T, member)` instead of
351+
// `MemberDeclRef(GenericAppDeclRef(G, T, G::Inner), member)`. That keeps decl refs
352+
// canonical so generic Val rewriting can remain a simple operand walk.
353+
if (memberDecl->parentDecl == genericAppDeclRef->getGenericDecl())
354+
{
355+
return getGenericAppDeclRef(
356+
DeclRef<GenericDecl>(genericAppDeclRef->getGenericDeclRef()),
357+
genericAppDeclRef->getArgs(),
358+
memberDecl)
359+
.template as<T>();
360+
}
361+
}
347362
else if (auto lookupDeclRef = as<LookupDeclRef>(parent.declRefBase))
348363
{
349364
// Handle some specicial case rules due to the way some of our builtin decls are

source/slang/slang-ast-copy.cpp

Lines changed: 0 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -146,103 +146,6 @@ Decl* ASTCopier::rewriteDecl(Decl* decl)
146146

147147
Val* ASTCopier::rewriteValImpl(Val* val)
148148
{
149-
if (auto memberDeclRef = as<MemberDeclRef>(val))
150-
{
151-
auto oldMemberDecl = memberDeclRef->getDecl();
152-
auto newMemberDecl = rewriteDecl(oldMemberDecl);
153-
if (newMemberDecl != oldMemberDecl)
154-
{
155-
// `MemberDeclRef` stores a substitution context as its parent operand. Checked type
156-
// expressions for nested generic constraints can use an enclosing specialized type,
157-
// e.g. `InlineVector<T, N>`, as that context while the constraint decl itself is being
158-
// copied into a standalone generic. Rebuild through `getParent()` so the copied member
159-
// is paired with the nearest rewritten declaration parent instead of a source-side
160-
// context that only belonged to the checked source graph.
161-
auto newParentDeclRef = rewriteDeclRef(memberDeclRef->getParent());
162-
if (newParentDeclRef && newMemberDecl->isChildOf(newParentDeclRef->getDecl()))
163-
return m_context.astBuilder->getMemberDeclRef(newParentDeclRef, newMemberDecl)
164-
.declRefBase;
165-
}
166-
}
167-
168-
if (auto genericAppDeclRef = as<GenericAppDeclRef>(val))
169-
{
170-
auto oldGenericDeclRef = genericAppDeclRef->getGenericDeclRef();
171-
auto newGenericDeclRef = rewriteDeclRef(oldGenericDeclRef);
172-
173-
List<Val*> newArgs;
174-
bool changed = newGenericDeclRef != oldGenericDeclRef;
175-
for (auto arg : genericAppDeclRef->getArgs())
176-
{
177-
auto newArg = rewriteVal(arg);
178-
changed = changed || newArg != arg;
179-
newArgs.add(newArg);
180-
}
181-
182-
auto oldInnerDecl = genericAppDeclRef->getDecl();
183-
auto newInnerDecl = rewriteDecl(oldInnerDecl);
184-
changed = changed || newInnerDecl != oldInnerDecl;
185-
186-
if (!changed)
187-
return val;
188-
189-
if (!newGenericDeclRef || !newInnerDecl)
190-
{
191-
SLANG_UNEXPECTED("ASTCopier could not coherently rewrite a GenericAppDeclRef.");
192-
}
193-
194-
if (!newInnerDecl->isChildOf(newGenericDeclRef->getDecl()))
195-
{
196-
auto oldGenericDecl =
197-
oldGenericDeclRef ? as<GenericDecl>(oldGenericDeclRef->getDecl()) : nullptr;
198-
if (oldGenericDecl && oldInnerDecl == oldGenericDecl->inner)
199-
{
200-
// `ITensor<Dimension>` inside an interface default method applies the original
201-
// generic interface type constructor to an argument from the copied generic
202-
// environment. The generic head is not itself being copied here; only the argument
203-
// values need rewriting.
204-
newGenericDeclRef = oldGenericDeclRef;
205-
newInnerDecl = oldInnerDecl;
206-
}
207-
else if (auto oldGenericLookup = as<LookupDeclRef>(oldGenericDeclRef))
208-
{
209-
// Re-resolve looked-up generic members through the rewritten lookup source/witness.
210-
// Interface default methods can reference generic requirements through a
211-
// LookupDeclRef; after copying the enclosing signature, the old looked-up inner
212-
// declaration is no longer a child of the rewritten generic parent, so resolve the
213-
// corresponding lookup in the copied environment before rebuilding the
214-
// GenericAppDeclRef.
215-
auto innerLookupDeclRef = m_context.astBuilder->getLookupDeclRef(
216-
oldGenericLookup->getLookupSource(),
217-
oldGenericLookup->getWitness(),
218-
oldInnerDecl);
219-
auto rewrittenInnerLookup = rewriteDeclRef(innerLookupDeclRef);
220-
if (rewrittenInnerLookup.declRefBase)
221-
{
222-
if (auto resolvedInnerDeclRef =
223-
as<DeclRefBase>(rewrittenInnerLookup.declRefBase->resolve()))
224-
{
225-
newInnerDecl = resolvedInnerDeclRef->getDecl();
226-
}
227-
else
228-
{
229-
newInnerDecl = rewrittenInnerLookup.getDecl();
230-
}
231-
}
232-
}
233-
}
234-
235-
if (!newInnerDecl->isChildOf(newGenericDeclRef->getDecl()))
236-
{
237-
SLANG_UNEXPECTED("ASTCopier could not coherently rewrite a GenericAppDeclRef.");
238-
}
239-
240-
return m_context.astBuilder->getGenericAppDeclRef(
241-
DeclRef<GenericDecl>(newGenericDeclRef),
242-
newArgs.getArrayView(),
243-
newInnerDecl);
244-
}
245-
246149
ValNodeDesc desc;
247150
desc.type = val->getClass();
248151

@@ -386,7 +289,6 @@ GenericSignatureCopier::GenericSignatureCopier(
386289
, m_destGenericDecl(destGenericDecl)
387290
, m_outGenericArgs(outGenericArgs)
388291
{
389-
m_astCopier.mapDecl(sourceGenericDecl, destGenericDecl);
390292
m_astCopier.getContext().allowDroppingWitnessTables = true;
391293
}
392294

source/slang/slang-ast-decl-ref.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,13 @@ DeclRefBase* GenericAppDeclRef::_substituteImplOverride(
477477
substGenericDeclRef,
478478
substArgs.getArrayView(),
479479
getDecl());
480+
else if (getDecl() == getGenericDecl()->inner)
481+
{
482+
// If substitution rewrites the generic declaration reference itself, the old primary
483+
// inner declaration is no longer owned by the substituted generic. Use the substituted
484+
// generic's primary inner declaration, matching `_resolveImplOverride`.
485+
return astBuilder->getGenericAppDeclRef(substGenericDeclRef, substArgs.getArrayView());
486+
}
480487
else
481488
{
482489
// If decl is no longer the child of the new parent, it's most likely due to

0 commit comments

Comments
 (0)