rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
99.1k stars 12.8k forks source link

Using impl Trait with closure local functions across crates results in ICE #43135

Closed Nemo157 closed 7 years ago

Nemo157 commented 7 years ago

Having an impl Trait type, containing a closure, where the closure has a locally defined function inside it, being passed across crate boundaries, results in an ICE.

The following function, defined in one crate, then used in another:

pub fn foo2() -> impl Future<Item=String, Error=()> {
    future::ok(()).and_then(|()| {
        fn msg() -> String { format!("Hello, {}!", "world") }
        future::ok(msg())
    })
}

gives the error:

error: internal compiler error: src/librustc_trans/collector.rs:662: Cannot create local trans-item for DefId { krate: CrateNum(12), node: DefIndex(9) => bar/ab23142::foo2[0]::{{closure}}[0]::msg[0] }

note: rustc 1.20.0-nightly (9b85e1cfa 2017-07-07) running on x86_64-apple-darwin

Presumably related to #40839/#35870, I found this while trying to come up with a decent workaround for #40839 specifically.

I have pushed a full testcase to https://github.com/Nemo157/impl-trait-across-crates, try building the foo2 crate.

Nemo157 commented 7 years ago

Actually, it looks like defining the function inside the closure is not needed, even just a private helper function in the crate that is only called from the closure will trigger this, e.g.

fn msg() -> String { format!("Hello, {}!", "world") }

pub fn foo2() -> impl Future<Item=String, Error=()> {
    future::ok(()).and_then(|()| future::ok(msg()) )
}
ishitatsuyuki commented 7 years ago

Stack trace:

thread 'rustc' panicked at 'Box<Any>', src/librustc_errors/lib.rs:490:8
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
  (panic handler, omitted)
  10: rustc_trans::collector::should_trans_locally
  11: rustc_trans::collector::visit_instance_use
  12: <rustc_trans::collector::MirNeighborCollector<'a, 'tcx> as rustc::mir::visit::Visitor<'tcx>>::visit_terminator_kind
  13: rustc::mir::visit::Visitor::visit_mir
  14: rustc_trans::collector::collect_items_rec
  (... recursion, omitted ...)
  42: rustc_trans::collector::collect_items_rec
  43: rustc_trans::base::collect_and_partition_translation_items::{{closure}}
  44: rustc_trans::base::trans_crate
  45: rustc_driver::driver::phase_4_translate_to_llvm
  46: rustc_driver::driver::compile_input::{{closure}}
  47: rustc_driver::driver::phase_3_run_analysis_passes::{{closure}}
  48: rustc_driver::driver::phase_3_run_analysis_passes
  49: rustc_driver::driver::compile_input
  50: rustc_driver::run_compiler
mhristache commented 7 years ago

I am also hitting this ICE. Is there a workaround?

ishitatsuyuki commented 7 years ago

@maximih Yes. Marking #[inline] as you encounter the error.

mhristache commented 7 years ago

Thanks. Using #[inline] seem to fix some occurances but not all. I still get the error for this method:

    #[inline]
    fn login<'a>(&'a self) -> impl Future<Item = String, Error = Error> + 'a {
        let req = self.prepare_login_request();
        result(req)
            .and_then(move |resp| check_http_status_parse_body(resp, hyper::Ok))
            .and_then(move |api_resp| {

                // check if the authentication was successful
                if &api_resp.status.reqStatus[..] == "SUCCESS" {

                    if api_resp.status.credentials.is_some() {

                        // save a copy of the token to be returned later
                        let to_return = api_resp.status.credentials.as_ref().unwrap().clone();

                        // add the data to cache
                        debug!("Login successful! Caching the response");
                        let to_store = Arc::new(api_resp);

                        // add the data to the cache
                        self.cache.insert_new(self.auth_url.clone(), to_store);

                        // return the token
                        ok(to_return)

                    } else {
                        err(Error::Auth)
                    }
                } else {
                    err(Error::Auth)
                }
            })
    }

The error I get:

error: internal compiler error: /checkout/src/librustc_trans/collector.rs:735: Cannot create local trans-item for DefId { krate: CrateNum(12), node: DefIndex(744) => ecmclient/ef9542a::{{impl}}[1]::login[0]::{{closure}}[1]::_LOC[0] }
plietar commented 7 years ago

I can't reproduce the original ICE, which was presumably fixed by #43857. This issue can probably be closed.

I'm however running into this ICE with generators, and have opened #44181 for that.

ishitatsuyuki commented 7 years ago

Triage: close? @Mark-Simulacrum