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

FullfillmentError ICE with const fn and existential type #53092

Closed
DutchGhost opened this issue Aug 5, 2018 · 9 comments · Fixed by #96899
Closed

FullfillmentError ICE with const fn and existential type #53092

DutchGhost opened this issue Aug 5, 2018 · 9 comments · Fixed by #96899
Assignees
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)]` glacier ICE tracked in rust-lang/glacier. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ I-needs-decision Issue: In need of a decision. 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

@DutchGhost
Copy link
Contributor

DutchGhost commented Aug 5, 2018

Again something that is highly unlikely to ever be found in real code, but nonetheless ICE's:

MCVE: #53092 (comment)

#![feature(const_fn)]
#![feature(existential_type)]
#![feature(untagged_unions)]

const fn transmute<T, U>(t: T) -> U {
    union Transform<TT, UU> {
        t: TT,
        u: UU,
    }
    
    unsafe { Transform { t }.u }
}


existential type Foo<F, U>: Fn(F) -> U + Copy;

const BAZR: Foo<u8, ()> = transmute(|x: ()| { x });

fn bar<T, U: From<T>>() -> Foo<T, U> { |x| x.into() }

fn main() {
    let x = BAZR(0);
}

Playground: https://play.rust-lang.org/?gist=47ee8d54d29329821783e315423aa352&version=nightly&mode=release&edition=2015

Backtrace:
error: internal compiler error: librustc/traits/codegen/mod.rs:169: Encountered errors `[FulfillmentError(Obligation(predicate=Binder(TraitPredicate(<() as std::convert::From<u8>>)),depth=1),Unimplemented)]` resolving bounds after type-checking

thread 'main' panicked at 'Box<Any>', librustc_errors/lib.rs:516: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::session::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::session::opt_span_bug_fmt
  13: rustc::session::span_bug_fmt
  14: rustc::traits::codegen::<impl rustc::infer::InferCtxt<'a, 'gcx, 'tcx>>::drain_fulfillment_cx_or_panic
  15: rustc::ty::context::tls::with_related_context
  16: rustc::traits::codegen::codegen_fulfill_obligation
  17: rustc::ty::query::__query_compute::codegen_fulfill_obligation
  18: rustc::ty::query::<impl rustc::ty::query::config::QueryAccessors<'tcx> for rustc::ty::query::queries::codegen_fulfill_obligation<'tcx>>::compute
  19: rustc::dep_graph::graph::DepGraph::with_task_impl
  20: rustc::ty::context::tls::with_related_context
  21: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::force_query_with_job
  22: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::get_query
  23: rustc::ty::instance::Instance::resolve
  24: rustc_mir::monomorphize::collector::visit_fn_use
  25: <rustc_mir::monomorphize::collector::MirNeighborCollector<'a, 'tcx> as rustc::mir::visit::Visitor<'tcx>>::visit_terminator_kind
  26: rustc_mir::monomorphize::collector::collect_items_rec
  27: rustc_mir::monomorphize::collector::collect_items_rec
  28: rustc_mir::monomorphize::collector::collect_crate_mono_items::{{closure}}
  29: rustc::util::common::time
  30: rustc_mir::monomorphize::collector::collect_crate_mono_items
  31: rustc::util::common::time
  32: rustc_codegen_llvm::base::collect_and_partition_mono_items
  33: rustc::ty::query::<impl rustc::ty::query::config::QueryAccessors<'tcx> for rustc::ty::query::queries::collect_and_partition_mono_items<'tcx>>::compute
  34: rustc::dep_graph::graph::DepGraph::with_task_impl
  35: rustc::ty::context::tls::with_related_context
  36: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::force_query_with_job
  37: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::get_query
  38: <rustc_codegen_llvm::LlvmCodegenBackend as rustc_codegen_utils::codegen_backend::CodegenBackend>::codegen_crate
  39: rustc::util::common::time
  40: rustc_driver::driver::phase_4_codegen
  41: rustc_driver::driver::compile_input::{{closure}}
  42: rustc::ty::context::tls::enter_context
  43: <std::thread::local::LocalKey<T>>::with
  44: rustc::ty::context::TyCtxt::create_and_enter
  45: rustc_driver::driver::compile_input
  46: rustc_driver::run_compiler_with_pool
  47: <scoped_tls::ScopedKey<T>>::set
  48: syntax::with_globals
  49: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
  50: __rust_maybe_catch_panic
             at libpanic_unwind/lib.rs:105
  51: rustc_driver::run
  52: rustc_driver::main
  53: std::rt::lang_start::{{closure}}
  54: std::panicking::try::do_call
             at libstd/rt.rs:59
             at libstd/panicking.rs:310
  55: __rust_maybe_catch_panic
             at libpanic_unwind/lib.rs:105
  56: std::rt::lang_start_internal
             at libstd/panicking.rs:289
             at libstd/panic.rs:392
             at libstd/rt.rs:58
  57: main
  58: __libc_start_main
  59: <unknown>
query stack during panic:
#0 [codegen_fulfill_obligation] checking if `std::convert::Into` fulfills its obligations
#1 [collect_and_partition_mono_items] collect_and_partition_mono_items
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 (3edb355b7 2018-08-03) running on x86_64-unknown-linux-gnu

note: compiler flags: -C opt-level=3 -C codegen-units=1 --crate-type bin

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

error: Could not compile `playground`.

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

Changing

fn bar<T, U: From<T>>() -> Foo<T, U> { |x| x.into() }

to

fn bar<T, U: From<T>>() -> Foo<T, U> { |x| U::from(x) }

also ICE's but with a different message:

error: internal compiler error: librustc/traits/codegen/mod.rs:68: Encountered error `Unimplemented` selecting `Binder(<() as std::convert::From<u8>>)` during codegen`

Removing the Copy from the existential type, gives the same ICE as #53087

@DutchGhost DutchGhost changed the title FullfillmentError with const fn and existential type FullfillmentError ICE with const fn and existential type Aug 5, 2018
@oli-obk oli-obk added I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. labels Aug 6, 2018
@oli-obk oli-obk self-assigned this Jan 25, 2019
@Centril Centril added F-const_fn F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]` F-untagged_unions `#![feature(untagged_unions)]` requires-nightly This issue requires a nightly compiler in some way. labels Jul 28, 2019
@jonas-schievink jonas-schievink added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. labels Aug 6, 2019
@Alexendoo

This comment has been minimized.

@JohnTitor

This comment has been minimized.

@JohnTitor JohnTitor added the E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. label Oct 24, 2019
@DutchGhost

This comment has been minimized.

@JohnTitor JohnTitor removed the E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. label Oct 28, 2019
@JohnTitor

This comment has been minimized.

@jackh726
Copy link
Member

jackh726 commented Feb 3, 2021

Much more minimized repro:

#![feature(impl_trait_in_bindings)]
#![feature(min_type_alias_impl_trait)]
#![feature(type_alias_impl_trait)]
#![allow(dead_code)]

type Bug<T, U> = impl Fn(T) -> U + Copy;

const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };

fn make_bug<T, U: From<T>>() -> Bug<T, U> {
    |x| x.into()
}

fn main() {
    CONST_BUG(0);
}

playground

This is only a type_alias_impl_trait bug, so we can probably remove the other labels.

@nikomatsakis
Copy link
Contributor

If we limit this to min_type_alias_impl_trait, the ICE goes away, so I am not tagging this with F-min_type_alias_impl_trait

@Alexendoo Alexendoo added F-min_type_alias_impl_trait and removed F-impl_trait_in_bindings `#![feature(impl_trait_in_bindings)]` F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]` labels Jul 22, 2021
@Alexendoo
Copy link
Member

This ICEs with just min_type_alias_impl_trait:

#![feature(min_type_alias_impl_trait)]
#![allow(dead_code)]

type Bug<T, U> = impl Fn(T) -> U + Copy;

const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };

fn make_bug<T, U: From<T>>() -> Bug<T, U> {
    |x| x.into()
}

fn main() {
    CONST_BUG(0);
}

@oli-obk
Copy link
Contributor

oli-obk commented May 3, 2022

This CONST_BUG(0) call, because Bug a ZST, does not ask the CONST_BUG constant for the closure type it transmuted (the constant doesn't know about it anymore), but gets the ZST hidden type of type Bug, which is the closure from make_bug.

That closure has a constraint that CONST_BUG does not satisfy.

This constraint is only noticed in RevealAll mode in codegen, which then ICEs because it expected typeck to already figure all of this out properly.

There are two ways to proceed here:

1. report an error instead of ICEing in codegen_fulfill_obligation.

This is similar to other codegen time errors, where cargo check will not report them. Unfortunate, but not the end of the the world for people doing weird transmutes.

2. forbid make_bug from being a defining use

make_bug has stricter bounds than the opaque type. The user-side fix when they hit this case would be to add the bounds to the definition of Bug, too. This is doable, but it's certainly nice not to have to specify that right now. If your definition is general enough, then there's no reason it couldn't just be fine. As an example:

type Foo<T> = impl Default;
fn foo<T: Debug>(t: T) -> Foo<T> {
    Some(t)
}
struct NotDefault;
fn main() {
    let x = Foo::<NotDefault>::default();
}

This is perfectly legal, as you'll just get a None, because Option implements Default regardless of T. On the other hand, the following will not fly compile:

type Foo<T> = impl Default;
fn foo<T: Debug>(t: T) -> Foo<T> {
    t // T does not implement `Default`
}

@oli-obk oli-obk added the I-needs-decision Issue: In need of a decision. label May 3, 2022
@oli-obk
Copy link
Contributor

oli-obk commented May 10, 2022

Since we already check function items correctly, we should probably just do the same for closures

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)]` glacier ICE tracked in rust-lang/glacier. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ I-needs-decision Issue: In need of a decision. 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.

9 participants