Repository: shader-slang/slang
File: source/slang/slang-ir-typeflow-specialize.cpp (C++)

Code before:
                    typeSet.add(as<IRWitnessTable>(witnessTable)->getConcreteType());
                    break;
                case kIROp_UninitializedWitnessTableElement:
                    typeSet.add(builder.getUninitializedTypeElement(
                        as<IRUninitializedWitnessTableElement>(witnessTable)
                            ->getBaseInterfaceType()));
                    break;
                case kIROp_NoneWitnessTableElement:
                    typeSet.add(builder.getNoneTypeElement());
                    break;
                }
            });

        // Create the tagged union type out of the type and table collection.
        return builder.getTaggedUnionType(
            tableSet,
            cast<IRTypeSet>(builder.getSet(kIROp_TypeSet, typeSet)));
    }

    // Check if a witness table set references a [Specialize]-only interface.
    // If so, emit error 52008 — the compiler has determined that dynamic dispatch
    // is needed, but the interface was explicitly marked for specialization only.
    //
    // Returns true if the interface is specialize-only (caller should bail out).
    //
    bool diagnoseSpecializeOnlyInterface(IRWitnessTableSet* tableSet, SourceLoc callSiteLoc)
    {
        if (!sink)
            return false;

        IRInst* conformanceType = nullptr;
        forEachInSet(
            tableSet,
            [&](IRInst* table)
            {
                if (conformanceType)
                    return;
                IRInst* ifaceType = nullptr;
                if (auto witnessTable = as<IRWitnessTable>(table))
                {
                    auto witnessTableType = as<IRWitnessTableType>(witnessTable->getDataType());
                    if (witnessTableType)
                        ifaceType = witnessTableType->getConformanceType();
                }
                else if (auto unbounded = as<IRUnboundedWitnessTableElement>(table))
                {
                    ifaceType = unbounded->getBaseInterfaceType();
                }
                else if (auto uninit = as<IRUninitializedWitnessTableElement>(table))
                {
                    ifaceType = uninit->getBaseInterfaceType();

Review comment (suggestion):
I would make this function return SlangResult. It's clearer that way what the result value means.

To me, `true` could mean that the type was ok; and `true` could mean that diagnostics was triggered.

(I would also rename these functions as checkSomething(), requireSomething(), rejectSomething(), etc. In my mind, diagnoseSomething() means something has already happened and now we're complaining about it. But Slang does use diagnoseSomething() also for checking + diagnosing.)

Code after:
                    typeSet.add(as<IRWitnessTable>(witnessTable)->getConcreteType());
                    break;
                case kIROp_UninitializedWitnessTableElement:
                    typeSet.add(builder.getUninitializedTypeElement(
                        as<IRUninitializedWitnessTableElement>(witnessTable)
                            ->getBaseInterfaceType()));
                    break;
                case kIROp_NoneWitnessTableElement:
                    typeSet.add(builder.getNoneTypeElement());
                    break;
                }
            });

        // Create the tagged union type out of the type and table collection.
        return builder.getTaggedUnionType(
            tableSet,
            cast<IRTypeSet>(builder.getSet(kIROp_TypeSet, typeSet)));
    }

    // Check if a witness table set references a [Specialize]-only interface.
    // If so, emit error 52008 — the compiler has determined that dynamic dispatch
    // is needed, but the interface was explicitly marked for specialization only.
    //
    // Returns SLANG_FAIL if the interface is specialize-only (caller should bail out).
    //
    SlangResult rejectSpecializeOnlyInterface(IRWitnessTableSet* tableSet, SourceLoc callSiteLoc)
    {
        IRInst* conformanceType = nullptr;
        forEachInSet(
            tableSet,
            [&](IRInst* table)
            {
                if (conformanceType)
                    return;
                IRInst* ifaceType = nullptr;
                if (auto witnessTable = as<IRWitnessTable>(table))
                {
                    auto witnessTableType = as<IRWitnessTableType>(witnessTable->getDataType());
                    if (witnessTableType)
                        ifaceType = witnessTableType->getConformanceType();
                }
                else if (auto unbounded = as<IRUnboundedWitnessTableElement>(table))
                {
                    ifaceType = unbounded->getBaseInterfaceType();
                }
                else if (auto uninit = as<IRUninitializedWitnessTableElement>(table))
                {
                    ifaceType = uninit->getBaseInterfaceType();
                }
                if (ifaceType && ifaceType->findDecoration<IRSpecializeDecoration>())
                    conformanceType = ifaceType;