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: Type parameter W/#1 out of range when substituting #55872

Closed
DutchGhost opened this issue Nov 11, 2018 · 8 comments · Fixed by #62090
Closed

ICE: Type parameter W/#1 out of range when substituting #55872

DutchGhost opened this issue Nov 11, 2018 · 8 comments · Fixed by #62090
Assignees
Labels
A-impl-trait Area: impl Trait. Universally / existentially quantified anonymous types with static dispatch. 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

@DutchGhost
Copy link
Contributor

DutchGhost commented Nov 11, 2018

Playing with async/await, using

  • Futures: futures-preview = "0.3.0-alpha.9"
  • Tokio: tokio = { version = "0.1.0", features = ["async-await-preview"] }

and some nightly features, I stumbled upon this ICE.
(possibly related to #55265)

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

macro_rules! async_for {
    ($item:ident in $stream:ident $todo:block) => (
        while let Some($item) = await!($stream.next()) $todo
    )
}

use futures::{Stream, Future};
use std::marker::Unpin;

use futures::StreamExt as StreamExt;

use tokio::prelude::{AsyncWriteExt};

pub trait Sip
where
    Self: Stream
{
    type Future: Future;

    fn start_sip<W, F>(self, writer: W, convert: F) -> Self::Future
    where
        W: AsyncWriteExt + Unpin,
        F: Fn(&Self::Item) -> &[u8] + Unpin
    ;
}

impl <S> Sip for S
where
    S: Stream + Unpin,
{
    existential type Future: Future<Output = ()>;

    fn start_sip<W, F>(mut self, mut writer: W, mut convert: F) -> Self::Future
    where
        W: AsyncWriteExt + Unpin,
        F: Fn(&Self::Item) -> &[u8] + Unpin
    {
        async move {
            async_for!(item in self {
                let bytes = convert(&item);
                await!(writer.write_async(bytes));
            });

            await!(tokio::io::shutdown(writer).into_awaitable());
        }
    }
}
Backtrace:
error: internal compiler error: librustc\ty\subst.rs:462: Type parameter `W/#1` (W/1) out of range when substituting (root type=Some(impl futures::Future)) substs=[S]

thread 'main' panicked at 'Box<Any>', librustc_errors\lib.rs:538:9
stack backtrace:
   0: <std::future::SetOnDrop as core::ops::drop::Drop>::drop
   1: std::panicking::take_hook
   2: std::panicking::take_hook
   3: <rustc::ty::sty::Binder<rustc::ty::ProjectionPredicate<'tcx>> as rustc::ty::ToPredicate<'tcx>>::to_predicate
   4: std::panicking::rust_panic_with_hook
   5: <usize as rustc::session::config::dep_tracking::DepTrackingHash>::hash
   6: <rustc::traits::query::type_op::outlives::DropckOutlives<'a> as rustc::ty::context::Lift<'tcx>>::lift_to_tcx
   7: rustc::ty::context::tls::track_diagnostic
   8: rustc::ty::context::tls::track_diagnostic
   9: rustc::ty::context::tls::track_diagnostic
  10: rustc::ty::context::tls::track_diagnostic
  11: rustc::util::bug::bug_fmt
  12: rustc::util::bug::bug_fmt
  13: <rustc::ty::subst::SubstFolder<'a, 'gcx, 'tcx> as rustc::ty::fold::TypeFolder<'gcx, 'tcx>>::fold_ty
  14: rustc::ty::context::TyCtxt::generate_borrow_of_any_match_input
  15: rustc::ty::error::<impl rustc::ty::TyS<'tcx>>::sort_string
  16: <rustc::ty::subst::SubstFolder<'a, 'gcx, 'tcx> as rustc::ty::fold::TypeFolder<'gcx, 'tcx>>::fold_ty
  17: rustc::ty::context::TyCtxt::generate_borrow_of_any_match_input
  18: rustc::ty::error::<impl rustc::ty::TyS<'tcx>>::sort_string
  19: <rustc::ty::subst::SubstFolder<'a, 'gcx, 'tcx> as rustc::ty::fold::TypeFolder<'gcx, 'tcx>>::fold_ty
  20: <rustc_mir::hair::pattern::check_match::MutationChecker<'a, 'tcx> as rustc::middle::expr_use_visitor::Delegate<'tcx>>::decl_without_init
  21: rustc_mir::borrow_check::nll::facts::<impl core::convert::From<usize> for rustc_mir::dataflow::move_paths::indexes::BorrowIndex>::from
  22: <rustc_mir::borrow_check::nll::type_check::TypeVerifier<'a, 'b, 'gcx, 'tcx> as rustc::mir::visit::Visitor<'tcx>>::visit_mir
  23: <rustc_mir::borrow_check::nll::type_check::liveness::local_use_map::LocalUseMapBuild<'_, '_> as rustc::mir::visit::Visitor<'tcx>>::visit_local
  24: <rustc_mir::borrow_check::nll::renumber::NLLVisitor<'a, 'gcx, 'tcx> as rustc::mir::visit::MutVisitor<'tcx>>::visit_statement
  25: <rustc_mir::util::borrowck_errors::Origin as core::fmt::Debug>::fmt
  26: <rustc_mir::hair::pattern::check_match::MutationChecker<'a, 'tcx> as rustc::middle::expr_use_visitor::Delegate<'tcx>>::decl_without_init
  27: <rustc_mir::borrow_check::nll::renumber::NLLVisitor<'a, 'gcx, 'tcx> as rustc::mir::visit::MutVisitor<'tcx>>::visit_statement
  28: rustc::ty::query::on_disk_cache::__ty_decoder_impl::<impl serialize::serialize::Decoder for rustc::ty::query::on_disk_cache::CacheDecoder<'a, 'tcx, 'x>>::read_str
  29: rustc::ty::context::tls::track_diagnostic
  30: rustc::ty::context::tls::track_diagnostic
  31: rustc::dep_graph::graph::DepGraph::assert_ignored
  32: rustc::ty::context::tls::track_diagnostic
  33: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::try_print_query_stack
  34: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::try_print_query_stack
  35: rustc::ty::query::<impl rustc::ty::context::TyCtxt<'a, 'tcx, 'lcx>>::mir_borrowck
  36: rustc_driver::set_sigpipe_handler
  37: rustc_driver::set_sigpipe_handler
  38: <rustc_driver::pretty::IdentifiedAnnotation<'hir> as rustc_driver::pretty::HirPrinterSupport<'hir>>::sess
  39: rustc_driver::set_sigpipe_handler
  40: rustc_driver::driver::compile_input
  41: rustc_driver::run_compiler
  42: <rustc_driver::profile::trace::Query as core::fmt::Debug>::fmt
  43: rustc_driver::run_compiler
  44: <humantime::date::Error as std::error::Error>::cause
  45: _rust_maybe_catch_panic
  46: <env_logger::filter::inner::Filter as core::fmt::Display>::fmt
  47: rustc_driver::main
  48: <unknown>
  49: std::panicking::update_panic_count
  50: _rust_maybe_catch_panic
  51: std::rt::lang_start_internal
  52: <unknown>
  53: <unknown>
  54: BaseThreadInitThunk
  55: RtlUserThreadStart
query stack during panic:
#0 [mir_borrowck] processing `<S as sip::Sip>::start_sip`
end of query stack
error: aborting due to previous error


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 (de9666f12 2018-10-31) running on x86_64-pc-windows-msvc

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 `webscraper_better`.

No ICE happens when writing the trait and implementation like this (notice the Generic parameters are now on the trait definition rather than on the function):

use futures::{Stream, Future};
use std::marker::Unpin;

use futures::StreamExt as StreamExt;

use tokio::prelude::{AsyncWriteExt};

pub trait Sip<W, F>
where
    Self: Stream
{
    type Future: Future;

    fn start_sip(self, writer: W, convert: F) -> Self::Future
    where
        W: AsyncWriteExt + Unpin,
        F: FnMut(&Self::Item) -> &[u8] + Unpin
    ;
}

impl <W, F, S> Sip<W, F> for S
where
    S: Stream + Unpin,
{
    existential type Future: Future<Output = ()>;

    fn start_sip(mut self, mut writer: W, mut convert: F) -> Self::Future
    where
        W: AsyncWriteExt + Unpin,
        F: FnMut(&Self::Item) -> &[u8] + Unpin
    {
        async move {
            async_for!(item in self {
                let bytes = convert(&item);
                await!(writer.write_async(bytes));
            });

            await!(tokio::io::shutdown(writer).into_awaitable());
        }
    }
}
@zackmdavis zackmdavis added the I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ label Nov 11, 2018
@jonas-schievink jonas-schievink added A-async-await Area: Async & Await C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 18, 2019
@gilescope
Copy link
Contributor

Confirmed this is still reproducible as of latest nightly (rustc 1.36.0-nightly (00859e3 2019-04-29))

@gilescope
Copy link
Contributor

This is about as small as I can get it to repro:

#![feature(async_await, existential_type)]
pub trait Bar
{
    type E: Copy;

    fn foo<T>() -> Self::E;
}

impl <S> Bar for S
{
    existential type E: Copy;

    fn foo<T>() -> Self::E
    {
        async {}
    }
}

fn main() {}

@nikomatsakis nikomatsakis added the AsyncAwait-Polish Async-await issues that are part of the "polish" area label Jun 4, 2019
@nikomatsakis
Copy link
Contributor

Marking as blocking -- thanks for the minimal reproduction @gilescope, that's fantastic!

@davidtwco
Copy link
Member

@rustbot claim

Going to investigate this with @nikomatsakis, see this message.

@nikomatsakis
Copy link
Contributor

Zulip topic

@nikomatsakis
Copy link
Contributor

Not really related to async-await. This minimization does not involve async/await but gets a very similar ICE:

#![feature(existential_type)]
pub trait Bar
{
    type E: Copy;

    fn foo<T>() -> Self::E;
}

impl <S> Bar for S
{
    existential type E: Copy;

    fn foo<T>() -> Self::E
    {
        || ()
    }
}

fn main() {}

@nikomatsakis nikomatsakis added A-impl-trait Area: impl Trait. Universally / existentially quantified anonymous types with static dispatch. and removed A-async-await Area: Async & Await AsyncAwait-Polish Async-await issues that are part of the "polish" area labels Jun 13, 2019
@nikomatsakis
Copy link
Contributor

nikomatsakis commented Jun 13, 2019

Preferred minimization (no annoying closures):

#![feature(existential_type)]
pub trait Bar
{
    type E: Copy;

    fn foo<T>() -> Self::E;
}

impl <S: Default> Bar for S
{
    existential type E: Copy;

    fn foo<T: Default>() -> Self::E
    {
        (S::default(), T::default())
    }
}

fn main() {}

The problem here is that the inferred type for E needs to be (S, T), but T is not in scope there. So we expect an error. (Not an ICE)

@nikomatsakis
Copy link
Contributor

The Zulip thread diagnoses the problem and explains everything in a lot of detail.

Centril added a commit to Centril/rust that referenced this issue Jul 8, 2019
Centril added a commit to Centril/rust that referenced this issue Jul 8, 2019
Centril added a commit to Centril/rust that referenced this issue Jul 9, 2019
Centril added a commit to Centril/rust that referenced this issue Jul 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-impl-trait Area: impl Trait. Universally / existentially quantified anonymous types with static dispatch. 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

Successfully merging a pull request may close this issue.

6 participants