In the following Rust snippet:
fn main() {
let list1: Vec<i32> = vec![0, 1, 2, 3, 4];
let it1 = list1.iter();
let tens = it1.map(|x| x * 10).collect::<Vec<i32>>();
println!("{:?}", tens);
let it2 = list1.iter();
let doubled_from_iter = scale_it_iter(&it2);
println!("{:?}", doubled_from_iter);
}
fn scale_it_iter(l: &dyn Iterator<Item = &i32>) -> Vec<i32> {
l.map(|x| x * 2).collect()
}
Rust Playground Link
I get this error:
error: the `map` method cannot be invoked on a trait object
--> src/main.rs:15:7
|
15 | l.map(|x| x * 2).collect()
| ^^^
|
::: /home/xolve/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:625:15
|
625 | Self: Sized,
| ----- this has a `Sized` requirement
|
= note: you need `&mut dyn Iterator<Item = &i32>` instead of `&dyn Iterator<Item = &i32>`
error: aborting due to previous error
Adding mut as suggested by the compiler solves this. Rust Playground link for working code.
I do not understand why it is needed. It's not needed in main when I call it1.map.
I don't understand the error messages.
the `map` method cannot be invoked on a trait object is solved by adding mut to the trait reference. This seems contradictory.
How is the message about the Sized trait bound related to the error?
The "map method cannot be invoked on a trait object" and "this has a Sized requirement" error messages are because map() consumes the original iterator. dyn Traits cannot be consumed (they are unsized types and cannot be passed to functions by value).
It works for it1 because 1) its not a trait object, its a concrete type Iter and 2) its not a reference so it is consumed.
The reason that &mut dyn Iterator works is because &mut dyn Iterator implements Iterator. The effective difference is just the reference is consumed and the underlying iterator is mutated.
If you want to follow convention, I'd make scale_it_iter consume the iterator like so:
fn scale_it_iter<'a>(l: impl Iterator<Item = &'a i32>) -> Vec<i32> {
l.map(|x| x * 2).collect()
}
Related
Rust reference object-safety confused me for a while, and says:
Explicitly non-dispatchable functions require:
Have a where Self: Sized bound (receiver type of Self (i.e. self) implies this).
But I found code::iter::Iterator has dozen of methods are declared as explicitly non-dispatchable functions, one of them below:
pub trait Iterator {
...
fn count(self) -> usize
where
Self: Sized,
{
self.fold(
0,
#[rustc_inherit_overflow_checks]
|count, _| count + 1,
)
}
...
}
However, all of them are dispatchable by trait-object at rust-playground:
fn main() {
let it: &mut dyn Iterator<Item = u32> = &mut [1, 2, 3].into_iter();
assert_eq!(3, it.count()); // ok
}
That is good, I start try to implements a worked example, but it can not be dispatched at rust-playground, and report compiler error: "the dispatch method cannot be invoked on a trait object" that is expected:
fn main() {
pub trait Sup {
fn dispatch(self) -> String
where
Self: Sized,
{
"sup".to_string()
}
}
struct Sub;
impl Sup for Sub {
fn dispatch(self) -> String {
"sub".to_string()
}
}
let it: &mut dyn Sup = &mut Sub;
assert_eq!("trait", it.dispatch());
}
Why explicitly non-dispatchable methods in code::iter::Iterator are dispatchable? Is there any magic which I didn't found?
The reason is simple, if we think of this: what type we're invoking the method count on?
Is it dyn Iterator<Item = u32>? Let's check:
assert_eq!(3, <dyn Iterator<Item = u32>>::count(it));
Nope, there are two errors:
error[E0308]: mismatched types
--> src/main.rs:3:53
|
3 | assert_eq!(3, <dyn Iterator<Item = u32>>::count(it));
| ^^ expected trait object `dyn Iterator`, found mutable reference
|
= note: expected trait object `dyn Iterator<Item = u32>`
found mutable reference `&mut dyn Iterator<Item = u32>`
error[E0277]: the size for values of type `dyn Iterator<Item = u32>` cannot be known at compilation time
--> src/main.rs:3:53
|
3 | assert_eq!(3, <dyn Iterator<Item = u32>>::count(it));
| --------------------------------- ^^ doesn't have a size known at compile-time
| |
| required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `dyn Iterator<Item = u32>`
note: required by a bound in `count`
OK, well... is it &mut dyn Iterator, then?
assert_eq!(3, <&mut dyn Iterator<Item = u32>>::count(it));
Now it compiles. It's understandable that the second error goes away - &mut T is always Sized. But why do the &mut dyn Iterator has access to the method of Iterator?
The answer is in the documentation. First, dyn Iterator obviously implements Iterator - that's true for any trait. Second, there's implementation of Iterator for any &mut I, where I: Iterator + ?Sized - which our dyn Iterator satisfies.
Now, one may ask - what code is executed when we use this implementation? After all, count requires consuming self, so calling it on reference can't delegate to the dyn Iterator - otherwise we'd be back to square one, dispatching non-dispatchable.
Here, the answer lies in the structure of the Iterator trait. As one can see, it has only a single required method, namely next, which takes &mut self; all other methods are provided, that is, they have some default implementations using next - for example, here's it for count:
fn count(self) -> usize
where
Self: Sized,
{
self.fold(
0,
#[rustc_inherit_overflow_checks]
|count, _| count + 1,
)
}
where fold, in turn, is the following:
fn fold<B, F>(mut self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
let mut accum = init;
while let Some(x) = self.next() {
accum = f(accum, x);
}
accum
}
As you can see, knowing just the next, compiler can derive fold and then count.
Now, back to our &mut dyn Iterators. Let's check how, exactly, this implementation looks like; it appears to be quite simple:
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator + ?Sized> Iterator for &mut I {
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<I::Item> {
(**self).next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(**self).size_hint()
}
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
(**self).advance_by(n)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
(**self).nth(n)
}
}
You can see that the &self and &mut self methods, i.e. the ones which can be called on the trait object, are forwarded by the reference to the inner value and dispatched dynamically.
The self methods, i.e. the ones which cannot use the trait object, are dispached statically using their default implementation, which consume the reference and pass it, eventually, into one of these - non-consuming, dynamically-dispatched - methods.
I am running into the error when calling .partition() on a vector iterator:
error[E0277]: the trait bound `std::vec::Vec<std::result::Result<std::collections::HashSet<&std::string::String>, std::boxed::Box<dyn std::error::Error>>>: std::iter::Extend<&std::result::Result<std::collections::HashSet<std::string::String>, std::boxed::Box<dyn std::error::Error>>>` is not satisfied
--> src/main.rs:9:24
|
9 | results.iter().partition(|r| r.is_ok());
| ^^^^^^^^^ the trait `std::iter::Extend<&std::result::Result<std::collections::HashSet<std::string::String>, std::boxed::Box<dyn std::error::Error>>>` is not implemented for `std::vec::Vec<std::result::Result<std::collections::HashSet<&std::string::String>, std::boxed::Box<dyn std::error::Error>>>`
|
= help: the following implementations were found:
<std::vec::Vec<T> as std::iter::Extend<&'a T>>
<std::vec::Vec<T> as std::iter::Extend<T>>
When running the following code:
use std::collections::HashSet;
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
fn main() {
let mut results: Vec<Result<HashSet<String>>> = Default::default();
let (okays, errors): (Vec<Result<HashSet<&String>>>, Vec<_>) =
results.iter().partition(|r| r.is_ok());
}
See playground for example.
As the error message states (with namespacing removed):
the trait Extend<&Result<HashSet<String>, Box<dyn Error>>> is not implemented for Vec<Result<HashSet<&String>, Box<dyn Error>>>
You can't extend a Vec<T> with elements of type &T because they aren't the same type.
Instead, you can do one of these:
Change the type of the destination collection to Vec<&Result<HashSet<String>>> (or just Vec<_>, like your second destination type, to allow the compiler to infer the inner type).
Convert the reference to an owned value, perhaps via clone or to_owned.
Don't iterate over references to start with, using into_iter or drain instead.
However, your current type will be very hard or expensive to achieve, as you state that you want an owned Result with an owned HashMap but a reference the String.
I think the best thing is to use Itertools::partition_map and into_iter:
use itertools::Itertools; // 0.9.0
use std::collections::HashSet;
type Error = Box<dyn std::error::Error>;
type Result<T, E = Error> = std::result::Result<T, E>;
fn main() {
let mut results: Vec<Result<HashSet<String>>> = Default::default();
let (errors, okays): (Vec<_>, Vec<_>) = results.into_iter().partition_map(Into::into);
// let (errors, okays): (Vec<Error>, Vec<HashSet<String>>)
}
See also:
What is the difference between iter and into_iter?
I am running into the error when calling .partition() on a vector iterator:
error[E0277]: the trait bound `std::vec::Vec<std::result::Result<std::collections::HashSet<&std::string::String>, std::boxed::Box<dyn std::error::Error>>>: std::iter::Extend<&std::result::Result<std::collections::HashSet<std::string::String>, std::boxed::Box<dyn std::error::Error>>>` is not satisfied
--> src/main.rs:9:24
|
9 | results.iter().partition(|r| r.is_ok());
| ^^^^^^^^^ the trait `std::iter::Extend<&std::result::Result<std::collections::HashSet<std::string::String>, std::boxed::Box<dyn std::error::Error>>>` is not implemented for `std::vec::Vec<std::result::Result<std::collections::HashSet<&std::string::String>, std::boxed::Box<dyn std::error::Error>>>`
|
= help: the following implementations were found:
<std::vec::Vec<T> as std::iter::Extend<&'a T>>
<std::vec::Vec<T> as std::iter::Extend<T>>
When running the following code:
use std::collections::HashSet;
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
fn main() {
let mut results: Vec<Result<HashSet<String>>> = Default::default();
let (okays, errors): (Vec<Result<HashSet<&String>>>, Vec<_>) =
results.iter().partition(|r| r.is_ok());
}
See playground for example.
As the error message states (with namespacing removed):
the trait Extend<&Result<HashSet<String>, Box<dyn Error>>> is not implemented for Vec<Result<HashSet<&String>, Box<dyn Error>>>
You can't extend a Vec<T> with elements of type &T because they aren't the same type.
Instead, you can do one of these:
Change the type of the destination collection to Vec<&Result<HashSet<String>>> (or just Vec<_>, like your second destination type, to allow the compiler to infer the inner type).
Convert the reference to an owned value, perhaps via clone or to_owned.
Don't iterate over references to start with, using into_iter or drain instead.
However, your current type will be very hard or expensive to achieve, as you state that you want an owned Result with an owned HashMap but a reference the String.
I think the best thing is to use Itertools::partition_map and into_iter:
use itertools::Itertools; // 0.9.0
use std::collections::HashSet;
type Error = Box<dyn std::error::Error>;
type Result<T, E = Error> = std::result::Result<T, E>;
fn main() {
let mut results: Vec<Result<HashSet<String>>> = Default::default();
let (errors, okays): (Vec<_>, Vec<_>) = results.into_iter().partition_map(Into::into);
// let (errors, okays): (Vec<Error>, Vec<HashSet<String>>)
}
See also:
What is the difference between iter and into_iter?
I am trying to grok Rust by implementing simple algorithms in it. I managed to make a generic merge_sorted, which ended up having the following signature:
fn merge_sorted<IL, ILL, I: Ord>(mut arrays: ILL) -> Vec<I>
where
IL: Iterator<Item = I>,
ILL: Iterator<Item = IL>,
{
// ...
}
This seems to be compiling on its own. The signature makes sense to me, as the function consumes the top-level iterator, and all the iterators it returns too. However, I am unable to construct a valid value to pass to this function:
fn main() {
let v1 = vec![1, 2];
let vectors = vec![v1.iter()];
merge_sorted(vectors.iter());
}
As expected, vectors in this sample has the type:
std::vec::Vec<std::slice::Iter<'_, i32>>
This is the error message I get:
error[E0277]: the trait bound `&std::slice::Iter<'_, {integer}>: std::iter::Iterator` is not satisfied
--> src\main.rs:58:5
|
58 | merge_sorted(vectors.iter());
| ^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator; maybe try calling `.iter()` or a similar method
|
= help: the trait `std::iter::Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`
note: required by `merge_sorted`
Where does the & come from?
Vec::iter borrows the items it contains, so you are iterating over borrowed iterators (&std::slice::Iter) that do not implement Iterator. To consume a vector in order to have the ownership of the items, you must call Vec::into_iter:
fn main() {
let v1 = vec![1, 2];
let vectors = vec![v1.iter()]; // You can use `into_iter` there to iterate over ints.
merge_sorted(vectors.into_iter());
}
You can also require IntoIterators that can make easier the usage of your API:
fn merge_sorted<IterT, IterIterT, T: Ord>(mut arrays: IterIterT) -> Vec<T>
where
IterT: IntoIterator<Item = T>,
IterIterT: IntoIterator<Item = IterT>,
{
panic!();
}
fn main() {
let v1 = vec![1, 2];
let vectors = vec![v1];
merge_sorted(vectors);
}
I'm having trouble understanding how references get forwarded through functions. The following scenario seems to compile as expected:
trait Trait {}
struct ImplementsTrait {}
impl Trait for ImplementsTrait {}
fn foo(t: &mut Trait) {
// ... use the mutable reference
}
fn forward(t: &mut Trait) {
foo(t); // forward the type '&mut Trait' to foo
}
fn main() {
let mut t = ImplementsTrait{};
forward(&mut t); // need to pass as reference because Trait has no static size
}
However, in using the API for the capnp crate, I get unexpected behavior:
fn parse_capnp(read: &mut BufRead) {
let reader = serialize_packed::read_message(read, message::ReaderOptions::new());
Ok(())
}
fn main() {
// ... ///
let mut br = BufReader::new(f);
parse_capnp(&mut br);
Ok(())
}
error[E0277]: the trait bound `std::io::BufRead: std::marker::Sized` is not satisfied
--> src/main.rs:18:16
|
18 | let reader = serialize_packed::read_message(read, message::ReaderOptions::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::io::BufRead` does not have a constant size known at compile-time
The signature of read_message is:
pub fn read_message<R>(
read: &mut R,
options: ReaderOptions
) -> Result<Reader<OwnedSegments>>
where
R: BufRead,
It appears that read is getting passed by value when it is a &mut BufRead and read_message is expecting a &mut BufRead. The only way to get this snippet to compile for me is changing this to:
fn parse_capnp(mut read: &mut BufRead) {
let reader = serialize_packed::read_message(&mut read, message::ReaderOptions::new());
Ok(())
}
I believe I am missing something simple about the types here. To me, this appears to pass a &mut &mut BufRead, which is not the expected type, but compiles.
Could someone add clarity to the types of read and t for the two examples?
I've looked at the following threads:
Use of mut in function signature
What are Rust's exact auto-dereferencing rules?
For the first thread, I'd say the comparison to C-style pointers is faulty due to the dereferencing rules that Rust applies.
Creating a Minimal, Complete, and Verifiable example that reproduces the problem is a useful step:
use std::io::BufRead;
pub fn read_message<R>(read: &mut R)
where
R: BufRead,
{}
fn parse_capnp(read: &mut BufRead) {
read_message(read);
}
fn main() {}
error[E0277]: the trait bound `std::io::BufRead: std::marker::Sized` is not satisfied
--> src/main.rs:9:5
|
9 | read_message(read);
| ^^^^^^^^^^^^ `std::io::BufRead` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `std::io::BufRead`
note: required by `read_message`
--> src/main.rs:3:1
|
3 | / pub fn read_message<R>(read: &mut R)
4 | | where
5 | | R: BufRead,
6 | | {}
| |__^
The error message is well covered in existing questions:
Why does a generic method inside a trait require trait object to be sized?
What does "Sized is not implemented" mean?
Working with trait objects requiring sized
Why is the `Sized` bound necessary in this trait?
TL;DR: trait objects aren't guaranteed to have a size, but generics have a Sized trait bound by default.
read is getting passed by value
Yes, everything in Rust is always passed by value. Sometimes that value happens to be a reference though.
read_message is expecting a &mut BufRead
It is not. It is expecting a generic type that implements the trait BufRead. These two signatures are different:
// Reference to a concrete type
pub fn read_message<R>(read: &mut R)
where
R: BufRead,
// Trait object
pub fn read_message<R>(read: &mut BufRead)
See also:
What is the difference between <T: Trait> Box<T> and &Trait / Box<Trait>?
What makes something a "trait object"?
a &mut &mut BufRead, which is not the expected type
It's a perfectly cromulent type. BufRead is implemented for any mutable reference to any type that implements BufRead itself:
impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B
Besides, in this case you don't have a &mut &mut BufRead, you have a &mut &mut R. The concrete monomorphization for the types you've shown is actually a &mut &mut Bufreader.
You can fix it by :
changing the read_message function to accept unsized types. This is fine since R is always behind a pointer:
pub fn read_message<R>(read: &mut R)
where
R: ?Sized + BufRead,
changing the parse_capnp function to take a reference to a concrete type instead of a trait object:
fn parse_capnp<R>(read: &mut R)
where
R: BufRead,
{
read_message(read);
}
changing the parse_capnp function to take a concrete type instead of a trait object. You then need to take a reference to it yourself:
fn parse_capnp<R>(mut read: R)
where
R: BufRead,
{
read_message(&mut read);
}