Change Ord impl for ParamKindOrd
Updated tests and error msgs Update stderr from test Update w/ lcnr comments Change some tests around, and also updated Ord implementation for ParamKindOrd Update w/ nits from lcnr
This commit is contained in:
parent
4f461f5d12
commit
be0d6f1c06
15 changed files with 82 additions and 55 deletions
|
@ -35,6 +35,7 @@ use rustc_span::source_map::{respan, Spanned};
|
|||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
|
@ -309,13 +310,37 @@ pub type GenericBounds = Vec<GenericBound>;
|
|||
/// Specifies the enforced ordering for generic parameters. In the future,
|
||||
/// if we wanted to relax this order, we could override `PartialEq` and
|
||||
/// `PartialOrd`, to allow the kinds to be unordered.
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
||||
pub enum ParamKindOrd {
|
||||
Lifetime,
|
||||
Type,
|
||||
// `unordered` is only `true` if `sess.has_features().const_generics`
|
||||
// is active. Specifically, if it's only `min_const_generics`, it will still require
|
||||
// ordering consts after types.
|
||||
Const { unordered: bool },
|
||||
}
|
||||
|
||||
impl Ord for ParamKindOrd {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
use ParamKindOrd::*;
|
||||
let to_int = |v| match v {
|
||||
Lifetime => 0,
|
||||
Type | Const { unordered: true } => 1,
|
||||
// technically both consts should be ordered equally,
|
||||
// but only one is ever encountered at a time, so this is
|
||||
// fine.
|
||||
Const { unordered: false } => 2,
|
||||
};
|
||||
|
||||
to_int(*self).cmp(&to_int(*other))
|
||||
}
|
||||
}
|
||||
impl PartialOrd for ParamKindOrd {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ParamKindOrd {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
|
|
|
@ -735,7 +735,6 @@ fn validate_generic_param_order<'a>(
|
|||
}
|
||||
let max_param = &mut max_param;
|
||||
match max_param {
|
||||
Some(ParamKindOrd::Const { unordered: true }) if kind != ParamKindOrd::Lifetime => (),
|
||||
Some(max_param) if *max_param > kind => {
|
||||
let entry = out_of_order.entry(kind).or_insert((*max_param, vec![]));
|
||||
entry.1.push(span);
|
||||
|
|
|
@ -504,14 +504,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
GenericArg::Const(_) => ParamKindOrd::Const { unordered },
|
||||
};
|
||||
|
||||
// This note will be true as long as generic parameters are strictly ordered by their kind.
|
||||
let (first, last) =
|
||||
if kind_ord < arg_ord { (kind, arg.descr()) } else { (arg.descr(), kind) };
|
||||
err.note(&format!("{} arguments must be provided before {} arguments", first, last));
|
||||
|
||||
if let Some(help) = help {
|
||||
err.help(help);
|
||||
// This note is only true when generic parameters are strictly ordered by their kind.
|
||||
if kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal {
|
||||
let (first, last) =
|
||||
if kind_ord < arg_ord { (kind, arg.descr()) } else { (arg.descr(), kind) };
|
||||
err.note(&format!("{} arguments must be provided before {} arguments", first, last));
|
||||
if let Some(help) = help {
|
||||
err.help(help);
|
||||
}
|
||||
}
|
||||
|
||||
err.emit();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ 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 consts and types: `<'a, 'b, T, U, const N: usize, const M: usize>`
|
||||
| -----------------^^-----^^-------------------- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, const N: usize, T, const M: usize, U>`
|
||||
|
||||
error[E0747]: lifetime provided when a type was expected
|
||||
--> $DIR/argument_order.rs:16:23
|
||||
|
@ -11,7 +11,7 @@ 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>`
|
||||
= help: reorder the arguments: lifetimes, then consts, then types, then consts, then types: `<'a, 'b, N, T, M, U>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
type Array<T, const N: usize> = [T; N];
|
||||
|
||||
|
|
|
@ -1,21 +1,9 @@
|
|||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/const-arg-type-arg-misordered.rs:1:12
|
||||
|
|
||||
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[E0747]: constant provided when a type was expected
|
||||
--> $DIR/const-arg-type-arg-misordered.rs:6:35
|
||||
|
|
||||
LL | fn foo<const N: usize>() -> Array<N, ()> {
|
||||
| ^
|
||||
|
|
||||
= note: type arguments must be provided before constant arguments
|
||||
= help: reorder the arguments: types, then consts: `<T, N>`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0747`.
|
||||
|
|
|
@ -5,14 +5,6 @@
|
|||
#![allow(incomplete_features)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
struct FixedOutput<'a, const N: usize, T=u32> {
|
||||
out: &'a [T; N],
|
||||
}
|
||||
|
||||
trait FixedOutputter {
|
||||
fn out(&self) -> FixedOutput<'_, 10>;
|
||||
}
|
||||
|
||||
struct NestedArrays<'a, const N: usize, A: 'a, const M: usize, T:'a =u32> {
|
||||
args: &'a [&'a [T; M]; N],
|
||||
specifier: A,
|
||||
|
|
|
@ -7,6 +7,6 @@ struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
|
|||
//~^ Error lifetime parameters must be declared prior to const parameters
|
||||
|
||||
struct Bar<const N: usize, T = u32, 'a>(&'a (), T);
|
||||
//~^ Error lifetime parameters must be declared prior to const parameters
|
||||
//~^ Error lifetime parameters must be declared prior to type parameters
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -2,13 +2,13 @@ error: lifetime parameters must be declared prior to const parameters
|
|||
--> $DIR/intermixed-lifetime.rs:6:28
|
||||
|
|
||||
LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
|
||||
| -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, T, const N: usize>`
|
||||
| -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T>`
|
||||
|
||||
error: lifetime parameters must be declared prior to const parameters
|
||||
error: lifetime parameters must be declared prior to type parameters
|
||||
--> $DIR/intermixed-lifetime.rs:9:37
|
||||
|
|
||||
LL | struct Bar<const N: usize, T = u32, 'a>(&'a (), T);
|
||||
| --------------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T, const N: usize>`
|
||||
| --------------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
error: type parameters must be declared prior to const parameters
|
||||
--> $DIR/needs-feature.rs:10:26
|
||||
|
|
||||
LL | struct A<const N: usize, T=u32>(T);
|
||||
| -----------------^----- help: reorder the parameters: lifetimes, then consts, then types: `<T, const N: usize>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
error: type parameters must be declared prior to const parameters
|
||||
--> $DIR/needs-feature.rs:4:26
|
||||
--> $DIR/needs-feature.rs:10:26
|
||||
|
|
||||
LL | struct A<const N: usize, T=u32>(T);
|
||||
| -----------------^----- help: reorder the parameters: lifetimes, then types: `<T, const N: usize>`
|
||||
|
||||
error[E0658]: const generics are unstable
|
||||
--> $DIR/needs-feature.rs:4:16
|
||||
--> $DIR/needs-feature.rs:10:16
|
||||
|
|
||||
LL | struct A<const N: usize, T=u32>(T);
|
||||
| ^
|
||||
|
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
= note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
|
||||
= help: add `#![feature(min_const_generics)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
@ -1,8 +1,17 @@
|
|||
//[full] run-pass
|
||||
// Verifies that having generic parameters after constants is not permitted without the
|
||||
// `const_generics` feature.
|
||||
// revisions: none min full
|
||||
|
||||
#![cfg_attr(full, feature(const_generics))]
|
||||
#![cfg_attr(full, allow(incomplete_features))]
|
||||
#![cfg_attr(min, feature(min_const_generics))]
|
||||
|
||||
struct A<const N: usize, T=u32>(T);
|
||||
//~^ ERROR type parameters must be declared prior
|
||||
//~| ERROR const generics are unstable
|
||||
//[none]~^ ERROR type parameters must be declared prior
|
||||
//[none]~| ERROR const generics are unstable
|
||||
//[min]~^^^ ERROR type parameters must be declared prior
|
||||
|
||||
fn main() {}
|
||||
fn main() {
|
||||
let _: A<3> = A(0);
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
// run-pass
|
||||
// Verifies that having generic parameters after constants is permitted.
|
||||
|
||||
#![feature(const_generics)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
struct A<const N: usize, T=u32>(T);
|
||||
|
||||
fn main() {
|
||||
let _: A<3> = A(0);
|
||||
}
|
15
src/test/ui/const-generics/defaults/simple-defaults.rs
Normal file
15
src/test/ui/const-generics/defaults/simple-defaults.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
// run-pass
|
||||
// Checks some basic test cases for defaults.
|
||||
#![feature(const_generics)]
|
||||
#![allow(incomplete_features)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
struct FixedOutput<'a, const N: usize, T=u32> {
|
||||
out: &'a [T; N],
|
||||
}
|
||||
|
||||
trait FixedOutputter {
|
||||
fn out(&self) -> FixedOutput<'_, 10>;
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue