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

Macro using expr non-terminal can cause incorrect borrowck error #8754

Closed
lilyball opened this issue Aug 26, 2013 · 4 comments
Closed

Macro using expr non-terminal can cause incorrect borrowck error #8754

lilyball opened this issue Aug 26, 2013 · 4 comments
Labels
A-lifetimes Area: Lifetimes / regions A-syntaxext Area: Syntax extensions

Comments

@lilyball
Copy link
Contributor

A macro that uses an expr non-terminal that's used in both arms of an if statement, where the expression given to the macro expression involves borrowing *self as mutable, triggers an incorrect borrowck warning where it claims *self is being borrowed as mutable twice.

Code:

struct Foo {
    i: int
}

macro_rules! foo(
    ($code:expr) => (
        if true {
            $code
        } else {
            $code
        }
    )
)

impl Foo {
    pub fn foo(&mut self) {
        foo!({ self.bar() })
    }

    pub fn bar(&mut self) {
        self.i += 1;
    }
}

fn main() {
    let mut foo = Foo{i: 0};

    foo.foo();
}

Errors:

Untitled.rs:17:15: 17:20 error: cannot borrow `*self` as mutable more than once at a time
Untitled.rs:17         foo!({ self.bar() })
                              ^~~~~
Untitled.rs:5:0: 13:1 note: in expansion of foo!
Untitled.rs:17:8: 18:5 note: expansion site
Untitled.rs:17:15: 17:20 note: second borrow of `*self` as mutable occurs here
Untitled.rs:17         foo!({ self.bar() })
                              ^~~~~
Untitled.rs:5:0: 13:1 note: in expansion of foo!
Untitled.rs:17:8: 18:5 note: expansion site
Untitled.rs:17:15: 17:20 error: cannot borrow `*self` as mutable more than once at a time
Untitled.rs:17         foo!({ self.bar() })
                              ^~~~~
Untitled.rs:5:0: 13:1 note: in expansion of foo!
Untitled.rs:17:8: 18:5 note: expansion site
Untitled.rs:17:15: 17:20 note: second borrow of `*self` as mutable occurs here
Untitled.rs:17         foo!({ self.bar() })
                              ^~~~~
Untitled.rs:5:0: 13:1 note: in expansion of foo!
Untitled.rs:17:8: 18:5 note: expansion site
error: aborting due to 2 previous errors
@lilyball
Copy link
Contributor Author

Same error happens if I use a block non-terminal instead of an expr one, as in

macro_rules! foo(
    ($code:block) => (
        if true $code else $code
    )
)

@huonw
Copy link
Member

huonw commented Aug 26, 2013

There's a few other open issues about this iirc, I can't find them while on my phone though. I think a work-around is assigning the $code to a temporary i.e. let code = $code; /* use code instead of $code */ (although this can't be used in all situations).

@lilyball
Copy link
Contributor Author

@huonw That won't work for me, though. The real macro that hit this needs $code to see a variable that in one arm is &[u8] and in the other is ~[u8]. The real macro is closer to

macro_rules! foo(
    ($var:ident, $code:expr) => (
        if test($var) {
            let var = cond.raise($var.to_owned());
            $code
        } else {
            $code
        }
    )
)

@lilyball
Copy link
Contributor Author

Looks like this might be the same as #7971, although that macro has both repetitions of the expression in the same block of code (and, in fact, on the same line).

nikomatsakis added a commit to nikomatsakis/rust that referenced this issue Sep 7, 2013
…node has a

unique id. Fixes numerous bugs in macro expansion and deriving. Add two
representative tests.

Fixes rust-lang#7971
Fixes rust-lang#6304
Fixes rust-lang#8367
Fixes rust-lang#8754
Fixes rust-lang#8852
bors added a commit that referenced this issue Sep 10, 2013
…r=catamorphism

Ensures that each AST node has a unique id. Fixes numerous bugs in macro expansion and deriving. Add two
representative tests.

Fixes #7971
Fixes #6304
Fixes #8367
Fixes #8754
Fixes #8852
Fixes #2543
Fixes #7654
flip1995 pushed a commit to flip1995/rust that referenced this issue Jun 4, 2022
New lint `no_effect_replace`

Closes rust-lang#1595

Signed-off-by: Federico Guerinoni <guerinoni.federico@gmail.com>

changelog: Add [`no_effect_replace`] lint.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lifetimes Area: Lifetimes / regions A-syntaxext Area: Syntax extensions
Projects
None yet
2 participants