As @PeterHall mentioned, with a generic method the trait cannot be object-safe.
The reason, it turns out, is simply an implementation limitation.
Efficient dispatch to the correct implementation of a trait method is achieved by using a virtual-table, which is essentially a table of pointer-to-functions. Each method in the trait object gets one slot in the virtual-table to store one pointer-to-function.
On the other hand, a generic function or method is no function or method at all. It's a blueprint to create as many different functions or methods as one wishes by substituting the generic parameters with actual, concrete, parameters.
This means that it is not possible to have a pointer-to-function for fn foo<T>() -> T;
as there is no code for it, instead you may have a pointer-to-function for one fn foo<i32>() -> i32
, and another pointer-to-function for one fn foo<String>() -> String
, and another...
The impossibility to have a pointer-to-function, and thus a v-table entry, for a generic method makes it impossible to call that method via run-time dispatch, that is, on a dyn Trait
.
It is notable that other languages also suffer the same restriction, for the same reasons; C++ cannot have template virtual methods either, for example.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…