Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unhelpful / misleading error message and help message when using a reference to a vector #83924

Open
njor opened this issue Apr 6, 2021 · 4 comments
Labels
A-coercions Area: implicit and explicit `expr as Type` coercions A-iterators Area: Iterators C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@njor
Copy link

njor commented Apr 6, 2021

Hello,
There is a case where the Rust compiler error message is misleading. I tried this code :

fn main() {
    let mut values = vec![10, 11, 12];
    let v = &mut values;

    let mut max = 0;
    
    for n in v {
        max = std::cmp::max(max, *n);
    }

    println!("max is {}", max);
    println!("Converting to percentages of maximum value...");
    for n in v {
        *n = 100 * (*n) / max;
    }
    println!("values: {:#?}", values);
}

…which gives the following error message, and misleading « help » message :

error[E0382]: use of moved value: `v`
   --> src/main.rs:13:14
    |
3   |     let v = &mut values;
    |         - move occurs because `v` has type `&mut Vec<i32>`, which does not implement the `Copy` trait
...
7   |     for n in v {
    |              -
    |              |
    |              `v` moved due to this implicit call to `.into_iter()`
    |              help: consider borrowing to avoid moving into the for loop: `&v`
...
13  |     for n in v {
    |              ^ value used here after move
    |

Especially, the help: consider borrowing to avoid moving into the for loop: '&v' is the misleading part, does not help solve the problem at all, and sent me an a wrong path.
As I am new to Rust, this got me scratching my head for some time until someone explained it to me (here).
(And since the Rust compiler is most of the time very helpful, I did not even consider that its suggestion could be wrong haha. Hm.)
Instead of this, maybe a short message explaining how to reborrow the reference in this kind of situation would be more helpful and less misleading ?
Thank you.

Meta

rustc --version --verbose:

rustc 1.48.0 (7eac88abb 2020-11-16)
binary: rustc
commit-hash: 7eac88abb2e57e752f3302f02be5f3ce3d7adfb4
commit-date: 2020-11-16
host: x86_64-unknown-linux-gnu
release: 1.48.0
LLVM version: 11.0
@njor njor added the C-bug Category: This is a bug. label Apr 6, 2021
@eggyal
Copy link
Contributor

eggyal commented Apr 6, 2021

I'm actually surprised that you got E0277 when doing for n in &v since I'd have expected that to resolve (via deref coercion) to the impl of IntoIterator for &Vec.

@eggyal
Copy link
Contributor

eggyal commented Apr 6, 2021

@rustbot label: +T-libs +A-iterators +A-coercions

@rustbot rustbot added A-coercions Area: implicit and explicit `expr as Type` coercions A-iterators Area: Iterators T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Apr 6, 2021
@eggyal
Copy link
Contributor

eggyal commented Apr 6, 2021

I'm actually surprised that you got E0277 when doing for n in &v since I'd have expected that to resolve (via deref coercion) to the impl of IntoIterator for &Vec.

Okay, this is due to the desugaring in rustc_ast_lowering::expr::lower_expr_for:

/// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:
/// ```rust
/// {
/// let result = match ::std::iter::IntoIterator::into_iter(<head>) {
/// mut iter => {
/// [opt_ident]: loop {
/// let mut __next;
/// match ::std::iter::Iterator::next(&mut iter) {
/// ::std::option::Option::Some(val) => __next = val,
/// ::std::option::Option::None => break
/// };
/// let <pat> = __next;
/// StmtKind::Expr(<body>);
/// }
/// }
/// };
/// result
/// }
/// ```

Because into_iter is invoked as a trait function IntoIterator::into_iter(<head>) rather than a method, deref coercion does not occur. It would be nicer if this could instead desugar to <head>.into_iter() but I guess there could then be issues correctly resolving to IntoIterator—but it shouldn't be impossible to ensure that happens correctly?

@eggyal
Copy link
Contributor

eggyal commented Apr 6, 2021

@rustbot label: -T-libs +T-compiler

@rustbot rustbot added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Apr 6, 2021
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Apr 7, 2021
Add suggestion to reborrow mutable references when they're moved in a for loop

Address rust-lang#83924
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Apr 7, 2021
Add suggestion to reborrow mutable references when they're moved in a for loop

Address rust-lang#83924
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-coercions Area: implicit and explicit `expr as Type` coercions A-iterators Area: Iterators C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants