Skip to content

ICE compiler panics on type inference when using proc macro (stable) #55765

Closed
@RustyYato

Description

@RustyYato

I was working on yet another implementation of the builder pattern, and pushing the type system to hold info about whether a type has been initialized. I used a proc macro to handle the boiler plate code. When I was testing it I ran into this ICE.

The code I wrote should fail to compile, but it shouldn't cause an ICE.

I tried creating a minimal example, but when I inline the macro call, the ICE disappears.

#[macro_use]
extern crate partial_init_derive;
extern crate partial_init_core;

#[derive(PartialInit)]
struct Foo<T> {
    thing: (T,),
}

fn main() {
    let foo = <Foo<_> as partial_init_core::PartialInit>::uninit().build();
}

note removing type inference by changing main to the code below, also gets rid of hte ICE.

fn main() {
    let foo = <Foo<()> as partial_init_core::PartialInit>::uninit().build();
}

The PartialInit derive macro creates this code (comments have been stripped for brevity):

#[allow(non_camel_case_types)]
mod __Foo__ {
    pub enum thing {}
    impl ::partial_init_core::FieldName for thing {}
    pub mod uninit {
        use super::super::*;
        pub type thing<T> = ::partial_init_core::Uninit<super::thing, T>;
    }
}

#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
struct PartialFoo<T, thing: ::partial_init_core::MaybeInit<__Foo__::thing, T>> {
    thing: thing,
    __phantom_data__partial_init_: ::partial_init_core::PhantomData<(T)>,
}

#[allow(non_camel_case_types)]
impl<T> ::partial_init_core::PartialInit for Foo<T> {
    type Uninitialized = PartialFoo<T, ::partial_init_core::Uninit<__Foo__::thing, T>>;

    #[inline(always)]
    fn uninit() -> Self::Uninitialized {
        Default::default()
    }
}

impl<T> Default for PartialFoo<T, ::partial_init_core::Uninit<__Foo__::thing, T>> {
    #[inline(always)]
    fn default() -> Self {
        PartialFoo {
            __phantom_data__partial_init_: Default::default(),
            thing: Default::default(),
        }
    }
}
#[allow(non_camel_case_types)]
impl<T, thing: ::partial_init_core::Init<__Foo__::thing, T>> PartialFoo<T, thing> {
    #[inline(always)]
    fn build(self) -> Foo<T> {
        Foo {
            thing: ::partial_init_core::Init::get(self.thing),
        }
    }
}

#[allow(non_camel_case_types)]
impl<T> PartialFoo<T, ::partial_init_core::Uninit<__Foo__::thing, T>> {
    #[inline(always)]
    fn thing<thing: ::partial_init_core::Init<__Foo__::thing, T>>(
        self,
        thing: thing,
    ) -> PartialFoo<T, thing> {
        PartialFoo {
            __phantom_data__partial_init_: Default::default(),
            thing,
        }
    }
}

And the relevant code can be seen here.

the run crate contains the test code
the partial-init-core contains necessary traits and structs for partial-init-derive
the partial-init-derive crate contains the proc-macro

stack trace

error: internal compiler error: librustc\traits\select.rs:3189: Impl DefId(10/0:33 ~ partial_init_core[903a]::init_impl[0]::{{impl}}[4]) was matchable against Obligation(predicate=Binder(TraitPredicate(<partial_init_core::Uninit<__Foo__::thing, (_,)> as partial_init_core::Init<__Foo__::thing, (_,)>>)),depth=0) but now is not

thread 'main' panicked at 'Box<Any>', librustc_errors\lib.rs:587:9
stack backtrace:
   0: <std::sys::windows::args::Args as core::ops::drop::Drop>::drop
   1: <std::path::PathBuf as core::convert::From<std::ffi::os_str::OsString>>::from
   2: std::panicking::take_hook
   3: std::panicking::take_hook
   4: <rustc::ty::sty::Binder<rustc::ty::ProjectionPredicate<'tcx>> as rustc::ty::ToPredicate<'tcx>>::to_predicate
   5: std::panicking::rust_panic_with_hook
   6: <rustc_errors::diagnostic::SubDiagnostic as core::fmt::Debug>::fmt
   7: rustc_errors::Handler::bug
   8: rustc::ty::context::tls::track_diagnostic
   9: rustc::ty::context::tls::track_diagnostic
  10: rustc::ty::context::tls::track_diagnostic
  11: rustc::ty::context::tls::track_diagnostic
  12: rustc::util::bug::bug_fmt
  13: rustc::util::bug::bug_fmt
  14: rustc::infer::InferCtxt::commit_from
  15: rustc::traits::select::SelectionContext::coinductive_predicate
  16: rustc::traits::select::SelectionContext::select
  17: rustc::ty::context::TypeckTables::expr_ty
  18: <rustc::traits::fulfill::FulfillmentContext<'tcx> as rustc::traits::engine::TraitEngine<'tcx>>::select_where_possible
  19: <rustc_typeck::check::FnCtxt<'a, 'gcx, 'tcx> as rustc_typeck::astconv::AstConv<'gcx, 'tcx>>::record_ty
  20: <rustc_typeck::check::FnCtxt<'a, 'gcx, 'tcx> as rustc_typeck::astconv::AstConv<'gcx, 'tcx>>::record_ty
  21: <rustc_typeck::check::FnCtxt<'a, 'gcx, 'tcx> as rustc_typeck::astconv::AstConv<'gcx, 'tcx>>::record_ty
  22: <rustc_typeck::check::FnCtxt<'a, 'gcx, 'tcx> as rustc_typeck::astconv::AstConv<'gcx, 'tcx>>::record_ty
  23: <rustc_typeck::check::FnCtxt<'a, 'gcx, 'tcx> as rustc_typeck::astconv::AstConv<'gcx, 'tcx>>::record_ty
  24: <rustc_typeck::check::FnCtxt<'a, 'gcx, 'tcx> as rustc_typeck::astconv::AstConv<'gcx, 'tcx>>::record_ty
  25: <rustc_typeck::check::FnCtxt<'a, 'gcx, 'tcx> as rustc_typeck::astconv::AstConv<'gcx, 'tcx>>::record_ty
  26: <rustc_typeck::check::FnCtxt<'a, 'gcx, 'tcx> as rustc_typeck::astconv::AstConv<'gcx, 'tcx>>::record_ty
  27: <rustc_typeck::check::FnCtxt<'a, 'gcx, 'tcx> as rustc_typeck::astconv::AstConv<'gcx, 'tcx>>::record_ty
  28: <rustc_typeck::check::FnCtxt<'a, 'gcx, 'tcx> as rustc_typeck::astconv::AstConv<'gcx, 'tcx>>::record_ty
  29: <rustc_typeck::check::GatherLocalsVisitor<'a, 'gcx, 'tcx> as rustc::hir::intravisit::Visitor<'gcx>>::visit_pat
  30: <rustc_typeck::check::method::suggest::TraitInfo as core::cmp::PartialOrd>::partial_cmp
  31: <rustc_typeck::astconv::Bounds<'tcx> as core::fmt::Debug>::fmt
  32: <rustc_typeck::check::CheckItemTypesVisitor<'a, 'tcx> as rustc::hir::itemlikevisit::ItemLikeVisitor<'tcx>>::visit_item
  33: <rustc::traits::query::dropck_outlives::DropckOutlivesResult<'a> as rustc::ty::context::Lift<'tcx>>::lift_to_tcx
  34: 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
  35: rustc::ty::context::tls::track_diagnostic
  36: rustc::dep_graph::graph::DepGraph::assert_ignored
  37: rustc::ty::context::tls::track_diagnostic
  38: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::try_print_query_stack
  39: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::try_print_query_stack
  40: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::try_print_query_stack
  41: <rustc_typeck::check::CheckItemTypesVisitor<'a, 'tcx> as rustc::hir::itemlikevisit::ItemLikeVisitor<'tcx>>::visit_item
  42: 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
  43: rustc::ty::context::tls::track_diagnostic
  44: rustc::dep_graph::graph::DepGraph::assert_ignored
  45: rustc::ty::context::tls::track_diagnostic
  46: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::try_print_query_stack
  47: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::try_print_query_stack
  48: rustc_typeck::check_crate
  49: <unknown>
  50: <rustc_driver::pretty::NoAnn<'hir> as rustc_driver::pretty::HirPrinterSupport<'hir>>::sess
  51: <rustc_driver::CompilationFailure as core::fmt::Debug>::fmt
  52: rustc_driver::driver::compile_input
  53: rustc_driver::run_compiler
  54: rustc_driver::target_features::add_configuration
  55: rustc_driver::run_compiler
  56: rustc_driver::target_features::add_configuration
  57: _rust_maybe_catch_panic
  58: rustc_driver::profile::dump
  59: rustc_driver::main
  60: <unknown>
  61: std::panicking::update_panic_count
  62: _rust_maybe_catch_panic
  63: std::rt::lang_start_internal
  64: <unknown>
  65: <unknown>
  66: BaseThreadInitThunk
  67: RtlUserThreadStart
query stack during panic:
#0 [typeck_tables_of] processing `main`
#1 [typeck_item_bodies] type-checking all item bodies
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 (da5f414c2 2018-10-24) 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 `run`.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-inferenceArea: Type inferenceA-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-trait-systemArea: Trait systemC-bugCategory: This is a bug.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions