From 8a2e4262e88bede44cfc5a3ab54e5b88442d6ed2 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 23 Jul 2020 10:15:02 +0200 Subject: [PATCH 1/5] stop sorting generic params --- src/librustc_ast_lowering/lib.rs | 15 +-------------- src/librustc_typeck/collect.rs | 21 +++++---------------- 2 files changed, 6 insertions(+), 30 deletions(-) diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index b5d3beb4f8a9b..b631686324b13 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -936,20 +936,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) }); - let mut lowered_params: Vec<_> = - lowered_generics.params.into_iter().chain(in_band_defs).collect(); - - // FIXME(const_generics): the compiler doesn't always cope with - // unsorted generic parameters at the moment, so we make sure - // that they're ordered correctly here for now. (When we chain - // the `in_band_defs`, we might make the order unsorted.) - lowered_params.sort_by_key(|param| match param.kind { - hir::GenericParamKind::Lifetime { .. } => ParamKindOrd::Lifetime, - hir::GenericParamKind::Type { .. } => ParamKindOrd::Type, - hir::GenericParamKind::Const { .. } => ParamKindOrd::Const, - }); - - lowered_generics.params = lowered_params.into(); + lowered_generics.params = lowered_generics.params.into_iter().chain(in_band_defs).collect(); let lowered_generics = lowered_generics.into_generics(self.arena); (lowered_generics, res) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index cb9348a9521bc..5953863cb3c3a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1362,13 +1362,9 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let type_start = own_start - has_self as u32 + params.len() as u32; let mut i = 0; - // 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 { + params.extend(ast_generics.params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => None, + GenericParamKind::Type { ref default, synthetic, .. } => { if !allow_defaults && default.is_some() { if !tcx.features().default_type_parameter_fallback { tcx.struct_span_lint_hir( @@ -1378,7 +1374,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { |lint| { lint.build( "defaults for type parameters are only allowed in \ - `struct`, `enum`, `type`, or `trait` definitions.", + `struct`, `enum`, `type`, or `trait` definitions.", ) .emit(); }, @@ -1403,13 +1399,8 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { }; i += 1; Some(param_def) - } else { - None } - })); - - params.extend(ast_generics.params.iter().filter_map(|param| { - if let GenericParamKind::Const { .. } = param.kind { + GenericParamKind::Const { .. } => { let param_def = ty::GenericParamDef { index: type_start + i as u32, name: param.name.ident().name, @@ -1419,8 +1410,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { }; i += 1; Some(param_def) - } else { - None } })); From e41072479edd514ae6ebe00449ce4808204c5afb Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 23 Jul 2020 12:28:27 +0200 Subject: [PATCH 2/5] fix ICE caused by wrongly ordered generic params --- src/librustc_resolve/late/lifetimes.rs | 5 ++++- src/librustc_typeck/collect.rs | 26 ++++++++++++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 6009e48a54f5e..658528b200dd1 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -1298,7 +1298,10 @@ fn object_lifetime_defaults_for_item( } GenericParamKind::Const { .. } => { // Generic consts don't impose any constraints. - None + // + // We still store a dummy value here to allow generic paramters + // in arbitrary order. + Some(Set1::Empty) } }) .collect() diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 5953863cb3c3a..c4734125e6f01 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1888,14 +1888,24 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat // Collect the predicates that were written inline by the user on each // type parameter (e.g., ``). for param in ast_generics.params { - if let GenericParamKind::Type { .. } = param.kind { - let name = param.name.ident().name; - let param_ty = ty::ParamTy::new(index, name).to_ty(tcx); - index += 1; - - let sized = SizedByDefault::Yes; - let bounds = AstConv::compute_bounds(&icx, param_ty, ¶m.bounds, sized, param.span); - predicates.extend(bounds.predicates(tcx, param_ty)); + match param.kind { + // We already dealt with early bound lifetimes above. + GenericParamKind::Lifetime { .. } => (), + GenericParamKind::Type { .. } => { + let name = param.name.ident().name; + let param_ty = ty::ParamTy::new(index, name).to_ty(tcx); + index += 1; + + let sized = SizedByDefault::Yes; + let bounds = + AstConv::compute_bounds(&icx, param_ty, ¶m.bounds, sized, param.span); + predicates.extend(bounds.predicates(tcx, param_ty)); + } + GenericParamKind::Const { .. } => { + // Bounds on const parameters are currently not possible. + debug_assert!(param.bounds.is_empty()); + index += 1; + } } } From 6dc6a1f9472d7e4be430368dad79a9f8a34c8de0 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 23 Jul 2020 13:04:44 +0200 Subject: [PATCH 3/5] cleanup --- src/librustc_ast_lowering/lib.rs | 2 +- src/librustc_resolve/late/lifetimes.rs | 4 ++-- src/librustc_typeck/collect.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index b631686324b13..1c70eef3bf5e3 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -936,7 +936,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) }); - lowered_generics.params = lowered_generics.params.into_iter().chain(in_band_defs).collect(); + lowered_generics.params.extend(in_band_defs); let lowered_generics = lowered_generics.into_generics(self.arena); (lowered_generics, res) diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 658528b200dd1..3fbb42ece47a0 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -1299,8 +1299,8 @@ fn object_lifetime_defaults_for_item( GenericParamKind::Const { .. } => { // Generic consts don't impose any constraints. // - // We still store a dummy value here to allow generic paramters - // in arbitrary order. + // We still store a dummy value here to allow generic parameters + // in an arbitrary order. Some(Set1::Empty) } }) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index c4734125e6f01..acf68be1176dd 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1374,7 +1374,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { |lint| { lint.build( "defaults for type parameters are only allowed in \ - `struct`, `enum`, `type`, or `trait` definitions.", + `struct`, `enum`, `type`, or `trait` definitions.", ) .emit(); }, From 9910f156df7a17cbbdf319790ce005487d66d2fd Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 23 Jul 2020 13:19:35 +0200 Subject: [PATCH 4/5] add more complex param order test --- src/test/ui/const-generics/argument_order.rs | 7 +++++++ src/test/ui/const-generics/argument_order.stderr | 14 +++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/test/ui/const-generics/argument_order.rs b/src/test/ui/const-generics/argument_order.rs index 6110d16c070d9..9a9b7986c9ccb 100644 --- a/src/test/ui/const-generics/argument_order.rs +++ b/src/test/ui/const-generics/argument_order.rs @@ -6,4 +6,11 @@ struct Bad { //~ ERROR type parameters must be declared prior another: T, } +struct AlsoBad { + //~^ ERROR type parameters must be declared prior + //~| ERROR lifetime parameters must be declared prior + a: &'a T, + b: &'b U, +} + fn main() { } diff --git a/src/test/ui/const-generics/argument_order.stderr b/src/test/ui/const-generics/argument_order.stderr index f77ae49cf10b1..bc2be3b8f1000 100644 --- a/src/test/ui/const-generics/argument_order.stderr +++ b/src/test/ui/const-generics/argument_order.stderr @@ -4,6 +4,18 @@ error: type parameters must be declared prior to const parameters LL | struct Bad { | -----------------^- help: reorder the parameters: lifetimes, then types, then consts: `` +error: lifetime parameters must be declared prior to const parameters + --> $DIR/argument_order.rs:9:32 + | +LL | struct AlsoBad { + | -----------------^^-----^^-------------------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T, U, const N: usize, const M: usize>` + +error: type parameters must be declared prior to const parameters + --> $DIR/argument_order.rs:9:36 + | +LL | struct AlsoBad { + | ---------------------^----------------------^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T, U, const N: usize, const M: usize>` + warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/argument_order.rs:1:12 | @@ -13,5 +25,5 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -error: aborting due to previous error; 1 warning emitted +error: aborting due to 3 previous errors; 1 warning emitted From 5f1eea93a9340d5f2243c5467b4234bd0c14e7a5 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 23 Jul 2020 14:30:01 +0200 Subject: [PATCH 5/5] test usage --- src/test/ui/const-generics/argument_order.rs | 5 ++++- src/test/ui/const-generics/argument_order.stderr | 12 +++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/test/ui/const-generics/argument_order.rs b/src/test/ui/const-generics/argument_order.rs index 9a9b7986c9ccb..1d1adf3943471 100644 --- a/src/test/ui/const-generics/argument_order.rs +++ b/src/test/ui/const-generics/argument_order.rs @@ -13,4 +13,7 @@ struct AlsoBad { b: &'b U, } -fn main() { } +fn main() { + let _: AlsoBad<7, 'static, u32, 'static, 17, u16>; + //~^ ERROR lifetime provided when a type was expected + } diff --git a/src/test/ui/const-generics/argument_order.stderr b/src/test/ui/const-generics/argument_order.stderr index bc2be3b8f1000..19e895b8eb886 100644 --- a/src/test/ui/const-generics/argument_order.stderr +++ b/src/test/ui/const-generics/argument_order.stderr @@ -25,5 +25,15 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -error: aborting due to 3 previous errors; 1 warning emitted +error[E0747]: lifetime provided when a type was expected + --> $DIR/argument_order.rs:17:23 + | +LL | let _: AlsoBad<7, 'static, u32, 'static, 17, u16>; + | ^^^^^^^ + | + = note: lifetime arguments must be provided before type arguments + = help: reorder the arguments: lifetimes, then types, then consts: `<'a, 'b, T, U, N, M>` + +error: aborting due to 4 previous errors; 1 warning emitted +For more information about this error, try `rustc --explain E0747`.