Description
The following code fails to compile because the reference to the iterator trait object must be mutable, to enable advancing the iterator:
fn test(t: &Iterator<Item=&u64>) -> u64 {
*t.min().unwrap()
}
fn main() {
let array = [0u64];
test(&array.iter());
}
When the problem is fixed by declaring the trait object as mutable, the code compiles and runs just fine:
fn test(t: &mut Iterator<Item=&u64>) -> u64 {
*t.min().unwrap()
}
fn main() {
let array = [0u64];
test(&mut array.iter());
}
Understanding the problem, I would expect the error message for the first snippet to be something along the lines of "error: Iterator<Item=&u64>::next requires a mutable reference". Instead, the compilation failed with the following error:
error[E0277]: the trait bound `std::iter::Iterator<Item=&u64>: std::marker::Sized` is not satisfied
--> iter.rs:2:9
|
2 | *t.min().unwrap()
| ^^^ trait `std::iter::Iterator<Item=&u64>: std::marker::Sized` not satisfied
|
= note: `std::iter::Iterator<Item=&u64>` does not have a constant size known at compile-time
error: aborting due to previous error
Being a beginner in Rust, this error message threw me off. First, I couldn't understand why Rust was insisting that the object is unsized, when the object was declared to accept a reference (fat pointer) to a trait, or that was at least my intention. (I still don't understand this part.)
More importantly, there was no hint that the problem could be resolved simply by changing &
to &mut
in declaration and invocation. Once I realized that, the change was obvious and easy, but the compiler's error message did not help me understand the problem.
Activity
bjorn3 commentedon Nov 21, 2016
Iterator::min consumes self, which requires the size of self to be known comile time. If you have a non mutable reference rustc will deref the reference to get something it can call .min on. However if you have a mutable reference rustc knows that there is a implementation of Iterator for it without having to dereference it, so you dont have a unsized value.
hniksic commentedon Nov 21, 2016
Thanks for the clarification. Could the compiler's diagnostics check, "if only this reference to trait were mutable, it would no longer be unsized", and provide a hint to the user? In many other cases rustc does an excellent job in guiding the user toward correct code.
Iterator
trait object #32627hniksic commentedon Dec 19, 2017
The message has changed in the meantime, but it still doesn't show how to fix the problem:
It would be nice if the message at least hinted at mutability as the source of the problem.
shepmaster commentedon Feb 16, 2018
This problem surfaced again on Stack Overflow, for the same underlying reason:
&Iterator
.An interesting point is that calling
next
directly does have a good error:estebank commentedon May 27, 2019
Current output:
Rollup merge of rust-lang#65077 - estebank:mut-trait-expected, r=niko…
14 remaining items