diff options
| author | Dylan DPC <dylan.dpc@gmail.com> | 2020-03-21 13:06:40 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-03-21 13:06:40 +0100 |
| commit | 266801d80683ea2ea023d370ff1edd857c66fe15 (patch) | |
| tree | f94bc5cd8db06d92e75c81caf5528769ff1f002c | |
| parent | 276b54e9c930c4ff015e1958ad1c640deffd29b2 (diff) | |
| parent | 17c94c6746e94a4349a05bbf6326bebe35893acc (diff) | |
| download | rust-266801d80683ea2ea023d370ff1edd857c66fe15.tar.gz rust-266801d80683ea2ea023d370ff1edd857c66fe15.zip | |
Rollup merge of #70032 - lcnr:issue69970, r=varkor
put type params in front of const params in generics_of fixes #69970 r? @varkor
| -rw-r--r-- | src/librustc_ast_passes/ast_validation.rs | 2 | ||||
| -rw-r--r-- | src/librustc_typeck/collect.rs | 94 | ||||
| -rw-r--r-- | src/test/ui/const-generics/argument_order.rs | 9 | ||||
| -rw-r--r-- | src/test/ui/const-generics/argument_order.stderr | 16 |
4 files changed, 84 insertions, 37 deletions
diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 541c681840f..b4363778094 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -645,6 +645,8 @@ impl<'a> AstValidator<'a> { } } +/// Checks that generic parameters are in the correct order, +/// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`) fn validate_generic_param_order<'a>( sess: &Session, handler: &rustc_errors::Handler, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 9fbff039942..a79c0653077 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1306,47 +1306,67 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { // 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]), - synthetic, + // FIXME(const_generics): a few places in the compiler expect generic params + // to be in the order lifetimes, then type params, then const params. + // + // To prevent internal errors in case const parameters are supplied before + // type parameters we first add all type params, then all const params. + params.extend(ast_generics.params.iter().filter_map(|param| { + if let GenericParamKind::Type { ref default, synthetic, .. } = param.kind { + 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(); + }, + ); } } - GenericParamKind::Const { .. } => ty::GenericParamDefKind::Const, - _ => return None, - }; - let param_def = ty::GenericParamDef { - index: type_start + i as u32, - name: param.name.ident().name, - def_id: tcx.hir().local_def_id(param.hir_id), - pure_wrt_drop: param.pure_wrt_drop, - kind, - }; - i += 1; - Some(param_def) + let kind = ty::GenericParamDefKind::Type { + has_default: default.is_some(), + object_lifetime_default: object_lifetime_defaults + .as_ref() + .map_or(rl::Set1::Empty, |o| o[i]), + synthetic, + }; + + let param_def = ty::GenericParamDef { + index: type_start + i as u32, + name: param.name.ident().name, + def_id: tcx.hir().local_def_id(param.hir_id), + pure_wrt_drop: param.pure_wrt_drop, + kind, + }; + i += 1; + Some(param_def) + } else { + None + } + })); + + params.extend(ast_generics.params.iter().filter_map(|param| { + if let GenericParamKind::Const { .. } = param.kind { + let param_def = ty::GenericParamDef { + index: type_start + i as u32, + name: param.name.ident().name, + def_id: tcx.hir().local_def_id(param.hir_id), + pure_wrt_drop: param.pure_wrt_drop, + kind: ty::GenericParamDefKind::Const, + }; + i += 1; + Some(param_def) + } else { + None + } })); // provide junk type parameter defs - the only place that diff --git a/src/test/ui/const-generics/argument_order.rs b/src/test/ui/const-generics/argument_order.rs new file mode 100644 index 00000000000..3446600d049 --- /dev/null +++ b/src/test/ui/const-generics/argument_order.rs @@ -0,0 +1,9 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct Bad<const N: usize, T> { //~ ERROR type parameters must be declared prior + arr: [u8; { N }], + another: T, +} + +fn main() { } diff --git a/src/test/ui/const-generics/argument_order.stderr b/src/test/ui/const-generics/argument_order.stderr new file mode 100644 index 00000000000..1e3b364eb60 --- /dev/null +++ b/src/test/ui/const-generics/argument_order.stderr @@ -0,0 +1,16 @@ +error: type parameters must be declared prior to const parameters + --> $DIR/argument_order.rs:4:28 + | +LL | 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 + --> $DIR/argument_order.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to previous error + |
