Repository: shader-slang/slang
File: source/slang/slang-check-conformance.cpp (C++)

Code before:
    {
        return getTypeTags(modifiedType->getBase());
    }
    if (as<ParameterBlockType>(type))
    {
        // ParameterBlock types are non-addressable
        return TypeTag::NonAddressable;
    }
    if (auto parameterGroupType = as<UniformParameterGroupType>(type))
    {
        auto elementTags = getTypeTags(parameterGroupType->getElementType());
        elementTags = (TypeTag)(((int)elementTags & ~(int)TypeTag::Unsized) | (int)TypeTag::Opaque);
        return elementTags;
    }
    else if (
        as<UntypedBufferResourceType>(type) || as<ResourceType>(type) ||
        as<SamplerStateType>(type) || as<HLSLStructuredBufferTypeBase>(type) ||
        as<DynamicResourceType>(type))
    {
        return TypeTag::Opaque;
    }
    else if (auto declRefType = as<DeclRefType>(type))
    {
        if (auto aggTypeDeclRef = as<AggTypeDecl>(declRefType->getDeclRef()))
        {
            auto aggTypeDecl = aggTypeDeclRef.getDecl();

            // Start with the stored tags
            TypeTag tags = aggTypeDecl->typeTags;

            // Check if any member has NonAddressable tag
            // We need to check members to propagate NonAddressable
            for (auto member : aggTypeDecl->getMembersOfType<VarDeclBase>())
            {
                // Skip static members
                if (member->hasModifier<HLSLStaticModifier>())
                    continue;

                // Get tags for the member type
                TypeTag memberTags = getTypeTags(member->getType());

                // If member is NonAddressable, the struct is also NonAddressable
                if ((int)memberTags & (int)TypeTag::NonAddressable)
                {
                    tags = (TypeTag)((int)tags | (int)TypeTag::NonAddressable);
                    // We found a NonAddressable member, no need to check further
                    break;
                }
            }

            return tags;

Review comment (suggestion):
I don't think this is necessary. Type tags are already propagated in `SemanticsDeclHeaderVisitor::checkVarDeclCommon(VarDeclBase* varDecl)` with a call to `unionTypeTagsWith` t here.

Code after:
    if (auto modifiedType = as<ModifiedType>(type))
    {
        return getTypeTags(modifiedType->getBase());
    }
    if (as<ParameterBlockType>(type))
    {
        // ParameterBlock types are non-addressable
        return TypeTag::NonAddressable;
    }
    if (auto parameterGroupType = as<UniformParameterGroupType>(type))
    {
        auto elementTags = getTypeTags(parameterGroupType->getElementType());
        elementTags = (TypeTag)(((int)elementTags & ~(int)TypeTag::Unsized) | (int)TypeTag::Opaque);
        return elementTags;
    }
    else if (
        as<UntypedBufferResourceType>(type) || as<ResourceType>(type) ||
        as<SamplerStateType>(type) || as<HLSLStructuredBufferTypeBase>(type) ||
        as<DynamicResourceType>(type))
    {
        return TypeTag::Opaque;
    }
    else if (auto declRefType = as<DeclRefType>(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);
}