From 5d7e7c25e4e6cea5b441227d5dc55b9defb170f1 Mon Sep 17 00:00:00 2001 From: Hameer Abbasi Date: Wed, 9 Sep 2020 13:28:41 +0200 Subject: [PATCH 01/18] Add revisions to const generic issue UI tests. --- .../auxiliary/const_generic_issues_lib.rs | 4 +- .../issues/issue-61935.full.stderr | 10 ++ .../issues/issue-61935.min.stderr | 10 ++ .../ui/const-generics/issues/issue-61935.rs | 9 +- .../const-generics/issues/issue-61935.stderr | 19 ---- ...-encountered-polymorphic-const.full.stderr | 10 ++ ...7-encountered-polymorphic-const.min.stderr | 10 ++ ...sue-62187-encountered-polymorphic-const.rs | 6 +- ...62187-encountered-polymorphic-const.stderr | 19 ---- ...e-62220.stderr => issue-62220.full.stderr} | 2 +- .../issues/issue-62220.min.stderr | 10 ++ .../ui/const-generics/issues/issue-62220.rs | 9 +- .../issues/issue-62456.full.stderr | 10 ++ .../issues/issue-62456.min.stderr | 10 ++ .../ui/const-generics/issues/issue-62456.rs | 9 +- .../const-generics/issues/issue-62456.stderr | 19 ---- ...e-62504.stderr => issue-62504.full.stderr} | 2 +- .../issues/issue-62504.min.stderr | 10 ++ .../ui/const-generics/issues/issue-62504.rs | 10 +- .../issues/issue-62579-no-match.min.stderr | 11 ++ .../issues/issue-62579-no-match.rs | 10 +- .../issues/issue-62579-no-match.stderr | 11 -- .../issues/issue-62878.full.stderr | 28 +++++ .../issues/issue-62878.min.stderr | 18 +++ .../ui/const-generics/issues/issue-62878.rs | 12 +- .../const-generics/issues/issue-62878.stderr | 33 ++++-- ...185-2.stderr => issue-67185-2.full.stderr} | 23 ++-- .../issues/issue-67185-2.min.stderr | 103 ++++++++++++++++++ .../ui/const-generics/issues/issue-67185-2.rs | 6 +- ...e-67739.stderr => issue-67739.full.stderr} | 0 .../issues/issue-67739.min.stderr | 10 ++ .../ui/const-generics/issues/issue-67739.rs | 11 +- ...e-68366.stderr => issue-68366.full.stderr} | 4 +- .../issues/issue-68366.min.stderr | 29 +++++ .../ui/const-generics/issues/issue-68366.rs | 7 +- ...e-72787.stderr => issue-72787.full.stderr} | 10 +- .../issues/issue-72787.min.stderr | 57 ++++++++++ .../ui/const-generics/issues/issue-72787.rs | 23 ++-- ...e-72819-generic-in-const-eval.full.stderr} | 2 +- ...sue-72819-generic-in-const-eval.min.stderr | 10 ++ .../issue-72819-generic-in-const-eval.rs | 9 +- .../ui/const-generics/issues/issue-73120.rs | 1 + 42 files changed, 467 insertions(+), 149 deletions(-) create mode 100644 src/test/ui/const-generics/issues/issue-61935.full.stderr create mode 100644 src/test/ui/const-generics/issues/issue-61935.min.stderr delete mode 100644 src/test/ui/const-generics/issues/issue-61935.stderr create mode 100644 src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.full.stderr create mode 100644 src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.min.stderr delete mode 100644 src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr rename src/test/ui/const-generics/issues/{issue-62220.stderr => issue-62220.full.stderr} (90%) create mode 100644 src/test/ui/const-generics/issues/issue-62220.min.stderr create mode 100644 src/test/ui/const-generics/issues/issue-62456.full.stderr create mode 100644 src/test/ui/const-generics/issues/issue-62456.min.stderr delete mode 100644 src/test/ui/const-generics/issues/issue-62456.stderr rename src/test/ui/const-generics/issues/{issue-62504.stderr => issue-62504.full.stderr} (89%) create mode 100644 src/test/ui/const-generics/issues/issue-62504.min.stderr create mode 100644 src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr delete mode 100644 src/test/ui/const-generics/issues/issue-62579-no-match.stderr create mode 100644 src/test/ui/const-generics/issues/issue-62878.full.stderr create mode 100644 src/test/ui/const-generics/issues/issue-62878.min.stderr rename src/test/ui/const-generics/issues/{issue-67185-2.stderr => issue-67185-2.full.stderr} (82%) create mode 100644 src/test/ui/const-generics/issues/issue-67185-2.min.stderr rename src/test/ui/const-generics/issues/{issue-67739.stderr => issue-67739.full.stderr} (100%) create mode 100644 src/test/ui/const-generics/issues/issue-67739.min.stderr rename src/test/ui/const-generics/issues/{issue-68366.stderr => issue-68366.full.stderr} (93%) create mode 100644 src/test/ui/const-generics/issues/issue-68366.min.stderr rename src/test/ui/const-generics/issues/{issue-72787.stderr => issue-72787.full.stderr} (88%) create mode 100644 src/test/ui/const-generics/issues/issue-72787.min.stderr rename src/test/ui/const-generics/issues/{issue-72819-generic-in-const-eval.stderr => issue-72819-generic-in-const-eval.full.stderr} (84%) create mode 100644 src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr diff --git a/src/test/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs b/src/test/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs index 59a4d345cbccb..7ea8d936d6141 100644 --- a/src/test/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs +++ b/src/test/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs @@ -1,4 +1,6 @@ -#![feature(const_generics)] +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] // All of these three items must be in `lib2` to reproduce the error diff --git a/src/test/ui/const-generics/issues/issue-61935.full.stderr b/src/test/ui/const-generics/issues/issue-61935.full.stderr new file mode 100644 index 0000000000000..b805bc0db7e55 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-61935.full.stderr @@ -0,0 +1,10 @@ +error: constant expression depends on a generic parameter + --> $DIR/issue-61935.rs:10:14 + | +LL | Self:FooImpl<{N==0}> + | ^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/issues/issue-61935.min.stderr b/src/test/ui/const-generics/issues/issue-61935.min.stderr new file mode 100644 index 0000000000000..e5715ec658c5c --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-61935.min.stderr @@ -0,0 +1,10 @@ +error: generic parameters must not be used inside of non trivial constant values + --> $DIR/issue-61935.rs:10:23 + | +LL | Self:FooImpl<{N==0}> + | ^ non-trivial anonymous constants must not depend on the parameter `N` + | + = help: it is currently only allowed to use either `N` or `{ N }` as generic constants + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/issues/issue-61935.rs b/src/test/ui/const-generics/issues/issue-61935.rs index 0d42ff1895cdb..64257da030943 100644 --- a/src/test/ui/const-generics/issues/issue-61935.rs +++ b/src/test/ui/const-generics/issues/issue-61935.rs @@ -1,12 +1,15 @@ -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] trait Foo {} impl Foo for [(); N] where Self:FooImpl<{N==0}> -//~^ERROR constant expression depends on a generic parameter +//[full]~^ERROR constant expression depends on a generic parameter +//[min]~^^ERROR generic parameters must not be used inside of non trivial constant values {} trait FooImpl{} diff --git a/src/test/ui/const-generics/issues/issue-61935.stderr b/src/test/ui/const-generics/issues/issue-61935.stderr deleted file mode 100644 index a785af5f008ea..0000000000000 --- a/src/test/ui/const-generics/issues/issue-61935.stderr +++ /dev/null @@ -1,19 +0,0 @@ -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-61935.rs:1:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information - -error: constant expression depends on a generic parameter - --> $DIR/issue-61935.rs:8:14 - | -LL | Self:FooImpl<{N==0}> - | ^^^^^^^^^^^^^^^ - | - = note: this may fail depending on what value the parameter takes - -error: aborting due to previous error; 1 warning emitted - diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.full.stderr b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.full.stderr new file mode 100644 index 0000000000000..aada9c007256b --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.full.stderr @@ -0,0 +1,10 @@ +warning: unused variable: `foo` + --> $DIR/issue-62187-encountered-polymorphic-const.rs:17:9 + | +LL | let foo = <[u8; 2]>::BIT_LEN; + | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` + | + = note: `#[warn(unused_variables)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.min.stderr b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.min.stderr new file mode 100644 index 0000000000000..aada9c007256b --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.min.stderr @@ -0,0 +1,10 @@ +warning: unused variable: `foo` + --> $DIR/issue-62187-encountered-polymorphic-const.rs:17:9 + | +LL | let foo = <[u8; 2]>::BIT_LEN; + | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` + | + = note: `#[warn(unused_variables)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs index 2f3b5c5dc5b89..710fdbd9a11f3 100644 --- a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs +++ b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs @@ -1,7 +1,9 @@ // run-pass -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] pub trait BitLen: Sized { const BIT_LEN: usize; diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr deleted file mode 100644 index a9abb877c094c..0000000000000 --- a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr +++ /dev/null @@ -1,19 +0,0 @@ -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-62187-encountered-polymorphic-const.rs:3:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information - -warning: unused variable: `foo` - --> $DIR/issue-62187-encountered-polymorphic-const.rs:15:9 - | -LL | let foo = <[u8; 2]>::BIT_LEN; - | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` - | - = note: `#[warn(unused_variables)]` on by default - -warning: 2 warnings emitted - diff --git a/src/test/ui/const-generics/issues/issue-62220.stderr b/src/test/ui/const-generics/issues/issue-62220.full.stderr similarity index 90% rename from src/test/ui/const-generics/issues/issue-62220.stderr rename to src/test/ui/const-generics/issues/issue-62220.full.stderr index d91d2bb326fc5..120aa8e4af5d2 100644 --- a/src/test/ui/const-generics/issues/issue-62220.stderr +++ b/src/test/ui/const-generics/issues/issue-62220.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-62220.rs:10:27 + --> $DIR/issue-62220.rs:13:27 | LL | pub fn trunc(self) -> (TruncatedVector, T) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-62220.min.stderr b/src/test/ui/const-generics/issues/issue-62220.min.stderr new file mode 100644 index 0000000000000..943b689bf61af --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62220.min.stderr @@ -0,0 +1,10 @@ +error: generic parameters must not be used inside of non trivial constant values + --> $DIR/issue-62220.rs:8:59 + | +LL | pub type TruncatedVector = Vector; + | ^ non-trivial anonymous constants must not depend on the parameter `N` + | + = help: it is currently only allowed to use either `N` or `{ N }` as generic constants + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/issues/issue-62220.rs b/src/test/ui/const-generics/issues/issue-62220.rs index 5c4a0d31a895d..acb13ad1170f2 100644 --- a/src/test/ui/const-generics/issues/issue-62220.rs +++ b/src/test/ui/const-generics/issues/issue-62220.rs @@ -1,14 +1,17 @@ -#![allow(incomplete_features)] -#![feature(const_generics)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] pub struct Vector([T; N]); pub type TruncatedVector = Vector; +//[min]~^ ERROR generic parameters must not be used inside of non trivial constant values impl Vector { /// Drop the last component and return the vector with one fewer dimension. pub fn trunc(self) -> (TruncatedVector, T) { - //~^ ERROR constant expression depends on a generic parameter + //[full]~^ ERROR constant expression depends on a generic parameter unimplemented!() } } diff --git a/src/test/ui/const-generics/issues/issue-62456.full.stderr b/src/test/ui/const-generics/issues/issue-62456.full.stderr new file mode 100644 index 0000000000000..a8d44074db9d1 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62456.full.stderr @@ -0,0 +1,10 @@ +error: constant expression depends on a generic parameter + --> $DIR/issue-62456.rs:7:20 + | +LL | let _ = [0u64; N + 1]; + | ^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/issues/issue-62456.min.stderr b/src/test/ui/const-generics/issues/issue-62456.min.stderr new file mode 100644 index 0000000000000..335f0ead27871 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62456.min.stderr @@ -0,0 +1,10 @@ +error: generic parameters must not be used inside of non trivial constant values + --> $DIR/issue-62456.rs:7:20 + | +LL | let _ = [0u64; N + 1]; + | ^ non-trivial anonymous constants must not depend on the parameter `N` + | + = help: it is currently only allowed to use either `N` or `{ N }` as generic constants + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/issues/issue-62456.rs b/src/test/ui/const-generics/issues/issue-62456.rs index 37947ad1b331c..c96868c00a3d6 100644 --- a/src/test/ui/const-generics/issues/issue-62456.rs +++ b/src/test/ui/const-generics/issues/issue-62456.rs @@ -1,9 +1,12 @@ -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] fn foo() { let _ = [0u64; N + 1]; - //~^ ERROR constant expression depends on a generic parameter + //[full]~^ ERROR constant expression depends on a generic parameter + //[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values } fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-62456.stderr b/src/test/ui/const-generics/issues/issue-62456.stderr deleted file mode 100644 index 0454fed670598..0000000000000 --- a/src/test/ui/const-generics/issues/issue-62456.stderr +++ /dev/null @@ -1,19 +0,0 @@ -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-62456.rs:1:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information - -error: constant expression depends on a generic parameter - --> $DIR/issue-62456.rs:5:20 - | -LL | let _ = [0u64; N + 1]; - | ^^^^^ - | - = note: this may fail depending on what value the parameter takes - -error: aborting due to previous error; 1 warning emitted - diff --git a/src/test/ui/const-generics/issues/issue-62504.stderr b/src/test/ui/const-generics/issues/issue-62504.full.stderr similarity index 89% rename from src/test/ui/const-generics/issues/issue-62504.stderr rename to src/test/ui/const-generics/issues/issue-62504.full.stderr index f09af76325e96..9c84f06ce9f74 100644 --- a/src/test/ui/const-generics/issues/issue-62504.stderr +++ b/src/test/ui/const-generics/issues/issue-62504.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-62504.rs:18:25 + --> $DIR/issue-62504.rs:19:25 | LL | ArrayHolder([0; Self::SIZE]) | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-62504.min.stderr b/src/test/ui/const-generics/issues/issue-62504.min.stderr new file mode 100644 index 0000000000000..752df17aad614 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62504.min.stderr @@ -0,0 +1,10 @@ +error: generic parameters must not be used inside of non trivial constant values + --> $DIR/issue-62504.rs:19:25 + | +LL | ArrayHolder([0; Self::SIZE]) + | ^^^^^^^^^^ non-trivial anonymous constants must not depend on the parameter `Self` + | + = help: it is currently only allowed to use either `Self` or `{ Self }` as generic constants + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/issues/issue-62504.rs b/src/test/ui/const-generics/issues/issue-62504.rs index 4e05aadd3930f..b520dbe4e803b 100644 --- a/src/test/ui/const-generics/issues/issue-62504.rs +++ b/src/test/ui/const-generics/issues/issue-62504.rs @@ -1,7 +1,8 @@ -// Regression test for #62504 - -#![feature(const_generics)] +// revisions: full min #![allow(incomplete_features)] +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] trait HasSize { const SIZE: usize; @@ -16,7 +17,8 @@ struct ArrayHolder([u32; X]); impl ArrayHolder { pub const fn new() -> Self { ArrayHolder([0; Self::SIZE]) - //~^ ERROR constant expression depends on a generic parameter + //[full]~^ ERROR constant expression depends on a generic parameter + //[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values } } diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr b/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr new file mode 100644 index 0000000000000..6903b20fad63c --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr @@ -0,0 +1,11 @@ +error: `NoMatch` is forbidden as the type of a const generic parameter + --> $DIR/issue-62579-no-match.rs:10:17 + | +LL | fn foo() -> bool { + | ^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = note: more complex types are supported with `#[feature(const_generics)]` + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.rs b/src/test/ui/const-generics/issues/issue-62579-no-match.rs index 7eaf5eea0787b..c9853aa9162e1 100644 --- a/src/test/ui/const-generics/issues/issue-62579-no-match.rs +++ b/src/test/ui/const-generics/issues/issue-62579-no-match.rs @@ -1,12 +1,14 @@ -// run-pass - -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete +// [full] run-pass +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] #[derive(PartialEq, Eq)] struct NoMatch; fn foo() -> bool { + //[min]~^ ERROR `NoMatch` is forbidden as the type of a const generic parameter true } diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.stderr b/src/test/ui/const-generics/issues/issue-62579-no-match.stderr deleted file mode 100644 index 9fb9b5b13d8d5..0000000000000 --- a/src/test/ui/const-generics/issues/issue-62579-no-match.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-62579-no-match.rs:3:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/const-generics/issues/issue-62878.full.stderr b/src/test/ui/const-generics/issues/issue-62878.full.stderr new file mode 100644 index 0000000000000..c8b9db8941098 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62878.full.stderr @@ -0,0 +1,28 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-62878.rs:6:38 + | +LL | fn foo() {} + | ^ the type must not depend on the parameter `N` + +error[E0107]: wrong number of const arguments: expected 2, found 1 + --> $DIR/issue-62878.rs:11:5 + | +LL | foo::<_, {[1]}>(); + | ^^^^^^^^^^^^^^^ expected 2 const arguments + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/issue-62878.rs:11:11 + | +LL | foo::<_, {[1]}>(); + | ^ unexpected type argument + +error[E0308]: mismatched types + --> $DIR/issue-62878.rs:11:15 + | +LL | foo::<_, {[1]}>(); + | ^^^ expected `usize`, found array `[{integer}; 1]` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0107, E0308, E0770. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/const-generics/issues/issue-62878.min.stderr b/src/test/ui/const-generics/issues/issue-62878.min.stderr new file mode 100644 index 0000000000000..34edd09b51565 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62878.min.stderr @@ -0,0 +1,18 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-62878.rs:6:38 + | +LL | fn foo() {} + | ^ the type must not depend on the parameter `N` + +error: `[u8; _]` is forbidden as the type of a const generic parameter + --> $DIR/issue-62878.rs:6:33 + | +LL | fn foo() {} + | ^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = note: more complex types are supported with `#[feature(const_generics)]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/src/test/ui/const-generics/issues/issue-62878.rs b/src/test/ui/const-generics/issues/issue-62878.rs index ccc05fdf100e7..0487dda2fe81d 100644 --- a/src/test/ui/const-generics/issues/issue-62878.rs +++ b/src/test/ui/const-generics/issues/issue-62878.rs @@ -1,11 +1,15 @@ -#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] fn foo() {} //~^ ERROR the type of const parameters must not +//[min]~| ERROR `[u8; _]` is forbidden as the type of a const generic parameter fn main() { foo::<_, {[1]}>(); - //~^ ERROR wrong number of const arguments - //~| ERROR wrong number of type arguments - //~| ERROR mismatched types + //[full]~^ ERROR wrong number of const arguments + //[full]~| ERROR wrong number of type arguments + //[full]~| ERROR mismatched types } diff --git a/src/test/ui/const-generics/issues/issue-62878.stderr b/src/test/ui/const-generics/issues/issue-62878.stderr index fe0990d8241fa..8f7fe000a8116 100644 --- a/src/test/ui/const-generics/issues/issue-62878.stderr +++ b/src/test/ui/const-generics/issues/issue-62878.stderr @@ -1,37 +1,46 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/issue-62878.rs:3:38 + --> $DIR/issue-62878.rs:5:38 | LL | fn foo() {} | ^ the type must not depend on the parameter `N` -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-62878.rs:1:12 +error[E0658]: const generics are unstable + --> $DIR/issue-62878.rs:5:14 | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ +LL | fn foo() {} + | ^ + | + = note: see issue #74878 for more information + = help: add `#![feature(min_const_generics)]` to the crate attributes to enable + +error[E0658]: const generics are unstable + --> $DIR/issue-62878.rs:5:30 + | +LL | fn foo() {} + | ^ | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information + = note: see issue #74878 for more information + = help: add `#![feature(min_const_generics)]` to the crate attributes to enable error[E0107]: wrong number of const arguments: expected 2, found 1 - --> $DIR/issue-62878.rs:7:5 + --> $DIR/issue-62878.rs:11:5 | LL | foo::<_, {[1]}>(); | ^^^^^^^^^^^^^^^ expected 2 const arguments error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/issue-62878.rs:7:11 + --> $DIR/issue-62878.rs:11:11 | LL | foo::<_, {[1]}>(); | ^ unexpected type argument error[E0308]: mismatched types - --> $DIR/issue-62878.rs:7:15 + --> $DIR/issue-62878.rs:11:15 | LL | foo::<_, {[1]}>(); | ^^^ expected `usize`, found array `[{integer}; 1]` -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0107, E0308, E0770. +Some errors have detailed explanations: E0107, E0308, E0658, E0770. For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/const-generics/issues/issue-67185-2.stderr b/src/test/ui/const-generics/issues/issue-67185-2.full.stderr similarity index 82% rename from src/test/ui/const-generics/issues/issue-67185-2.stderr rename to src/test/ui/const-generics/issues/issue-67185-2.full.stderr index 7d947a907a0ee..78c7ebff05985 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-2.full.stderr @@ -1,14 +1,5 @@ -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-67185-2.rs:1:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information - error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:15:1 + --> $DIR/issue-67185-2.rs:17:1 | LL | / trait Foo LL | | @@ -26,7 +17,7 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:15:1 + --> $DIR/issue-67185-2.rs:17:1 | LL | / trait Foo LL | | @@ -44,7 +35,7 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:25:6 + --> $DIR/issue-67185-2.rs:27:6 | LL | trait Foo | --- required by a bound in this @@ -60,7 +51,7 @@ LL | impl Foo for FooImpl {} <[u16; 4] as Bar> error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:25:6 + --> $DIR/issue-67185-2.rs:27:6 | LL | trait Foo | --- required by a bound in this @@ -76,7 +67,7 @@ LL | impl Foo for FooImpl {} <[u16; 4] as Bar> error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:29:14 + --> $DIR/issue-67185-2.rs:31:14 | LL | trait Foo | --- required by a bound in this @@ -92,7 +83,7 @@ LL | fn f(_: impl Foo) {} <[u16; 4] as Bar> error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:29:14 + --> $DIR/issue-67185-2.rs:31:14 | LL | trait Foo | --- required by a bound in this @@ -107,6 +98,6 @@ LL | fn f(_: impl Foo) {} <[[u16; 3]; 3] as Bar> <[u16; 4] as Bar> -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/issues/issue-67185-2.min.stderr b/src/test/ui/const-generics/issues/issue-67185-2.min.stderr new file mode 100644 index 0000000000000..78c7ebff05985 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-67185-2.min.stderr @@ -0,0 +1,103 @@ +error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:17:1 + | +LL | / trait Foo +LL | | +LL | | where +LL | | [::Quaks; 2]: Bar, +LL | | ::Quaks: Bar, +LL | | { +LL | | } + | |_^ the trait `Bar` is not implemented for `[u16; 3]` + | + = help: the following implementations were found: + <[[u16; 3]; 3] as Bar> + <[u16; 4] as Bar> + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:17:1 + | +LL | / trait Foo +LL | | +LL | | where +LL | | [::Quaks; 2]: Bar, +LL | | ::Quaks: Bar, +LL | | { +LL | | } + | |_^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` + | + = help: the following implementations were found: + <[[u16; 3]; 3] as Bar> + <[u16; 4] as Bar> + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:27:6 + | +LL | trait Foo + | --- required by a bound in this +... +LL | ::Quaks: Bar, + | --- required by this bound in `Foo` +... +LL | impl Foo for FooImpl {} + | ^^^ the trait `Bar` is not implemented for `[u16; 3]` + | + = help: the following implementations were found: + <[[u16; 3]; 3] as Bar> + <[u16; 4] as Bar> + +error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:27:6 + | +LL | trait Foo + | --- required by a bound in this +... +LL | [::Quaks; 2]: Bar, + | --- required by this bound in `Foo` +... +LL | impl Foo for FooImpl {} + | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` + | + = help: the following implementations were found: + <[[u16; 3]; 3] as Bar> + <[u16; 4] as Bar> + +error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:31:14 + | +LL | trait Foo + | --- required by a bound in this +... +LL | [::Quaks; 2]: Bar, + | --- required by this bound in `Foo` +... +LL | fn f(_: impl Foo) {} + | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` + | + = help: the following implementations were found: + <[[u16; 3]; 3] as Bar> + <[u16; 4] as Bar> + +error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:31:14 + | +LL | trait Foo + | --- required by a bound in this +... +LL | ::Quaks: Bar, + | --- required by this bound in `Foo` +... +LL | fn f(_: impl Foo) {} + | ^^^ the trait `Bar` is not implemented for `[u16; 3]` + | + = help: the following implementations were found: + <[[u16; 3]; 3] as Bar> + <[u16; 4] as Bar> + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/issues/issue-67185-2.rs b/src/test/ui/const-generics/issues/issue-67185-2.rs index 111b718dd5efd..1176d0c690403 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.rs +++ b/src/test/ui/const-generics/issues/issue-67185-2.rs @@ -1,5 +1,7 @@ -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] trait Baz { type Quaks; diff --git a/src/test/ui/const-generics/issues/issue-67739.stderr b/src/test/ui/const-generics/issues/issue-67739.full.stderr similarity index 100% rename from src/test/ui/const-generics/issues/issue-67739.stderr rename to src/test/ui/const-generics/issues/issue-67739.full.stderr diff --git a/src/test/ui/const-generics/issues/issue-67739.min.stderr b/src/test/ui/const-generics/issues/issue-67739.min.stderr new file mode 100644 index 0000000000000..1254ee7239dc7 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-67739.min.stderr @@ -0,0 +1,10 @@ +error: generic parameters must not be used inside of non trivial constant values + --> $DIR/issue-67739.rs:12:30 + | +LL | [0u8; mem::size_of::()]; + | ^^^^^^^^^^^^^^^^ non-trivial anonymous constants must not depend on the parameter `Self` + | + = help: it is currently only allowed to use either `Self` or `{ Self }` as generic constants + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/issues/issue-67739.rs b/src/test/ui/const-generics/issues/issue-67739.rs index c8ee182123985..72bf3ee9602fc 100644 --- a/src/test/ui/const-generics/issues/issue-67739.rs +++ b/src/test/ui/const-generics/issues/issue-67739.rs @@ -1,7 +1,7 @@ -// Regression test for #67739 - -#![allow(incomplete_features)] -#![feature(const_generics)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] use std::mem; @@ -10,7 +10,8 @@ pub trait Trait { fn associated_size(&self) -> usize { [0u8; mem::size_of::()]; - //~^ ERROR constant expression depends on a generic parameter + //[full]~^ ERROR constant expression depends on a generic parameter + //[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values 0 } } diff --git a/src/test/ui/const-generics/issues/issue-68366.stderr b/src/test/ui/const-generics/issues/issue-68366.full.stderr similarity index 93% rename from src/test/ui/const-generics/issues/issue-68366.stderr rename to src/test/ui/const-generics/issues/issue-68366.full.stderr index bba16f421535a..ac774f50c7493 100644 --- a/src/test/ui/const-generics/issues/issue-68366.stderr +++ b/src/test/ui/const-generics/issues/issue-68366.full.stderr @@ -1,5 +1,5 @@ error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:10:13 + --> $DIR/issue-68366.rs:12:13 | LL | impl Collatz<{Some(N)}> {} | ^ unconstrained const parameter @@ -8,7 +8,7 @@ LL | impl Collatz<{Some(N)}> {} = note: proving the result of expressions other than the parameter are unique is not supported error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:15:12 + --> $DIR/issue-68366.rs:18:12 | LL | impl Foo {} | ^ unconstrained const parameter diff --git a/src/test/ui/const-generics/issues/issue-68366.min.stderr b/src/test/ui/const-generics/issues/issue-68366.min.stderr new file mode 100644 index 0000000000000..8d34bdc6ea0c8 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-68366.min.stderr @@ -0,0 +1,29 @@ +error: generic parameters must not be used inside of non trivial constant values + --> $DIR/issue-68366.rs:12:37 + | +LL | impl Collatz<{Some(N)}> {} + | ^ non-trivial anonymous constants must not depend on the parameter `N` + | + = help: it is currently only allowed to use either `N` or `{ N }` as generic constants + +error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-68366.rs:12:13 + | +LL | impl Collatz<{Some(N)}> {} + | ^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-68366.rs:18:12 + | +LL | impl Foo {} + | ^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0207`. diff --git a/src/test/ui/const-generics/issues/issue-68366.rs b/src/test/ui/const-generics/issues/issue-68366.rs index a06b99d6645ec..819fcaffea18c 100644 --- a/src/test/ui/const-generics/issues/issue-68366.rs +++ b/src/test/ui/const-generics/issues/issue-68366.rs @@ -2,13 +2,16 @@ // The note should relate to the fact that it cannot be shown forall N that it maps 1-1 to a new // type. -#![feature(const_generics)] -#![allow(incomplete_features)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] struct Collatz>; impl Collatz<{Some(N)}> {} //~^ ERROR the const parameter +//[min]~^^ generic parameters must not be used inside of non trivial constant values struct Foo; diff --git a/src/test/ui/const-generics/issues/issue-72787.stderr b/src/test/ui/const-generics/issues/issue-72787.full.stderr similarity index 88% rename from src/test/ui/const-generics/issues/issue-72787.stderr rename to src/test/ui/const-generics/issues/issue-72787.full.stderr index ed892e46bbbed..29f975f566280 100644 --- a/src/test/ui/const-generics/issues/issue-72787.stderr +++ b/src/test/ui/const-generics/issues/issue-72787.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-72787.rs:9:32 + --> $DIR/issue-72787.rs:11:32 | LL | Condition<{ LHS <= RHS }>: True | ^^^^ @@ -7,7 +7,7 @@ LL | Condition<{ LHS <= RHS }>: True = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/issue-72787.rs:20:42 + --> $DIR/issue-72787.rs:27:42 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^^^^ @@ -15,7 +15,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/issue-72787.rs:20:42 + --> $DIR/issue-72787.rs:27:42 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^^^^ @@ -23,7 +23,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/issue-72787.rs:20:42 + --> $DIR/issue-72787.rs:27:42 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^^^^ @@ -31,7 +31,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/issue-72787.rs:20:42 + --> $DIR/issue-72787.rs:27:42 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^^^^ diff --git a/src/test/ui/const-generics/issues/issue-72787.min.stderr b/src/test/ui/const-generics/issues/issue-72787.min.stderr new file mode 100644 index 0000000000000..d2c512898fe88 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-72787.min.stderr @@ -0,0 +1,57 @@ +error: generic parameters must not be used inside of non trivial constant values + --> $DIR/issue-72787.rs:11:17 + | +LL | Condition<{ LHS <= RHS }>: True + | ^^^ non-trivial anonymous constants must not depend on the parameter `LHS` + | + = help: it is currently only allowed to use either `LHS` or `{ LHS }` as generic constants + +error: generic parameters must not be used inside of non trivial constant values + --> $DIR/issue-72787.rs:11:24 + | +LL | Condition<{ LHS <= RHS }>: True + | ^^^ non-trivial anonymous constants must not depend on the parameter `RHS` + | + = help: it is currently only allowed to use either `RHS` or `{ RHS }` as generic constants + +error: generic parameters must not be used inside of non trivial constant values + --> $DIR/issue-72787.rs:27:25 + | +LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, + | ^ non-trivial anonymous constants must not depend on the parameter `I` + | + = help: it is currently only allowed to use either `I` or `{ I }` as generic constants + +error: generic parameters must not be used inside of non trivial constant values + --> $DIR/issue-72787.rs:27:36 + | +LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, + | ^ non-trivial anonymous constants must not depend on the parameter `J` + | + = help: it is currently only allowed to use either `J` or `{ J }` as generic constants + +error[E0283]: type annotations needed + --> $DIR/issue-72787.rs:22:26 + | +LL | pub trait True {} + | -------------- required by this bound in `True` +... +LL | IsLessOrEqual: True, + | ^^^^ cannot infer type for struct `IsLessOrEqual` + | + = note: cannot satisfy `IsLessOrEqual: True` + +error[E0283]: type annotations needed + --> $DIR/issue-72787.rs:22:26 + | +LL | pub trait True {} + | -------------- required by this bound in `True` +... +LL | IsLessOrEqual: True, + | ^^^^ cannot infer type for struct `IsLessOrEqual` + | + = note: cannot satisfy `IsLessOrEqual: True` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/const-generics/issues/issue-72787.rs b/src/test/ui/const-generics/issues/issue-72787.rs index a368c226ec338..e95976b5f0229 100644 --- a/src/test/ui/const-generics/issues/issue-72787.rs +++ b/src/test/ui/const-generics/issues/issue-72787.rs @@ -1,5 +1,7 @@ -#![feature(const_generics)] -#![allow(incomplete_features)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] pub struct IsLessOrEqual; pub struct Condition; @@ -7,7 +9,9 @@ pub trait True {} impl True for IsLessOrEqual where Condition<{ LHS <= RHS }>: True -//~^ Error constant expression depends on a generic parameter +//[full]~^ Error constant expression depends on a generic parameter +//[min]~^^ Error generic parameters must not be used inside of non trivial constant values +//[min]~| Error generic parameters must not be used inside of non trivial constant values { } impl True for Condition {} @@ -16,12 +20,17 @@ struct S; impl S where IsLessOrEqual: True, +//[min]~^ Error type annotations needed [E0283] +//[min]~| Error type annotations needed [E0283] + // Condition<{ 8 - I <= 8 - J }>: True, IsLessOrEqual: True, IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, -//~^ Error constant expression depends on a generic parameter -//~| Error constant expression depends on a generic parameter -//~| Error constant expression depends on a generic parameter -//~| Error constant expression depends on a generic parameter +//[full]~^ constant expression depends on a generic parameter +//[full]~| constant expression depends on a generic parameter +//[full]~| constant expression depends on a generic parameter +//[full]~| constant expression depends on a generic parameter +//[min]~^^^^^ Error generic parameters must not be used inside of non trivial constant values +//[min]~| Error generic parameters must not be used inside of non trivial constant values // Condition<{ 8 - I <= 8 - J }>: True, { fn print() { diff --git a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.stderr b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.full.stderr similarity index 84% rename from src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.stderr rename to src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.full.stderr index a9f664d0ac8c5..e4105a3df1c88 100644 --- a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.stderr +++ b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-72819-generic-in-const-eval.rs:7:47 + --> $DIR/issue-72819-generic-in-const-eval.rs:9:47 | LL | where Assert::<{N < usize::max_value() / 2}>: IsTrue, | ^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr new file mode 100644 index 0000000000000..48a1f0bd19c0a --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr @@ -0,0 +1,10 @@ +error: generic parameters must not be used inside of non trivial constant values + --> $DIR/issue-72819-generic-in-const-eval.rs:9:17 + | +LL | where Assert::<{N < usize::max_value() / 2}>: IsTrue, + | ^ non-trivial anonymous constants must not depend on the parameter `N` + | + = help: it is currently only allowed to use either `N` or `{ N }` as generic constants + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs index 225593c3178a5..b653b91d99d14 100644 --- a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs +++ b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs @@ -1,11 +1,14 @@ // Regression test for #72819: ICE due to failure in resolving the const generic in `Arr`'s type // bounds. +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] -#![feature(const_generics)] -#![allow(incomplete_features)] struct Arr where Assert::<{N < usize::max_value() / 2}>: IsTrue, -//~^ ERROR constant expression depends on a generic parameter +//[full]~^ ERROR constant expression depends on a generic parameter +//[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values { } diff --git a/src/test/ui/const-generics/issues/issue-73120.rs b/src/test/ui/const-generics/issues/issue-73120.rs index aea4de39f79ce..c153a93cdef4f 100644 --- a/src/test/ui/const-generics/issues/issue-73120.rs +++ b/src/test/ui/const-generics/issues/issue-73120.rs @@ -1,3 +1,4 @@ +// revisions: full min // check-pass // aux-build:const_generic_issues_lib.rs extern crate const_generic_issues_lib as lib2; From 00e64ba476fa5bbc515bd6ff11151f8064748e88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 10 Sep 2020 00:00:00 +0000 Subject: [PATCH 02/18] Validate removal of AscribeUserType, FakeRead, and Shallow borrow Those statements are removed by CleanupNonCodegenStatements pass in drop lowering phase, and should not occur afterwards. --- compiler/rustc_mir/src/transform/validate.rs | 28 ++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir/src/transform/validate.rs b/compiler/rustc_mir/src/transform/validate.rs index 8f01e94280116..d3ca14abdcab2 100644 --- a/compiler/rustc_mir/src/transform/validate.rs +++ b/compiler/rustc_mir/src/transform/validate.rs @@ -4,8 +4,8 @@ use super::{MirPass, MirSource}; use rustc_middle::mir::visit::Visitor; use rustc_middle::{ mir::{ - AggregateKind, BasicBlock, Body, Location, MirPhase, Operand, Rvalue, Statement, - StatementKind, Terminator, TerminatorKind, + AggregateKind, BasicBlock, Body, BorrowKind, Location, MirPhase, Operand, Rvalue, + Statement, StatementKind, Terminator, TerminatorKind, }, ty::{ self, @@ -274,9 +274,33 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ) } } + Rvalue::Ref(_, BorrowKind::Shallow, _) => { + if self.mir_phase > MirPhase::DropLowering { + self.fail( + location, + "`Assign` statement with a `Shallow` borrow should have been removed after drop lowering phase", + ); + } + } _ => {} } } + StatementKind::AscribeUserType(..) => { + if self.mir_phase > MirPhase::DropLowering { + self.fail( + location, + "`AscribeUserType` should have been removed after drop lowering phase", + ); + } + } + StatementKind::FakeRead(..) => { + if self.mir_phase > MirPhase::DropLowering { + self.fail( + location, + "`FakeRead` should have been removed after drop lowering phase", + ); + } + } _ => {} } } From 01bf35010fb76154475fb722773731073fb50fa3 Mon Sep 17 00:00:00 2001 From: Andrew Lilley Brinker Date: Wed, 9 Sep 2020 19:36:15 -0700 Subject: [PATCH 03/18] Reword `trivial_casts` lint to better explain. The current description of the trivial casts lint under the "allowed by default" listing in the rustc book indicates the lint is for lints which may be removed, which is less clear than saying it's for lints which may be replaced by coercion (which is the wording used by the error message included in the doc). This commit changes the wording slightly to better describe what the lint does. --- src/doc/rustc/src/lints/listing/allowed-by-default.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc/src/lints/listing/allowed-by-default.md b/src/doc/rustc/src/lints/listing/allowed-by-default.md index d3dfc3197e2f6..d2d8c471efc96 100644 --- a/src/doc/rustc/src/lints/listing/allowed-by-default.md +++ b/src/doc/rustc/src/lints/listing/allowed-by-default.md @@ -232,7 +232,8 @@ error: lifetime name `'x` only used once ## trivial-casts -This lint detects trivial casts which could be removed. Some example code +This lint detects trivial casts which could be replaced with coercion, which may require +type ascription or a temporary variable. Some example code that triggers this lint: ```rust From 8667f93040cf539c469e3a64b9ed82c5f13bf938 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 10 Sep 2020 08:52:02 +0200 Subject: [PATCH 04/18] implement `const_evaluatable_checked` feature MVP --- compiler/rustc_feature/src/active.rs | 6 ++- compiler/rustc_span/src/symbol.rs | 1 + .../src/traits/const_evaluatable.rs | 51 +++++++++++++------ compiler/rustc_typeck/src/collect.rs | 46 ++++++++++++++++- .../const_evaluatable_checked/simple.rs | 14 +++++ .../const_evaluatable_checked/simple_fail.rs | 12 +++++ .../simple_fail.stderr | 9 ++++ 7 files changed, 122 insertions(+), 17 deletions(-) create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/simple.rs create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/simple_fail.stderr diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 3d7b3da45ccb9..d7adf1cdb6d24 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -585,6 +585,9 @@ declare_features! ( /// Allows `if let` guard in match arms. (active, if_let_guard, "1.47.0", Some(51114), None), + /// Allows non trivial generic constants which have to be manually propageted upwards. + (active, const_evaluatable_checked, "1.48.0", Some(0), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- @@ -600,6 +603,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::const_generics, sym::let_chains, sym::raw_dylib, + sym::const_evaluatable_checked, sym::const_trait_impl, sym::const_trait_bound_opt_out, sym::lazy_normalization_consts, @@ -607,6 +611,6 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ ]; /// Some features are not allowed to be used together at the same time, if -/// the two are present, produce an error +/// the two are present, produce an error. pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = &[(sym::const_generics, sym::min_const_generics)]; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5092b945f72c4..407663e57577a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -348,6 +348,7 @@ symbols! { const_compare_raw_pointers, const_constructor, const_eval_limit, + const_evaluatable_checked, const_extern_fn, const_fn, const_fn_transmute, diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 013cd71ea305d..74f7b1b352caf 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -14,6 +14,24 @@ pub fn is_const_evaluatable<'cx, 'tcx>( param_env: ty::ParamEnv<'tcx>, span: Span, ) -> Result<(), ErrorHandled> { + debug!("is_const_evaluatable({:?}, {:?})", def, substs); + if infcx.tcx.features().const_evaluatable_checked { + // FIXME(const_evaluatable_checked): Actually look into generic constants to + // implement const equality. + for pred in param_env.caller_bounds() { + match pred.skip_binders() { + ty::PredicateAtom::ConstEvaluatable(b_def, b_substs) => { + debug!("is_const_evaluatable: caller_bound={:?}, {:?}", b_def, b_substs); + if b_def == def && b_substs == substs { + debug!("is_const_evaluatable: caller_bound ~~> ok"); + return Ok(()); + } + } + _ => {} // don't care + } + } + } + let future_compat_lint = || { if let Some(local_def_id) = def.did.as_local() { infcx.tcx.struct_span_lint_hir( @@ -38,24 +56,27 @@ pub fn is_const_evaluatable<'cx, 'tcx>( // See #74595 for more details about this. let concrete = infcx.const_eval_resolve(param_env, def, substs, None, Some(span)); - let def_kind = infcx.tcx.def_kind(def.did); - match def_kind { - DefKind::AnonConst => { - let mir_body = if let Some(def) = def.as_const_arg() { - infcx.tcx.optimized_mir_of_const_arg(def) - } else { - infcx.tcx.optimized_mir(def.did) - }; - if mir_body.is_polymorphic && concrete.is_ok() { - future_compat_lint(); - } - } - _ => { - if substs.has_param_types_or_consts() && concrete.is_ok() { - future_compat_lint(); + if concrete.is_ok() && substs.has_param_types_or_consts() { + match infcx.tcx.def_kind(def.did) { + DefKind::AnonConst => { + let mir_body = if let Some(def) = def.as_const_arg() { + infcx.tcx.optimized_mir_of_const_arg(def) + } else { + infcx.tcx.optimized_mir(def.did) + }; + + if mir_body.is_polymorphic { + future_compat_lint(); + } } + _ => future_compat_lint(), } } + if concrete.is_ok() { + debug!("is_const_evaluatable: concrete ~~> ok"); + } else { + debug!("is_const_evaluatable: concrete ~~> err"); + } concrete.map(drop) } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index ea59375bad736..0bba8b821a70c 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -37,11 +37,12 @@ use rustc_middle::hir::map::Map; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::mono::Linkage; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::subst::InternalSubsts; +use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::util::Discr; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt}; use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness}; +use rustc_middle::ty::{TypeFoldable, TypeVisitor}; use rustc_session::config::SanitizerSet; use rustc_session::lint; use rustc_session::parse::feature_err; @@ -50,6 +51,8 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; +use smallvec::SmallVec; + mod type_of; struct OnlySelfBounds(bool); @@ -1672,10 +1675,51 @@ fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicate .alloc_from_iter(result.predicates.iter().chain(inferred_outlives).copied()); } } + + if tcx.features().const_evaluatable_checked { + let const_evaluatable = const_evaluatable_predicates_of(tcx, def_id, &result); + if result.predicates.is_empty() { + result.predicates = tcx.arena.alloc_from_iter(const_evaluatable); + } else { + result.predicates = tcx + .arena + .alloc_from_iter(result.predicates.iter().copied().chain(const_evaluatable)); + } + } + debug!("predicates_defined_on({:?}) = {:?}", def_id, result); result } +pub fn const_evaluatable_predicates_of<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + predicates: &ty::GenericPredicates<'tcx>, +) -> impl Iterator, Span)> { + #[derive(Default)] + struct ConstCollector<'tcx> { + ct: SmallVec<[(ty::WithOptConstParam, SubstsRef<'tcx>); 4]>, + } + + impl<'tcx> TypeVisitor<'tcx> for ConstCollector<'tcx> { + fn visit_const(&mut self, ct: &'tcx Const<'tcx>) -> bool { + if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val { + self.ct.push((def, substs)); + } + false + } + } + + let mut collector = ConstCollector::default(); + for (pred, _span) in predicates.predicates.iter() { + pred.visit_with(&mut collector); + } + warn!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.ct); + collector.ct.into_iter().map(move |(def_id, subst)| { + (ty::PredicateAtom::ConstEvaluatable(def_id, subst).to_predicate(tcx), DUMMY_SP) + }) +} + /// Returns a list of all type predicates (explicit and implicit) for the definition with /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus /// `Self: Trait` predicates for traits. diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple.rs b/src/test/ui/const-generics/const_evaluatable_checked/simple.rs new file mode 100644 index 0000000000000..a7ead78b97bae --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/simple.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +type Arr = [u8; N - 1]; + +fn test() -> Arr where Arr: Default { + Default::default() +} + +fn main() { + let x = test::<33>(); + assert_eq!(x, [0; 32]); +} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs new file mode 100644 index 0000000000000..1edf1885dd281 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs @@ -0,0 +1,12 @@ +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +type Arr = [u8; N - 1]; //~ ERROR evaluation of constant + +fn test() -> Arr where Arr: Sized { + todo!() +} + +fn main() { + test::<0>(); +} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.stderr b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.stderr new file mode 100644 index 0000000000000..1ac5e1d95537a --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/simple_fail.rs:4:33 + | +LL | type Arr = [u8; N - 1]; + | ^^^^^ attempt to compute `0_usize - 1_usize` which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. From 2815db1844824def6183ac2ec5b8ad82ce1888db Mon Sep 17 00:00:00 2001 From: Hameer Abbasi Date: Thu, 10 Sep 2020 09:04:14 +0200 Subject: [PATCH 05/18] Respond to review comments. --- ...-encountered-polymorphic-const.full.stderr | 10 ---- ...7-encountered-polymorphic-const.min.stderr | 10 ---- ...sue-62187-encountered-polymorphic-const.rs | 2 +- .../const-generics/issues/issue-62878.stderr | 46 ------------------- .../issues/issue-72787.full.stderr | 8 ++-- .../issues/issue-72787.min.stderr | 4 +- .../ui/const-generics/issues/issue-72787.rs | 1 - 7 files changed, 7 insertions(+), 74 deletions(-) delete mode 100644 src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.full.stderr delete mode 100644 src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.min.stderr delete mode 100644 src/test/ui/const-generics/issues/issue-62878.stderr diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.full.stderr b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.full.stderr deleted file mode 100644 index aada9c007256b..0000000000000 --- a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.full.stderr +++ /dev/null @@ -1,10 +0,0 @@ -warning: unused variable: `foo` - --> $DIR/issue-62187-encountered-polymorphic-const.rs:17:9 - | -LL | let foo = <[u8; 2]>::BIT_LEN; - | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` - | - = note: `#[warn(unused_variables)]` on by default - -warning: 1 warning emitted - diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.min.stderr b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.min.stderr deleted file mode 100644 index aada9c007256b..0000000000000 --- a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.min.stderr +++ /dev/null @@ -1,10 +0,0 @@ -warning: unused variable: `foo` - --> $DIR/issue-62187-encountered-polymorphic-const.rs:17:9 - | -LL | let foo = <[u8; 2]>::BIT_LEN; - | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` - | - = note: `#[warn(unused_variables)]` on by default - -warning: 1 warning emitted - diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs index 710fdbd9a11f3..a8fa378035660 100644 --- a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs +++ b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs @@ -14,5 +14,5 @@ impl BitLen for [u8; L] { } fn main() { - let foo = <[u8; 2]>::BIT_LEN; //~ WARN unused variable + let _foo = <[u8; 2]>::BIT_LEN; } diff --git a/src/test/ui/const-generics/issues/issue-62878.stderr b/src/test/ui/const-generics/issues/issue-62878.stderr deleted file mode 100644 index 8f7fe000a8116..0000000000000 --- a/src/test/ui/const-generics/issues/issue-62878.stderr +++ /dev/null @@ -1,46 +0,0 @@ -error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/issue-62878.rs:5:38 - | -LL | fn foo() {} - | ^ the type must not depend on the parameter `N` - -error[E0658]: const generics are unstable - --> $DIR/issue-62878.rs:5:14 - | -LL | fn foo() {} - | ^ - | - = note: see issue #74878 for more information - = help: add `#![feature(min_const_generics)]` to the crate attributes to enable - -error[E0658]: const generics are unstable - --> $DIR/issue-62878.rs:5:30 - | -LL | fn foo() {} - | ^ - | - = note: see issue #74878 for more information - = help: add `#![feature(min_const_generics)]` to the crate attributes to enable - -error[E0107]: wrong number of const arguments: expected 2, found 1 - --> $DIR/issue-62878.rs:11:5 - | -LL | foo::<_, {[1]}>(); - | ^^^^^^^^^^^^^^^ expected 2 const arguments - -error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/issue-62878.rs:11:11 - | -LL | foo::<_, {[1]}>(); - | ^ unexpected type argument - -error[E0308]: mismatched types - --> $DIR/issue-62878.rs:11:15 - | -LL | foo::<_, {[1]}>(); - | ^^^ expected `usize`, found array `[{integer}; 1]` - -error: aborting due to 6 previous errors - -Some errors have detailed explanations: E0107, E0308, E0658, E0770. -For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/const-generics/issues/issue-72787.full.stderr b/src/test/ui/const-generics/issues/issue-72787.full.stderr index 29f975f566280..b4c79d4171b7a 100644 --- a/src/test/ui/const-generics/issues/issue-72787.full.stderr +++ b/src/test/ui/const-generics/issues/issue-72787.full.stderr @@ -7,7 +7,7 @@ LL | Condition<{ LHS <= RHS }>: True = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/issue-72787.rs:27:42 + --> $DIR/issue-72787.rs:26:42 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^^^^ @@ -15,7 +15,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/issue-72787.rs:27:42 + --> $DIR/issue-72787.rs:26:42 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^^^^ @@ -23,7 +23,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/issue-72787.rs:27:42 + --> $DIR/issue-72787.rs:26:42 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^^^^ @@ -31,7 +31,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/issue-72787.rs:27:42 + --> $DIR/issue-72787.rs:26:42 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^^^^ diff --git a/src/test/ui/const-generics/issues/issue-72787.min.stderr b/src/test/ui/const-generics/issues/issue-72787.min.stderr index d2c512898fe88..d3e9887fe209c 100644 --- a/src/test/ui/const-generics/issues/issue-72787.min.stderr +++ b/src/test/ui/const-generics/issues/issue-72787.min.stderr @@ -15,7 +15,7 @@ LL | Condition<{ LHS <= RHS }>: True = help: it is currently only allowed to use either `RHS` or `{ RHS }` as generic constants error: generic parameters must not be used inside of non trivial constant values - --> $DIR/issue-72787.rs:27:25 + --> $DIR/issue-72787.rs:26:25 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^ non-trivial anonymous constants must not depend on the parameter `I` @@ -23,7 +23,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = help: it is currently only allowed to use either `I` or `{ I }` as generic constants error: generic parameters must not be used inside of non trivial constant values - --> $DIR/issue-72787.rs:27:36 + --> $DIR/issue-72787.rs:26:36 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^ non-trivial anonymous constants must not depend on the parameter `J` diff --git a/src/test/ui/const-generics/issues/issue-72787.rs b/src/test/ui/const-generics/issues/issue-72787.rs index e95976b5f0229..45c20191c8848 100644 --- a/src/test/ui/const-generics/issues/issue-72787.rs +++ b/src/test/ui/const-generics/issues/issue-72787.rs @@ -22,7 +22,6 @@ where IsLessOrEqual: True, //[min]~^ Error type annotations needed [E0283] //[min]~| Error type annotations needed [E0283] - // Condition<{ 8 - I <= 8 - J }>: True, IsLessOrEqual: True, IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, //[full]~^ constant expression depends on a generic parameter From 36903d79c8d61f1909bb430d9b09c2cb4a0d9db1 Mon Sep 17 00:00:00 2001 From: Hameer Abbasi Date: Thu, 10 Sep 2020 09:18:40 +0200 Subject: [PATCH 06/18] Add revisions to const generic default UI tests. --- .../defaults/complex-unord-param.min.stderr | 8 ++++++ .../defaults/complex-unord-param.rs | 10 ++++--- ...stderr => intermixed-lifetime.full.stderr} | 4 +-- .../defaults/intermixed-lifetime.min.stderr | 26 +++++++++++++++++++ .../defaults/intermixed-lifetime.rs | 12 ++++++--- .../defaults/simple-defaults.min.stderr | 8 ++++++ .../defaults/simple-defaults.rs | 9 ++++--- 7 files changed, 64 insertions(+), 13 deletions(-) create mode 100644 src/test/ui/const-generics/defaults/complex-unord-param.min.stderr rename src/test/ui/const-generics/defaults/{intermixed-lifetime.stderr => intermixed-lifetime.full.stderr} (87%) create mode 100644 src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr create mode 100644 src/test/ui/const-generics/defaults/simple-defaults.min.stderr diff --git a/src/test/ui/const-generics/defaults/complex-unord-param.min.stderr b/src/test/ui/const-generics/defaults/complex-unord-param.min.stderr new file mode 100644 index 0000000000000..0574ddfb2557a --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-unord-param.min.stderr @@ -0,0 +1,8 @@ +error: type parameters must be declared prior to const parameters + --> $DIR/complex-unord-param.rs:9:41 + | +LL | struct NestedArrays<'a, const N: usize, A: 'a, const M: usize, T:'a =u32> { + | ---------------------^----------------------^--------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, A: 'a, T: 'a, const N: usize, const M: usize>` + +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 index 72967640a8e62..e83a96388c190 100644 --- a/src/test/ui/const-generics/defaults/complex-unord-param.rs +++ b/src/test/ui/const-generics/defaults/complex-unord-param.rs @@ -1,11 +1,13 @@ -// run-pass +// [full] run-pass +// revisions: full min // Checks a complicated usage of unordered params - -#![feature(const_generics)] -#![allow(incomplete_features)] +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] #![allow(dead_code)] struct NestedArrays<'a, const N: usize, A: 'a, const M: usize, T:'a =u32> { + //[min]~^ ERROR type parameters must be declared prior to const parameters args: &'a [&'a [T; M]; N], specifier: A, } diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr similarity index 87% rename from src/test/ui/const-generics/defaults/intermixed-lifetime.stderr rename to src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr index 0f6d7f1065af8..9cc3e9c0da665 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.stderr +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr @@ -1,11 +1,11 @@ error: lifetime parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:6:28 + --> $DIR/intermixed-lifetime.rs:7:28 | LL | struct Foo(&'a (), T); | -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T>` error: lifetime parameters must be declared prior to type parameters - --> $DIR/intermixed-lifetime.rs:9:37 + --> $DIR/intermixed-lifetime.rs:11:37 | LL | struct Bar(&'a (), T); | --------------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T>` diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr new file mode 100644 index 0000000000000..4d80fdb5bcbc2 --- /dev/null +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr @@ -0,0 +1,26 @@ +error: lifetime parameters must be declared prior to const parameters + --> $DIR/intermixed-lifetime.rs:7:28 + | +LL | struct Foo(&'a (), T); + | -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>` + +error: type parameters must be declared prior to const parameters + --> $DIR/intermixed-lifetime.rs:7:32 + | +LL | struct Foo(&'a (), T); + | ---------------------^------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>` + +error: lifetime parameters must be declared prior to const parameters + --> $DIR/intermixed-lifetime.rs:11:37 + | +LL | struct Bar(&'a (), T); + | --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>` + +error: type parameters must be declared prior to const parameters + --> $DIR/intermixed-lifetime.rs:11:28 + | +LL | struct Bar(&'a (), T); + | -----------------^----------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>` + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs index ea3a8c14b98cb..cc0d1c6c0c97c 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs @@ -1,12 +1,16 @@ +// revisions: full min // Checks that lifetimes cannot be interspersed between consts and types. - -#![feature(const_generics)] -#![allow(incomplete_features)] +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] struct Foo(&'a (), T); //~^ Error lifetime parameters must be declared prior to const parameters +//[min]~^^ Error type parameters must be declared prior to const parameters struct Bar(&'a (), T); -//~^ Error lifetime parameters must be declared prior to type parameters +//[full]~^ Error lifetime parameters must be declared prior to type parameters +//[min]~^^ Error type parameters must be declared prior to const parameters +//[min]~| Error lifetime parameters must be declared prior to const parameters fn main() {} diff --git a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr b/src/test/ui/const-generics/defaults/simple-defaults.min.stderr new file mode 100644 index 0000000000000..59cc6f28af857 --- /dev/null +++ b/src/test/ui/const-generics/defaults/simple-defaults.min.stderr @@ -0,0 +1,8 @@ +error: type parameters must be declared prior to const parameters + --> $DIR/simple-defaults.rs:9:40 + | +LL | struct FixedOutput<'a, const N: usize, T=u32> { + | ---------------------^----- 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/simple-defaults.rs b/src/test/ui/const-generics/defaults/simple-defaults.rs index b282dfd37cc4a..78abe3519985b 100644 --- a/src/test/ui/const-generics/defaults/simple-defaults.rs +++ b/src/test/ui/const-generics/defaults/simple-defaults.rs @@ -1,10 +1,13 @@ -// run-pass +// [full] run-pass +// revisions: min full // Checks some basic test cases for defaults. -#![feature(const_generics)] -#![allow(incomplete_features)] +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] #![allow(dead_code)] struct FixedOutput<'a, const N: usize, T=u32> { + //[min]~^ ERROR type parameters must be declared prior to const parameters out: &'a [T; N], } From bec8e5fc145a2958c303fd276303f529e759b07c Mon Sep 17 00:00:00 2001 From: Hameer Abbasi Date: Thu, 10 Sep 2020 09:30:05 +0200 Subject: [PATCH 07/18] Add revisions to const generic UI tests. --- .../const-generics/auxiliary/const_generic_lib.rs | 4 +++- .../ui/const-generics/auxiliary/impl-const.rs | 4 +++- ...nst-argument-cross-crate-mismatch.full.stderr} | 4 ++-- ...const-argument-cross-crate-mismatch.min.stderr | 15 +++++++++++++++ .../const-argument-cross-crate-mismatch.rs | 1 + .../const-generics/const-argument-cross-crate.rs | 1 + 6 files changed, 25 insertions(+), 4 deletions(-) rename src/test/ui/const-generics/{const-argument-cross-crate-mismatch.stderr => const-argument-cross-crate-mismatch.full.stderr} (86%) create mode 100644 src/test/ui/const-generics/const-argument-cross-crate-mismatch.min.stderr diff --git a/src/test/ui/const-generics/auxiliary/const_generic_lib.rs b/src/test/ui/const-generics/auxiliary/const_generic_lib.rs index 901fb5dd054e2..899a5a1836c33 100644 --- a/src/test/ui/const-generics/auxiliary/const_generic_lib.rs +++ b/src/test/ui/const-generics/auxiliary/const_generic_lib.rs @@ -1,4 +1,6 @@ -#![feature(const_generics)] +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] pub struct Struct(pub [u8; N]); diff --git a/src/test/ui/const-generics/auxiliary/impl-const.rs b/src/test/ui/const-generics/auxiliary/impl-const.rs index fc993d63927c3..2e25dadf119c4 100644 --- a/src/test/ui/const-generics/auxiliary/impl-const.rs +++ b/src/test/ui/const-generics/auxiliary/impl-const.rs @@ -1,4 +1,6 @@ -#![feature(const_generics)] +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] pub struct Num; diff --git a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.full.stderr similarity index 86% rename from src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr rename to src/test/ui/const-generics/const-argument-cross-crate-mismatch.full.stderr index aefd514f7a68e..a35c3abc113b9 100644 --- a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr +++ b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.full.stderr @@ -1,11 +1,11 @@ error[E0308]: mismatched types - --> $DIR/const-argument-cross-crate-mismatch.rs:6:67 + --> $DIR/const-argument-cross-crate-mismatch.rs:7:67 | LL | let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8])); | ^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements error[E0308]: mismatched types - --> $DIR/const-argument-cross-crate-mismatch.rs:8:65 + --> $DIR/const-argument-cross-crate-mismatch.rs:9:65 | LL | let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]); | ^^^^^^^^^^^^^^^ expected an array with a fixed size of 2 elements, found one with 3 elements diff --git a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.min.stderr b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.min.stderr new file mode 100644 index 0000000000000..a35c3abc113b9 --- /dev/null +++ b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.min.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/const-argument-cross-crate-mismatch.rs:7:67 + | +LL | let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8])); + | ^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements + +error[E0308]: mismatched types + --> $DIR/const-argument-cross-crate-mismatch.rs:9:65 + | +LL | let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]); + | ^^^^^^^^^^^^^^^ expected an array with a fixed size of 2 elements, found one with 3 elements + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs index d863d097d5caf..9ae2ae50ba0ab 100644 --- a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs +++ b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs @@ -1,4 +1,5 @@ // aux-build:const_generic_lib.rs +// revisions: full min extern crate const_generic_lib; diff --git a/src/test/ui/const-generics/const-argument-cross-crate.rs b/src/test/ui/const-generics/const-argument-cross-crate.rs index 98cf39a7ee11c..fda3ec3eef799 100644 --- a/src/test/ui/const-generics/const-argument-cross-crate.rs +++ b/src/test/ui/const-generics/const-argument-cross-crate.rs @@ -1,4 +1,5 @@ // run-pass +// revisions: full min // aux-build:const_generic_lib.rs extern crate const_generic_lib; From 300b0acb85e41a19b518715147968f177679ebc1 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 10 Sep 2020 09:48:02 +0200 Subject: [PATCH 08/18] fix tidy, small cleanup --- compiler/rustc_feature/src/active.rs | 2 +- .../src/traits/const_evaluatable.rs | 6 +----- compiler/rustc_typeck/src/collect.rs | 9 ++------- .../feature-gate-const_evaluatable_checked.rs | 14 ++++++++++++++ .../feature-gate-const_evaluatable_checked.stderr | 10 ++++++++++ 5 files changed, 28 insertions(+), 13 deletions(-) create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.rs create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.stderr diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index d7adf1cdb6d24..1aeb0bd5ad9aa 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -586,7 +586,7 @@ declare_features! ( (active, if_let_guard, "1.47.0", Some(51114), None), /// Allows non trivial generic constants which have to be manually propageted upwards. - (active, const_evaluatable_checked, "1.48.0", Some(0), None), + (active, const_evaluatable_checked, "1.48.0", Some(76560), None), // ------------------------------------------------------------------------- // feature-group-end: actual feature gates diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 74f7b1b352caf..fdb87c085b54e 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -73,10 +73,6 @@ pub fn is_const_evaluatable<'cx, 'tcx>( } } - if concrete.is_ok() { - debug!("is_const_evaluatable: concrete ~~> ok"); - } else { - debug!("is_const_evaluatable: concrete ~~> err"); - } + debug!(?concrete, "is_const_evaluatable"); concrete.map(drop) } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 0bba8b821a70c..7d6b3df03b064 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1678,13 +1678,8 @@ fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicate if tcx.features().const_evaluatable_checked { let const_evaluatable = const_evaluatable_predicates_of(tcx, def_id, &result); - if result.predicates.is_empty() { - result.predicates = tcx.arena.alloc_from_iter(const_evaluatable); - } else { - result.predicates = tcx - .arena - .alloc_from_iter(result.predicates.iter().copied().chain(const_evaluatable)); - } + result.predicates = + tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(const_evaluatable)); } debug!("predicates_defined_on({:?}) = {:?}", def_id, result); diff --git a/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.rs b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.rs new file mode 100644 index 0000000000000..941bd5e9e5d0a --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.rs @@ -0,0 +1,14 @@ +#![feature(const_generics)] +#![allow(incomplete_features)] + +type Arr = [u8; N - 1]; + +fn test() -> Arr where Arr: Default { + //~^ ERROR constant expression depends + Default::default() +} + +fn main() { + let x = test::<33>(); + assert_eq!(x, [0; 32]); +} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.stderr b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.stderr new file mode 100644 index 0000000000000..6e4a22a38b17c --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.stderr @@ -0,0 +1,10 @@ +error: constant expression depends on a generic parameter + --> $DIR/feature-gate-const_evaluatable_checked.rs:6:30 + | +LL | fn test() -> Arr where Arr: Default { + | ^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error + From 8b059980d71765270b637b2fce7f13f728ca24b4 Mon Sep 17 00:00:00 2001 From: Nanami <12036195+yokodake@users.noreply.github.com> Date: Thu, 10 Sep 2020 11:56:11 +0200 Subject: [PATCH 09/18] small typo fix in rustc_parse docs --- compiler/rustc_parse/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 462279b0a9e03..8e1e4c1b4513b 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -109,7 +109,7 @@ pub fn maybe_new_parser_from_source_str( } /// Creates a new parser, handling errors as appropriate if the file doesn't exist. -/// If a span is given, that is used on an error as the as the source of the problem. +/// If a span is given, that is used on an error as the source of the problem. pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path, sp: Option) -> Parser<'a> { source_file_to_parser(sess, file_to_source_file(sess, path, sp)) } From 6bfe132067890abba67b6710060a88d4ad91abfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 10 Sep 2020 13:08:28 +0200 Subject: [PATCH 10/18] take reference to Place directly instead of taking reference to Box clippy::borrowed_box --- compiler/rustc_mir/src/transform/simplify_try.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/transform/simplify_try.rs b/compiler/rustc_mir/src/transform/simplify_try.rs index a7a3548189e1c..a320d00614d40 100644 --- a/compiler/rustc_mir/src/transform/simplify_try.rs +++ b/compiler/rustc_mir/src/transform/simplify_try.rs @@ -674,7 +674,7 @@ impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> { y_bb_idx: BasicBlock, ) -> StatementEquality { let helper = |rhs: &Rvalue<'tcx>, - place: &Box>, + place: &Place<'tcx>, variant_index: &VariantIdx, side_to_choose| { let place_type = place.ty(self.body, self.tcx).ty; From e2a511fe2059f7e64137aa893550b37195e96209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 10 Sep 2020 13:16:35 +0200 Subject: [PATCH 11/18] use String::from instead of format!() macro to craft string clippy::useless_format --- compiler/rustc_mir/src/transform/instrument_coverage.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/transform/instrument_coverage.rs b/compiler/rustc_mir/src/transform/instrument_coverage.rs index 8f43df8a6cbd1..a5b30a25a9bdf 100644 --- a/compiler/rustc_mir/src/transform/instrument_coverage.rs +++ b/compiler/rustc_mir/src/transform/instrument_coverage.rs @@ -353,7 +353,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { if !INCLUDE_COVERAGE_STATEMENTS { continue; } - format!("unreachable") + String::from("unreachable") } }, _ => format!("{:?}", statement), From e11c667e4af17ddebc47df803d6ea641cef7359b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 10 Sep 2020 13:20:33 +0200 Subject: [PATCH 12/18] don't clone types that are copy (clippy::clone_on_copy) --- compiler/rustc_infer/src/infer/lub.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index 3e2ea3d0f8fbf..9f43fac0916b5 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -50,7 +50,7 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b), ty::Covariant => self.relate(a, b), // FIXME(#41044) -- not correct, need test - ty::Bivariant => Ok(a.clone()), + ty::Bivariant => Ok(a), ty::Contravariant => self.fields.glb(self.a_is_expected).relate(a, b), } } From 9bb10cc90741fada64ec633122835cb821d0c89c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 10 Sep 2020 13:57:40 +0200 Subject: [PATCH 13/18] use push(char) instead of push_str(&str) to add single chars to strings clippy::single-char-push-str --- .../src/format_foreign.rs | 12 +++++----- compiler/rustc_codegen_ssa/src/back/link.rs | 2 +- .../src/debuginfo/type_names.rs | 2 +- .../src/infer/error_reporting/mod.rs | 2 +- .../src/borrow_check/diagnostics/mod.rs | 22 ++++++++++--------- .../src/borrow_check/region_infer/values.rs | 4 ++-- .../src/monomorphize/partitioning/mod.rs | 6 ++--- compiler/rustc_mir/src/util/pretty.rs | 2 +- compiler/rustc_save_analysis/src/lib.rs | 2 +- compiler/rustc_save_analysis/src/sig.rs | 2 +- compiler/rustc_session/src/config.rs | 4 ++-- 11 files changed, 31 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs index 85cf4c42e9435..b39423b86e7b5 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign.rs @@ -166,14 +166,14 @@ pub mod printf { let cap = self.span.len() + if has_options { 2 } else { 0 }; let mut s = String::with_capacity(cap); - s.push_str("{"); + s.push('{'); if let Some(arg) = self.parameter { write!(s, "{}", arg.checked_sub(1)?).ok()?; } if has_options { - s.push_str(":"); + s.push(':'); let align = if let Some(fill) = fill { s.push_str(fill); @@ -191,11 +191,11 @@ pub mod printf { } if alt { - s.push_str("#"); + s.push('#'); } if zero_fill { - s.push_str("0"); + s.push('0'); } if let Some(width) = width { @@ -203,7 +203,7 @@ pub mod printf { } if let Some(precision) = precision { - s.push_str("."); + s.push('.'); precision.translate(&mut s).ok()?; } @@ -212,7 +212,7 @@ pub mod printf { } } - s.push_str("}"); + s.push('}'); Some(s) } } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index c044020d9301b..faeb727202cd6 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1076,7 +1076,7 @@ fn exec_linker( } .to_string(), ); - args.push_str("\n"); + args.push('\n'); } let file = tmpdir.join("linker-arguments"); let bytes = if sess.target.target.options.is_like_msvc { diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 54e5d4d00f6e4..0c0f1bc681cf8 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -37,7 +37,7 @@ pub fn push_debuginfo_type_name<'tcx>( ty::Bool => output.push_str("bool"), ty::Char => output.push_str("char"), ty::Str => output.push_str("str"), - ty::Never => output.push_str("!"), + ty::Never => output.push('!'), ty::Int(int_ty) => output.push_str(int_ty.name_str()), ty::Uint(uint_ty) => output.push_str(uint_ty.name_str()), ty::Float(float_ty) => output.push_str(float_ty.name_str()), diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index b53605b0796c9..1225776db4590 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2093,7 +2093,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { _ => String::new(), }; if !s.is_empty() { - s.push_str(" "); + s.push(' '); } s }; diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs index f51bf7730ea09..3cee32834beb7 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs @@ -150,8 +150,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Some(mut descr) => { // Surround descr with `backticks`. descr.reserve(2); - descr.insert_str(0, "`"); - descr.push_str("`"); + descr.insert(0, '`'); + descr.push('`'); descr } None => "value".to_string(), @@ -222,7 +222,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if self.upvars[var_index].by_ref { buf.push_str(&name); } else { - buf.push_str(&format!("*{}", &name)); + buf.push('*'); + buf.push_str(&name); } } else { if autoderef { @@ -234,7 +235,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &including_downcast, )?; } else { - buf.push_str(&"*"); + buf.push('*'); self.append_place_to_string( PlaceRef { local, projection: proj_base }, buf, @@ -272,7 +273,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { autoderef, &including_downcast, )?; - buf.push_str(&format!(".{}", field_name)); + buf.push('.'); + buf.push_str(&field_name); } } ProjectionElem::Index(index) => { @@ -284,11 +286,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { autoderef, &including_downcast, )?; - buf.push_str("["); + buf.push('['); if self.append_local_to_string(*index, buf).is_err() { - buf.push_str("_"); + buf.push('_'); } - buf.push_str("]"); + buf.push(']'); } ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => { autoderef = true; @@ -301,7 +303,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { autoderef, &including_downcast, )?; - buf.push_str(&"[..]"); + buf.push_str("[..]"); } }; } @@ -648,7 +650,7 @@ impl UseSpans { " in closure".to_string() } } - _ => "".to_string(), + _ => String::new(), } } diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/values.rs b/compiler/rustc_mir/src/borrow_check/region_infer/values.rs index 8a5a600cfdd8a..f247d07e1f05e 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/values.rs +++ b/compiler/rustc_mir/src/borrow_check/region_infer/values.rs @@ -417,7 +417,7 @@ crate fn location_set_str( fn region_value_str(elements: impl IntoIterator) -> String { let mut result = String::new(); - result.push_str("{"); + result.push('{'); // Set to Some(l1, l2) when we have observed all the locations // from l1..=l2 (inclusive) but not yet printed them. This @@ -478,7 +478,7 @@ fn region_value_str(elements: impl IntoIterator) -> String push_location_range(&mut result, location1, location2); } - result.push_str("}"); + result.push('}'); return result; diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs b/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs index e96af77bbb8e0..0f6f078d9686f 100644 --- a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs +++ b/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs @@ -382,7 +382,7 @@ fn collect_and_partition_mono_items<'tcx>( cgus.sort_by_key(|(name, _)| *name); cgus.dedup(); for &(ref cgu_name, (linkage, _)) in cgus.iter() { - output.push_str(" "); + output.push(' '); output.push_str(&cgu_name.as_str()); let linkage_abbrev = match linkage { @@ -399,9 +399,9 @@ fn collect_and_partition_mono_items<'tcx>( Linkage::Common => "Common", }; - output.push_str("["); + output.push('['); output.push_str(linkage_abbrev); - output.push_str("]"); + output.push(']'); } output }) diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index 54bc248bc5b4a..75567181b6916 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -514,7 +514,7 @@ fn write_scope_tree( write!(indented_decl, " as {:?}", user_ty).unwrap(); } } - indented_decl.push_str(";"); + indented_decl.push(';'); let local_name = if local == RETURN_PLACE { " return place".to_string() } else { String::new() }; diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index c95e7e193be30..032d7cb3ed6b7 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -438,7 +438,7 @@ impl<'tcx> SaveContext<'tcx> { .next() .map(|item| item.def_id); } - qualname.push_str(">"); + qualname.push('>'); (qualname, trait_id, decl_id, docs, attrs) } diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index 6dd7f89d59486..747e198cd9324 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -497,7 +497,7 @@ impl<'hir> Sig for hir::Item<'hir> { sig.text.push_str(&bounds_to_string(bounds)); } // FIXME where clause - sig.text.push_str(";"); + sig.text.push(';'); Ok(sig) } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 19cd238599210..4aecb35294a07 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -581,9 +581,9 @@ impl OutputFilenames { if !ext.is_empty() { if !extension.is_empty() { - extension.push_str("."); + extension.push('.'); extension.push_str(RUST_CGU_EXT); - extension.push_str("."); + extension.push('.'); } extension.push_str(ext); From d7a97070517f20fa6533ff29fdc2945908fc58d7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 10 Sep 2020 14:11:25 +0200 Subject: [PATCH 14/18] Add missing examples on core traits' method --- library/core/src/ops/arith.rs | 77 +++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index 622a138abe9d1..bdf93baa1b8f9 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -78,6 +78,12 @@ pub trait Add { type Output; /// Performs the `+` operation. + /// + /// # Example + /// + /// ``` + /// assert_eq!(12 + 1, 13); + /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn add(self, rhs: Rhs) -> Self::Output; @@ -178,6 +184,12 @@ pub trait Sub { type Output; /// Performs the `-` operation. + /// + /// # Example + /// + /// ``` + /// assert_eq!(12 - 1, 11); + /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn sub(self, rhs: Rhs) -> Self::Output; @@ -300,6 +312,12 @@ pub trait Mul { type Output; /// Performs the `*` operation. + /// + /// # Example + /// + /// ``` + /// assert_eq!(12 * 2, 24); + /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn mul(self, rhs: Rhs) -> Self::Output; @@ -426,6 +444,12 @@ pub trait Div { type Output; /// Performs the `/` operation. + /// + /// # Example + /// + /// ``` + /// assert_eq!(12 / 2, 6); + /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn div(self, rhs: Rhs) -> Self::Output; @@ -513,6 +537,12 @@ pub trait Rem { type Output; /// Performs the `%` operation. + /// + /// # Example + /// + /// ``` + /// assert_eq!(12 % 10, 2); + /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn rem(self, rhs: Rhs) -> Self::Output; @@ -612,6 +642,13 @@ pub trait Neg { type Output; /// Performs the unary `-` operation. + /// + /// # Example + /// + /// ``` + /// let x: i32 = 12; + /// assert_eq!(-x, -12); + /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn neg(self) -> Self::Output; @@ -673,6 +710,14 @@ neg_impl! { isize i8 i16 i32 i64 i128 f32 f64 } #[doc(alias = "+=")] pub trait AddAssign { /// Performs the `+=` operation. + /// + /// # Example + /// + /// ``` + /// let mut x: u32 = 12; + /// x += 1; + /// assert_eq!(x, 13); + /// ``` #[stable(feature = "op_assign_traits", since = "1.8.0")] fn add_assign(&mut self, rhs: Rhs); } @@ -731,6 +776,14 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } #[doc(alias = "-=")] pub trait SubAssign { /// Performs the `-=` operation. + /// + /// # Example + /// + /// ``` + /// let mut x: u32 = 12; + /// x -= 1; + /// assert_eq!(x, 11); + /// ``` #[stable(feature = "op_assign_traits", since = "1.8.0")] fn sub_assign(&mut self, rhs: Rhs); } @@ -780,6 +833,14 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } #[doc(alias = "*=")] pub trait MulAssign { /// Performs the `*=` operation. + /// + /// # Example + /// + /// ``` + /// let mut x: u32 = 12; + /// x *= 2; + /// assert_eq!(x, 24); + /// ``` #[stable(feature = "op_assign_traits", since = "1.8.0")] fn mul_assign(&mut self, rhs: Rhs); } @@ -829,6 +890,14 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } #[doc(alias = "/=")] pub trait DivAssign { /// Performs the `/=` operation. + /// + /// # Example + /// + /// ``` + /// let mut x: u32 = 12; + /// x /= 2; + /// assert_eq!(x, 6); + /// ``` #[stable(feature = "op_assign_traits", since = "1.8.0")] fn div_assign(&mut self, rhs: Rhs); } @@ -881,6 +950,14 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } #[doc(alias = "%=")] pub trait RemAssign { /// Performs the `%=` operation. + /// + /// # Example + /// + /// ``` + /// let mut x: u32 = 12; + /// x %= 10; + /// assert_eq!(x, 2); + /// ``` #[stable(feature = "op_assign_traits", since = "1.8.0")] fn rem_assign(&mut self, rhs: Rhs); } From fd4dd00ddef578aa01744e4146c1dfe3fbca4866 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 23 Aug 2020 03:42:19 -0700 Subject: [PATCH 15/18] Syntactically permit unsafety on mods --- compiler/rustc_ast/src/ast.rs | 10 ++- compiler/rustc_ast/src/mut_visit.rs | 7 +- .../rustc_ast_passes/src/ast_validation.rs | 10 ++- compiler/rustc_ast_pretty/src/pprust.rs | 11 ++- compiler/rustc_expand/src/config.rs | 2 +- compiler/rustc_expand/src/expand.rs | 27 ++++-- compiler/rustc_expand/src/module.rs | 12 ++- compiler/rustc_parse/src/parser/item.rs | 67 ++++++++++---- .../ast-json/ast-json-noexpand-output.stdout | 2 +- src/test/ui/ast-json/ast-json-output.stdout | 2 +- src/test/ui/parser/unsafe-foreign-mod.rs | 9 ++ src/test/ui/parser/unsafe-foreign-mod.stderr | 14 +++ src/test/ui/parser/unsafe-mod.rs | 9 ++ src/test/ui/parser/unsafe-mod.stderr | 23 +++++ .../proc-macro/auxiliary/macro-only-syntax.rs | 89 +++++++++++++++++++ src/test/ui/proc-macro/unsafe-foreign-mod.rs | 14 +++ src/test/ui/proc-macro/unsafe-mod.rs | 13 +++ 17 files changed, 284 insertions(+), 37 deletions(-) create mode 100644 src/test/ui/parser/unsafe-foreign-mod.rs create mode 100644 src/test/ui/parser/unsafe-foreign-mod.stderr create mode 100644 src/test/ui/parser/unsafe-mod.rs create mode 100644 src/test/ui/parser/unsafe-mod.stderr create mode 100644 src/test/ui/proc-macro/auxiliary/macro-only-syntax.rs create mode 100644 src/test/ui/proc-macro/unsafe-foreign-mod.rs create mode 100644 src/test/ui/proc-macro/unsafe-mod.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 49aa1fc17357e..b9f380dc4e835 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2289,12 +2289,15 @@ impl FnRetTy { /// Module declaration. /// /// E.g., `mod foo;` or `mod foo { .. }`. -#[derive(Clone, Encodable, Decodable, Debug, Default)] +#[derive(Clone, Encodable, Decodable, Debug)] pub struct Mod { /// A span from the first token past `{` to the last token until `}`. /// For `mod foo;`, the inner span ranges from the first token /// to the last token in the external file. pub inner: Span, + /// `unsafe` keyword accepted syntactically for macro DSLs, but not + /// semantically by Rust. + pub unsafety: Unsafe, pub items: Vec>, /// `true` for `mod foo { .. }`; `false` for `mod foo;`. pub inline: bool, @@ -2302,9 +2305,12 @@ pub struct Mod { /// Foreign module declaration. /// -/// E.g., `extern { .. }` or `extern C { .. }`. +/// E.g., `extern { .. }` or `extern "C" { .. }`. #[derive(Clone, Encodable, Decodable, Debug)] pub struct ForeignMod { + /// `unsafe` keyword accepted syntactically for macro DSLs, but not + /// semantically by Rust. + pub unsafety: Unsafe, pub abi: Option, pub items: Vec>, } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 3ef83ef3fc973..3119c5e0a12fa 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -490,7 +490,7 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { } pub fn noop_visit_foreign_mod(foreign_mod: &mut ForeignMod, vis: &mut T) { - let ForeignMod { abi: _, items } = foreign_mod; + let ForeignMod { unsafety: _, abi: _, items } = foreign_mod; items.flat_map_in_place(|item| vis.flat_map_foreign_item(item)); } @@ -970,7 +970,8 @@ pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) { vis.visit_asyncness(asyncness); } -pub fn noop_visit_mod(Mod { inner, items, inline: _ }: &mut Mod, vis: &mut T) { +pub fn noop_visit_mod(module: &mut Mod, vis: &mut T) { + let Mod { inner, unsafety: _, items, inline: _ } = module; vis.visit_span(inner); items.flat_map_in_place(|item| vis.flat_map_item(item)); } @@ -990,7 +991,7 @@ pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) { let len = items.len(); if len == 0 { - let module = Mod { inner: span, items: vec![], inline: true }; + let module = Mod { inner: span, unsafety: Unsafe::No, items: vec![], inline: true }; Crate { module, attrs: vec![], span, proc_macros } } else if len == 1 { let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner(); diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index a01dd8c939cf6..998acf4fd10cb 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -990,12 +990,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.error_item_without_body(item.span, "function", msg, " { }"); } } - ItemKind::ForeignMod(_) => { + ItemKind::ForeignMod(ForeignMod { unsafety, .. }) => { let old_item = mem::replace(&mut self.extern_mod, Some(item)); self.invalid_visibility( &item.vis, Some("place qualifiers on individual foreign items instead"), ); + if let Unsafe::Yes(span) = unsafety { + self.err_handler().span_err(span, "extern block cannot be declared unsafe"); + } visit::walk_item(self, item); self.extern_mod = old_item; return; // Avoid visiting again. @@ -1029,7 +1032,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(self, visit_attribute, &item.attrs); return; } - ItemKind::Mod(Mod { inline, .. }) => { + ItemKind::Mod(Mod { inline, unsafety, .. }) => { + if let Unsafe::Yes(span) = unsafety { + self.err_handler().span_err(span, "module cannot be declared unsafe"); + } // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584). if !inline && !self.session.contains_name(&item.attrs, sym::path) { self.check_mod_file_item_asciionly(item.ident); diff --git a/compiler/rustc_ast_pretty/src/pprust.rs b/compiler/rustc_ast_pretty/src/pprust.rs index 9743a00042969..955d1677647ec 100644 --- a/compiler/rustc_ast_pretty/src/pprust.rs +++ b/compiler/rustc_ast_pretty/src/pprust.rs @@ -1139,7 +1139,11 @@ impl<'a> State<'a> { self.print_fn_full(sig, item.ident, gen, &item.vis, def, body, &item.attrs); } ast::ItemKind::Mod(ref _mod) => { - self.head(visibility_qualified(&item.vis, "mod")); + self.head(to_string(|s| { + s.print_visibility(&item.vis); + s.print_unsafety(_mod.unsafety); + s.word("mod"); + })); self.print_ident(item.ident); if _mod.inline || self.is_expanded { @@ -1154,7 +1158,10 @@ impl<'a> State<'a> { } } ast::ItemKind::ForeignMod(ref nmod) => { - self.head("extern"); + self.head(to_string(|s| { + s.print_unsafety(nmod.unsafety); + s.word("extern"); + })); if let Some(abi) = nmod.abi { self.print_literal(&abi.as_lit()); self.nbsp(); diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 97608a389035b..dd087ab91509b 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -399,7 +399,7 @@ impl<'a> StripUnconfigured<'a> { } pub fn configure_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) { - let ast::ForeignMod { abi: _, items } = foreign_mod; + let ast::ForeignMod { unsafety: _, abi: _, items } = foreign_mod; items.flat_map_in_place(|item| self.configure(item)); } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index ca6f7324ca40f..241566a042a0e 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -13,7 +13,7 @@ use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast::{self as ast, AttrItem, Block, LitKind, NodeId, PatKind, Path}; -use rustc_ast::{ItemKind, MacArgs, MacCallStmt, MacStmtStyle, StmtKind}; +use rustc_ast::{ItemKind, MacArgs, MacCallStmt, MacStmtStyle, StmtKind, Unsafe}; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; use rustc_data_structures::map_in_place::MapInPlace; @@ -370,11 +370,21 @@ impl<'a, 'b> MacroExpander<'a, 'b> { None => { // Resolution failed so we return an empty expansion krate.attrs = vec![]; - krate.module = ast::Mod { inner: orig_mod_span, items: vec![], inline: true }; + krate.module = ast::Mod { + inner: orig_mod_span, + unsafety: Unsafe::No, + items: vec![], + inline: true, + }; } Some(ast::Item { span, kind, .. }) => { krate.attrs = vec![]; - krate.module = ast::Mod { inner: orig_mod_span, items: vec![], inline: true }; + krate.module = ast::Mod { + inner: orig_mod_span, + unsafety: Unsafe::No, + items: vec![], + inline: true, + }; self.cx.span_err( span, &format!( @@ -1441,8 +1451,15 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { push_directory(&self.cx.sess, ident, &item.attrs, dir) } else { // We have an outline `mod foo;` so we need to parse the file. - let (new_mod, dir) = - parse_external_mod(&self.cx.sess, ident, span, dir, &mut attrs, pushed); + let (new_mod, dir) = parse_external_mod( + &self.cx.sess, + ident, + span, + old_mod.unsafety, + dir, + &mut attrs, + pushed, + ); let krate = ast::Crate { span: new_mod.inner, diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index fefc0bdeb7cc2..171cb3fa8e6e9 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -1,4 +1,4 @@ -use rustc_ast::{token, Attribute, Mod}; +use rustc_ast::{token, Attribute, Mod, Unsafe}; use rustc_errors::{struct_span_err, PResult}; use rustc_parse::new_parser_from_file; use rustc_session::parse::ParseSess; @@ -42,6 +42,7 @@ crate fn parse_external_mod( sess: &Session, id: Ident, span: Span, // The span to blame on errors. + unsafety: Unsafe, Directory { mut ownership, path }: Directory, attrs: &mut Vec, pop_mod_stack: &mut bool, @@ -60,13 +61,16 @@ crate fn parse_external_mod( drop(included_mod_stack); // Actually parse the external file as a module. - let mut module = - new_parser_from_file(&sess.parse_sess, &mp.path, Some(span)).parse_mod(&token::Eof)?; + let mut parser = new_parser_from_file(&sess.parse_sess, &mp.path, Some(span)); + let mut module = parser.parse_mod(&token::Eof, unsafety)?; module.0.inline = false; module }; // (1) ...instead, we return a dummy module. - let (module, mut new_attrs) = result.map_err(|mut err| err.emit()).unwrap_or_default(); + let (module, mut new_attrs) = result.map_err(|mut err| err.emit()).unwrap_or_else(|_| { + let module = Mod { inner: Span::default(), unsafety, items: Vec::new(), inline: false }; + (module, Vec::new()) + }); attrs.append(&mut new_attrs); // Extract the directory path for submodules of `module`. diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 9143af651df2d..1a428f8bb0ab5 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -28,7 +28,7 @@ impl<'a> Parser<'a> { /// Parses a source module as a crate. This is the main entry point for the parser. pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> { let lo = self.token.span; - let (module, attrs) = self.parse_mod(&token::Eof)?; + let (module, attrs) = self.parse_mod(&token::Eof, Unsafe::No)?; let span = lo.to(self.token.span); let proc_macros = Vec::new(); // Filled in by `proc_macro_harness::inject()`. Ok(ast::Crate { attrs, module, span, proc_macros }) @@ -36,27 +36,38 @@ impl<'a> Parser<'a> { /// Parses a `mod { ... }` or `mod ;` item. fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { + let unsafety = self.parse_unsafety(); + self.expect_keyword(kw::Mod)?; let id = self.parse_ident()?; let (module, mut inner_attrs) = if self.eat(&token::Semi) { - Default::default() + (Mod { inner: Span::default(), unsafety, items: Vec::new(), inline: false }, Vec::new()) } else { self.expect(&token::OpenDelim(token::Brace))?; - self.parse_mod(&token::CloseDelim(token::Brace))? + self.parse_mod(&token::CloseDelim(token::Brace), unsafety)? }; attrs.append(&mut inner_attrs); Ok((id, ItemKind::Mod(module))) } /// Parses the contents of a module (inner attributes followed by module items). - pub fn parse_mod(&mut self, term: &TokenKind) -> PResult<'a, (Mod, Vec)> { + pub fn parse_mod( + &mut self, + term: &TokenKind, + unsafety: Unsafe, + ) -> PResult<'a, (Mod, Vec)> { let lo = self.token.span; let attrs = self.parse_inner_attributes()?; - let module = self.parse_mod_items(term, lo)?; + let module = self.parse_mod_items(term, lo, unsafety)?; Ok((module, attrs)) } /// Given a termination token, parses all of the items in a module. - fn parse_mod_items(&mut self, term: &TokenKind, inner_lo: Span) -> PResult<'a, Mod> { + fn parse_mod_items( + &mut self, + term: &TokenKind, + inner_lo: Span, + unsafety: Unsafe, + ) -> PResult<'a, Mod> { let mut items = vec![]; while let Some(item) = self.parse_item()? { items.push(item); @@ -75,7 +86,7 @@ impl<'a> Parser<'a> { let hi = if self.token.span.is_dummy() { inner_lo } else { self.prev_token.span }; - Ok(Mod { inner: inner_lo.to(hi), items, inline: true }) + Ok(Mod { inner: inner_lo.to(hi), unsafety, items, inline: true }) } } @@ -235,8 +246,13 @@ impl<'a> Parser<'a> { self.parse_item_extern_crate()? } else { // EXTERN BLOCK - self.parse_item_foreign_mod(attrs)? + self.parse_item_foreign_mod(attrs, Unsafe::No)? } + } else if self.is_unsafe_foreign_mod() { + // EXTERN BLOCK + let unsafety = self.parse_unsafety(); + self.expect_keyword(kw::Extern)?; + self.parse_item_foreign_mod(attrs, unsafety)? } else if self.is_static_global() { // STATIC ITEM self.bump(); // `static` @@ -256,7 +272,9 @@ impl<'a> Parser<'a> { { // IMPL ITEM self.parse_item_impl(attrs, def())? - } else if self.eat_keyword(kw::Mod) { + } else if self.check_keyword(kw::Mod) + || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Mod]) + { // MODULE ITEM self.parse_item_mod(attrs)? } else if self.eat_keyword(kw::Type) { @@ -893,10 +911,14 @@ impl<'a> Parser<'a> { /// extern "C" {} /// extern {} /// ``` - fn parse_item_foreign_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { + fn parse_item_foreign_mod( + &mut self, + attrs: &mut Vec, + unsafety: Unsafe, + ) -> PResult<'a, ItemInfo> { let abi = self.parse_abi(); // ABI? let items = self.parse_item_list(attrs, |p| p.parse_foreign_item())?; - let module = ast::ForeignMod { abi, items }; + let module = ast::ForeignMod { unsafety, abi, items }; Ok((Ident::invalid(), ItemKind::ForeignMod(module))) } @@ -938,6 +960,15 @@ impl<'a> Parser<'a> { .emit(); } + fn is_unsafe_foreign_mod(&self) -> bool { + self.token.is_keyword(kw::Unsafe) + && self.is_keyword_ahead(1, &[kw::Extern]) + && self.look_ahead( + 2 + self.look_ahead(2, |t| t.can_begin_literal_maybe_minus() as usize), + |t| t.kind == token::OpenDelim(token::Brace), + ) + } + fn is_static_global(&mut self) -> bool { if self.check_keyword(kw::Static) { // Check if this could be a closure. @@ -1552,10 +1583,14 @@ impl<'a> Parser<'a> { // `$qual fn` or `$qual $qual`: || QUALS.iter().any(|&kw| self.check_keyword(kw)) && self.look_ahead(1, |t| { - // ...qualified and then `fn`, e.g. `const fn`. + // `$qual fn`, e.g. `const fn` or `async fn`. t.is_keyword(kw::Fn) - // Two qualifiers. This is enough. Due `async` we need to check that it's reserved. - || t.is_non_raw_ident_where(|i| QUALS.contains(&i.name) && i.is_reserved()) + // Two qualifiers `$qual $qual` is enough, e.g. `async unsafe`. + || t.is_non_raw_ident_where(|i| QUALS.contains(&i.name) + // Rule out 2015 `const async: T = val`. + && i.is_reserved() + // Rule out unsafe extern block. + && !self.is_unsafe_foreign_mod()) }) // `extern ABI fn` || self.check_keyword(kw::Extern) @@ -1567,9 +1602,9 @@ impl<'a> Parser<'a> { /// up to and including the `fn` keyword. The formal grammar is: /// /// ``` - /// Extern = "extern" StringLit ; + /// Extern = "extern" StringLit? ; /// FnQual = "const"? "async"? "unsafe"? Extern? ; - /// FnFrontMatter = FnQual? "fn" ; + /// FnFrontMatter = FnQual "fn" ; /// ``` pub(super) fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> { let constness = self.parse_constness(); diff --git a/src/test/ui/ast-json/ast-json-noexpand-output.stdout b/src/test/ui/ast-json/ast-json-noexpand-output.stdout index 031c0d0cae51c..0e5a3a14ac7b5 100644 --- a/src/test/ui/ast-json/ast-json-noexpand-output.stdout +++ b/src/test/ui/ast-json/ast-json-noexpand-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} +{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout index 9b3b6870cbe7e..8752ed2ae9993 100644 --- a/src/test/ui/ast-json/ast-json-output.stdout +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} +{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} diff --git a/src/test/ui/parser/unsafe-foreign-mod.rs b/src/test/ui/parser/unsafe-foreign-mod.rs new file mode 100644 index 0000000000000..872af95bd225b --- /dev/null +++ b/src/test/ui/parser/unsafe-foreign-mod.rs @@ -0,0 +1,9 @@ +unsafe extern { + //~^ ERROR extern block cannot be declared unsafe +} + +unsafe extern "C" { + //~^ ERROR extern block cannot be declared unsafe +} + +fn main() {} diff --git a/src/test/ui/parser/unsafe-foreign-mod.stderr b/src/test/ui/parser/unsafe-foreign-mod.stderr new file mode 100644 index 0000000000000..5e10988051ea0 --- /dev/null +++ b/src/test/ui/parser/unsafe-foreign-mod.stderr @@ -0,0 +1,14 @@ +error: extern block cannot be declared unsafe + --> $DIR/unsafe-foreign-mod.rs:1:1 + | +LL | unsafe extern { + | ^^^^^^ + +error: extern block cannot be declared unsafe + --> $DIR/unsafe-foreign-mod.rs:5:1 + | +LL | unsafe extern "C" { + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/unsafe-mod.rs b/src/test/ui/parser/unsafe-mod.rs new file mode 100644 index 0000000000000..7916d878ea585 --- /dev/null +++ b/src/test/ui/parser/unsafe-mod.rs @@ -0,0 +1,9 @@ +unsafe mod m { + //~^ ERROR module cannot be declared unsafe +} + +unsafe mod n; +//~^ ERROR module cannot be declared unsafe +//~^^ ERROR file not found for module `n` + +fn main() {} diff --git a/src/test/ui/parser/unsafe-mod.stderr b/src/test/ui/parser/unsafe-mod.stderr new file mode 100644 index 0000000000000..259b2c1d61e08 --- /dev/null +++ b/src/test/ui/parser/unsafe-mod.stderr @@ -0,0 +1,23 @@ +error[E0583]: file not found for module `n` + --> $DIR/unsafe-mod.rs:5:1 + | +LL | unsafe mod n; + | ^^^^^^^^^^^^^ + | + = help: to create the module `n`, create file "$DIR/n.rs" + +error: module cannot be declared unsafe + --> $DIR/unsafe-mod.rs:1:1 + | +LL | unsafe mod m { + | ^^^^^^ + +error: module cannot be declared unsafe + --> $DIR/unsafe-mod.rs:5:1 + | +LL | unsafe mod n; + | ^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0583`. diff --git a/src/test/ui/proc-macro/auxiliary/macro-only-syntax.rs b/src/test/ui/proc-macro/auxiliary/macro-only-syntax.rs new file mode 100644 index 0000000000000..c72306c3d50b3 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/macro-only-syntax.rs @@ -0,0 +1,89 @@ +// force-host +// no-prefer-dynamic + +// These are tests for syntax that is accepted by the Rust parser but +// unconditionally rejected semantically after macro expansion. Attribute macros +// are permitted to accept such syntax as long as they replace it with something +// that makes sense to Rust. +// +// We also inspect some of the spans to verify the syntax is not triggering the +// lossy string reparse hack (https://github.com/rust-lang/rust/issues/43081). + +#![crate_type = "proc-macro"] +#![feature(proc_macro_span)] + +extern crate proc_macro; +use proc_macro::{token_stream, Delimiter, TokenStream, TokenTree}; +use std::path::Component; + +// unsafe mod m { +// pub unsafe mod inner; +// } +#[proc_macro_attribute] +pub fn expect_unsafe_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream { + let tokens = &mut input.into_iter(); + expect(tokens, "unsafe"); + expect(tokens, "mod"); + expect(tokens, "m"); + let tokens = &mut expect_brace(tokens); + expect(tokens, "pub"); + expect(tokens, "unsafe"); + expect(tokens, "mod"); + let ident = expect(tokens, "inner"); + expect(tokens, ";"); + check_useful_span(ident, "unsafe-mod.rs"); + TokenStream::new() +} + +// unsafe extern { +// type T; +// } +#[proc_macro_attribute] +pub fn expect_unsafe_foreign_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream { + let tokens = &mut input.into_iter(); + expect(tokens, "unsafe"); + expect(tokens, "extern"); + let tokens = &mut expect_brace(tokens); + expect(tokens, "type"); + let ident = expect(tokens, "T"); + expect(tokens, ";"); + check_useful_span(ident, "unsafe-foreign-mod.rs"); + TokenStream::new() +} + +// unsafe extern "C++" {} +#[proc_macro_attribute] +pub fn expect_unsafe_extern_cpp_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream { + let tokens = &mut input.into_iter(); + expect(tokens, "unsafe"); + expect(tokens, "extern"); + let abi = expect(tokens, "\"C++\""); + expect_brace(tokens); + check_useful_span(abi, "unsafe-foreign-mod.rs"); + TokenStream::new() +} + +fn expect(tokens: &mut token_stream::IntoIter, expected: &str) -> TokenTree { + match tokens.next() { + Some(token) if token.to_string() == expected => token, + wrong => panic!("unexpected token: {:?}, expected `{}`", wrong, expected), + } +} + +fn expect_brace(tokens: &mut token_stream::IntoIter) -> token_stream::IntoIter { + match tokens.next() { + Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Brace => { + group.stream().into_iter() + } + wrong => panic!("unexpected token: {:?}, expected `{{`", wrong), + } +} + +fn check_useful_span(token: TokenTree, expected_filename: &str) { + let span = token.span(); + assert!(span.start().column < span.end().column); + + let source_path = span.source_file().path(); + let filename = source_path.components().last().unwrap(); + assert_eq!(filename, Component::Normal(expected_filename.as_ref())); +} diff --git a/src/test/ui/proc-macro/unsafe-foreign-mod.rs b/src/test/ui/proc-macro/unsafe-foreign-mod.rs new file mode 100644 index 0000000000000..7bdfa93c21fc7 --- /dev/null +++ b/src/test/ui/proc-macro/unsafe-foreign-mod.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:macro-only-syntax.rs + +extern crate macro_only_syntax; + +#[macro_only_syntax::expect_unsafe_foreign_mod] +unsafe extern { + type T; +} + +#[macro_only_syntax::expect_unsafe_extern_cpp_mod] +unsafe extern "C++" {} + +fn main() {} diff --git a/src/test/ui/proc-macro/unsafe-mod.rs b/src/test/ui/proc-macro/unsafe-mod.rs new file mode 100644 index 0000000000000..8ff6e352c53d0 --- /dev/null +++ b/src/test/ui/proc-macro/unsafe-mod.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:macro-only-syntax.rs + +#![feature(proc_macro_hygiene)] + +extern crate macro_only_syntax; + +#[macro_only_syntax::expect_unsafe_mod] +unsafe mod m { + pub unsafe mod inner; +} + +fn main() {} From fd5859a673e69eb9fd98e9a92c32dd0dc7fc1855 Mon Sep 17 00:00:00 2001 From: arijit79 <65700195+arijit79@users.noreply.github.com> Date: Thu, 3 Sep 2020 20:08:15 +0530 Subject: [PATCH 16/18] Add docs about crate level documentation support --- src/doc/rustdoc/src/what-is-rustdoc.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/doc/rustdoc/src/what-is-rustdoc.md b/src/doc/rustdoc/src/what-is-rustdoc.md index adcebc832bc0b..7a38c96d7147b 100644 --- a/src/doc/rustdoc/src/what-is-rustdoc.md +++ b/src/doc/rustdoc/src/what-is-rustdoc.md @@ -93,6 +93,29 @@ passes `-L`, a flag that helps rustdoc find the dependencies your code relies on. If our project used dependencies, we'd get documentation for them as well! +## Outer and inner documentation + +The `///` syntax is used to document the item present after it. +That's why it is called an outer documentation. +There is another syntax: `//!`, which is used to document the +item it is present inside. It is called an inner documentation. +It is often used when documenting the entire crate, +because nothing comes before it: it is the root of the crate. +So in order to document an entire crate, you need to use `//!` syntax. +For example: + +``` rust +//! This is my first rust crate +``` + +When used in the crate root, it documents the item it is inside, +which is the crate itself. + +For more information about the `//!` syntax, see [the Book]. + +[the Book]: https://doc.rust-lang.org/book/ch14-02-publishing-to-crates-io.html#commenting-contained-items + + ## Using standalone Markdown files `rustdoc` can also generate HTML from standalone Markdown files. Let's From c0894e72320a9b8a80f39fae1908d9e83a8b7277 Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 9 Sep 2020 15:42:37 +0100 Subject: [PATCH 17/18] typeck/expr: inaccessible private fields This commit adjusts the missing field diagnostic logic for struct expressions in typeck to improve the diagnostic when the missing fields are inaccessible. Signed-off-by: David Wood --- compiler/rustc_typeck/src/check/expr.rs | 118 +++++++++++++++++------- src/test/ui/issues/issue-76077.rs | 10 ++ src/test/ui/issues/issue-76077.stderr | 8 ++ 3 files changed, 103 insertions(+), 33 deletions(-) create mode 100644 src/test/ui/issues/issue-76077.rs create mode 100644 src/test/ui/issues/issue-76077.stderr diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index fa8b8dbd9f8d4..dba46f35dca92 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1241,42 +1241,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.sess.span_err(span, "union expressions should have exactly one field"); } } else if check_completeness && !error_happened && !remaining_fields.is_empty() { - let len = remaining_fields.len(); - - let mut displayable_field_names = - remaining_fields.keys().map(|ident| ident.as_str()).collect::>(); - - displayable_field_names.sort(); + let no_accessible_remaining_fields = remaining_fields + .iter() + .filter(|(_, (_, field))| { + field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx) + }) + .next() + .is_none(); - let truncated_fields_error = if len <= 3 { - String::new() + if no_accessible_remaining_fields { + self.report_no_accessible_fields(adt_ty, span); } else { - format!(" and {} other field{}", (len - 3), if len - 3 == 1 { "" } else { "s" }) - }; - - let remaining_fields_names = displayable_field_names - .iter() - .take(3) - .map(|n| format!("`{}`", n)) - .collect::>() - .join(", "); - - struct_span_err!( - tcx.sess, - span, - E0063, - "missing field{} {}{} in initializer of `{}`", - pluralize!(remaining_fields.len()), - remaining_fields_names, - truncated_fields_error, - adt_ty - ) - .span_label( - span, - format!("missing {}{}", remaining_fields_names, truncated_fields_error), - ) - .emit(); + self.report_missing_field(adt_ty, span, remaining_fields); + } } + error_happened } @@ -1293,6 +1272,79 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Report an error for a struct field expression when there are fields which aren't provided. + /// + /// ```ignore (diagnostic) + /// error: missing field `you_can_use_this_field` in initializer of `foo::Foo` + /// --> src/main.rs:8:5 + /// | + /// 8 | foo::Foo {}; + /// | ^^^^^^^^ missing `you_can_use_this_field` + /// + /// error: aborting due to previous error + /// ``` + fn report_missing_field( + &self, + adt_ty: Ty<'tcx>, + span: Span, + remaining_fields: FxHashMap, + ) { + let tcx = self.tcx; + let len = remaining_fields.len(); + + let mut displayable_field_names = + remaining_fields.keys().map(|ident| ident.as_str()).collect::>(); + + displayable_field_names.sort(); + + let truncated_fields_error = if len <= 3 { + String::new() + } else { + format!(" and {} other field{}", (len - 3), if len - 3 == 1 { "" } else { "s" }) + }; + + let remaining_fields_names = displayable_field_names + .iter() + .take(3) + .map(|n| format!("`{}`", n)) + .collect::>() + .join(", "); + + struct_span_err!( + tcx.sess, + span, + E0063, + "missing field{} {}{} in initializer of `{}`", + pluralize!(remaining_fields.len()), + remaining_fields_names, + truncated_fields_error, + adt_ty + ) + .span_label(span, format!("missing {}{}", remaining_fields_names, truncated_fields_error)) + .emit(); + } + + /// Report an error for a struct field expression when there are no visible fields. + /// + /// ```ignore (diagnostic) + /// error: cannot construct `Foo` with struct literal syntax due to inaccessible fields + /// --> src/main.rs:8:5 + /// | + /// 8 | foo::Foo {}; + /// | ^^^^^^^^ + /// + /// error: aborting due to previous error + /// ``` + fn report_no_accessible_fields(&self, adt_ty: Ty<'tcx>, span: Span) { + self.tcx.sess.span_err( + span, + &format!( + "cannot construct `{}` with struct literal syntax due to inaccessible fields", + adt_ty, + ), + ); + } + fn report_unknown_field( &self, ty: Ty<'tcx>, diff --git a/src/test/ui/issues/issue-76077.rs b/src/test/ui/issues/issue-76077.rs new file mode 100644 index 0000000000000..1ecd37de2e14a --- /dev/null +++ b/src/test/ui/issues/issue-76077.rs @@ -0,0 +1,10 @@ +pub mod foo { + pub struct Foo { + you_cant_use_this_field: bool, + } +} + +fn main() { + foo::Foo {}; + //~^ ERROR cannot construct `Foo` with struct literal syntax due to inaccessible fields +} diff --git a/src/test/ui/issues/issue-76077.stderr b/src/test/ui/issues/issue-76077.stderr new file mode 100644 index 0000000000000..d834ec5e0edd2 --- /dev/null +++ b/src/test/ui/issues/issue-76077.stderr @@ -0,0 +1,8 @@ +error: cannot construct `Foo` with struct literal syntax due to inaccessible fields + --> $DIR/issue-76077.rs:8:5 + | +LL | foo::Foo {}; + | ^^^^^^^^ + +error: aborting due to previous error + From 409c14197372495b26fa8ee9f4b812492a7fb75a Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 10 Sep 2020 12:32:45 +0100 Subject: [PATCH 18/18] typeck/pat: inaccessible private fields This commit adjusts the missing field diagnostic logic for struct patterns in typeck to improve the diagnostic when the missing fields are inaccessible. Signed-off-by: David Wood --- compiler/rustc_typeck/src/check/pat.rs | 90 ++++++++++++++++++++++--- src/test/ui/issues/issue-76077-1.fixed | 18 +++++ src/test/ui/issues/issue-76077-1.rs | 18 +++++ src/test/ui/issues/issue-76077-1.stderr | 24 +++++++ 4 files changed, 141 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/issues/issue-76077-1.fixed create mode 100644 src/test/ui/issues/issue-76077-1.rs create mode 100644 src/test/ui/issues/issue-76077-1.stderr diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index f06929aa98ff4..1896155e327d8 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1078,8 +1078,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut unmentioned_fields = variant .fields .iter() - .map(|field| field.ident.normalize_to_macros_2_0()) - .filter(|ident| !used_fields.contains_key(&ident)) + .map(|field| (field, field.ident.normalize_to_macros_2_0())) + .filter(|(_, ident)| !used_fields.contains_key(&ident)) .collect::>(); let inexistent_fields_err = if !(inexistent_fields.is_empty() || variant.is_recovered()) { @@ -1110,7 +1110,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit(); } } else if !etc && !unmentioned_fields.is_empty() { - unmentioned_err = Some(self.error_unmentioned_fields(pat, &unmentioned_fields)); + let no_accessible_unmentioned_fields = unmentioned_fields + .iter() + .filter(|(field, _)| { + field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx) + }) + .next() + .is_none(); + + if no_accessible_unmentioned_fields { + unmentioned_err = Some(self.error_no_accessible_fields(pat, &fields)); + } else { + unmentioned_err = Some(self.error_unmentioned_fields(pat, &unmentioned_fields)); + } } match (inexistent_fields_err, unmentioned_err) { (Some(mut i), Some(mut u)) => { @@ -1173,7 +1185,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, kind_name: &str, inexistent_fields: &[Ident], - unmentioned_fields: &mut Vec, + unmentioned_fields: &mut Vec<(&ty::FieldDef, Ident)>, variant: &ty::VariantDef, ) -> DiagnosticBuilder<'tcx> { let tcx = self.tcx; @@ -1215,7 +1227,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), ); if plural == "" { - let input = unmentioned_fields.iter().map(|field| &field.name); + let input = unmentioned_fields.iter().map(|(_, field)| &field.name); let suggested_name = find_best_match_for_name(input, ident.name, None); if let Some(suggested_name) = suggested_name { err.span_suggestion( @@ -1232,7 +1244,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `smart_resolve_context_dependent_help`. if suggested_name.to_ident_string().parse::().is_err() { // We don't want to throw `E0027` in case we have thrown `E0026` for them. - unmentioned_fields.retain(|&x| x.name != suggested_name); + unmentioned_fields.retain(|&(_, x)| x.name != suggested_name); } } } @@ -1300,17 +1312,77 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None } + /// Returns a diagnostic reporting a struct pattern which is missing an `..` due to + /// inaccessible fields. + /// + /// ```ignore (diagnostic) + /// error: pattern requires `..` due to inaccessible fields + /// --> src/main.rs:10:9 + /// | + /// LL | let foo::Foo {} = foo::Foo::default(); + /// | ^^^^^^^^^^^ + /// | + /// help: add a `..` + /// | + /// LL | let foo::Foo { .. } = foo::Foo::default(); + /// | ^^^^^^ + /// ``` + fn error_no_accessible_fields( + &self, + pat: &Pat<'_>, + fields: &'tcx [hir::FieldPat<'tcx>], + ) -> DiagnosticBuilder<'tcx> { + let mut err = self + .tcx + .sess + .struct_span_err(pat.span, "pattern requires `..` due to inaccessible fields"); + + if let Some(field) = fields.last() { + err.span_suggestion_verbose( + field.span.shrink_to_hi(), + "ignore the inaccessible and unused fields", + ", ..".to_string(), + Applicability::MachineApplicable, + ); + } else { + let qpath_span = if let PatKind::Struct(qpath, ..) = &pat.kind { + qpath.span() + } else { + bug!("`error_no_accessible_fields` called on non-struct pattern"); + }; + + // Shrink the span to exclude the `foo:Foo` in `foo::Foo { }`. + let span = pat.span.with_lo(qpath_span.shrink_to_hi().hi()); + err.span_suggestion_verbose( + span, + "ignore the inaccessible and unused fields", + " { .. }".to_string(), + Applicability::MachineApplicable, + ); + } + err + } + + /// Returns a diagnostic reporting a struct pattern which does not mention some fields. + /// + /// ```ignore (diagnostic) + /// error[E0027]: pattern does not mention field `you_cant_use_this_field` + /// --> src/main.rs:15:9 + /// | + /// LL | let foo::Foo {} = foo::Foo::new(); + /// | ^^^^^^^^^^^ missing field `you_cant_use_this_field` + /// ``` fn error_unmentioned_fields( &self, pat: &Pat<'_>, - unmentioned_fields: &[Ident], + unmentioned_fields: &[(&ty::FieldDef, Ident)], ) -> DiagnosticBuilder<'tcx> { let field_names = if unmentioned_fields.len() == 1 { - format!("field `{}`", unmentioned_fields[0]) + format!("field `{}`", unmentioned_fields[0].1) } else { let fields = unmentioned_fields .iter() - .map(|name| format!("`{}`", name)) + .map(|(_, name)| format!("`{}`", name)) .collect::>() .join(", "); format!("fields {}", fields) diff --git a/src/test/ui/issues/issue-76077-1.fixed b/src/test/ui/issues/issue-76077-1.fixed new file mode 100644 index 0000000000000..8103a7ca47d4e --- /dev/null +++ b/src/test/ui/issues/issue-76077-1.fixed @@ -0,0 +1,18 @@ +// run-rustfix +#![allow(dead_code, unused_variables)] + +pub mod foo { + #[derive(Default)] + pub struct Foo { invisible: bool, } + + #[derive(Default)] + pub struct Bar { pub visible: bool, invisible: bool, } +} + +fn main() { + let foo::Foo { .. } = foo::Foo::default(); + //~^ ERROR pattern requires `..` due to inaccessible fields + + let foo::Bar { visible, .. } = foo::Bar::default(); + //~^ ERROR pattern requires `..` due to inaccessible fields +} diff --git a/src/test/ui/issues/issue-76077-1.rs b/src/test/ui/issues/issue-76077-1.rs new file mode 100644 index 0000000000000..730332853c124 --- /dev/null +++ b/src/test/ui/issues/issue-76077-1.rs @@ -0,0 +1,18 @@ +// run-rustfix +#![allow(dead_code, unused_variables)] + +pub mod foo { + #[derive(Default)] + pub struct Foo { invisible: bool, } + + #[derive(Default)] + pub struct Bar { pub visible: bool, invisible: bool, } +} + +fn main() { + let foo::Foo {} = foo::Foo::default(); + //~^ ERROR pattern requires `..` due to inaccessible fields + + let foo::Bar { visible } = foo::Bar::default(); + //~^ ERROR pattern requires `..` due to inaccessible fields +} diff --git a/src/test/ui/issues/issue-76077-1.stderr b/src/test/ui/issues/issue-76077-1.stderr new file mode 100644 index 0000000000000..4557595529fa2 --- /dev/null +++ b/src/test/ui/issues/issue-76077-1.stderr @@ -0,0 +1,24 @@ +error: pattern requires `..` due to inaccessible fields + --> $DIR/issue-76077-1.rs:13:9 + | +LL | let foo::Foo {} = foo::Foo::default(); + | ^^^^^^^^^^^ + | +help: ignore the inaccessible and unused fields + | +LL | let foo::Foo { .. } = foo::Foo::default(); + | ^^^^^^ + +error: pattern requires `..` due to inaccessible fields + --> $DIR/issue-76077-1.rs:16:9 + | +LL | let foo::Bar { visible } = foo::Bar::default(); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: ignore the inaccessible and unused fields + | +LL | let foo::Bar { visible, .. } = foo::Bar::default(); + | ^^^^ + +error: aborting due to 2 previous errors +