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

'assertion failed: current_depth > ty::DebruijnIndex::INNERMOST' when using generators #51353

Closed
ngg opened this Issue Jun 4, 2018 · 8 comments

Comments

Projects
None yet
9 participants
@ngg
Copy link
Contributor

ngg commented Jun 4, 2018

I've got an ICE when I tried to use async/await support from futures-0.2 together with impl traits. I've tried to minimized the code, now there are no external dependencies:

// ice.rs

#![feature(generators)]

trait Future {
    type Item;
}

struct Join<T: Future>(T::Item);

impl<F: Fn() -> ()> Future for F
{
    type Item = ();
}

fn join<T: Future<Item = ()>>(_: T) -> Join<T>
{
    Join(())
}

fn ice<'a>() -> impl Send + 'a {
    join(|| ())
}

fn main() {
    || {
        let _f = ice();
        yield;
    };
}

Running RUST_BACKTRACE=1 rustc ice.rs on the latest rustc 1.28.0-nightly (29f48ccf3 2018-06-03) gives the following output:

thread 'main' panicked at 'assertion failed: current_depth > ty::DebruijnIndex::INNERMOST', librustc/infer/higher_ranked/mod.rs:738:21
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::print
             at libstd/sys_common/backtrace.rs:71
             at libstd/sys_common/backtrace.rs:59
   2: std::panicking::default_hook::{{closure}}
             at libstd/panicking.rs:211
   3: std::panicking::default_hook
             at libstd/panicking.rs:227
   4: rustc::util::common::panic_hook
   5: std::panicking::rust_panic_with_hook
             at libstd/panicking.rs:515
   6: std::panicking::begin_panic
   7: rustc::infer::higher_ranked::<impl rustc::infer::InferCtxt<'a, 'gcx, 'tcx>>::plug_leaks::{{closure}}
   8: <rustc_data_structures::array_vec::ArrayVec<A> as core::iter::traits::Extend<<A as rustc_data_structures::array_vec::Array>::Element>>::extend
   9: rustc::ty::fold::TypeFoldable::fold_with
  10: rustc::ty::fold::TypeFoldable::fold_with
  11: rustc::ty::fold::TypeFoldable::fold_with
  12: rustc::infer::InferCtxt::commit_if_ok
  13: rustc::traits::select::SelectionContext::evaluate_predicate_recursively
  14: rustc::infer::InferCtxt::probe
  15: rustc::traits::select::SelectionContext::evaluate_stack
  16: rustc::dep_graph::graph::DepGraph::with_anon_task
  17: rustc::traits::select::SelectionContext::evaluate_predicate_recursively
  18: rustc::infer::InferCtxt::probe
  19: rustc::traits::select::SelectionContext::evaluate_stack
  20: rustc::dep_graph::graph::DepGraph::with_anon_task
  21: rustc::traits::select::SelectionContext::evaluate_predicate_recursively
  22: rustc::infer::InferCtxt::probe
  23: rustc::traits::select::SelectionContext::evaluate_stack
  24: rustc::dep_graph::graph::DepGraph::with_anon_task
  25: rustc::traits::select::SelectionContext::evaluate_predicate_recursively
  26: rustc::infer::InferCtxt::probe
  27: rustc::traits::select::SelectionContext::evaluate_stack
  28: rustc::dep_graph::graph::DepGraph::with_anon_task
  29: rustc::traits::select::SelectionContext::evaluate_predicate_recursively
  30: rustc::traits::select::SelectionContext::evaluate_obligation_recursively
  31: rustc::ty::context::tls::with_related_context
  32: rustc::infer::InferCtxtBuilder::enter
  33: rustc_traits::evaluate_obligation::evaluate_obligation
  34: rustc::ty::maps::__query_compute::evaluate_obligation
  35: rustc::ty::maps::<impl rustc::ty::maps::config::QueryConfig<'tcx> for rustc::ty::maps::queries::evaluate_obligation<'tcx>>::compute
  36: rustc::dep_graph::graph::DepGraph::with_task_impl
  37: rustc::ty::context::tls::with_related_context
  38: rustc::ty::maps::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::force_query_with_job
  39: rustc::ty::maps::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::get_query
  40: rustc::traits::query::evaluate_obligation::<impl rustc::infer::InferCtxt<'cx, 'gcx, 'tcx>>::evaluate_obligation
  41: rustc::traits::type_known_to_meet_bound
  42: rustc::ty::context::tls::with_related_context
  43: rustc::infer::InferCtxtBuilder::enter
  44: rustc::ty::util::is_freeze_raw
  45: rustc::ty::maps::__query_compute::is_freeze_raw
  46: rustc::ty::maps::<impl rustc::ty::maps::config::QueryConfig<'tcx> for rustc::ty::maps::queries::is_freeze_raw<'tcx>>::compute
  47: rustc::dep_graph::graph::DepGraph::with_task_impl
  48: rustc::ty::context::tls::with_related_context
  49: rustc::ty::maps::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::force_query_with_job
  50: rustc::ty::maps::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::get_query
  51: rustc::ty::util::<impl rustc::ty::TyS<'tcx>>::is_freeze
  52: rustc_mir::transform::qualify_consts::Qualifier::new
  53: <rustc_mir::transform::qualify_consts::QualifyAndPromoteConstants as rustc_mir::transform::MirPass>::run_pass
  54: rustc_mir::transform::mir_validated::{{closure}}
  55: rustc_mir::transform::mir_validated
  56: rustc::ty::maps::__query_compute::mir_validated
  57: rustc::ty::maps::<impl rustc::ty::maps::config::QueryConfig<'tcx> for rustc::ty::maps::queries::mir_validated<'tcx>>::compute
  58: rustc::dep_graph::graph::DepGraph::with_task_impl
  59: rustc::ty::context::tls::with_related_context
  60: rustc::ty::maps::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::force_query_with_job
  61: rustc::ty::maps::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::get_query
  62: rustc::ty::maps::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::ensure_query
  63: rustc_borrowck::borrowck::borrowck
  64: rustc::ty::maps::<impl rustc::ty::maps::config::QueryConfig<'tcx> for rustc::ty::maps::queries::borrowck<'tcx>>::compute
  65: rustc::dep_graph::graph::DepGraph::with_task_impl
  66: rustc::ty::context::tls::with_related_context
  67: rustc::ty::maps::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::force_query_with_job
  68: rustc::ty::maps::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::get_query
  69: <rustc_borrowck::borrowck::unused::UsedMutFinder<'a, 'tcx> as rustc::hir::intravisit::Visitor<'tcx>>::visit_nested_body
  70: rustc::hir::intravisit::walk_expr
  71: rustc_borrowck::borrowck::unused::check
  72: rustc_borrowck::borrowck::borrowck
  73: rustc::ty::maps::<impl rustc::ty::maps::config::QueryConfig<'tcx> for rustc::ty::maps::queries::borrowck<'tcx>>::compute
  74: rustc::dep_graph::graph::DepGraph::with_task_impl
  75: rustc::ty::context::tls::with_related_context
  76: rustc::ty::maps::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::force_query_with_job
  77: rustc::ty::maps::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::get_query
  78: rustc_borrowck::borrowck::check_crate
  79: rustc::util::common::time
  80: rustc::ty::context::tls::enter_context
  81: <std::thread::local::LocalKey<T>>::with
  82: rustc::ty::context::TyCtxt::create_and_enter
  83: rustc_driver::driver::compile_input
  84: rustc_driver::run_compiler_with_pool
  85: <scoped_tls::ScopedKey<T>>::set
  86: syntax::with_globals
  87: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
  88: __rust_maybe_catch_panic
             at libpanic_unwind/lib.rs:105
  89: rustc_driver::run
  90: rustc_driver::main
  91: std::rt::lang_start::{{closure}}
  92: std::panicking::try::do_call
             at libstd/rt.rs:59
             at libstd/panicking.rs:310
  93: __rust_maybe_catch_panic
             at libpanic_unwind/lib.rs:105
  94: std::rt::lang_start_internal
             at libstd/panicking.rs:289
             at libstd/panic.rs:374
             at libstd/rt.rs:58
  95: main
  96: __libc_start_main
  97: <unknown>
query stack during panic:
#0 [evaluate_obligation] evaluating trait selection obligation `[generator@ice.rs:24:5: 27:6 for<'r, 's> {impl std::marker::Send, ()}]: std::marker::Freeze`
#1 [is_freeze_raw] computing whether `[generator@ice.rs:24:5: 27:6 for<'r, 's> {impl std::marker::Send, ()}]` is freeze
#2 [mir_validated] processing `main::{{closure}}`
#3 [borrowck] processing `main::{{closure}}`
#4 [borrowck] processing `main`
end of query stack

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.28.0-nightly (29f48ccf3 2018-06-03) running on x86_64-unknown-linux-gnu

[1]    14102 exit 101   RUST_BACKTRACE=1 rustc ice.rs
@ngg

This comment has been minimized.

Copy link
Contributor Author

ngg commented Jun 5, 2018

This is probably the same bug as #48969 which I couldn't find before because I was only looking for DebruijnIndex. Anyway this repro case is simpler (doesn't depend on the futures crate).

@Zoxc Zoxc added the A-generators label Aug 6, 2018

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Sep 13, 2018

The example can be reduced to:

#![feature(generators)]

struct Foo<T: Fn()>(T, T::Output);

fn ice<'a>() -> impl Send + 'a {
    Foo(|| {}, ())
}

fn main() {
    || {
        let _f = ice();
        yield;
    };
}

The T::Output projection is crucial, it seems, and the type of || {} inside ice depends on 'a.

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Sep 14, 2018

In our case (for rust-lang/gll#47), we were down to one source of this ICE, and the fix was:

-    .map(|children| children.iter().map(|&i| P::from_usize(i))),
+    .map(|children| children.iter().cloned().map(|i| P::from_usize(i))),

That is, the problematic closure was changed from taking a &usize to take an usize, and the value was read from behind the reference by .cloned() (which is immune to the ICE).

@xrl

This comment has been minimized.

Copy link

xrl commented Oct 8, 2018

I am playing around with future streams with tokio-async-await shim and I'm seeing a similar error. Maybe this example is useful as well?

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());

    tokio::run_async(do_couchie_stuff(args));
}

async fn do_couchie_stuff(args: Args) {
    let database = Arc::new(Database::new(Client::new(), "depot-orders", &args.arg_COUCHDB_URI[..] /* "http://127.0.0.1:8001/api/v1/namespaces/staging/services/couchdb/proxy" */));
    let view = ViewClient::new(database.clone(), "QuotedWare", "by_all_created_at_date");

    let page_size = args.flag_limit;
    let total_pages = await!(view.total_pages(page_size));
    let pages = PageIterator::new(&view, total_pages, page_size);

    let page_stream : IterOk<PageIterator,()> = iter_ok::<PageIterator,()>(pages);
    let task_stream = page_stream.map(|page| {
        println!("got a page {:?}", page);
        async {
            await!(do_page_work(&database, page))
        };
        Ok(())
    })
    .buffer_unordered(1)
    .for_each(|_| {
        println!("for each!");
        Ok(())
    });
    await!(task_stream);
}

async fn do_page_work<'a>(database: &'a Arc<Database<'a>>, page: Page) -> Result<(),()> {
        println!("uri: {}", page.uri);

        let response = await!({
            database.client.get(page.uri.parse().unwrap())
                .timeout(Duration::from_secs(10))
            }).unwrap();

        let body = await!(response.into_body().concat2()).unwrap();
        println!("content len {:?}", body.len());

        let view_response = parse_all_together(&body[..])?;

        for row in view_response.rows {
            let quoted_ware : QuotedWare = row.doc;
            println!("qw {} {:?}", quoted_ware.created_at, quoted_ware.quote_group_id);
        }

        Ok(())
}

results in

cargo check --color=always
warning: the cargo feature `edition` is now stable and is no longer necessary to be listed in the manifest
    Checking dracula v0.1.0 (/Users/xlange/code/rust/dracula)
thread 'main' panicked at 'assertion failed: current_depth > ty::INNERMOST', librustc/infer/higher_ranked/mod.rs:757:21
query stack during panic:
#0 [evaluate_obligation] evaluating trait selection obligation `impl std::future::Future: std::marker::Send`
#1 [typeck_tables_of] processing `main`
#2 [typeck_item_bodies] type-checking all item bodies
end of query stack

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.31.0-nightly (fddcd316a 2018-10-05) running on x86_64-apple-darwin

note: compiler flags: -C debuginfo=2 -C incremental --crate-type bin

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

error: Could not compile `dracula`.

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

Process finished with exit code 101

if I comment out the inner async work code:

    let page_stream : IterOk<PageIterator,()> = iter_ok::<PageIterator,()>(pages);
    let task_stream = page_stream.map(|page| {
        println!("got a page {:?}", page);
//        async {
//            await!(do_page_work(&database, page))
//        };
        Ok(())
    })
    .buffer_unordered(1)
    .for_each(|_| {
        println!("for each!");
        Ok(())
    });
    await!(task_stream);

then I don't get the ICE. should I be cloning something to workaround this bug?

@DutchGhost

This comment has been minimized.

Copy link

DutchGhost commented Oct 17, 2018

Stumbled upon this also:

#![feature(await_macro, async_await, futures_api, pin,)]

#[macro_use]
extern crate tokio;

use hyper::Uri;

use hyper::Client;

use hyper::client::HttpConnector;
use hyper::rt::Stream as HStream;

use futures::sync::mpsc::*;
use futures::Future;

use tokio::prelude::{Sink, Stream};

use std::borrow::ToOwned;

async fn read_url<'a>(
    url: Uri,
    sender: UnboundedSender<Vec<u8>>,
    client: &'a Client<HttpConnector, hyper::Body>,
) {
    await!(
        client
            .get(url)
            .and_then(|content| content.into_body().for_each(|item| {
                sender.start_send(vec![]);
                Ok(())
            }))
    );
}

fn main() {
    let (sender, recv) = unbounded::<Vec<u8>>();

    let url_sender = sender.clone();
    let client = Client::new();

    tokio::run_async(read_url(
        "http://ikariam.org".parse().unwrap(),
        url_sender,
        &client,
    ));
}
@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Nov 4, 2018

@lqd

This comment has been minimized.

Copy link
Contributor

lqd commented Feb 22, 2019

The original code (playground) doesn't ICE anymore.

Neither does eddy's minimized repro (playground).

The last snippet involves tokio-async-await which doesn't build on nightly anymore since the recent LocalWaker, and will need to be retested once tokio-rs/tokio#919 or similar lands — but if it's indeed a repro of the other 2, it should probably avoid the ICE as well.

@cramertj

This comment has been minimized.

Copy link
Member

cramertj commented Feb 22, 2019

Nice! Closing-- if anyone repros, I can reopen. cc @withoutboats @nikomatsakis

@cramertj cramertj closed this Feb 22, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.