Reputation: 969
The following code will work and print Foo("hello")
:
#[derive(Debug)]
struct Foo<'a>(&'a str);
impl<'a> From<&'a str> for Foo<'a> {
fn from(s: &'a str) -> Self {
Foo(s)
}
}
fn main() {
let s: &str = "hello";
let foo = Foo::from(s);
println!("{:?}", foo);
}
However, if I use generics, and change all str
into T
, it won't work:
#[derive(Debug)]
struct Foo<'a, T>(&'a T);
impl<'a, T> From<&'a T> for Foo<'a, T> {
fn from(s: &'a T) -> Self {
Foo(s)
}
}
fn main() {
let s: &str = "hello";
let foo = Foo::from(s);
println!("{:?}", foo);
}
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> a.rs:12:25
|
2 | struct Foo<'a, T>(&'a T);
| ------------------------- required by `Foo`
...
12 | let foo = Foo::from(s);
| ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
Isn't &'a T
equivalent to &'a str
? Why is the compiler seemingly using str
instead of &'a str
?
Upvotes: 4
Views: 3305
Reputation: 1819
Type parameters are implicitly Sized
in rust. You should add ?Sized
constraint explicitly.
#[derive(Debug)]
struct Foo<'a, T: ?Sized>(&'a T);
impl<'a, T: ?Sized> From<&'a T> for Foo<'a, T> {
fn from(s: &'a T) -> Self {
Foo(s)
}
}
Upvotes: 5