Skip to content

Commit 4b284da

Browse files
committedJan 13, 2018
Support nested generics
fixes shader-slang#362
1 parent df6eeb9 commit 4b284da

19 files changed

+544
-215
lines changed
 

‎source/slang/check.cpp

+54-30
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)
@@ -1287,16 +1289,34 @@ namespace Slang
12871289
varDecl->initExpr = initExpr;
12881290
}
12891291

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

13021322
void checkDecl(Decl* decl)
@@ -1343,6 +1363,7 @@ namespace Slang
13431363
{
13441364
// check the type being inherited from
13451365
auto base = inheritanceDecl->base;
1366+
CheckConstraintSubType(base);
13461367
base = TranslateTypeNode(base);
13471368
inheritanceDecl->base = base;
13481369

@@ -1677,18 +1698,18 @@ namespace Slang
16771698
// An associated type requirement should be allowed
16781699
// to be satisfied by any type declaration:
16791700
// a typedef, a `struct`, etc.
1680-
auto checkSubTypeMember = [&](DeclRef<AggTypeDecl> subStructTypeDeclRef) -> bool
1701+
auto checkSubTypeMember = [&](DeclRef<ContainerDecl> subStructTypeDeclRef) -> bool
16811702
{
16821703
EnsureDecl(subStructTypeDeclRef.getDecl());
16831704
// this is a sub type (e.g. nested struct declaration) in an aggregate type
16841705
// check if this sub type declaration satisfies the constraints defined by the associated type
16851706
if (auto requiredTypeDeclRef = requiredMemberDeclRef.As<AssocTypeDecl>())
16861707
{
16871708
bool conformance = true;
1688-
auto inheritanceReqDeclRefs = getMembersOfType<InheritanceDecl>(requiredTypeDeclRef);
1709+
auto inheritanceReqDeclRefs = getMembersOfType<TypeConstraintDecl>(requiredTypeDeclRef);
16891710
for (auto inheritanceReqDeclRef : inheritanceReqDeclRefs)
16901711
{
1691-
auto interfaceDeclRefType = inheritanceReqDeclRef.getDecl()->base.type.As<DeclRefType>();
1712+
auto interfaceDeclRefType = inheritanceReqDeclRef.getDecl()->getSup().type.As<DeclRefType>();
16921713
SLANG_ASSERT(interfaceDeclRefType);
16931714
auto interfaceDeclRef = interfaceDeclRefType->declRef.As<InterfaceDecl>();
16941715
SLANG_ASSERT(interfaceDeclRef);
@@ -1744,20 +1765,22 @@ namespace Slang
17441765
// check if the specified type satisfies the constraints defined by the associated type
17451766
if (auto requiredTypeDeclRef = requiredMemberDeclRef.As<AssocTypeDecl>())
17461767
{
1747-
auto constraintList = getMembersOfType<InheritanceDecl>(requiredTypeDeclRef);
1748-
if (constraintList.Count())
1768+
auto declRefType = GetType(typedefDeclRef)->GetCanonicalType()->As<DeclRefType>();
1769+
if (!declRefType)
1770+
return false;
1771+
1772+
if (auto genTypeParamDeclRef = declRefType->declRef.As<GenericTypeParamDecl>())
17491773
{
1750-
auto declRefType = GetType(typedefDeclRef)->GetCanonicalType()->As<DeclRefType>();
1751-
if (!declRefType)
1752-
return false;
1774+
// TODO: check generic type parameter satisfies constraints
1775+
return true;
1776+
}
1777+
17531778

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

1758-
return checkSubTypeMember(structTypeDeclRef);
1759-
}
1760-
return true;
1783+
return checkSubTypeMember(containerDeclRef);
17611784
}
17621785
}
17631786
// Default: just assume that thing aren't being satisfied.
@@ -2496,6 +2519,7 @@ namespace Slang
24962519
// TODO: This needs to bottleneck through the common variable checks
24972520

24982521
para->type = CheckUsableType(para->type);
2522+
24992523
if (para->type.Equals(getSession()->getVoidType()))
25002524
{
25012525
if (!isRewriteMode())
@@ -6154,7 +6178,6 @@ namespace Slang
61546178
return expr;
61556179

61566180
expr->type = QualType(getSession()->getErrorType());
6157-
61586181
auto lookupResult = lookUp(
61596182
getSession(),
61606183
this, expr->name, expr->scope);
@@ -6983,16 +7006,17 @@ namespace Slang
69837006
subst->genericDecl = genericDecl;
69847007
subst->outer = parentSubst.genericSubstitutions;
69857008
resultSubst.genericSubstitutions = subst;
6986-
7009+
SubstitutionSet outerSubst = resultSubst;
7010+
outerSubst.genericSubstitutions = outerSubst.genericSubstitutions?outerSubst.genericSubstitutions->outer:nullptr;
69877011
for( auto mm : genericDecl->Members )
69887012
{
69897013
if( auto genericTypeParamDecl = mm.As<GenericTypeParamDecl>() )
69907014
{
6991-
subst->args.Add(DeclRefType::Create(session, makeDeclRef(genericTypeParamDecl.Ptr())));
7015+
subst->args.Add(DeclRefType::Create(session, DeclRef<Decl>(genericTypeParamDecl.Ptr(), outerSubst)));
69927016
}
69937017
else if( auto genericValueParamDecl = mm.As<GenericValueParamDecl>() )
69947018
{
6995-
subst->args.Add(new GenericParamIntVal(makeDeclRef(genericValueParamDecl.Ptr())));
7019+
subst->args.Add(new GenericParamIntVal(DeclRef<GenericValueParamDecl>(genericValueParamDecl.Ptr(), outerSubst)));
69967020
}
69977021
}
69987022

@@ -7002,7 +7026,7 @@ namespace Slang
70027026
if (auto genericTypeConstraintDecl = mm.As<GenericTypeConstraintDecl>())
70037027
{
70047028
RefPtr<DeclaredSubtypeWitness> witness = new DeclaredSubtypeWitness();
7005-
witness->declRef = makeDeclRef(genericTypeConstraintDecl.Ptr());
7029+
witness->declRef = DeclRef<Decl>(genericTypeConstraintDecl.Ptr(), outerSubst);
70067030
witness->sub = genericTypeConstraintDecl->sub.type;
70077031
witness->sup = genericTypeConstraintDecl->sup.type;
70087032
subst->args.Add(witness);

‎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)
Please sign in to comment.