Observed
Since #829, a parameter whose DECLARED consumers impose disagreeing dtypes reports the union over the imposed dtypes. A parameter fed different dtypes from different call sites, with no coercion involved, reports the same union through the ordinary join. The two reported sets are indistinguishable, and the information that separates them exists at collection time (the engine's per-parameter imposed map, before the transfer flattens it) but is not exposed.
Why It Matters: Identical Evidence, Opposite Required Treatments
Two whole programs, both running on TF 2.9.3, both reporting {float64, float32} on the parameter at 0.52.84.
Consumer-imposed plurality, where a single tracing specification is impossible AND an unspecified trace materializes the argument at the fed dtype and raises at the mismatched op, so a client transforming the function must decline entirely:
import numpy as np
import tensorflow as tf
V32 = tf.Variable(tf.zeros([2]), name="v32")
V64 = tf.Variable(tf.zeros([2], dtype=tf.float64), name="v64")
X = np.array([1.5, 2.5])
def combine(x):
return tf.reduce_sum(V32 * x), tf.reduce_sum(V64 * x)
combine(X)
Fed plurality, where both calls succeed eagerly, nothing coerces anything, retracing per dtype is correct, and only the specification is unwritable, so the same client must proceed without one:
import tensorflow as tf
def summed(x):
return tf.reduce_sum(x)
summed(tf.ones((2,), dtype=tf.float32))
summed(tf.ones((2,), dtype=tf.float64))
Expected
Expose a per-parameter fact: whether the parameter's dtype plurality is consumer-imposed. A boolean suffices, since the downstream remedy stays with the client either way, so the imposed map itself need not be exposed, and the engine already computes it (the disagreement population in the #829 split log line is exactly this predicate's true-count). The surface can follow the depth-limited signal's precedent: a queryable result on the engine beside the analysis, keyed by the parameter's pointer key.
Observed
Since #829, a parameter whose DECLARED consumers impose disagreeing dtypes reports the union over the imposed dtypes. A parameter fed different dtypes from different call sites, with no coercion involved, reports the same union through the ordinary join. The two reported sets are indistinguishable, and the information that separates them exists at collection time (the engine's per-parameter imposed map, before the transfer flattens it) but is not exposed.
Why It Matters: Identical Evidence, Opposite Required Treatments
Two whole programs, both running on TF 2.9.3, both reporting
{float64, float32}on the parameter at 0.52.84.Consumer-imposed plurality, where a single tracing specification is impossible AND an unspecified trace materializes the argument at the fed dtype and raises at the mismatched op, so a client transforming the function must decline entirely:
Fed plurality, where both calls succeed eagerly, nothing coerces anything, retracing per dtype is correct, and only the specification is unwritable, so the same client must proceed without one:
Expected
Expose a per-parameter fact: whether the parameter's dtype plurality is consumer-imposed. A boolean suffices, since the downstream remedy stays with the client either way, so the imposed map itself need not be exposed, and the engine already computes it (the disagreement population in the #829 split log line is exactly this predicate's true-count). The surface can follow the depth-limited signal's precedent: a queryable result on the engine beside the analysis, keyed by the parameter's pointer key.