In a mathematical sense, the property whether, for any types
T2, the trait implementation
From<T2> for T1 exists, i.e. whether the trait bound
T1: From<T2> is satisfied, or not, can be seen as a “(binary) relation”. In this interpretation, the relation (between types) that the trait
From gives rise to, is “reflexive” in the mathematical sense of the term. See also the Wikipedia pages I linked.
More commonly known examples for binary relations in mathematics are e.g. the < and ≤ relations. For any number n, the the statement “n ≤ n” is always true, e.g. 2≤2, 3≤3, etc… are all true, so “≤”, is a reflexive relation, too. On the other hand the same doesn’t hold true for the ”<” relation, where something like 2<2 is false. While for “<” this goes as far as that “n < n” is actually false for all numbers, in general, even a single such counter-example would be sufficient for a relation not to be considered reflexive.
For example the
Add trait in Rust, with its implementation in the standard library, also gives rise to a relation between types, much like
From, but this relation is not reflexive: While for certain types,
T: Add<T> is fulfilled, for example
i32: Add<i32>, and in fact the reflexive case is so common that
Add comes with a shorthand, where a trait bound
Foo: Add is short for
Foo: Add<Foo>, there do exist lots of types that don’t implement
Add<…> at all, and even ones that do, but not reflexively.
For example there is no implementation for
char, because you are not supposed to think of unicode scalar values as numbers, but more as characters, and those don’t do arithmetic. Or e.g. for
Instant, there is an implementation for
Instant: Add<Duration>, but not
Instant: Add<Instant>, because you can offset points in time by time durations, but there’s no sense in adding points in time to each other. (E.g. there’s no sense in defining weird things like adding the year 2023 to itself giving, say, the year 4046; since any choice of a “0” point is just arbitrary, and we don’t like results depending on such arbitrary choices.) Another example is
&str which do implement
String: Add<&str>, but neither
String has a reflexive implementation; this is mainly an arbitrary API choice in order to encourage the user to create unnecessary allocations. (Though also some people don’t like it at all that strings allow a
+ operator in Rust.)