summaryrefslogtreecommitdiffstats
path: root/source/slang/syntax.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/syntax.cpp')
-rw-r--r--source/slang/syntax.cpp80
1 files changed, 75 insertions, 5 deletions
diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp
index cdc112846..4f043e0a1 100644
--- a/source/slang/syntax.cpp
+++ b/source/slang/syntax.cpp
@@ -1275,8 +1275,12 @@ void Type::accept(IValVisitor* visitor, void* extra)
{
if (!subst)
return true;
- if (subst && dynamic_cast<ThisTypeSubstitution*>(subst))
- return true;
+ if (auto thisTypeSubst = dynamic_cast<ThisTypeSubstitution*>(subst))
+ {
+ if (!sourceType || !thisTypeSubst->sourceType)
+ return true;
+ return sourceType->EqualsVal(thisTypeSubst->sourceType);
+ }
return false;
}
@@ -1405,19 +1409,48 @@ void Type::accept(IValVisitor* visitor, void* extra)
*ioDiff += diff;
}
+ void buildMemberDictionary(ContainerDecl* decl);
+
DeclRefBase DeclRefBase::SubstituteImpl(Substitutions* subst, int* ioDiff)
{
int diff = 0;
RefPtr<Substitutions> substSubst = substituteSubstitutions(substitutions, subst, &diff);
-
if (!diff)
- return *this;
+ return *this;
*ioDiff += diff;
DeclRefBase substDeclRef;
substDeclRef.decl = decl;
substDeclRef.substitutions = substSubst;
+
+ // if this is a AssocTypeDecl, try lookup the actual associated type
+ if (auto assocTypeDecl = substDeclRef.decl->As<AssocTypeDecl>())
+ {
+ auto thisSubst = getThisTypeSubst(substDeclRef, false);
+ if (thisSubst)
+ {
+ if (auto declRefType = thisSubst->sourceType.As<DeclRefType>())
+ {
+ if (auto aggDeclRef = declRefType->declRef.As<StructDecl>())
+ {
+ Decl* subTypeDecl = nullptr;
+ buildMemberDictionary(aggDeclRef.getDecl());
+ SLANG_ASSERT(aggDeclRef.getDecl()->memberDictionaryIsValid);
+ aggDeclRef.getDecl()->memberDictionary.TryGetValue(assocTypeDecl->getName(), subTypeDecl);
+ if (auto typeDefDecl = subTypeDecl->As<TypeDefDecl>())
+ {
+ auto t = GetType(DeclRef<TypeDefDecl>(typeDefDecl, aggDeclRef.substitutions));
+ auto canonicalType = t->GetCanonicalType()->AsDeclRefType();
+ SLANG_ASSERT(canonicalType);
+ return canonicalType->declRef;
+ }
+ SLANG_ASSERT(subTypeDecl);
+ return DeclRefBase(subTypeDecl, aggDeclRef.substitutions);
+ }
+ }
+ }
+ }
return substDeclRef;
}
@@ -1428,7 +1461,7 @@ void Type::accept(IValVisitor* visitor, void* extra)
if (decl != declRef.decl)
return false;
if (!substitutions)
- return !declRef.substitutions || declRef.substitutions.As<ThisTypeSubstitution>();
+ return !hasGenericSubstitutions(declRef.substitutions);
if (!substitutions->Equals(declRef.substitutions.Ptr()))
return false;
@@ -1903,6 +1936,17 @@ void Type::accept(IValVisitor* visitor, void* extra)
declRef.substitutions = substToInsert;
}
+ ThisTypeSubstitution* findThisTypeSubst(Substitutions* subst)
+ {
+ while (subst)
+ {
+ if (auto thisSubst = dynamic_cast<ThisTypeSubstitution*>(subst))
+ return thisSubst;
+ subst = subst->outer.Ptr();
+ }
+ return nullptr;
+ }
+
RefPtr<ThisTypeSubstitution> getThisTypeSubst(DeclRefBase & declRef, bool insertSubstEntry)
{
RefPtr<ThisTypeSubstitution> thisSubst;
@@ -1958,6 +2002,18 @@ void Type::accept(IValVisitor* visitor, void* extra)
}
}
+ bool hasThisTypeSubstitutions(RefPtr<Substitutions> subst)
+ {
+ auto p = subst.Ptr();
+ while (p)
+ {
+ if (dynamic_cast<ThisTypeSubstitution*>(p))
+ return true;
+ p = p->outer.Ptr();
+ }
+ return false;
+ }
+
bool hasGenericSubstitutions(RefPtr<Substitutions> subst)
{
auto p = subst.Ptr();
@@ -1987,8 +2043,22 @@ void Type::accept(IValVisitor* visitor, void* extra)
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)
RefPtr<Substitutions> 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;
}
}