Skip to content

Commit d4dab2c

Browse files
authored
Merge pull request shader-slang#364 from csyonghe/assoctype
Support nested generics
2 parents df6eeb9 + 4d2086f commit d4dab2c

19 files changed

+515
-221
lines changed

source/slang/check.cpp

+61-36
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,15 @@ namespace Slang
120120
auto typeRepr = TranslateTypeNodeImpl(node);
121121
return ExtractTypeFromTypeRepr(typeRepr);
122122
}
123+
TypeExp TranslateTypeNodeForced(TypeExp const& typeExp)
124+
{
125+
auto typeRepr = TranslateTypeNodeImpl(typeExp.exp);
126+
127+
TypeExp result;
128+
result.exp = typeRepr;
129+
result.type = ExtractTypeFromTypeRepr(typeRepr);
130+
return result;
131+
}
123132
TypeExp TranslateTypeNode(TypeExp const& typeExp)
124133
{
125134
// HACK(tfoley): It seems that in some cases we end up re-checking
@@ -130,14 +139,7 @@ namespace Slang
130139
{
131140
return typeExp;
132141
}
133-
134-
135-
auto typeRepr = TranslateTypeNodeImpl(typeExp.exp);
136-
137-
TypeExp result;
138-
result.exp = typeRepr;
139-
result.type = ExtractTypeFromTypeRepr(typeRepr);
140-
return result;
142+
return TranslateTypeNodeForced(typeExp);
141143
}
142144

143145
RefPtr<DeclRefType> getExprDeclRefType(Expr * expr)
@@ -153,8 +155,6 @@ namespace Slang
153155
RefPtr<Expr> baseExpr,
154156
SourceLoc loc)
155157
{
156-
if (declRef.As<AssocTypeDecl>())
157-
getNewThisTypeSubst(declRef);
158158
if (baseExpr)
159159
{
160160
RefPtr<Expr> expr;
@@ -1287,16 +1287,34 @@ namespace Slang
12871287
varDecl->initExpr = initExpr;
12881288
}
12891289

1290+
// Fill in default substitutions for the 'subtype' part of a type constraint decl
1291+
void CheckConstraintSubType(TypeExp & typeExp)
1292+
{
1293+
if (auto sharedTypeExpr = typeExp.exp.As<SharedTypeExpr>())
1294+
{
1295+
if (auto declRefType = sharedTypeExpr->base->AsDeclRefType())
1296+
{
1297+
declRefType->declRef.substitutions = createDefaultSubstitutions(getSession(), declRefType->declRef.getDecl());
1298+
if (auto typetype = typeExp.exp->type.type.As<TypeType>())
1299+
typetype->type = declRefType;
1300+
}
1301+
}
1302+
}
1303+
12901304
void CheckGenericConstraintDecl(GenericTypeConstraintDecl* decl)
12911305
{
12921306
// TODO: are there any other validations we can do at this point?
12931307
//
12941308
// There probably needs to be a kind of "occurs check" to make
12951309
// sure that the constraint actually applies to at least one
12961310
// of the parameters of the generic.
1297-
1298-
decl->sub = TranslateTypeNode(decl->sub);
1299-
decl->sup = TranslateTypeNode(decl->sup);
1311+
if (decl->checkState == DeclCheckState::Unchecked)
1312+
{
1313+
decl->checkState = DeclCheckState::Checked;
1314+
CheckConstraintSubType(decl->sub);
1315+
decl->sub = TranslateTypeNodeForced(decl->sub);
1316+
decl->sup = TranslateTypeNodeForced(decl->sup);
1317+
}
13001318
}
13011319

13021320
void checkDecl(Decl* decl)
@@ -1343,6 +1361,7 @@ namespace Slang
13431361
{
13441362
// check the type being inherited from
13451363
auto base = inheritanceDecl->base;
1364+
CheckConstraintSubType(base);
13461365
base = TranslateTypeNode(base);
13471366
inheritanceDecl->base = base;
13481367

@@ -1677,18 +1696,18 @@ namespace Slang
16771696
// An associated type requirement should be allowed
16781697
// to be satisfied by any type declaration:
16791698
// a typedef, a `struct`, etc.
1680-
auto checkSubTypeMember = [&](DeclRef<AggTypeDecl> subStructTypeDeclRef) -> bool
1699+
auto checkSubTypeMember = [&](DeclRef<ContainerDecl> subStructTypeDeclRef) -> bool
16811700
{
16821701
EnsureDecl(subStructTypeDeclRef.getDecl());
16831702
// this is a sub type (e.g. nested struct declaration) in an aggregate type
16841703
// check if this sub type declaration satisfies the constraints defined by the associated type
16851704
if (auto requiredTypeDeclRef = requiredMemberDeclRef.As<AssocTypeDecl>())
16861705
{
16871706
bool conformance = true;
1688-
auto inheritanceReqDeclRefs = getMembersOfType<InheritanceDecl>(requiredTypeDeclRef);
1707+
auto inheritanceReqDeclRefs = getMembersOfType<TypeConstraintDecl>(requiredTypeDeclRef);
16891708
for (auto inheritanceReqDeclRef : inheritanceReqDeclRefs)
16901709
{
1691-
auto interfaceDeclRefType = inheritanceReqDeclRef.getDecl()->base.type.As<DeclRefType>();
1710+
auto interfaceDeclRefType = inheritanceReqDeclRef.getDecl()->getSup().type.As<DeclRefType>();
16921711
SLANG_ASSERT(interfaceDeclRefType);
16931712
auto interfaceDeclRef = interfaceDeclRefType->declRef.As<InterfaceDecl>();
16941713
SLANG_ASSERT(interfaceDeclRef);
@@ -1744,20 +1763,22 @@ namespace Slang
17441763
// check if the specified type satisfies the constraints defined by the associated type
17451764
if (auto requiredTypeDeclRef = requiredMemberDeclRef.As<AssocTypeDecl>())
17461765
{
1747-
auto constraintList = getMembersOfType<InheritanceDecl>(requiredTypeDeclRef);
1748-
if (constraintList.Count())
1766+
auto declRefType = GetType(typedefDeclRef)->GetCanonicalType()->As<DeclRefType>();
1767+
if (!declRefType)
1768+
return false;
1769+
1770+
if (auto genTypeParamDeclRef = declRefType->declRef.As<GenericTypeParamDecl>())
17491771
{
1750-
auto declRefType = GetType(typedefDeclRef)->GetCanonicalType()->As<DeclRefType>();
1751-
if (!declRefType)
1752-
return false;
1772+
// TODO: check generic type parameter satisfies constraints
1773+
return true;
1774+
}
1775+
17531776

1754-
auto structTypeDeclRef = declRefType->declRef.As<AggTypeDecl>();
1755-
if (!structTypeDeclRef)
1756-
return false;
1777+
auto containerDeclRef = declRefType->declRef.As<ContainerDecl>();
1778+
if (!containerDeclRef)
1779+
return false;
17571780

1758-
return checkSubTypeMember(structTypeDeclRef);
1759-
}
1760-
return true;
1781+
return checkSubTypeMember(containerDeclRef);
17611782
}
17621783
}
17631784
// Default: just assume that thing aren't being satisfied.
@@ -2496,6 +2517,7 @@ namespace Slang
24962517
// TODO: This needs to bottleneck through the common variable checks
24972518

24982519
para->type = CheckUsableType(para->type);
2520+
24992521
if (para->type.Equals(getSession()->getVoidType()))
25002522
{
25012523
if (!isRewriteMode())
@@ -6154,7 +6176,6 @@ namespace Slang
61546176
return expr;
61556177

61566178
expr->type = QualType(getSession()->getErrorType());
6157-
61586179
auto lookupResult = lookUp(
61596180
getSession(),
61606181
this, expr->name, expr->scope);
@@ -6970,29 +6991,34 @@ namespace Slang
69706991
Decl* decl,
69716992
SubstitutionSet parentSubst)
69726993
{
6994+
SubstitutionSet resultSubst = parentSubst;
6995+
if (auto interfaceDecl = dynamic_cast<InterfaceDecl*>(decl))
6996+
{
6997+
resultSubst.thisTypeSubstitution = new ThisTypeSubstitution();
6998+
}
69736999
auto dd = decl->ParentDecl;
69747000
if( auto genericDecl = dynamic_cast<GenericDecl*>(dd) )
69757001
{
69767002
// We don't want to specialize references to anything
69777003
// other than the "inner" declaration itself.
69787004
if(decl != genericDecl->inner)
6979-
return parentSubst;
7005+
return resultSubst;
69807006

6981-
SubstitutionSet resultSubst = parentSubst;
69827007
RefPtr<GenericSubstitution> subst = new GenericSubstitution();
69837008
subst->genericDecl = genericDecl;
69847009
subst->outer = parentSubst.genericSubstitutions;
69857010
resultSubst.genericSubstitutions = subst;
6986-
7011+
SubstitutionSet outerSubst = resultSubst;
7012+
outerSubst.genericSubstitutions = outerSubst.genericSubstitutions?outerSubst.genericSubstitutions->outer:nullptr;
69877013
for( auto mm : genericDecl->Members )
69887014
{
69897015
if( auto genericTypeParamDecl = mm.As<GenericTypeParamDecl>() )
69907016
{
6991-
subst->args.Add(DeclRefType::Create(session, makeDeclRef(genericTypeParamDecl.Ptr())));
7017+
subst->args.Add(DeclRefType::Create(session, DeclRef<Decl>(genericTypeParamDecl.Ptr(), outerSubst)));
69927018
}
69937019
else if( auto genericValueParamDecl = mm.As<GenericValueParamDecl>() )
69947020
{
6995-
subst->args.Add(new GenericParamIntVal(makeDeclRef(genericValueParamDecl.Ptr())));
7021+
subst->args.Add(new GenericParamIntVal(DeclRef<GenericValueParamDecl>(genericValueParamDecl.Ptr(), outerSubst)));
69967022
}
69977023
}
69987024

@@ -7002,15 +7028,14 @@ namespace Slang
70027028
if (auto genericTypeConstraintDecl = mm.As<GenericTypeConstraintDecl>())
70037029
{
70047030
RefPtr<DeclaredSubtypeWitness> witness = new DeclaredSubtypeWitness();
7005-
witness->declRef = makeDeclRef(genericTypeConstraintDecl.Ptr());
7031+
witness->declRef = DeclRef<Decl>(genericTypeConstraintDecl.Ptr(), outerSubst);
70067032
witness->sub = genericTypeConstraintDecl->sub.type;
70077033
witness->sup = genericTypeConstraintDecl->sup.type;
70087034
subst->args.Add(witness);
70097035
}
70107036
}
7011-
return resultSubst;
70127037
}
7013-
return parentSubst;
7038+
return resultSubst;
70147039
}
70157040

70167041
SubstitutionSet createDefaultSubstitutions(

source/slang/emit.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -4947,7 +4947,7 @@ emitDeclImpl(decl, nullptr);
49474947
{
49484948
auto type = inst->getType();
49494949

4950-
if(type->As<UniformParameterGroupType>())
4950+
if(type->As<UniformParameterGroupType>() && !type->As<ParameterBlockType>())
49514951
{
49524952
// TODO: we need to be careful here, because
49534953
// HLSL shader model 6 allows these as explicit
@@ -6341,7 +6341,7 @@ emitDeclImpl(decl, nullptr);
63416341
{
63426342
// We don't want to declare generic functions,
63436343
// because none of our targets actually support them.
6344-
if(func->genericDecl)
6344+
if(func->getGenericDecl())
63456345
return;
63466346

63476347
// We also don't want to emit declarations for operations
@@ -6453,7 +6453,7 @@ emitDeclImpl(decl, nullptr);
64536453
EmitContext* ctx,
64546454
IRFunc* func)
64556455
{
6456-
if(func->genericDecl)
6456+
if(func->getGenericDecl())
64576457
{
64586458
Emit("/* ");
64596459
emitIRFuncDecl(ctx, func);
@@ -7110,7 +7110,7 @@ emitDeclImpl(decl, nullptr);
71107110
// Don't emit anything for a generic function,
71117111
// since we only care about the types used by
71127112
// the actual specializations.
7113-
if (irFunc->genericDecl)
7113+
if (irFunc->getGenericDecl())
71147114
return;
71157115

71167116
emitIRUsedType(ctx, irFunc->getResultType());

source/slang/ir-insts.h

-10
Original file line numberDiff line numberDiff line change
@@ -315,16 +315,6 @@ struct IRWitnessTable : IRGlobalValue
315315
IRValueList<IRWitnessTableEntry> entries;
316316
};
317317

318-
// An abstract witness table is a global value that
319-
// represents an inheritance relationship that can't
320-
// be resolved to a witness table at IR-generation time.
321-
struct IRAbstractWitness : IRGlobalValue
322-
{
323-
RefPtr<SubtypeWitness> witness;
324-
DeclRef<Decl> subTypeDeclRef, supTypeDeclRef;
325-
};
326-
327-
328318
// Description of an instruction to be used for global value numbering
329319
struct IRInstKey
330320
{

0 commit comments

Comments
 (0)