Skip to content

Confusing compiler error message when attempting to pass a trait object to a function using immutable reference #37914

@hniksic

Description

@hniksic
Contributor

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

bjorn3 commented on Nov 21, 2016

@bjorn3
Member

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

hniksic commented on Nov 21, 2016

@hniksic
ContributorAuthor

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.

hniksic

hniksic commented on Dec 19, 2017

@hniksic
ContributorAuthor

The message has changed in the meantime, but it still doesn't show how to fix the problem:

   Compiling playground v0.0.1 (file:///playground)
error: the `min` method cannot be invoked on a trait object
 --> src/main.rs:2:9
  |
2 |      *t.min().unwrap()
  |         ^^^

error: aborting due to previous error

It would be nice if the message at least hinted at mutability as the source of the problem.

shepmaster

shepmaster commented on Feb 16, 2018

@shepmaster
Member

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:

fn test(t: &Iterator<Item = &u64>) {
    t.next();
}
error[E0596]: cannot borrow immutable borrowed content `*t` as mutable
 --> src/main.rs:2:5
  |
1 | fn test(t: &Iterator<Item = &u64>) {
  |            ---------------------- use `&mut Iterator<Item = &u64>` here to make mutable
2 |     t.next();
  |     ^ cannot borrow as mutable
estebank

estebank commented on May 27, 2019

@estebank
Contributor

Current output:

error: the `min` method cannot be invoked on a trait object
 --> src/main.rs:2:9
  |
2 |      *t.min().unwrap()
  |         ^^^
added a commit that references this issue on Oct 7, 2019

Rollup merge of rust-lang#65077 - estebank:mut-trait-expected, r=niko…

fa961fa

14 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsC-enhancementCategory: An issue proposing an enhancement or a PR with one.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Participants

      @shepmaster@crlf0710@hniksic@acshi@estebank

      Issue actions

        Confusing compiler error message when attempting to pass a trait object to a function using immutable reference · Issue #37914 · rust-lang/rust