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

Moving out of & in match yields a confusing error message #8064

Closed
alexcrichton opened this issue Jul 26, 2013 · 7 comments
Closed

Moving out of & in match yields a confusing error message #8064

alexcrichton opened this issue Jul 26, 2013 · 7 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints P-low Low priority

Comments

@alexcrichton
Copy link
Member

Currently, moving out of a managed box in a match yields an unclear error message that's sometimes difficult to track down:

$ cat foo.rs
struct A {
    a: ~int
}

fn free<T>(_: T) {}

fn main() {
    let a = &A { a: ~1 };
    match a.a {
        n => { free(n) }
    }
    free(a)
}
$ rustc foo.rs
foo.rs:9:10: 9:13 error: cannot move out of dereference of `&`-pointer
foo.rs:9     match a.a {
                   ^~~
error: aborting due to previous error

However when using owned boxes, you get a very nice and clear error message

$ cat foo.rs
struct A {
    a: ~int
}

fn free<T>(_: T) {}

fn main() {
    let a = ~A { a: ~1 };
    match a.a {
        n => { free(n) }
    }
    free(a)
}
$ rustc foo.rs
foo.rs:12:9: 12:10 error: use of partially moved value: `a`
foo.rs:12     free(a)
                   ^
foo.rs:10:8: 10:9 note: `(*a).a` moved here because it has type `~int`, which is moved by default (use `ref` to override)
foo.rs:10         n => { free(n) }
                  ^
error: aborting due to previous error

It'd be awesome to have similar behavior (the extra note) in the managed case as well.

@alexcrichton
Copy link
Member Author

Nominating for production-ready status.

@huonw
Copy link
Member

huonw commented Jul 27, 2013

One can't partially move out of a @ box at all (since moving requires ownership, and no-one owns the contents of an @), so it's not clear to me what the extra note would point to.

@alexcrichton
Copy link
Member Author

In the owned case, the note points to the exact location of where the move happened. It's true that the error messages are slightly different because they're exercising different properties of the language, but it would be great if in the @ case it actually pointed at where the move happened in the case as well.

Currently if you have a match with ~20 arms and you make a large refactoring and all of a sudden one of the arms causes a move, it's sometimes difficult to track it down. I think that this issue is specific to just match in that it should point to the arm which was considered as having moved out.

@nikomatsakis
Copy link
Contributor

Interesting, I tried to always point at the arm when giving an error, but I guess this case slipped by. This shouldn't be so hard to fix.

@catamorphism
Copy link
Contributor

Accepted production-ready

@alexcrichton
Copy link
Member Author

Note that this has the same bad error message if you're moving out of an & pointer.

@pnkfelix
Copy link
Member

Not a 1.0 blocker, P-low.

@alexcrichton alexcrichton changed the title Moving out of @ in match yields a confusing error message Moving out of & in match yields a confusing error message Mar 20, 2014
bors added a commit that referenced this issue Apr 16, 2014
This commit changes the way move errors are reported when some value is
captured by a PatIdent. First, we collect all of the "cannot move out
of" errors before reporting them, and those errors with the same "move
source" are reported together. If the move is caused by a PatIdent (that
binds by value), we add a note indicating where it is and suggest the
user to put `ref` if they don't want the value to move. This makes the
"cannot move out of" error in match expression nicer (though the extra
note may not feel that helpful in other places :P). For example, with
the following code snippet,

```rust
enum Foo {
    Foo1(~u32, ~u32),
    Foo2(~u32),
    Foo3,
}

fn main() {
    let f = &Foo1(~1u32, ~2u32);
    match *f {
        Foo1(num1, num2) => (),
        Foo2(num) => (),
        Foo3 => ()
    }
}
```

Errors before the change:

```rust
test.rs:10:9: 10:25 error: cannot move out of dereference of `&`-pointer
test.rs:10         Foo1(num1, num2) => (),
                   ^~~~~~~~~~~~~~~~
test.rs:10:9: 10:25 error: cannot move out of dereference of `&`-pointer
test.rs:10         Foo1(num1, num2) => (),
                   ^~~~~~~~~~~~~~~~
test.rs:11:9: 11:18 error: cannot move out of dereference of `&`-pointer
test.rs:11         Foo2(num) => (),
                   ^~~~~~~~~
```

After:

```rust
test.rs:9:11: 9:13 error: cannot move out of dereference of `&`-pointer
test.rs:9     match *f {
                    ^~
test.rs:10:14: 10:18 note: attempting to move value to here (to prevent the move, use `ref num1` or `ref mut num1` to capture value by reference)
test.rs:10         Foo1(num1, num2) => (),
                        ^~~~
test.rs:10:20: 10:24 note: and here (use `ref num2` or `ref mut num2`)
test.rs:10         Foo1(num1, num2) => (),
                              ^~~~
test.rs:11:14: 11:17 note: and here (use `ref num` or `ref mut num`)
test.rs:11         Foo2(num) => (),
                        ^~~
```

Close #8064
@bors bors closed this as completed in 13d6c35 Apr 16, 2014
flip1995 pushed a commit to flip1995/rust that referenced this issue Apr 7, 2022
…fate

Fix `as_deref_mut` false positives in `needless_option_as_deref`

Also moves it into `methods/`

Fixes rust-lang#7846
Fixes rust-lang#8047

changelog: [`needless_option_as_deref`]: No longer lints for `as_deref_mut` on Options that cannot be moved

supersedes rust-lang#8064
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints P-low Low priority
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants