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

match arm bindings have weird lifetimes #46525

Closed
arielb1 opened this issue Dec 5, 2017 · 9 comments · Fixed by #60174
Closed

match arm bindings have weird lifetimes #46525

arielb1 opened this issue Dec 5, 2017 · 9 comments · Fixed by #60174
Assignees
Labels
A-NLL Area: Non-lexical lifetimes (NLL) C-cleanup Category: PRs that clean code up or issues documenting cleanup. NLL-complete Working towards the "valid code works" goal P-medium Medium priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@arielb1
Copy link
Contributor

arielb1 commented Dec 5, 2017

I should have opened this issue a long while ago, but now I have a place in the code I want to link it to.

Match bindings have weird lifetime, especially when guards are involved: instead of the destructors executing when the bindings go out of scope, all of the destructors of all match bindings are run just after the match ends.

e.g. I think this causes unnecessary drop elaboration and etc. load on big functions with many-armed matches.

One very weird case is this:

    fn main() {
         match 0 {
             a | a
             if { println!("a={}", a); false } => {}
             _ => {}
         }
     }

Here, the guard is executed twice, and a is only storage-killed after the match ends, so we have storage-live -> storage-live -> storage-dead, which might annoy some things.

FIXME: remember more weird cases and clean them up.

@arielb1 arielb1 added C-cleanup Category: PRs that clean code up or issues documenting cleanup. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-compiler-nll labels Dec 5, 2017
@arielb1
Copy link
Contributor Author

arielb1 commented Dec 6, 2017

I think that it will be hard to fix this in a way AST borrowck and region inference will understand, but afterwards this is fair game.

@nikomatsakis
Copy link
Contributor

I think that this fits into what @pnkfelix is doing in overhauling how we handle match arms?

@nikomatsakis
Copy link
Contributor

I guess this is just a matter of generating better code...?

@nikomatsakis nikomatsakis added A-NLL Area: Non-lexical lifetimes (NLL) and removed WG-compiler-nll labels Aug 27, 2018
@pnkfelix
Copy link
Member

Re-triaging for #56754. NLL-complete. P-medium. Assigning to self.

@pnkfelix pnkfelix added P-medium Medium priority NLL-complete Working towards the "valid code works" goal and removed NLL-deferred labels Dec 19, 2018
@pnkfelix pnkfelix self-assigned this Dec 19, 2018
@pnkfelix
Copy link
Member

pnkfelix commented Feb 22, 2019

In terms of observable semantics with implementations of Drop, its hard today to encounter this as a user, unless you turn on #![feature(bind_by_move_pattern_guards)]. (And even then, I'm not sure a rust developer can tell the difference between the code we generate today versus what @arielb1 desires, at least in terms of potential MIR-borrowck errors.)

So like @nikomatsakis, I think this is just a matter of generating better code.

But I would like to actually be sure of that before we e.g. turn off NLL migrate more (and subsequently stabilize #![feature(bind_by_move_pattern_guards)). Which may mean I want to just do the code-gen changes suggested here.

Increasing priority of this issue to P-high.

@pnkfelix pnkfelix added P-high High priority and removed P-medium Medium priority labels Feb 22, 2019
@matthewjasper matthewjasper self-assigned this Mar 27, 2019
@pnkfelix pnkfelix removed their assignment Mar 28, 2019
@Centril Centril added I-nominated T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Mar 28, 2019
@Centril
Copy link
Contributor

Centril commented Mar 28, 2019

Nominating for some discussion on today's lang meeting.


Also, here's an example of observable drop order:

#![feature(bind_by_move_pattern_guards)]

#[derive(Debug)]
struct A;

impl A {
    fn foo(&self) -> bool { dbg!(2); false }
}

impl Drop for A {
    fn drop(&mut self) { dbg!(3); }
}

fn main() {
    dbg!(0);
    match dbg!(A) {
        a if a.foo() => { dbg!(4); }
        _ => { dbg!(5); }
    }
    dbg!(6);
}

prints:

[src/main.rs:15] 0 = 0
[src/main.rs:16] A = A
[src/main.rs:7] 2 = 2
[src/main.rs:18] 5 = 5
[src/main.rs:11] 3 = 3
[src/main.rs:20] 6 = 6

showing that 5 happens before 3.
The _ patterns makes no difference.

@matthewjasper
Copy link
Contributor

Fixing this issue, would not change the order there, or any observable runtime behaviour at all.

@Centril Centril removed I-nominated T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Mar 28, 2019
@pnkfelix
Copy link
Member

pnkfelix commented Apr 4, 2019

triage: @matthewjasper do you think this actually warrants P-high? I know we want to do it eventually, but if things are working okay thus far, it seems like we can continue to coast?

@matthewjasper
Copy link
Contributor

It's not really p-high, but I hope to create a PR for this once migrate mode is enabled on all editions.

@matthewjasper matthewjasper added P-medium Medium priority and removed P-high High priority labels Apr 5, 2019
Centril added a commit to Centril/rust that referenced this issue May 15, 2019
… r=pnkfelix

Add match arm scopes and other scope fixes

* Add drop and lint scopes for match arms.
* Lint attributes are now respected on match arms.
* Make sure we emit a StorageDead if we diverge when initializing a temporary.
* Adjust MIR pretty printing of scopes for locals.
* Don't generate duplicate lint scopes for `let statements`.
* Add some previously missing fake borrows for matches.

closes rust-lang#46525

cc @rust-lang/compiler
Centril added a commit to Centril/rust that referenced this issue May 15, 2019
… r=pnkfelix

Add match arm scopes and other scope fixes

* Add drop and lint scopes for match arms.
* Lint attributes are now respected on match arms.
* Make sure we emit a StorageDead if we diverge when initializing a temporary.
* Adjust MIR pretty printing of scopes for locals.
* Don't generate duplicate lint scopes for `let statements`.
* Add some previously missing fake borrows for matches.

closes rust-lang#46525

cc @rust-lang/compiler
bors added a commit that referenced this issue May 15, 2019
Add match arm scopes and other scope fixes

* Add drop and lint scopes for match arms.
* Lint attributes are now respected on match arms.
* Make sure we emit a StorageDead if we diverge when initializing a temporary.
* Adjust MIR pretty printing of scopes for locals.
* Don't generate duplicate lint scopes for `let statements`.
* Add some previously missing fake borrows for matches.

closes #46525

cc @rust-lang/compiler
bors added a commit that referenced this issue May 23, 2019
Add match arm scopes and other scope fixes

* Add drop and lint scopes for match arms.
* Lint attributes are now respected on match arms.
* Make sure we emit a StorageDead if we diverge when initializing a temporary.
* Adjust MIR pretty printing of scopes for locals.
* Don't generate duplicate lint scopes for `let statements`.
* Add some previously missing fake borrows for matches.

closes #46525

cc @rust-lang/compiler
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-NLL Area: Non-lexical lifetimes (NLL) C-cleanup Category: PRs that clean code up or issues documenting cleanup. NLL-complete Working towards the "valid code works" goal P-medium Medium priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants