Skip to content

[ForwardDerivativeOf] cannot resolve a shaped generic overload beside a catch-all generic overload #12825

Description

@tangent-vector

Summary

[ForwardDerivativeOf] cannot resolve a shaped generic function when the target name also has a
catch-all generic overload. The same failure occurs when the catch-all generic is the only target
and the derivative applies to a constrained subset of its specializations.

This blocks adding interface-constrained generic wrappers for core-module functions such as
sin: the wrapper makes the existing vector/matrix [ForwardDerivativeOf(sin)] declarations fail
while loading the builtin module.

Minimal reproduction

#ifndef OMIT_SHAPED_OVERLOAD
__generic<T : __BuiltinFloatingPointType, let N : int>
[Differentiable]
vector<T, N> testFunction(vector<T, N> value)
{
    return value * value;
}
#endif

#ifndef OMIT_GENERIC_OVERLOAD
[Differentiable]
T testFunction<T : IFloat>(T value)
{
    return value * value;
}
#endif

__generic<T : __BuiltinFloatingPointType, let N : int>
[ForwardDerivativeOf(testFunction)]
DifferentialPair<vector<T, N>> testFunctionForward(
    DifferentialPair<vector<T, N>> value)
{
    return diffPair(
        testFunction(value.p),
        T(2.0) * value.p * value.d);
}

[shader("compute")]
[numthreads(1, 1, 1)]
void main()
{}

Compile with:

slangc repro.slang -target spirv -entry main -stage compute -o repro.spv

The default configuration produces:

error[E31148]: cannot resolve derivative function
  --> repro.slang:19:2
   |
19 | [ForwardDerivativeOf(testFunction)]
   |  ^^^^^^^^^^^^^^^^^^^ cannot resolve the custom derivative function

Control results:

Configuration Result
Both overloads present E31148
-DOMIT_GENERIC_OVERLOAD (only the shaped generic) Compiles
-DOMIT_SHAPED_OVERLOAD (only the catch-all generic) E31148

Tested with slangc 2026.14.1-80-gd4c72aab0 on Windows.

Expected behavior / design question

For the overload-set case, the compiler should either preserve the association with the exactly
shaped generic overload, or provide a way for the attribute to explicitly select that overload.
If both declarations are intentionally considered applicable, the diagnostic should identify the
ambiguity and its candidates rather than reporting only that the derivative cannot be resolved.

For the catch-all-only case, the derivative is an override for the subset of specializations where
the primal's T is vector<Element, N>. Supporting this kind of constrained derivative override
was an explicit goal of #6486.

Why this appears related to the autodiff-overhaul design

#6486 describes derivative overrides that apply to a subset of a generic function's
specializations and says the mapping must be constructed at the relevant use site using the
specialization arguments. Its design discussion also proposed resolving a *DerivativeOf
OverloadedExpr by testing the candidates through constraint solving. The issue was closed by
#9808, whose description says the new interface/extension model supports constrained generic
custom derivatives and translates the legacy derivative attributes into that model.

The behavior above suggests that this support is incomplete in the legacy
[ForwardDerivativeOf(...)] translation/checking path, or that the implemented model still lacks
a necessary overload-disambiguation rule. The still-open #10107 records another unresolved
*DerivativeOf overload-selection problem (a synthesized backward derivative being selected over
a user-defined one), although that is not the same reproducer.

Core-module impact

In a numeric-interface design spike, adding a public wrapper equivalent to:

[Differentiable]
T sin<T : IReal>(T value)
{
    return value.sin();
}

beside the existing scalar/vector/matrix sin overloads makes the existing generated
[ForwardDerivativeOf(sin)] declarations fail with E31148. The spike can compile only by renaming
the shaped builtin implementations, attaching their derivatives to those private names, and
routing the public surface through the new generic wrapper. That workaround should not be required
merely to add a generic public overload.

Related: #6486, #9808, #10107.

Metadata

Metadata

Labels

Type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions