From 109ee8aae399042fba6ea71e43e5ee2d441288dd Mon Sep 17 00:00:00 2001 From: Yong He Date: Fri, 24 Nov 2017 11:55:54 -0500 Subject: Fix substitution mechanism to remove special cases for global params (#297) Add a new function: `substituteSubstitutions(Substitutions * substHead, Substitutions subst, int * ioDiff)` This function substitutes the type arguments referenced in a linked list of substitutions headed at `substHead` using the substitutions specified by `subst`. If the linked list `substHead` does not contain `GlobalGenericParamSubstitution` entries, they will be added to the bottom (outter most) of the linked list. Note that this function should be called when `substHead` is known to be the head of substitution linked list because the existance of `GlobalGenericPaaramSubstitution` is detected assuming the linked lists starts at `substHead`. If a substitution that is not the head of a substitution linked list is passed in, duplicate `GlobalGenericParamSubstitution`s could be appended to the linked list. This means that this function should *not* be called in places like `GenericSubstitution::SubstitutionImpl()` for its outer substitutions, because `outer` is obviously not the head of the linked list. Instead, use this function to substitution the substitution lists of `DeclRef` etc. instead of calling `declRef.substitutions->SubstituteImpl()` where the head to the linked list is known as a member of that class. With this function, IRSpecContext::maybeCloneType() is simplified down to `originalType->Substitute(subst)` Updates `DeclRefBase::SubstituteImpl` and `DeclRefType::SubstituteImpl` to call `substituteSubstitutions` instead of making direct `substitutions->SubstituteImpl` call. Providing actual implementation of `GlobalGenericParamSubstitution::SubstituteImpl` instead of just returning `this` to deal with potential situations where a true substitution is needed. --- source/slang/syntax.cpp | 57 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 11 deletions(-) (limited to 'source/slang/syntax.cpp') diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index 2c214a332..f8237359d 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -489,7 +489,7 @@ void Type::accept(IValVisitor* visitor, void* extra) bool restore = false; if (thisSubst && thisSubst->sourceType.Ptr() == dynamic_cast(this)) thisSubst->sourceType = nullptr; - auto newSubst = declRef.substitutions->SubstituteImpl(subst, ioDiff); + auto newSubst = substituteSubstitutions(declRef.substitutions, subst, ioDiff); if (restore) thisSubst->sourceType = oldSubstSrc; if (auto thisTypeSubst = newSubst.As()) @@ -1205,9 +1205,7 @@ void Type::accept(IValVisitor* visitor, void* extra) if (!this) return nullptr; int diff = 0; - RefPtr outerSubst; - if (outer) - outerSubst = outer->SubstituteImpl(subst, &diff); + RefPtr outerSubst = outer ? outer->SubstituteImpl(subst, &diff) : nullptr; RefPtr newSourceType; if (sourceType) newSourceType = sourceType->SubstituteImpl(subst, &diff); @@ -1244,9 +1242,36 @@ void Type::accept(IValVisitor* visitor, void* extra) return false; } - RefPtr GlobalGenericParamSubstitution::SubstituteImpl(Substitutions* /*subst*/, int* /*ioDiff*/) + RefPtr GlobalGenericParamSubstitution::SubstituteImpl(Substitutions* subst, int* ioDiff) { - // we will never replace values for this type of substitution + // if we find a GlobalGenericParamSubstitution in subst that references the same __generic_param decl + // return a copy of that GlobalGenericParamSubstitution + int diff = 0; + RefPtr outerSubst = outer ? outer->SubstituteImpl(subst, &diff) : nullptr; + while (subst) + { + if (auto gSubst = dynamic_cast(subst)) + { + if (gSubst->paramDecl == paramDecl) + { + // substitute only if we are really different + if (!gSubst->actualType->EqualsVal(actualType)) + { + RefPtr rs = new GlobalGenericParamSubstitution(*gSubst); + rs->outer = outerSubst; + return rs; + } + } + } + subst = subst->outer; + } + if (diff) + { + *ioDiff++; + RefPtr rs = new GlobalGenericParamSubstitution(*this); + rs->outer = outerSubst; + return rs; + } return this; } @@ -1322,8 +1347,9 @@ void Type::accept(IValVisitor* visitor, void* extra) } return false; } - void insertGlobalGenericSubstitutions(RefPtr & destSubst, Substitutions * srcSubst) + void insertGlobalGenericSubstitutions(RefPtr & destSubst, Substitutions * srcSubst, int * ioDiff) { + int diff = 0; while (srcSubst) { if (auto globalGenSubst = dynamic_cast(srcSubst)) @@ -1333,19 +1359,18 @@ void Type::accept(IValVisitor* visitor, void* extra) RefPtr cpyGlobalGenSubst = new GlobalGenericParamSubstitution(*globalGenSubst); cpyGlobalGenSubst->outer = nullptr; insertSubstAtBottom(destSubst, cpyGlobalGenSubst); + diff = 1; } } srcSubst = srcSubst->outer; } + *ioDiff += diff; } DeclRefBase DeclRefBase::SubstituteImpl(Substitutions* subst, int* ioDiff) { - insertGlobalGenericSubstitutions(substitutions, subst); - if (!substitutions) return *this; - int diff = 0; - RefPtr substSubst = substitutions->SubstituteImpl(subst, &diff); + RefPtr substSubst = substituteSubstitutions(substitutions, subst, &diff); if (!diff) return *this; @@ -1841,6 +1866,16 @@ void Type::accept(IValVisitor* visitor, void* extra) return nullptr; } + RefPtr substituteSubstitutions(RefPtr oldSubst, Substitutions * subst, int * ioDiff) + { + if (oldSubst) + oldSubst = oldSubst->SubstituteImpl(subst, ioDiff); + + RefPtr newSubst = oldSubst; + insertGlobalGenericSubstitutions(newSubst, subst, ioDiff); + return newSubst; + } + // FilteredTupleType String FilteredTupleType::ToString() -- cgit v1.2.3