Skip to content

Commit ef28f83

Browse files
committed
Substitute generic parameter decl refs
1 parent 7724675 commit ef28f83

2 files changed

Lines changed: 58 additions & 32 deletions

File tree

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

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,62 @@
88
namespace Slang
99
{
1010

11+
DeclRefBase* _getDeclRefFromVal(Val* val);
12+
13+
static DeclRefBase* _maybeSubstituteGenericParamDeclRef(
14+
DeclRefBase* paramDeclRef,
15+
SubstitutionSet subst,
16+
int* ioDiff)
17+
{
18+
// Type and value substitution can replace a generic parameter with an arbitrary value, but
19+
// decl-ref substitution can only preserve that replacement when the argument itself still has
20+
// declaration identity.
21+
auto paramDecl = paramDeclRef->getDecl();
22+
if (!isGenericParam(paramDecl))
23+
return nullptr;
24+
25+
auto outerGeneric = as<GenericDecl>(paramDecl->parentDecl);
26+
if (!outerGeneric)
27+
return nullptr;
28+
29+
auto genAppArgs = subst.findGenericAppDeclRef(outerGeneric);
30+
if (!genAppArgs)
31+
return nullptr;
32+
33+
auto args = genAppArgs->getArgs();
34+
Count argCount = args.getCount();
35+
Count argIndex = 0;
36+
for (auto member : outerGeneric->getDirectMemberDecls())
37+
{
38+
if (argIndex >= argCount)
39+
return nullptr;
40+
41+
if (member == paramDecl)
42+
{
43+
if (auto substDeclRef = _getDeclRefFromVal(args[argIndex]))
44+
{
45+
(*ioDiff)++;
46+
return substDeclRef;
47+
}
48+
return nullptr;
49+
}
50+
else if (isGenericParam(member))
51+
{
52+
argIndex++;
53+
}
54+
}
55+
56+
return nullptr;
57+
}
58+
1159
DeclRefBase* DirectDeclRef::_substituteImplOverride(
1260
ASTBuilder* astBuilder,
1361
SubstitutionSet subst,
1462
int* ioDiff)
1563
{
1664
SLANG_UNUSED(astBuilder);
17-
SLANG_UNUSED(subst);
18-
SLANG_UNUSED(ioDiff);
65+
if (auto substDeclRef = _maybeSubstituteGenericParamDeclRef(this, subst, ioDiff))
66+
return substDeclRef;
1967
return this;
2068
}
2169

source/slang/slang-check-decl.cpp

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5794,9 +5794,11 @@ bool SemanticsVisitor::doesGenericSignatureMatchRequirement(
57945794
//
57955795

57965796
auto getNonEmptyConstraintTargetDeclRef =
5797-
[&](NonEmptyPackConstraintDecl* constraintDecl) -> DeclRef<Decl>
5797+
[&](DeclRef<NonEmptyPackConstraintDecl> const& constraintDeclRef) -> DeclRef<Decl>
57985798
{
5799-
if (auto declRefExpr = as<DeclRefExpr>(constraintDecl->packExpr))
5799+
auto packExpr =
5800+
constraintDeclRef.substitute(m_astBuilder, constraintDeclRef.getDecl()->packExpr);
5801+
if (auto declRefExpr = packExpr.as<DeclRefExpr>())
58005802
return getDeclRef(m_astBuilder, declRefExpr);
58015803
return DeclRef<Decl>();
58025804
};
@@ -6044,30 +6046,6 @@ bool SemanticsVisitor::doesGenericSignatureMatchRequirement(
60446046
}
60456047
}
60466048

6047-
// Constraint checks below compare declarations after the required signature has been aligned to
6048-
// the satisfying signature. Some substituted decl refs still point at the original required
6049-
// binder, so treat paired generic parameters as equivalent when they occupy the same signature
6050-
// slot and the structural parameter checks above have already matched their kinds.
6051-
auto areGenericSignatureDeclRefsAligned = [&](DeclRef<Decl> requiredDeclRef,
6052-
DeclRef<Decl> satisfyingDeclRef) -> bool
6053-
{
6054-
if (requiredDeclRef.equals(satisfyingDeclRef))
6055-
return true;
6056-
if (!requiredDeclRef || !satisfyingDeclRef)
6057-
return false;
6058-
6059-
for (Index i = 0; i < requiredParams.getCount(); i++)
6060-
{
6061-
if (requiredParams[i].getDecl() == requiredDeclRef.getDecl() &&
6062-
satisfyingParams[i].getDecl() == satisfyingDeclRef.getDecl())
6063-
{
6064-
return true;
6065-
}
6066-
}
6067-
6068-
return false;
6069-
};
6070-
60716049
for (Index i = 0; i < requiredConstraints.getCount(); i++)
60726050
{
60736051
auto requiredMemberDeclRef = requiredConstraints[i];
@@ -6282,10 +6260,10 @@ bool SemanticsVisitor::doesGenericSignatureMatchRequirement(
62826260
return false;
62836261

62846262
auto requiredPackTarget =
6285-
getNonEmptyConstraintTargetDeclRef(specializedRequiredConstraintDeclRef.getDecl());
6263+
getNonEmptyConstraintTargetDeclRef(specializedRequiredConstraintDeclRef);
62866264
auto satisfyingPackTarget =
6287-
getNonEmptyConstraintTargetDeclRef(satisfyingConstraintDeclRef.getDecl());
6288-
if (!areGenericSignatureDeclRefsAligned(requiredPackTarget, satisfyingPackTarget))
6265+
getNonEmptyConstraintTargetDeclRef(satisfyingConstraintDeclRef);
6266+
if (!requiredPackTarget.equals(satisfyingPackTarget))
62896267
{
62906268
return false;
62916269
}
@@ -6316,7 +6294,7 @@ bool SemanticsVisitor::doesGenericSignatureMatchRequirement(
63166294
specializedRequiredConstraintDeclRef);
63176295
auto satisfyingPackTarget =
63186296
getPackCountConstraintTargetDeclRef(m_astBuilder, satisfyingConstraintDeclRef);
6319-
if (!areGenericSignatureDeclRefsAligned(requiredPackTarget, satisfyingPackTarget))
6297+
if (!requiredPackTarget.equals(satisfyingPackTarget))
63206298
{
63216299
return false;
63226300
}

0 commit comments

Comments
 (0)