diff options
| author | bors <bors@rust-lang.org> | 2020-07-24 13:58:36 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-07-24 13:58:36 +0000 |
| commit | cfb6114b2a20e04e3212ed030bc68d23faf8048f (patch) | |
| tree | 795b20e848c334ca2038a30bfbfd2036791073e4 | |
| parent | 900869371e13cead086f4f9809419daa6a63cfaf (diff) | |
| parent | 5f1eea93a9340d5f2243c5467b4234bd0c14e7a5 (diff) | |
| download | rust-cfb6114b2a20e04e3212ed030bc68d23faf8048f.tar.gz rust-cfb6114b2a20e04e3212ed030bc68d23faf8048f.zip | |
Auto merge of #74676 - lcnr:generics-no-sort, r=varkor
correctly deal with unsorted generic parameters We now stop sorting generic params and instead correctly handle unsorted params in the rest of the compiler. We still restrict const params to come after type params though, so this PR does not change anything which is visible to users. This might slightly influence perf, so let's prevent any unintentional rollups. @bors rollup=never r? @varkor
| -rw-r--r-- | src/librustc_ast_lowering/lib.rs | 15 | ||||
| -rw-r--r-- | src/librustc_resolve/late/lifetimes.rs | 5 | ||||
| -rw-r--r-- | src/librustc_typeck/collect.rs | 47 | ||||
| -rw-r--r-- | src/test/ui/const-generics/argument_order.rs | 12 | ||||
| -rw-r--r-- | src/test/ui/const-generics/argument_order.stderr | 24 |
5 files changed, 62 insertions, 41 deletions
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index b5d3beb4f8a..1c70eef3bf5 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.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 6009e48a54f..3fbb42ece47 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 parameters + // in an arbitrary order. + Some(Set1::Empty) } }) .collect() diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index cb9348a9521..acf68be1176 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 } })); @@ -1899,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., `<T: Foo>`). 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; + } } } diff --git a/src/test/ui/const-generics/argument_order.rs b/src/test/ui/const-generics/argument_order.rs index 6110d16c070..1d1adf39434 100644 --- a/src/test/ui/const-generics/argument_order.rs +++ b/src/test/ui/const-generics/argument_order.rs @@ -6,4 +6,14 @@ struct Bad<const N: usize, T> { //~ ERROR type parameters must be declared prior another: T, } -fn main() { } +struct AlsoBad<const N: usize, 'a, T, 'b, const M: usize, U> { + //~^ ERROR type parameters must be declared prior + //~| ERROR lifetime parameters must be declared prior + a: &'a T, + b: &'b U, +} + +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 f77ae49cf10..19e895b8eb8 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<const N: usize, T> { | -----------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const N: usize>` +error: lifetime parameters must be declared prior to const parameters + --> $DIR/argument_order.rs:9:32 + | +LL | struct AlsoBad<const N: usize, 'a, T, 'b, const M: usize, U> { + | -----------------^^-----^^-------------------- 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<const N: usize, 'a, T, 'b, const M: usize, U> { + | ---------------------^----------------------^- 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,15 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information -error: aborting due to previous error; 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`. |
