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

[MIR] broken MIR (bad assignment) for non-returning closure #32959

Closed
alexcrichton opened this issue Apr 14, 2016 · 13 comments
Closed

[MIR] broken MIR (bad assignment) for non-returning closure #32959

alexcrichton opened this issue Apr 14, 2016 · 13 comments
Labels
A-MIR Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@alexcrichton
Copy link
Member

This code:

fn main() {
    let o: Option<u32> = None;

    let foo = || -> ! {
        loop {}
    };

    o.unwrap_or_else(|| {
        foo();
    });
}

Will yield this warning:

main.rs:8:25: 10:6 warning: broken MIR (return = ()): bad assignment (u32 = ()): Sorts(ExpectedFound { expected: u32, found: () })
main.rs: 8     o.unwrap_or_else(|| {
main.rs: 9         foo();
main.rs:10     });
@alexcrichton alexcrichton added the A-MIR Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html label Apr 14, 2016
@nagisa
Copy link
Member

nagisa commented Apr 14, 2016

This happens because we construct MIR for the 2nd closure as if foo closure was converging. That’s trivially wrong. I’m looking into fixing this.

@nagisa
Copy link
Member

nagisa commented Apr 14, 2016

Okay, so:

  1. You cannot have ! as an associated type;
  2. Fn has Self::Output as return type for closures;
  3. MIR uses <[[email protected]:4:15: 6:6] as core::ops::Fn<()>>::call(tmp1, tmp3) to call the offending closure in question.

Specifically for MIR, we could stop using Fn::call and have some special case for closures, but to me it seems like the issue is deeper rooted than MIR here.

@arielb1
Copy link
Contributor

arielb1 commented Apr 15, 2016

Can we have diverging closures, anyway?

@arielb1
Copy link
Contributor

arielb1 commented Apr 15, 2016

The closure has the output type (), not !. This code should not compile (as splitting it into separate functions should demonstrate). Or we should support diverging closures which requires !.

@arielb1
Copy link
Contributor

arielb1 commented Apr 15, 2016

This seems like a serious backwards-compatibility hazard. We seem to have forced ourselves to introduce a ! type. Unless we call this code "just a bug".

@nikomatsakis
Copy link
Contributor

Hmm. I thought that || -> ! was disallowed now.

@nikomatsakis
Copy link
Contributor

That is, we are not supposed to have diverging closures!

@nikomatsakis nikomatsakis added I-nominated T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Apr 16, 2016
@canndrew
Copy link
Contributor

We seem to have forced ourselves to introduce a ! type.

You say that like it's a bad thing.

That is, we are not supposed to have diverging closures!

Well that's just a crappy, arbitrary restriction that we can get rid of. Also we do have diverging closures because you can write || -> Void

@arielb1
Copy link
Contributor

arielb1 commented Apr 16, 2016

@canndrew

I don't want to have MIR blocked on new RFCs, basically. Maybe we can get that done fast enough.

Well that's just a crappy, arbitrary restriction that we can get rid of. Also we do have diverging closures because you can write || -> Void

A || -> Void closure is not treated as diverging for dataflow purposes - you have to match on it for that.

@nikomatsakis
Copy link
Contributor

On Sat, Apr 16, 2016 at 02:33:55AM -0700, Andrew Cann wrote:

That is, we are not supposed to have diverging closures!

Well that's just a crappy, arbitrary restriction that we can get rid of. Also we do have diverging closures because you can write || -> Void

I don't really disagree. I'd just prefer to make that decision on its
own merits, not because of this oversight. But oh well: the failure to
completely remove -> ! closures (which is my oversight as much as
anyone's) does kind of force our hand. We have to fix it one way or
another, and it's certainly worth thinking if we can fix it in a
backwards-compatible way (e.g., by making ! into a type, and
assigning stronger semantics to empty enums, or at least to Void).

@nikomatsakis
Copy link
Contributor

Discussed in @rust-lang/lang team meeting -- we think it makes sense to reconsider the RFC that makes ! into a sort of type.

We also should try to find some sort of way to "unregress" this test case in the short term, but I'm not sure what's the best plan there.

bors added a commit that referenced this issue May 7, 2016
[MIR] Temporary hack for 32959

Gets rid of the warning. This is more elegant that I thought it would be, actually.

r? @nikomatsakis

cc #32959
@nagisa
Copy link
Member

nagisa commented May 9, 2016

The code sample does not emit the warning anymore, but please keep the issue open because it was hacked around only.

@nagisa
Copy link
Member

nagisa commented Jan 28, 2017

Now that we have actual never type, it might be interesting to revisit this.

nagisa added a commit to nagisa/rust that referenced this issue Jan 29, 2017
This workaround is no longer necessary as Rust, and by extension MIR, now support uninhabited type
properly. This removes the workaround for the gh32959 that was introduced in gh33267.

Fixes rust-lang#32959
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Feb 2, 2017
…, r=pnkfelix

Remove the workaround for gh32959

This workaround is no longer necessary as Rust, and by extension MIR, now support uninhabited type
properly. This removes the workaround for the gh32959 that was introduced in gh33267.

Fixes rust-lang#32959
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-MIR Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants