Repository: shader-slang/slang
File: source/slang/slang-legalize-types.cpp (C++)

Code before:
            TuplePseudoType::Element specialElement;
            specialElement.key = fieldKey;
            specialElement.type = specialType;
            specialElements.add(specialElement);
        }

        pairElement.type = LegalType::pair(ordinaryType, specialType, elementPairInfo);
        pairElements.add(pairElement);
    }

    // Add a field to the (pseudo-)type we are building
    void addField(IRStructField* field)
    {
        auto fieldType = field->getFieldType();

        bool isSpecialField = context->isSpecialType(fieldType);
        auto legalFieldType = legalizeType(context, fieldType);
        addField(field->getKey(), legalFieldType, legalFieldType, isSpecialField, fieldType);
    }

    LegalType getResult()
    {
        // If this is an empty struct
        if (!anyOrdinary && !anySpecial && !anyComplex)
        {
            // Check if this is a ray payload struct - these need special handling
            // to avoid crashes in ray tracing intrinsics
            if (auto structType = as<IRStructType>(type))
            {
                if (structType->findDecoration<IRRayPayloadDecoration>())
                {
                    // Keep empty ray payload structs as simple types to allow
                    // ray tracing operations to work correctly
                    return LegalType::simple(type);
                }
            }
            // For other empty structs, eliminate them as usual
            return LegalType();
        }

        // If we didn't see anything "special"
        // then we can use the type as-is.
        // we can conceivably just use the type as-is
        //
        if (!anyComplex)
        {
            return LegalType::simple(type);
        }

        // If there were any "ordinary" fields along the way,
        // then we need to collect them into a new `struct` type

Review comment (bug):
I don't think this is correct. Putting a special case here only for the result types and not elsewhere will lead to various bugs due to inconsistent behavior. The right approach should be to fix whatever is crashing and make that able to deal with the case where the payload is empty, instead of trying to change type legalization.

Code after:
            TuplePseudoType::Element specialElement;
            specialElement.key = fieldKey;
            specialElement.type = specialType;
            specialElements.add(specialElement);
        }

        pairElement.type = LegalType::pair(ordinaryType, specialType, elementPairInfo);
        pairElements.add(pairElement);
    }

    // Add a field to the (pseudo-)type we are building
    void addField(IRStructField* field)
    {
        auto fieldType = field->getFieldType();

        bool isSpecialField = context->isSpecialType(fieldType);
        auto legalFieldType = legalizeType(context, fieldType);
        addField(field->getKey(), legalFieldType, legalFieldType, isSpecialField, fieldType);
    }

    LegalType getResult()
    {
        // If this is an empty struct, return a none type
        // This helps get rid of emtpy structs that often trips up the
        // downstream compiler
        if (!anyOrdinary && !anySpecial && !anyComplex)
            return LegalType();

        // If we didn't see anything "special"
        // then we can use the type as-is.
        // we can conceivably just use the type as-is
        //
        if (!anyComplex)
        {
            return LegalType::simple(type);
        }

        // If there were any "ordinary" fields along the way,
        // then we need to collect them into a new `struct` type
        // that represents these fields.
        //
        LegalType ordinaryType;
        if (anyOrdinary)
        {
            // We are going to create an new IR `struct` type that contains
            // the "ordinary" fields from the original type. Note that these
            // fields may have different types from what they did before,
            // because the fields themselves might have been legalized.
            //
            // The new type will have the same mangled name as the old one, so
            // downstream code is going to need to be careful not to emit declarations