Skip to content

3 "broken MIR" ICEs when combining futures and assoc. types #61320

Closed
@jonas-schievink

Description

@jonas-schievink

The following code, which uses futures, a few self-defined traits with associated types, and where-clauses on those, causes 3 "broken MIR" ICEs when built (Playground link):

use futures::{Future, IntoFuture};

struct Request<T>(T);

trait RequestContext {}
impl<T> RequestContext for T {}
struct NoContext;
impl AsRef<NoContext> for NoContext {
    fn as_ref(&self) -> &Self { &NoContext }
}

type BoxedError = Box<dyn ::std::error::Error + Send + Sync>;
type DefaultFuture<T, E> = Box<dyn Future<Item=T, Error=E> + Send>;

trait Guard: Sized {
    type Result: IntoFuture<Item = Self, Error = BoxedError>;
    fn from_request(
        request: &Request<()>, 
    ) -> Self::Result;
}

trait FromRequest: Sized {
    type Context;
    type Future: Future<Item = Self, Error = BoxedError> + Send;
    fn from_request(
        request: Request<()>, 
    ) -> Self::Future;
}

struct MyGuard;
impl Guard for MyGuard {
    type Result = Result<Self, BoxedError>;
    fn from_request(_request: &Request<()>) -> Self::Result {
        Ok(MyGuard)
    }
}

struct Generic<I> {
    _inner: I,
}

impl<I> FromRequest for Generic<I>
where
    MyGuard: Guard,
    <MyGuard as Guard>::Result:
        futures::IntoFuture<Item = MyGuard, Error = BoxedError>,
    <<MyGuard as Guard>::Result as futures::IntoFuture>::Future:
        Send,
    I: FromRequest<Context = NoContext>
{
    type Future = DefaultFuture<Self, BoxedError>;
    type Context = NoContext;
    fn from_request(
        headers: Request<()>,
    ) -> DefaultFuture<Self, BoxedError> {
        let _future = <MyGuard as Guard>::from_request(&headers)
            .into_future()
            .and_then(move |_| {
                <I as FromRequest>::from_request(headers)
                    .into_future()
                    .and_then(move |fld_inner| {
                        Ok(Generic {
                            _inner: fld_inner,
                        })
                        .into_future()
                    })
            });
        panic!();
    }
}

Compiler output:

error: internal compiler error: broken MIR in DefId(0/0:29 ~ playground[aa0a]::{{impl}}[3]::from_request[0]) (Terminator { source_info: SourceInfo { span: src/lib.rs:56:23: 57:27, scope: scope[0] }, kind: _4 = const futures::future::IntoFuture::into_future(move _5) -> [return: bb3, unwind: bb4] }): call dest mismatch (futures::future::result_::FutureResult<MyGuard, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>> <- <std::result::Result<MyGuard, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>> as futures::future::IntoFuture>::Future): NoSolution
  --> src/lib.rs:56:64
   |
56 |         let _future = <MyGuard as Guard>::from_request(&headers)
   |                                                                ^

error: internal compiler error: broken MIR in DefId(0/1:20 ~ playground[aa0a]::{{impl}}[3]::from_request[0]::{{closure}}[0]) (NoSolution): could not prove Binder(TraitPredicate(<<std::result::Result<MyGuard, std::boxed::Box<(dyn std::error::Error + std::marker::Send + std::marker::Sync + 'static)>> as futures::future::IntoFuture>::Future as std::marker::Send>))
  --> src/lib.rs:61:31
   |
61 |                       .and_then(move |fld_inner| {
   |  _______________________________^
62 | |                         Ok(Generic {
63 | |                             _inner: fld_inner,
64 | |                         })
65 | |                         .into_future()
66 | |                     })
   | |_____________________^

error: internal compiler error: broken MIR in DefId(0/0:29 ~ playground[aa0a]::{{impl}}[3]::from_request[0]) (NoSolution): could not prove Binder(TraitPredicate(<<std::result::Result<MyGuard, std::boxed::Box<(dyn std::error::Error + std::marker::Send + std::marker::Sync + 'static)>> as futures::future::IntoFuture>::Future as std::marker::Send>))
  --> src/lib.rs:58:23
   |
58 |               .and_then(move |_| {
   |  _______________________^
59 | |                 <I as FromRequest>::from_request(headers)
60 | |                     .into_future()
61 | |                     .and_then(move |fld_inner| {
...  |
66 | |                     })
67 | |             });
   | |_____________^

thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:354:17
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

error: internal compiler error: unexpected panic

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.35.0 (3c235d560 2019-05-20) running on x86_64-unknown-linux-gnu

note: compiler flags: -C codegen-units=1 -C debuginfo=2 --crate-type lib

note: some of the compiler flags provided by cargo are hidden

error: Could not compile `playground`.

Any help on minifying the code would be welcome. Inlining the futures trait definitions into the crate makes one of the ICEs go away, so this version pulls it in as an external crate.

Metadata

Metadata

Assignees

Labels

A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlA-associated-itemsArea: Associated items (types, constants & functions)C-bugCategory: This is a bug.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions