Skip to content

Const generic ICE: constant in type had an ignored error: TooGeneric #66962

Description

@qwerty19106

Environment:

note: rustc 1.41.0-nightly (4007d4ef2 2019-12-01) running on x86_64-unknown-linux-gnu
note: compiler flags: -C codegen-units=1 -C debuginfo=2 --crate-type bin

The code:

#![feature(const_generics)]

#[derive(PartialEq, Eq)]
struct Config {
    arr_size: usize
}

struct B<const CFG: Config> {
    arr: [u8; {CFG.arr_size}]
}

fn main() {
}

gives ICE:

error: internal compiler error: constant in type had an ignored error: TooGeneric

Playground

Activity

  1. added
    A-const-genericsArea: const generics (parameters and arguments)
    requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️
    and removed
    requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.
    on Dec 3, 2019
  2. Centril commented on Dec 3, 2019

    @Centril
    Contributor

    Reproduces without the feature gate enabled.

  3. hellow554 commented on Dec 3, 2019

    @hellow554
    Contributor

    It is noteworthy (and probably a bug too), that it only works if you use #[derive(PartialEq, Eq)].

    My code below does ICE on stable, but not on nightly, but emits an error:

    #![feature(const_generics)]
    
    struct Config(usize);
    
    impl std::cmp::Eq for Config {}
    impl std::cmp::PartialEq for Config {
        fn eq(&self, _: &Self) -> bool { false }
    }
    
    struct B<const CFG: Config> {
        arr: [u8; {CFG.0}]
    }
    
    fn main() {}
    error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq`
      --> src/main.rs:10:21
       |
    10 | struct B<const CFG: Config> {
       |                     ^^^^^^ `Config` doesn't derive both `PartialEq` and `Eq`
    

    Backtrace:

    error: internal compiler error: constant in type had an ignored error: TooGeneric
      --> src/main.rs:12:5
       |
    12 |     arr: [u8; {CFG.0}]
       |     ^^^^^^^^^^^^^^^^^^
    
    thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:347:17
    stack backtrace:
       0:     0x7f63673e75d4 - backtrace::backtrace::libunwind::trace::hc586f95f659e6084
                                   at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
       1:     0x7f63673e75d4 - backtrace::backtrace::trace_unsynchronized::ha9827fdb593fd967
                                   at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66
       2:     0x7f63673e75d4 - std::sys_common::backtrace::_print_fmt::h00c888c95e07165a
                                   at src/libstd/sys_common/backtrace.rs:84
       3:     0x7f63673e75d4 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h8407ffb2d059bc74
                                   at src/libstd/sys_common/backtrace.rs:61
       4:     0x7f636741fcec - core::fmt::write::h4165a12a3856465f
                                   at src/libcore/fmt/mod.rs:1024
       5:     0x7f63673db937 - std::io::Write::write_fmt::h499a0566ceaa0048
                                   at src/libstd/io/mod.rs:1428
       6:     0x7f63673eba7e - std::sys_common::backtrace::_print::h05fbb11587298e2b
                                   at src/libstd/sys_common/backtrace.rs:65
       7:     0x7f63673eba7e - std::sys_common::backtrace::print::h8021a3ed2b5ff07e
                                   at src/libstd/sys_common/backtrace.rs:50
       8:     0x7f63673eba7e - std::panicking::default_hook::{{closure}}::hd3a6326f5c6c149f
                                   at src/libstd/panicking.rs:193
       9:     0x7f63673eb771 - std::panicking::default_hook::h7088fb00a0cb1faf
                                   at src/libstd/panicking.rs:210
      10:     0x7f6367931833 - rustc_driver::report_ice::h7d5c1d6a7c4e3fb5
      11:     0x7f63673ec230 - std::panicking::rust_panic_with_hook::h6b223bff7721d4c1
                                   at src/libstd/panicking.rs:475
      12:     0x7f63697c94f5 - std::panicking::begin_panic::h372a91a0f5e0855e
      13:     0x7f63697faa5c - <rustc_errors::HandlerInner as core::ops::drop::Drop>::drop::h222594a5efabe6ee
      14:     0x7f63678ddd96 - core::ptr::real_drop_in_place::ha878bee8c6c3164e
      15:     0x7f63678e3843 - <alloc::rc::Rc<T> as core::ops::drop::Drop>::drop::h78a9ef975e0151c9
      16:     0x7f636790431c - core::ptr::real_drop_in_place::h126176f0f6835d28
      17:     0x7f63678f8860 - rustc_interface::interface::run_compiler_in_existing_thread_pool::h450b3e47e99b2a02
      18:     0x7f63678c8b72 - std::thread::local::LocalKey<T>::with::hc064f9c463ba87b1
      19:     0x7f63678c268e - scoped_tls::ScopedKey<T>::set::he618e0867346e071
      20:     0x7f636793c9a4 - syntax::with_globals::h05656a832d1edc4c
      21:     0x7f636793eb00 - std::sys_common::backtrace::__rust_begin_short_backtrace::hb45a6b809630e3e0
      22:     0x7f63673fcd0a - __rust_maybe_catch_panic
                                   at src/libpanic_unwind/lib.rs:78
      23:     0x7f63678d9469 - core::ops::function::FnOnce::call_once{{vtable.shim}}::h0091d3870173b469
      24:     0x7f63673cd88f - <alloc::boxed::Box<F> as core::ops::function::FnOnce<A>>::call_once::h9ef9eb6ec2ee6be0
                                   at /rustc/fdc0011561c6365c596dfd8fa1ef388162bc89c7/src/liballoc/boxed.rs:969
      25:     0x7f63673fb730 - <alloc::boxed::Box<F> as core::ops::function::FnOnce<A>>::call_once::hc0fc46e9a64f076e
                                   at /rustc/fdc0011561c6365c596dfd8fa1ef388162bc89c7/src/liballoc/boxed.rs:969
      26:     0x7f63673fb730 - std::sys_common::thread::start_thread::h4eee21a391e25c99
                                   at src/libstd/sys_common/thread.rs:13
      27:     0x7f63673fb730 - std::sys::unix::thread::Thread::new::thread_start::h673f7c20aae94594
                                   at src/libstd/sys/unix/thread.rs:80
      28:     0x7f636733a669 - start_thread
      29:     0x7f6367251323 - clone
      30:                0x0 - <unknown>
    
    error: internal compiler error: unexpected panic
    
    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.41.0-nightly (fdc001156 2019-12-02) running on x86_64-unknown-linux-gnu
    
    query stack during panic:
    end of query stack
    
  4. slightlyoutofphase commented on Dec 3, 2019

    @slightlyoutofphase
    Contributor

    Just for the sake of maybe helping to drill down on the cause of the bug by way of comparison, here's an example of similar code that's somewhat more complex but that interestingly does work fine:

    #![allow(incomplete_features)]
    #![feature(const_fn)]
    #![feature(const_generics)]
    #![feature(const_if_match)]
    
    use std::fmt::{self, Debug, Formatter};
    
    struct CFG<const OPT_A: char, const OPT_B: bool> {}
    
    impl<const OPT_A: char, const OPT_B: bool> CFG<OPT_A, OPT_B> {
        const LEN: usize = match OPT_A {
            'A' => 64,
            'B' => 128,
            'C' => 256,
            'D' => 512,
            _ => 512,
        };
        const IS_TRUE: bool = OPT_B;
    }
    
    struct CFGBuilder<const A: char, const B: bool> {}
    
    type Options = (usize, bool);
    
    impl<const A: char, const B: bool> CFGBuilder<A, B> {
        const RESULT: Options = (CFG::<A, B>::LEN, CFG::<A, B>::IS_TRUE);
    }
    
    const DEFAULT_CFG: Options = CFGBuilder::<'A', true>::RESULT;
    const ALT_CFG: Options = CFGBuilder::<'B', false>::RESULT;
    
    struct B1 {
        arr: [u8; DEFAULT_CFG.0],
    }
    
    impl B1 {
        const CAP: usize = DEFAULT_CFG.0;
        const IS_TRUE: bool = DEFAULT_CFG.1;
        const fn new(val: u8) -> Self {
            Self {
                arr: [val; Self::CAP],
            }
        }
    }
    
    impl Debug for B1 {
        fn fmt(&self, f: &mut Formatter) -> fmt::Result {
            write!(f, "B1 IS_TRUE: {}\n{:?}", Self::IS_TRUE, unsafe {
                // Not actually unsafe, because it can't go out of bounds.
                self.arr.get_unchecked(..)
            })
        }
    }
    
    struct B2 {
        arr: [u8; ALT_CFG.0],
    }
    
    impl B2 {
        const CAP: usize = ALT_CFG.0;
        const IS_TRUE: bool = ALT_CFG.1;
        const fn new(val: u8) -> Self {
            Self {
                arr: [val; Self::CAP],
            }
        }
    }
    
    impl Debug for B2 {
        fn fmt(&self, f: &mut Formatter) -> fmt::Result {
            write!(f, "B2 IS_TRUE: {}\n{:?}", Self::IS_TRUE, unsafe {
                // Not actually unsafe, because it can't go out of bounds.
                self.arr.get_unchecked(..)
            })
        }
    }
    
    const ONE: B1 = B1::new(1);
    const TWO: B2 = B2::new(2);
    
    fn main() {
        println!("{:?}", ONE);
        println!("{:?}", TWO);
    }
  5. osa1 commented on Dec 4, 2019

    @osa1
    Contributor

    The backtrace is not too useful as it shows the reporting code rather than the code that raised the error. I did a little bit of debugging and I think rustc_mir::interpret::operand raises the error in this code:

        crate fn eval_const_to_op(
            &self,
            val: &'tcx ty::Const<'tcx>,
            layout: Option<TyLayout<'tcx>>,
        ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
            let tag_scalar = |scalar| match scalar {
                Scalar::Ptr(ptr) => Scalar::Ptr(self.tag_static_base_pointer(ptr)),
                Scalar::Raw { data, size } => Scalar::Raw { data, size },
            };
            // Early-return cases.
            let val_val = match val.val {
                ty::ConstKind::Param(_) =>
                    throw_inval!(TooGeneric), // <--------------------
                ...
  6. osa1 commented on Dec 4, 2019

    @osa1
    Contributor

    Adding some debug prints, I see that the ParamConst is something like ParamConst { index: 0, name: "CFG" }. Is there a way to resolve this "CFG" to the actual const Config struct so that I can select the field?

  7. eddyb commented on Dec 19, 2019

    @eddyb
    Contributor

    TooGeneric shouldn't really cause an error, it should be silent and simply leave the constant unevaluated (until a later situation in which the const parameter is replaced with an actual value).

  8. 4 remaining items

  9. eddyb commented on Jan 18, 2020

    @eddyb
    Contributor

    This is a legitimate error, but it shouldn't have been ICEing. I'm sorry I didn't notice it earlier!

    The reason the original example shouldn't compile is because it can cause post-monomorphization const-eval failures!

    The struct should have a bound which effectively forces all use sites to evaluate the constant and ensure it has no errors (but this is not yet implemented - the syntax where [u8; {CFG.arr_size}]:, should do this).

  10. reopened this on Jan 18, 2020
  11. eddyb commented on Jan 18, 2020

    @eddyb
    Contributor

    Given the lack of const expression unification, this is what it would take:

    #![feature(const_generics)]
    
    #[derive(PartialEq, Eq)]
    struct Config {
        arr_size: usize
    }
    
    type CfgArray<T, const CFG: Config> = [T; {CFG.arr_size}];
    
    struct B<const CFG: Config>
        where CfgArray<u8, CFG>:,
    {
        arr: CfgArray<u8, CFG>,
    }

    Note that the where bound doesn't need to use u8 as the element type, as long as it passes the same Config parameter as the actual use in a field type.

    This might require coordination with @rust-lang/wg-traits to make sure the WF semantics here are coherent with the rest of WF.

  12. djugei commented on Jan 20, 2020

    @djugei
    Contributor

    Thanks for showing a way forward @eddyb
    The previous pull request did in fact not resolve the issue for me.

    So we need to construct a wrapper around the arr_size? i don't quite understand why/what that does. Is there somewhere to read up on it? just to avoid cargo culting.

    specifically whats the difference to

    #![feature(const_generics)]
    type CfgArray<T, const N: usize> = [T; {N}];
    struct B<const N: usize>
        where CfgArray<u8, N>:,
        {
            arr: CfgArray<u8, N>,
        }

    and what does the "empty" where clause do.

  13. eddyb commented on Jan 20, 2020

    @eddyb
    Contributor

    @djugei So there's a few things going on:

    • we have a bit of a messaging issue (cc @varkor @yodaldevoid), you never have to write braces around the array length expression, [T; N] works just as well (the braces aren't for const generic params specifically, they're for expressions in paths, e.g. Foo<T, {N+M}>)
    • [T; N] (or [T; {N}], same thing) and Foo<T, {N}>, where N is a const generic parameter name, will not rely on a const expression, but let the typesystem see that a const parameter is used there, so CfgArray in your example isn't useful
    • OTOH, an expression like N+1 or CFG.arr_size is currently treated opaquely (because we have no algorithm to unify two such expressions), so if you write it twice, the compiler doesn't know it's the same one, hence using a type alias to write it only once
  14. varkor commented on Jan 20, 2020

    @varkor
    Contributor

    I've opened an issue about the first observation (#68387), but there are definitely going to be learnability problems with the latter two until we address it properly.

  15. varkor commented on Jan 20, 2020

    @varkor
    Contributor

    This issue should be addressed in #68388 (though the code in the original post will not be accepted).

  16. djugei commented on Jan 20, 2020

    @djugei
    Contributor

    @eddyb
    so its kinda like my workaround example?
    the rules around when you need to be using brackets are kinda... inconsistent, but thats probably a different issue all together.

  17. varkor commented on Jan 20, 2020

    @varkor
    Contributor

    the rules around when you need to be using brackets are kinda... inconsistent, but thats probably a different issue all together.

    Yes, this is #68257. These examples should all work (and hopefully will do soon!).

  18. added 4 commits that reference this issue on Jan 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-const-genericsArea: const generics (parameters and arguments)F-const_generics`#![feature(const_generics)]`I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️P-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.glacierICE tracked in rust-lang/glacier.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions