Consider the following code:
trait AsBytes {
fn as_bytes(&self) -> &[u8];
}
impl AsBytes for [u8] {
fn as_bytes(&self) -> &[u8] {
self
}
}
impl AsBytes for str {
fn as_bytes(&self) -> &[u8] {
self.as_ref()
}
}
impl AsBytes for String {
fn as_bytes(&self) -> &[u8] {
self.as_ref()
}
}
impl<T: ?Sized> AsBytes for &T
where
T: AsBytes,
{
fn as_bytes(&self) -> &[u8] {
<T as AsBytes>::as_bytes(*self)
}
}
fn foo(s: &[u8]) -> impl Iterator<Item=&[u8]> + '_ {
s.as_bytes().split(|&b| b == b' ')
}
This builds just fine.
Now, if you try to write the same thing with a more generic twist, it fails:
trait AsBytes {
fn as_bytes(&self) -> &[u8];
}
impl<T: AsRef<[u8]>> AsBytes for T {
fn as_bytes(&self) -> &[u8] {
self.as_ref()
}
}
fn foo(s: &[u8]) -> impl Iterator<Item=&[u8]> + '_ {
s.as_bytes().split(|&b| b == b' ')
}
The failure is:
error[E0515]: cannot return value referencing function parameter `s`
--> src/lib.rs:12:5
|
12 | s.as_bytes().split(|&b| b == b' ')
| -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `s` is borrowed here
|
= help: use `.collect()` to allocate the iterator
I'm rather lost as to why there is a difference.