Reputation: 55
I have this setup:
use std::borrow::Cow;
fn encode_text<'a, T: Into<Cow<'a, str>>>(text: T) {}
fn encode_texts<'a, T: Into<Cow<'a, str>>>(texts: &[T]) {
for text in texts {
encode_text(text);
}
}
fn main() {
encode_texts(&vec!["foo", "bar"]);
}
The error that I get is:
error[E0277]: the trait bound `std::borrow::Cow<'_, str>: std::convert::From<&T>` is not satisfied
--> src/main.rs:7:9
|
7 | encode_text(text);
| ^^^^^^^^^^^ the trait `std::convert::From<&T>` is not implemented for `std::borrow::Cow<'_, str>`
|
= help: consider adding a `where std::borrow::Cow<'_, str>: std::convert::From<&T>` bound
= note: required because of the requirements on the impl of `std::convert::Into<std::borrow::Cow<'_, str>>` for `&T`
note: required by `encode_text`
--> src/main.rs:3:1
|
3 | fn encode_text<'a, T: Into<Cow<'a, str>>>(text: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This makes sense as a T
is a valid param to encode_text
and &T
is not, but somehow I fail to get this to work. I can't call encode_text(*text)
because I can't move it out of borrowed content (the texts
param of encode_texts
).
I haven't added a where std::borrow::Cow<'_, str>: std::convert::From<&T>
because it basically states that I want the standard library type Cow
to implement From<&T>
. If that's not already the case, then my adding the constraint won't help.
I am stuck and I can't find any resources on how to work with Cow
s in collections or slices.
Upvotes: 0
Views: 693
Reputation: 431489
Your code cannot be made generic because it doesn't work in the non-generic case to start with. Substitute the concrete type in:
use std::borrow::Cow;
fn encode_text<'a, T: Into<Cow<'a, str>>>(text: T) {}
fn encode_texts(texts: &[&'static str]) {
for text in texts {
encode_text(text);
}
}
fn main() {
encode_texts(&["foo", "bar"]);
}
error[E0277]: the trait bound `std::borrow::Cow<'_, str>: std::convert::From<&&str>` is not satisfied
--> src/main.rs:7:9
|
7 | encode_text(text);
| ^^^^^^^^^^^ the trait `std::convert::From<&&str>` is not implemented for `std::borrow::Cow<'_, str>`
|
= help: the following implementations were found:
<std::borrow::Cow<'a, std::path::Path> as std::convert::From<&'a std::path::Path>>
<std::borrow::Cow<'a, std::path::Path> as std::convert::From<std::path::PathBuf>>
<std::borrow::Cow<'a, str> as std::convert::From<&'a str>>
<std::borrow::Cow<'a, [T]> as std::convert::From<&'a [T]>>
and 2 others
= note: required because of the requirements on the impl of `std::convert::Into<std::borrow::Cow<'_, str>>` for `&&str`
note: required by `encode_text`
--> src/main.rs:3:1
|
3 | fn encode_text<'a, T: Into<Cow<'a, str>>>(text: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Cow
has a limited set of From
implementations:
impl<'a> From<&'a str> for Cow<'a, str> {}
impl<'a, T> From<&'a [T]> for Cow<'a, [T]>
where
T: Clone
{}
impl<'a, T> From<Vec<T>> for Cow<'a, [T]>
where
T: Clone,
{}
impl<'a> From<String> for Cow<'a, str> {}
Converting from a &&str
is not in the list. This makes some amount of sense as dereferencing one level from &&str
would give you &str
, which wouldn't be useful in a Cow
.
Instead, I'd implement the code as taking any iterator where the value can be converted to a Cow
. You then need to adapt the slice before passing it in:
use std::borrow::Cow;
fn encode_text<'a, T>(_text: T)
where
T: Into<Cow<'a, str>>,
{}
fn encode_texts<'a, I>(texts: I)
where
I: IntoIterator,
I::Item: Into<Cow<'a, str>>,
{
for text in texts {
encode_text(text);
}
}
fn main() {
encode_texts(["foo", "bar"].iter().cloned());
}
Upvotes: 3