summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/slang/check.cpp97
-rw-r--r--source/slang/emit.cpp8
-rw-r--r--source/slang/ir-insts.h10
-rw-r--r--source/slang/ir.cpp285
-rw-r--r--source/slang/ir.h10
-rw-r--r--source/slang/lookup.cpp5
-rw-r--r--source/slang/lower-to-ir.cpp66
-rw-r--r--source/slang/mangle.cpp16
-rw-r--r--source/slang/mangle.h3
-rw-r--r--source/slang/parser.cpp32
-rw-r--r--source/slang/slang.natvis42
-rw-r--r--source/slang/syntax.cpp27
12 files changed, 380 insertions, 221 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp
index e7bd6d711..6c484b493 100644
--- a/source/slang/check.cpp
+++ b/source/slang/check.cpp
@@ -120,6 +120,15 @@ namespace Slang
auto typeRepr = TranslateTypeNodeImpl(node);
return ExtractTypeFromTypeRepr(typeRepr);
}
+ TypeExp TranslateTypeNodeForced(TypeExp const& typeExp)
+ {
+ auto typeRepr = TranslateTypeNodeImpl(typeExp.exp);
+
+ TypeExp result;
+ result.exp = typeRepr;
+ result.type = ExtractTypeFromTypeRepr(typeRepr);
+ return result;
+ }
TypeExp TranslateTypeNode(TypeExp const& typeExp)
{
// HACK(tfoley): It seems that in some cases we end up re-checking
@@ -130,14 +139,7 @@ namespace Slang
{
return typeExp;
}
-
-
- auto typeRepr = TranslateTypeNodeImpl(typeExp.exp);
-
- TypeExp result;
- result.exp = typeRepr;
- result.type = ExtractTypeFromTypeRepr(typeRepr);
- return result;
+ return TranslateTypeNodeForced(typeExp);
}
RefPtr<DeclRefType> getExprDeclRefType(Expr * expr)
@@ -153,8 +155,6 @@ namespace Slang
RefPtr<Expr> baseExpr,
SourceLoc loc)
{
- if (declRef.As<AssocTypeDecl>())
- getNewThisTypeSubst(declRef);
if (baseExpr)
{
RefPtr<Expr> expr;
@@ -1287,6 +1287,20 @@ namespace Slang
varDecl->initExpr = initExpr;
}
+ // Fill in default substitutions for the 'subtype' part of a type constraint decl
+ void CheckConstraintSubType(TypeExp & typeExp)
+ {
+ if (auto sharedTypeExpr = typeExp.exp.As<SharedTypeExpr>())
+ {
+ if (auto declRefType = sharedTypeExpr->base->AsDeclRefType())
+ {
+ declRefType->declRef.substitutions = createDefaultSubstitutions(getSession(), declRefType->declRef.getDecl());
+ if (auto typetype = typeExp.exp->type.type.As<TypeType>())
+ typetype->type = declRefType;
+ }
+ }
+ }
+
void CheckGenericConstraintDecl(GenericTypeConstraintDecl* decl)
{
// TODO: are there any other validations we can do at this point?
@@ -1294,9 +1308,13 @@ namespace Slang
// There probably needs to be a kind of "occurs check" to make
// sure that the constraint actually applies to at least one
// of the parameters of the generic.
-
- decl->sub = TranslateTypeNode(decl->sub);
- decl->sup = TranslateTypeNode(decl->sup);
+ if (decl->checkState == DeclCheckState::Unchecked)
+ {
+ decl->checkState = DeclCheckState::Checked;
+ CheckConstraintSubType(decl->sub);
+ decl->sub = TranslateTypeNodeForced(decl->sub);
+ decl->sup = TranslateTypeNodeForced(decl->sup);
+ }
}
void checkDecl(Decl* decl)
@@ -1343,6 +1361,7 @@ namespace Slang
{
// check the type being inherited from
auto base = inheritanceDecl->base;
+ CheckConstraintSubType(base);
base = TranslateTypeNode(base);
inheritanceDecl->base = base;
@@ -1677,7 +1696,7 @@ namespace Slang
// An associated type requirement should be allowed
// to be satisfied by any type declaration:
// a typedef, a `struct`, etc.
- auto checkSubTypeMember = [&](DeclRef<AggTypeDecl> subStructTypeDeclRef) -> bool
+ auto checkSubTypeMember = [&](DeclRef<ContainerDecl> subStructTypeDeclRef) -> bool
{
EnsureDecl(subStructTypeDeclRef.getDecl());
// this is a sub type (e.g. nested struct declaration) in an aggregate type
@@ -1685,10 +1704,10 @@ namespace Slang
if (auto requiredTypeDeclRef = requiredMemberDeclRef.As<AssocTypeDecl>())
{
bool conformance = true;
- auto inheritanceReqDeclRefs = getMembersOfType<InheritanceDecl>(requiredTypeDeclRef);
+ auto inheritanceReqDeclRefs = getMembersOfType<TypeConstraintDecl>(requiredTypeDeclRef);
for (auto inheritanceReqDeclRef : inheritanceReqDeclRefs)
{
- auto interfaceDeclRefType = inheritanceReqDeclRef.getDecl()->base.type.As<DeclRefType>();
+ auto interfaceDeclRefType = inheritanceReqDeclRef.getDecl()->getSup().type.As<DeclRefType>();
SLANG_ASSERT(interfaceDeclRefType);
auto interfaceDeclRef = interfaceDeclRefType->declRef.As<InterfaceDecl>();
SLANG_ASSERT(interfaceDeclRef);
@@ -1744,20 +1763,22 @@ namespace Slang
// check if the specified type satisfies the constraints defined by the associated type
if (auto requiredTypeDeclRef = requiredMemberDeclRef.As<AssocTypeDecl>())
{
- auto constraintList = getMembersOfType<InheritanceDecl>(requiredTypeDeclRef);
- if (constraintList.Count())
+ auto declRefType = GetType(typedefDeclRef)->GetCanonicalType()->As<DeclRefType>();
+ if (!declRefType)
+ return false;
+
+ if (auto genTypeParamDeclRef = declRefType->declRef.As<GenericTypeParamDecl>())
{
- auto declRefType = GetType(typedefDeclRef)->GetCanonicalType()->As<DeclRefType>();
- if (!declRefType)
- return false;
+ // TODO: check generic type parameter satisfies constraints
+ return true;
+ }
+
- auto structTypeDeclRef = declRefType->declRef.As<AggTypeDecl>();
- if (!structTypeDeclRef)
- return false;
+ auto containerDeclRef = declRefType->declRef.As<ContainerDecl>();
+ if (!containerDeclRef)
+ return false;
- return checkSubTypeMember(structTypeDeclRef);
- }
- return true;
+ return checkSubTypeMember(containerDeclRef);
}
}
// Default: just assume that thing aren't being satisfied.
@@ -2496,6 +2517,7 @@ namespace Slang
// TODO: This needs to bottleneck through the common variable checks
para->type = CheckUsableType(para->type);
+
if (para->type.Equals(getSession()->getVoidType()))
{
if (!isRewriteMode())
@@ -6154,7 +6176,6 @@ namespace Slang
return expr;
expr->type = QualType(getSession()->getErrorType());
-
auto lookupResult = lookUp(
getSession(),
this, expr->name, expr->scope);
@@ -6970,29 +6991,34 @@ namespace Slang
Decl* decl,
SubstitutionSet parentSubst)
{
+ SubstitutionSet resultSubst = parentSubst;
+ if (auto interfaceDecl = dynamic_cast<InterfaceDecl*>(decl))
+ {
+ resultSubst.thisTypeSubstitution = new ThisTypeSubstitution();
+ }
auto dd = decl->ParentDecl;
if( auto genericDecl = dynamic_cast<GenericDecl*>(dd) )
{
// We don't want to specialize references to anything
// other than the "inner" declaration itself.
if(decl != genericDecl->inner)
- return parentSubst;
+ return resultSubst;
- SubstitutionSet resultSubst = parentSubst;
RefPtr<GenericSubstitution> subst = new GenericSubstitution();
subst->genericDecl = genericDecl;
subst->outer = parentSubst.genericSubstitutions;
resultSubst.genericSubstitutions = subst;
-
+ SubstitutionSet outerSubst = resultSubst;
+ outerSubst.genericSubstitutions = outerSubst.genericSubstitutions?outerSubst.genericSubstitutions->outer:nullptr;
for( auto mm : genericDecl->Members )
{
if( auto genericTypeParamDecl = mm.As<GenericTypeParamDecl>() )
{
- subst->args.Add(DeclRefType::Create(session, makeDeclRef(genericTypeParamDecl.Ptr())));
+ subst->args.Add(DeclRefType::Create(session, DeclRef<Decl>(genericTypeParamDecl.Ptr(), outerSubst)));
}
else if( auto genericValueParamDecl = mm.As<GenericValueParamDecl>() )
{
- subst->args.Add(new GenericParamIntVal(makeDeclRef(genericValueParamDecl.Ptr())));
+ subst->args.Add(new GenericParamIntVal(DeclRef<GenericValueParamDecl>(genericValueParamDecl.Ptr(), outerSubst)));
}
}
@@ -7002,15 +7028,14 @@ namespace Slang
if (auto genericTypeConstraintDecl = mm.As<GenericTypeConstraintDecl>())
{
RefPtr<DeclaredSubtypeWitness> witness = new DeclaredSubtypeWitness();
- witness->declRef = makeDeclRef(genericTypeConstraintDecl.Ptr());
+ witness->declRef = DeclRef<Decl>(genericTypeConstraintDecl.Ptr(), outerSubst);
witness->sub = genericTypeConstraintDecl->sub.type;
witness->sup = genericTypeConstraintDecl->sup.type;
subst->args.Add(witness);
}
}
- return resultSubst;
}
- return parentSubst;
+ return resultSubst;
}
SubstitutionSet createDefaultSubstitutions(
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 41ae819d9..33328fbb1 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -4947,7 +4947,7 @@ emitDeclImpl(decl, nullptr);
{
auto type = inst->getType();
- if(type->As<UniformParameterGroupType>())
+ if(type->As<UniformParameterGroupType>() && !type->As<ParameterBlockType>())
{
// TODO: we need to be careful here, because
// HLSL shader model 6 allows these as explicit
@@ -6341,7 +6341,7 @@ emitDeclImpl(decl, nullptr);
{
// We don't want to declare generic functions,
// because none of our targets actually support them.
- if(func->genericDecl)
+ if(func->getGenericDecl())
return;
// We also don't want to emit declarations for operations
@@ -6453,7 +6453,7 @@ emitDeclImpl(decl, nullptr);
EmitContext* ctx,
IRFunc* func)
{
- if(func->genericDecl)
+ if(func->getGenericDecl())
{
Emit("/* ");
emitIRFuncDecl(ctx, func);
@@ -7110,7 +7110,7 @@ emitDeclImpl(decl, nullptr);
// Don't emit anything for a generic function,
// since we only care about the types used by
// the actual specializations.
- if (irFunc->genericDecl)
+ if (irFunc->getGenericDecl())
return;
emitIRUsedType(ctx, irFunc->getResultType());
diff --git a/source/slang/ir-insts.h b/source/slang/ir-insts.h
index 55ff26185..23e948b3a 100644
--- a/source/slang/ir-insts.h
+++ b/source/slang/ir-insts.h
@@ -315,16 +315,6 @@ struct IRWitnessTable : IRGlobalValue
IRValueList<IRWitnessTableEntry> entries;
};
-// An abstract witness table is a global value that
-// represents an inheritance relationship that can't
-// be resolved to a witness table at IR-generation time.
-struct IRAbstractWitness : IRGlobalValue
-{
- RefPtr<SubtypeWitness> witness;
- DeclRef<Decl> subTypeDeclRef, supTypeDeclRef;
-};
-
-
// Description of an instruction to be used for global value numbering
struct IRInstKey
{
diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp
index 626de3d7a..46eff33e9 100644
--- a/source/slang/ir.cpp
+++ b/source/slang/ir.cpp
@@ -2104,10 +2104,10 @@ namespace Slang
dump(context, "ir_func ");
dumpID(context, func);
- if (func->genericDecl)
+ if (func->getGenericDecl())
{
dump(context, " ");
- dumpGenericSignature(context, func->genericDecl);
+ dumpGenericSignature(context, func->getGenericDecl());
}
dumpInstTypeClause(context, func->getType());
@@ -3084,6 +3084,9 @@ namespace Slang
SharedIRBuilder sharedBuilderStorage;
IRBuilder builderStorage;
+
+ // Non-generic functions to be processed (for generic specialization context)
+ List<IRFunc*> workList;
};
struct IRSpecContextBase
@@ -3297,23 +3300,28 @@ namespace Slang
{
int diff = 0;
newDeclRef = od->declRef.SubstituteImpl(subst, &diff);
- if (newDeclRef.getDecl() == subst.globalGenParamSubstitutions->paramDecl)
- return builder->getTypeVal(subst.globalGenParamSubstitutions->actualType.As<Type>());
- else if (auto genConstraint = newDeclRef.As<GenericTypeConstraintDecl>())
+ for (auto globalGenSubst = subst.globalGenParamSubstitutions; globalGenSubst; globalGenSubst = globalGenSubst->outer)
{
- // a decl-ref to GenericTypeConstraintDecl as a result of
- // referencing a generic parameter type should be replaced with
- // the actual witness table
- if (genConstraint.getDecl()->ParentDecl == subst.globalGenParamSubstitutions->paramDecl)
+ if (!globalGenSubst)
+ continue;
+ if (newDeclRef.getDecl() == globalGenSubst->paramDecl)
+ return builder->getTypeVal(globalGenSubst->actualType.As<Type>());
+ else if (auto genConstraint = newDeclRef.As<GenericTypeConstraintDecl>())
{
- // find the witness table from subst
- for (auto witness : subst.globalGenParamSubstitutions->witnessTables)
+ // a decl-ref to GenericTypeConstraintDecl as a result of
+ // referencing a generic parameter type should be replaced with
+ // the actual witness table
+ if (genConstraint.getDecl()->ParentDecl == globalGenSubst->paramDecl)
{
- if (witness.Key->EqualsVal(GetSup(genConstraint)))
+ // find the witness table from subst
+ for (auto witness : globalGenSubst->witnessTables)
{
- auto proxyVal = witness.Value.As<IRProxyVal>();
- SLANG_ASSERT(proxyVal);
- return proxyVal->inst.usedValue;
+ if (witness.Key->EqualsVal(GetSup(genConstraint)))
+ {
+ auto proxyVal = witness.Value.As<IRProxyVal>();
+ SLANG_ASSERT(proxyVal);
+ return proxyVal->inst.usedValue;
+ }
}
}
}
@@ -3515,9 +3523,10 @@ namespace Slang
IRWitnessTable* cloneWitnessTableImpl(
IRSpecContextBase* context,
IRWitnessTable* originalTable,
- IROriginalValuesForClone const& originalValues)
+ IROriginalValuesForClone const& originalValues,
+ IRWitnessTable* dstTable = nullptr)
{
- auto clonedTable = context->builder->createWitnessTable();
+ auto clonedTable = dstTable ? dstTable : context->builder->createWitnessTable();
registerClonedValue(context, clonedTable, originalValues);
auto mangledName = originalTable->mangledName;
@@ -3543,9 +3552,10 @@ namespace Slang
IRWitnessTable* cloneWitnessTableWithoutRegistering(
IRSpecContextBase* context,
- IRWitnessTable* originalTable)
+ IRWitnessTable* originalTable,
+ IRWitnessTable* dstTable = nullptr)
{
- return cloneWitnessTableImpl(context, originalTable, IROriginalValuesForClone());
+ return cloneWitnessTableImpl(context, originalTable, IROriginalValuesForClone(), dstTable);
}
void cloneGlobalValueWithCodeCommon(
@@ -3614,7 +3624,8 @@ namespace Slang
{
// First clone all the simple properties.
clonedFunc->mangledName = originalFunc->mangledName;
- clonedFunc->genericDecl = originalFunc->genericDecl;
+ clonedFunc->genericDecls = originalFunc->genericDecls;
+ clonedFunc->specializedGenericLevel = originalFunc->specializedGenericLevel;
clonedFunc->type = context->maybeCloneType(originalFunc->type);
cloneDecorations(context, clonedFunc, originalFunc);
@@ -3678,13 +3689,13 @@ namespace Slang
// and their instructions.
cloneFunctionCommon(context, clonedFunc, originalFunc);
- //// for now, clone all unreferenced witness tables
- //for (auto gv = context->getOriginalModule()->getFirstGlobalValue();
- // gv; gv = gv->getNextValue())
- //{
- // if (gv->op == kIROp_witness_table)
- // cloneGlobalValue(context, (IRWitnessTable*)gv);
- //}
+ // for now, clone all unreferenced witness tables
+ /*for (auto gv = context->getOriginalModule()->getFirstGlobalValue();
+ gv; gv = gv->getNextValue())
+ {
+ if (gv->op == kIROp_witness_table)
+ cloneGlobalValue(context, (IRWitnessTable*)gv);
+ }*/
// We need to attach the layout information for
// the entry point to this declaration, so that
@@ -4055,54 +4066,10 @@ namespace Slang
SubstitutionSet typeSubst);
RefPtr<GlobalGenericParamSubstitution> createGlobalGenericParamSubstitution(
- EntryPointRequest * entryPointRequest,
+ EntryPointRequest * entryPointRequest,
ProgramLayout * programLayout,
IRSpecContext* context,
- IRModule* originalIRModule)
- {
- RefPtr<GlobalGenericParamSubstitution> globalParamSubst;
- GlobalGenericParamSubstitution * curTailSubst = nullptr;
- for (auto param : programLayout->globalGenericParams)
- {
- auto paramSubst = new GlobalGenericParamSubstitution();
- if (!globalParamSubst)
- globalParamSubst = paramSubst;
- if (curTailSubst)
- curTailSubst->outer = paramSubst;
- curTailSubst = paramSubst;
- paramSubst->paramDecl = param->decl;
- SLANG_ASSERT((UInt)param->index < entryPointRequest->genericParameterTypes.Count());
- paramSubst->actualType = entryPointRequest->genericParameterTypes[param->index];
- // find witness tables
- for (auto witness : entryPointRequest->genericParameterWitnesses)
- {
- if (auto subtypeWitness = witness.As<SubtypeWitness>())
- {
- if (subtypeWitness->sub->EqualsVal(paramSubst->actualType))
- {
- auto witnessTableName = getMangledNameForConformanceWitness(subtypeWitness->sub, subtypeWitness->sup);
- auto globalVar = originalIRModule->getFirstGlobalValue();
- IRGlobalValue * table = nullptr;
- while (globalVar)
- {
- if (globalVar->mangledName == witnessTableName)
- {
- table = globalVar;
- break;
- }
- globalVar = globalVar->getNextValue();
- }
- SLANG_ASSERT(table);
- table = cloneGlobalValue(context, (IRWitnessTable*)(table));
- IRProxyVal * tableVal = new IRProxyVal();
- tableVal->inst.init(nullptr, table);
- paramSubst->witnessTables.Add(KeyValuePair<RefPtr<Type>, RefPtr<Val>>(subtypeWitness->sup, tableVal));
- }
- }
- }
- }
- return globalParamSubst;
- }
+ IRModule* originalIRModule);
struct IRSpecializationState
{
@@ -4266,19 +4233,11 @@ namespace Slang
break;
}
}
-
- //
-
- struct IRSharedGenericSpecContext : IRSharedSpecContext
- {
- // Non-generic functions to be processed
- List<IRFunc*> workList;
- };
-
+
struct IRGenericSpecContext : IRSpecContextBase
{
- IRSharedGenericSpecContext* getShared() { return (IRSharedGenericSpecContext*) shared; }
-
+ IRSharedSpecContext* getShared() { return shared; }
+
// Override the "maybe clone" logic so that we always clone
virtual IRValue* maybeCloneValue(IRValue* originalVal) override;
@@ -4298,13 +4257,12 @@ namespace Slang
subtypeWitness->sup);
RefPtr<IRSpecSymbol> symbol;
- if( !context->getSymbols().TryGetValue(mangledName, symbol) )
+ if (context->getSymbols().TryGetValue(mangledName, symbol))
{
- SLANG_UNEXPECTED("couldn't find symbol for conformance!");
- return nullptr;
+ return symbol->irGlobalValue;
}
-
- return symbol->irGlobalValue;
+ else
+ return nullptr;
}
else if (auto proxyVal = dynamic_cast<IRProxyVal*>(val))
{
@@ -4385,7 +4343,8 @@ namespace Slang
// the `Val` we have been given.
if(declRef.getDecl()->ParentDecl == genSubst->genericDecl)
{
- return getSubstValue(this, declRef);
+ if (auto substVal = getSubstValue(this, declRef))
+ return substVal;
}
int diff = 0;
@@ -4442,7 +4401,7 @@ namespace Slang
// overloads in the mix, and produces a new set of
// substitutiosn without this issue.
RefPtr<GenericSubstitution> cloneSubstitutionsForSpecialization(
- IRSharedGenericSpecContext* sharedContext,
+ IRSharedSpecContext* sharedContext,
RefPtr<GenericSubstitution> oldSubst,
Decl* newDecl)
{
@@ -4452,15 +4411,26 @@ namespace Slang
if(!oldGenericSubst)
return nullptr;
+ auto innerGenericName = oldGenericSubst->genericDecl->inner->getName();
+
// We will also peel back layers of declarations until
// we find our first generic decl.
- auto newGenericDecl = getInnermostGenericDecl(newDecl);
- if( !newGenericDecl )
+ GenericDecl* newGenericDecl = nullptr;
+
+ for (Decl* d = newDecl; d; d = d->ParentDecl)
{
-// SLANG_UNEXPECTED("generic subst without generic decl");
- return nullptr;
+ if (auto gd = dynamic_cast<GenericDecl*>(d))
+ {
+ if (gd->inner->getName() == innerGenericName)
+ {
+ newGenericDecl = gd;
+ break;
+ }
+ }
}
+ SLANG_ASSERT(newGenericDecl);
+
RefPtr<GenericSubstitution> newSubst = new GenericSubstitution();
newSubst->genericDecl = newGenericDecl;
newSubst->args = oldGenericSubst->args;
@@ -4474,11 +4444,11 @@ namespace Slang
}
IRFunc* getSpecializedFunc(
- IRSharedGenericSpecContext* sharedContext,
+ IRSharedSpecContext* sharedContext,
IRFunc* genericFunc,
DeclRef<Decl> specDeclRef);
- IRWitnessTable* specializeWitnessTable(IRSharedGenericSpecContext * sharedContext, IRWitnessTable* originalTable, DeclRef<Decl> specDeclRef)
+ IRWitnessTable* specializeWitnessTable(IRSharedSpecContext * sharedContext, IRWitnessTable* originalTable, DeclRef<Decl> specDeclRef, IRWitnessTable* dstTable)
{
// First, we want to see if an existing specialization
// has already been made. To do that we will need to
@@ -4488,6 +4458,9 @@ namespace Slang
String specializedMangledName = getMangledNameForConformanceWitness(specDeclRef.Substitute(originalTable->subTypeDeclRef),
specDeclRef.Substitute(originalTable->supTypeDeclRef));
+ if (dstTable && dstTable->mangledName.Length())
+ specializedMangledName = dstTable->mangledName;
+
// TODO: This is a terrible linear search, and we should
// avoid it by building a dictionary ahead of time,
// as is being done for the `IRSpecContext` used above.
@@ -4512,7 +4485,7 @@ namespace Slang
// TODO: other initialization is needed here...
- auto specTable = cloneWitnessTableWithoutRegistering(&context, originalTable);
+ auto specTable = cloneWitnessTableWithoutRegistering(&context, originalTable, dstTable);
// Set up the clone to recognize that it is no longer generic
specTable->mangledName = specMangledName;
@@ -4525,7 +4498,7 @@ namespace Slang
if (entry->satisfyingVal.usedValue->op == kIROp_Func)
{
IRFunc* func = (IRFunc*)entry->satisfyingVal.usedValue;
- if (func->genericDecl)
+ if (func->getGenericDecl())
entry->satisfyingVal.set(getSpecializedFunc(sharedContext, func, specDeclRef));
}
@@ -4537,9 +4510,9 @@ namespace Slang
return specTable;
}
-
+
IRFunc* getSpecializedFunc(
- IRSharedGenericSpecContext* sharedContext,
+ IRSharedSpecContext* sharedContext,
IRFunc* genericFunc,
DeclRef<Decl> specDeclRef)
{
@@ -4548,7 +4521,7 @@ namespace Slang
// compute the mangled name of the specialized function,
// so that we can look for existing declarations.
String specMangledName;
- if (genericFunc->genericDecl == specDeclRef.decl)
+ if (genericFunc->getGenericDecl() == specDeclRef.decl)
specMangledName = getMangledName(specDeclRef);
else
specMangledName = mangleSpecializedFuncName(genericFunc->mangledName, specDeclRef.substitutions);
@@ -4574,7 +4547,10 @@ namespace Slang
RefPtr<GenericSubstitution> newSubst = cloneSubstitutionsForSpecialization(
sharedContext,
specDeclRef.substitutions.genericSubstitutions,
- genericFunc->genericDecl);
+ genericFunc->getGenericDecl());
+
+ if (!newSubst)
+ return genericFunc;
IRGenericSpecContext context;
context.shared = sharedContext;
@@ -4586,9 +4562,11 @@ namespace Slang
auto specFunc = cloneSimpleFuncWithoutRegistering(&context, genericFunc);
- // Set up the clone to recognize that it is no longer generic
specFunc->mangledName = specMangledName;
- specFunc->genericDecl = nullptr;
+
+ // reduce specialized generic level by 1
+ if (specFunc->specializedGenericLevel >= 0)
+ specFunc->specializedGenericLevel--;
// Put the function into the global sequence right after
// the function it specializes.
@@ -4601,7 +4579,8 @@ namespace Slang
// At this point we've created a new non-generic function,
// which means we should add it to our work list for
// subsequent processing.
- sharedContext->workList.Add(specFunc);
+ if (specFunc->specializedGenericLevel == -1)
+ sharedContext->workList.Add(specFunc);
// We also need to make sure that we register this specialized
// function under its mangled name, so that later lookup
@@ -4661,7 +4640,7 @@ namespace Slang
void specializeGenerics(
IRModule* module)
{
- IRSharedGenericSpecContext sharedContextStorage;
+ IRSharedSpecContext sharedContextStorage;
auto sharedContext = &sharedContextStorage;
initializeSharedSpecContext(
@@ -4688,7 +4667,7 @@ namespace Slang
auto func = (IRFunc*) gv;
// Is it generic? If so, skip.
- if(func->genericDecl)
+ if(func->getGenericDecl())
continue;
sharedContext->workList.Add(func);
@@ -4760,7 +4739,7 @@ namespace Slang
if (genericVal->op == kIROp_Func)
{
auto genericFunc = (IRFunc*)genericVal;
- if (!genericFunc->genericDecl)
+ if (!genericFunc->getGenericDecl())
continue;
// Okay, we have a candidate for specialization here.
@@ -4780,7 +4759,7 @@ namespace Slang
{
// specialize a witness table
auto originalTable = (IRWitnessTable*)genericVal;
- auto specWitnessTable = specializeWitnessTable(sharedContext, originalTable, specDeclRef);
+ auto specWitnessTable = specializeWitnessTable(sharedContext, originalTable, specDeclRef, nullptr);
witnessTables.AddIfNotExists(specWitnessTable->mangledName, specWitnessTable);
specInst->replaceUsesWith(specWitnessTable);
specInst->removeAndDeallocate();
@@ -4856,6 +4835,90 @@ namespace Slang
// functions that in turn reference a generic function.
}
- //
+ RefPtr<GlobalGenericParamSubstitution> createGlobalGenericParamSubstitution(
+ EntryPointRequest * entryPointRequest,
+ ProgramLayout * programLayout,
+ IRSpecContext* context,
+ IRModule* originalIRModule)
+ {
+ RefPtr<GlobalGenericParamSubstitution> globalParamSubst;
+ GlobalGenericParamSubstitution * curTailSubst = nullptr;
+ struct WitnessTableSpecializationWorkItem
+ {
+ IRWitnessTable* dstTable;
+ IRWitnessTable* srcTable;
+ DeclRef<Decl> specDeclRef;
+ };
+ List<WitnessTableSpecializationWorkItem> witnessTablesToSpecailize;
+ for (auto param : programLayout->globalGenericParams)
+ {
+ auto paramSubst = new GlobalGenericParamSubstitution();
+ if (!globalParamSubst)
+ globalParamSubst = paramSubst;
+ if (curTailSubst)
+ curTailSubst->outer = paramSubst;
+ curTailSubst = paramSubst;
+ paramSubst->paramDecl = param->decl;
+ SLANG_ASSERT((UInt)param->index < entryPointRequest->genericParameterTypes.Count());
+ paramSubst->actualType = entryPointRequest->genericParameterTypes[param->index];
+ // find witness tables
+ for (auto witness : entryPointRequest->genericParameterWitnesses)
+ {
+ if (auto subtypeWitness = witness.As<SubtypeWitness>())
+ {
+ if (subtypeWitness->sub->EqualsVal(paramSubst->actualType))
+ {
+ auto witnessTableName = getMangledNameForConformanceWitness(subtypeWitness->sub, subtypeWitness->sup);
+ auto findWitnessTableByName = [&](String name)
+ {
+ auto globalVar = originalIRModule->getFirstGlobalValue();
+ IRGlobalValue * rs = nullptr;
+ while (globalVar)
+ {
+ if (globalVar->mangledName == name)
+ {
+ rs = globalVar;
+ break;
+ }
+ globalVar = globalVar->getNextValue();
+ }
+ return rs;
+ };
+ auto table = findWitnessTableByName(witnessTableName);
+ if (!table)
+ {
+ if (auto subDeclRefType = subtypeWitness->sub.As<DeclRefType>())
+ {
+ auto genericWitnessTableName = getMangledNameForConformanceWitness(DeclRef<Decl>(subDeclRefType->declRef.getDecl(), nullptr), subtypeWitness->sup);
+ table = findWitnessTableByName(genericWitnessTableName);
+ WitnessTableSpecializationWorkItem workItem;
+ workItem.srcTable = (IRWitnessTable*)table;
+ workItem.dstTable = context->builder->createWitnessTable();
+ workItem.dstTable->mangledName = getMangledNameForConformanceWitness(subDeclRefType->declRef, subtypeWitness->sup);
+ workItem.specDeclRef = subDeclRefType->declRef;
+ registerClonedValue(context, workItem.dstTable, workItem.srcTable);
+ witnessTablesToSpecailize.Add(workItem);
+ table = workItem.dstTable;
+ }
+ }
+ else
+ table = cloneGlobalValue(context, (IRWitnessTable*)(table));
+ SLANG_ASSERT(table);
+ IRProxyVal * tableVal = new IRProxyVal();
+ tableVal->inst.init(nullptr, table);
+ paramSubst->witnessTables.Add(KeyValuePair<RefPtr<Type>, RefPtr<Val>>(subtypeWitness->sup, tableVal));
+ }
+ }
+ }
+ }
+ for (auto workItem : witnessTablesToSpecailize)
+ {
+ int diff = 0;
+ specializeWitnessTable(context->shared, workItem.srcTable,
+ workItem.specDeclRef.SubstituteImpl(SubstitutionSet(nullptr, nullptr, globalParamSubst), &diff), workItem.dstTable);
+ }
+ return globalParamSubst;
+ }
+
}
diff --git a/source/slang/ir.h b/source/slang/ir.h
index c56f8fb62..fe6fab5f6 100644
--- a/source/slang/ir.h
+++ b/source/slang/ir.h
@@ -438,7 +438,15 @@ struct IRFunc : IRGlobalValueWithCode
// If this function is generic, then we store a reference
// to the AST-level generic that defines its parameters
// and their constraints.
- RefPtr<GenericDecl> genericDecl;
+ List<RefPtr<GenericDecl>> genericDecls;
+ int specializedGenericLevel = -1;
+
+ GenericDecl* getGenericDecl()
+ {
+ if (specializedGenericLevel != -1)
+ return genericDecls[specializedGenericLevel].Ptr();
+ return nullptr;
+ }
// Convenience accessors for working with the
// function's type.
diff --git a/source/slang/lookup.cpp b/source/slang/lookup.cpp
index 901661667..376d9bd6d 100644
--- a/source/slang/lookup.cpp
+++ b/source/slang/lookup.cpp
@@ -1,5 +1,6 @@
// lookup.cpp
#include "lookup.h"
+#include "name.h"
namespace Slang {
@@ -320,8 +321,8 @@ void DoLookupImpl(
continue;
DeclRef<ContainerDecl> containerDeclRef =
- DeclRef<Decl>(containerDecl, nullptr).As<ContainerDecl>();
-
+ DeclRef<Decl>(containerDecl, createDefaultSubstitutions(session, containerDecl)).As<ContainerDecl>();
+
BreadcrumbInfo breadcrumb;
BreadcrumbInfo* breadcrumbs = nullptr;
diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp
index 4af36f718..61ca53278 100644
--- a/source/slang/lower-to-ir.cpp
+++ b/source/slang/lower-to-ir.cpp
@@ -480,9 +480,10 @@ LoweredValInfo emitWitnessTableRef(
{
if (auto mbrExpr = dynamic_cast<MemberExpr*>(expr))
{
- if (auto inheritanceDeclRef = mbrExpr->declRef.As<InheritanceDecl>())
+ if (auto typeConstraintDeclRef = mbrExpr->declRef.As<TypeConstraintDecl>())
{
- if (inheritanceDeclRef.getDecl()->ParentDecl->As<InterfaceDecl>() || inheritanceDeclRef.getDecl()->ParentDecl->As<AssocTypeDecl>())
+ if (mbrExpr->declRef.getDecl()->ParentDecl->As<InterfaceDecl>()
+ || mbrExpr->declRef.getDecl()->ParentDecl->As<AssocTypeDecl>())
{
RefPtr<Type> exprType = nullptr;
if (auto tt = mbrExpr->BaseExpression->type->As<TypeType>())
@@ -499,16 +500,19 @@ LoweredValInfo emitWitnessTableRef(
// and generate specialize instruction
srcDeclRef.substitutions = SubstitutionSet();
}
- witnessTableVal = context->irBuilder->emitFindWitnessTable(srcDeclRef, inheritanceDeclRef.getDecl()->base.type);
+ witnessTableVal = context->irBuilder->emitFindWitnessTable(srcDeclRef, mbrExpr->declRef.As<TypeConstraintDecl>().getDecl()->getSup().type);
return maybeEmitSpecializeInst(context, LoweredValInfo::simple(witnessTableVal), declRefType->declRef);
}
- else if (inheritanceDeclRef.getDecl()->ParentDecl->As<AggTypeDeclBase>())
+ }
+ if (auto inheritanceDecl = mbrExpr->declRef.As<InheritanceDecl>())
+ {
+ if (mbrExpr->declRef.getDecl()->ParentDecl->As<AggTypeDeclBase>())
{
- return LoweredValInfo::simple(findWitnessTable(context, inheritanceDeclRef));
+ return LoweredValInfo::simple(findWitnessTable(context, mbrExpr->declRef));
}
-
}
- else if (auto genConstraintDeclRef = mbrExpr->declRef.As<GenericTypeConstraintDecl>())
+
+ if (auto genConstraintDeclRef = mbrExpr->declRef.As<GenericTypeConstraintDecl>())
{
return LoweredValInfo::simple(context->irBuilder->getDeclRefVal(genConstraintDeclRef));
}
@@ -549,7 +553,6 @@ LoweredValInfo emitFuncRef(
// a body, so we don't want to emit or call it), and
// we actually want to perform a lookup step to
// find the corresponding member on our chosen type.
-
RefPtr<Type> type = funcExpr->type;
auto loweredBaseWitnessTable = emitWitnessTableRef(context, baseMemberExpr);
auto loweredVal = LoweredValInfo::simple(context->irBuilder->emitLookupInterfaceMethodInst(
@@ -2751,6 +2754,13 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
SLANG_UNIMPLEMENTED_X("decl catch-all");
}
+ LoweredValInfo visitExtensionDecl(ExtensionDecl* decl)
+ {
+ for (auto & member : decl->Members)
+ ensureDecl(context, member);
+ return LoweredValInfo();
+ }
+
LoweredValInfo visitImportDecl(ImportDecl* /*decl*/)
{
return LoweredValInfo();
@@ -2789,7 +2799,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// Construct the mangled name for the witness table, which depends
// on the type that is conforming, and the type that it conforms to.
String mangledName = getMangledNameForConformanceWitness(
- type,
+ makeDeclRef(parentDecl),
superType);
// Build an IR level witness table, which will represent the
@@ -3466,11 +3476,10 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
{
if(auto genericAncestor = dynamic_cast<GenericDecl*>(pp))
{
- irFunc->genericDecl = genericAncestor;
- break;
+ irFunc->genericDecls.Add(genericAncestor);
}
}
-
+ irFunc->specializedGenericLevel = (int)irFunc->genericDecls.Count() - 1;
for( auto paramInfo : parameterLists.params )
{
RefPtr<Type> irParamType = lowerSimpleType(context, paramInfo.type);
@@ -3904,28 +3913,49 @@ LoweredValInfo maybeEmitSpecializeInst(IRGenContext* context,
if (loweredDecl.flavor == LoweredValInfo::Flavor::None)
return loweredDecl;
+ if (!declRef.As<FuncDecl>() && !declRef.As<TypeConstraintDecl>())
+ return loweredDecl;
+
auto val = getSimpleVal(context, loweredDecl);
+
+ RefPtr<GenericSubstitution> outterMostSubst, secondOutterMostSubst;
+ for (auto subst = declRef.substitutions.genericSubstitutions; subst; subst = subst->outer)
+ {
+ if (!subst->outer)
+ outterMostSubst = subst;
+ else
+ secondOutterMostSubst = subst;
+ }
+ auto newSubst = outterMostSubst;
// We have the "raw" substitutions from the AST, but we may
// need to walk through those and replace things in
// cases where the `Val`s used for substitution should
// lower to something other than their original form.
- auto newSubst = lowerSubstitutions(context, declRef.substitutions);
- declRef.substitutions = newSubst;
-
+ auto lowedNewSubst = lowerGenericSubstitutions(context, newSubst);
+ DeclRef<Decl> newDeclRef = DeclRef<Decl>(declRef.decl,
+ SubstitutionSet(lowedNewSubst, declRef.substitutions.thisTypeSubstitution,
+ declRef.substitutions.globalGenParamSubstitutions));
RefPtr<Type> type;
if (auto declType = val->getType())
{
- type = declType->Substitute(declRef.substitutions).As<Type>();
+ type = declType->Substitute(newDeclRef.substitutions).As<Type>();
}
// Otherwise, we need to construct a specialization of the
// given declaration.
- return LoweredValInfo::simple((IRInst*)context->irBuilder->emitSpecializeInst(
+ auto specializedVal = LoweredValInfo::simple((IRInst*)context->irBuilder->emitSpecializeInst(
type,
val,
- declRef));
+ newDeclRef));
+ if (secondOutterMostSubst)
+ {
+ newDeclRef.substitutions.genericSubstitutions = new GenericSubstitution(*secondOutterMostSubst);
+ newDeclRef.substitutions.genericSubstitutions->outer = nullptr;
+ return maybeEmitSpecializeInst(context, specializedVal, newDeclRef);
+ }
+ return specializedVal;
}
diff --git a/source/slang/mangle.cpp b/source/slang/mangle.cpp
index 070c2b172..1a412d041 100644
--- a/source/slang/mangle.cpp
+++ b/source/slang/mangle.cpp
@@ -408,6 +408,22 @@ namespace Slang
}
String getMangledNameForConformanceWitness(
+ DeclRef<Decl> sub,
+ Type* sup)
+ {
+ // The mangled form for a witness that `sub`
+ // conforms to `sup` will be named:
+ //
+ // {Conforms(sub,sup)} => _SW{sub}{sup}
+ //
+ ManglingContext context;
+ emitRaw(&context, "_SW");
+ emitQualifiedName(&context, sub);
+ emitType(&context, sup);
+ return context.sb.ProduceString();
+ }
+
+ String getMangledNameForConformanceWitness(
Type* sub,
Type* sup)
{
diff --git a/source/slang/mangle.h b/source/slang/mangle.h
index 45b1d4bd1..8f4c6d1d0 100644
--- a/source/slang/mangle.h
+++ b/source/slang/mangle.h
@@ -19,6 +19,9 @@ namespace Slang
String getMangledNameForConformanceWitness(
DeclRef<Decl> sub,
DeclRef<Decl> sup);
+ String getMangledNameForConformanceWitness(
+ DeclRef<Decl> sub,
+ Type* sup);
String getMangledTypeName(Type* type);
}
diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp
index 11e3eb159..1378191ca 100644
--- a/source/slang/parser.cpp
+++ b/source/slang/parser.cpp
@@ -2216,20 +2216,9 @@ namespace Slang
return blockVarDecl;
}
- static RefPtr<RefObject> ParseExtensionDecl(Parser* parser, void* /*userData*/)
- {
- RefPtr<ExtensionDecl> decl = new ExtensionDecl();
- parser->FillPosition(decl.Ptr());
- decl->targetType = parser->ParseTypeExp();
-
- parseAggTypeDeclBody(parser, decl.Ptr());
-
- return decl;
- }
-
- static void parseOptionalInheritanceClause(Parser* parser, AggTypeDecl* decl)
+ static void parseOptionalInheritanceClause(Parser* parser, AggTypeDeclBase* decl)
{
- if( AdvanceIf(parser, TokenType::Colon) )
+ if (AdvanceIf(parser, TokenType::Colon))
{
do
{
@@ -2242,10 +2231,22 @@ namespace Slang
AddMember(decl, inheritanceDecl);
- } while( AdvanceIf(parser, TokenType::Comma) );
+ } while (AdvanceIf(parser, TokenType::Comma));
}
}
+ static RefPtr<RefObject> ParseExtensionDecl(Parser* parser, void* /*userData*/)
+ {
+ RefPtr<ExtensionDecl> decl = new ExtensionDecl();
+ parser->FillPosition(decl.Ptr());
+ decl->targetType = parser->ParseTypeExp();
+ parseOptionalInheritanceClause(parser, decl);
+ parseAggTypeDeclBody(parser, decl.Ptr());
+
+ return decl;
+ }
+
+
void parseOptionalGenericConstraints(Parser * parser, ContainerDecl* decl)
{
if (AdvanceIf(parser, TokenType::Colon))
@@ -2255,6 +2256,7 @@ namespace Slang
RefPtr<GenericTypeConstraintDecl> paramConstraint = new GenericTypeConstraintDecl();
parser->FillPosition(paramConstraint);
+ // substitution needs to be filled during check
RefPtr<DeclRefType> paramType = DeclRefType::Create(
parser->getSession(),
DeclRef<Decl>(decl, nullptr));
@@ -2279,7 +2281,7 @@ namespace Slang
auto nameToken = parser->ReadToken(TokenType::Identifier);
assocTypeDecl->nameAndLoc = NameLoc(nameToken);
assocTypeDecl->loc = nameToken.loc;
- parseOptionalInheritanceClause(parser, assocTypeDecl);
+ parseOptionalGenericConstraints(parser, assocTypeDecl);
parser->ReadToken(TokenType::Semicolon);
return assocTypeDecl;
}
diff --git a/source/slang/slang.natvis b/source/slang/slang.natvis
index d58e733fa..93979f473 100644
--- a/source/slang/slang.natvis
+++ b/source/slang/slang.natvis
@@ -12,23 +12,59 @@
<Type Name="Slang::DeclRef&lt;*&gt;">
<SmartPointer Usage="Minimal">decl ? ($T1*)(decl) : ($T1*)0</SmartPointer>
<DisplayString Condition="decl == 0">DeclRef nullptr</DisplayString>
- <DisplayString Condition="decl != 0">DeclRef {(*(*(Slang::DeclRefBase*)this).decl).nameAndLoc}</DisplayString>
+ <DisplayString Condition="decl != 0">{(*(*(Slang::DeclRefBase*)this).decl).nameAndLoc}</DisplayString>
<Expand>
<ExpandedItem>decl ? ($T1*)(decl) : ($T1*)0</ExpandedItem>
<Item Name="[Substitutions]:">"========================="</Item>
<LinkedListItems>
- <HeadPointer>substitutions.pointer</HeadPointer>
+ <HeadPointer>substitutions.genericSubstitutions.pointer</HeadPointer>
<NextPointer>outer.pointer</NextPointer>
<ValueNode>this</ValueNode>
</LinkedListItems>
+ <LinkedListItems>
+ <HeadPointer>substitutions.globalGenParamSubstitutions.pointer</HeadPointer>
+ <NextPointer>outer.pointer</NextPointer>
+ <ValueNode>this</ValueNode>
+ </LinkedListItems>
+ <Item Name ="thisSubst">substitutions.thisTypeSubstitution</Item>
</Expand>
</Type>
+ <Type Name="Slang::DeclRefBase">
+ <SmartPointer Usage="Minimal">decl</SmartPointer>
+ <DisplayString Condition="decl == 0">DeclRefBase nullptr</DisplayString>
+ <DisplayString Condition="decl != 0">{(*(*(Slang::DeclRefBase*)this).decl).nameAndLoc}</DisplayString>
+ <Expand>
+ <ExpandedItem>decl</ExpandedItem>
+ <Item Name="[Substitutions]:">"========================="</Item>
+ <LinkedListItems>
+ <HeadPointer>substitutions.genericSubstitutions.pointer</HeadPointer>
+ <NextPointer>outer.pointer</NextPointer>
+ <ValueNode>this</ValueNode>
+ </LinkedListItems>
+ <LinkedListItems>
+ <HeadPointer>substitutions.globalGenParamSubstitutions.pointer</HeadPointer>
+ <NextPointer>outer.pointer</NextPointer>
+ <ValueNode>this</ValueNode>
+ </LinkedListItems>
+ <Item Name ="thisSubst">substitutions.thisTypeSubstitution</Item>
+ </Expand>
+ </Type>
+ <Type Name="Slang::GenericSubstitution">
+ <DisplayString>GenSubst {(*genericDecl).nameAndLoc}</DisplayString>
+ <Expand>
+ <Item Name="genericDecl">genericDecl</Item>
+ <ExpandedItem>args</ExpandedItem>
+ </Expand>
+ </Type>
<Type Name="Slang::DeclRefType">
<DisplayString>DeclRefType {declRef}</DisplayString>
<Expand>
<ExpandedItem>declRef</ExpandedItem>
</Expand>
</Type>
+ <Type Name="Slang::FuncDecl">
+ <DisplayString>FuncDecl {nameAndLoc}</DisplayString>
+ </Type>
<Type Name="Slang::Name">
<DisplayString>{{name={(char*)(text.buffer.pointer+1), s}}}</DisplayString>
</Type>
@@ -88,6 +124,8 @@
<Item Name="[ResultType]">(*(IRFuncType*)(type.pointer)).resultType</Item>
<Item Name="[ParameterTypes]">(*(IRFuncType*)(type.pointer)).paramTypes</Item>
<Item Name="[FirstBlock]">firstBlock</Item>
+ <Item Name="[SpecLevel]">specializedGenericLevel</Item>
+ <Item Name="genericDecls">genericDecls</Item>
</Expand>
</Type>
diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp
index c63dfc781..2ed10e138 100644
--- a/source/slang/syntax.cpp
+++ b/source/slang/syntax.cpp
@@ -1194,6 +1194,7 @@ void Type::accept(IValVisitor* visitor, void* extra)
auto substSubst = new GenericSubstitution();
substSubst->genericDecl = genericDecl;
substSubst->args = substArgs;
+ substSubst->outer = outerSubst.As<GenericSubstitution>();
return substSubst;
}
@@ -1897,27 +1898,9 @@ void Type::accept(IValVisitor* visitor, void* extra)
SubstitutionSet substituteSubstitutions(SubstitutionSet oldSubst, SubstitutionSet subst, int * ioDiff)
{
- if (oldSubst)
- oldSubst = oldSubst.substituteImpl(subst, ioDiff);
-
- // if oldSubst does not have ThisTypeSubst (which means `this_type` is free variable)
- // and subst has a ThisTypeSubst (which means `this_type` is bound to a type),
- // then copy that ThisTypeSubst over (to bind the this_type to the specified type)
- SubstitutionSet newSubst = oldSubst;
- insertGlobalGenericSubstitutions(newSubst, subst, ioDiff);
- /*if (!hasThisTypeSubstitutions(oldSubst))
- {
- auto thisTypeSubst = findThisTypeSubst(subst);
- if (thisTypeSubst)
- {
- auto cpyThisTypeSubst = new ThisTypeSubstitution();
- cpyThisTypeSubst->sourceType = thisTypeSubst->sourceType;
- insertSubstAtBottom(newSubst, cpyThisTypeSubst);
- *ioDiff = 1;
- }
- }*/
- return newSubst;
+ return oldSubst.substituteImpl(subst, ioDiff);
}
+
bool SubstitutionSet::Equals(SubstitutionSet substSet) const
{
if (genericSubstitutions)
@@ -1951,8 +1934,8 @@ void Type::accept(IValVisitor* visitor, void* extra)
rs.globalGenParamSubstitutions = globalGenParamSubstitutions->SubstituteImpl(subst, ioDiff).As<GlobalGenericParamSubstitution>();
if (thisTypeSubstitution)
rs.thisTypeSubstitution = thisTypeSubstitution->SubstituteImpl(subst, ioDiff).As<ThisTypeSubstitution>();
- else
- rs.thisTypeSubstitution = subst.thisTypeSubstitution;
+
+ insertGlobalGenericSubstitutions(rs, subst, ioDiff);
return rs;
}
int SubstitutionSet::GetHashCode() const