Skip to content

match arm bindings have weird lifetimes #46525

New issue

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

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

Already on GitHub? # to your account

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
# for free to join this conversation on GitHub. Already have an account? # 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