Isn't String::len
useless, since we already have str::len
and String
dereferences to str
?
impl Deref for String
was added in #18443, which also removed several now-unnecessary inherent methods. One day after that PR was opened and two days before it was merged, #18474 was submitted, which removed the Collection
trait, and added new inherent methods like String::len
to replace the old Collection::len
trait method.
It looks to me like this was simply an oversight caused by both of these PRs being in progress at the same time.
We also have Vec::len
in addition to <[T]>::len
.
Not exactly: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=5d5614070a96417cad98a988c6e8d66c
fn foo(_f: impl Fn(&String) -> usize) {}
fn string_len(x: &String) -> usize { x.len() }
fn str_len(x: &str) -> usize { x.len() }
fn main() {
foo(string_len); // Works
foo(str_len); // ERROR: type mismatch in function arguments
}
The problem is that there are no function coercions. So something like .map(String::len)
and .map(str::len)
are different -- one can't just always use the more general one.
Yes, this is required for some unsafe
code: v.deref().len()
creates a shared reference to the entire current content of the vector; if you have outstanding pointers into the vector, they might be invalidated. v.len()
avoids creating those references.
I would expect that creating a reference to the vector (e.g. &Vec<T>
) should assert shared access to the whole slice, or at least to the first element since it is pointed by an Unique<T>
. I would consider unsound to rely on Vec::len
not invalidating outstanding mutable pointers.
You are expecting incorrectly then.
Unique
cannot proactively assert anything since there might be no elements.
Vec
even documents that you can rely on push
not relocating the buffer under some conditions, so not invalidating outstanding pointers is clearly an explicitly intended feature of careful Vec
interaction.
I was going to answer "likely pre-1.0 historical reasons", but felt it was too much of a guess. Turns out my guess was correct
Of course, removing the method now would be breaking, but that's not really the point.
Is that true? I thought that the dot operator would call len
on str
once not found on the String
receiver.
That's true for the dot operator but it's breaking in other places: See Why do we have String::len? - #4 by scottmcm above
If rust supported methods with self: *const Self
then <[T]>::len
could be such a method (since it only accesses the metadata in the pointer).
If rust had some kind of DerefConstRaw
trait which let you deref a *const
to a *const
then Vec<T>
could implement this and allow you to get a *const [T]
without acquiring a shared reference to the slice.
You'd then be able to write vec.len()
without having to go through &[T]
and without causing problems. I think (?).
@canndrew fully agreed; if Rust had those things, they would be helpful here.
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.