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: Existential type (w/ and w/o NLL) #53598

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