From 58b1a04b9edc19a2f44f780475ebace12a0ab435 Mon Sep 17 00:00:00 2001 From: julianknodt Date: Thu, 30 Jul 2020 00:40:50 -0700 Subject: [PATCH 1/9] Allow types to come after consts in AST validation --- src/librustc_ast_passes/ast_validation.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 0e98c047c2fc..f4cb400892e7 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -735,6 +735,7 @@ fn validate_generic_param_order<'a>( } let max_param = &mut max_param; match max_param { + Some(ParamKindOrd::Const) if ParamKindOrd::Type == kind => (), Some(max_param) if *max_param > kind => { let entry = out_of_order.entry(kind).or_insert((*max_param, vec![])); entry.1.push(span); From 18481cbec981f320abfb83df0e96fd127def7cd5 Mon Sep 17 00:00:00 2001 From: kadmin Date: Thu, 30 Jul 2020 18:39:53 +0000 Subject: [PATCH 2/9] Rm restriction on ord of default types w/ consts --- src/librustc_ast_passes/ast_validation.rs | 3 ++- src/test/ui/const-generics/argument_order.rs | 7 +++--- .../ui/const-generics/argument_order.stderr | 25 ++----------------- .../const-param-before-other-params.rs | 4 +-- .../const-param-before-other-params.stderr | 8 +----- .../ui/const-generics/defaults/right-order.rs | 11 ++++++++ 6 files changed, 20 insertions(+), 38 deletions(-) create mode 100644 src/test/ui/const-generics/defaults/right-order.rs diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index f4cb400892e7..893de1f60e87 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -735,7 +735,8 @@ fn validate_generic_param_order<'a>( } let max_param = &mut max_param; match max_param { - Some(ParamKindOrd::Const) if ParamKindOrd::Type == kind => (), + Some(ParamKindOrd::Const) if ParamKindOrd::Type == kind && + sess.features_untracked().const_generics => (), Some(max_param) if *max_param > kind => { let entry = out_of_order.entry(kind).or_insert((*max_param, vec![])); entry.1.push(span); diff --git a/src/test/ui/const-generics/argument_order.rs b/src/test/ui/const-generics/argument_order.rs index 1d1adf394347..9e071e674e70 100644 --- a/src/test/ui/const-generics/argument_order.rs +++ b/src/test/ui/const-generics/argument_order.rs @@ -1,14 +1,13 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete +#![allow(incomplete_features)] -struct Bad { //~ ERROR type parameters must be declared prior +struct Bad { arr: [u8; { N }], another: T, } struct AlsoBad { - //~^ ERROR type parameters must be declared prior - //~| ERROR lifetime parameters must be declared prior + //~^ ERROR lifetime parameters must be declared prior a: &'a T, b: &'b U, } diff --git a/src/test/ui/const-generics/argument_order.stderr b/src/test/ui/const-generics/argument_order.stderr index 19e895b8eb88..058cc346d1b7 100644 --- a/src/test/ui/const-generics/argument_order.stderr +++ b/src/test/ui/const-generics/argument_order.stderr @@ -1,32 +1,11 @@ -error: type parameters must be declared prior to const parameters - --> $DIR/argument_order.rs:4:28 - | -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 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information - error[E0747]: lifetime provided when a type was expected - --> $DIR/argument_order.rs:17:23 + --> $DIR/argument_order.rs:16:23 | LL | let _: AlsoBad<7, 'static, u32, 'static, 17, u16>; | ^^^^^^^ @@ -34,6 +13,6 @@ 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 +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0747`. diff --git a/src/test/ui/const-generics/const-param-before-other-params.rs b/src/test/ui/const-generics/const-param-before-other-params.rs index 756e961ce914..0d787d9a67b5 100644 --- a/src/test/ui/const-generics/const-param-before-other-params.rs +++ b/src/test/ui/const-generics/const-param-before-other-params.rs @@ -5,8 +5,6 @@ fn bar(_: &'a ()) { //~^ ERROR lifetime parameters must be declared prior to const parameters } -fn foo(_: &T) { - //~^ ERROR type parameters must be declared prior to const parameters -} +fn foo(_: &T) {} fn main() {} diff --git a/src/test/ui/const-generics/const-param-before-other-params.stderr b/src/test/ui/const-generics/const-param-before-other-params.stderr index 9b18b8c79edd..5c1171aae605 100644 --- a/src/test/ui/const-generics/const-param-before-other-params.stderr +++ b/src/test/ui/const-generics/const-param-before-other-params.stderr @@ -4,11 +4,5 @@ error: lifetime parameters must be declared prior to const parameters LL | fn bar(_: &'a ()) { | --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>` -error: type parameters must be declared prior to const parameters - --> $DIR/const-param-before-other-params.rs:8:21 - | -LL | fn foo(_: &T) { - | --------------^- help: reorder the parameters: lifetimes, then types, then consts: `` - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/const-generics/defaults/right-order.rs b/src/test/ui/const-generics/defaults/right-order.rs new file mode 100644 index 000000000000..f1b5c1f02c86 --- /dev/null +++ b/src/test/ui/const-generics/defaults/right-order.rs @@ -0,0 +1,11 @@ +// run-pass +// Verifies that having generic parameters after constants is permitted + +#![feature(const_generics)] +#![allow(incomplete_features)] + +struct A(T); + +fn main() { + let _: A<3> = A(0); +} From f8588284afbaa7dbe479320d0aeae063f0fd4868 Mon Sep 17 00:00:00 2001 From: kadmin Date: Thu, 30 Jul 2020 18:43:44 +0000 Subject: [PATCH 3/9] Added +1 test for only works w/ feat const gen Added this test to ensure that reordering the parameters only works with the feature const generics enabled. Fixed nits Also added another test to verify that intermixed lifetimes are forbidden --- src/librustc_ast_passes/ast_validation.rs | 7 +++++-- .../defaults/intermixed-lifetime.rs | 9 +++++++++ .../defaults/intermixed-lifetime.stderr | 8 ++++++++ .../const-generics/defaults/needs-feature.rs | 8 ++++++++ .../defaults/needs-feature.stderr | 18 ++++++++++++++++++ .../ui/const-generics/defaults/right-order.rs | 2 +- .../type-after-const-requires-default.rs | 10 ++++++++++ 7 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/const-generics/defaults/intermixed-lifetime.rs create mode 100644 src/test/ui/const-generics/defaults/intermixed-lifetime.stderr create mode 100644 src/test/ui/const-generics/defaults/needs-feature.rs create mode 100644 src/test/ui/const-generics/defaults/needs-feature.stderr create mode 100644 src/test/ui/const-generics/defaults/type-after-const-requires-default.rs diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 893de1f60e87..4ebf089c68bd 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -735,8 +735,11 @@ fn validate_generic_param_order<'a>( } let max_param = &mut max_param; match max_param { - Some(ParamKindOrd::Const) if ParamKindOrd::Type == kind && - sess.features_untracked().const_generics => (), + Some(ParamKindOrd::Const) + if ParamKindOrd::Type == kind && sess.features_untracked().const_generics => + { + () + } Some(max_param) if *max_param > kind => { let entry = out_of_order.entry(kind).or_insert((*max_param, vec![])); entry.1.push(span); diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs new file mode 100644 index 000000000000..ff052edcec7c --- /dev/null +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs @@ -0,0 +1,9 @@ +// Checks that lifetimes cannot be interspersed between consts and types. + +#![feature(const_generics)] +#![allow(incomplete_features)] + +struct Foo(&'a (), T); +//~^ Error lifetime parameters must be declared prior to const parameters + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.stderr new file mode 100644 index 000000000000..0880581ec7f0 --- /dev/null +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.stderr @@ -0,0 +1,8 @@ +error: lifetime parameters must be declared prior to const parameters + --> $DIR/intermixed-lifetime.rs:6:28 + | +LL | struct Foo(&'a (), T); + | -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>` + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/defaults/needs-feature.rs b/src/test/ui/const-generics/defaults/needs-feature.rs new file mode 100644 index 000000000000..ea38a4022ae0 --- /dev/null +++ b/src/test/ui/const-generics/defaults/needs-feature.rs @@ -0,0 +1,8 @@ +// Verifies that having generic parameters after constants is not permitted without the +// `const_generics` feature. + +struct A(T); +//~^ ERROR type parameters must be declared prior +//~| ERROR const generics are unstable + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/needs-feature.stderr b/src/test/ui/const-generics/defaults/needs-feature.stderr new file mode 100644 index 000000000000..30604feab1b9 --- /dev/null +++ b/src/test/ui/const-generics/defaults/needs-feature.stderr @@ -0,0 +1,18 @@ +error: type parameters must be declared prior to const parameters + --> $DIR/needs-feature.rs:4:26 + | +LL | struct A(T); + | -----------------^----- help: reorder the parameters: lifetimes, then types: `` + +error[E0658]: const generics are unstable + --> $DIR/needs-feature.rs:4:16 + | +LL | struct A(T); + | ^ + | + = note: see issue #44580 for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/defaults/right-order.rs b/src/test/ui/const-generics/defaults/right-order.rs index f1b5c1f02c86..fce3ab2e6a3a 100644 --- a/src/test/ui/const-generics/defaults/right-order.rs +++ b/src/test/ui/const-generics/defaults/right-order.rs @@ -1,5 +1,5 @@ // run-pass -// Verifies that having generic parameters after constants is permitted +// Verifies that having generic parameters after constants is permitted. #![feature(const_generics)] #![allow(incomplete_features)] diff --git a/src/test/ui/const-generics/defaults/type-after-const-requires-default.rs b/src/test/ui/const-generics/defaults/type-after-const-requires-default.rs new file mode 100644 index 000000000000..fc977d6617c5 --- /dev/null +++ b/src/test/ui/const-generics/defaults/type-after-const-requires-default.rs @@ -0,0 +1,10 @@ +// run-pass +// Verifies that having generic parameters after constants is permitted + +#![feature(const_generics)] +#![allow(incomplete_features)] + +#[allow(dead_code)] +struct A(T); + +fn main() {} From b8352eb2d19b08606fb407def7a378cc93b8f5de Mon Sep 17 00:00:00 2001 From: kadmin Date: Thu, 30 Jul 2020 20:53:32 +0000 Subject: [PATCH 4/9] Test lifetimes after types after consts forbidden Added more complex test and changed error message --- src/librustc_ast_passes/ast_validation.rs | 12 ++++---- .../ui/const-generics/argument_order.stderr | 2 +- .../const-param-before-other-params.stderr | 2 +- .../defaults/complex-unord-param.rs | 28 +++++++++++++++++++ .../defaults/intermixed-lifetime.rs | 3 ++ .../defaults/intermixed-lifetime.stderr | 10 +++++-- 6 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/const-generics/defaults/complex-unord-param.rs diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 4ebf089c68bd..f348d9902b3b 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -780,13 +780,13 @@ fn validate_generic_param_order<'a>( err.span_suggestion( span, &format!( - "reorder the parameters: lifetimes, then types{}", - if sess.features_untracked().const_generics - || sess.features_untracked().min_const_generics - { - ", then consts" + "reorder the parameters: lifetimes{}", + if sess.features_untracked().const_generics { + ", then consts and types" + } else if sess.features_untracked().min_const_generics { + ", then consts, then types" } else { - "" + ", then types" }, ), ordered_params.clone(), diff --git a/src/test/ui/const-generics/argument_order.stderr b/src/test/ui/const-generics/argument_order.stderr index 058cc346d1b7..87dff170b2a6 100644 --- a/src/test/ui/const-generics/argument_order.stderr +++ b/src/test/ui/const-generics/argument_order.stderr @@ -2,7 +2,7 @@ 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>` + | -----------------^^-----^^-------------------- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, T, U, const N: usize, const M: usize>` error[E0747]: lifetime provided when a type was expected --> $DIR/argument_order.rs:16:23 diff --git a/src/test/ui/const-generics/const-param-before-other-params.stderr b/src/test/ui/const-generics/const-param-before-other-params.stderr index 5c1171aae605..1194dd30f61b 100644 --- a/src/test/ui/const-generics/const-param-before-other-params.stderr +++ b/src/test/ui/const-generics/const-param-before-other-params.stderr @@ -2,7 +2,7 @@ error: lifetime parameters must be declared prior to const parameters --> $DIR/const-param-before-other-params.rs:4:21 | LL | fn bar(_: &'a ()) { - | --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>` + | --------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const X: ()>` error: aborting due to previous error diff --git a/src/test/ui/const-generics/defaults/complex-unord-param.rs b/src/test/ui/const-generics/defaults/complex-unord-param.rs new file mode 100644 index 000000000000..8ee5604633e1 --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-unord-param.rs @@ -0,0 +1,28 @@ +// run-pass +// Checks a complicated usage of unordered params + +#![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>; +} + +struct NestedArrays<'a, const N: usize, A: 'a, const M: usize, T:'a =u32> { + args: &'a [&'a [T; M]; N], + specifier: A, +} + +fn main() { + let array = [1, 2, 3]; + let nest = [&array]; + let _ = NestedArrays { + args: &nest, + specifier: true, + }; +} diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs index ff052edcec7c..d53958c9573c 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs @@ -6,4 +6,7 @@ struct Foo(&'a (), T); //~^ Error lifetime parameters must be declared prior to const parameters +struct Bar(&'a (), T); +//~^ Error lifetime parameters must be declared prior to const parameters + fn main() {} diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.stderr index 0880581ec7f0..d8450ba442d0 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.stderr +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.stderr @@ -2,7 +2,13 @@ error: lifetime parameters must be declared prior to const parameters --> $DIR/intermixed-lifetime.rs:6:28 | LL | struct Foo(&'a (), T); - | -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>` + | -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, T, const N: usize>` -error: aborting due to previous error +error: lifetime parameters must be declared prior to const parameters + --> $DIR/intermixed-lifetime.rs:9:37 + | +LL | struct Bar(&'a (), T); + | --------------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T, const N: usize>` + +error: aborting due to 2 previous errors From 319c4f45e0d26430ebd6d7b8b03724c7a0306885 Mon Sep 17 00:00:00 2001 From: kadmin Date: Thu, 30 Jul 2020 22:11:54 +0000 Subject: [PATCH 5/9] Blessed old test where error message had changed Added minor fmt change to ast_validation --- src/librustc_ast_passes/ast_validation.rs | 5 +---- src/test/ui/issues/issue-59508-1.stderr | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index f348d9902b3b..bc249ada7e30 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -736,10 +736,7 @@ fn validate_generic_param_order<'a>( let max_param = &mut max_param; match max_param { Some(ParamKindOrd::Const) - if ParamKindOrd::Type == kind && sess.features_untracked().const_generics => - { - () - } + if ParamKindOrd::Type == kind && sess.features_untracked().const_generics => {} Some(max_param) if *max_param > kind => { let entry = out_of_order.entry(kind).or_insert((*max_param, vec![])); entry.1.push(span); diff --git a/src/test/ui/issues/issue-59508-1.stderr b/src/test/ui/issues/issue-59508-1.stderr index 85db20b13fb4..5e97339f148c 100644 --- a/src/test/ui/issues/issue-59508-1.stderr +++ b/src/test/ui/issues/issue-59508-1.stderr @@ -2,7 +2,7 @@ error: lifetime parameters must be declared prior to type parameters --> $DIR/issue-59508-1.rs:12:25 | LL | pub fn do_things() { - | ----^^--^^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b: 'a, T>` + | ----^^--^^----- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b: 'a, T>` warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-59508-1.rs:2:12 From 1ae1a6332c27fd5f384d3877cb2c4b546dd86c37 Mon Sep 17 00:00:00 2001 From: kadmin Date: Wed, 5 Aug 2020 22:36:47 +0000 Subject: [PATCH 6/9] Add ParamKindOrd::ConstUnordered variant --- src/librustc_ast/ast.rs | 2 ++ src/librustc_ast_passes/ast_validation.rs | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index 3d2625917470..95e01f07e01b 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -314,6 +314,7 @@ pub enum ParamKindOrd { Lifetime, Type, Const, + ConstUnordered, } impl fmt::Display for ParamKindOrd { @@ -322,6 +323,7 @@ impl fmt::Display for ParamKindOrd { ParamKindOrd::Lifetime => "lifetime".fmt(f), ParamKindOrd::Type => "type".fmt(f), ParamKindOrd::Const => "const".fmt(f), + ParamKindOrd::ConstUnordered => "const".fmt(f), } } } diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index bc249ada7e30..7179a59c0dd9 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -735,8 +735,7 @@ fn validate_generic_param_order<'a>( } let max_param = &mut max_param; match max_param { - Some(ParamKindOrd::Const) - if ParamKindOrd::Type == kind && sess.features_untracked().const_generics => {} + Some(ParamKindOrd::ConstUnordered) 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); From 4f461f5d1282ac58892b8985f1df7ea26df6613f Mon Sep 17 00:00:00 2001 From: kadmin Date: Thu, 6 Aug 2020 00:23:17 +0000 Subject: [PATCH 7/9] Switched to unordered field in ParamKindOrd Run fmt --- src/librustc_ast/ast.rs | 6 ++---- src/librustc_ast_passes/ast_validation.rs | 8 ++++++-- src/librustc_typeck/astconv.rs | 12 +++++++++--- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index 95e01f07e01b..5e8066dd960c 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -313,8 +313,7 @@ pub type GenericBounds = Vec; pub enum ParamKindOrd { Lifetime, Type, - Const, - ConstUnordered, + Const { unordered: bool }, } impl fmt::Display for ParamKindOrd { @@ -322,8 +321,7 @@ impl fmt::Display for ParamKindOrd { match self { ParamKindOrd::Lifetime => "lifetime".fmt(f), ParamKindOrd::Type => "type".fmt(f), - ParamKindOrd::Const => "const".fmt(f), - ParamKindOrd::ConstUnordered => "const".fmt(f), + ParamKindOrd::Const { .. } => "const".fmt(f), } } } diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 7179a59c0dd9..a229987da760 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -735,7 +735,7 @@ fn validate_generic_param_order<'a>( } let max_param = &mut max_param; match max_param { - Some(ParamKindOrd::ConstUnordered) if kind != ParamKindOrd::Lifetime => (), + 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); @@ -1159,7 +1159,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident), GenericParamKind::Const { ref ty, kw_span: _ } => { let ty = pprust::ty_to_string(ty); - (ParamKindOrd::Const, Some(format!("const {}: {}", param.ident, ty))) + let unordered = self.session.features_untracked().const_generics; + ( + ParamKindOrd::Const { unordered }, + Some(format!("const {}: {}", param.ident, ty)), + ) } }; (kind, Some(&*param.bounds), param.ident.span, ident) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 79d2f104a525..becabe9c3b99 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -489,10 +489,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { kind, ); + let unordered = sess.features_untracked().const_generics; let kind_ord = match kind { "lifetime" => ParamKindOrd::Lifetime, "type" => ParamKindOrd::Type, - "constant" => ParamKindOrd::Const, + "constant" => ParamKindOrd::Const { unordered }, // It's more concise to match on the string representation, though it means // the match is non-exhaustive. _ => bug!("invalid generic parameter kind {}", kind), @@ -500,7 +501,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let arg_ord = match arg { GenericArg::Lifetime(_) => ParamKindOrd::Lifetime, GenericArg::Type(_) => ParamKindOrd::Type, - GenericArg::Const(_) => ParamKindOrd::Const, + GenericArg::Const(_) => ParamKindOrd::Const { unordered }, }; // This note will be true as long as generic parameters are strictly ordered by their kind. @@ -672,7 +673,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ParamKindOrd::Type } GenericParamDefKind::Const => { - ParamKindOrd::Const + ParamKindOrd::Const { + unordered: tcx + .sess + .features_untracked() + .const_generics, + } } }, param, From be0d6f1c0636b2c7c3c8df819d8c2066669c8024 Mon Sep 17 00:00:00 2001 From: kadmin Date: Thu, 6 Aug 2020 08:22:32 +0000 Subject: [PATCH 8/9] 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 --- src/librustc_ast/ast.rs | 27 ++++++++++++++++++- src/librustc_ast_passes/ast_validation.rs | 1 - src/librustc_typeck/astconv.rs | 16 ++++++----- .../ui/const-generics/argument_order.stderr | 4 +-- .../const-arg-type-arg-misordered.rs | 2 +- .../const-arg-type-arg-misordered.stderr | 14 +--------- .../defaults/complex-unord-param.rs | 8 ------ .../defaults/intermixed-lifetime.rs | 2 +- .../defaults/intermixed-lifetime.stderr | 6 ++--- .../defaults/needs-feature.min.stderr | 8 ++++++ ...ature.stderr => needs-feature.none.stderr} | 8 +++--- .../const-generics/defaults/needs-feature.rs | 15 ++++++++--- .../ui/const-generics/defaults/right-order.rs | 11 -------- .../defaults/simple-defaults.rs | 15 +++++++++++ ...ires-default.rs => type-after-const-ok.rs} | 0 15 files changed, 82 insertions(+), 55 deletions(-) create mode 100644 src/test/ui/const-generics/defaults/needs-feature.min.stderr rename src/test/ui/const-generics/defaults/{needs-feature.stderr => needs-feature.none.stderr} (64%) delete mode 100644 src/test/ui/const-generics/defaults/right-order.rs create mode 100644 src/test/ui/const-generics/defaults/simple-defaults.rs rename src/test/ui/const-generics/{defaults/type-after-const-requires-default.rs => type-after-const-ok.rs} (100%) diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index 5e8066dd960c..2f11596c22c0 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -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; /// 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 { + Some(self.cmp(other)) + } +} + impl fmt::Display for ParamKindOrd { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index a229987da760..83f64793833b 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -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); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index becabe9c3b99..2be100ae3366 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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(); } diff --git a/src/test/ui/const-generics/argument_order.stderr b/src/test/ui/const-generics/argument_order.stderr index 87dff170b2a6..687e8589bf08 100644 --- a/src/test/ui/const-generics/argument_order.stderr +++ b/src/test/ui/const-generics/argument_order.stderr @@ -2,7 +2,7 @@ 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 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 diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.rs b/src/test/ui/const-generics/const-arg-type-arg-misordered.rs index 9f989ee20a56..13ca56ad3e69 100644 --- a/src/test/ui/const-generics/const-arg-type-arg-misordered.rs +++ b/src/test/ui/const-generics/const-arg-type-arg-misordered.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete +#![allow(incomplete_features)] type Array = [T; N]; diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr b/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr index 4a6241de1b45..2e2bfed51fb2 100644 --- a/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr +++ b/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr @@ -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 for more information - error[E0747]: constant provided when a type was expected --> $DIR/const-arg-type-arg-misordered.rs:6:35 | LL | fn foo() -> Array { | ^ - | - = note: type arguments must be provided before constant arguments - = help: reorder the arguments: types, then consts: `` -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`. diff --git a/src/test/ui/const-generics/defaults/complex-unord-param.rs b/src/test/ui/const-generics/defaults/complex-unord-param.rs index 8ee5604633e1..72967640a8e6 100644 --- a/src/test/ui/const-generics/defaults/complex-unord-param.rs +++ b/src/test/ui/const-generics/defaults/complex-unord-param.rs @@ -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, diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs index d53958c9573c..ea3a8c14b98c 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs @@ -7,6 +7,6 @@ struct Foo(&'a (), T); //~^ Error lifetime parameters must be declared prior to const parameters struct Bar(&'a (), T); -//~^ Error lifetime parameters must be declared prior to const parameters +//~^ Error lifetime parameters must be declared prior to type parameters fn main() {} diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.stderr index d8450ba442d0..0f6d7f1065af 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.stderr +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.stderr @@ -2,13 +2,13 @@ error: lifetime parameters must be declared prior to const parameters --> $DIR/intermixed-lifetime.rs:6:28 | LL | struct Foo(&'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(&'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 diff --git a/src/test/ui/const-generics/defaults/needs-feature.min.stderr b/src/test/ui/const-generics/defaults/needs-feature.min.stderr new file mode 100644 index 000000000000..d57190ea3bba --- /dev/null +++ b/src/test/ui/const-generics/defaults/needs-feature.min.stderr @@ -0,0 +1,8 @@ +error: type parameters must be declared prior to const parameters + --> $DIR/needs-feature.rs:10:26 + | +LL | struct A(T); + | -----------------^----- help: reorder the parameters: lifetimes, then consts, then types: `` + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/defaults/needs-feature.stderr b/src/test/ui/const-generics/defaults/needs-feature.none.stderr similarity index 64% rename from src/test/ui/const-generics/defaults/needs-feature.stderr rename to src/test/ui/const-generics/defaults/needs-feature.none.stderr index 30604feab1b9..3b6f63a8efec 100644 --- a/src/test/ui/const-generics/defaults/needs-feature.stderr +++ b/src/test/ui/const-generics/defaults/needs-feature.none.stderr @@ -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(T); | -----------------^----- help: reorder the parameters: lifetimes, then types: `` error[E0658]: const generics are unstable - --> $DIR/needs-feature.rs:4:16 + --> $DIR/needs-feature.rs:10:16 | LL | struct A(T); | ^ | - = note: see issue #44580 for more information - = help: add `#![feature(const_generics)]` to the crate attributes to enable + = note: see issue #74878 for more information + = help: add `#![feature(min_const_generics)]` to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/defaults/needs-feature.rs b/src/test/ui/const-generics/defaults/needs-feature.rs index ea38a4022ae0..ec02dbf407d6 100644 --- a/src/test/ui/const-generics/defaults/needs-feature.rs +++ b/src/test/ui/const-generics/defaults/needs-feature.rs @@ -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(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); +} diff --git a/src/test/ui/const-generics/defaults/right-order.rs b/src/test/ui/const-generics/defaults/right-order.rs deleted file mode 100644 index fce3ab2e6a3a..000000000000 --- a/src/test/ui/const-generics/defaults/right-order.rs +++ /dev/null @@ -1,11 +0,0 @@ -// run-pass -// Verifies that having generic parameters after constants is permitted. - -#![feature(const_generics)] -#![allow(incomplete_features)] - -struct A(T); - -fn main() { - let _: A<3> = A(0); -} diff --git a/src/test/ui/const-generics/defaults/simple-defaults.rs b/src/test/ui/const-generics/defaults/simple-defaults.rs new file mode 100644 index 000000000000..b282dfd37cc4 --- /dev/null +++ b/src/test/ui/const-generics/defaults/simple-defaults.rs @@ -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() {} diff --git a/src/test/ui/const-generics/defaults/type-after-const-requires-default.rs b/src/test/ui/const-generics/type-after-const-ok.rs similarity index 100% rename from src/test/ui/const-generics/defaults/type-after-const-requires-default.rs rename to src/test/ui/const-generics/type-after-const-ok.rs From 64f643782245b25326c6e9a76bf78c798f1ae168 Mon Sep 17 00:00:00 2001 From: kadmin Date: Sun, 9 Aug 2020 07:50:56 +0000 Subject: [PATCH 9/9] Convert `Eq` impl to check Ord::Equal --- src/librustc_ast/ast.rs | 8 +++++++- src/test/ui/const-generics/argument_order.stderr | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index 2f11596c22c0..c56f0bd8420a 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -310,7 +310,7 @@ pub type GenericBounds = Vec; /// 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, Hash, Clone, Copy)] +#[derive(Hash, Clone, Copy)] pub enum ParamKindOrd { Lifetime, Type, @@ -340,6 +340,12 @@ impl PartialOrd for ParamKindOrd { Some(self.cmp(other)) } } +impl PartialEq for ParamKindOrd { + fn eq(&self, other: &Self) -> bool { + self.cmp(other) == Ordering::Equal + } +} +impl Eq for ParamKindOrd {} impl fmt::Display for ParamKindOrd { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/test/ui/const-generics/argument_order.stderr b/src/test/ui/const-generics/argument_order.stderr index 687e8589bf08..d6546a768d23 100644 --- a/src/test/ui/const-generics/argument_order.stderr +++ b/src/test/ui/const-generics/argument_order.stderr @@ -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 consts, then types, then consts, then types: `<'a, 'b, N, T, M, U>` + = help: reorder the arguments: lifetimes, then consts: `<'a, 'b, N, T, M, U>` error: aborting due to 2 previous errors