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

Code before:
            }
            return;
        }

        // For structs, recurse into fields
        if (auto structDeclRef = isDeclRefTypeOf<StructDecl>(type))
        {
            for (auto field : structDeclRef.getDecl()->getMembersOfType<VarDeclBase>())
            {
                if (field->hasModifier<HLSLStaticModifier>())
                    continue;
                _warnAboutDefaultInitializedResources(field->getType(), argCount, ioArgIndex, loc);
            }
            return;
        }

        // For other types (scalars, vectors, matrices), one argument is consumed
        ioArgIndex++;
        return;
    }

    // No more arguments - this type will be default-initialized
    // Check if it contains resource types
    if (as<ResourceType>(type))
    {
        getSink()->diagnose(loc, Diagnostics::cannotDefaultInitializeResourceType, type);
        return;
    }

    // For arrays, recurse to check element type
    if (auto arrayType = as<ArrayExpressionType>(type))
    {
        auto elementType = arrayType->getElementType();
        if (!arrayType->isUnsized())
        {
            if (auto constCount = as<ConstantIntVal>(arrayType->getElementCount()))
            {
                UInt elementCount = (UInt)constCount->getValue();
                for (UInt i = 0; i < elementCount; i++)
                {
                    _warnAboutDefaultInitializedResources(elementType, argCount, ioArgIndex, loc);
                }
            }
        }
        return;
    }

    // For structs, recurse into fields
    if (auto structDeclRef = isDeclRefTypeOf<StructDecl>(type))
    {
        for (auto field : structDeclRef.getDecl()->getMembersOfType<VarDeclBase>())

Review comment (suggestion):
This warning is arguably a bit redundant with the one happening in slang-ir-use-uninitialized-values.cpp, except that that one happens late enough that it won't show up via the language server. So I've added this one at the front end.

This check had originally been up before line 132, but that logic has different stopping conditions. It seemed preferable to make it its own thing rather than try to make the other code do two things.

Code after:
    {
        return true;
    }

    // Try to invoke the synthesized constructor if it exists
    if (createInvokeExprForSynthesizedCtor(toType, fromInitializerListExpr, outToExpr))
    {
        return true;
    }

    // We will fall back to the legacy logic of initialize list.
    Expr* outInitListExpr = nullptr;
    if (!_readAggregateValueFromInitializerList(
            toType,
            &outInitListExpr,
            fromInitializerListExpr,
            argIndex))
        return false;
    if (argIndex != argCount)
    {
        if (outToExpr)
        {
            getSink()->diagnose(
                fromInitializerListExpr,
                Diagnostics::tooManyInitializers,
                argIndex,
                argCount);
        }
    }
    if (outToExpr)
        *outToExpr = outInitListExpr;

    return true;
}

bool SemanticsVisitor::_failedCoercion(
    Type* toType,
    Expr** outToExpr,
    Expr* fromExpr,
    DiagnosticSink* sink)
{
    if (outToExpr)
    {
        // As a special case, if the expression we are trying to convert
        // from is overloaded (implying an ambiguous reference), then we
        // will try to produce a more appropriately tailored error message.
        //
        auto fromType = fromExpr->type.type;
        if (as<OverloadGroupType>(fromType))
        {
            diagnoseAmbiguousReference(fromExpr);