[rustlings conversion1] the size for values of type `(dyn std::convert::AsRef<usize> + 'static)` cannot be known at compilation time

Hello,

IM stuck again at the advanced topic

here is the task :

// AsRef and AsMut allow for cheap reference-to-reference conversions.
// Read more about them at https://doc.rust-lang.org/std/convert/trait.AsRef.html
// and https://doc.rust-lang.org/std/convert/trait.AsMut.html, respectively.

// I AM NOT DONE
// Obtain the number of bytes (not characters) in the given argument
// Add the AsRef trait appropriately as a trait bound
fn byte_counter<T>(arg: AsRef<usize>) -> usize {
    arg.as_ref().as_bytes().len()
}

but i see the above error . Please any hints how to solve it and I read the chapter of the book but still stuck

You're trying to take the trait object as a parameter. This will not work. Try to use something like you've done in your previous topic instead.

oke, I will read that one. I tried it do it as the first example of this chapter: AsRef in std::convert - Rust

Have you read the chapter 10 of the book?

However, the first example there is different. It uses generic function, and your code does not.

it does, the orgina is using generics

fn byte_counter<T>(arg: T) -> usize {
    arg.as_ref().as_bytes().len()
}

Yes, but your code, provided in the first post, does not.

No, that was my wrong attempt to make the code works an I see now that there is something I do not understand well

Oke,

Is the solution this simple:

fn byte_counter<T: AsRef<str>>(arg: T) -> usize {
    arg.as_ref().as_bytes().len()
}

// Obtain the number of characters (not bytes) in the given argument
// Add the AsRef trait appropriately as a trait bound
fn char_counter<T: AsRef<str>>(arg: T) -> usize {
    arg.as_ref().chars().count()
}

Yes, that's it.

The only thing that could be added is the fact that generic argument can be specified in two ways:

  • as a named type - that's the way you've used: you introduce a type with some bounds and then use it.
  • as an anonymous type - through the impl Trait syntax.

So, you could've also write this code in the following way:

fn byte_counter(arg: impl AsRef<str>) -> usize {
    arg.as_ref().as_bytes().len()
}

fn char_counter(arg: impl AsRef<str>) -> usize {
    arg.as_ref().chars().count()
}

Semantically this is the same; the only difference is that with impl Trait you can't specify the type at call site explicitly (through "turbofish" syntax).

Then I think i solved all the challenges with some help,
maybe it's better to leave it for a few days and do the rustlings again before im going to dive into rocket

There's is another option which is using the trait objects, which makes the function be compiled only once and uses arg.as_ref() through a vtable at runtime:

fn byte_counter(arg: &dyn AsRef<str>) -> usize {
    arg.as_ref().as_bytes().len()
}

This can be slower to run but faster to compile. Most of the time it doesn't matter.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.