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

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

Closed
Nemo157 opened this Issue Jul 9, 2017 · 7 comments

Comments

Projects
None yet
5 participants
@Nemo157
Copy link
Contributor

Nemo157 commented Jul 9, 2017

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

This comment has been minimized.

Copy link
Contributor Author

Nemo157 commented Jul 9, 2017

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

This comment has been minimized.

Copy link
Member

ishitatsuyuki commented Aug 7, 2017

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

This comment has been minimized.

Copy link

mhristache commented Aug 12, 2017

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

@ishitatsuyuki

This comment has been minimized.

Copy link
Member

ishitatsuyuki commented Aug 12, 2017

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

@mhristache

This comment has been minimized.

Copy link

mhristache commented Aug 13, 2017

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] }

bors added a commit that referenced this issue Aug 14, 2017

Auto merge of #43857 - michaelwoerister:fix-impl-trait-closure-vis, r…
…=eddyb

Mark closures return via impl-trait as reachable.

This should fix some of the open `impl trait` issues, like #40839, #43135, and #35870.

r? @eddyb
@plietar

This comment has been minimized.

Copy link
Contributor

plietar commented Aug 30, 2017

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

This comment has been minimized.

Copy link
Member

ishitatsuyuki commented Nov 1, 2017

Triage: close? @Mark-Simulacrum

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment