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

ICE with higher-ranked lifetimes #48112

Closed
asajeffrey opened this issue Feb 10, 2018 · 4 comments
Closed

ICE with higher-ranked lifetimes #48112

asajeffrey opened this issue Feb 10, 2018 · 4 comments
Labels
A-lifetimes Area: Lifetimes / regions C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@asajeffrey
Copy link

In the middle of mucking around with coding existential lifetime polymorphism with higher-ranked lifetimes, I got an ICE. No surprise there.

https://play.rust-lang.org/?gist=b09f418c9fd12193515708d11ec80eb2&version=stable

produces

Standard Error

   Compiling playground v0.0.1 (file:///playground)
error: internal compiler error: /checkout/src/librustc/traits/trans/mod.rs:66: Encountered error `OutputTypeParameterMismatch(Binder(<[closure@src/main.rs:145:32: 148:18] as std::ops::FnOnce<(<*mut std::string::String as Unpack<'_>>::Unpacked,)>>), Binder(<[closure@src/main.rs:145:32: 148:18] as std::ops::FnOnce<(&mut std::string::String,)>>), Sorts(ExpectedFound { expected: &mut std::string::String, found: <*mut std::string::String as Unpack<'_>>::Unpacked }))` selecting `Binder(<[closure@src/main.rs:145:32: 148:18] as std::ops::FnOnce<(&mut std::string::String,)>>)` during trans

note: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports

note: rustc 1.23.0 (766bd11c8 2018-01-01) running on x86_64-unknown-linux-gnu

thread 'rustc' panicked at 'Box<Any>', /checkout/src/librustc_errors/lib.rs:471:8
note: Run with `RUST_BACKTRACE=1` for a backtrace.

error: Could not compile `playground`.

To learn more, run the command again with --verbose.

I'm afraid it's as far from a small self-contained example as possible, sigh.

@CAD97
Copy link
Contributor

CAD97 commented Feb 10, 2018

Did some minimization, and found some weird behavior.

More minimal case
use std::cell::RefMut;

fn main() {
    StateMachine2::Init.resume();
}

enum StateMachine2<'a> {
    Init,
    #[allow(dead_code)] // match required for ICE
    AfterTwoYields {
        p: Backed<'a, *mut String>,
    },
}

impl<'a> StateMachine2<'a> {
    fn take(&self) -> Self {
        StateMachine2::Init
    }
}

impl<'a> StateMachine2<'a> {
    fn resume(&mut self) -> () {
        use StateMachine2::*;
        match self.take() {
            AfterTwoYields { p } => {
                p.with(|_| {});
            }
            _ => panic!("Resume after completed."),
        }
    }
}

unsafe trait Unpack<'a> {
    type Unpacked: 'a;

    fn unpack(&self) -> Self::Unpacked {
        unsafe { std::mem::transmute_copy(&self) }
    }
}

unsafe trait Pack {
    type Packed;

    fn pack(&self) -> Self::Packed {
        unsafe { std::mem::transmute_copy(&self) }
    }
}

unsafe impl<'a> Unpack<'a> for String {
    type Unpacked = String;
}

unsafe impl Pack for String {
    type Packed = String;
}

unsafe impl<'a> Unpack<'a> for *mut String {
    type Unpacked = &'a mut String;
}

unsafe impl<'a> Pack for &'a mut String {
    type Packed = *mut String;
}

struct Backed<'a, U>(RefMut<'a, Option<String>>, U);

impl<'a, 'b, U: Unpack<'b>> Backed<'a, U> {
    fn with<F>(self, f: F) -> Backed<'a, ()>
    where
        F: for<'f> FnOnce(<U as Unpack<'f>>::Unpacked) -> (),
    {
        let result = f(self.1.unpack());
        Backed(self.0, result)
    }
}

I ran into a wall in minimization here because my next step was to inline <U: Unpack<'b>> in the bottom impl. So transforming between the following two blocks:

impl<'a, 'b, U: Unpack<'b>> Backed<'a, U> {
    fn with<F>(self, f: F) -> Backed<'a, ()>
    where
        F: for<'f> FnOnce(<U as Unpack<'f>>::Unpacked) -> (),
    {
        let result = f(self.1.unpack());
        Backed(self.0, result)
    }
}
impl<'a, 'b> Backed<'a, *mut String> {
    fn with<F>(self, f: F) -> Backed<'a, ()>
    where
        F: for<'f> FnOnce(&'f mut String) -> (),
    {
        let result = f(self.1.unpack());
        Backed(self.0, result)
    }
}

When making that transformation, the ICE goes away. Replacing the entire body with unimplemented!() does so as well. Other choke points where removal = no ICE:

  • 4   StateMachine2::Init.resume();
    
  • 26              p.with(|_| {});
    

@pietroalbini pietroalbini added A-lifetimes Area: Lifetimes / regions I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. labels Feb 10, 2018
@asajeffrey
Copy link
Author

You are doing a better job of minimizing than I managed!

@estebank
Copy link
Contributor

CC #29997.

@pnkfelix
Copy link
Member

closing as duplicate of #62529, which is where I will try to track future instances of this field of ICE.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lifetimes Area: Lifetimes / regions C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants