Skip to content

ICE: Existential type (w/ and w/o NLL) #53598

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
andreytkachenko opened this issue Aug 22, 2018 · 11 comments · Fixed by #63474
Closed

ICE: Existential type (w/ and w/o NLL) #53598

andreytkachenko opened this issue Aug 22, 2018 · 11 comments · Fixed by #63474
Labels
A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. C-bug Category: This is a bug. F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]` I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ P-medium Medium priority requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@andreytkachenko
Copy link

here is the example:

#![feature(nll, existential_type)]

pub trait Engine {}
pub trait RenderImplementation<E, CE> 
    where E: Engine,
          CE: Engine,
{
    fn render_impl<C: Renderable<CE>>(&self, eng: &E, children: &C);
}
pub trait Renderable<E> 
    where E: Engine,
{
    fn render(&self, eng: &E);
}
pub trait View<E, CE>
    where E: Engine,
          CE: Engine,
{
    type Renderable: Renderable<E>;

    fn build<C: Renderable<CE> + 'static>(self, children: Option<C>) -> Self::Renderable;
}

pub struct Node <E, I, CHE, CH>
    where 
        E: Engine,
        CHE: Engine,
        I: RenderImplementation<E, CHE>,
        CH: Renderable<CHE>
{
    _m: std::marker::PhantomData<(I, CH, E, CHE)>
}

impl<E, I, CHE, CH> Node<E, I, CHE, CH>
    where 
        E: Engine,
        CHE: Engine,
        I: RenderImplementation<E, CHE>,
        CH: Renderable<CHE>
{
    pub fn new(_item: I, _children: CH) -> Self {
        Self {
            _m: Default::default()
        }
    }
}

impl<E, I, CHE, CH> Renderable<E> for Node<E, I, CHE, CH>
    where 
        E: Engine,
        CHE: Engine,
        I: RenderImplementation<E, CHE>,
        CH: Renderable<CHE>
{
    fn render(&self, _eng: &E) {}
}

impl <E: Engine, T: Renderable<E>> Renderable<E> for Option<T> {
    fn render(&self, _eng: &E) {}
}

pub struct HtmlEngine;
impl Engine for HtmlEngine {}

pub struct Div;

impl RenderImplementation<HtmlEngine, HtmlEngine> for Div {   
    fn render_impl<C>(&self, _eng: &HtmlEngine, _children: &C)
        where C: Renderable<HtmlEngine> 
    {}
}

impl View<HtmlEngine, HtmlEngine> for Div {
    existential type Renderable: Renderable<HtmlEngine>;

    fn build<C: Renderable<HtmlEngine> + 'static>(self, children: Option<C>) -> Self::Renderable {
        Node::new(self, children)
    }
}

fn main() {}

this example will compile well if you remove nll

@matthiaskrgr
Copy link
Member

Backtrace:


   Compiling issue_53598 v0.1.0 (file:///tmp/issue_53598)
error: internal compiler error: librustc/ty/subst.rs:479: Type parameter `C/#0` (C/0) out of range when substituting (root type=Some(Node<HtmlEngine, Div, HtmlEngine, std::option::Option<C>>)) substs=[]
thread 'main' panicked at 'Box<Any>', librustc_errors/lib.rs:517:9
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:479
   6: std::panicking::begin_panic
   7: rustc_errors::Handler::span_bug
   8: rustc::util::bug::opt_span_bug_fmt::{{closure}}
   9: rustc::ty::context::tls::with_opt::{{closure}}
  10: rustc::ty::context::tls::with_context_opt
  11: rustc::ty::context::tls::with_opt
  12: rustc::util::bug::opt_span_bug_fmt
  13: rustc::util::bug::span_bug_fmt
  14: <rustc::ty::subst::SubstFolder<'a, 'gcx, 'tcx> as rustc::ty::fold::TypeFolder<'gcx, 'tcx>>::fold_ty
  15: rustc::ty::fold::TypeFoldable::fold_with
  16: rustc::ty::structural_impls::<impl rustc::ty::fold::TypeFoldable<'tcx> for &'tcx rustc::ty::TyS<'tcx>>::super_fold_with
  17: <rustc::ty::subst::SubstFolder<'a, 'gcx, 'tcx> as rustc::ty::fold::TypeFolder<'gcx, 'tcx>>::fold_ty
  18: rustc::ty::fold::TypeFoldable::fold_with
  19: rustc::ty::structural_impls::<impl rustc::ty::fold::TypeFoldable<'tcx> for &'tcx rustc::ty::TyS<'tcx>>::super_fold_with
  20: <rustc::ty::subst::SubstFolder<'a, 'gcx, 'tcx> as rustc::ty::fold::TypeFolder<'gcx, 'tcx>>::fold_ty
  21: rustc::infer::InferCtxt::commit_if_ok
  22: <rustc::traits::query::type_op::custom::CustomTypeOp<F, G> as rustc::traits::query::type_op::TypeOp<'gcx, 'tcx>>::fully_perform
  23: rustc_mir::borrow_check::nll::type_check::type_check
  24: rustc_mir::borrow_check::nll::compute_regions
  25: rustc_mir::borrow_check::do_mir_borrowck
  26: rustc::ty::context::GlobalCtxt::enter_local
  27: rustc_mir::borrow_check::mir_borrowck
  28: rustc::ty::query::__query_compute::mir_borrowck
  29: rustc::ty::query::<impl rustc::ty::query::config::QueryAccessors<'tcx> for rustc::ty::query::queries::mir_borrowck<'tcx>>::compute
  30: rustc::ty::context::tls::with_context
  31: rustc::dep_graph::graph::DepGraph::with_task_impl
  32: <rustc::ty::query::plumbing::JobOwner<'a, 'tcx, Q>>::start
  33: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::force_query_with_job
  34: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::get_query
  35: rustc::ty::query::<impl rustc::ty::context::TyCtxt<'a, 'tcx, 'lcx>>::mir_borrowck
  36: rustc::ty::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::par_body_owners
  37: rustc::util::common::time
  38: rustc::ty::context::tls::enter_context
  39: <std::thread::local::LocalKey<T>>::with
  40: rustc::ty::context::TyCtxt::create_and_enter
  41: rustc_driver::driver::compile_input
  42: rustc_driver::run_compiler_with_pool
  43: syntax::with_globals
  44: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
  45: __rust_maybe_catch_panic
             at libpanic_unwind/lib.rs:102
  46: rustc_driver::run
  47: rustc_driver::main
  48: std::rt::lang_start::{{closure}}
  49: std::panicking::try::do_call
             at libstd/rt.rs:59
             at libstd/panicking.rs:310
  50: __rust_maybe_catch_panic
             at libpanic_unwind/lib.rs:102
  51: std::rt::lang_start_internal
             at libstd/panicking.rs:289
             at libstd/panic.rs:392
             at libstd/rt.rs:58
  52: main
  53: __libc_start_main
  54: <unknown>
query stack during panic:
#0 [mir_borrowck] processing `<Div as View<HtmlEngine, HtmlEngine>>::build`
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.30.0-nightly (33b923fd4 2018-08-18) running on x86_64-unknown-linux-gnu
note: compiler flags: -C debuginfo=2 -C incremental -C target-cpu=native --crate-type bin
note: some of the compiler flags provided by cargo are hidden
error: Could not compile `issue_53598`.
To learn more, run the command again with --verbose.

@csmoe csmoe added A-NLL Area: Non-lexical lifetimes (NLL) A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. labels Aug 22, 2018
@andreytkachenko
Copy link
Author

Hmm I reproduced same ICE with next snippet without nll:

#![feature(existential_type)]

pub trait Engine {}
pub trait RenderImplementation<E, CE> 
    where E: Engine,
          CE: Engine,
{
    fn render_impl<C: Renderable<CE>>(&self, eng: &E, children: &C);
}
pub trait Renderable<E> 
    where E: Engine,
{
    fn render(&self, eng: &E);
}
pub trait View<E, CE>
    where E: Engine,
          CE: Engine,
{
    type Renderable: Renderable<E>;

    fn build<C: Renderable<CE> + 'static>(self, children: Option<C>) -> Self::Renderable;
}

pub struct Node <E, I, CHE, CH>
    where 
        E: Engine,
        CHE: Engine,
        I: RenderImplementation<E, CHE>,
        CH: Renderable<CHE>
{
    _m: std::marker::PhantomData<(I, CH, E, CHE)>
}

impl<E, I, CHE, CH> Node<E, I, CHE, CH>
    where 
        E: Engine,
        CHE: Engine,
        I: RenderImplementation<E, CHE>,
        CH: Renderable<CHE>
{
    pub fn new(_item: I, _children: CH) -> Self {
        Self {
            _m: Default::default()
        }
    }
}

impl<E, I, CHE, CH> Renderable<E> for Node<E, I, CHE, CH>
    where 
        E: Engine,
        CHE: Engine,
        I: RenderImplementation<E, CHE>,
        CH: Renderable<CHE>
{
    fn render(&self, _eng: &E) {}
}

impl <E: Engine, T: Renderable<E>> Renderable<E> for Option<T> {
    fn render(&self, _eng: &E) {}
}

pub struct HtmlEngine;
impl Engine for HtmlEngine {}

pub struct Div;

impl RenderImplementation<HtmlEngine, HtmlEngine> for Div {   
    fn render_impl<C>(&self, _eng: &HtmlEngine, _children: &C)
        where C: Renderable<HtmlEngine> 
    {}
}

impl View<HtmlEngine, HtmlEngine> for Div {
    existential type Renderable: Renderable<HtmlEngine>;

    fn build<C: Renderable<HtmlEngine> + 'static>(self, children: Option<C>) -> Self::Renderable {
        Node::new(self, children)
    }
}

#[derive(Default)]
pub struct Stub<E: Engine> {
    _e: std::marker::PhantomData<E>
}

impl<E: Engine> Renderable<E> for Stub<E>  {
    fn render(&self, _eng: &E) {}
}

fn main() {
    Div.build::<Stub<_>>(None);
}

@andreytkachenko andreytkachenko changed the title ICE: Existential type + NLL ICE: Existential type [+ NLL] Aug 22, 2018
@estebank estebank added the I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ label Aug 22, 2018
@nikomatsakis nikomatsakis added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed A-NLL Area: Non-lexical lifetimes (NLL) labels Aug 27, 2018
@pnkfelix pnkfelix changed the title ICE: Existential type [+ NLL] ICE: Existential type (w/ and w/o NLL) Aug 28, 2018
@Arnavion
Copy link

Arnavion commented Jan 29, 2019

Smaller repro:

#![feature(existential_type)]

pub trait Foo {
    type Item: std::fmt::Debug;

    fn foo<T: std::fmt::Debug>(_: T) -> Self::Item;
}

#[derive(Debug)]
pub struct S<T>(std::marker::PhantomData<T>);

pub struct S2;

impl Foo for S2 {
    existential type Item: std::fmt::Debug;

    fn foo<T: std::fmt::Debug>(_: T) -> Self::Item {
        S::<T>(Default::default())
    }
}

Edit: AFAICT the problem is the existential assoc type is being made dependent on the type parameter of the trait method (<S2 as Foo>::foo's T in this repro, <Div as View<HtmlEngine, HtmlEngine>>::build's C in the OP). So it would be a compile error if it weren't for the ICE.

@andreytkachenko
Copy link
Author

@Arnavion you example compiles without ICE.

@andreytkachenko
Copy link
Author

andreytkachenko commented Jan 29, 2019

@Arnavion, sorry it needs to be added nll feature or used 2018 edition.

Here is complete one which fails to compile regardless nll feature:

#![feature(existential_type)]

pub trait Foo {
    type Item: std::fmt::Debug;

    fn foo<T: std::fmt::Debug>(_: T) -> Self::Item;
}

#[derive(Debug)]
pub struct S<T>(std::marker::PhantomData<T>);

pub struct S2;

impl Foo for S2 {
    existential type Item: std::fmt::Debug;

    fn foo<T: std::fmt::Debug>(_: T) -> Self::Item {
        S::<T>(Default::default())
    }
}

fn main() {
    S2::foo(123);
}

@oli-obk oli-obk self-assigned this Jan 29, 2019
@Arnavion
Copy link

@andreytkachenko Right, 2015 doesn't hit the error until you actually try to use the type.

Regardless, as I said in my previous comment, this code should be a compile error anyway regardless of edition, since it's trying to declare an associated type that depends on the type parameters of the trait method rather than the trait.

@pnkfelix
Copy link
Member

pnkfelix commented Mar 6, 2019

hey @oli-obk, have you had a chance to look into this yet? Do you think you will be looking at it in the near term, or should we unassign you?

@oli-obk oli-obk removed their assignment Mar 6, 2019
@oli-obk
Copy link
Contributor

oli-obk commented Mar 6, 2019

Removed my assignment. Unfortunately I'm running behind on the not-time-critical issues I assigned to myself.

@pnkfelix pnkfelix added the P-high High priority label Mar 7, 2019
@pnkfelix
Copy link
Member

Discussed in T-compiler meeting. This is a blocker for the existential type feature. But there is no schedule yet set for stabilizing that feature. Thus, downgrading fixing this to P-medium.

@pnkfelix pnkfelix added P-medium Medium priority and removed P-high High priority labels Mar 14, 2019
@Centril Centril added F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]` requires-nightly This issue requires a nightly compiler in some way. labels Jul 28, 2019
@Aaron1011
Copy link
Member

This no longer produces an ICE on the latest nightly.

@Arnavion
Copy link

Yes, it was fixed by #62090

@jonas-schievink jonas-schievink added the C-bug Category: This is a bug. label Aug 6, 2019
Centril added a commit to Centril/rust that referenced this issue Aug 12, 2019
bors added a commit that referenced this issue Aug 12, 2019
Rollup of 10 pull requests

Successful merges:

 - #62108 (Use sharded maps for queries)
 - #63297 (Improve pointer offset method docs)
 - #63306 (Adapt AddRetag for shallow retagging)
 - #63406 (Suggest using a qualified path in patterns with inconsistent bindings)
 - #63431 (Revert "Simplify MIR generation for logical ops")
 - #63449 (resolve: Remove remaining special cases from built-in macros)
 - #63461 (docs: add stdlib env::var(_os) panic)
 - #63473 (Regression test for #56870)
 - #63474 (Add tests for issue #53598 and #57700)
 - #63480 (Fixes #63477)

Failed merges:

r? @ghost
Centril added a commit to Centril/rust that referenced this issue Aug 12, 2019
bors added a commit that referenced this issue Aug 12, 2019
Rollup of 9 pull requests

Successful merges:

 - #62108 (Use sharded maps for queries)
 - #63297 (Improve pointer offset method docs)
 - #63406 (Suggest using a qualified path in patterns with inconsistent bindings)
 - #63431 (Revert "Simplify MIR generation for logical ops")
 - #63449 (resolve: Remove remaining special cases from built-in macros)
 - #63461 (docs: add stdlib env::var(_os) panic)
 - #63473 (Regression test for #56870)
 - #63474 (Add tests for issue #53598 and #57700)
 - #63480 (Fixes #63477)

Failed merges:

r? @ghost
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. C-bug Category: This is a bug. F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]` I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ P-medium Medium priority requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Development

Successfully merging a pull request may close this issue.