简体   繁体   中英

Why is ?Sized required to pass a reference to a generic type parameter?

When I run the following code on Rust playground...

fn take_part_1<'a>(s: &'a str) -> &'a str {
    s.split(':').next().unwrap()
}

fn take_part_2<'a, T: 'a + AsRef<str>>(s: &'a T) -> &'a str {
    let b = s.as_ref().split(':').next().unwrap();
    b
}

fn main() {
    println!("{}", take_part_1("a:b"));
    println!("{}", take_part_2("a:b"));
}

... the compiler returns an error that doesn't make sense:

12 |     println!("{}", take_part_2("a:b"));
   |                    ^^^^^^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `str`

I can fix it by adding ?Sized like so:

fn take_part_2<'a, T: 'a + AsRef<str> + ?Sized>(s: &'a T) -> &'a str {

Why is this ?Sized required (and why does the compiler point the error at the function call)? What does it do? Shouldn't I be able to pass the reference to an unsized object and have it just work?

What confuses me is that the non-generic implementation works as you'd expect, with no requirements for ?Sized (even though the compiler has pointed out that str isn't Sized !)

Most places where you use a type parameter, Rust will implicitly insert an additional Sized bound. That's because it is the most common case - if it didn't behave that way then you'd have to write the bound yourself everywhere and it would get repetitive and noisy.

For example, your take_part function is exactly equivalent to this:

fn take_part_2<'a, T: 'a + AsRef<str> + Sized>(s: &'a T) -> &'a str {
    let b = s.as_ref().split(':').next().unwrap();
    b
}

However, your function's implementation does not require T to be Sized because it only ever uses it by reference. Adding : ?Sized effectively removes that implicit bound, communicating to the type checker that the size of T doesn't need to be known, so your function is as general as possible. In this case, making it more general allows it to be called with T as str , a dynamically sized type.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM