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

reordering type parameters causes const generics ICE #69970

Closed
Nugine opened this issue Mar 13, 2020 · 4 comments · Fixed by #70032
Closed

reordering type parameters causes const generics ICE #69970

Nugine opened this issue Mar 13, 2020 · 4 comments · Fixed by #70032
Labels
A-const-generics Area: const generics (parameters and arguments) C-bug Category: This is a bug. F-const_generics `#![feature(const_generics)]` glacier ICE tracked in rust-lang/glacier. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Nugine
Copy link
Contributor

Nugine commented Mar 13, 2020

Code

#![feature(const_generics)]

struct Bad<const N: usize, T> {
    arr: [u8; { N }],
    another: T,
}

// struct Good<T, const N: usize> {
//     arr: [u8; { N }],
//     another: T,
// }

fn main() {}

Meta

rustc +nightly --version --verbose:

rustc 1.43.0-nightly (c20d7eecb 2020-03-11)
binary: rustc
commit-hash: c20d7eecbc0928b57da8fe30b2ef8528e2bdd5be
commit-date: 2020-03-11
host: x86_64-unknown-linux-gnu
release: 1.43.0-nightly
LLVM version: 9.0

Error output

error: type parameters must be declared prior to const parameters
 --> src/main.rs:3:28
  |
3 | struct Bad<const N: usize, T> {
  |           -----------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const N: usize>`

warning: the feature `const_generics` is incomplete and may cause the compiler to crash
 --> src/main.rs:1:12
  |
1 | #![feature(const_generics)]
  |            ^^^^^^^^^^^^^^
  |
  = note: `#[warn(incomplete_features)]` on by default

thread 'rustc' panicked at 'index out of bounds: the len is 1 but the index is 1', src/librustc_typeck/collect.rs:1318:54
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

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.43.0-nightly (c20d7eecb 2020-03-11) running on x86_64-unknown-linux-gnu

note: compiler flags: -C debuginfo=2 -C incremental --crate-type bin

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

error: aborting due to previous error
Backtrace

error: type parameters must be declared prior to const parameters
 --> src/main.rs:3:28
  |
3 | struct Bad<const N: usize, T> {
  |           -----------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const N: usize>`

warning: the feature `const_generics` is incomplete and may cause the compiler to crash
 --> src/main.rs:1:12
  |
1 | #![feature(const_generics)]
  |            ^^^^^^^^^^^^^^
  |
  = note: `#[warn(incomplete_features)]` on by default

thread 'rustc' panicked at 'index out of bounds: the len is 1 but the index is 1', src/librustc_typeck/collect.rs:1318:54
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /cargo/registry/src/gh.neting.cc-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/libunwind.rs:86
   1: backtrace::backtrace::trace_unsynchronized
             at /cargo/registry/src/gh.neting.cc-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/mod.rs:66
   2: std::sys_common::backtrace::_print_fmt
             at src/libstd/sys_common/backtrace.rs:78
   3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
             at src/libstd/sys_common/backtrace.rs:59
   4: core::fmt::write
             at src/libcore/fmt/mod.rs:1063
   5: std::io::Write::write_fmt
             at src/libstd/io/mod.rs:1426
   6: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:62
   7: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:49
   8: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:204
   9: std::panicking::default_hook
             at src/libstd/panicking.rs:224
  10: rustc_driver::report_ice
  11: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:474
  12: rust_begin_unwind
             at src/libstd/panicking.rs:378
  13: core::panicking::panic_fmt
             at src/libcore/panicking.rs:111
  14: core::panicking::panic_bounds_check
             at src/libcore/panicking.rs:69
  15: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
  16: <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T,I>>::spec_extend
  17: rustc_typeck::collect::generics_of
  18: rustc::ty::query::__query_compute::generics_of
  19: rustc::ty::query::<impl rustc::ty::query::config::QueryAccessors for rustc::ty::query::queries::generics_of>::compute
  20: rustc::dep_graph::graph::DepGraph::with_task_impl
  21: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt>::get_query
  22: <rustc_typeck::collect::CollectItemTypesVisitor as rustc_hir::intravisit::Visitor>::visit_item
  23: rustc::hir::map::Map::visit_item_likes_in_module
  24: rustc_typeck::collect::collect_mod_item_types
  25: rustc::ty::query::__query_compute::collect_mod_item_types
  26: rustc::ty::query::<impl rustc::ty::query::config::QueryAccessors for rustc::ty::query::queries::collect_mod_item_types>::compute
  27: rustc::dep_graph::graph::DepGraph::with_task_impl
  28: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt>::get_query
  29: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt>::ensure_query
  30: rustc_typeck::check_crate
  31: rustc_interface::passes::analysis
  32: rustc::ty::query::__query_compute::analysis
  33: rustc::dep_graph::graph::DepGraph::with_task_impl
  34: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt>::get_query
  35: rustc::ty::context::tls::enter_global
  36: rustc_interface::interface::run_compiler_in_existing_thread_pool
  37: scoped_tls::ScopedKey<T>::set
  38: rustc_ast::attr::with_globals
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

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.43.0-nightly (c20d7eecb 2020-03-11) running on x86_64-unknown-linux-gnu

note: compiler flags: -C debuginfo=2 -C incremental --crate-type bin

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

query stack during panic:
#0 [generics_of] processing `Bad`
#1 [collect_mod_item_types] collecting item types in top-level module
#2 [analysis] running analysis passes on this crate
end of query stack
error: aborting due to previous error

@Nugine Nugine added C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 13, 2020
@JohnTitor JohnTitor added the A-const-generics Area: const generics (parameters and arguments) label Mar 13, 2020
@JohnTitor
Copy link
Member

It doesn't require feature flag.

@rust-lang-glacier-bot rust-lang-glacier-bot added the glacier ICE tracked in rust-lang/glacier. label Mar 13, 2020
@Centril Centril added the F-const_generics `#![feature(const_generics)]` label Mar 13, 2020
@lcnr
Copy link
Contributor

lcnr commented Mar 15, 2020

I am currently working on this

@lcnr
Copy link
Contributor

lcnr commented Mar 15, 2020

@varkor, my first idea was to fix this ICE locally by offsetting i in line 1318 for each wrongly placed const param.

// Now create the real type and const parameters.
let type_start = own_start - has_self as u32 + params.len() as u32;
let mut i = 0;
params.extend(ast_generics.params.iter().filter_map(|param| {
let kind = match param.kind {
GenericParamKind::Type { ref default, synthetic, .. } => {
if !allow_defaults && default.is_some() {
if !tcx.features().default_type_parameter_fallback {
tcx.struct_span_lint_hir(
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
param.hir_id,
param.span,
|lint| {
lint.build(
"defaults for type parameters are only allowed in \
`struct`, `enum`, `type`, or `trait` definitions.",
)
.emit();
},
);
}
}
ty::GenericParamDefKind::Type {
has_default: default.is_some(),
object_lifetime_default: object_lifetime_defaults
.as_ref()
.map_or(rl::Set1::Empty, |o| o[i]),

This only moves the error further back.

fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> {
// Look up the type in the substitutions. It really should be in there.
let opt_ty = self.substs.get(p.index as usize).map(|k| k.unpack());
let ty = match opt_ty {
Some(GenericArgKind::Type(ty)) => ty,
Some(kind) => {
let span = self.span.unwrap_or(DUMMY_SP);
span_bug!(
span,
"expected type for `{:?}` ({:?}/{}) but found {:?} \
when substituting (root type={:?}) substs={:?}",
p,
source_ty,
p.index,
kind,
self.root_ty,
self.substs,
);
}

I currently think that it would be best to actually fix the param order if validate_generic_param_order order fails.

fn validate_generic_param_order<'a>(
sess: &Session,
handler: &rustc_errors::Handler,
generics: impl Iterator<Item = (ParamKindOrd, Option<&'a [GenericBound]>, Span, Option<String>)>,
span: Span,
) {

Is this a good approach?

And how should this be done, as validate_generic_param_order is used in AstVisitor::visit_generics, which only receives an immutable reference to Generics.

@varkor
Copy link
Member

varkor commented Mar 15, 2020

I think the right fix for this would be to make sure we can handle generic parameters in any order — there's no technical reason the parameters should be in a fixed order; it's just historical. This would involve doing what you started with, and fixing each problem in turn. However, I don't know how many things still rely on this order, so it could be an involved task.

For a shorter-term fix, we could just make sure that generics are sorted if they're in the wrong order. We could probably do this in generics_of and sort the ast_generics.params before creating the ty::GenericParamDef. This might be more pragmatic, though we should leave a FIXME to address later if we do this.

Thanks for looking into this @lcnr!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-generics Area: const generics (parameters and arguments) C-bug Category: This is a bug. F-const_generics `#![feature(const_generics)]` glacier ICE tracked in rust-lang/glacier. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants