diff options
| author | Ellie Hermaszewska <ellieh@nvidia.com> | 2024-10-29 14:49:26 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-29 14:49:26 +0800 |
| commit | f65d756bff8d4c5cbc15bd0322a2ae8e6b896a21 (patch) | |
| tree | ea1d61342cd29368e19135000ec2948813096205 /source/slang/slang-check-conformance.cpp | |
| parent | a729c15e9dce9f5116a38afc66329ab2ca4cea54 (diff) | |
format
* format
* Minor test fixes
* enable checking cpp format in ci
Diffstat (limited to 'source/slang/slang-check-conformance.cpp')
| -rw-r--r-- | source/slang/slang-check-conformance.cpp | 618 |
1 files changed, 315 insertions, 303 deletions
diff --git a/source/slang/slang-check-conformance.cpp b/source/slang/slang-check-conformance.cpp index 9d9047e41..499b409ea 100644 --- a/source/slang/slang-check-conformance.cpp +++ b/source/slang/slang-check-conformance.cpp @@ -7,367 +7,379 @@ namespace Slang { - bool SemanticsVisitor::isInterfaceSafeForTaggedUnion( - DeclRef<InterfaceDecl> interfaceDeclRef) +bool SemanticsVisitor::isInterfaceSafeForTaggedUnion(DeclRef<InterfaceDecl> interfaceDeclRef) +{ + for (auto memberDeclRef : getMembers(m_astBuilder, interfaceDeclRef)) { - for( auto memberDeclRef : getMembers(m_astBuilder, interfaceDeclRef) ) - { - if(!isInterfaceRequirementSafeForTaggedUnion(interfaceDeclRef, memberDeclRef)) - return false; - } + if (!isInterfaceRequirementSafeForTaggedUnion(interfaceDeclRef, memberDeclRef)) + return false; + } + + return true; +} + +bool SemanticsVisitor::isInterfaceRequirementSafeForTaggedUnion( + DeclRef<InterfaceDecl> interfaceDeclRef, + DeclRef<Decl> requirementDeclRef) +{ + SLANG_UNUSED(interfaceDeclRef); + + if (auto callableDeclRef = requirementDeclRef.as<CallableDecl>()) + { + // A `static` method requirement can't be satisfied by a + // tagged union, because there is no tag to dispatch on. + // + if (requirementDeclRef.getDecl()->hasModifier<HLSLStaticModifier>()) + return false; + + // TODO: We will eventually want to check that any callable + // requirements do not use the `This` type or any associated + // types in ways that could lead to errors. + // + // For now we are disallowing interfaces that have associated + // types completely, and we haven't implemented the `This` + // type, so we should be safe. return true; } - - bool SemanticsVisitor::isInterfaceRequirementSafeForTaggedUnion( - DeclRef<InterfaceDecl> interfaceDeclRef, - DeclRef<Decl> requirementDeclRef) + else { - SLANG_UNUSED(interfaceDeclRef); + return false; + } +} - if(auto callableDeclRef = requirementDeclRef.as<CallableDecl>()) - { - // A `static` method requirement can't be satisfied by a - // tagged union, because there is no tag to dispatch on. - // - if(requirementDeclRef.getDecl()->hasModifier<HLSLStaticModifier>()) - return false; +SubtypeWitness* SemanticsVisitor::isSubtype( + Type* subType, + Type* superType, + IsSubTypeOptions isSubTypeOptions) +{ + SubtypeWitness* result = nullptr; + if (getShared()->tryGetSubtypeWitnessFromCache(subType, superType, result)) + return result; + result = checkAndConstructSubtypeWitness(subType, superType, isSubTypeOptions); - // TODO: We will eventually want to check that any callable - // requirements do not use the `This` type or any associated - // types in ways that could lead to errors. - // - // For now we are disallowing interfaces that have associated - // types completely, and we haven't implemented the `This` - // type, so we should be safe. + if (!result && (int(isSubTypeOptions) & int(IsSubTypeOptions::NoCaching))) + return result; - return true; - } - else + getShared()->cacheSubtypeWitness(subType, superType, result); + return result; +} + +SubtypeWitness* SemanticsVisitor::checkAndConstructSubtypeWitness( + Type* subType, + Type* superType, + IsSubTypeOptions isSubTypeOptions) +{ + // TODO: The Slang codebase is currently being quite slippery by conflating + // multiple concepts, all under the banner of a "subtype" test: + // + // * Struct/class inheritance: When concrete type `A` inherits from concrete + // type `B`, we can directly convert any value of type `A` into a value of type `B` + // + // * Derived interfaces: When interface `X` derives from interface `Y`, we know + // that any concrete type conforming to `X` must also conform to `Y`, so we can + // derive a witness that `A : Y` from a witness tbale that `A : X` for some concrete `A` + // + // * Conformance: When concrete type `A` conforms to interface `X`, we know that there exists + // a witness table for that conformance. + // + // The problem is that these relationships mean different things. If we use the same + // `isSubtype()` test for all of the above cases, then we risk determining that `IFoo` + // *conforms* to `IBar` just because it was declared as `interface IFoo : IBar`. Or + // even more simply that `IFoo` conforms to `IFoo`. + // + // It is dangerous to start treating an interface type like it conforms to itself: + // + // interface IFoo { static int getValue(); } + // int get< T : IFoo >() { return T.getValue(); } + // + // int x = get<IFoo>(); // This needs to be an error!!! + // + // We will eventually need to clarify the distinction between the different kinds of + // subtype-ish relationships, *or* we will need to ensure that `interface`s are not + // treated as proper types (such that they can be passed as generic arguments, etc.) + // + // Note that there is one more case of a subtype-ish relationship that is not covered + // by this function, but that is relevant if/when we do more serious type inference: + // + // * Convertibility: When any value of type `A` can be converted to a value of type + // `B` (even if that conversion might involve computation or a change of representation), + // and that conversion is one that the compiler considers "okay" to do implicitly. + // + // For now we are continuing to conflate all the subtype-ish relationships but not + // tangling convertibility into it. + + // First, make sure both sub type and super type decl are ready for lookup. + if (!(int(isSubTypeOptions) & int(IsSubTypeOptions::NoCaching))) + { + if (auto subDeclRefType = as<DeclRefType>(subType)) { - return false; + ensureDecl(subDeclRefType->getDeclRef().getDecl(), DeclCheckState::ReadyForLookup); } } - - SubtypeWitness* SemanticsVisitor::isSubtype( - Type* subType, - Type* superType, - IsSubTypeOptions isSubTypeOptions - ) + if (auto superDeclRefType = as<DeclRefType>(superType)) { - SubtypeWitness* result = nullptr; - if (getShared()->tryGetSubtypeWitnessFromCache(subType, superType, result)) - return result; - result = checkAndConstructSubtypeWitness(subType, superType, isSubTypeOptions); - - if(!result && (int(isSubTypeOptions) & int(IsSubTypeOptions::NoCaching))) - return result; - - getShared()->cacheSubtypeWitness(subType, superType, result); - return result; + ensureDecl(superDeclRefType->getDeclRef().getDecl(), DeclCheckState::ReadyForLookup); } - SubtypeWitness* SemanticsVisitor::checkAndConstructSubtypeWitness( - Type* subType, - Type* superType, - IsSubTypeOptions isSubTypeOptions) + // In the common case, we can use the pre-computed inheritance information for `subType` + // to enumerate all the types it transitively inherits from. + // + auto inheritanceInfo = getShared()->getInheritanceInfo(subType); + for (auto facet : inheritanceInfo.facets) { - // TODO: The Slang codebase is currently being quite slippery by conflating - // multiple concepts, all under the banner of a "subtype" test: - // - // * Struct/class inheritance: When concrete type `A` inherits from concrete - // type `B`, we can directly convert any value of type `A` into a value of type `B` - // - // * Derived interfaces: When interface `X` derives from interface `Y`, we know - // that any concrete type conforming to `X` must also conform to `Y`, so we can - // derive a witness that `A : Y` from a witness tbale that `A : X` for some concrete `A` - // - // * Conformance: When concrete type `A` conforms to interface `X`, we know that there exists - // a witness table for that conformance. + // The `subType` will have a `facet` for each type + // that it transitively inherits from, as well as + // for each `extension` that was found to apply to it. // - // The problem is that these relationships mean different things. If we use the same - // `isSubtype()` test for all of the above cases, then we risk determining that `IFoo` - // *conforms* to `IBar` just because it was declared as `interface IFoo : IBar`. Or - // even more simply that `IFoo` conforms to `IFoo`. + // For subtype testing, we are only interested in + // the facets that represent supertypes, and those + // will be the ones that store a type on the facet. // - // It is dangerous to start treating an interface type like it conforms to itself: - // - // interface IFoo { static int getValue(); } - // int get< T : IFoo >() { return T.getValue(); } - // - // int x = get<IFoo>(); // This needs to be an error!!! - // - // We will eventually need to clarify the distinction between the different kinds of - // subtype-ish relationships, *or* we will need to ensure that `interface`s are not - // treated as proper types (such that they can be passed as generic arguments, etc.) - // - // Note that there is one more case of a subtype-ish relationship that is not covered - // by this function, but that is relevant if/when we do more serious type inference: - // - // * Convertibility: When any value of type `A` can be converted to a value of type - // `B` (even if that conversion might involve computation or a change of representation), - // and that conversion is one that the compiler considers "okay" to do implicitly. - // - // For now we are continuing to conflate all the subtype-ish relationships but not - // tangling convertibility into it. + auto facetType = facet->getType(); + if (!facetType) + continue; - // First, make sure both sub type and super type decl are ready for lookup. - if ( !(int(isSubTypeOptions) & int(IsSubTypeOptions::NoCaching)) ) - { - if (auto subDeclRefType = as<DeclRefType>(subType)) - { - ensureDecl(subDeclRefType->getDeclRef().getDecl(), DeclCheckState::ReadyForLookup); - } - } - if (auto superDeclRefType = as<DeclRefType>(superType)) - { - ensureDecl(superDeclRefType->getDeclRef().getDecl(), DeclCheckState::ReadyForLookup); - } + // We will scan until we find a facet that corresponds + // to `superType`, or fail to find such a facet. + // + if (!facetType->equals(superType)) + continue; - // In the common case, we can use the pre-computed inheritance information for `subType` - // to enumerate all the types it transitively inherits from. + // If the `superType` appears in the flattened inheritance list + // for the `subType`, then we know that the subtype relationship + // holds. Conveniently, the `facet` stores a pre-computed witness + // for the subtype relationship, which we can return here. // - auto inheritanceInfo = getShared()->getInheritanceInfo(subType); - for (auto facet : inheritanceInfo.facets) - { - // The `subType` will have a `facet` for each type - // that it transitively inherits from, as well as - // for each `extension` that was found to apply to it. - // - // For subtype testing, we are only interested in - // the facets that represent supertypes, and those - // will be the ones that store a type on the facet. - // - auto facetType = facet->getType(); - if (!facetType) - continue; + return facet->subtypeWitness; + } + // + // TODO: We could expand upon the test using the facet list above + // by taking the facet lists of both `subType` and `superType` + // and then checking if all of the facets that appear in `superType`'s + // linearization also appear in the linearization for `subType` + // (and occur in the same order). + // + // That test could potentially handle certain cases of interface + // conjunctions that the simpler algorithm above can't, but it wouldn't + // seem to be a complete algorithm unless we ensured that interfaces + // have a canonical sorting order for how they appear in linearizations. + // + // One of the main reasons why we don't implement such a test right now + // is that it isn't obvious how to directly produce a witness value + // as collateral from the test. - // We will scan until we find a facet that corresponds - // to `superType`, or fail to find such a facet. - // - if (!facetType->equals(superType)) - continue; + // We expect the logic above to cover the vast majority of subtype + // tests, but there are a few remaining cases of subtype testing + // that cannot be folded into the type linearizations above. + // + // A few of these cases case if the `superType` is a `DeclRefType` + // and, if so, want to compare its `DeclRef` against others. As + // such, we will extract the `DeclRef` here, if it exists, + // as a convienience. + // + DeclRef<Decl> superTypeDeclRef; + if (auto superDeclRefType = as<DeclRefType>(superType)) + { + superTypeDeclRef = superDeclRefType->getDeclRef(); + } - // If the `superType` appears in the flattened inheritance list - // for the `subType`, then we know that the subtype relationship - // holds. Conveniently, the `facet` stores a pre-computed witness - // for the subtype relationship, which we can return here. - // - return facet->subtypeWitness; - } + if (as<DynamicType>(subType)) + { + // A __Dynamic type always conforms to the interface via its witness table. + auto witness = m_astBuilder->getOrCreate<DynamicSubtypeWitness>(subType, superType); + return witness; + } + else if (auto conjunctionSuperType = as<AndType>(superType)) + { + // We know that `T <: L & R` if `T <: L` and `T <: R`. // - // TODO: We could expand upon the test using the facet list above - // by taking the facet lists of both `subType` and `superType` - // and then checking if all of the facets that appear in `superType`'s - // linearization also appear in the linearization for `subType` - // (and occur in the same order). + // We therefore simply recursively test both `T <: L` + // and `T <: R`. // - // That test could potentially handle certain cases of interface - // conjunctions that the simpler algorithm above can't, but it wouldn't - // seem to be a complete algorithm unless we ensured that interfaces - // have a canonical sorting order for how they appear in linearizations. + auto leftWitness = + isSubtype(subType, conjunctionSuperType->getLeft(), IsSubTypeOptions::None); + if (!leftWitness) + return nullptr; // - // One of the main reasons why we don't implement such a test right now - // is that it isn't obvious how to directly produce a witness value - // as collateral from the test. + auto rightWitness = + isSubtype(subType, conjunctionSuperType->getRight(), IsSubTypeOptions::None); + if (!rightWitness) + return nullptr; - // We expect the logic above to cover the vast majority of subtype - // tests, but there are a few remaining cases of subtype testing - // that cannot be folded into the type linearizations above. + // If both of the sub-relationships hold, we can construct + // a conjunction of those witnesses to witness `T <: L&R` // - // A few of these cases case if the `superType` is a `DeclRefType` - // and, if so, want to compare its `DeclRef` against others. As - // such, we will extract the `DeclRef` here, if it exists, - // as a convienience. + return m_astBuilder->getConjunctionSubtypeWitness( + subType, + conjunctionSuperType, + leftWitness, + rightWitness); + } + else if (auto extractExistentialType = as<ExtractExistentialType>(subType)) + { + // An ExtractExistentialType from an existential value of type I + // is a subtype of I. + // We need to check and make sure the interface type of the `ExtractExistentialType` + // is equal to `superType`. // - DeclRef<Decl> superTypeDeclRef; - if (auto superDeclRefType = as<DeclRefType>(superType)) - { - superTypeDeclRef = superDeclRefType->getDeclRef(); - } - - if (as<DynamicType>(subType)) + // TODO(tfoley): We could add support for `ExtractExistentialType` to + // the inheritance linearization logic, and eliminate this case. + // + auto interfaceDeclRef = extractExistentialType->getOriginalInterfaceDeclRef(); + if (interfaceDeclRef.equals(superTypeDeclRef)) { - // A __Dynamic type always conforms to the interface via its witness table. - auto witness = m_astBuilder->getOrCreate<DynamicSubtypeWitness>(subType, superType); + auto witness = extractExistentialType->getSubtypeWitness(); return witness; } - else if (auto conjunctionSuperType = as<AndType>(superType)) - { - // We know that `T <: L & R` if `T <: L` and `T <: R`. - // - // We therefore simply recursively test both `T <: L` - // and `T <: R`. - // - auto leftWitness = isSubtype(subType, conjunctionSuperType->getLeft(), IsSubTypeOptions::None); - if (!leftWitness) return nullptr; - // - auto rightWitness = isSubtype(subType, conjunctionSuperType->getRight(), IsSubTypeOptions::None); - if (!rightWitness) return nullptr; - - // If both of the sub-relationships hold, we can construct - // a conjunction of those witnesses to witness `T <: L&R` - // - return m_astBuilder->getConjunctionSubtypeWitness( - subType, - conjunctionSuperType, - leftWitness, - rightWitness); - } - else if (auto extractExistentialType = as<ExtractExistentialType>(subType)) - { - // An ExtractExistentialType from an existential value of type I - // is a subtype of I. - // We need to check and make sure the interface type of the `ExtractExistentialType` - // is equal to `superType`. - // - // TODO(tfoley): We could add support for `ExtractExistentialType` to - // the inheritance linearization logic, and eliminate this case. - // - auto interfaceDeclRef = extractExistentialType->getOriginalInterfaceDeclRef(); - if (interfaceDeclRef.equals(superTypeDeclRef)) - { - auto witness = extractExistentialType->getSubtypeWitness(); - return witness; - } - return nullptr; - } - else if (auto subTypePack = as<ConcreteTypePack>(subType)) - { - // A type pack (T0, T1, ...) is a subtype of supType, if each of its elements - // is a subtype of the supType. - ShortList<SubtypeWitness*> elementWitnesses; - for (Index i = 0; i < subTypePack->getTypeCount(); i++) - { - auto elementWitness = isSubtype(subTypePack->getElementType(i), superType, IsSubTypeOptions::None); - if (!elementWitness) - return nullptr; - elementWitnesses.add(elementWitness); - } - return m_astBuilder->getSubtypeWitnessPack(subType, superType, elementWitnesses.getArrayView().arrayView); - } - else if (auto expandType = as<ExpandType>(subType)) - { - // A expand type `expand patternType, captureList` is a subtype of supType, if patternType is a subtype of supType. - auto elementWitness = isSubtype(expandType->getPatternType(), superType, IsSubTypeOptions::None); - if (!elementWitness) - return nullptr; - return m_astBuilder->getExpandSubtypeWitness(subType, superType, elementWitness); - } - else if (auto eachType = as<EachType>(subType)) + return nullptr; + } + else if (auto subTypePack = as<ConcreteTypePack>(subType)) + { + // A type pack (T0, T1, ...) is a subtype of supType, if each of its elements + // is a subtype of the supType. + ShortList<SubtypeWitness*> elementWitnesses; + for (Index i = 0; i < subTypePack->getTypeCount(); i++) { - auto elementWitness = isSubtype(eachType->getElementType(), superType, IsSubTypeOptions::None); + auto elementWitness = + isSubtype(subTypePack->getElementType(i), superType, IsSubTypeOptions::None); if (!elementWitness) return nullptr; - return m_astBuilder->getEachSubtypeWitness(subType, superType, elementWitness); + elementWitnesses.add(elementWitness); } - // default is failure - return nullptr; + return m_astBuilder->getSubtypeWitnessPack( + subType, + superType, + elementWitnesses.getArrayView().arrayView); } - - bool SemanticsVisitor::isValidGenericConstraintType(Type* type) + else if (auto expandType = as<ExpandType>(subType)) { - if (auto andType = as<AndType>(type)) - { - return isValidGenericConstraintType(andType->getLeft()) && isValidGenericConstraintType(andType->getRight()); - } - return isInterfaceType(type); + // A expand type `expand patternType, captureList` is a subtype of supType, if patternType + // is a subtype of supType. + auto elementWitness = + isSubtype(expandType->getPatternType(), superType, IsSubTypeOptions::None); + if (!elementWitness) + return nullptr; + return m_astBuilder->getExpandSubtypeWitness(subType, superType, elementWitness); } + else if (auto eachType = as<EachType>(subType)) + { + auto elementWitness = + isSubtype(eachType->getElementType(), superType, IsSubTypeOptions::None); + if (!elementWitness) + return nullptr; + return m_astBuilder->getEachSubtypeWitness(subType, superType, elementWitness); + } + // default is failure + return nullptr; +} - SubtypeWitness* SemanticsVisitor::isTypeDifferentiable(Type* type) +bool SemanticsVisitor::isValidGenericConstraintType(Type* type) +{ + if (auto andType = as<AndType>(type)) { - if (auto valueWitness = isSubtype(type, m_astBuilder->getDiffInterfaceType(), IsSubTypeOptions::None)) - return valueWitness; - else if (auto ptrWitness = isSubtype(type, m_astBuilder->getDifferentiableRefInterfaceType(), IsSubTypeOptions::None)) - return ptrWitness; - - return nullptr; + return isValidGenericConstraintType(andType->getLeft()) && + isValidGenericConstraintType(andType->getRight()); } + return isInterfaceType(type); +} - bool SemanticsVisitor::doesTypeHaveTag(Type* type, TypeTag tag) +SubtypeWitness* SemanticsVisitor::isTypeDifferentiable(Type* type) +{ + if (auto valueWitness = + isSubtype(type, m_astBuilder->getDiffInterfaceType(), IsSubTypeOptions::None)) + return valueWitness; + else if ( + auto ptrWitness = isSubtype( + type, + m_astBuilder->getDifferentiableRefInterfaceType(), + IsSubTypeOptions::None)) + return ptrWitness; + + return nullptr; +} + +bool SemanticsVisitor::doesTypeHaveTag(Type* type, TypeTag tag) +{ + if (auto arrayType = as<ArrayExpressionType>(type)) { - if (auto arrayType = as<ArrayExpressionType>(type)) - { - return doesTypeHaveTag(arrayType->getElementType(), tag); - } - if (auto modifiedType = as<ModifiedType>(type)) - { - return doesTypeHaveTag(modifiedType->getBase(), tag); - } - if (auto declRefType = as<DeclRefType>(type)) - { - if (auto aggTypeDecl = as<AggTypeDecl>(declRefType->getDeclRef())) - return aggTypeDecl.getDecl()->hasTag(tag); - } - return false; + return doesTypeHaveTag(arrayType->getElementType(), tag); + } + if (auto modifiedType = as<ModifiedType>(type)) + { + return doesTypeHaveTag(modifiedType->getBase(), tag); } + if (auto declRefType = as<DeclRefType>(type)) + { + if (auto aggTypeDecl = as<AggTypeDecl>(declRefType->getDeclRef())) + return aggTypeDecl.getDecl()->hasTag(tag); + } + return false; +} - TypeTag SemanticsVisitor::getTypeTags(Type* type) +TypeTag SemanticsVisitor::getTypeTags(Type* type) +{ + if (auto arrayType = as<ArrayExpressionType>(type)) { - if (auto arrayType = as<ArrayExpressionType>(type)) + auto typeTag = getTypeTags(arrayType->getElementType()); + bool sized = false; + if (auto cint = as<ConstantIntVal>(arrayType->getElementCount())) { - auto typeTag = getTypeTags(arrayType->getElementType()); - bool sized = false; - if (auto cint = as<ConstantIntVal>(arrayType->getElementCount())) - { - if (cint->getValue() != kUnsizedArrayMagicLength) - { - sized = true; - } - } - else if (arrayType->getElementCount()) + if (cint->getValue() != kUnsizedArrayMagicLength) { sized = true; - typeTag = (TypeTag)((int)typeTag | (int)TypeTag::LinkTimeSized); } - if (!sized) - typeTag = (TypeTag)((int)typeTag | (int)TypeTag::Unsized); - - return typeTag; - } - if (auto modifiedType = as<ModifiedType>(type)) - { - return getTypeTags(modifiedType->getBase()); - } - if (auto parameterGroupType = as<UniformParameterGroupType>(type)) - { - auto elementTags = getTypeTags(parameterGroupType->getElementType()); - elementTags = (TypeTag)((int)elementTags & ~(int)TypeTag::Unsized); - return elementTags; } - else if (auto declRefType = as<DeclRefType>(type)) + else if (arrayType->getElementCount()) { - if (auto aggTypeDecl = as<AggTypeDecl>(declRefType->getDeclRef())) - return aggTypeDecl.getDecl()->typeTags; + sized = true; + typeTag = (TypeTag)((int)typeTag | (int)TypeTag::LinkTimeSized); } - return TypeTag::None; - } + if (!sized) + typeTag = (TypeTag)((int)typeTag | (int)TypeTag::Unsized); - - Type* SemanticsVisitor::getConstantBufferElementType(Type* type) + return typeTag; + } + if (auto modifiedType = as<ModifiedType>(type)) { - if (auto arrType = as<ArrayExpressionType>(type)) - return getConstantBufferElementType(arrType->getElementType()); - if (auto modifiedType = as<ModifiedType>(type)) - return getConstantBufferElementType(modifiedType->getBase()); - if (auto constantBuffer = as<ConstantBufferType>(type)) - return constantBuffer->getElementType(); - if (auto parameterBlock = as<ParameterBlockType>(type)) - return parameterBlock->getElementType(); - return nullptr; + return getTypeTags(modifiedType->getBase()); } - - - SubtypeWitness* SemanticsVisitor::tryGetInterfaceConformanceWitness( - Type* type, - Type* interfaceType) + if (auto parameterGroupType = as<UniformParameterGroupType>(type)) { - return isSubtype(type, interfaceType, IsSubTypeOptions::None); + auto elementTags = getTypeTags(parameterGroupType->getElementType()); + elementTags = (TypeTag)((int)elementTags & ~(int)TypeTag::Unsized); + return elementTags; } - - TypeEqualityWitness* SemanticsVisitor::createTypeEqualityWitness( - Type* type) + else if (auto declRefType = as<DeclRefType>(type)) { - return m_astBuilder->getTypeEqualityWitness(type); + if (auto aggTypeDecl = as<AggTypeDecl>(declRefType->getDeclRef())) + return aggTypeDecl.getDecl()->typeTags; } + return TypeTag::None; +} + + +Type* SemanticsVisitor::getConstantBufferElementType(Type* type) +{ + if (auto arrType = as<ArrayExpressionType>(type)) + return getConstantBufferElementType(arrType->getElementType()); + if (auto modifiedType = as<ModifiedType>(type)) + return getConstantBufferElementType(modifiedType->getBase()); + if (auto constantBuffer = as<ConstantBufferType>(type)) + return constantBuffer->getElementType(); + if (auto parameterBlock = as<ParameterBlockType>(type)) + return parameterBlock->getElementType(); + return nullptr; +} + + +SubtypeWitness* SemanticsVisitor::tryGetInterfaceConformanceWitness(Type* type, Type* interfaceType) +{ + return isSubtype(type, interfaceType, IsSubTypeOptions::None); +} + +TypeEqualityWitness* SemanticsVisitor::createTypeEqualityWitness(Type* type) +{ + return m_astBuilder->getTypeEqualityWitness(type); } +} // namespace Slang |
