There's only one type¹ that can be assigned to a Decimal
— Decimal
itself — but there may be any number of types that can be added to a Decimal
.
let add: Decimal = one() + val;
one()
must be of some type that implements Add<Decimal, Output = Decimal>
. But there could be many types that satisfy that constraint, and the compiler will not choose one, so you get an error.
let inc: Decimal = val + one();
In this case, if one()
is of type T
, Decimal
must implement Add<T, Output = Decimal>
. But again, there could be many T
s that satisfy this constraint, and the compiler will not choose one.
To fix either error, you can explicitly say that you want the Decimal
version of one
:
let add = one::<Decimal>() + val;
(The : Decimal
annotation on add
is no longer necessary because the Add
implementation unambiguously determines the Output
type.)
Decimal only allows additions with other Decimals (otherwise I'd be using a literal '1' instead), so I'm not sure what the ambiguity is in this particular case.
It doesn't actually matter how many types exist that satisfy the requirements. The compiler does not "go looking" for types to satisfy all the constraints; the types have to be unambiguously determined by only local information. Suppose there was only one type that worked, but it was defined in a third-party crate; should the compiler know about it? Or if there's only one type that works today, but tomorrow you include a new crate and there are two such types — should your code break then? It's to avoid this kind of nonlocal breakage that Rust declines to choose a type for you. In general², the compiler will only deduce types; it doesn't speculate.
This question is a lot like How does one subtract 1 from a BigInt in Rust?
¹Okay, this is not strictly true. Types that can be coerced to Decimal
can also be assigned to Decimal
variables. But coercion is only possible when the compiler knows both sides of the assignment already, so you can't infer through the =
when a coercion is happening.
²There are limited contexts in which the compiler can choose types. See this answer for one example. Autoref-based stable specialization describes using a similar technique. I could not find a way to apply this to your problem.