I was reading an answer to stackoverflow question and tried to modify the function history
to take IntoIter
where item can be anything that can be transformed into reference and has some traits Debug
in this case.
If I will remove V: ?Sized
from the function definition rust compiler would complain that it doesn't know the size of str
at compile time.
use std::fmt::Debug;
pub fn history<I: IntoIterator, V: ?Sized>(i: I) where I::Item: AsRef<V>, V: Debug {
for s in i {
println!("{:?}", s.as_ref());
}
}
fn main() {
history::<_, str>(&["st", "t", "u"]);
}
I don't understand why compiler shows error in the first place and not sure why the program is working properly if I kind of cheat with V: ?Sized
.
I kind of cheat with
V: ?Sized
It isn't cheating. All generic arguments are assumed to be Sized
by default. This default is there because it's the most common case - without it, nearly every type parameter would have to be annotated with : Sized
.
In your case, V
is only ever accessed by reference, so it doesn't need to be Sized
. Relaxing the Sized
constraint makes your function as general as possible, allowing it to be used with the most possible types.
The type str
is unsized, so this is not just about generalisation, you actually need to relax the default Sized
constraint to be able to use your function with str
.