diff options
Diffstat (limited to 'source/slang/syntax.cpp')
| -rw-r--r-- | source/slang/syntax.cpp | 1270 |
1 files changed, 792 insertions, 478 deletions
diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index 70e230f33..9d29e7d21 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -228,12 +228,6 @@ void Type::accept(IValVisitor* visitor, void* extra) overloadedType = new OverloadGroupType(); overloadedType->setSession(this); - - irBasicBlockType = new IRBasicBlockType(); - irBasicBlockType->setSession(this); - - constExprRate = new ConstExprRate(); - constExprRate->setSession(this); } Type* Session::getBoolType() @@ -286,33 +280,12 @@ void Type::accept(IValVisitor* visitor, void* extra) return errorType; } - Type* Session::getIRBasicBlockType() - { - return irBasicBlockType; - } - - Type* Session::getConstExprRate() - { - return constExprRate; - } - Type* Session::getStringType() { auto stringTypeDecl = findMagicDecl(this, "StringType"); return DeclRefType::Create(this, makeDeclRef<Decl>(stringTypeDecl)); } - RefPtr<RateQualifiedType> Session::getRateQualifiedType( - Type* rate, - Type* valueType) - { - RefPtr<RateQualifiedType> rateQualifiedType = new RateQualifiedType(); - rateQualifiedType->setSession(this); - rateQualifiedType->rate = rate; - rateQualifiedType->valueType = valueType; - return rateQualifiedType; - } - RefPtr<PtrType> Session::getPtrType( RefPtr<Type> valueType) { @@ -363,16 +336,6 @@ void Type::accept(IValVisitor* visitor, void* extra) return arrayType; } - - RefPtr<GroupSharedType> Session::getGroupSharedType(RefPtr<Type> valueType) - { - RefPtr<GroupSharedType> groupSharedType = new GroupSharedType(); - groupSharedType->setSession(this); - groupSharedType->valueType = valueType; - return groupSharedType; - } - - SyntaxClass<RefObject> Session::findSyntaxClass(Name* name) { SyntaxClass<RefObject> syntaxClass; @@ -432,142 +395,147 @@ void Type::accept(IValVisitor* visitor, void* extra) return baseType->ToString() + "[]"; } - // RateQualifiedType - - Slang::String RateQualifiedType::ToString() - { - return "@" + rate->ToString() + " " + valueType->ToString(); - } - - bool RateQualifiedType::EqualsImpl(Type * type) - { - auto rateQualifiedType = type->As<RateQualifiedType>(); - if(!rateQualifiedType) - return false; - - return rate->Equals(rateQualifiedType->rate) - && valueType->Equals(rateQualifiedType->valueType); - } - - RefPtr<Val> RateQualifiedType::SubstituteImpl(SubstitutionSet subst, int* ioDiff) - { - int diff = 0; - auto substRate = rate->SubstituteImpl(subst, &diff).As<Type>(); - auto substValueType = valueType->SubstituteImpl(subst, &diff).As<Type>(); - if(!diff) - return this; - - (*ioDiff)++; - - return getSession()->getRateQualifiedType(substRate, substValueType); - } - - RefPtr<Type> RateQualifiedType::CreateCanonicalType() - { - RefPtr<Type> canRate = rate->GetCanonicalType(); - RefPtr<Type> canValueType = valueType->GetCanonicalType(); - - RefPtr<RateQualifiedType> canRateQualifiedType = new RateQualifiedType(); - canRateQualifiedType->setSession(session); - canRateQualifiedType->rate = canRate; - canRateQualifiedType->valueType = valueType; - return canRateQualifiedType; - } + // DeclRefType - int RateQualifiedType::GetHashCode() + String DeclRefType::ToString() { - auto hash = (int)(typeid(this).hash_code()); - hash = combineHash(hash, rate->GetHashCode()); - hash = combineHash(hash, valueType->GetHashCode()); - return hash; + return declRef.toString(); } - // ConstExprRate - - Slang::String ConstExprRate::ToString() + int DeclRefType::GetHashCode() { - return "ConstExpr"; + return (declRef.GetHashCode() * 16777619) ^ (int)(typeid(this).hash_code()); } - bool ConstExprRate::EqualsImpl(Type * type) + bool DeclRefType::EqualsImpl(Type * type) { - auto constExprRate = type->As<ConstExprRate>(); - if(!constExprRate) - return false; - - return true; + if (auto declRefType = type->AsDeclRefType()) + { + return declRef.Equals(declRefType->declRef); + } + return false; } - RefPtr<Val> ConstExprRate::SubstituteImpl(SubstitutionSet /*subst*/, int* /*ioDiff*/) + RefPtr<Type> DeclRefType::CreateCanonicalType() { + // A declaration reference is already canonical return this; } - RefPtr<Type> ConstExprRate::CreateCanonicalType() - { - return this; - } + // + // RequirementWitness + // - int ConstExprRate::GetHashCode() - { - auto hash = (int)(typeid(this).hash_code()); - return hash; - } + RequirementWitness::RequirementWitness(RefPtr<Val> val) + : m_flavor(Flavor::val) + , m_obj(val) + {} - // GroupSharedType - Slang::String GroupSharedType::ToString() - { - return "@ThreadGroup " + valueType->ToString(); - } + RequirementWitness::RequirementWitness(RefPtr<WitnessTable> witnessTable) + : m_flavor(Flavor::witnessTable) + , m_obj(witnessTable) + {} - bool GroupSharedType::EqualsImpl(Type * type) + RefPtr<WitnessTable> RequirementWitness::getWitnessTable() { - auto t = type->As<GroupSharedType>(); - if (!t) - return false; - return valueType->Equals(t->valueType); + SLANG_ASSERT(getFlavor() == Flavor::witnessTable); + return m_obj.As<WitnessTable>(); } - RefPtr<Type> GroupSharedType::CreateCanonicalType() - { - auto canonicalValueType = valueType->GetCanonicalType(); - auto canonicalGroupSharedType = getSession()->getGroupSharedType(canonicalValueType); - return canonicalGroupSharedType; - } - int GroupSharedType::GetHashCode() + RequirementWitness RequirementWitness::specialize(SubstitutionSet const& subst) { - return combineHash( - valueType->GetHashCode(), - (int)(typeid(this).hash_code())); - } - - // DeclRefType + switch(getFlavor()) + { + default: + SLANG_UNEXPECTED("unknown requirement witness flavor"); + case RequirementWitness::Flavor::none: + return RequirementWitness(); - String DeclRefType::ToString() - { - return declRef.toString(); - } + case RequirementWitness::Flavor::declRef: + { + int diff = 0; + return RequirementWitness( + getDeclRef().SubstituteImpl(subst, &diff)); + } - int DeclRefType::GetHashCode() - { - return (declRef.GetHashCode() * 16777619) ^ (int)(typeid(this).hash_code()); + case RequirementWitness::Flavor::val: + return RequirementWitness( + getVal()->Substitute(subst)); + } } - bool DeclRefType::EqualsImpl(Type * type) + RequirementWitness tryLookUpRequirementWitness( + SubtypeWitness* subtypeWitness, + Decl* requirementKey) { - if (auto declRefType = type->AsDeclRefType()) + if(auto declaredSubtypeWitness = dynamic_cast<DeclaredSubtypeWitness*>(subtypeWitness)) { - return declRef.Equals(declRefType->declRef); + if(auto inheritanceDeclRef = declaredSubtypeWitness->declRef.As<InheritanceDecl>()) + { + // A conformance that was declared as part of an inheritance clause + // will have built up a dictionary of the satisfying declarations + // for each of its requirements. + RequirementWitness requirementWitness; + auto witnessTable = inheritanceDeclRef.getDecl()->witnessTable; + if(witnessTable && witnessTable->requirementDictionary.TryGetValue(requirementKey, requirementWitness)) + { + // The `inheritanceDeclRef` has substitutions applied to it that + // *aren't* present in the `requirementWitness`, because it was + // derived by the front-end when looking at the `InheritanceDecl` alone. + // + // We need to apply these substitutions here for the result to make sense. + // + // E.g., if we have a case like: + // + // interface ISidekick { associatedtype Hero; void follow(Hero hero); } + // struct Sidekick<H> : ISidekick { typedef H Hero; void follow(H hero) {} }; + // + // void followHero<S : ISidekick>(S s, S.Hero h) + // { + // s.follow(h); + // } + // + // Batman batman; + // Sidekick<Batman> robin; + // followHero<Sidekick<Batman>>(robin, batman); + // + // The second argument to `followHero` is `batman`, which has type `Batman`. + // The parameter declaration lists the type `S.Hero`, which is a reference + // to an associated type. The front end will expand this into something + // like `S.{S:ISidekick}.Hero` - that is, we'll end up with a declaration + // reference to `ISidekick.Hero` with a this-type substitution that references + // the `{S:ISidekick}` declaration as a witness. + // + // The front-end will expand the generic appliation `followHero<Sidekick<Batman>>` + // to `followHero<Sidekick<Batman>, {Sidekick<H>:ISidekick}[H->Batman]>` + // (that is, the hidden second parameter will reference the inheritance + // clause on `Sidekick<H>`, with a substitution to map `H` to `Batman`. + // + // This step should map the `{S:ISidekick}` declaration over to the + // concrete `{Sidekick<H>:ISidekick}[H->Batman]` inheritance declaration. + // At that point `tryLookupRequirementWitness` might be called, because + // we want to look up the witness for the key `ISidekick.Hero` in the + // inheritance decl-ref that is `{Sidekick<H>:ISidekick}[H->Batman]`. + // + // That lookup will yield us a reference to the typedef `Sidekick<H>.Hero`, + // *without* any substitution for `H` (or rather, with a default one that + // maps `H` to `H`. + // + // So, in order to get the *right* end result, we need to apply + // the substitutions from the inheritance decl-ref to the witness. + // + requirementWitness = requirementWitness.specialize(inheritanceDeclRef.substitutions); + + return requirementWitness; + } + } } - return false; - } - RefPtr<Type> DeclRefType::CreateCanonicalType() - { - // A declaration reference is already canonical - return this; + // TODO: should handle the transitive case here too + + return RequirementWitness(); } RefPtr<Val> DeclRefType::SubstituteImpl(SubstitutionSet subst, int* ioDiff) @@ -579,9 +547,12 @@ void Type::accept(IValVisitor* visitor, void* extra) if (auto genericTypeParamDecl = dynamic_cast<GenericTypeParamDecl*>(declRef.getDecl())) { // search for a substitution that might apply to us - for (auto s = subst.genericSubstitutions; s; s = s->outer.Ptr()) + for(auto s = subst.substitutions; s; s = s->outer) { - auto genericSubst = s; + auto genericSubst = s.As<GenericSubstitution>(); + if(!genericSubst) + continue; + // the generic decl associated with the substitution list must be // the generic decl that declared this parameter auto genericDecl = genericSubst->genericDecl; @@ -611,50 +582,15 @@ void Type::accept(IValVisitor* visitor, void* extra) } } } - // the second case we care about is when this decl type refers to an associatedtype decl - // we want to replace it with the actual associated type - else if (auto assocTypeDecl = dynamic_cast<AssocTypeDecl*>(declRef.getDecl())) - { - auto thisSubst = getThisTypeSubst(declRef, false); - auto oldSubstSrc = thisSubst ? thisSubst->sourceType : nullptr; - bool restore = false; - if (thisSubst && thisSubst->sourceType.Ptr() == dynamic_cast<Val*>(this)) - thisSubst->sourceType = nullptr; - auto newSubst = substituteSubstitutions(declRef.substitutions, subst, ioDiff); - if (restore) - thisSubst->sourceType = oldSubstSrc; - if (auto thisTypeSubst = newSubst.thisTypeSubstitution) - { - if (thisTypeSubst->sourceType) - { - if (auto aggTypeDeclRef = thisTypeSubst->sourceType.As<DeclRefType>()->declRef.As<AggTypeDecl>()) - { - Decl * targetType = nullptr; - if (aggTypeDeclRef.getDecl()->memberDictionary.TryGetValue(assocTypeDecl->getName(), targetType)) - { - if (auto typeDefDecl = dynamic_cast<TypeDefDecl*>(targetType)) - { - DeclRef<TypeDefDecl> targetTypeDeclRef(typeDefDecl, aggTypeDeclRef.substitutions); - return GetType(targetTypeDeclRef); - } - else if (auto targetAggType = dynamic_cast<AggTypeDecl*>(targetType)) - { - return DeclRefType::Create(getSession(), DeclRef<Decl>(targetAggType, aggTypeDeclRef.substitutions)); - } - else - { - SLANG_UNIMPLEMENTED_X("unknown assoctype implementation type."); - } - } - } - } - } - } else if (auto globalGenParam = dynamic_cast<GlobalGenericParamDecl*>(declRef.getDecl())) { // search for a substitution that might apply to us - for (auto genericSubst = subst.globalGenParamSubstitutions; genericSubst; genericSubst = genericSubst->outer.Ptr()) + for(auto s = subst.substitutions; s; s = s->outer) { + auto genericSubst = s.As<GlobalGenericParamSubstitution>(); + if(!genericSubst) + continue; + if (genericSubst->paramDecl == globalGenParam) { (*ioDiff)++; @@ -671,6 +607,45 @@ void Type::accept(IValVisitor* visitor, void* extra) // Make sure to record the difference! *ioDiff += diff; + // If this type is a reference to an associated type declaration, + // and the substitutions provide a "this type" substitution for + // the outer interface, then try to replace the type with the + // actual value of the associated type for the given implementation. + // + if(auto substAssocTypeDecl = substDeclRef.decl->As<AssocTypeDecl>()) + { + for(auto s = substDeclRef.substitutions.substitutions; s; s = s->outer) + { + auto thisSubst = s.As<ThisTypeSubstitution>(); + if(!thisSubst) + continue; + + if(auto interfaceDecl = substAssocTypeDecl->ParentDecl->As<InterfaceDecl>()) + { + if(thisSubst->interfaceDecl == interfaceDecl) + { + // We need to look up the declaration that satisfies + // the requirement named by the associated type. + Decl* requirementKey = substAssocTypeDecl; + RequirementWitness requirementWitness = tryLookUpRequirementWitness(thisSubst->witness, requirementKey); + switch(requirementWitness.getFlavor()) + { + default: + // No usable value was found, so there is nothing we can do. + break; + + case RequirementWitness::Flavor::val: + { + auto satisfyingVal = requirementWitness.getVal(); + return satisfyingVal; + } + break; + } + } + } + } + } + // Re-construct the type in case we are using a specialized sub-class return DeclRefType::Create(getSession(), substDeclRef); } @@ -689,9 +664,7 @@ void Type::accept(IValVisitor* visitor, void* extra) return intVal; } - // TODO: need to figure out how to unify this with the logic - // in the generic case... - DeclRefType* DeclRefType::Create( + DeclRef<Decl> createDefaultSubstitutionsIfNeeded( Session* session, DeclRef<Decl> declRef) { @@ -701,30 +674,81 @@ void Type::accept(IValVisitor* visitor, void* extra) // within its own member functions). To handle this case, // we will construct a default specialization at the use // site if needed. + // + // This same logic should also apply to declarations nested + // more than one level inside of a generic (e.g., a `typdef` + // inside of a generic `struct`). + // + // Similarly, it needs to work for multiple levels of + // nested generics. + // + + // We are going to build up a list of substitutions that need + // to be applied to the decl-ref to make it specialized. + RefPtr<Substitutions> substsToApply; + RefPtr<Substitutions>* link = &substsToApply; - if (auto genericParent = declRef.GetParent().As<GenericDecl>()) + RefPtr<Decl> dd = declRef.getDecl(); + for(;;) { - auto subst = declRef.substitutions; - // try find a substitution targeting this generic decl - bool substFound = false; - for (auto genSubst = subst.genericSubstitutions; genSubst; genSubst = genSubst->outer) + RefPtr<Decl> childDecl = dd; + RefPtr<Decl> parentDecl = dd->ParentDecl; + if(!parentDecl) + break; + + dd = parentDecl; + + if(auto genericParentDecl = parentDecl.As<GenericDecl>()) { - if (genSubst->genericDecl == genericParent.decl) + // Don't specialize any parameters of a generic. + if(childDecl != genericParentDecl->inner) + break; + + // We have a generic ancestor, but do we have an substitutions for it? + RefPtr<GenericSubstitution> foundSubst; + for(auto s = declRef.substitutions.substitutions; s; s = s->outer) { - substFound = true; + auto genSubst = s.As<GenericSubstitution>(); + if(!genSubst) + continue; + + if(genSubst->genericDecl != genericParentDecl) + continue; + + // Okay, we found a matching substitution, + // so there is nothing to be done. + foundSubst = genSubst; break; } - } - // we did not find an existing substituion, create a default one - if (!substFound) - { - declRef.substitutions = createDefaultSubstitutions( - session, - declRef.decl, - subst); + + if(!foundSubst) + { + RefPtr<Substitutions> newSubst = createDefaultSubsitutionsForGeneric( + session, + genericParentDecl, + nullptr); + + *link = newSubst; + link = &newSubst->outer; + } } } + if(!substsToApply) + return declRef; + + int diff = 0; + return declRef.SubstituteImpl(substsToApply, &diff); + } + + // TODO: need to figure out how to unify this with the logic + // in the generic case... + DeclRefType* DeclRefType::Create( + Session* session, + DeclRef<Decl> declRef) + { + declRef = createDefaultSubstitutionsIfNeeded(session, declRef); + if (auto builtinMod = declRef.getDecl()->FindModifier<BuiltinTypeModifier>()) { auto type = new BasicExpressionType(builtinMod->tag); @@ -734,7 +758,15 @@ void Type::accept(IValVisitor* visitor, void* extra) } else if (auto magicMod = declRef.getDecl()->FindModifier<MagicTypeModifier>()) { - GenericSubstitution* subst = declRef.substitutions.genericSubstitutions.Ptr(); + GenericSubstitution* subst = nullptr; + for(auto s = declRef.substitutions.substitutions; s; s = s->outer) + { + if(auto genericSubst = s.As<GenericSubstitution>()) + { + subst = genericSubst; + break; + } + } if (magicMod->name == "SamplerState") { @@ -910,28 +942,6 @@ void Type::accept(IValVisitor* visitor, void* extra) return (int)(int64_t)(void*)this; } - // IRBasicBlockType - - String IRBasicBlockType::ToString() - { - return "Block"; - } - - bool IRBasicBlockType::EqualsImpl(Type * /*type*/) - { - return false; - } - - RefPtr<Type> IRBasicBlockType::CreateCanonicalType() - { - return this; - } - - int IRBasicBlockType::GetHashCode() - { - return (int)(int64_t)(void*)this; - } - // InitializerListType String InitializerListType::ToString() @@ -1196,6 +1206,18 @@ void Type::accept(IValVisitor* visitor, void* extra) return elementType->AsBasicType(); } + // + + RefPtr<GenericSubstitution> findInnerMostGenericSubstitution(Substitutions* subst) + { + for(RefPtr<Substitutions> s = subst; s; s = s->outer) + { + if(auto genericSubst = s.As<GenericSubstitution>()) + return genericSubst; + } + return nullptr; + } + // MatrixExpressionType String MatrixExpressionType::ToString() @@ -1212,24 +1234,24 @@ void Type::accept(IValVisitor* visitor, void* extra) Type* MatrixExpressionType::getElementType() { - return this->declRef.substitutions.genericSubstitutions->args[0].As<Type>().Ptr(); + return findInnerMostGenericSubstitution(declRef.substitutions)->args[0].As<Type>().Ptr(); } IntVal* MatrixExpressionType::getRowCount() { - return this->declRef.substitutions.genericSubstitutions->args[1].As<IntVal>().Ptr(); + return findInnerMostGenericSubstitution(declRef.substitutions)->args[1].As<IntVal>().Ptr(); } IntVal* MatrixExpressionType::getColumnCount() { - return this->declRef.substitutions.genericSubstitutions->args[2].As<IntVal>().Ptr(); + return findInnerMostGenericSubstitution(declRef.substitutions)->args[2].As<IntVal>().Ptr(); } // PtrTypeBase Type* PtrTypeBase::getValueType() { - return this->declRef.substitutions.genericSubstitutions->args[0].As<Type>().Ptr(); + return findInnerMostGenericSubstitution(declRef.substitutions)->args[0].As<Type>().Ptr(); } // GenericParamIntVal @@ -1256,9 +1278,13 @@ void Type::accept(IValVisitor* visitor, void* extra) RefPtr<Val> GenericParamIntVal::SubstituteImpl(SubstitutionSet subst, int* ioDiff) { // search for a substitution that might apply to us - for (auto genSubst = subst.genericSubstitutions; genSubst; genSubst = genSubst->outer.Ptr()) + for(auto s = subst.substitutions; s; s = s->outer) { - // the generic decl associated with the substitution list must be + auto genSubst = s.As<GenericSubstitution>(); + if(!genSubst) + continue; + + // the generic decl associated with the substitution list must be // the generic decl that declared this parameter auto genericDecl = genSubst->genericDecl; if (genericDecl != declRef.getDecl()->ParentDecl) @@ -1293,17 +1319,18 @@ void Type::accept(IValVisitor* visitor, void* extra) // Substitutions - RefPtr<Substitutions> GenericSubstitution::SubstituteImpl(SubstitutionSet subst, int* ioDiff) + RefPtr<Substitutions> GenericSubstitution::applySubstitutionsShallow(SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff) { if (!this) return nullptr; int diff = 0; - auto outerSubst = outer ? outer->SubstituteImpl(subst, &diff) : nullptr; + + if(substOuter != outer) diff++; List<RefPtr<Val>> substArgs; for (auto a : args) { - substArgs.Add(a->SubstituteImpl(subst, &diff)); + substArgs.Add(a->SubstituteImpl(substSet, &diff)); } if (!diff) return this; @@ -1312,7 +1339,7 @@ void Type::accept(IValVisitor* visitor, void* extra) auto substSubst = new GenericSubstitution(); substSubst->genericDecl = genericDecl; substSubst->args = substArgs; - substSubst->outer = outerSubst.As<GenericSubstitution>(); + substSubst->outer = substOuter; return substSubst; } @@ -1344,75 +1371,72 @@ void Type::accept(IValVisitor* visitor, void* extra) return true; } - RefPtr<Substitutions> ThisTypeSubstitution::SubstituteImpl(SubstitutionSet subst, int* ioDiff) + RefPtr<Substitutions> ThisTypeSubstitution::applySubstitutionsShallow(SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff) { if (!this) return nullptr; int diff = 0; - RefPtr<Val> newSourceType; - if (sourceType) - newSourceType = sourceType->SubstituteImpl(subst, &diff); - else - { - // this_type is a free variable, use this_type from subst - if (subst.thisTypeSubstitution) - { - if (subst.thisTypeSubstitution->sourceType != sourceType) - { - newSourceType = subst.thisTypeSubstitution->sourceType; - diff = 1; - } - } - } + + if(substOuter != outer) diff++; + auto substWitness = witness->SubstituteImpl(substSet, &diff).As<SubtypeWitness>(); + if (!diff) return this; (*ioDiff)++; auto substSubst = new ThisTypeSubstitution(); - substSubst->sourceType = newSourceType; + substSubst->interfaceDecl = interfaceDecl; + substSubst->witness = substWitness; + substSubst->outer = substOuter; return substSubst; } bool ThisTypeSubstitution::Equals(Substitutions* subst) { if (!subst) - return true; + return this == nullptr; if (auto thisTypeSubst = dynamic_cast<ThisTypeSubstitution*>(subst)) { - if (!sourceType || !thisTypeSubst->sourceType) - return true; - return sourceType->EqualsVal(thisTypeSubst->sourceType); + return witness->EqualsVal(thisTypeSubst->witness); } return false; } - RefPtr<Substitutions> GlobalGenericParamSubstitution::SubstituteImpl(SubstitutionSet subst, int* ioDiff) + int ThisTypeSubstitution::GetHashCode() const + { + return witness->GetHashCode(); + } + + RefPtr<Substitutions> GlobalGenericParamSubstitution::applySubstitutionsShallow(SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff) { // if we find a GlobalGenericParamSubstitution in subst that references the same __generic_param decl // return a copy of that GlobalGenericParamSubstitution int diff = 0; - RefPtr<Substitutions> outerSubst = outer ? outer->SubstituteImpl(subst, &diff) : nullptr; - for (auto gSubst = subst.globalGenParamSubstitutions; gSubst; gSubst = gSubst->outer) - { - if (gSubst->paramDecl == paramDecl) - { - // substitute only if we are really different - if (!gSubst->actualType->EqualsVal(actualType)) - { - RefPtr<GlobalGenericParamSubstitution> rs = new GlobalGenericParamSubstitution(*gSubst); - rs->outer = outerSubst.As<GlobalGenericParamSubstitution>(); - return rs; - } - } - } - if (diff) + if(substOuter != outer) diff++; + + auto substActualType = actualType->SubstituteImpl(substSet, &diff).As<Type>(); + + List<ConstraintArg> substConstraintArgs; + for(auto constraintArg : constraintArgs) { - *ioDiff++; - RefPtr<GlobalGenericParamSubstitution> rs = new GlobalGenericParamSubstitution(*this); - rs->outer = outerSubst.As<GlobalGenericParamSubstitution>(); - return rs; + ConstraintArg substConstraintArg; + substConstraintArg.decl = constraintArg.decl; + substConstraintArg.val = constraintArg.val->SubstituteImpl(substSet, &diff); + + substConstraintArgs.Add(substConstraintArg); } - return this; + + if(!diff) + return this; + + (*ioDiff)++; + + RefPtr<GlobalGenericParamSubstitution> substSubst = new GlobalGenericParamSubstitution(); + substSubst->paramDecl = paramDecl; + substSubst->actualType = substActualType; + substSubst->constraintArgs = substConstraintArgs; + substSubst->outer = substOuter; + return substSubst; } bool GlobalGenericParamSubstitution::Equals(Substitutions* subst) @@ -1425,13 +1449,11 @@ void Type::accept(IValVisitor* visitor, void* extra) return false; if (!actualType->EqualsVal(genSubst->actualType)) return false; - if (witnessTables.Count() != genSubst->witnessTables.Count()) + if (constraintArgs.Count() != genSubst->constraintArgs.Count()) return false; - for (UInt i = 0; i < witnessTables.Count(); i++) + for (UInt i = 0; i < constraintArgs.Count(); i++) { - if (!witnessTables[i].Key->Equals(genSubst->witnessTables[i].Key)) - return false; - if (!witnessTables[i].Value->EqualsVal(genSubst->witnessTables[i].Value)) + if (!constraintArgs[i].val->EqualsVal(genSubst->constraintArgs[i].val)) return false; } return true; @@ -1474,74 +1496,354 @@ void Type::accept(IValVisitor* visitor, void* extra) UNREACHABLE_RETURN(expr); } - bool hasGlobalGenericSubst(SubstitutionSet destSubst, GlobalGenericParamSubstitution * genSubst) + void buildMemberDictionary(ContainerDecl* decl); + + InterfaceDecl* findOuterInterfaceDecl(Decl* decl) { - for (auto subst = destSubst.globalGenParamSubstitutions; subst; subst = subst->outer) + Decl* dd = decl; + while(dd) { - if (subst->paramDecl == genSubst->paramDecl) - return true; + if(auto interfaceDecl = dd->As<InterfaceDecl>()) + return interfaceDecl; + + dd = dd->ParentDecl; } - return false; + return nullptr; } - void insertGlobalGenericSubstitutions(SubstitutionSet & destSubst, SubstitutionSet srcSubst, int * ioDiff) + + RefPtr<GlobalGenericParamSubstitution> findGlobalGenericSubst( + RefPtr<Substitutions> substs, + GlobalGenericParamDecl* paramDecl) { - int diff = 0; - - if (auto globalGenSubst = srcSubst.globalGenParamSubstitutions) + for(auto s = substs; s; s = s->outer) { - if (!hasGlobalGenericSubst(destSubst, globalGenSubst)) - { - RefPtr<GlobalGenericParamSubstitution> cpyGlobalGenSubst = new GlobalGenericParamSubstitution(*globalGenSubst); - cpyGlobalGenSubst->outer = destSubst.globalGenParamSubstitutions; - destSubst.globalGenParamSubstitutions = cpyGlobalGenSubst; - diff = 1; - } + auto gSubst = s.As<GlobalGenericParamSubstitution>(); + if(!gSubst) + continue; + + if(gSubst->paramDecl != paramDecl) + continue; + + return gSubst; } - *ioDiff += diff; + + return nullptr; } - void buildMemberDictionary(ContainerDecl* decl); + RefPtr<Substitutions> specializeSubstitutionsShallow( + RefPtr<Substitutions> substToSpecialize, + RefPtr<Substitutions> substsToApply, + RefPtr<Substitutions> restSubst, + int* ioDiff) + { + return substToSpecialize->applySubstitutionsShallow(substsToApply, restSubst, ioDiff); + } - DeclRefBase DeclRefBase::SubstituteImpl(SubstitutionSet subst, int* ioDiff) + RefPtr<Substitutions> specializeGlobalGenericSubstitutions( + Decl* declToSpecialize, + RefPtr<Substitutions> substsToSpecialize, + RefPtr<Substitutions> substsToApply, + int* ioDiff, + HashSet<GlobalGenericParamDecl*>& ioParametersFound) { - int diff = 0; - auto substSubst = substituteSubstitutions(substitutions, subst, &diff); - if (!diff) - return *this; + // Any existing global-generic substitutions will trigger + // a recursive case that skips the rest of the function. + for(auto specSubst = substsToSpecialize; specSubst; specSubst = specSubst->outer) + { + auto specGlobalGenericSubst = specSubst.As<GlobalGenericParamSubstitution>(); + if(!specGlobalGenericSubst) + continue; - *ioDiff += diff; + ioParametersFound.Add(specGlobalGenericSubst->paramDecl); - 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>()) + int diff = 0; + auto restSubst = specializeGlobalGenericSubstitutions( + declToSpecialize, + specSubst->outer, + substsToApply, + &diff, + ioParametersFound); + + auto firstSubst = specializeSubstitutionsShallow( + specGlobalGenericSubst, + substsToApply, + restSubst, + &diff); + + *ioDiff += diff; + return firstSubst; + } + + // No more existing substitutions, so we know we can apply + // our global generic substitutions without any special work. + + // We expect global generic substitutions to come at + // the end of the list in all cases, so lets advance + // until we see them. + RefPtr<Substitutions> appGlobalGenericSubsts = substsToApply; + while(appGlobalGenericSubsts && !appGlobalGenericSubsts.As<GlobalGenericParamSubstitution>()) + appGlobalGenericSubsts = appGlobalGenericSubsts->outer; + + + // If there is nothing to apply, then we are done + if(!appGlobalGenericSubsts) + return nullptr; + + // Otherwise, it seems like something has to change. + (*ioDiff)++; + + // If there were no parameters bound by the existing substitution, + // then we can safely use the global generics from the to-apply set. + if(ioParametersFound.Count() == 0) + return appGlobalGenericSubsts; + + RefPtr<Substitutions> resultSubst; + RefPtr<Substitutions>* link = &resultSubst; + for(auto appSubst = appGlobalGenericSubsts; appSubst; appSubst = appSubst->outer) { - auto thisSubst = getThisTypeSubst(substDeclRef, false); - if (thisSubst) + auto appGlobalGenericSubst = appSubst.As<GlobalGenericParamSubstitution>(); + if(!appSubst) + continue; + + // Don't include substitutions for parameters already handled. + if(ioParametersFound.Contains(appGlobalGenericSubst->paramDecl)) + continue; + + RefPtr<GlobalGenericParamSubstitution> newSubst = new GlobalGenericParamSubstitution(); + newSubst->paramDecl = appGlobalGenericSubst->paramDecl; + newSubst->actualType = appGlobalGenericSubst->actualType; + newSubst->constraintArgs = appGlobalGenericSubst->constraintArgs; + + *link = newSubst; + link = &newSubst->outer; + } + + return resultSubst; + } + + RefPtr<Substitutions> specializeGlobalGenericSubstitutions( + Decl* declToSpecialize, + RefPtr<Substitutions> substsToSpecialize, + RefPtr<Substitutions> substsToApply, + int* ioDiff) + { + // Keep track of any parameters already present in the + // existing substitution. + HashSet<GlobalGenericParamDecl*> parametersFound; + return specializeGlobalGenericSubstitutions(declToSpecialize, substsToSpecialize, substsToApply, ioDiff, parametersFound); + } + + + // Construct new substitutions to apply to a declaration, + // based on a provided substituion set to be applied + RefPtr<Substitutions> specializeSubstitutions( + Decl* declToSpecialize, + RefPtr<Substitutions> substsToSpecialize, + RefPtr<Substitutions> substsToApply, + int* ioDiff) + { + // No declaration? Then nothing to specialize. + if(!declToSpecialize) + return nullptr; + + // No (remaining) substitutions to apply? Then we are done. + if(!substsToApply) + return substsToSpecialize; + + // Walk the hierarchy of the declaration to determine what specializations might apply. + // We assume that the `substsToSpecialize` must be aligned with the ancestor + // hierarchy of `declToSpecialize` such that if, e.g., the `declToSpecialize` is + // nested directly in a generic, then `substToSpecialize` will either start with + // the corresponding `GenericSubstitution` or there will be *no* generic substitutions + // corresponding to that decl. + for(Decl* ancestorDecl = declToSpecialize; ancestorDecl; ancestorDecl = ancestorDecl->ParentDecl) + { + if(auto ancestorGenericDecl = ancestorDecl->As<GenericDecl>()) { - if (auto declRefType = thisSubst->sourceType.As<DeclRefType>()) + // The declaration is nested inside a generic. + // Does it already have a specialization for that generic? + if(auto specGenericSubst = substsToSpecialize.As<GenericSubstitution>()) { - if (auto aggDeclRef = declRefType->declRef.As<StructDecl>()) + if(specGenericSubst->genericDecl == ancestorGenericDecl) { - 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); + // Yes. We have an existing specialization, so we will + // keep one matching it in place. + int diff = 0; + auto restSubst = specializeSubstitutions( + ancestorGenericDecl->ParentDecl, + specGenericSubst->outer, + substsToApply, + &diff); + + auto firstSubst = specializeSubstitutionsShallow( + specGenericSubst, + substsToApply, + restSubst, + &diff); + + *ioDiff += diff; + return firstSubst; + } + } + + // If the declaration is not already specialized + // for the given generic, then see if we are trying + // to *apply* such specializations to it. + // + // TODO: The way we handle things right now with + // "default" specializations, this case shouldn't + // actually come up. + // + for(auto s = substsToApply; s; s = s->outer) + { + auto appGenericSubst = s.As<GenericSubstitution>(); + if(!appGenericSubst) + continue; + + if(appGenericSubst->genericDecl != ancestorGenericDecl) + continue; + + // The substitutions we are applying are trying + // to specialize this generic, but we don't already + // have a generic substitution in place. + // We will need to create one. + + int diff = 0; + auto restSubst = specializeSubstitutions( + ancestorGenericDecl->ParentDecl, + substsToSpecialize, + substsToApply, + &diff); + + RefPtr<GenericSubstitution> firstSubst = new GenericSubstitution(); + firstSubst->genericDecl = ancestorGenericDecl; + firstSubst->args = appGenericSubst->args; + firstSubst->outer = restSubst; + + (*ioDiff)++; + return firstSubst; + } + } + else if(auto ancestorInterfaceDecl = ancestorDecl->As<InterfaceDecl>()) + { + // The task is basically the same as for the generic case: + // We want to see if there is any existing substitution that + // applies to this declaration, and use that if possible. + + // The declaration is nested inside a generic. + // Does it already have a specialization for that generic? + if(auto specThisTypeSubst = substsToSpecialize.As<ThisTypeSubstitution>()) + { + if(specThisTypeSubst->interfaceDecl == ancestorInterfaceDecl) + { + // Yes. We have an existing specialization, so we will + // keep one matching it in place. + int diff = 0; + auto restSubst = specializeSubstitutions( + ancestorInterfaceDecl->ParentDecl, + specThisTypeSubst->outer, + substsToApply, + &diff); + + auto firstSubst = specializeSubstitutionsShallow( + specThisTypeSubst, + substsToApply, + restSubst, + &diff); + + *ioDiff += diff; + return firstSubst; } } + + // Otherwise, check if we are trying to apply + // a this-type substitution to the given interface + // + for(auto s = substsToApply; s; s = s->outer) + { + auto appThisTypeSubst = s.As<ThisTypeSubstitution>(); + if(!appThisTypeSubst) + continue; + + if(appThisTypeSubst->interfaceDecl != ancestorInterfaceDecl) + continue; + + int diff = 0; + auto restSubst = specializeSubstitutions( + ancestorInterfaceDecl->ParentDecl, + substsToSpecialize, + substsToApply, + &diff); + + RefPtr<ThisTypeSubstitution> firstSubst = new ThisTypeSubstitution(); + firstSubst->interfaceDecl = ancestorInterfaceDecl; + firstSubst->witness = appThisTypeSubst->witness; + firstSubst->outer = restSubst; + + (*ioDiff)++; + return firstSubst; + } } } + + // If we reach here then we've walked the full hierarchy up from + // `declToSpecialize` and either didn't run into an generic/interface + // declarations, or we didn't find any attempt to specialize them + // in either substitution. + // + // As an invariant, there should *not* be any generic or this-type + // substitutiosn in `substToSpecialize`, because otherwise they + // would be specializations that don't actually apply to the given + // declaration. + // + // The remaining substitutions to apply, if any, should thus be + // global-generic substitutions. And similarly, those are the + // only remaining substitutions we really care about in + // `substsToApply`. + // + // Note: this does *not* mean that `substsToApply` doesn't have + // any generic or this-type substitutions; it just means that none + // of them were applicable. + // + return specializeGlobalGenericSubstitutions( + declToSpecialize, + substsToSpecialize, + substsToApply, + ioDiff); + } + + DeclRefBase DeclRefBase::SubstituteImpl(SubstitutionSet substSet, int* ioDiff) + { + // Nothing to do when we have no declaration. + if(!decl) + return *this; + + // Apply the given substitutions to any specializations + // that have already been applied to this declaration. + int diff = 0; + + auto substSubst = specializeSubstitutions( + decl, + substitutions.substitutions, + substSet.substitutions, + &diff); + + if (!diff) + return *this; + + *ioDiff += diff; + + DeclRefBase substDeclRef; + substDeclRef.decl = decl; + substDeclRef.substitutions = substSubst; + + // TODO: The old code here used to try to translate a decl-ref + // to an associated type in a decl-ref for the concrete type + // in a paarticular implementation. + // + // I have only kept that logic in `DeclRefType::SubstituteImpl`, + // but it may turn out it is needed here too. + return substDeclRef; } @@ -1569,32 +1871,45 @@ void Type::accept(IValVisitor* visitor, void* extra) if (!parentDecl) return DeclRefBase(); - if (auto parentGeneric = dynamic_cast<GenericDecl*>(parentDecl)) + // Default is to apply the same set of substitutions/specializations + // to the parent declaration as were applied to the child. + RefPtr<Substitutions> substToApply = substitutions.substitutions; + + if(auto interfaceDecl = dynamic_cast<InterfaceDecl*>(decl)) { - auto genSubst = substitutions.genericSubstitutions; - if (genSubst && genSubst->genericDecl == parentDecl) - { - // We strip away the specializations that were applied to - // the parent, since we were asked for a reference *to* the parent. - return DeclRefBase(parentGeneric, SubstitutionSet(genSubst->outer, substitutions.thisTypeSubstitution, - substitutions.globalGenParamSubstitutions)); - } - else + // The declaration being referenced is an `interface` declaration, + // and there might be a this-type substitution in place. + // A reference to the parent of the interface declaration + // should not include that substitution. + if(auto thisTypeSubst = substToApply.As<ThisTypeSubstitution>()) { - // Either we don't have specializations, or the inner-most - // specializations didn't apply to the parent decl. This - // can happen if we are looking at an unspecialized - // declaration that is a child of a generic. - return DeclRefBase(parentGeneric, substitutions); + if(thisTypeSubst->interfaceDecl == interfaceDecl) + { + // Strip away that specializations that apply to the interface. + substToApply = thisTypeSubst->outer; + } } } - else + + if (auto parentGenericDecl = dynamic_cast<GenericDecl*>(parentDecl)) { - // If the parent isn't a generic, then it must - // use the same specializations as this declaration - return DeclRefBase(parentDecl, substitutions); + // The parent of this declaration is a generic, which means + // that the decl-ref to the current declaration might include + // substitutiosn that specialize the generic parameters. + // A decl-ref to the parent generic should *not* include + // those substitutions. + // + if(auto genericSubst = substToApply.As<GenericSubstitution>()) + { + if(genericSubst->genericDecl == parentGenericDecl) + { + // Strip away the specializations that were applied to the parent. + substToApply = genericSubst->outer; + } + } } + return DeclRefBase(parentDecl, substToApply); } int DeclRefBase::GetHashCode() const @@ -1706,12 +2021,12 @@ void Type::accept(IValVisitor* visitor, void* extra) Type* HLSLPatchType::getElementType() { - return this->declRef.substitutions.genericSubstitutions->args[0].As<Type>().Ptr(); + return findInnerMostGenericSubstitution(declRef.substitutions)->args[0].As<Type>().Ptr(); } IntVal* HLSLPatchType::getElementCount() { - return this->declRef.substitutions.genericSubstitutions->args[1].As<IntVal>().Ptr(); + return findInnerMostGenericSubstitution(declRef.substitutions)->args[1].As<IntVal>().Ptr(); } // Constructors for types @@ -1742,7 +2057,9 @@ void Type::accept(IValVisitor* visitor, void* extra) Session* session, DeclRef<TypeDefDecl> const& declRef) { - auto namedType = new NamedExpressionType(declRef); + DeclRef<TypeDefDecl> specializedDeclRef = createDefaultSubstitutionsIfNeeded(session, declRef).As<TypeDefDecl>(); + + auto namedType = new NamedExpressionType(specializedDeclRef); namedType->setSession(session); return namedType; } @@ -1828,64 +2145,141 @@ void Type::accept(IValVisitor* visitor, void* extra) && declRef.Equals(otherWitness->declRef); } + RefPtr<ThisTypeSubstitution> findThisTypeSubstitution( + Substitutions* substs, + InterfaceDecl* interfaceDecl) + { + for(RefPtr<Substitutions> s = substs; s; s = s->outer) + { + auto thisTypeSubst = s.As<ThisTypeSubstitution>(); + if(!thisTypeSubst) + continue; + + if(thisTypeSubst->interfaceDecl != interfaceDecl) + continue; + + return thisTypeSubst; + } + + return nullptr; + } + RefPtr<Val> DeclaredSubtypeWitness::SubstituteImpl(SubstitutionSet subst, int * ioDiff) { - if (auto genConstraintDecl = declRef.As<GenericTypeConstraintDecl>()) + if (auto genConstraintDeclRef = declRef.As<GenericTypeConstraintDecl>()) { + auto genConstraintDecl = genConstraintDeclRef.getDecl(); + // search for a substitution that might apply to us - for (auto genericSubst = subst.genericSubstitutions; genericSubst; genericSubst = genericSubst->outer.Ptr()) + for(auto s = subst.substitutions; s; s = s->outer) { - // the generic decl associated with the substitution list must be - // the generic decl that declared this parameter - auto genericDecl = genericSubst->genericDecl; - if (genericDecl != genConstraintDecl.getDecl()->ParentDecl) - continue; - bool found = false; - UInt index = 0; - for (auto m : genericDecl->Members) + if(auto genericSubst = s.As<GenericSubstitution>()) { - if (auto constraintParam = m.As<GenericTypeConstraintDecl>()) + // the generic decl associated with the substitution list must be + // the generic decl that declared this parameter + auto genericDecl = genericSubst->genericDecl; + if (genericDecl != genConstraintDecl->ParentDecl) + continue; + + bool found = false; + UInt index = 0; + for (auto m : genericDecl->Members) { - if (constraintParam.Ptr() == declRef.getDecl()) + if (auto constraintParam = m.As<GenericTypeConstraintDecl>()) { - found = true; - break; + if (constraintParam.Ptr() == declRef.getDecl()) + { + found = true; + break; + } + index++; } - index++; + } + if (found) + { + (*ioDiff)++; + auto ordinaryParamCount = genericDecl->getMembersOfType<GenericTypeParamDecl>().Count() + + genericDecl->getMembersOfType<GenericValueParamDecl>().Count(); + SLANG_ASSERT(index + ordinaryParamCount < genericSubst->args.Count()); + return genericSubst->args[index + ordinaryParamCount]; } } - if (found) + else if(auto globalGenericSubst = s.As<GlobalGenericParamSubstitution>()) { - (*ioDiff)++; - auto ordinaryParamCount = genericDecl->getMembersOfType<GenericTypeParamDecl>().Count() + - genericDecl->getMembersOfType<GenericValueParamDecl>().Count(); - SLANG_ASSERT(index + ordinaryParamCount < genericSubst->args.Count()); - return genericSubst->args[index + ordinaryParamCount]; + // check if the substitution is really about this global generic type parameter + if (globalGenericSubst->paramDecl != genConstraintDecl->ParentDecl) + continue; + + for(auto constraintArg : globalGenericSubst->constraintArgs) + { + if(constraintArg.decl.Ptr() != genConstraintDecl) + continue; + + (*ioDiff)++; + return constraintArg.val; + } } } - for (auto globalGenParamSubst = subst.globalGenParamSubstitutions; globalGenParamSubst; globalGenParamSubst = globalGenParamSubst->outer.Ptr()) - { - // we have a GlobalGenericParamSubstitution, this substitution will provide - // a concrete IRWitnessTable for a generic global variable - auto supType = GetSup(genConstraintDecl); + } - // check if the substitution is really about this global generic type parameter - if (globalGenParamSubst->paramDecl != genConstraintDecl.getDecl()->ParentDecl) - continue; + // Perform substitution on the constituent elements. + int diff = 0; + auto substSub = sub->SubstituteImpl(subst, &diff).As<Type>(); + auto substSup = sup->SubstituteImpl(subst, &diff).As<Type>(); + auto substDeclRef = declRef.SubstituteImpl(subst, &diff); + if (!diff) + return this; + + (*ioDiff)++; - // find witness table for the required interface - for (auto witness : globalGenParamSubst->witnessTables) - if (witness.Key->EqualsVal(supType)) + // If we have a reference to a type constraint for an + // associated type declaration, then we can replace it + // with the concrete conformance witness for a concrete + // type implementing the outer interface. + // + // TODO: It is a bit gross that we use `GenericTypeConstraintDecl` for + // associated types, when they aren't really generic type *parameters*, + // so we'll need to change this location in the code if we ever clean + // up the hierarchy. + // + if (auto substTypeConstraintDecl = substDeclRef.decl->As<GenericTypeConstraintDecl>()) + { + if (auto substAssocTypeDecl = substTypeConstraintDecl->ParentDecl->As<AssocTypeDecl>()) + { + if (auto interfaceDecl = substAssocTypeDecl->ParentDecl->As<InterfaceDecl>()) + { + // At this point we have a constraint decl for an associated type, + // and we nee to see if we are dealing with a concrete substitution + // for the interface around that associated type. + if(auto thisTypeSubst = findThisTypeSubstitution(substDeclRef.substitutions, interfaceDecl)) { - (*ioDiff)++; - return witness.Value; + // We need to look up the declaration that satisfies + // the requirement named by the associated type. + Decl* requirementKey = substTypeConstraintDecl; + RequirementWitness requirementWitness = tryLookUpRequirementWitness(thisTypeSubst->witness, requirementKey); + switch(requirementWitness.getFlavor()) + { + default: + break; + + case RequirementWitness::Flavor::val: + { + auto satisfyingVal = requirementWitness.getVal(); + return satisfyingVal; + } + } } + } } } + + + + RefPtr<DeclaredSubtypeWitness> rs = new DeclaredSubtypeWitness(); - rs->sub = sub->SubstituteImpl(subst, ioDiff).As<Type>(); - rs->sup = sup->SubstituteImpl(subst, ioDiff).As<Type>(); - rs->declRef = declRef.SubstituteImpl(subst, ioDiff); + rs->sub = substSub; + rs->sup = substSup; + rs->declRef = substDeclRef; return rs; } @@ -1918,7 +2312,7 @@ void Type::accept(IValVisitor* visitor, void* extra) return sub->Equals(otherWitness->sub) && sup->Equals(otherWitness->sup) && subToMid->EqualsVal(otherWitness->subToMid) - && midToSup->EqualsVal(otherWitness->midToSup); + && midToSup.Equals(otherWitness->midToSup); } RefPtr<Val> TransitiveSubtypeWitness::SubstituteImpl(SubstitutionSet subst, int * ioDiff) @@ -1928,7 +2322,7 @@ void Type::accept(IValVisitor* visitor, void* extra) RefPtr<Type> substSub = sub->SubstituteImpl(subst, &diff).As<Type>(); RefPtr<Type> substSup = sup->SubstituteImpl(subst, &diff).As<Type>(); RefPtr<SubtypeWitness> substSubToMid = subToMid->SubstituteImpl(subst, &diff).As<SubtypeWitness>(); - RefPtr<SubtypeWitness> substMidToSup = midToSup->SubstituteImpl(subst, &diff).As<SubtypeWitness>(); + DeclRef<Decl> substMidToSup = midToSup.SubstituteImpl(subst, &diff); // If nothing changed, then we can bail out early. if (!diff) @@ -1971,7 +2365,7 @@ void Type::accept(IValVisitor* visitor, void* extra) sb << "TransitiveSubtypeWitness("; sb << this->subToMid->ToString(); sb << ", "; - sb << this->midToSup->ToString(); + sb << this->midToSup.toString(); sb << ")"; return sb.ProduceString(); } @@ -1981,29 +2375,7 @@ void Type::accept(IValVisitor* visitor, void* extra) auto hash = sub->GetHashCode(); hash = combineHash(hash, sup->GetHashCode()); hash = combineHash(hash, subToMid->GetHashCode()); - hash = combineHash(hash, midToSup->GetHashCode()); - return hash; - } - - // IRProxyVal - - bool IRProxyVal::EqualsVal(Val* val) - { - auto otherProxy = dynamic_cast<IRProxyVal*>(val); - if(!otherProxy) - return false; - - return this->inst.get() == otherProxy->inst.get(); - } - - String IRProxyVal::ToString() - { - return "IRProxyVal(...)"; - } - - int IRProxyVal::GetHashCode() - { - auto hash = Slang::GetHashCode(inst.get()); + hash = combineHash(hash, midToSup.GetHashCode()); return hash; } @@ -2020,77 +2392,19 @@ void Type::accept(IValVisitor* visitor, void* extra) return name->text; } - RefPtr<ThisTypeSubstitution> getThisTypeSubst(DeclRefBase & declRef, bool insertSubstEntry) - { - RefPtr<ThisTypeSubstitution> thisSubst = declRef.substitutions.thisTypeSubstitution; - if (!thisSubst) - { - thisSubst = new ThisTypeSubstitution(); - if (insertSubstEntry) - { - declRef.substitutions.thisTypeSubstitution = thisSubst; - } - } - return thisSubst; - } - - RefPtr<ThisTypeSubstitution> getNewThisTypeSubst(DeclRefBase & declRef) - { - declRef.substitutions.thisTypeSubstitution = new ThisTypeSubstitution(); - return declRef.substitutions.thisTypeSubstitution; - } - - SubstitutionSet substituteSubstitutions(SubstitutionSet oldSubst, SubstitutionSet subst, int * ioDiff) - { - return oldSubst.substituteImpl(subst, ioDiff); - } - bool SubstitutionSet::Equals(SubstitutionSet substSet) const { - if (genericSubstitutions) - { - if (!genericSubstitutions->Equals(substSet.genericSubstitutions)) - return false; - } - else - { - if (substSet.genericSubstitutions) - return false; - } - if (thisTypeSubstitution) - { - if (!thisTypeSubstitution->Equals(substSet.thisTypeSubstitution)) - return false; - } - else - { - if (substSet.thisTypeSubstitution && substSet.thisTypeSubstitution->sourceType != nullptr) - return false; - } - return true; - } - SubstitutionSet SubstitutionSet::substituteImpl(SubstitutionSet subst, int * ioDiff) - { - SubstitutionSet rs; - if (genericSubstitutions) - rs.genericSubstitutions = genericSubstitutions->SubstituteImpl(subst, ioDiff).As<GenericSubstitution>(); - if (globalGenParamSubstitutions) - rs.globalGenParamSubstitutions = globalGenParamSubstitutions->SubstituteImpl(subst, ioDiff).As<GlobalGenericParamSubstitution>(); - if (thisTypeSubstitution) - rs.thisTypeSubstitution = thisTypeSubstitution->SubstituteImpl(subst, ioDiff).As<ThisTypeSubstitution>(); + if(!substitutions || !substSet.substitutions) + return substitutions == substSet.substitutions; - insertGlobalGenericSubstitutions(rs, subst, ioDiff); - return rs; + return substitutions->Equals(substSet.substitutions); } + int SubstitutionSet::GetHashCode() const { int rs = 0; - if (genericSubstitutions) - rs = combineHash(rs, genericSubstitutions->GetHashCode()); - if (thisTypeSubstitution) - rs = combineHash(rs, thisTypeSubstitution->GetHashCode()); - if (globalGenParamSubstitutions) - rs = combineHash(rs, globalGenParamSubstitutions->GetHashCode()); + if (substitutions) + rs = combineHash(rs, substitutions->GetHashCode()); return rs; } } |
