Skip to content

&mut self to &mut Trait moves self #8813

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

Closed
alexcrichton opened this issue Aug 28, 2013 · 5 comments
Closed

&mut self to &mut Trait moves self #8813

alexcrichton opened this issue Aug 28, 2013 · 5 comments
Labels
A-trait-system Area: Trait system

Comments

@alexcrichton
Copy link
Member

This code shows some odd behavior:

trait A {}
struct B;
impl A for B {}

fn foo(_: &mut A) {}

impl B {
    fn good(&mut self) {
        self.foo();
        foo(&mut *self as &mut A);
        self.foo();
    }

    fn bad(&mut self) {
        self.foo();
        foo(self as &mut A);
        self.foo();
    }

    fn foo(&mut self) {}
}

fn main() {}

Because good works, I would expect bad to work as well.

$ rustc test.rs
test.rs:17:8: 17:13 error: use of moved value: `self`
test.rs:17         self.foo();
                   ^~~~~
test.rs:16:12: 16:19 note: `self` moved here because it has type `&mut B`, 
which is non-copyable (perhaps you meant to use clone()?)
test.rs:16         foo(self as &mut A);
                       ^~~~~~~
error: aborting due to previous error

cc @nikomatsakis

@nikomatsakis
Copy link
Contributor

Yes this is a bug. I've noticed it too. The compiler should reborrow automatically as we do almost everywhere else; you can workaround it temporarily by making the reborrow explicit (&mut *self as &mut A).

@Ogeon
Copy link

Ogeon commented Jul 26, 2014

I noticed that this is also an issue with references to generics. The following example should compile and run just fine:

trait TraitA {}

struct A;

impl TraitA for A {}

fn foo1<T: TraitA>(something: &T) {
    object_bar(something);
    object_bar(something);
}

fn foo2<T: TraitA>(something: &mut T) {
    generic_bar(something);
    generic_bar(something);
}

fn foo3<T: TraitA>(something: &mut T) {
    mut_object_bar(something);
    mut_object_bar(something);
}

fn foo4<T: TraitA>(something: &mut T) {
    object_bar(something);
    object_bar(something);
}

fn object_bar(_something: &TraitA) {}
fn mut_object_bar(_something: &mut TraitA) {}
fn generic_bar<T: TraitA>(_something: &mut T) {}

fn main() {
    let mut a = A;

    foo1(&a);
    foo2(&mut a);
    foo3(&mut a);
    foo4(&mut a);
}

but rustc complains with

<anon>:19:20: 19:29 error: use of moved value: `something`
<anon>:19     mut_object_bar(something);
                             ^~~~~~~~~
<anon>:18:20: 18:29 note: `something` moved here because it has type `&mut TraitA`, which is non-copyable (perhaps you meant to use clone()?)
<anon>:18     mut_object_bar(something);
                             ^~~~~~~~~
<anon>:24:16: 24:25 error: use of moved value: `something`
<anon>:24     object_bar(something);
                         ^~~~~~~~~
<anon>:23:16: 23:25 note: `something` moved here because it has type `&TraitA`, which is moved by default (use `copy` to override)
<anon>:23     object_bar(something);
                         ^~~~~~~~~
error: aborting due to 2 previous errors
playpen: application terminated with error code 101

Playpen link

@steveklabnik
Copy link
Member

We no longer auto-borrow in this situation, so I think that this is invalid. @nikomatsakis @alexcrichton ?

@steveklabnik steveklabnik added the A-trait-system Area: Trait system label Jan 29, 2015
@nikomatsakis
Copy link
Contributor

I think this is still as true as it ever was. In general, we aggressively "reborrow" all &mut values so as to hide the fact that they are affine (that is, they move by default). But in this particular case of doing x as &mut Foo, we do not reborrow, so the value x gets consumed. This is not exactly a bug but it is suboptimal. I consider it an enhancement.

@steveklabnik
Copy link
Member

I'm pulling a massive triage effort to get us ready for 1.0. As part of this, I'm moving stuff that's wishlist-like to the RFCs repo, as that's where major new things should get discussed/prioritized.

This issue has been moved to the RFCs repo: rust-lang/rfcs#800

xFrednet pushed a commit to xFrednet/rust that referenced this issue May 21, 2022
…r=Alexendoo

Fix redundant_allocation warning for Rc<Box<str>>

changelog: [`redundant_allocation`] Fixes rust-lang#8604

Fixes false positives where a fat pointer with `str` type was made thin by another allocation, but that thinning allocation was marked as redundant
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-trait-system Area: Trait system
Projects
None yet
Development

No branches or pull requests

4 participants