From 30fc601dde6065172e22ba1b351870390d32ec82 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Wed, 10 Mar 2021 21:36:37 -0800 Subject: [PATCH 01/32] Tests for field is never read diagnostic --- .../dead-code/drop-only-field-issue-81658.rs | 42 ++++++++++++++++ .../drop-only-field-issue-81658.stderr | 14 ++++++ .../field-used-in-ffi-issue-81658.rs | 50 +++++++++++++++++++ .../field-used-in-ffi-issue-81658.stderr | 14 ++++++ 4 files changed, 120 insertions(+) create mode 100644 src/test/ui/lint/dead-code/drop-only-field-issue-81658.rs create mode 100644 src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr create mode 100644 src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.rs create mode 100644 src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr diff --git a/src/test/ui/lint/dead-code/drop-only-field-issue-81658.rs b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.rs new file mode 100644 index 0000000000000..d28b6430bc587 --- /dev/null +++ b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.rs @@ -0,0 +1,42 @@ +//! The field `guard` is never used directly, but it is still useful for its side effect when +//! dropped. Since rustc doesn't consider a `Drop` impl as a use, we want to make sure we at least +//! produce a helpful diagnostic that points the user to what they can do if they indeed intended to +//! have a field that is only used for its `Drop` side effect. +//! +//! Issue: https://github.com/rust-lang/rust/issues/81658 + +#![deny(dead_code)] + +use std::sync::{Mutex, MutexGuard}; + +/// Holds a locked value until it is dropped +pub struct Locked<'a, T> { + // Field is kept for its affect when dropped, but otherwise unused + guard: MutexGuard<'a, T>, //~ ERROR field is never read +} + +impl<'a, T> Locked<'a, T> { + pub fn new(value: &'a Mutex) -> Self { + Self { + guard: value.lock().unwrap(), + } + } +} + +fn main() { + let items = Mutex::new(vec![1, 2, 3]); + + // Hold a lock on items while doing something else + let result = { + // The lock will be released at the end of this scope + let _lock = Locked::new(&items); + + do_something_else() + }; + + println!("{}", result); +} + +fn do_something_else() -> i32 { + 1 + 1 +} diff --git a/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr new file mode 100644 index 0000000000000..c2a3e9d3c48b4 --- /dev/null +++ b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr @@ -0,0 +1,14 @@ +error: field is never read: `guard` + --> $DIR/drop-only-field-issue-81658.rs:15:5 + | +LL | guard: MutexGuard<'a, T>, + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/drop-only-field-issue-81658.rs:8:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.rs b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.rs new file mode 100644 index 0000000000000..12eafe6ae4958 --- /dev/null +++ b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.rs @@ -0,0 +1,50 @@ +//! The field `items` is being "used" by FFI (implicitly through pointers). However, since rustc +//! doesn't know how to detect that, we produce a message that says the field is unused. This can +//! cause some confusion and we want to make sure our diagnostics help as much as they can. +//! +//! Issue: https://github.com/rust-lang/rust/issues/81658 + +#![deny(dead_code)] + +/// A struct for holding on to data while it is being used in our FFI code +pub struct FFIData { + /// These values cannot be dropped while the pointers to each item + /// are still in use + items: Option>, //~ ERROR field is never read +} + +impl FFIData { + pub fn new() -> Self { + Self {items: None} + } + + /// Load items into this type and return pointers to each item that can + /// be passed to FFI + pub fn load(&mut self, items: Vec) -> Vec<*const T> { + let ptrs = items.iter().map(|item| item as *const _).collect(); + + self.items = Some(items); + + ptrs + } +} + +extern { + /// The FFI code that uses items + fn process_item(item: *const i32); +} + +fn main() { + // Data cannot be dropped until the end of this scope or else the items + // will be dropped before they are processed + let mut data = FFIData::new(); + + let ptrs = data.load(vec![1, 2, 3, 4, 5]); + + for ptr in ptrs { + // Safety: This pointer is valid as long as the arena is in scope + unsafe { process_item(ptr); } + } + + // Items will be safely freed at the end of this scope +} diff --git a/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr new file mode 100644 index 0000000000000..874afa110c433 --- /dev/null +++ b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr @@ -0,0 +1,14 @@ +error: field is never read: `items` + --> $DIR/field-used-in-ffi-issue-81658.rs:13:5 + | +LL | items: Option>, + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/field-used-in-ffi-issue-81658.rs:7:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + From 321aace531687cb6c6a7545341344c9a810492da Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Thu, 11 Mar 2021 20:16:34 -0800 Subject: [PATCH 02/32] Added suggestion and note for when a field is never used --- compiler/rustc_passes/src/dead.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index c63edf365a1aa..0457d287e01e8 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -3,6 +3,7 @@ // from live codes are live, and everything else is dead. use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; @@ -577,7 +578,26 @@ impl DeadVisitor<'tcx> { self.tcx.struct_span_lint_hir(lint::builtin::DEAD_CODE, id, span, |lint| { let def_id = self.tcx.hir().local_def_id(id); let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id()); - lint.build(&format!("{} is never {}: `{}`", descr, participle, name)).emit() + + let prefixed = vec![(span, format!("_{}", name))]; + + let mut diag = + lint.build(&format!("{} is never {}: `{}`", descr, participle, name)); + diag.multipart_suggestion( + "if this is intentional, prefix it with an underscore", + prefixed, + Applicability::MachineApplicable, + ) + .note(&format!( + "the leading underscore helps signal to the reader that the {} may still serve\n\ + a purpose even if it isn't used in a way that we can detect (e.g. the {}\nis \ + only used through FFI or used only for its effect when dropped)", + descr, descr, + )); + // Force the note we added to the front, before any other subdiagnostics + diag.children.rotate_right(1); + + diag.emit() }); } } From 7faaf396b2828f487bd862cfba53b66612998fa2 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Thu, 11 Mar 2021 21:43:26 -0800 Subject: [PATCH 03/32] Updating test stderr files --- .../associated-const-dead-code.stderr | 5 +- .../ui/derive-uninhabited-enum-38885.stderr | 5 +- src/test/ui/issues/issue-37515.stderr | 5 +- src/test/ui/lint/dead-code/basic.stderr | 5 +- .../ui/lint/dead-code/const-and-self.stderr | 11 +++- .../drop-only-field-issue-81658.stderr | 5 +- .../lint/dead-code/empty-unused-enum.stderr | 5 +- .../field-used-in-ffi-issue-81658.stderr | 5 +- src/test/ui/lint/dead-code/impl-trait.stderr | 5 +- .../ui/lint/dead-code/lint-dead-code-1.stderr | 59 +++++++++++++++---- .../ui/lint/dead-code/lint-dead-code-2.stderr | 17 +++++- .../ui/lint/dead-code/lint-dead-code-3.stderr | 29 +++++++-- .../ui/lint/dead-code/lint-dead-code-4.stderr | 59 +++++++++++++++---- .../ui/lint/dead-code/lint-dead-code-5.stderr | 23 ++++++-- .../ui/lint/dead-code/lint-dead-code-6.stderr | 23 ++++++-- .../ui/lint/dead-code/newline-span.stderr | 17 +++++- src/test/ui/lint/dead-code/type-alias.stderr | 5 +- src/test/ui/lint/dead-code/unused-enum.stderr | 17 +++++- .../dead-code/unused-struct-variant.stderr | 5 +- .../ui/lint/dead-code/unused-variant.stderr | 5 +- .../ui/lint/dead-code/with-core-crate.stderr | 5 +- .../ui/lint/dead-code/write-only-field.stderr | 35 +++++++++-- .../ui/lint/issue-17718-const-naming.stderr | 5 +- .../ui/span/macro-span-replacement.stderr | 5 +- .../unused-warning-point-at-identifier.stderr | 23 ++++++-- .../ui/test-attrs/test-warns-dead-code.stderr | 5 +- src/test/ui/union/union-fields-1.stderr | 23 ++++++-- src/test/ui/union/union-lint-dead-code.stderr | 5 +- 28 files changed, 342 insertions(+), 74 deletions(-) diff --git a/src/test/ui/associated-consts/associated-const-dead-code.stderr b/src/test/ui/associated-consts/associated-const-dead-code.stderr index 9b6bbb68a71f7..60c227ef557f5 100644 --- a/src/test/ui/associated-consts/associated-const-dead-code.stderr +++ b/src/test/ui/associated-consts/associated-const-dead-code.stderr @@ -2,8 +2,11 @@ error: associated constant is never used: `BAR` --> $DIR/associated-const-dead-code.rs:6:5 | LL | const BAR: u32 = 1; - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_BAR` | + = note: the leading underscore helps signal to the reader that the associated constant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the associated constant + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/associated-const-dead-code.rs:1:9 | diff --git a/src/test/ui/derive-uninhabited-enum-38885.stderr b/src/test/ui/derive-uninhabited-enum-38885.stderr index 72607629d3c10..7aa5fc4d15b48 100644 --- a/src/test/ui/derive-uninhabited-enum-38885.stderr +++ b/src/test/ui/derive-uninhabited-enum-38885.stderr @@ -2,8 +2,11 @@ warning: variant is never constructed: `Void` --> $DIR/derive-uninhabited-enum-38885.rs:13:5 | LL | Void(Void), - | ^^^^^^^^^^ + | ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Void` | + = note: the leading underscore helps signal to the reader that the variant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the variant + is only used through FFI or used only for its effect when dropped) = note: `-W dead-code` implied by `-W unused` warning: 1 warning emitted diff --git a/src/test/ui/issues/issue-37515.stderr b/src/test/ui/issues/issue-37515.stderr index 204a39bc8e8e9..683602ce8af97 100644 --- a/src/test/ui/issues/issue-37515.stderr +++ b/src/test/ui/issues/issue-37515.stderr @@ -2,8 +2,11 @@ warning: type alias is never used: `Z` --> $DIR/issue-37515.rs:5:1 | LL | type Z = dyn for<'x> Send; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Z` | + = note: the leading underscore helps signal to the reader that the type alias may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the type alias + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/issue-37515.rs:3:9 | diff --git a/src/test/ui/lint/dead-code/basic.stderr b/src/test/ui/lint/dead-code/basic.stderr index f7b9b9c613ae0..f42008b4f0d1b 100644 --- a/src/test/ui/lint/dead-code/basic.stderr +++ b/src/test/ui/lint/dead-code/basic.stderr @@ -2,8 +2,11 @@ error: function is never used: `foo` --> $DIR/basic.rs:4:4 | LL | fn foo() { - | ^^^ + | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/basic.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/const-and-self.stderr b/src/test/ui/lint/dead-code/const-and-self.stderr index c0e406189e8ab..0e2e66cfef7b1 100644 --- a/src/test/ui/lint/dead-code/const-and-self.stderr +++ b/src/test/ui/lint/dead-code/const-and-self.stderr @@ -2,8 +2,11 @@ warning: variant is never constructed: `B` --> $DIR/const-and-self.rs:33:5 | LL | B, - | ^ + | ^ help: if this is intentional, prefix it with an underscore: `_B` | + = note: the leading underscore helps signal to the reader that the variant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the variant + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/const-and-self.rs:3:9 | @@ -14,7 +17,11 @@ warning: variant is never constructed: `C` --> $DIR/const-and-self.rs:34:5 | LL | C, - | ^ + | ^ help: if this is intentional, prefix it with an underscore: `_C` + | + = note: the leading underscore helps signal to the reader that the variant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the variant + is only used through FFI or used only for its effect when dropped) warning: 2 warnings emitted diff --git a/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr index c2a3e9d3c48b4..8c5a5f0a7e5bf 100644 --- a/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr +++ b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr @@ -2,8 +2,11 @@ error: field is never read: `guard` --> $DIR/drop-only-field-issue-81658.rs:15:5 | LL | guard: MutexGuard<'a, T>, - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_guard` | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/drop-only-field-issue-81658.rs:8:9 | diff --git a/src/test/ui/lint/dead-code/empty-unused-enum.stderr b/src/test/ui/lint/dead-code/empty-unused-enum.stderr index ed9a7ccd14b21..8e16d24c001d5 100644 --- a/src/test/ui/lint/dead-code/empty-unused-enum.stderr +++ b/src/test/ui/lint/dead-code/empty-unused-enum.stderr @@ -2,8 +2,11 @@ error: enum is never used: `E` --> $DIR/empty-unused-enum.rs:3:6 | LL | enum E {} - | ^ + | ^ help: if this is intentional, prefix it with an underscore: `_E` | + = note: the leading underscore helps signal to the reader that the enum may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the enum + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/empty-unused-enum.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr index 874afa110c433..d5b5ee777dc07 100644 --- a/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr +++ b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr @@ -2,8 +2,11 @@ error: field is never read: `items` --> $DIR/field-used-in-ffi-issue-81658.rs:13:5 | LL | items: Option>, - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_items` | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/field-used-in-ffi-issue-81658.rs:7:9 | diff --git a/src/test/ui/lint/dead-code/impl-trait.stderr b/src/test/ui/lint/dead-code/impl-trait.stderr index 09b6d08eb8fb8..fe3d4a8a214b6 100644 --- a/src/test/ui/lint/dead-code/impl-trait.stderr +++ b/src/test/ui/lint/dead-code/impl-trait.stderr @@ -2,8 +2,11 @@ error: type alias is never used: `Unused` --> $DIR/impl-trait.rs:12:1 | LL | type Unused = (); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Unused` | + = note: the leading underscore helps signal to the reader that the type alias may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the type alias + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/impl-trait.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr index af97ea98b2b6d..7d1038db4b289 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr @@ -2,8 +2,11 @@ error: struct is never constructed: `Bar` --> $DIR/lint-dead-code-1.rs:12:16 | LL | pub struct Bar; - | ^^^ + | ^^^ help: if this is intentional, prefix it with an underscore: `_Bar` | + = note: the leading underscore helps signal to the reader that the struct may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the struct + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/lint-dead-code-1.rs:5:9 | @@ -14,55 +17,91 @@ error: static is never used: `priv_static` --> $DIR/lint-dead-code-1.rs:20:1 | LL | static priv_static: isize = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_static` + | + = note: the leading underscore helps signal to the reader that the static may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the static + is only used through FFI or used only for its effect when dropped) error: constant is never used: `priv_const` --> $DIR/lint-dead-code-1.rs:27:1 | LL | const priv_const: isize = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_const` + | + = note: the leading underscore helps signal to the reader that the constant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the constant + is only used through FFI or used only for its effect when dropped) error: struct is never constructed: `PrivStruct` --> $DIR/lint-dead-code-1.rs:35:8 | LL | struct PrivStruct; - | ^^^^^^^^^^ + | ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_PrivStruct` + | + = note: the leading underscore helps signal to the reader that the struct may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the struct + is only used through FFI or used only for its effect when dropped) error: enum is never used: `priv_enum` --> $DIR/lint-dead-code-1.rs:64:6 | LL | enum priv_enum { foo2, bar2 } - | ^^^^^^^^^ + | ^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_enum` + | + = note: the leading underscore helps signal to the reader that the enum may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the enum + is only used through FFI or used only for its effect when dropped) error: variant is never constructed: `bar3` --> $DIR/lint-dead-code-1.rs:67:5 | LL | bar3 - | ^^^^ + | ^^^^ help: if this is intentional, prefix it with an underscore: `_bar3` + | + = note: the leading underscore helps signal to the reader that the variant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the variant + is only used through FFI or used only for its effect when dropped) error: function is never used: `priv_fn` --> $DIR/lint-dead-code-1.rs:88:4 | LL | fn priv_fn() { - | ^^^^^^^ + | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_fn` + | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) error: function is never used: `foo` --> $DIR/lint-dead-code-1.rs:93:4 | LL | fn foo() { - | ^^^ + | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` + | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) error: function is never used: `bar` --> $DIR/lint-dead-code-1.rs:98:4 | LL | fn bar() { - | ^^^ + | ^^^ help: if this is intentional, prefix it with an underscore: `_bar` + | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) error: function is never used: `baz` --> $DIR/lint-dead-code-1.rs:102:4 | LL | fn baz() -> impl Copy { - | ^^^ + | ^^^ help: if this is intentional, prefix it with an underscore: `_baz` + | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) error: aborting due to 10 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-2.stderr b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr index b01ba57f98580..f840daee7a0c7 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-2.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr @@ -2,8 +2,11 @@ error: function is never used: `dead_fn` --> $DIR/lint-dead-code-2.rs:22:4 | LL | fn dead_fn() {} - | ^^^^^^^ + | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_dead_fn` | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/lint-dead-code-2.rs:2:9 | @@ -14,13 +17,21 @@ error: function is never used: `dead_fn2` --> $DIR/lint-dead-code-2.rs:25:4 | LL | fn dead_fn2() {} - | ^^^^^^^^ + | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_dead_fn2` + | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) error: function is never used: `main` --> $DIR/lint-dead-code-2.rs:38:4 | LL | fn main() { - | ^^^^ + | ^^^^ help: if this is intentional, prefix it with an underscore: `_main` + | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr index cf8f01ea19f0c..ad7fec0181519 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr @@ -2,8 +2,11 @@ error: struct is never constructed: `Foo` --> $DIR/lint-dead-code-3.rs:14:8 | LL | struct Foo; - | ^^^ + | ^^^ help: if this is intentional, prefix it with an underscore: `_Foo` | + = note: the leading underscore helps signal to the reader that the struct may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the struct + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/lint-dead-code-3.rs:4:9 | @@ -14,25 +17,41 @@ error: associated function is never used: `foo` --> $DIR/lint-dead-code-3.rs:16:8 | LL | fn foo(&self) { - | ^^^ + | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` + | + = note: the leading underscore helps signal to the reader that the associated function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the associated function + is only used through FFI or used only for its effect when dropped) error: function is never used: `bar` --> $DIR/lint-dead-code-3.rs:21:4 | LL | fn bar() { - | ^^^ + | ^^^ help: if this is intentional, prefix it with an underscore: `_bar` + | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) error: enum is never used: `c_void` --> $DIR/lint-dead-code-3.rs:60:6 | LL | enum c_void {} - | ^^^^^^ + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_c_void` + | + = note: the leading underscore helps signal to the reader that the enum may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the enum + is only used through FFI or used only for its effect when dropped) error: function is never used: `free` --> $DIR/lint-dead-code-3.rs:62:5 | LL | fn free(p: *const c_void); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_free` + | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) error: aborting due to 5 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr index 3905d1a06bdfe..7fd275159c2eb 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr @@ -2,8 +2,11 @@ error: field is never read: `b` --> $DIR/lint-dead-code-4.rs:7:5 | LL | b: bool, - | ^^^^^^^ + | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_b` | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/lint-dead-code-4.rs:3:9 | @@ -14,7 +17,11 @@ error: variant is never constructed: `X` --> $DIR/lint-dead-code-4.rs:15:5 | LL | X, - | ^ + | ^ help: if this is intentional, prefix it with an underscore: `_X` + | + = note: the leading underscore helps signal to the reader that the variant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the variant + is only used through FFI or used only for its effect when dropped) error: variant is never constructed: `Y` --> $DIR/lint-dead-code-4.rs:16:5 @@ -24,49 +31,81 @@ LL | | a: String, LL | | b: i32, LL | | c: i32, LL | | }, - | |_____^ + | |_____^ help: if this is intentional, prefix it with an underscore: `_Y` + | + = note: the leading underscore helps signal to the reader that the variant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the variant + is only used through FFI or used only for its effect when dropped) error: enum is never used: `ABC` --> $DIR/lint-dead-code-4.rs:24:6 | LL | enum ABC { - | ^^^ + | ^^^ help: if this is intentional, prefix it with an underscore: `_ABC` + | + = note: the leading underscore helps signal to the reader that the enum may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the enum + is only used through FFI or used only for its effect when dropped) error: variant is never constructed: `I` --> $DIR/lint-dead-code-4.rs:36:5 | LL | I, - | ^ + | ^ help: if this is intentional, prefix it with an underscore: `_I` + | + = note: the leading underscore helps signal to the reader that the variant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the variant + is only used through FFI or used only for its effect when dropped) error: field is never read: `b` --> $DIR/lint-dead-code-4.rs:39:9 | LL | b: i32, - | ^^^^^^ + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_b` + | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) error: field is never read: `c` --> $DIR/lint-dead-code-4.rs:40:9 | LL | c: i32, - | ^^^^^^ + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_c` + | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) error: variant is never constructed: `K` --> $DIR/lint-dead-code-4.rs:42:5 | LL | K - | ^ + | ^ help: if this is intentional, prefix it with an underscore: `_K` + | + = note: the leading underscore helps signal to the reader that the variant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the variant + is only used through FFI or used only for its effect when dropped) error: field is never read: `x` --> $DIR/lint-dead-code-4.rs:61:5 | LL | x: usize, - | ^^^^^^^^ + | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) error: field is never read: `c` --> $DIR/lint-dead-code-4.rs:63:5 | LL | c: bool, - | ^^^^^^^ + | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_c` + | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) error: aborting due to 10 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr index 519add826273f..d0868af5f4473 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr @@ -2,8 +2,11 @@ error: variant is never constructed: `Variant2` --> $DIR/lint-dead-code-5.rs:6:5 | LL | Variant2 - | ^^^^^^^^ + | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant2` | + = note: the leading underscore helps signal to the reader that the variant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the variant + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/lint-dead-code-5.rs:2:9 | @@ -14,19 +17,31 @@ error: variant is never constructed: `Variant5` --> $DIR/lint-dead-code-5.rs:13:5 | LL | Variant5 { _x: isize }, - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant5` + | + = note: the leading underscore helps signal to the reader that the variant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the variant + is only used through FFI or used only for its effect when dropped) error: variant is never constructed: `Variant6` --> $DIR/lint-dead-code-5.rs:14:5 | LL | Variant6(isize), - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant6` + | + = note: the leading underscore helps signal to the reader that the variant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the variant + is only used through FFI or used only for its effect when dropped) error: enum is never used: `Enum3` --> $DIR/lint-dead-code-5.rs:35:6 | LL | enum Enum3 { - | ^^^^^ + | ^^^^^ help: if this is intentional, prefix it with an underscore: `_Enum3` + | + = note: the leading underscore helps signal to the reader that the enum may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the enum + is only used through FFI or used only for its effect when dropped) error: aborting due to 4 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-6.stderr b/src/test/ui/lint/dead-code/lint-dead-code-6.stderr index 7dc60730d6aad..687a49eb7619a 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-6.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-6.stderr @@ -2,8 +2,11 @@ error: struct is never constructed: `UnusedStruct` --> $DIR/lint-dead-code-6.rs:3:8 | LL | struct UnusedStruct; - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_UnusedStruct` | + = note: the leading underscore helps signal to the reader that the struct may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the struct + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/lint-dead-code-6.rs:1:9 | @@ -14,19 +17,31 @@ error: associated function is never used: `unused_impl_fn_1` --> $DIR/lint-dead-code-6.rs:5:8 | LL | fn unused_impl_fn_1() { - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_impl_fn_1` + | + = note: the leading underscore helps signal to the reader that the associated function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the associated function + is only used through FFI or used only for its effect when dropped) error: associated function is never used: `unused_impl_fn_2` --> $DIR/lint-dead-code-6.rs:9:8 | LL | fn unused_impl_fn_2(var: i32) { - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_impl_fn_2` + | + = note: the leading underscore helps signal to the reader that the associated function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the associated function + is only used through FFI or used only for its effect when dropped) error: associated function is never used: `unused_impl_fn_3` --> $DIR/lint-dead-code-6.rs:13:8 | LL | fn unused_impl_fn_3( - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_impl_fn_3` + | + = note: the leading underscore helps signal to the reader that the associated function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the associated function + is only used through FFI or used only for its effect when dropped) error: aborting due to 4 previous errors diff --git a/src/test/ui/lint/dead-code/newline-span.stderr b/src/test/ui/lint/dead-code/newline-span.stderr index fd74405f2b648..b636079631c35 100644 --- a/src/test/ui/lint/dead-code/newline-span.stderr +++ b/src/test/ui/lint/dead-code/newline-span.stderr @@ -2,8 +2,11 @@ error: function is never used: `unused` --> $DIR/newline-span.rs:3:4 | LL | fn unused() { - | ^^^^^^ + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/newline-span.rs:1:9 | @@ -14,13 +17,21 @@ error: function is never used: `unused2` --> $DIR/newline-span.rs:7:4 | LL | fn unused2(var: i32) { - | ^^^^^^^ + | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused2` + | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) error: function is never used: `unused3` --> $DIR/newline-span.rs:11:4 | LL | fn unused3( - | ^^^^^^^ + | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused3` + | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/dead-code/type-alias.stderr b/src/test/ui/lint/dead-code/type-alias.stderr index b2acd5d4213b3..5c11626bb1e44 100644 --- a/src/test/ui/lint/dead-code/type-alias.stderr +++ b/src/test/ui/lint/dead-code/type-alias.stderr @@ -2,8 +2,11 @@ error: type alias is never used: `Unused` --> $DIR/type-alias.rs:4:1 | LL | type Unused = u8; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Unused` | + = note: the leading underscore helps signal to the reader that the type alias may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the type alias + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/type-alias.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/unused-enum.stderr b/src/test/ui/lint/dead-code/unused-enum.stderr index 9f368fdd2f816..c71d305987c77 100644 --- a/src/test/ui/lint/dead-code/unused-enum.stderr +++ b/src/test/ui/lint/dead-code/unused-enum.stderr @@ -2,8 +2,11 @@ error: struct is never constructed: `F` --> $DIR/unused-enum.rs:3:8 | LL | struct F; - | ^ + | ^ help: if this is intentional, prefix it with an underscore: `_F` | + = note: the leading underscore helps signal to the reader that the struct may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the struct + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/unused-enum.rs:1:9 | @@ -15,13 +18,21 @@ error: struct is never constructed: `B` --> $DIR/unused-enum.rs:4:8 | LL | struct B; - | ^ + | ^ help: if this is intentional, prefix it with an underscore: `_B` + | + = note: the leading underscore helps signal to the reader that the struct may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the struct + is only used through FFI or used only for its effect when dropped) error: enum is never used: `E` --> $DIR/unused-enum.rs:6:6 | LL | enum E { - | ^ + | ^ help: if this is intentional, prefix it with an underscore: `_E` + | + = note: the leading underscore helps signal to the reader that the enum may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the enum + is only used through FFI or used only for its effect when dropped) error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/dead-code/unused-struct-variant.stderr b/src/test/ui/lint/dead-code/unused-struct-variant.stderr index b93d6d4ac1866..198986bde049d 100644 --- a/src/test/ui/lint/dead-code/unused-struct-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-struct-variant.stderr @@ -2,8 +2,11 @@ error: variant is never constructed: `Bar` --> $DIR/unused-struct-variant.rs:8:5 | LL | Bar(B), - | ^^^^^^ + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_Bar` | + = note: the leading underscore helps signal to the reader that the variant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the variant + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/unused-struct-variant.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/unused-variant.stderr b/src/test/ui/lint/dead-code/unused-variant.stderr index a547f5af4b082..5fff7b1fdb3e0 100644 --- a/src/test/ui/lint/dead-code/unused-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-variant.stderr @@ -2,8 +2,11 @@ error: variant is never constructed: `Variant1` --> $DIR/unused-variant.rs:5:5 | LL | Variant1, - | ^^^^^^^^ + | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant1` | + = note: the leading underscore helps signal to the reader that the variant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the variant + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/unused-variant.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/with-core-crate.stderr b/src/test/ui/lint/dead-code/with-core-crate.stderr index 2c63e60d67609..ab4c1793b0667 100644 --- a/src/test/ui/lint/dead-code/with-core-crate.stderr +++ b/src/test/ui/lint/dead-code/with-core-crate.stderr @@ -2,8 +2,11 @@ error: function is never used: `foo` --> $DIR/with-core-crate.rs:7:4 | LL | fn foo() { - | ^^^ + | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/with-core-crate.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/write-only-field.stderr b/src/test/ui/lint/dead-code/write-only-field.stderr index a191d22c8b94c..a7dcb69e2e366 100644 --- a/src/test/ui/lint/dead-code/write-only-field.stderr +++ b/src/test/ui/lint/dead-code/write-only-field.stderr @@ -2,8 +2,11 @@ error: field is never read: `f` --> $DIR/write-only-field.rs:4:5 | LL | f: i32, - | ^^^^^^ + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_f` | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/write-only-field.rs:1:9 | @@ -14,31 +17,51 @@ error: field is never read: `sub` --> $DIR/write-only-field.rs:5:5 | LL | sub: Sub, - | ^^^^^^^^ + | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_sub` + | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) error: field is never read: `f` --> $DIR/write-only-field.rs:9:5 | LL | f: i32, - | ^^^^^^ + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_f` + | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) error: field is never read: `y` --> $DIR/write-only-field.rs:28:9 | LL | y: bool, - | ^^^^^^^ + | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_y` + | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) error: field is never read: `u` --> $DIR/write-only-field.rs:58:9 | LL | u: u32, - | ^^^^^^ + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_u` + | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) error: field is never read: `v` --> $DIR/write-only-field.rs:59:9 | LL | v: u32, - | ^^^^^^ + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_v` + | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) error: aborting due to 6 previous errors diff --git a/src/test/ui/lint/issue-17718-const-naming.stderr b/src/test/ui/lint/issue-17718-const-naming.stderr index ce4ebcb5e3ef6..f0d95f5b83d2f 100644 --- a/src/test/ui/lint/issue-17718-const-naming.stderr +++ b/src/test/ui/lint/issue-17718-const-naming.stderr @@ -2,8 +2,11 @@ error: constant is never used: `foo` --> $DIR/issue-17718-const-naming.rs:4:1 | LL | const foo: isize = 3; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_foo` | + = note: the leading underscore helps signal to the reader that the constant may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the constant + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/issue-17718-const-naming.rs:2:9 | diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr index 45cf5f8688cd1..91f9f271e5ceb 100644 --- a/src/test/ui/span/macro-span-replacement.stderr +++ b/src/test/ui/span/macro-span-replacement.stderr @@ -2,11 +2,14 @@ warning: struct is never constructed: `S` --> $DIR/macro-span-replacement.rs:7:14 | LL | $b $a; - | ^ + | ^ help: if this is intentional, prefix it with an underscore: `_S` ... LL | m!(S struct); | ------------- in this macro invocation | + = note: the leading underscore helps signal to the reader that the struct may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the struct + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/macro-span-replacement.rs:3:9 | diff --git a/src/test/ui/span/unused-warning-point-at-identifier.stderr b/src/test/ui/span/unused-warning-point-at-identifier.stderr index 6ef877da122f5..21579fbd92b7c 100644 --- a/src/test/ui/span/unused-warning-point-at-identifier.stderr +++ b/src/test/ui/span/unused-warning-point-at-identifier.stderr @@ -2,8 +2,11 @@ warning: enum is never used: `Enum` --> $DIR/unused-warning-point-at-identifier.rs:5:6 | LL | enum Enum { - | ^^^^ + | ^^^^ help: if this is intentional, prefix it with an underscore: `_Enum` | + = note: the leading underscore helps signal to the reader that the enum may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the enum + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/unused-warning-point-at-identifier.rs:3:9 | @@ -15,19 +18,31 @@ warning: struct is never constructed: `Struct` --> $DIR/unused-warning-point-at-identifier.rs:12:8 | LL | struct Struct { - | ^^^^^^ + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_Struct` + | + = note: the leading underscore helps signal to the reader that the struct may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the struct + is only used through FFI or used only for its effect when dropped) warning: function is never used: `func` --> $DIR/unused-warning-point-at-identifier.rs:19:4 | LL | fn func() -> usize { - | ^^^^ + | ^^^^ help: if this is intentional, prefix it with an underscore: `_func` + | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) warning: function is never used: `func_complete_span` --> $DIR/unused-warning-point-at-identifier.rs:24:1 | LL | func_complete_span() - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_func_complete_span` + | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) warning: 4 warnings emitted diff --git a/src/test/ui/test-attrs/test-warns-dead-code.stderr b/src/test/ui/test-attrs/test-warns-dead-code.stderr index d3bcea2951364..d41a4e54985a2 100644 --- a/src/test/ui/test-attrs/test-warns-dead-code.stderr +++ b/src/test/ui/test-attrs/test-warns-dead-code.stderr @@ -2,8 +2,11 @@ error: function is never used: `dead` --> $DIR/test-warns-dead-code.rs:5:4 | LL | fn dead() {} - | ^^^^ + | ^^^^ help: if this is intentional, prefix it with an underscore: `_dead` | + = note: the leading underscore helps signal to the reader that the function may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the function + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/test-warns-dead-code.rs:3:9 | diff --git a/src/test/ui/union/union-fields-1.stderr b/src/test/ui/union/union-fields-1.stderr index 87621cc01b1b9..9c90e94ff91bf 100644 --- a/src/test/ui/union/union-fields-1.stderr +++ b/src/test/ui/union/union-fields-1.stderr @@ -2,8 +2,11 @@ error: field is never read: `c` --> $DIR/union-fields-1.rs:6:5 | LL | c: u8, - | ^^^^^ + | ^^^^^ help: if this is intentional, prefix it with an underscore: `_c` | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/union-fields-1.rs:1:9 | @@ -14,19 +17,31 @@ error: field is never read: `a` --> $DIR/union-fields-1.rs:9:5 | LL | a: u8, - | ^^^^^ + | ^^^^^ help: if this is intentional, prefix it with an underscore: `_a` + | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) error: field is never read: `a` --> $DIR/union-fields-1.rs:13:20 | LL | union NoDropLike { a: u8 } - | ^^^^^ + | ^^^^^ help: if this is intentional, prefix it with an underscore: `_a` + | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) error: field is never read: `c` --> $DIR/union-fields-1.rs:18:5 | LL | c: u8, - | ^^^^^ + | ^^^^^ help: if this is intentional, prefix it with an underscore: `_c` + | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) error: aborting due to 4 previous errors diff --git a/src/test/ui/union/union-lint-dead-code.stderr b/src/test/ui/union/union-lint-dead-code.stderr index 7de70ec33801f..6dfeae0248455 100644 --- a/src/test/ui/union/union-lint-dead-code.stderr +++ b/src/test/ui/union/union-lint-dead-code.stderr @@ -2,8 +2,11 @@ error: field is never read: `b` --> $DIR/union-lint-dead-code.rs:5:5 | LL | b: bool, - | ^^^^^^^ + | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_b` | + = note: the leading underscore helps signal to the reader that the field may still serve + a purpose even if it isn't used in a way that we can detect (e.g. the field + is only used through FFI or used only for its effect when dropped) note: the lint level is defined here --> $DIR/union-lint-dead-code.rs:1:9 | From 789186d8befacb9ea933dd80c02e7ca49e190df0 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Thu, 11 Mar 2021 23:00:22 -0800 Subject: [PATCH 04/32] Trying out a new message that works a little better for values *and* items --- compiler/rustc_passes/src/dead.rs | 9 +-- .../associated-const-dead-code.stderr | 7 +- .../ui/derive-uninhabited-enum-38885.stderr | 7 +- src/test/ui/issues/issue-37515.stderr | 7 +- src/test/ui/lint/dead-code/basic.stderr | 7 +- .../ui/lint/dead-code/const-and-self.stderr | 14 ++-- .../drop-only-field-issue-81658.stderr | 7 +- .../lint/dead-code/empty-unused-enum.stderr | 7 +- .../field-used-in-ffi-issue-81658.stderr | 7 +- src/test/ui/lint/dead-code/impl-trait.stderr | 7 +- .../ui/lint/dead-code/lint-dead-code-1.stderr | 70 +++++++++++-------- .../ui/lint/dead-code/lint-dead-code-2.stderr | 21 +++--- .../ui/lint/dead-code/lint-dead-code-3.stderr | 35 ++++++---- .../ui/lint/dead-code/lint-dead-code-4.stderr | 70 +++++++++++-------- .../ui/lint/dead-code/lint-dead-code-5.stderr | 28 ++++---- .../ui/lint/dead-code/lint-dead-code-6.stderr | 28 ++++---- .../ui/lint/dead-code/newline-span.stderr | 21 +++--- src/test/ui/lint/dead-code/type-alias.stderr | 7 +- src/test/ui/lint/dead-code/unused-enum.stderr | 21 +++--- .../dead-code/unused-struct-variant.stderr | 7 +- .../ui/lint/dead-code/unused-variant.stderr | 7 +- .../ui/lint/dead-code/with-core-crate.stderr | 7 +- .../ui/lint/dead-code/write-only-field.stderr | 42 ++++++----- .../ui/lint/issue-17718-const-naming.stderr | 7 +- .../ui/span/macro-span-replacement.stderr | 7 +- .../unused-warning-point-at-identifier.stderr | 28 ++++---- .../ui/test-attrs/test-warns-dead-code.stderr | 7 +- src/test/ui/union/union-fields-1.stderr | 28 ++++---- src/test/ui/union/union-lint-dead-code.stderr | 7 +- 29 files changed, 301 insertions(+), 226 deletions(-) diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 0457d287e01e8..8df91645626a3 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -589,10 +589,11 @@ impl DeadVisitor<'tcx> { Applicability::MachineApplicable, ) .note(&format!( - "the leading underscore helps signal to the reader that the {} may still serve\n\ - a purpose even if it isn't used in a way that we can detect (e.g. the {}\nis \ - only used through FFI or used only for its effect when dropped)", - descr, descr, + "The leading underscore signals to the reader that while the {} may not be {}\n\ + by any Rust code, it still serves some other purpose that isn't detected by rustc.\n\ + (e.g. some values are used for their effect when dropped or used in FFI code\n\ + exclusively through raw pointers)", + descr, participle, )); // Force the note we added to the front, before any other subdiagnostics diag.children.rotate_right(1); diff --git a/src/test/ui/associated-consts/associated-const-dead-code.stderr b/src/test/ui/associated-consts/associated-const-dead-code.stderr index 60c227ef557f5..9cf817905cc0a 100644 --- a/src/test/ui/associated-consts/associated-const-dead-code.stderr +++ b/src/test/ui/associated-consts/associated-const-dead-code.stderr @@ -4,9 +4,10 @@ error: associated constant is never used: `BAR` LL | const BAR: u32 = 1; | ^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_BAR` | - = note: the leading underscore helps signal to the reader that the associated constant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the associated constant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the associated constant may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/associated-const-dead-code.rs:1:9 | diff --git a/src/test/ui/derive-uninhabited-enum-38885.stderr b/src/test/ui/derive-uninhabited-enum-38885.stderr index 7aa5fc4d15b48..de151b915d0a7 100644 --- a/src/test/ui/derive-uninhabited-enum-38885.stderr +++ b/src/test/ui/derive-uninhabited-enum-38885.stderr @@ -4,9 +4,10 @@ warning: variant is never constructed: `Void` LL | Void(Void), | ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Void` | - = note: the leading underscore helps signal to the reader that the variant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the variant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the variant may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) = note: `-W dead-code` implied by `-W unused` warning: 1 warning emitted diff --git a/src/test/ui/issues/issue-37515.stderr b/src/test/ui/issues/issue-37515.stderr index 683602ce8af97..02da48748ec13 100644 --- a/src/test/ui/issues/issue-37515.stderr +++ b/src/test/ui/issues/issue-37515.stderr @@ -4,9 +4,10 @@ warning: type alias is never used: `Z` LL | type Z = dyn for<'x> Send; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Z` | - = note: the leading underscore helps signal to the reader that the type alias may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the type alias - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the type alias may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/issue-37515.rs:3:9 | diff --git a/src/test/ui/lint/dead-code/basic.stderr b/src/test/ui/lint/dead-code/basic.stderr index f42008b4f0d1b..4b165c30003a6 100644 --- a/src/test/ui/lint/dead-code/basic.stderr +++ b/src/test/ui/lint/dead-code/basic.stderr @@ -4,9 +4,10 @@ error: function is never used: `foo` LL | fn foo() { | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/basic.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/const-and-self.stderr b/src/test/ui/lint/dead-code/const-and-self.stderr index 0e2e66cfef7b1..80da402f79817 100644 --- a/src/test/ui/lint/dead-code/const-and-self.stderr +++ b/src/test/ui/lint/dead-code/const-and-self.stderr @@ -4,9 +4,10 @@ warning: variant is never constructed: `B` LL | B, | ^ help: if this is intentional, prefix it with an underscore: `_B` | - = note: the leading underscore helps signal to the reader that the variant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the variant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the variant may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/const-and-self.rs:3:9 | @@ -19,9 +20,10 @@ warning: variant is never constructed: `C` LL | C, | ^ help: if this is intentional, prefix it with an underscore: `_C` | - = note: the leading underscore helps signal to the reader that the variant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the variant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the variant may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) warning: 2 warnings emitted diff --git a/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr index 8c5a5f0a7e5bf..dc9dcb770df0b 100644 --- a/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr +++ b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr @@ -4,9 +4,10 @@ error: field is never read: `guard` LL | guard: MutexGuard<'a, T>, | ^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_guard` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/drop-only-field-issue-81658.rs:8:9 | diff --git a/src/test/ui/lint/dead-code/empty-unused-enum.stderr b/src/test/ui/lint/dead-code/empty-unused-enum.stderr index 8e16d24c001d5..8fa3ae27af3ea 100644 --- a/src/test/ui/lint/dead-code/empty-unused-enum.stderr +++ b/src/test/ui/lint/dead-code/empty-unused-enum.stderr @@ -4,9 +4,10 @@ error: enum is never used: `E` LL | enum E {} | ^ help: if this is intentional, prefix it with an underscore: `_E` | - = note: the leading underscore helps signal to the reader that the enum may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the enum - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the enum may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/empty-unused-enum.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr index d5b5ee777dc07..e2f6849304d39 100644 --- a/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr +++ b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr @@ -4,9 +4,10 @@ error: field is never read: `items` LL | items: Option>, | ^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_items` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/field-used-in-ffi-issue-81658.rs:7:9 | diff --git a/src/test/ui/lint/dead-code/impl-trait.stderr b/src/test/ui/lint/dead-code/impl-trait.stderr index fe3d4a8a214b6..bca3c4002de70 100644 --- a/src/test/ui/lint/dead-code/impl-trait.stderr +++ b/src/test/ui/lint/dead-code/impl-trait.stderr @@ -4,9 +4,10 @@ error: type alias is never used: `Unused` LL | type Unused = (); | ^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Unused` | - = note: the leading underscore helps signal to the reader that the type alias may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the type alias - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the type alias may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/impl-trait.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr index 7d1038db4b289..bd1de549134a0 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr @@ -4,9 +4,10 @@ error: struct is never constructed: `Bar` LL | pub struct Bar; | ^^^ help: if this is intentional, prefix it with an underscore: `_Bar` | - = note: the leading underscore helps signal to the reader that the struct may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the struct - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the struct may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/lint-dead-code-1.rs:5:9 | @@ -19,9 +20,10 @@ error: static is never used: `priv_static` LL | static priv_static: isize = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_static` | - = note: the leading underscore helps signal to the reader that the static may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the static - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the static may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: constant is never used: `priv_const` --> $DIR/lint-dead-code-1.rs:27:1 @@ -29,9 +31,10 @@ error: constant is never used: `priv_const` LL | const priv_const: isize = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_const` | - = note: the leading underscore helps signal to the reader that the constant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the constant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the constant may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: struct is never constructed: `PrivStruct` --> $DIR/lint-dead-code-1.rs:35:8 @@ -39,9 +42,10 @@ error: struct is never constructed: `PrivStruct` LL | struct PrivStruct; | ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_PrivStruct` | - = note: the leading underscore helps signal to the reader that the struct may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the struct - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the struct may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: enum is never used: `priv_enum` --> $DIR/lint-dead-code-1.rs:64:6 @@ -49,9 +53,10 @@ error: enum is never used: `priv_enum` LL | enum priv_enum { foo2, bar2 } | ^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_enum` | - = note: the leading underscore helps signal to the reader that the enum may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the enum - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the enum may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: variant is never constructed: `bar3` --> $DIR/lint-dead-code-1.rs:67:5 @@ -59,9 +64,10 @@ error: variant is never constructed: `bar3` LL | bar3 | ^^^^ help: if this is intentional, prefix it with an underscore: `_bar3` | - = note: the leading underscore helps signal to the reader that the variant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the variant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the variant may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: function is never used: `priv_fn` --> $DIR/lint-dead-code-1.rs:88:4 @@ -69,9 +75,10 @@ error: function is never used: `priv_fn` LL | fn priv_fn() { | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_fn` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: function is never used: `foo` --> $DIR/lint-dead-code-1.rs:93:4 @@ -79,9 +86,10 @@ error: function is never used: `foo` LL | fn foo() { | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: function is never used: `bar` --> $DIR/lint-dead-code-1.rs:98:4 @@ -89,9 +97,10 @@ error: function is never used: `bar` LL | fn bar() { | ^^^ help: if this is intentional, prefix it with an underscore: `_bar` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: function is never used: `baz` --> $DIR/lint-dead-code-1.rs:102:4 @@ -99,9 +108,10 @@ error: function is never used: `baz` LL | fn baz() -> impl Copy { | ^^^ help: if this is intentional, prefix it with an underscore: `_baz` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: aborting due to 10 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-2.stderr b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr index f840daee7a0c7..ecc0169eadd56 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-2.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr @@ -4,9 +4,10 @@ error: function is never used: `dead_fn` LL | fn dead_fn() {} | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_dead_fn` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/lint-dead-code-2.rs:2:9 | @@ -19,9 +20,10 @@ error: function is never used: `dead_fn2` LL | fn dead_fn2() {} | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_dead_fn2` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: function is never used: `main` --> $DIR/lint-dead-code-2.rs:38:4 @@ -29,9 +31,10 @@ error: function is never used: `main` LL | fn main() { | ^^^^ help: if this is intentional, prefix it with an underscore: `_main` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr index ad7fec0181519..53ccae0f0cec6 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr @@ -4,9 +4,10 @@ error: struct is never constructed: `Foo` LL | struct Foo; | ^^^ help: if this is intentional, prefix it with an underscore: `_Foo` | - = note: the leading underscore helps signal to the reader that the struct may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the struct - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the struct may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/lint-dead-code-3.rs:4:9 | @@ -19,9 +20,10 @@ error: associated function is never used: `foo` LL | fn foo(&self) { | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` | - = note: the leading underscore helps signal to the reader that the associated function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the associated function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the associated function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: function is never used: `bar` --> $DIR/lint-dead-code-3.rs:21:4 @@ -29,9 +31,10 @@ error: function is never used: `bar` LL | fn bar() { | ^^^ help: if this is intentional, prefix it with an underscore: `_bar` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: enum is never used: `c_void` --> $DIR/lint-dead-code-3.rs:60:6 @@ -39,9 +42,10 @@ error: enum is never used: `c_void` LL | enum c_void {} | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_c_void` | - = note: the leading underscore helps signal to the reader that the enum may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the enum - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the enum may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: function is never used: `free` --> $DIR/lint-dead-code-3.rs:62:5 @@ -49,9 +53,10 @@ error: function is never used: `free` LL | fn free(p: *const c_void); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_free` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: aborting due to 5 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr index 7fd275159c2eb..23e4a5ca69187 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr @@ -4,9 +4,10 @@ error: field is never read: `b` LL | b: bool, | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_b` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/lint-dead-code-4.rs:3:9 | @@ -19,9 +20,10 @@ error: variant is never constructed: `X` LL | X, | ^ help: if this is intentional, prefix it with an underscore: `_X` | - = note: the leading underscore helps signal to the reader that the variant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the variant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the variant may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: variant is never constructed: `Y` --> $DIR/lint-dead-code-4.rs:16:5 @@ -33,9 +35,10 @@ LL | | c: i32, LL | | }, | |_____^ help: if this is intentional, prefix it with an underscore: `_Y` | - = note: the leading underscore helps signal to the reader that the variant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the variant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the variant may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: enum is never used: `ABC` --> $DIR/lint-dead-code-4.rs:24:6 @@ -43,9 +46,10 @@ error: enum is never used: `ABC` LL | enum ABC { | ^^^ help: if this is intentional, prefix it with an underscore: `_ABC` | - = note: the leading underscore helps signal to the reader that the enum may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the enum - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the enum may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: variant is never constructed: `I` --> $DIR/lint-dead-code-4.rs:36:5 @@ -53,9 +57,10 @@ error: variant is never constructed: `I` LL | I, | ^ help: if this is intentional, prefix it with an underscore: `_I` | - = note: the leading underscore helps signal to the reader that the variant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the variant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the variant may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: field is never read: `b` --> $DIR/lint-dead-code-4.rs:39:9 @@ -63,9 +68,10 @@ error: field is never read: `b` LL | b: i32, | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_b` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: field is never read: `c` --> $DIR/lint-dead-code-4.rs:40:9 @@ -73,9 +79,10 @@ error: field is never read: `c` LL | c: i32, | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_c` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: variant is never constructed: `K` --> $DIR/lint-dead-code-4.rs:42:5 @@ -83,9 +90,10 @@ error: variant is never constructed: `K` LL | K | ^ help: if this is intentional, prefix it with an underscore: `_K` | - = note: the leading underscore helps signal to the reader that the variant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the variant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the variant may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: field is never read: `x` --> $DIR/lint-dead-code-4.rs:61:5 @@ -93,9 +101,10 @@ error: field is never read: `x` LL | x: usize, | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_x` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: field is never read: `c` --> $DIR/lint-dead-code-4.rs:63:5 @@ -103,9 +112,10 @@ error: field is never read: `c` LL | c: bool, | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_c` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: aborting due to 10 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr index d0868af5f4473..b0fcb9a199ca4 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr @@ -4,9 +4,10 @@ error: variant is never constructed: `Variant2` LL | Variant2 | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant2` | - = note: the leading underscore helps signal to the reader that the variant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the variant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the variant may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/lint-dead-code-5.rs:2:9 | @@ -19,9 +20,10 @@ error: variant is never constructed: `Variant5` LL | Variant5 { _x: isize }, | ^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant5` | - = note: the leading underscore helps signal to the reader that the variant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the variant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the variant may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: variant is never constructed: `Variant6` --> $DIR/lint-dead-code-5.rs:14:5 @@ -29,9 +31,10 @@ error: variant is never constructed: `Variant6` LL | Variant6(isize), | ^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant6` | - = note: the leading underscore helps signal to the reader that the variant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the variant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the variant may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: enum is never used: `Enum3` --> $DIR/lint-dead-code-5.rs:35:6 @@ -39,9 +42,10 @@ error: enum is never used: `Enum3` LL | enum Enum3 { | ^^^^^ help: if this is intentional, prefix it with an underscore: `_Enum3` | - = note: the leading underscore helps signal to the reader that the enum may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the enum - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the enum may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: aborting due to 4 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-6.stderr b/src/test/ui/lint/dead-code/lint-dead-code-6.stderr index 687a49eb7619a..58714084ed3b5 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-6.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-6.stderr @@ -4,9 +4,10 @@ error: struct is never constructed: `UnusedStruct` LL | struct UnusedStruct; | ^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_UnusedStruct` | - = note: the leading underscore helps signal to the reader that the struct may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the struct - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the struct may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/lint-dead-code-6.rs:1:9 | @@ -19,9 +20,10 @@ error: associated function is never used: `unused_impl_fn_1` LL | fn unused_impl_fn_1() { | ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_impl_fn_1` | - = note: the leading underscore helps signal to the reader that the associated function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the associated function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the associated function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: associated function is never used: `unused_impl_fn_2` --> $DIR/lint-dead-code-6.rs:9:8 @@ -29,9 +31,10 @@ error: associated function is never used: `unused_impl_fn_2` LL | fn unused_impl_fn_2(var: i32) { | ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_impl_fn_2` | - = note: the leading underscore helps signal to the reader that the associated function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the associated function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the associated function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: associated function is never used: `unused_impl_fn_3` --> $DIR/lint-dead-code-6.rs:13:8 @@ -39,9 +42,10 @@ error: associated function is never used: `unused_impl_fn_3` LL | fn unused_impl_fn_3( | ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_impl_fn_3` | - = note: the leading underscore helps signal to the reader that the associated function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the associated function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the associated function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: aborting due to 4 previous errors diff --git a/src/test/ui/lint/dead-code/newline-span.stderr b/src/test/ui/lint/dead-code/newline-span.stderr index b636079631c35..cfe83cff7c5ea 100644 --- a/src/test/ui/lint/dead-code/newline-span.stderr +++ b/src/test/ui/lint/dead-code/newline-span.stderr @@ -4,9 +4,10 @@ error: function is never used: `unused` LL | fn unused() { | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/newline-span.rs:1:9 | @@ -19,9 +20,10 @@ error: function is never used: `unused2` LL | fn unused2(var: i32) { | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused2` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: function is never used: `unused3` --> $DIR/newline-span.rs:11:4 @@ -29,9 +31,10 @@ error: function is never used: `unused3` LL | fn unused3( | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused3` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/dead-code/type-alias.stderr b/src/test/ui/lint/dead-code/type-alias.stderr index 5c11626bb1e44..3533209eb1ddf 100644 --- a/src/test/ui/lint/dead-code/type-alias.stderr +++ b/src/test/ui/lint/dead-code/type-alias.stderr @@ -4,9 +4,10 @@ error: type alias is never used: `Unused` LL | type Unused = u8; | ^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Unused` | - = note: the leading underscore helps signal to the reader that the type alias may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the type alias - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the type alias may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/type-alias.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/unused-enum.stderr b/src/test/ui/lint/dead-code/unused-enum.stderr index c71d305987c77..646ec2b701fee 100644 --- a/src/test/ui/lint/dead-code/unused-enum.stderr +++ b/src/test/ui/lint/dead-code/unused-enum.stderr @@ -4,9 +4,10 @@ error: struct is never constructed: `F` LL | struct F; | ^ help: if this is intentional, prefix it with an underscore: `_F` | - = note: the leading underscore helps signal to the reader that the struct may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the struct - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the struct may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/unused-enum.rs:1:9 | @@ -20,9 +21,10 @@ error: struct is never constructed: `B` LL | struct B; | ^ help: if this is intentional, prefix it with an underscore: `_B` | - = note: the leading underscore helps signal to the reader that the struct may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the struct - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the struct may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: enum is never used: `E` --> $DIR/unused-enum.rs:6:6 @@ -30,9 +32,10 @@ error: enum is never used: `E` LL | enum E { | ^ help: if this is intentional, prefix it with an underscore: `_E` | - = note: the leading underscore helps signal to the reader that the enum may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the enum - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the enum may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/dead-code/unused-struct-variant.stderr b/src/test/ui/lint/dead-code/unused-struct-variant.stderr index 198986bde049d..9fe2259d89db7 100644 --- a/src/test/ui/lint/dead-code/unused-struct-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-struct-variant.stderr @@ -4,9 +4,10 @@ error: variant is never constructed: `Bar` LL | Bar(B), | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_Bar` | - = note: the leading underscore helps signal to the reader that the variant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the variant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the variant may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/unused-struct-variant.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/unused-variant.stderr b/src/test/ui/lint/dead-code/unused-variant.stderr index 5fff7b1fdb3e0..a8eacf580c257 100644 --- a/src/test/ui/lint/dead-code/unused-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-variant.stderr @@ -4,9 +4,10 @@ error: variant is never constructed: `Variant1` LL | Variant1, | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant1` | - = note: the leading underscore helps signal to the reader that the variant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the variant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the variant may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/unused-variant.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/with-core-crate.stderr b/src/test/ui/lint/dead-code/with-core-crate.stderr index ab4c1793b0667..386a17e953fac 100644 --- a/src/test/ui/lint/dead-code/with-core-crate.stderr +++ b/src/test/ui/lint/dead-code/with-core-crate.stderr @@ -4,9 +4,10 @@ error: function is never used: `foo` LL | fn foo() { | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/with-core-crate.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/write-only-field.stderr b/src/test/ui/lint/dead-code/write-only-field.stderr index a7dcb69e2e366..ac307de729ca5 100644 --- a/src/test/ui/lint/dead-code/write-only-field.stderr +++ b/src/test/ui/lint/dead-code/write-only-field.stderr @@ -4,9 +4,10 @@ error: field is never read: `f` LL | f: i32, | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_f` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/write-only-field.rs:1:9 | @@ -19,9 +20,10 @@ error: field is never read: `sub` LL | sub: Sub, | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_sub` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: field is never read: `f` --> $DIR/write-only-field.rs:9:5 @@ -29,9 +31,10 @@ error: field is never read: `f` LL | f: i32, | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_f` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: field is never read: `y` --> $DIR/write-only-field.rs:28:9 @@ -39,9 +42,10 @@ error: field is never read: `y` LL | y: bool, | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_y` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: field is never read: `u` --> $DIR/write-only-field.rs:58:9 @@ -49,9 +53,10 @@ error: field is never read: `u` LL | u: u32, | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_u` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: field is never read: `v` --> $DIR/write-only-field.rs:59:9 @@ -59,9 +64,10 @@ error: field is never read: `v` LL | v: u32, | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_v` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: aborting due to 6 previous errors diff --git a/src/test/ui/lint/issue-17718-const-naming.stderr b/src/test/ui/lint/issue-17718-const-naming.stderr index f0d95f5b83d2f..a7805c3b8788f 100644 --- a/src/test/ui/lint/issue-17718-const-naming.stderr +++ b/src/test/ui/lint/issue-17718-const-naming.stderr @@ -4,9 +4,10 @@ error: constant is never used: `foo` LL | const foo: isize = 3; | ^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_foo` | - = note: the leading underscore helps signal to the reader that the constant may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the constant - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the constant may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/issue-17718-const-naming.rs:2:9 | diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr index 91f9f271e5ceb..b432bcb947eac 100644 --- a/src/test/ui/span/macro-span-replacement.stderr +++ b/src/test/ui/span/macro-span-replacement.stderr @@ -7,9 +7,10 @@ LL | $b $a; LL | m!(S struct); | ------------- in this macro invocation | - = note: the leading underscore helps signal to the reader that the struct may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the struct - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the struct may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/macro-span-replacement.rs:3:9 | diff --git a/src/test/ui/span/unused-warning-point-at-identifier.stderr b/src/test/ui/span/unused-warning-point-at-identifier.stderr index 21579fbd92b7c..f6d8dad9b9090 100644 --- a/src/test/ui/span/unused-warning-point-at-identifier.stderr +++ b/src/test/ui/span/unused-warning-point-at-identifier.stderr @@ -4,9 +4,10 @@ warning: enum is never used: `Enum` LL | enum Enum { | ^^^^ help: if this is intentional, prefix it with an underscore: `_Enum` | - = note: the leading underscore helps signal to the reader that the enum may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the enum - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the enum may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/unused-warning-point-at-identifier.rs:3:9 | @@ -20,9 +21,10 @@ warning: struct is never constructed: `Struct` LL | struct Struct { | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_Struct` | - = note: the leading underscore helps signal to the reader that the struct may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the struct - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the struct may not be constructed + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) warning: function is never used: `func` --> $DIR/unused-warning-point-at-identifier.rs:19:4 @@ -30,9 +32,10 @@ warning: function is never used: `func` LL | fn func() -> usize { | ^^^^ help: if this is intentional, prefix it with an underscore: `_func` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) warning: function is never used: `func_complete_span` --> $DIR/unused-warning-point-at-identifier.rs:24:1 @@ -40,9 +43,10 @@ warning: function is never used: `func_complete_span` LL | func_complete_span() | ^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_func_complete_span` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) warning: 4 warnings emitted diff --git a/src/test/ui/test-attrs/test-warns-dead-code.stderr b/src/test/ui/test-attrs/test-warns-dead-code.stderr index d41a4e54985a2..0ab483e485c0f 100644 --- a/src/test/ui/test-attrs/test-warns-dead-code.stderr +++ b/src/test/ui/test-attrs/test-warns-dead-code.stderr @@ -4,9 +4,10 @@ error: function is never used: `dead` LL | fn dead() {} | ^^^^ help: if this is intentional, prefix it with an underscore: `_dead` | - = note: the leading underscore helps signal to the reader that the function may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the function - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the function may not be used + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/test-warns-dead-code.rs:3:9 | diff --git a/src/test/ui/union/union-fields-1.stderr b/src/test/ui/union/union-fields-1.stderr index 9c90e94ff91bf..1e0d6f48eb73a 100644 --- a/src/test/ui/union/union-fields-1.stderr +++ b/src/test/ui/union/union-fields-1.stderr @@ -4,9 +4,10 @@ error: field is never read: `c` LL | c: u8, | ^^^^^ help: if this is intentional, prefix it with an underscore: `_c` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/union-fields-1.rs:1:9 | @@ -19,9 +20,10 @@ error: field is never read: `a` LL | a: u8, | ^^^^^ help: if this is intentional, prefix it with an underscore: `_a` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: field is never read: `a` --> $DIR/union-fields-1.rs:13:20 @@ -29,9 +31,10 @@ error: field is never read: `a` LL | union NoDropLike { a: u8 } | ^^^^^ help: if this is intentional, prefix it with an underscore: `_a` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: field is never read: `c` --> $DIR/union-fields-1.rs:18:5 @@ -39,9 +42,10 @@ error: field is never read: `c` LL | c: u8, | ^^^^^ help: if this is intentional, prefix it with an underscore: `_c` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) error: aborting due to 4 previous errors diff --git a/src/test/ui/union/union-lint-dead-code.stderr b/src/test/ui/union/union-lint-dead-code.stderr index 6dfeae0248455..0e8546ec19803 100644 --- a/src/test/ui/union/union-lint-dead-code.stderr +++ b/src/test/ui/union/union-lint-dead-code.stderr @@ -4,9 +4,10 @@ error: field is never read: `b` LL | b: bool, | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_b` | - = note: the leading underscore helps signal to the reader that the field may still serve - a purpose even if it isn't used in a way that we can detect (e.g. the field - is only used through FFI or used only for its effect when dropped) + = note: The leading underscore signals to the reader that while the field may not be read + by any Rust code, it still serves some other purpose that isn't detected by rustc. + (e.g. some values are used for their effect when dropped or used in FFI code + exclusively through raw pointers) note: the lint level is defined here --> $DIR/union-lint-dead-code.rs:1:9 | From 2acd8eb21f9ab5a28f7c64efcf0245691e619da0 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Fri, 12 Mar 2021 21:11:16 -0800 Subject: [PATCH 05/32] New shorter diagnostic note that is different for items versus fields --- compiler/rustc_passes/src/dead.rs | 54 +++++++++++---- .../associated-const-dead-code.stderr | 6 +- .../ui/derive-uninhabited-enum-38885.stderr | 6 +- src/test/ui/issues/issue-37515.stderr | 6 +- src/test/ui/lint/dead-code/basic.stderr | 6 +- .../ui/lint/dead-code/const-and-self.stderr | 12 ++-- .../drop-only-field-issue-81658.stderr | 7 +- .../lint/dead-code/empty-unused-enum.stderr | 6 +- .../field-used-in-ffi-issue-81658.stderr | 7 +- src/test/ui/lint/dead-code/impl-trait.stderr | 6 +- .../ui/lint/dead-code/lint-dead-code-1.stderr | 60 ++++++----------- .../ui/lint/dead-code/lint-dead-code-2.stderr | 18 ++--- .../ui/lint/dead-code/lint-dead-code-3.stderr | 30 +++------ .../ui/lint/dead-code/lint-dead-code-4.stderr | 65 +++++++------------ .../ui/lint/dead-code/lint-dead-code-5.stderr | 24 +++---- .../ui/lint/dead-code/lint-dead-code-6.stderr | 24 +++---- .../ui/lint/dead-code/newline-span.stderr | 18 ++--- src/test/ui/lint/dead-code/type-alias.stderr | 6 +- src/test/ui/lint/dead-code/unused-enum.stderr | 18 ++--- .../dead-code/unused-struct-variant.stderr | 6 +- .../ui/lint/dead-code/unused-variant.stderr | 6 +- .../ui/lint/dead-code/with-core-crate.stderr | 6 +- .../ui/lint/dead-code/write-only-field.stderr | 42 +++++------- .../ui/lint/issue-17718-const-naming.stderr | 6 +- .../ui/span/macro-span-replacement.stderr | 6 +- .../unused-warning-point-at-identifier.stderr | 24 +++---- .../ui/test-attrs/test-warns-dead-code.stderr | 6 +- src/test/ui/union/union-fields-1.stderr | 28 ++++---- src/test/ui/union/union-lint-dead-code.stderr | 7 +- 29 files changed, 207 insertions(+), 309 deletions(-) diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 8df91645626a3..3f6bb2c8d0f0a 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -506,6 +506,13 @@ fn find_live<'tcx>( symbol_visitor.live_symbols } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +enum ExtraNote { + /// Use this to provide some examples in the diagnostic of potential other purposes for a value + /// or field that is dead code + OtherPurposeExamples, +} + struct DeadVisitor<'tcx> { tcx: TyCtxt<'tcx>, live_symbols: FxHashSet, @@ -573,6 +580,7 @@ impl DeadVisitor<'tcx> { span: rustc_span::Span, name: Symbol, participle: &str, + extra_note: Option, ) { if !name.as_str().starts_with('_') { self.tcx.struct_span_lint_hir(lint::builtin::DEAD_CODE, id, span, |lint| { @@ -583,19 +591,26 @@ impl DeadVisitor<'tcx> { let mut diag = lint.build(&format!("{} is never {}: `{}`", descr, participle, name)); + diag.multipart_suggestion( "if this is intentional, prefix it with an underscore", prefixed, Applicability::MachineApplicable, - ) - .note(&format!( - "The leading underscore signals to the reader that while the {} may not be {}\n\ - by any Rust code, it still serves some other purpose that isn't detected by rustc.\n\ - (e.g. some values are used for their effect when dropped or used in FFI code\n\ - exclusively through raw pointers)", - descr, participle, - )); + ); + + let mut note = format!( + "the leading underscore signals that this {} serves some other \ + purpose\neven if it isn't used in a way that we can detect.", + descr, + ); + if matches!(extra_note, Some(ExtraNote::OtherPurposeExamples)) { + note += " (e.g. for its effect\nwhen dropped or in foreign code)"; + } + + diag.note(¬e); + // Force the note we added to the front, before any other subdiagnostics + // added in lint.build(...) diag.children.rotate_right(1); diag.emit() @@ -644,7 +659,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { hir::ItemKind::Struct(..) => "constructed", // Issue #52325 _ => "used", }; - self.warn_dead_code(item.hir_id(), span, item.ident.name, participle); + self.warn_dead_code(item.hir_id(), span, item.ident.name, participle, None); } else { // Only continue if we didn't warn intravisit::walk_item(self, item); @@ -658,7 +673,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { id: hir::HirId, ) { if self.should_warn_about_variant(&variant) { - self.warn_dead_code(variant.id, variant.span, variant.ident.name, "constructed"); + self.warn_dead_code(variant.id, variant.span, variant.ident.name, "constructed", None); } else { intravisit::walk_variant(self, variant, g, id); } @@ -666,14 +681,20 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem<'tcx>) { if self.should_warn_about_foreign_item(fi) { - self.warn_dead_code(fi.hir_id(), fi.span, fi.ident.name, "used"); + self.warn_dead_code(fi.hir_id(), fi.span, fi.ident.name, "used", None); } intravisit::walk_foreign_item(self, fi); } fn visit_field_def(&mut self, field: &'tcx hir::FieldDef<'tcx>) { if self.should_warn_about_field(&field) { - self.warn_dead_code(field.hir_id, field.span, field.ident.name, "read"); + self.warn_dead_code( + field.hir_id, + field.span, + field.ident.name, + "read", + Some(ExtraNote::OtherPurposeExamples), + ); } intravisit::walk_field_def(self, field); } @@ -687,6 +708,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { impl_item.span, impl_item.ident.name, "used", + None, ); } self.visit_nested_body(body_id) @@ -704,7 +726,13 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { } else { impl_item.ident.span }; - self.warn_dead_code(impl_item.hir_id(), span, impl_item.ident.name, "used"); + self.warn_dead_code( + impl_item.hir_id(), + span, + impl_item.ident.name, + "used", + None, + ); } self.visit_nested_body(body_id) } diff --git a/src/test/ui/associated-consts/associated-const-dead-code.stderr b/src/test/ui/associated-consts/associated-const-dead-code.stderr index 9cf817905cc0a..ebd21c66a98b1 100644 --- a/src/test/ui/associated-consts/associated-const-dead-code.stderr +++ b/src/test/ui/associated-consts/associated-const-dead-code.stderr @@ -4,10 +4,8 @@ error: associated constant is never used: `BAR` LL | const BAR: u32 = 1; | ^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_BAR` | - = note: The leading underscore signals to the reader that while the associated constant may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this associated constant serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/associated-const-dead-code.rs:1:9 | diff --git a/src/test/ui/derive-uninhabited-enum-38885.stderr b/src/test/ui/derive-uninhabited-enum-38885.stderr index de151b915d0a7..1583420697898 100644 --- a/src/test/ui/derive-uninhabited-enum-38885.stderr +++ b/src/test/ui/derive-uninhabited-enum-38885.stderr @@ -4,10 +4,8 @@ warning: variant is never constructed: `Void` LL | Void(Void), | ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Void` | - = note: The leading underscore signals to the reader that while the variant may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this variant serves some other purpose + even if it isn't used in a way that we can detect. = note: `-W dead-code` implied by `-W unused` warning: 1 warning emitted diff --git a/src/test/ui/issues/issue-37515.stderr b/src/test/ui/issues/issue-37515.stderr index 02da48748ec13..70bb990445236 100644 --- a/src/test/ui/issues/issue-37515.stderr +++ b/src/test/ui/issues/issue-37515.stderr @@ -4,10 +4,8 @@ warning: type alias is never used: `Z` LL | type Z = dyn for<'x> Send; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Z` | - = note: The leading underscore signals to the reader that while the type alias may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this type alias serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/issue-37515.rs:3:9 | diff --git a/src/test/ui/lint/dead-code/basic.stderr b/src/test/ui/lint/dead-code/basic.stderr index 4b165c30003a6..40a1b69dc2fc7 100644 --- a/src/test/ui/lint/dead-code/basic.stderr +++ b/src/test/ui/lint/dead-code/basic.stderr @@ -4,10 +4,8 @@ error: function is never used: `foo` LL | fn foo() { | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/basic.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/const-and-self.stderr b/src/test/ui/lint/dead-code/const-and-self.stderr index 80da402f79817..b22fed0e537c1 100644 --- a/src/test/ui/lint/dead-code/const-and-self.stderr +++ b/src/test/ui/lint/dead-code/const-and-self.stderr @@ -4,10 +4,8 @@ warning: variant is never constructed: `B` LL | B, | ^ help: if this is intentional, prefix it with an underscore: `_B` | - = note: The leading underscore signals to the reader that while the variant may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this variant serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/const-and-self.rs:3:9 | @@ -20,10 +18,8 @@ warning: variant is never constructed: `C` LL | C, | ^ help: if this is intentional, prefix it with an underscore: `_C` | - = note: The leading underscore signals to the reader that while the variant may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this variant serves some other purpose + even if it isn't used in a way that we can detect. warning: 2 warnings emitted diff --git a/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr index dc9dcb770df0b..4418d8d5d3033 100644 --- a/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr +++ b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr @@ -4,10 +4,9 @@ error: field is never read: `guard` LL | guard: MutexGuard<'a, T>, | ^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_guard` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) note: the lint level is defined here --> $DIR/drop-only-field-issue-81658.rs:8:9 | diff --git a/src/test/ui/lint/dead-code/empty-unused-enum.stderr b/src/test/ui/lint/dead-code/empty-unused-enum.stderr index 8fa3ae27af3ea..bd62e9a984b1a 100644 --- a/src/test/ui/lint/dead-code/empty-unused-enum.stderr +++ b/src/test/ui/lint/dead-code/empty-unused-enum.stderr @@ -4,10 +4,8 @@ error: enum is never used: `E` LL | enum E {} | ^ help: if this is intentional, prefix it with an underscore: `_E` | - = note: The leading underscore signals to the reader that while the enum may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this enum serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/empty-unused-enum.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr index e2f6849304d39..fab196a267517 100644 --- a/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr +++ b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr @@ -4,10 +4,9 @@ error: field is never read: `items` LL | items: Option>, | ^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_items` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) note: the lint level is defined here --> $DIR/field-used-in-ffi-issue-81658.rs:7:9 | diff --git a/src/test/ui/lint/dead-code/impl-trait.stderr b/src/test/ui/lint/dead-code/impl-trait.stderr index bca3c4002de70..cca84602ba857 100644 --- a/src/test/ui/lint/dead-code/impl-trait.stderr +++ b/src/test/ui/lint/dead-code/impl-trait.stderr @@ -4,10 +4,8 @@ error: type alias is never used: `Unused` LL | type Unused = (); | ^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Unused` | - = note: The leading underscore signals to the reader that while the type alias may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this type alias serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/impl-trait.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr index bd1de549134a0..7ddc89c995760 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr @@ -4,10 +4,8 @@ error: struct is never constructed: `Bar` LL | pub struct Bar; | ^^^ help: if this is intentional, prefix it with an underscore: `_Bar` | - = note: The leading underscore signals to the reader that while the struct may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this struct serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/lint-dead-code-1.rs:5:9 | @@ -20,10 +18,8 @@ error: static is never used: `priv_static` LL | static priv_static: isize = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_static` | - = note: The leading underscore signals to the reader that while the static may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this static serves some other purpose + even if it isn't used in a way that we can detect. error: constant is never used: `priv_const` --> $DIR/lint-dead-code-1.rs:27:1 @@ -31,10 +27,8 @@ error: constant is never used: `priv_const` LL | const priv_const: isize = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_const` | - = note: The leading underscore signals to the reader that while the constant may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this constant serves some other purpose + even if it isn't used in a way that we can detect. error: struct is never constructed: `PrivStruct` --> $DIR/lint-dead-code-1.rs:35:8 @@ -42,10 +36,8 @@ error: struct is never constructed: `PrivStruct` LL | struct PrivStruct; | ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_PrivStruct` | - = note: The leading underscore signals to the reader that while the struct may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this struct serves some other purpose + even if it isn't used in a way that we can detect. error: enum is never used: `priv_enum` --> $DIR/lint-dead-code-1.rs:64:6 @@ -53,10 +45,8 @@ error: enum is never used: `priv_enum` LL | enum priv_enum { foo2, bar2 } | ^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_enum` | - = note: The leading underscore signals to the reader that while the enum may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this enum serves some other purpose + even if it isn't used in a way that we can detect. error: variant is never constructed: `bar3` --> $DIR/lint-dead-code-1.rs:67:5 @@ -64,10 +54,8 @@ error: variant is never constructed: `bar3` LL | bar3 | ^^^^ help: if this is intentional, prefix it with an underscore: `_bar3` | - = note: The leading underscore signals to the reader that while the variant may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this variant serves some other purpose + even if it isn't used in a way that we can detect. error: function is never used: `priv_fn` --> $DIR/lint-dead-code-1.rs:88:4 @@ -75,10 +63,8 @@ error: function is never used: `priv_fn` LL | fn priv_fn() { | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_fn` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. error: function is never used: `foo` --> $DIR/lint-dead-code-1.rs:93:4 @@ -86,10 +72,8 @@ error: function is never used: `foo` LL | fn foo() { | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. error: function is never used: `bar` --> $DIR/lint-dead-code-1.rs:98:4 @@ -97,10 +81,8 @@ error: function is never used: `bar` LL | fn bar() { | ^^^ help: if this is intentional, prefix it with an underscore: `_bar` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. error: function is never used: `baz` --> $DIR/lint-dead-code-1.rs:102:4 @@ -108,10 +90,8 @@ error: function is never used: `baz` LL | fn baz() -> impl Copy { | ^^^ help: if this is intentional, prefix it with an underscore: `_baz` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. error: aborting due to 10 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-2.stderr b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr index ecc0169eadd56..dce763c5ed61f 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-2.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr @@ -4,10 +4,8 @@ error: function is never used: `dead_fn` LL | fn dead_fn() {} | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_dead_fn` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/lint-dead-code-2.rs:2:9 | @@ -20,10 +18,8 @@ error: function is never used: `dead_fn2` LL | fn dead_fn2() {} | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_dead_fn2` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. error: function is never used: `main` --> $DIR/lint-dead-code-2.rs:38:4 @@ -31,10 +27,8 @@ error: function is never used: `main` LL | fn main() { | ^^^^ help: if this is intentional, prefix it with an underscore: `_main` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr index 53ccae0f0cec6..a5ecc91edb060 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr @@ -4,10 +4,8 @@ error: struct is never constructed: `Foo` LL | struct Foo; | ^^^ help: if this is intentional, prefix it with an underscore: `_Foo` | - = note: The leading underscore signals to the reader that while the struct may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this struct serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/lint-dead-code-3.rs:4:9 | @@ -20,10 +18,8 @@ error: associated function is never used: `foo` LL | fn foo(&self) { | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` | - = note: The leading underscore signals to the reader that while the associated function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this associated function serves some other purpose + even if it isn't used in a way that we can detect. error: function is never used: `bar` --> $DIR/lint-dead-code-3.rs:21:4 @@ -31,10 +27,8 @@ error: function is never used: `bar` LL | fn bar() { | ^^^ help: if this is intentional, prefix it with an underscore: `_bar` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. error: enum is never used: `c_void` --> $DIR/lint-dead-code-3.rs:60:6 @@ -42,10 +36,8 @@ error: enum is never used: `c_void` LL | enum c_void {} | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_c_void` | - = note: The leading underscore signals to the reader that while the enum may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this enum serves some other purpose + even if it isn't used in a way that we can detect. error: function is never used: `free` --> $DIR/lint-dead-code-3.rs:62:5 @@ -53,10 +45,8 @@ error: function is never used: `free` LL | fn free(p: *const c_void); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_free` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. error: aborting due to 5 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr index 23e4a5ca69187..2297c172fc987 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr @@ -4,10 +4,9 @@ error: field is never read: `b` LL | b: bool, | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_b` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) note: the lint level is defined here --> $DIR/lint-dead-code-4.rs:3:9 | @@ -20,10 +19,8 @@ error: variant is never constructed: `X` LL | X, | ^ help: if this is intentional, prefix it with an underscore: `_X` | - = note: The leading underscore signals to the reader that while the variant may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this variant serves some other purpose + even if it isn't used in a way that we can detect. error: variant is never constructed: `Y` --> $DIR/lint-dead-code-4.rs:16:5 @@ -35,10 +32,8 @@ LL | | c: i32, LL | | }, | |_____^ help: if this is intentional, prefix it with an underscore: `_Y` | - = note: The leading underscore signals to the reader that while the variant may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this variant serves some other purpose + even if it isn't used in a way that we can detect. error: enum is never used: `ABC` --> $DIR/lint-dead-code-4.rs:24:6 @@ -46,10 +41,8 @@ error: enum is never used: `ABC` LL | enum ABC { | ^^^ help: if this is intentional, prefix it with an underscore: `_ABC` | - = note: The leading underscore signals to the reader that while the enum may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this enum serves some other purpose + even if it isn't used in a way that we can detect. error: variant is never constructed: `I` --> $DIR/lint-dead-code-4.rs:36:5 @@ -57,10 +50,8 @@ error: variant is never constructed: `I` LL | I, | ^ help: if this is intentional, prefix it with an underscore: `_I` | - = note: The leading underscore signals to the reader that while the variant may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this variant serves some other purpose + even if it isn't used in a way that we can detect. error: field is never read: `b` --> $DIR/lint-dead-code-4.rs:39:9 @@ -68,10 +59,9 @@ error: field is never read: `b` LL | b: i32, | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_b` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) error: field is never read: `c` --> $DIR/lint-dead-code-4.rs:40:9 @@ -79,10 +69,9 @@ error: field is never read: `c` LL | c: i32, | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_c` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) error: variant is never constructed: `K` --> $DIR/lint-dead-code-4.rs:42:5 @@ -90,10 +79,8 @@ error: variant is never constructed: `K` LL | K | ^ help: if this is intentional, prefix it with an underscore: `_K` | - = note: The leading underscore signals to the reader that while the variant may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this variant serves some other purpose + even if it isn't used in a way that we can detect. error: field is never read: `x` --> $DIR/lint-dead-code-4.rs:61:5 @@ -101,10 +88,9 @@ error: field is never read: `x` LL | x: usize, | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_x` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) error: field is never read: `c` --> $DIR/lint-dead-code-4.rs:63:5 @@ -112,10 +98,9 @@ error: field is never read: `c` LL | c: bool, | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_c` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) error: aborting due to 10 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr index b0fcb9a199ca4..afe159c2d8bba 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr @@ -4,10 +4,8 @@ error: variant is never constructed: `Variant2` LL | Variant2 | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant2` | - = note: The leading underscore signals to the reader that while the variant may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this variant serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/lint-dead-code-5.rs:2:9 | @@ -20,10 +18,8 @@ error: variant is never constructed: `Variant5` LL | Variant5 { _x: isize }, | ^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant5` | - = note: The leading underscore signals to the reader that while the variant may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this variant serves some other purpose + even if it isn't used in a way that we can detect. error: variant is never constructed: `Variant6` --> $DIR/lint-dead-code-5.rs:14:5 @@ -31,10 +27,8 @@ error: variant is never constructed: `Variant6` LL | Variant6(isize), | ^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant6` | - = note: The leading underscore signals to the reader that while the variant may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this variant serves some other purpose + even if it isn't used in a way that we can detect. error: enum is never used: `Enum3` --> $DIR/lint-dead-code-5.rs:35:6 @@ -42,10 +36,8 @@ error: enum is never used: `Enum3` LL | enum Enum3 { | ^^^^^ help: if this is intentional, prefix it with an underscore: `_Enum3` | - = note: The leading underscore signals to the reader that while the enum may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this enum serves some other purpose + even if it isn't used in a way that we can detect. error: aborting due to 4 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-6.stderr b/src/test/ui/lint/dead-code/lint-dead-code-6.stderr index 58714084ed3b5..d212a4bc443d9 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-6.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-6.stderr @@ -4,10 +4,8 @@ error: struct is never constructed: `UnusedStruct` LL | struct UnusedStruct; | ^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_UnusedStruct` | - = note: The leading underscore signals to the reader that while the struct may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this struct serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/lint-dead-code-6.rs:1:9 | @@ -20,10 +18,8 @@ error: associated function is never used: `unused_impl_fn_1` LL | fn unused_impl_fn_1() { | ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_impl_fn_1` | - = note: The leading underscore signals to the reader that while the associated function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this associated function serves some other purpose + even if it isn't used in a way that we can detect. error: associated function is never used: `unused_impl_fn_2` --> $DIR/lint-dead-code-6.rs:9:8 @@ -31,10 +27,8 @@ error: associated function is never used: `unused_impl_fn_2` LL | fn unused_impl_fn_2(var: i32) { | ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_impl_fn_2` | - = note: The leading underscore signals to the reader that while the associated function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this associated function serves some other purpose + even if it isn't used in a way that we can detect. error: associated function is never used: `unused_impl_fn_3` --> $DIR/lint-dead-code-6.rs:13:8 @@ -42,10 +36,8 @@ error: associated function is never used: `unused_impl_fn_3` LL | fn unused_impl_fn_3( | ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_impl_fn_3` | - = note: The leading underscore signals to the reader that while the associated function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this associated function serves some other purpose + even if it isn't used in a way that we can detect. error: aborting due to 4 previous errors diff --git a/src/test/ui/lint/dead-code/newline-span.stderr b/src/test/ui/lint/dead-code/newline-span.stderr index cfe83cff7c5ea..b57df1dfcedb4 100644 --- a/src/test/ui/lint/dead-code/newline-span.stderr +++ b/src/test/ui/lint/dead-code/newline-span.stderr @@ -4,10 +4,8 @@ error: function is never used: `unused` LL | fn unused() { | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/newline-span.rs:1:9 | @@ -20,10 +18,8 @@ error: function is never used: `unused2` LL | fn unused2(var: i32) { | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused2` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. error: function is never used: `unused3` --> $DIR/newline-span.rs:11:4 @@ -31,10 +27,8 @@ error: function is never used: `unused3` LL | fn unused3( | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused3` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/dead-code/type-alias.stderr b/src/test/ui/lint/dead-code/type-alias.stderr index 3533209eb1ddf..3e7298a6f2d3e 100644 --- a/src/test/ui/lint/dead-code/type-alias.stderr +++ b/src/test/ui/lint/dead-code/type-alias.stderr @@ -4,10 +4,8 @@ error: type alias is never used: `Unused` LL | type Unused = u8; | ^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Unused` | - = note: The leading underscore signals to the reader that while the type alias may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this type alias serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/type-alias.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/unused-enum.stderr b/src/test/ui/lint/dead-code/unused-enum.stderr index 646ec2b701fee..6e65e6565076f 100644 --- a/src/test/ui/lint/dead-code/unused-enum.stderr +++ b/src/test/ui/lint/dead-code/unused-enum.stderr @@ -4,10 +4,8 @@ error: struct is never constructed: `F` LL | struct F; | ^ help: if this is intentional, prefix it with an underscore: `_F` | - = note: The leading underscore signals to the reader that while the struct may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this struct serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/unused-enum.rs:1:9 | @@ -21,10 +19,8 @@ error: struct is never constructed: `B` LL | struct B; | ^ help: if this is intentional, prefix it with an underscore: `_B` | - = note: The leading underscore signals to the reader that while the struct may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this struct serves some other purpose + even if it isn't used in a way that we can detect. error: enum is never used: `E` --> $DIR/unused-enum.rs:6:6 @@ -32,10 +28,8 @@ error: enum is never used: `E` LL | enum E { | ^ help: if this is intentional, prefix it with an underscore: `_E` | - = note: The leading underscore signals to the reader that while the enum may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this enum serves some other purpose + even if it isn't used in a way that we can detect. error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/dead-code/unused-struct-variant.stderr b/src/test/ui/lint/dead-code/unused-struct-variant.stderr index 9fe2259d89db7..a5c7eea0579e6 100644 --- a/src/test/ui/lint/dead-code/unused-struct-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-struct-variant.stderr @@ -4,10 +4,8 @@ error: variant is never constructed: `Bar` LL | Bar(B), | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_Bar` | - = note: The leading underscore signals to the reader that while the variant may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this variant serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/unused-struct-variant.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/unused-variant.stderr b/src/test/ui/lint/dead-code/unused-variant.stderr index a8eacf580c257..9536c492fc04f 100644 --- a/src/test/ui/lint/dead-code/unused-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-variant.stderr @@ -4,10 +4,8 @@ error: variant is never constructed: `Variant1` LL | Variant1, | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant1` | - = note: The leading underscore signals to the reader that while the variant may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this variant serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/unused-variant.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/with-core-crate.stderr b/src/test/ui/lint/dead-code/with-core-crate.stderr index 386a17e953fac..563b0b65020ee 100644 --- a/src/test/ui/lint/dead-code/with-core-crate.stderr +++ b/src/test/ui/lint/dead-code/with-core-crate.stderr @@ -4,10 +4,8 @@ error: function is never used: `foo` LL | fn foo() { | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/with-core-crate.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/write-only-field.stderr b/src/test/ui/lint/dead-code/write-only-field.stderr index ac307de729ca5..f750beade18ec 100644 --- a/src/test/ui/lint/dead-code/write-only-field.stderr +++ b/src/test/ui/lint/dead-code/write-only-field.stderr @@ -4,10 +4,9 @@ error: field is never read: `f` LL | f: i32, | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_f` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) note: the lint level is defined here --> $DIR/write-only-field.rs:1:9 | @@ -20,10 +19,9 @@ error: field is never read: `sub` LL | sub: Sub, | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_sub` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) error: field is never read: `f` --> $DIR/write-only-field.rs:9:5 @@ -31,10 +29,9 @@ error: field is never read: `f` LL | f: i32, | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_f` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) error: field is never read: `y` --> $DIR/write-only-field.rs:28:9 @@ -42,10 +39,9 @@ error: field is never read: `y` LL | y: bool, | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_y` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) error: field is never read: `u` --> $DIR/write-only-field.rs:58:9 @@ -53,10 +49,9 @@ error: field is never read: `u` LL | u: u32, | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_u` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) error: field is never read: `v` --> $DIR/write-only-field.rs:59:9 @@ -64,10 +59,9 @@ error: field is never read: `v` LL | v: u32, | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_v` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) error: aborting due to 6 previous errors diff --git a/src/test/ui/lint/issue-17718-const-naming.stderr b/src/test/ui/lint/issue-17718-const-naming.stderr index a7805c3b8788f..0bafca2e4d785 100644 --- a/src/test/ui/lint/issue-17718-const-naming.stderr +++ b/src/test/ui/lint/issue-17718-const-naming.stderr @@ -4,10 +4,8 @@ error: constant is never used: `foo` LL | const foo: isize = 3; | ^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_foo` | - = note: The leading underscore signals to the reader that while the constant may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this constant serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/issue-17718-const-naming.rs:2:9 | diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr index b432bcb947eac..d5fad7c3b88ec 100644 --- a/src/test/ui/span/macro-span-replacement.stderr +++ b/src/test/ui/span/macro-span-replacement.stderr @@ -7,10 +7,8 @@ LL | $b $a; LL | m!(S struct); | ------------- in this macro invocation | - = note: The leading underscore signals to the reader that while the struct may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this struct serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/macro-span-replacement.rs:3:9 | diff --git a/src/test/ui/span/unused-warning-point-at-identifier.stderr b/src/test/ui/span/unused-warning-point-at-identifier.stderr index f6d8dad9b9090..0bf85d252d60c 100644 --- a/src/test/ui/span/unused-warning-point-at-identifier.stderr +++ b/src/test/ui/span/unused-warning-point-at-identifier.stderr @@ -4,10 +4,8 @@ warning: enum is never used: `Enum` LL | enum Enum { | ^^^^ help: if this is intentional, prefix it with an underscore: `_Enum` | - = note: The leading underscore signals to the reader that while the enum may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this enum serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/unused-warning-point-at-identifier.rs:3:9 | @@ -21,10 +19,8 @@ warning: struct is never constructed: `Struct` LL | struct Struct { | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_Struct` | - = note: The leading underscore signals to the reader that while the struct may not be constructed - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this struct serves some other purpose + even if it isn't used in a way that we can detect. warning: function is never used: `func` --> $DIR/unused-warning-point-at-identifier.rs:19:4 @@ -32,10 +28,8 @@ warning: function is never used: `func` LL | fn func() -> usize { | ^^^^ help: if this is intentional, prefix it with an underscore: `_func` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. warning: function is never used: `func_complete_span` --> $DIR/unused-warning-point-at-identifier.rs:24:1 @@ -43,10 +37,8 @@ warning: function is never used: `func_complete_span` LL | func_complete_span() | ^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_func_complete_span` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. warning: 4 warnings emitted diff --git a/src/test/ui/test-attrs/test-warns-dead-code.stderr b/src/test/ui/test-attrs/test-warns-dead-code.stderr index 0ab483e485c0f..795a9fb8820ce 100644 --- a/src/test/ui/test-attrs/test-warns-dead-code.stderr +++ b/src/test/ui/test-attrs/test-warns-dead-code.stderr @@ -4,10 +4,8 @@ error: function is never used: `dead` LL | fn dead() {} | ^^^^ help: if this is intentional, prefix it with an underscore: `_dead` | - = note: The leading underscore signals to the reader that while the function may not be used - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this function serves some other purpose + even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/test-warns-dead-code.rs:3:9 | diff --git a/src/test/ui/union/union-fields-1.stderr b/src/test/ui/union/union-fields-1.stderr index 1e0d6f48eb73a..e1695ca12cf72 100644 --- a/src/test/ui/union/union-fields-1.stderr +++ b/src/test/ui/union/union-fields-1.stderr @@ -4,10 +4,9 @@ error: field is never read: `c` LL | c: u8, | ^^^^^ help: if this is intentional, prefix it with an underscore: `_c` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) note: the lint level is defined here --> $DIR/union-fields-1.rs:1:9 | @@ -20,10 +19,9 @@ error: field is never read: `a` LL | a: u8, | ^^^^^ help: if this is intentional, prefix it with an underscore: `_a` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) error: field is never read: `a` --> $DIR/union-fields-1.rs:13:20 @@ -31,10 +29,9 @@ error: field is never read: `a` LL | union NoDropLike { a: u8 } | ^^^^^ help: if this is intentional, prefix it with an underscore: `_a` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) error: field is never read: `c` --> $DIR/union-fields-1.rs:18:5 @@ -42,10 +39,9 @@ error: field is never read: `c` LL | c: u8, | ^^^^^ help: if this is intentional, prefix it with an underscore: `_c` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) error: aborting due to 4 previous errors diff --git a/src/test/ui/union/union-lint-dead-code.stderr b/src/test/ui/union/union-lint-dead-code.stderr index 0e8546ec19803..565e13fb2ae1f 100644 --- a/src/test/ui/union/union-lint-dead-code.stderr +++ b/src/test/ui/union/union-lint-dead-code.stderr @@ -4,10 +4,9 @@ error: field is never read: `b` LL | b: bool, | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_b` | - = note: The leading underscore signals to the reader that while the field may not be read - by any Rust code, it still serves some other purpose that isn't detected by rustc. - (e.g. some values are used for their effect when dropped or used in FFI code - exclusively through raw pointers) + = note: the leading underscore signals that this field serves some other purpose + even if it isn't used in a way that we can detect. (e.g. for its effect + when dropped or in foreign code) note: the lint level is defined here --> $DIR/union-lint-dead-code.rs:1:9 | From 3e34eb8d7162efcd7d902e975d6501f422c148df Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Wed, 24 Mar 2021 20:23:49 -0700 Subject: [PATCH 06/32] Putting help message only under the identifier that needs to be prefixed --- compiler/rustc_passes/src/dead.rs | 28 ++++----- .../associated-const-dead-code.stderr | 7 ++- .../ui/derive-uninhabited-enum-38885.stderr | 7 ++- src/test/ui/issues/issue-37515.stderr | 7 ++- src/test/ui/lint/dead-code/basic.stderr | 3 +- .../ui/lint/dead-code/const-and-self.stderr | 6 +- .../drop-only-field-issue-81658.stderr | 8 +-- .../lint/dead-code/empty-unused-enum.stderr | 3 +- .../field-used-in-ffi-issue-81658.stderr | 8 +-- src/test/ui/lint/dead-code/impl-trait.stderr | 7 ++- .../ui/lint/dead-code/lint-dead-code-1.stderr | 38 +++++------- .../ui/lint/dead-code/lint-dead-code-2.stderr | 9 +-- .../ui/lint/dead-code/lint-dead-code-3.stderr | 19 +++--- .../ui/lint/dead-code/lint-dead-code-4.stderr | 62 +++++++++---------- .../ui/lint/dead-code/lint-dead-code-5.stderr | 20 +++--- .../ui/lint/dead-code/lint-dead-code-6.stderr | 12 ++-- .../ui/lint/dead-code/newline-span.stderr | 9 +-- src/test/ui/lint/dead-code/type-alias.stderr | 7 ++- src/test/ui/lint/dead-code/unused-enum.stderr | 9 +-- .../dead-code/unused-struct-variant.stderr | 7 ++- .../ui/lint/dead-code/unused-variant.stderr | 3 +- .../ui/lint/dead-code/with-core-crate.stderr | 3 +- .../ui/lint/dead-code/write-only-field.stderr | 48 +++++++------- .../ui/lint/issue-17718-const-naming.stderr | 7 ++- .../ui/span/macro-span-replacement.stderr | 7 ++- .../unused-warning-point-at-identifier.stderr | 12 ++-- .../ui/test-attrs/test-warns-dead-code.stderr | 3 +- src/test/ui/union/union-fields-1.stderr | 32 +++++----- src/test/ui/union/union-lint-dead-code.stderr | 8 +-- 29 files changed, 183 insertions(+), 216 deletions(-) diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 3f6bb2c8d0f0a..70b019e8468e7 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -16,7 +16,7 @@ use rustc_middle::middle::privacy; use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_session::lint; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::{sym, Ident, Symbol}; // Any local node that may call something in its body block should be // explored. For example, if it's a live Node::Item that is a @@ -578,7 +578,7 @@ impl DeadVisitor<'tcx> { &mut self, id: hir::HirId, span: rustc_span::Span, - name: Symbol, + name: Ident, participle: &str, extra_note: Option, ) { @@ -587,7 +587,7 @@ impl DeadVisitor<'tcx> { let def_id = self.tcx.hir().local_def_id(id); let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id()); - let prefixed = vec![(span, format!("_{}", name))]; + let prefixed = vec![(name.span, format!("_{}", name))]; let mut diag = lint.build(&format!("{} is never {}: `{}`", descr, participle, name)); @@ -600,11 +600,11 @@ impl DeadVisitor<'tcx> { let mut note = format!( "the leading underscore signals that this {} serves some other \ - purpose\neven if it isn't used in a way that we can detect.", + purpose even if it isn't used in a way that we can detect.", descr, ); if matches!(extra_note, Some(ExtraNote::OtherPurposeExamples)) { - note += " (e.g. for its effect\nwhen dropped or in foreign code)"; + note += " (e.g. for its effect when dropped or in foreign code)"; } diag.note(¬e); @@ -659,7 +659,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { hir::ItemKind::Struct(..) => "constructed", // Issue #52325 _ => "used", }; - self.warn_dead_code(item.hir_id(), span, item.ident.name, participle, None); + self.warn_dead_code(item.hir_id(), span, item.ident, participle, None); } else { // Only continue if we didn't warn intravisit::walk_item(self, item); @@ -673,7 +673,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { id: hir::HirId, ) { if self.should_warn_about_variant(&variant) { - self.warn_dead_code(variant.id, variant.span, variant.ident.name, "constructed", None); + self.warn_dead_code(variant.id, variant.span, variant.ident, "constructed", None); } else { intravisit::walk_variant(self, variant, g, id); } @@ -681,7 +681,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem<'tcx>) { if self.should_warn_about_foreign_item(fi) { - self.warn_dead_code(fi.hir_id(), fi.span, fi.ident.name, "used", None); + self.warn_dead_code(fi.hir_id(), fi.span, fi.ident, "used", None); } intravisit::walk_foreign_item(self, fi); } @@ -691,7 +691,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { self.warn_dead_code( field.hir_id, field.span, - field.ident.name, + field.ident, "read", Some(ExtraNote::OtherPurposeExamples), ); @@ -706,7 +706,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { self.warn_dead_code( impl_item.hir_id(), impl_item.span, - impl_item.ident.name, + impl_item.ident, "used", None, ); @@ -726,13 +726,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { } else { impl_item.ident.span }; - self.warn_dead_code( - impl_item.hir_id(), - span, - impl_item.ident.name, - "used", - None, - ); + self.warn_dead_code(impl_item.hir_id(), span, impl_item.ident, "used", None); } self.visit_nested_body(body_id) } diff --git a/src/test/ui/associated-consts/associated-const-dead-code.stderr b/src/test/ui/associated-consts/associated-const-dead-code.stderr index ebd21c66a98b1..e9915ba9e96a5 100644 --- a/src/test/ui/associated-consts/associated-const-dead-code.stderr +++ b/src/test/ui/associated-consts/associated-const-dead-code.stderr @@ -2,10 +2,11 @@ error: associated constant is never used: `BAR` --> $DIR/associated-const-dead-code.rs:6:5 | LL | const BAR: u32 = 1; - | ^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_BAR` + | ^^^^^^---^^^^^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_BAR` | - = note: the leading underscore signals that this associated constant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this associated constant serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/associated-const-dead-code.rs:1:9 | diff --git a/src/test/ui/derive-uninhabited-enum-38885.stderr b/src/test/ui/derive-uninhabited-enum-38885.stderr index 1583420697898..ff8fb9953fb53 100644 --- a/src/test/ui/derive-uninhabited-enum-38885.stderr +++ b/src/test/ui/derive-uninhabited-enum-38885.stderr @@ -2,10 +2,11 @@ warning: variant is never constructed: `Void` --> $DIR/derive-uninhabited-enum-38885.rs:13:5 | LL | Void(Void), - | ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Void` + | ----^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_Void` | - = note: the leading underscore signals that this variant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect. = note: `-W dead-code` implied by `-W unused` warning: 1 warning emitted diff --git a/src/test/ui/issues/issue-37515.stderr b/src/test/ui/issues/issue-37515.stderr index 70bb990445236..3223554a5b778 100644 --- a/src/test/ui/issues/issue-37515.stderr +++ b/src/test/ui/issues/issue-37515.stderr @@ -2,10 +2,11 @@ warning: type alias is never used: `Z` --> $DIR/issue-37515.rs:5:1 | LL | type Z = dyn for<'x> Send; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Z` + | ^^^^^-^^^^^^^^^^^^^^^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_Z` | - = note: the leading underscore signals that this type alias serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this type alias serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/issue-37515.rs:3:9 | diff --git a/src/test/ui/lint/dead-code/basic.stderr b/src/test/ui/lint/dead-code/basic.stderr index 40a1b69dc2fc7..8264d0736e03e 100644 --- a/src/test/ui/lint/dead-code/basic.stderr +++ b/src/test/ui/lint/dead-code/basic.stderr @@ -4,8 +4,7 @@ error: function is never used: `foo` LL | fn foo() { | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/basic.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/const-and-self.stderr b/src/test/ui/lint/dead-code/const-and-self.stderr index b22fed0e537c1..e7233f386cc68 100644 --- a/src/test/ui/lint/dead-code/const-and-self.stderr +++ b/src/test/ui/lint/dead-code/const-and-self.stderr @@ -4,8 +4,7 @@ warning: variant is never constructed: `B` LL | B, | ^ help: if this is intentional, prefix it with an underscore: `_B` | - = note: the leading underscore signals that this variant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/const-and-self.rs:3:9 | @@ -18,8 +17,7 @@ warning: variant is never constructed: `C` LL | C, | ^ help: if this is intentional, prefix it with an underscore: `_C` | - = note: the leading underscore signals that this variant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect. warning: 2 warnings emitted diff --git a/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr index 4418d8d5d3033..f379a0941166f 100644 --- a/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr +++ b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr @@ -2,11 +2,11 @@ error: field is never read: `guard` --> $DIR/drop-only-field-issue-81658.rs:15:5 | LL | guard: MutexGuard<'a, T>, - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_guard` + | -----^^^^^^^^^^^^^^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_guard` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) note: the lint level is defined here --> $DIR/drop-only-field-issue-81658.rs:8:9 | diff --git a/src/test/ui/lint/dead-code/empty-unused-enum.stderr b/src/test/ui/lint/dead-code/empty-unused-enum.stderr index bd62e9a984b1a..5c06cd5a6a0b2 100644 --- a/src/test/ui/lint/dead-code/empty-unused-enum.stderr +++ b/src/test/ui/lint/dead-code/empty-unused-enum.stderr @@ -4,8 +4,7 @@ error: enum is never used: `E` LL | enum E {} | ^ help: if this is intentional, prefix it with an underscore: `_E` | - = note: the leading underscore signals that this enum serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this enum serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/empty-unused-enum.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr index fab196a267517..d6a247d98e292 100644 --- a/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr +++ b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr @@ -2,11 +2,11 @@ error: field is never read: `items` --> $DIR/field-used-in-ffi-issue-81658.rs:13:5 | LL | items: Option>, - | ^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_items` + | -----^^^^^^^^^^^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_items` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) note: the lint level is defined here --> $DIR/field-used-in-ffi-issue-81658.rs:7:9 | diff --git a/src/test/ui/lint/dead-code/impl-trait.stderr b/src/test/ui/lint/dead-code/impl-trait.stderr index cca84602ba857..fb18eb2819f76 100644 --- a/src/test/ui/lint/dead-code/impl-trait.stderr +++ b/src/test/ui/lint/dead-code/impl-trait.stderr @@ -2,10 +2,11 @@ error: type alias is never used: `Unused` --> $DIR/impl-trait.rs:12:1 | LL | type Unused = (); - | ^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Unused` + | ^^^^^------^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_Unused` | - = note: the leading underscore signals that this type alias serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this type alias serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/impl-trait.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr index 7ddc89c995760..15448448e1169 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr @@ -4,8 +4,7 @@ error: struct is never constructed: `Bar` LL | pub struct Bar; | ^^^ help: if this is intentional, prefix it with an underscore: `_Bar` | - = note: the leading underscore signals that this struct serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/lint-dead-code-1.rs:5:9 | @@ -16,19 +15,21 @@ error: static is never used: `priv_static` --> $DIR/lint-dead-code-1.rs:20:1 | LL | static priv_static: isize = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_static` + | ^^^^^^^-----------^^^^^^^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_priv_static` | - = note: the leading underscore signals that this static serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this static serves some other purpose even if it isn't used in a way that we can detect. error: constant is never used: `priv_const` --> $DIR/lint-dead-code-1.rs:27:1 | LL | const priv_const: isize = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_const` + | ^^^^^^----------^^^^^^^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_priv_const` | - = note: the leading underscore signals that this constant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this constant serves some other purpose even if it isn't used in a way that we can detect. error: struct is never constructed: `PrivStruct` --> $DIR/lint-dead-code-1.rs:35:8 @@ -36,8 +37,7 @@ error: struct is never constructed: `PrivStruct` LL | struct PrivStruct; | ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_PrivStruct` | - = note: the leading underscore signals that this struct serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect. error: enum is never used: `priv_enum` --> $DIR/lint-dead-code-1.rs:64:6 @@ -45,8 +45,7 @@ error: enum is never used: `priv_enum` LL | enum priv_enum { foo2, bar2 } | ^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_enum` | - = note: the leading underscore signals that this enum serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this enum serves some other purpose even if it isn't used in a way that we can detect. error: variant is never constructed: `bar3` --> $DIR/lint-dead-code-1.rs:67:5 @@ -54,8 +53,7 @@ error: variant is never constructed: `bar3` LL | bar3 | ^^^^ help: if this is intentional, prefix it with an underscore: `_bar3` | - = note: the leading underscore signals that this variant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect. error: function is never used: `priv_fn` --> $DIR/lint-dead-code-1.rs:88:4 @@ -63,8 +61,7 @@ error: function is never used: `priv_fn` LL | fn priv_fn() { | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_fn` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. error: function is never used: `foo` --> $DIR/lint-dead-code-1.rs:93:4 @@ -72,8 +69,7 @@ error: function is never used: `foo` LL | fn foo() { | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. error: function is never used: `bar` --> $DIR/lint-dead-code-1.rs:98:4 @@ -81,8 +77,7 @@ error: function is never used: `bar` LL | fn bar() { | ^^^ help: if this is intentional, prefix it with an underscore: `_bar` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. error: function is never used: `baz` --> $DIR/lint-dead-code-1.rs:102:4 @@ -90,8 +85,7 @@ error: function is never used: `baz` LL | fn baz() -> impl Copy { | ^^^ help: if this is intentional, prefix it with an underscore: `_baz` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. error: aborting due to 10 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-2.stderr b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr index dce763c5ed61f..5e19c7d02ffd3 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-2.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr @@ -4,8 +4,7 @@ error: function is never used: `dead_fn` LL | fn dead_fn() {} | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_dead_fn` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/lint-dead-code-2.rs:2:9 | @@ -18,8 +17,7 @@ error: function is never used: `dead_fn2` LL | fn dead_fn2() {} | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_dead_fn2` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. error: function is never used: `main` --> $DIR/lint-dead-code-2.rs:38:4 @@ -27,8 +25,7 @@ error: function is never used: `main` LL | fn main() { | ^^^^ help: if this is intentional, prefix it with an underscore: `_main` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr index a5ecc91edb060..d32fde5872d99 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr @@ -4,8 +4,7 @@ error: struct is never constructed: `Foo` LL | struct Foo; | ^^^ help: if this is intentional, prefix it with an underscore: `_Foo` | - = note: the leading underscore signals that this struct serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/lint-dead-code-3.rs:4:9 | @@ -18,8 +17,7 @@ error: associated function is never used: `foo` LL | fn foo(&self) { | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` | - = note: the leading underscore signals that this associated function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this associated function serves some other purpose even if it isn't used in a way that we can detect. error: function is never used: `bar` --> $DIR/lint-dead-code-3.rs:21:4 @@ -27,8 +25,7 @@ error: function is never used: `bar` LL | fn bar() { | ^^^ help: if this is intentional, prefix it with an underscore: `_bar` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. error: enum is never used: `c_void` --> $DIR/lint-dead-code-3.rs:60:6 @@ -36,17 +33,17 @@ error: enum is never used: `c_void` LL | enum c_void {} | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_c_void` | - = note: the leading underscore signals that this enum serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this enum serves some other purpose even if it isn't used in a way that we can detect. error: function is never used: `free` --> $DIR/lint-dead-code-3.rs:62:5 | LL | fn free(p: *const c_void); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_free` + | ^^^----^^^^^^^^^^^^^^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_free` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. error: aborting due to 5 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr index 2297c172fc987..2785faa29f5d9 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr @@ -2,11 +2,11 @@ error: field is never read: `b` --> $DIR/lint-dead-code-4.rs:7:5 | LL | b: bool, - | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_b` + | -^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_b` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) note: the lint level is defined here --> $DIR/lint-dead-code-4.rs:3:9 | @@ -19,21 +19,22 @@ error: variant is never constructed: `X` LL | X, | ^ help: if this is intentional, prefix it with an underscore: `_X` | - = note: the leading underscore signals that this variant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect. error: variant is never constructed: `Y` --> $DIR/lint-dead-code-4.rs:16:5 | -LL | / Y { +LL | Y { + | ^ help: if this is intentional, prefix it with an underscore: `_Y` + | _____| + | | LL | | a: String, LL | | b: i32, LL | | c: i32, LL | | }, - | |_____^ help: if this is intentional, prefix it with an underscore: `_Y` + | |_____^ | - = note: the leading underscore signals that this variant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect. error: enum is never used: `ABC` --> $DIR/lint-dead-code-4.rs:24:6 @@ -41,8 +42,7 @@ error: enum is never used: `ABC` LL | enum ABC { | ^^^ help: if this is intentional, prefix it with an underscore: `_ABC` | - = note: the leading underscore signals that this enum serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this enum serves some other purpose even if it isn't used in a way that we can detect. error: variant is never constructed: `I` --> $DIR/lint-dead-code-4.rs:36:5 @@ -50,28 +50,27 @@ error: variant is never constructed: `I` LL | I, | ^ help: if this is intentional, prefix it with an underscore: `_I` | - = note: the leading underscore signals that this variant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect. error: field is never read: `b` --> $DIR/lint-dead-code-4.rs:39:9 | LL | b: i32, - | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_b` + | -^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_b` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) error: field is never read: `c` --> $DIR/lint-dead-code-4.rs:40:9 | LL | c: i32, - | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_c` + | -^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_c` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) error: variant is never constructed: `K` --> $DIR/lint-dead-code-4.rs:42:5 @@ -79,28 +78,27 @@ error: variant is never constructed: `K` LL | K | ^ help: if this is intentional, prefix it with an underscore: `_K` | - = note: the leading underscore signals that this variant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect. error: field is never read: `x` --> $DIR/lint-dead-code-4.rs:61:5 | LL | x: usize, - | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_x` + | -^^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_x` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) error: field is never read: `c` --> $DIR/lint-dead-code-4.rs:63:5 | LL | c: bool, - | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_c` + | -^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_c` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) error: aborting due to 10 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr index afe159c2d8bba..6375d98d35cb2 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr @@ -4,8 +4,7 @@ error: variant is never constructed: `Variant2` LL | Variant2 | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant2` | - = note: the leading underscore signals that this variant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/lint-dead-code-5.rs:2:9 | @@ -16,19 +15,21 @@ error: variant is never constructed: `Variant5` --> $DIR/lint-dead-code-5.rs:13:5 | LL | Variant5 { _x: isize }, - | ^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant5` + | --------^^^^^^^^^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_Variant5` | - = note: the leading underscore signals that this variant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect. error: variant is never constructed: `Variant6` --> $DIR/lint-dead-code-5.rs:14:5 | LL | Variant6(isize), - | ^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant6` + | --------^^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_Variant6` | - = note: the leading underscore signals that this variant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect. error: enum is never used: `Enum3` --> $DIR/lint-dead-code-5.rs:35:6 @@ -36,8 +37,7 @@ error: enum is never used: `Enum3` LL | enum Enum3 { | ^^^^^ help: if this is intentional, prefix it with an underscore: `_Enum3` | - = note: the leading underscore signals that this enum serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this enum serves some other purpose even if it isn't used in a way that we can detect. error: aborting due to 4 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-6.stderr b/src/test/ui/lint/dead-code/lint-dead-code-6.stderr index d212a4bc443d9..ef26fe54ab589 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-6.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-6.stderr @@ -4,8 +4,7 @@ error: struct is never constructed: `UnusedStruct` LL | struct UnusedStruct; | ^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_UnusedStruct` | - = note: the leading underscore signals that this struct serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/lint-dead-code-6.rs:1:9 | @@ -18,8 +17,7 @@ error: associated function is never used: `unused_impl_fn_1` LL | fn unused_impl_fn_1() { | ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_impl_fn_1` | - = note: the leading underscore signals that this associated function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this associated function serves some other purpose even if it isn't used in a way that we can detect. error: associated function is never used: `unused_impl_fn_2` --> $DIR/lint-dead-code-6.rs:9:8 @@ -27,8 +25,7 @@ error: associated function is never used: `unused_impl_fn_2` LL | fn unused_impl_fn_2(var: i32) { | ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_impl_fn_2` | - = note: the leading underscore signals that this associated function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this associated function serves some other purpose even if it isn't used in a way that we can detect. error: associated function is never used: `unused_impl_fn_3` --> $DIR/lint-dead-code-6.rs:13:8 @@ -36,8 +33,7 @@ error: associated function is never used: `unused_impl_fn_3` LL | fn unused_impl_fn_3( | ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_impl_fn_3` | - = note: the leading underscore signals that this associated function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this associated function serves some other purpose even if it isn't used in a way that we can detect. error: aborting due to 4 previous errors diff --git a/src/test/ui/lint/dead-code/newline-span.stderr b/src/test/ui/lint/dead-code/newline-span.stderr index b57df1dfcedb4..5bd566be35e01 100644 --- a/src/test/ui/lint/dead-code/newline-span.stderr +++ b/src/test/ui/lint/dead-code/newline-span.stderr @@ -4,8 +4,7 @@ error: function is never used: `unused` LL | fn unused() { | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/newline-span.rs:1:9 | @@ -18,8 +17,7 @@ error: function is never used: `unused2` LL | fn unused2(var: i32) { | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused2` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. error: function is never used: `unused3` --> $DIR/newline-span.rs:11:4 @@ -27,8 +25,7 @@ error: function is never used: `unused3` LL | fn unused3( | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused3` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/dead-code/type-alias.stderr b/src/test/ui/lint/dead-code/type-alias.stderr index 3e7298a6f2d3e..1e7a030de3aa7 100644 --- a/src/test/ui/lint/dead-code/type-alias.stderr +++ b/src/test/ui/lint/dead-code/type-alias.stderr @@ -2,10 +2,11 @@ error: type alias is never used: `Unused` --> $DIR/type-alias.rs:4:1 | LL | type Unused = u8; - | ^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Unused` + | ^^^^^------^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_Unused` | - = note: the leading underscore signals that this type alias serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this type alias serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/type-alias.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/unused-enum.stderr b/src/test/ui/lint/dead-code/unused-enum.stderr index 6e65e6565076f..d536479c800ae 100644 --- a/src/test/ui/lint/dead-code/unused-enum.stderr +++ b/src/test/ui/lint/dead-code/unused-enum.stderr @@ -4,8 +4,7 @@ error: struct is never constructed: `F` LL | struct F; | ^ help: if this is intentional, prefix it with an underscore: `_F` | - = note: the leading underscore signals that this struct serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/unused-enum.rs:1:9 | @@ -19,8 +18,7 @@ error: struct is never constructed: `B` LL | struct B; | ^ help: if this is intentional, prefix it with an underscore: `_B` | - = note: the leading underscore signals that this struct serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect. error: enum is never used: `E` --> $DIR/unused-enum.rs:6:6 @@ -28,8 +26,7 @@ error: enum is never used: `E` LL | enum E { | ^ help: if this is intentional, prefix it with an underscore: `_E` | - = note: the leading underscore signals that this enum serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this enum serves some other purpose even if it isn't used in a way that we can detect. error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/dead-code/unused-struct-variant.stderr b/src/test/ui/lint/dead-code/unused-struct-variant.stderr index a5c7eea0579e6..394ced3e81001 100644 --- a/src/test/ui/lint/dead-code/unused-struct-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-struct-variant.stderr @@ -2,10 +2,11 @@ error: variant is never constructed: `Bar` --> $DIR/unused-struct-variant.rs:8:5 | LL | Bar(B), - | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_Bar` + | ---^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_Bar` | - = note: the leading underscore signals that this variant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/unused-struct-variant.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/unused-variant.stderr b/src/test/ui/lint/dead-code/unused-variant.stderr index 9536c492fc04f..7dcb79d0490c1 100644 --- a/src/test/ui/lint/dead-code/unused-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-variant.stderr @@ -4,8 +4,7 @@ error: variant is never constructed: `Variant1` LL | Variant1, | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant1` | - = note: the leading underscore signals that this variant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/unused-variant.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/with-core-crate.stderr b/src/test/ui/lint/dead-code/with-core-crate.stderr index 563b0b65020ee..1bde434069ee7 100644 --- a/src/test/ui/lint/dead-code/with-core-crate.stderr +++ b/src/test/ui/lint/dead-code/with-core-crate.stderr @@ -4,8 +4,7 @@ error: function is never used: `foo` LL | fn foo() { | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/with-core-crate.rs:1:9 | diff --git a/src/test/ui/lint/dead-code/write-only-field.stderr b/src/test/ui/lint/dead-code/write-only-field.stderr index f750beade18ec..13a21bb1193de 100644 --- a/src/test/ui/lint/dead-code/write-only-field.stderr +++ b/src/test/ui/lint/dead-code/write-only-field.stderr @@ -2,11 +2,11 @@ error: field is never read: `f` --> $DIR/write-only-field.rs:4:5 | LL | f: i32, - | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_f` + | -^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_f` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) note: the lint level is defined here --> $DIR/write-only-field.rs:1:9 | @@ -17,51 +17,51 @@ error: field is never read: `sub` --> $DIR/write-only-field.rs:5:5 | LL | sub: Sub, - | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_sub` + | ---^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_sub` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) error: field is never read: `f` --> $DIR/write-only-field.rs:9:5 | LL | f: i32, - | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_f` + | -^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_f` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) error: field is never read: `y` --> $DIR/write-only-field.rs:28:9 | LL | y: bool, - | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_y` + | -^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_y` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) error: field is never read: `u` --> $DIR/write-only-field.rs:58:9 | LL | u: u32, - | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_u` + | -^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_u` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) error: field is never read: `v` --> $DIR/write-only-field.rs:59:9 | LL | v: u32, - | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_v` + | -^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_v` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) error: aborting due to 6 previous errors diff --git a/src/test/ui/lint/issue-17718-const-naming.stderr b/src/test/ui/lint/issue-17718-const-naming.stderr index 0bafca2e4d785..e880006e114c1 100644 --- a/src/test/ui/lint/issue-17718-const-naming.stderr +++ b/src/test/ui/lint/issue-17718-const-naming.stderr @@ -2,10 +2,11 @@ error: constant is never used: `foo` --> $DIR/issue-17718-const-naming.rs:4:1 | LL | const foo: isize = 3; - | ^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_foo` + | ^^^^^^---^^^^^^^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_foo` | - = note: the leading underscore signals that this constant serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this constant serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/issue-17718-const-naming.rs:2:9 | diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr index d5fad7c3b88ec..f94a9e30a3dfa 100644 --- a/src/test/ui/span/macro-span-replacement.stderr +++ b/src/test/ui/span/macro-span-replacement.stderr @@ -2,13 +2,14 @@ warning: struct is never constructed: `S` --> $DIR/macro-span-replacement.rs:7:14 | LL | $b $a; - | ^ help: if this is intentional, prefix it with an underscore: `_S` + | --^ + | | + | help: if this is intentional, prefix it with an underscore: `_S` ... LL | m!(S struct); | ------------- in this macro invocation | - = note: the leading underscore signals that this struct serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/macro-span-replacement.rs:3:9 | diff --git a/src/test/ui/span/unused-warning-point-at-identifier.stderr b/src/test/ui/span/unused-warning-point-at-identifier.stderr index 0bf85d252d60c..3bf342f197252 100644 --- a/src/test/ui/span/unused-warning-point-at-identifier.stderr +++ b/src/test/ui/span/unused-warning-point-at-identifier.stderr @@ -4,8 +4,7 @@ warning: enum is never used: `Enum` LL | enum Enum { | ^^^^ help: if this is intentional, prefix it with an underscore: `_Enum` | - = note: the leading underscore signals that this enum serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this enum serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/unused-warning-point-at-identifier.rs:3:9 | @@ -19,8 +18,7 @@ warning: struct is never constructed: `Struct` LL | struct Struct { | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_Struct` | - = note: the leading underscore signals that this struct serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect. warning: function is never used: `func` --> $DIR/unused-warning-point-at-identifier.rs:19:4 @@ -28,8 +26,7 @@ warning: function is never used: `func` LL | fn func() -> usize { | ^^^^ help: if this is intentional, prefix it with an underscore: `_func` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. warning: function is never used: `func_complete_span` --> $DIR/unused-warning-point-at-identifier.rs:24:1 @@ -37,8 +34,7 @@ warning: function is never used: `func_complete_span` LL | func_complete_span() | ^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_func_complete_span` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. warning: 4 warnings emitted diff --git a/src/test/ui/test-attrs/test-warns-dead-code.stderr b/src/test/ui/test-attrs/test-warns-dead-code.stderr index 795a9fb8820ce..e5a8dee6ccb68 100644 --- a/src/test/ui/test-attrs/test-warns-dead-code.stderr +++ b/src/test/ui/test-attrs/test-warns-dead-code.stderr @@ -4,8 +4,7 @@ error: function is never used: `dead` LL | fn dead() {} | ^^^^ help: if this is intentional, prefix it with an underscore: `_dead` | - = note: the leading underscore signals that this function serves some other purpose - even if it isn't used in a way that we can detect. + = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect. note: the lint level is defined here --> $DIR/test-warns-dead-code.rs:3:9 | diff --git a/src/test/ui/union/union-fields-1.stderr b/src/test/ui/union/union-fields-1.stderr index e1695ca12cf72..3595bf6dce688 100644 --- a/src/test/ui/union/union-fields-1.stderr +++ b/src/test/ui/union/union-fields-1.stderr @@ -2,11 +2,11 @@ error: field is never read: `c` --> $DIR/union-fields-1.rs:6:5 | LL | c: u8, - | ^^^^^ help: if this is intentional, prefix it with an underscore: `_c` + | -^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_c` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) note: the lint level is defined here --> $DIR/union-fields-1.rs:1:9 | @@ -17,31 +17,31 @@ error: field is never read: `a` --> $DIR/union-fields-1.rs:9:5 | LL | a: u8, - | ^^^^^ help: if this is intentional, prefix it with an underscore: `_a` + | -^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_a` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) error: field is never read: `a` --> $DIR/union-fields-1.rs:13:20 | LL | union NoDropLike { a: u8 } - | ^^^^^ help: if this is intentional, prefix it with an underscore: `_a` + | -^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_a` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) error: field is never read: `c` --> $DIR/union-fields-1.rs:18:5 | LL | c: u8, - | ^^^^^ help: if this is intentional, prefix it with an underscore: `_c` + | -^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_c` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) error: aborting due to 4 previous errors diff --git a/src/test/ui/union/union-lint-dead-code.stderr b/src/test/ui/union/union-lint-dead-code.stderr index 565e13fb2ae1f..8ead9cde9b333 100644 --- a/src/test/ui/union/union-lint-dead-code.stderr +++ b/src/test/ui/union/union-lint-dead-code.stderr @@ -2,11 +2,11 @@ error: field is never read: `b` --> $DIR/union-lint-dead-code.rs:5:5 | LL | b: bool, - | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_b` + | -^^^^^^ + | | + | help: if this is intentional, prefix it with an underscore: `_b` | - = note: the leading underscore signals that this field serves some other purpose - even if it isn't used in a way that we can detect. (e.g. for its effect - when dropped or in foreign code) + = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code) note: the lint level is defined here --> $DIR/union-lint-dead-code.rs:1:9 | From 539242a07b15ec95aa196bfa4c18f6a8b01b8ecb Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 1 Apr 2021 08:37:29 +0900 Subject: [PATCH 07/32] Add a suggestion when using a type alias instead of trait alias --- compiler/rustc_resolve/src/late/diagnostics.rs | 9 ++++++++- src/test/ui/codemap_tests/two_files.stderr | 5 ++--- src/test/ui/resolve/issue-3907.stderr | 5 ++--- src/test/ui/resolve/issue-5035.stderr | 14 +++++++------- .../unboxed-closure-sugar-nonexistent-trait.stderr | 5 ++--- .../suggest-trait-alias-instead-of-type.fixed | 13 +++++++++++++ .../alias/suggest-trait-alias-instead-of-type.rs | 13 +++++++++++++ .../suggest-trait-alias-instead-of-type.stderr | 14 ++++++++++++++ 8 files changed, 61 insertions(+), 17 deletions(-) create mode 100644 src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed create mode 100644 src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.rs create mode 100644 src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 1fb07bdae9d00..0314de9ebbe5d 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -928,7 +928,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \ `type` alias"; if let Some(span) = self.def_span(def_id) { - err.span_help(span, msg); + if let Ok(snip) = self.r.session.source_map().span_to_snippet(span) { + // The span contains a type alias so we should be able to + // replace `type` with `trait`. + let snip = snip.replacen("type", "trait", 1); + err.span_suggestion(span, msg, snip, Applicability::MaybeIncorrect); + } else { + err.span_help(span, msg); + } } else { err.help(msg); } diff --git a/src/test/ui/codemap_tests/two_files.stderr b/src/test/ui/codemap_tests/two_files.stderr index de2ffc2e5dc1d..aff51ee9e2f54 100644 --- a/src/test/ui/codemap_tests/two_files.stderr +++ b/src/test/ui/codemap_tests/two_files.stderr @@ -5,10 +5,9 @@ LL | impl Bar for Baz { } | ^^^ type aliases cannot be used as traits | help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias - --> $DIR/two_files_data.rs:5:1 | -LL | type Bar = dyn Foo; - | ^^^^^^^^^^^^^^^^^^^ +LL | trait Bar = dyn Foo; + | error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-3907.stderr b/src/test/ui/resolve/issue-3907.stderr index 4d0b0af58a320..6fc61cae84339 100644 --- a/src/test/ui/resolve/issue-3907.stderr +++ b/src/test/ui/resolve/issue-3907.stderr @@ -5,10 +5,9 @@ LL | impl Foo for S { | ^^^ type aliases cannot be used as traits | help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias - --> $DIR/issue-3907.rs:5:1 | -LL | type Foo = dyn issue_3907::Foo; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait Foo = dyn issue_3907::Foo; + | help: consider importing this trait instead | LL | use issue_3907::Foo; diff --git a/src/test/ui/resolve/issue-5035.stderr b/src/test/ui/resolve/issue-5035.stderr index 41dff2fe54205..a8aa50b7c3ab2 100644 --- a/src/test/ui/resolve/issue-5035.stderr +++ b/src/test/ui/resolve/issue-5035.stderr @@ -11,16 +11,16 @@ LL | trait I {} | ------- similarly named trait `I` defined here LL | type K = dyn I; LL | impl K for isize {} - | ^ - | | - | type aliases cannot be used as traits - | help: a trait with a similar name exists: `I` + | ^ type aliases cannot be used as traits | help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias - --> $DIR/issue-5035.rs:2:1 | -LL | type K = dyn I; - | ^^^^^^^^^^^^^^^ +LL | trait K = dyn I; + | +help: a trait with a similar name exists + | +LL | impl I for isize {} + | ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr index 2974d08eb23b1..8addc0303fb91 100644 --- a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr +++ b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr @@ -11,10 +11,9 @@ LL | fn g isize>(x: F) {} | ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used as traits | help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias - --> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:4:1 | -LL | type Typedef = isize; - | ^^^^^^^^^^^^^^^^^^^^^ +LL | trait Typedef = isize; + | error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed b/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed new file mode 100644 index 0000000000000..8a94abaeb0744 --- /dev/null +++ b/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed @@ -0,0 +1,13 @@ +// Regression test of #43913. + +// run-rustfix + +#![feature(trait_alias)] +#![allow(bare_trait_objects, dead_code)] + +trait Strings = Iterator; + +struct Struct(S); +//~^ ERROR: expected trait, found type alias `Strings` + +fn main() {} diff --git a/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.rs b/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.rs new file mode 100644 index 0000000000000..40c678c281f4c --- /dev/null +++ b/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.rs @@ -0,0 +1,13 @@ +// Regression test of #43913. + +// run-rustfix + +#![feature(trait_alias)] +#![allow(bare_trait_objects, dead_code)] + +type Strings = Iterator; + +struct Struct(S); +//~^ ERROR: expected trait, found type alias `Strings` + +fn main() {} diff --git a/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr b/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr new file mode 100644 index 0000000000000..6e03eeada499c --- /dev/null +++ b/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr @@ -0,0 +1,14 @@ +error[E0404]: expected trait, found type alias `Strings` + --> $DIR/suggest-trait-alias-instead-of-type.rs:10:18 + | +LL | struct Struct(S); + | ^^^^^^^ type aliases cannot be used as traits + | +help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias + | +LL | trait Strings = Iterator; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. From eea27b81366a6a91a5b05153cd9ab6207d7f11bc Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 1 Apr 2021 08:39:48 +0900 Subject: [PATCH 08/32] Mention trait alias on the E0404 note --- .../src/error_codes/E0404.md | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0404.md b/compiler/rustc_error_codes/src/error_codes/E0404.md index 1360cc99afcc4..d6fa51e618c4c 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0404.md +++ b/compiler/rustc_error_codes/src/error_codes/E0404.md @@ -8,14 +8,15 @@ struct Foo; struct Bar; impl Foo for Bar {} // error: `Foo` is not a trait +fn baz(t: T) {} // error: `Foo` is not a trait ``` Another erroneous code example: ```compile_fail,E0404 -struct Foo; +type Foo = Iterator; -fn bar(t: T) {} // error: `Foo` is not a trait +fn bar(t: T) {} // error: `Foo` is a type alias ``` Please verify that the trait's name was not misspelled or that the right @@ -30,14 +31,27 @@ struct Bar; impl Foo for Bar { // ok! // functions implementation } + +fn baz(t: T) {} // ok! ``` -or: +Alternatively, you could introduce a new trait with your desired restrictions +as a super trait: ``` -trait Foo { - // some functions -} +# trait Foo {} +# struct Bar; +# impl Foo for Bar {} +trait Qux: Foo {} // Anything that implements Qux also needs to implement Foo +fn baz(t: T) {} // also ok! +``` + +Finally, if you are on nightly and want to use a trait alias +instead of a type alias, you should use `#![feature(trait_alias)]`: + +``` +#![feature(trait_alias)] +trait Foo = Iterator; fn bar(t: T) {} // ok! ``` From 115e216067aff0b7b2fa55d9a66394f14a3a8397 Mon Sep 17 00:00:00 2001 From: Rustin-Liu Date: Fri, 24 Apr 2020 22:05:32 +0800 Subject: [PATCH 09/32] Rename AssociatedItems to AssocItems Signed-off-by: Rustin-Liu --- test.rs | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 test.rs diff --git a/test.rs b/test.rs new file mode 100644 index 0000000000000..bc7f5af826efa --- /dev/null +++ b/test.rs @@ -0,0 +1,125 @@ +#![allow(missing_docs)] + +use embedded_hal::digital::v2::{InputPin, OutputPin}; +use generic_array::{ArrayLength, GenericArray}; +use heapless::Vec; + +pub trait HeterogenousArray { + type Len; +} + +/// Macro to implement a iterator on trait objects from a tuple struct. +#[macro_export] +macro_rules! impl_heterogenous_array { + ($s:ident, $t:ty, $len:tt, [$($idx:tt),+]) => { + impl<'a> IntoIterator for &'a $s { + type Item = &'a $t; + type IntoIter = generic_array::GenericArrayIter<&'a $t, $len>; + fn into_iter(self) -> Self::IntoIter { + self.as_array().into_iter() + } + } + impl<'a> IntoIterator for &'a mut $s { + type Item = &'a mut $t; + type IntoIter = generic_array::GenericArrayIter<&'a mut $t, $len>; + fn into_iter(self) -> Self::IntoIter { + self.as_mut_array().into_iter() + } + } + impl $crate::matrix::HeterogenousArray for $s { + type Len = $len; + } + impl $s { + pub fn as_array(&self) -> generic_array::GenericArray<&$t, $len> { + generic_array::arr![&$t; $( &self.$idx as &$t, )+] + } + pub fn as_mut_array(&mut self) -> generic_array::GenericArray<&mut $t, $len> { + generic_array::arr![&mut $t; $( &mut self.$idx as &mut $t, )+] + } + } + } +} + +pub struct Matrix { + cols: C, + rows: R, +} + +impl Matrix { + pub fn new(cols: C, rows: R) -> Result + where + for<'a> &'a mut R: IntoIterator>, + { + let mut res = Self { cols, rows }; + res.clear()?; + Ok(res) + } + pub fn clear<'a, E: 'a>(&'a mut self) -> Result<(), E> + where + &'a mut R: IntoIterator>, + { + for r in self.rows.into_iter() { + r.set_high()?; + } + Ok(()) + } + pub fn get<'a, E: 'a>(&'a mut self) -> Result, E> + where + &'a mut R: IntoIterator>, + R: HeterogenousArray, + R::Len: ArrayLength>, + &'a C: IntoIterator>, + C: HeterogenousArray, + C::Len: ArrayLength, + { + let cols = &self.cols; + self.rows + .into_iter() + .map(|r| { + r.set_low()?; + let col = cols + .into_iter() + .map(|c| c.is_low()) + .collect::, E>>()? + .into_iter() + .collect(); + r.set_high()?; + Ok(col) + }) + .collect::, E>>() + .map(|res| PressedKeys(res.into_iter().collect())) + } +} + +#[derive(Default, PartialEq, Eq)] +pub struct PressedKeys(pub GenericArray, U>) + where + V: ArrayLength, + U: ArrayLength>; + +impl PressedKeys + where + V: ArrayLength, + U: ArrayLength>, +{ + pub fn iter_pressed<'a>(&'a self) -> impl Iterator + Clone + 'a { + self.0.iter().enumerate().flat_map(|(i, r)| { + r.iter() + .enumerate() + .filter_map(move |(j, &b)| if b { Some((i, j)) } else { None }) + }) + } +} + +impl<'a, U, V> IntoIterator for &'a PressedKeys + where + V: ArrayLength, + U: ArrayLength>, + U: ArrayLength<&'a GenericArray>, +{ + type IntoIter = core::slice::Iter<'a, GenericArray>; + type Item = &'a GenericArray; + fn into_iter(self) -> Self::IntoIter { + self.0.iter() + } +} \ No newline at end of file From 6c3f5b85351ba62d4eea875964781cfd924d1ca2 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Mon, 5 Apr 2021 22:54:50 +0800 Subject: [PATCH 10/32] resolve conflicts resolve conflicts --- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/assoc.rs | 6 +- compiler/rustc_ty_utils/src/ty.rs | 4 +- .../src/coherence/inherent_impls_overlap.rs | 4 +- test.rs | 125 ------------------ 5 files changed, 8 insertions(+), 133 deletions(-) delete mode 100644 test.rs diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index bac69e282a521..1aca93fc5c56a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -564,7 +564,7 @@ rustc_queries! { } /// Collects the associated items defined on a trait or impl. - query associated_items(key: DefId) -> ty::AssociatedItems<'tcx> { + query associated_items(key: DefId) -> ty::AssocItems<'tcx> { storage(ArenaCacheSelector<'tcx>) desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) } } diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index d3770fa416b53..d005f63ed4383 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -96,15 +96,15 @@ impl AssocKind { /// it is relatively expensive. Instead, items are indexed by `Symbol` and hygienic comparison is /// done only on items with the same name. #[derive(Debug, Clone, PartialEq, HashStable)] -pub struct AssociatedItems<'tcx> { +pub struct AssocItems<'tcx> { pub(super) items: SortedIndexMultiMap, } -impl<'tcx> AssociatedItems<'tcx> { +impl<'tcx> AssocItems<'tcx> { /// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order. pub fn new(items_in_def_order: impl IntoIterator) -> Self { let items = items_in_def_order.into_iter().map(|item| (item.ident.name, item)).collect(); - AssociatedItems { items } + AssocItems { items } } /// Returns a slice of associated items in the order they were defined. diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 29f1761b84d2b..38e5ce6fd831c 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -210,9 +210,9 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { } } -fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssociatedItems<'_> { +fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> { let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)); - ty::AssociatedItems::new(items) + ty::AssocItems::new(items) } fn def_ident_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option { diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs index 2965409999202..c69389e7b432b 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs @@ -24,8 +24,8 @@ impl InherentOverlapChecker<'tcx> { /// namespace. fn impls_have_common_items( &self, - impl_items1: &ty::AssociatedItems<'_>, - impl_items2: &ty::AssociatedItems<'_>, + impl_items1: &ty::AssocItems<'_>, + impl_items2: &ty::AssocItems<'_>, ) -> bool { let mut impl_items1 = &impl_items1; let mut impl_items2 = &impl_items2; diff --git a/test.rs b/test.rs deleted file mode 100644 index bc7f5af826efa..0000000000000 --- a/test.rs +++ /dev/null @@ -1,125 +0,0 @@ -#![allow(missing_docs)] - -use embedded_hal::digital::v2::{InputPin, OutputPin}; -use generic_array::{ArrayLength, GenericArray}; -use heapless::Vec; - -pub trait HeterogenousArray { - type Len; -} - -/// Macro to implement a iterator on trait objects from a tuple struct. -#[macro_export] -macro_rules! impl_heterogenous_array { - ($s:ident, $t:ty, $len:tt, [$($idx:tt),+]) => { - impl<'a> IntoIterator for &'a $s { - type Item = &'a $t; - type IntoIter = generic_array::GenericArrayIter<&'a $t, $len>; - fn into_iter(self) -> Self::IntoIter { - self.as_array().into_iter() - } - } - impl<'a> IntoIterator for &'a mut $s { - type Item = &'a mut $t; - type IntoIter = generic_array::GenericArrayIter<&'a mut $t, $len>; - fn into_iter(self) -> Self::IntoIter { - self.as_mut_array().into_iter() - } - } - impl $crate::matrix::HeterogenousArray for $s { - type Len = $len; - } - impl $s { - pub fn as_array(&self) -> generic_array::GenericArray<&$t, $len> { - generic_array::arr![&$t; $( &self.$idx as &$t, )+] - } - pub fn as_mut_array(&mut self) -> generic_array::GenericArray<&mut $t, $len> { - generic_array::arr![&mut $t; $( &mut self.$idx as &mut $t, )+] - } - } - } -} - -pub struct Matrix { - cols: C, - rows: R, -} - -impl Matrix { - pub fn new(cols: C, rows: R) -> Result - where - for<'a> &'a mut R: IntoIterator>, - { - let mut res = Self { cols, rows }; - res.clear()?; - Ok(res) - } - pub fn clear<'a, E: 'a>(&'a mut self) -> Result<(), E> - where - &'a mut R: IntoIterator>, - { - for r in self.rows.into_iter() { - r.set_high()?; - } - Ok(()) - } - pub fn get<'a, E: 'a>(&'a mut self) -> Result, E> - where - &'a mut R: IntoIterator>, - R: HeterogenousArray, - R::Len: ArrayLength>, - &'a C: IntoIterator>, - C: HeterogenousArray, - C::Len: ArrayLength, - { - let cols = &self.cols; - self.rows - .into_iter() - .map(|r| { - r.set_low()?; - let col = cols - .into_iter() - .map(|c| c.is_low()) - .collect::, E>>()? - .into_iter() - .collect(); - r.set_high()?; - Ok(col) - }) - .collect::, E>>() - .map(|res| PressedKeys(res.into_iter().collect())) - } -} - -#[derive(Default, PartialEq, Eq)] -pub struct PressedKeys(pub GenericArray, U>) - where - V: ArrayLength, - U: ArrayLength>; - -impl PressedKeys - where - V: ArrayLength, - U: ArrayLength>, -{ - pub fn iter_pressed<'a>(&'a self) -> impl Iterator + Clone + 'a { - self.0.iter().enumerate().flat_map(|(i, r)| { - r.iter() - .enumerate() - .filter_map(move |(j, &b)| if b { Some((i, j)) } else { None }) - }) - } -} - -impl<'a, U, V> IntoIterator for &'a PressedKeys - where - V: ArrayLength, - U: ArrayLength>, - U: ArrayLength<&'a GenericArray>, -{ - type IntoIter = core::slice::Iter<'a, GenericArray>; - type Item = &'a GenericArray; - fn into_iter(self) -> Self::IntoIter { - self.0.iter() - } -} \ No newline at end of file From 7efba4f982a200627605f77b444e09de02ab2a1a Mon Sep 17 00:00:00 2001 From: AnthonyMikh Date: Thu, 8 Oct 2020 16:02:06 +0300 Subject: [PATCH 11/32] Implement indexing slices with pairs of ops::Bound --- library/core/src/slice/index.rs | 112 ++++++++++++++++++++++++++++++++ library/core/tests/slice.rs | 43 ++++++++++++ 2 files changed, 155 insertions(+) diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index c92b37b14be4f..1ef040484c344 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -81,6 +81,8 @@ mod private_slice_index { impl Sealed for ops::RangeInclusive {} #[stable(feature = "slice_get_slice", since = "1.28.0")] impl Sealed for ops::RangeToInclusive {} + #[stable(feature = "slice_index_with_ops_bound_pair", since = "1.51.0")] + impl Sealed for (ops::Bound, ops::Bound) {} } /// A helper trait used for indexing operations. @@ -546,3 +548,113 @@ where ops::Range { start, end } } + +/// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking +fn into_range_unchecked( + len: usize, + (start, end): (ops::Bound, ops::Bound), +) -> ops::Range { + use ops::Bound; + let start = match start { + Bound::Included(i) => i, + Bound::Excluded(i) => i + 1, + Bound::Unbounded => 0, + }; + let end = match end { + Bound::Included(i) => i + 1, + Bound::Excluded(i) => i, + Bound::Unbounded => len, + }; + start..end +} + +/// Convert pair of `ops::Bound`s into `ops::Range`. +/// Returns `None` on overflowing indices. +fn into_range( + len: usize, + (start, end): (ops::Bound, ops::Bound), +) -> Option> { + use ops::Bound; + let start = match start { + Bound::Included(start) => start, + Bound::Excluded(start) => start.checked_add(1)?, + Bound::Unbounded => 0, + }; + + let end = match end { + Bound::Included(end) => end.checked_add(1)?, + Bound::Excluded(end) => end, + Bound::Unbounded => len, + }; + + // Don't bother with checking `start < end` and `end <= len` + // since these checks are handled by `Range` impls + + Some(start..end) +} + +/// Convert pair of `ops::Bound`s into `ops::Range`. +/// Panics on overflowing indices. +fn into_slice_range( + len: usize, + (start, end): (ops::Bound, ops::Bound), +) -> ops::Range { + use ops::Bound; + let start = match start { + Bound::Included(start) => start, + Bound::Excluded(start) => { + start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail()) + } + Bound::Unbounded => 0, + }; + + let end = match end { + Bound::Included(end) => { + end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail()) + } + Bound::Excluded(end) => end, + Bound::Unbounded => len, + }; + + // Don't bother with checking `start < end` and `end <= len` + // since these checks are handled by `Range` impls + + start..end +} + +#[stable(feature = "slice_index_with_ops_bound_pair", since = "1.51.0")] +unsafe impl SliceIndex<[T]> for (ops::Bound, ops::Bound) { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&Self::Output> { + into_range(slice.len(), self)?.get(slice) + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { + into_range(slice.len(), self)?.get_mut(slice) + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { into_range_unchecked(slice.len(), self).get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { into_range_unchecked(slice.len(), self).get_unchecked_mut(slice) } + } + + #[inline] + fn index(self, slice: &[T]) -> &Self::Output { + into_slice_range(slice.len(), self).index(slice) + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { + into_slice_range(slice.len(), self).index_mut(slice) + } +} diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 7e198631cc7eb..3a98cd9d2ee91 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -1280,6 +1280,9 @@ mod slice_index { } )*) => {$( mod $case_name { + #[allow(unused_imports)] + use core::ops::Bound; + #[test] fn pass() { let mut v = $data; @@ -1376,6 +1379,24 @@ mod slice_index { bad: data[7..=6]; message: "out of range"; } + + in mod boundpair_len { + data: [0, 1, 2, 3, 4, 5]; + + good: data[(Bound::Included(6), Bound::Unbounded)] == []; + good: data[(Bound::Unbounded, Bound::Included(5))] == [0, 1, 2, 3, 4, 5]; + good: data[(Bound::Unbounded, Bound::Excluded(6))] == [0, 1, 2, 3, 4, 5]; + good: data[(Bound::Included(0), Bound::Included(5))] == [0, 1, 2, 3, 4, 5]; + good: data[(Bound::Included(0), Bound::Excluded(6))] == [0, 1, 2, 3, 4, 5]; + good: data[(Bound::Included(2), Bound::Excluded(4))] == [2, 3]; + good: data[(Bound::Excluded(1), Bound::Included(4))] == [2, 3, 4]; + good: data[(Bound::Excluded(5), Bound::Excluded(6))] == []; + good: data[(Bound::Included(6), Bound::Excluded(6))] == []; + good: data[(Bound::Excluded(5), Bound::Included(5))] == []; + good: data[(Bound::Included(6), Bound::Included(5))] == []; + bad: data[(Bound::Unbounded, Bound::Included(6))]; + message: "out of range"; + } } panic_cases! { @@ -1416,6 +1437,14 @@ mod slice_index { bad: data[4..=2]; message: "but ends at"; } + + in mod boundpair_neg_width { + data: [0, 1, 2, 3, 4, 5]; + + good: data[(Bound::Included(4), Bound::Excluded(4))] == []; + bad: data[(Bound::Included(4), Bound::Excluded(3))]; + message: "but ends at"; + } } panic_cases! { @@ -1434,6 +1463,20 @@ mod slice_index { bad: data[..= usize::MAX]; message: "maximum usize"; } + + in mod boundpair_overflow_end { + data: [0; 1]; + + bad: data[(Bound::Unbounded, Bound::Included(usize::MAX))]; + message: "maximum usize"; + } + + in mod boundpair_overflow_start { + data: [0; 1]; + + bad: data[(Bound::Excluded(usize::MAX), Bound::Unbounded)]; + message: "maximum usize"; + } } // panic_cases! } From 904ee686ca06c78135d356235265997a1faf292e Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Wed, 14 Apr 2021 04:04:27 +0200 Subject: [PATCH 12/32] Explicitly implement `!Send` and `!Sync` for `sys::{Args, Env}` --- library/std/src/sys/hermit/args.rs | 8 ++++---- library/std/src/sys/hermit/os.rs | 7 ++++--- library/std/src/sys/unix/args.rs | 13 ++++++------- library/std/src/sys/unix/os.rs | 7 ++++--- library/std/src/sys/wasi/args.rs | 10 ++++------ library/std/src/sys/wasi/os.rs | 7 ++++--- library/std/src/sys/wasm/args.rs | 7 ++++--- 7 files changed, 30 insertions(+), 29 deletions(-) diff --git a/library/std/src/sys/hermit/args.rs b/library/std/src/sys/hermit/args.rs index 7727293927282..17b27c50bb2d3 100644 --- a/library/std/src/sys/hermit/args.rs +++ b/library/std/src/sys/hermit/args.rs @@ -1,5 +1,4 @@ use crate::ffi::OsString; -use crate::marker::PhantomData; use crate::vec; /// One-time global initialization. @@ -19,7 +18,6 @@ pub fn args() -> Args { pub struct Args { iter: vec::IntoIter, - _dont_send_or_sync_me: PhantomData<*mut ()>, } impl Args { @@ -28,6 +26,9 @@ impl Args { } } +impl !Send for Args {} +impl !Sync for Args {} + impl Iterator for Args { type Item = OsString; fn next(&mut self) -> Option { @@ -53,7 +54,6 @@ impl DoubleEndedIterator for Args { mod imp { use super::Args; use crate::ffi::{CStr, OsString}; - use crate::marker::PhantomData; use crate::ptr; use crate::sys_common::os_str_bytes::*; @@ -76,7 +76,7 @@ mod imp { } pub fn args() -> Args { - Args { iter: clone().into_iter(), _dont_send_or_sync_me: PhantomData } + Args { iter: clone().into_iter() } } fn clone() -> Vec { diff --git a/library/std/src/sys/hermit/os.rs b/library/std/src/sys/hermit/os.rs index 78eabf8f81e98..f09f437e533bf 100644 --- a/library/std/src/sys/hermit/os.rs +++ b/library/std/src/sys/hermit/os.rs @@ -3,7 +3,6 @@ use crate::error::Error as StdError; use crate::ffi::{CStr, OsStr, OsString}; use crate::fmt; use crate::io; -use crate::marker::PhantomData; use crate::memchr; use crate::path::{self, PathBuf}; use crate::str; @@ -110,9 +109,11 @@ pub fn init_environment(env: *const *const i8) { pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Args {} +impl !Sync for Args {} + impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { @@ -134,7 +135,7 @@ pub fn env() -> Env { result.push((key.clone(), value.clone())); } - return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData }; + return Env { iter: result.into_iter() }; } } diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs index 6967647249390..4fca0d0752fe8 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -6,7 +6,6 @@ #![allow(dead_code)] // runtime init functions not used during testing use crate::ffi::OsString; -use crate::marker::PhantomData; use crate::vec; /// One-time global initialization. @@ -26,9 +25,11 @@ pub fn args() -> Args { pub struct Args { iter: vec::IntoIter, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Args {} +impl !Sync for Args {} + impl Args { pub fn inner_debug(&self) -> &[OsString] { self.iter.as_slice() @@ -76,7 +77,6 @@ impl DoubleEndedIterator for Args { mod imp { use super::Args; use crate::ffi::{CStr, OsString}; - use crate::marker::PhantomData; use crate::os::unix::prelude::*; use crate::ptr; use crate::sync::atomic::{AtomicIsize, AtomicPtr, Ordering}; @@ -133,7 +133,7 @@ mod imp { } pub fn args() -> Args { - Args { iter: clone().into_iter(), _dont_send_or_sync_me: PhantomData } + Args { iter: clone().into_iter() } } fn clone() -> Vec { @@ -155,7 +155,6 @@ mod imp { mod imp { use super::Args; use crate::ffi::CStr; - use crate::marker::PhantomData; pub unsafe fn init(_argc: isize, _argv: *const *const u8) {} @@ -180,7 +179,7 @@ mod imp { }) .collect::>() }; - Args { iter: vec.into_iter(), _dont_send_or_sync_me: PhantomData } + Args { iter: vec.into_iter() } } // As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs @@ -247,6 +246,6 @@ mod imp { } } - Args { iter: res.into_iter(), _dont_send_or_sync_me: PhantomData } + Args { iter: res.into_iter() } } } diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 4a077e2151ed9..e4355653498cf 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -12,7 +12,6 @@ use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; use crate::io; use crate::iter; -use crate::marker::PhantomData; use crate::mem; use crate::memchr; use crate::path::{self, PathBuf}; @@ -465,9 +464,11 @@ pub fn current_exe() -> io::Result { pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Env {} +impl !Sync for Env {} + impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { @@ -515,7 +516,7 @@ pub fn env() -> Env { environ = environ.add(1); } } - return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData }; + return Env { iter: result.into_iter() }; } fn parse(input: &[u8]) -> Option<(OsString, OsString)> { diff --git a/library/std/src/sys/wasi/args.rs b/library/std/src/sys/wasi/args.rs index 9a27218e1fb70..61a9bd28fd812 100644 --- a/library/std/src/sys/wasi/args.rs +++ b/library/std/src/sys/wasi/args.rs @@ -1,7 +1,6 @@ #![deny(unsafe_op_in_unsafe_fn)] use crate::ffi::{CStr, OsStr, OsString}; -use crate::marker::PhantomData; use crate::os::wasi::ffi::OsStrExt; use crate::vec; @@ -11,15 +10,14 @@ pub unsafe fn cleanup() {} pub struct Args { iter: vec::IntoIter, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Args {} +impl !Sync for Args {} + /// Returns the command line arguments pub fn args() -> Args { - Args { - iter: maybe_args().unwrap_or(Vec::new()).into_iter(), - _dont_send_or_sync_me: PhantomData, - } + Args { iter: maybe_args().unwrap_or(Vec::new()).into_iter() } } fn maybe_args() -> Option> { diff --git a/library/std/src/sys/wasi/os.rs b/library/std/src/sys/wasi/os.rs index 185d6109cb93e..18271a46270cb 100644 --- a/library/std/src/sys/wasi/os.rs +++ b/library/std/src/sys/wasi/os.rs @@ -5,7 +5,6 @@ use crate::error::Error as StdError; use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; use crate::io; -use crate::marker::PhantomData; use crate::os::wasi::prelude::*; use crate::path::{self, PathBuf}; use crate::str; @@ -129,9 +128,11 @@ pub fn current_exe() -> io::Result { } pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Args {} +impl !Sync for Args {} + impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { @@ -155,7 +156,7 @@ pub fn env() -> Env { environ = environ.add(1); } } - return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData }; + return Env { iter: result.into_iter() }; } // See src/libstd/sys/unix/os.rs, same as that diff --git a/library/std/src/sys/wasm/args.rs b/library/std/src/sys/wasm/args.rs index 3b6557ae3257f..8c25a1d262a63 100644 --- a/library/std/src/sys/wasm/args.rs +++ b/library/std/src/sys/wasm/args.rs @@ -1,5 +1,4 @@ use crate::ffi::OsString; -use crate::marker::PhantomData; use crate::vec; pub unsafe fn init(_argc: isize, _argv: *const *const u8) { @@ -9,14 +8,16 @@ pub unsafe fn init(_argc: isize, _argv: *const *const u8) { pub unsafe fn cleanup() {} pub fn args() -> Args { - Args { iter: Vec::new().into_iter(), _dont_send_or_sync_me: PhantomData } + Args { iter: Vec::new().into_iter() } } pub struct Args { iter: vec::IntoIter, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Args {} +impl !Sync for Args {} + impl Args { pub fn inner_debug(&self) -> &[OsString] { self.iter.as_slice() From 2ecc820d311d18de0523742b4c74a37cfca9a1d2 Mon Sep 17 00:00:00 2001 From: CDirkx Date: Wed, 14 Apr 2021 12:42:38 +0200 Subject: [PATCH 13/32] Correct typos Co-authored-by: Mara Bos --- library/std/src/sys/hermit/os.rs | 4 ++-- library/std/src/sys/wasi/os.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/hermit/os.rs b/library/std/src/sys/hermit/os.rs index f09f437e533bf..fd2a0fe22a95d 100644 --- a/library/std/src/sys/hermit/os.rs +++ b/library/std/src/sys/hermit/os.rs @@ -111,8 +111,8 @@ pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, } -impl !Send for Args {} -impl !Sync for Args {} +impl !Send for Env {} +impl !Sync for Env {} impl Iterator for Env { type Item = (OsString, OsString); diff --git a/library/std/src/sys/wasi/os.rs b/library/std/src/sys/wasi/os.rs index 18271a46270cb..ee89c5578b265 100644 --- a/library/std/src/sys/wasi/os.rs +++ b/library/std/src/sys/wasi/os.rs @@ -130,8 +130,8 @@ pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, } -impl !Send for Args {} -impl !Sync for Args {} +impl !Send for Env {} +impl !Sync for Env {} impl Iterator for Env { type Item = (OsString, OsString); From 98a11e01e5f5bf274451320834ea85f9cbd03b92 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Mon, 19 Apr 2021 15:39:19 -0500 Subject: [PATCH 14/32] Remove closure_tree --- compiler/rustc_middle/src/middle/region.rs | 31 ---------------------- compiler/rustc_passes/src/region.rs | 15 +---------- 2 files changed, 1 insertion(+), 45 deletions(-) diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 5440e63543d40..f44267a404bf3 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -235,18 +235,6 @@ pub struct ScopeTree { /// escape into 'static and should have no local cleanup scope. rvalue_scopes: FxHashMap>, - /// Encodes the hierarchy of fn bodies. Every fn body (including - /// closures) forms its own distinct region hierarchy, rooted in - /// the block that is the fn body. This map points from the ID of - /// that root block to the ID of the root block for the enclosing - /// fn, if any. Thus the map structures the fn bodies into a - /// hierarchy based on their lexical mapping. This is used to - /// handle the relationships between regions in a fn and in a - /// closure defined by that fn. See the "Modeling closures" - /// section of the README in infer::region_constraints for - /// more details. - closure_tree: FxHashMap, - /// If there are any `yield` nested within a scope, this map /// stores the `Span` of the last one and its index in the /// postorder of the Visitor traversal on the HIR. @@ -356,23 +344,6 @@ impl ScopeTree { self.destruction_scopes.get(&n).cloned() } - /// Records that `sub_closure` is defined within `sup_closure`. These IDs - /// should be the ID of the block that is the fn body, which is - /// also the root of the region hierarchy for that fn. - pub fn record_closure_parent( - &mut self, - sub_closure: hir::ItemLocalId, - sup_closure: hir::ItemLocalId, - ) { - debug!( - "record_closure_parent(sub_closure={:?}, sup_closure={:?})", - sub_closure, sup_closure - ); - assert!(sub_closure != sup_closure); - let previous = self.closure_tree.insert(sub_closure, sup_closure); - assert!(previous.is_none()); - } - pub fn record_var_scope(&mut self, var: hir::ItemLocalId, lifetime: Scope) { debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime); assert!(var != lifetime.item_local_id()); @@ -474,7 +445,6 @@ impl<'a> HashStable> for ScopeTree { ref var_map, ref destruction_scopes, ref rvalue_scopes, - ref closure_tree, ref yield_in_scope, } = *self; @@ -488,7 +458,6 @@ impl<'a> HashStable> for ScopeTree { var_map.hash_stable(hcx, hasher); destruction_scopes.hash_stable(hcx, hasher); rvalue_scopes.hash_stable(hcx, hasher); - closure_tree.hash_stable(hcx, hasher); yield_in_scope.hash_stable(hcx, hasher); } } diff --git a/compiler/rustc_passes/src/region.rs b/compiler/rustc_passes/src/region.rs index b532021bed2e9..14a373c59423f 100644 --- a/compiler/rustc_passes/src/region.rs +++ b/compiler/rustc_passes/src/region.rs @@ -23,14 +23,6 @@ use std::mem; #[derive(Debug, Copy, Clone)] pub struct Context { - /// The root of the current region tree. This is typically the id - /// of the innermost fn body. Each fn forms its own disjoint tree - /// in the region hierarchy. These fn bodies are themselves - /// arranged into a tree. See the "Modeling closures" section of - /// the README in `rustc_trait_selection::infer::region_constraints` - /// for more details. - root_id: Option, - /// The scope that contains any new variables declared, plus its depth in /// the scope tree. var_parent: Option<(Scope, ScopeDepth)>, @@ -743,11 +735,6 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false); self.terminating_scopes.insert(body.value.hir_id.local_id); - if let Some(root_id) = self.cx.root_id { - self.scope_tree.record_closure_parent(body.value.hir_id.local_id, root_id); - } - self.cx.root_id = Some(body.value.hir_id.local_id); - self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::CallSite }); self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::Arguments }); @@ -824,7 +811,7 @@ fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { tcx, scope_tree: ScopeTree::default(), expr_and_pat_count: 0, - cx: Context { root_id: None, parent: None, var_parent: None }, + cx: Context { parent: None, var_parent: None }, terminating_scopes: Default::default(), pessimistic_yield: false, fixup_scopes: vec![], From c9c14d0c1f04f888fbd4ec8b254b61fff84db7d4 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Mon, 19 Apr 2021 15:40:05 -0500 Subject: [PATCH 15/32] Small refactor --- compiler/rustc_trait_selection/src/traits/object_safety.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index b5a458db6075f..ac5ec24eeeeb5 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -439,8 +439,7 @@ fn virtual_call_violation_for_method<'tcx>( return Some(MethodViolationCode::WhereClauseReferencesSelf); } - let receiver_ty = - tcx.liberate_late_bound_regions(method.def_id, sig.map_bound(|sig| sig.inputs()[0])); + let receiver_ty = tcx.liberate_late_bound_regions(method.def_id, sig.input(0)); // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on. // However, this is already considered object-safe. We allow it as a special case here. From a10d01be22819f21ae0011390f71fa3c3902d1e4 Mon Sep 17 00:00:00 2001 From: Tor Hovland Date: Tue, 20 Apr 2021 22:31:48 +0200 Subject: [PATCH 16/32] Uses flex to fix formatting of h1 at any width. --- src/librustdoc/html/static/rustdoc.css | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 8f11dda2fb205..415bb608911e5 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -116,6 +116,9 @@ h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) { padding-bottom: 6px; } h1.fqn { + display: flex; + gap: 8px; + width: 100%; border-bottom: 1px dashed; margin-top: 0; } @@ -458,6 +461,12 @@ nav.sub { font-weight: normal; } +h1.fqn > .out-of-band { + float: unset; + flex: 1; + text-align: right; +} + h3.impl > .out-of-band { font-size: 21px; } @@ -1450,10 +1459,6 @@ h4 > .notable-traits { padding: 0; } - .content .in-band { - width: 100%; - } - .content h4 > .out-of-band { position: inherit; } From ba3d22ed6685f3ddbfda29edc20b93810a641db8 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Mon, 12 Apr 2021 09:12:10 -0400 Subject: [PATCH 17/32] Precompute inverse binder depth --- compiler/rustc_resolve/src/late/lifetimes.rs | 177 ++++++++----------- 1 file changed, 73 insertions(+), 104 deletions(-) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index fc1ea4ec84629..88ceb23b72f5b 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -249,6 +249,8 @@ enum Scope<'a> { /// requires binders of nested trait refs to be merged. from_poly_trait_ref: bool, + binder_depth: u32, + /// The late bound vars for a given item are stored by `HirId` to be /// queried later. However, if we enter an elision scope, we have to /// later append the elided bound vars to the list and need to know what @@ -345,6 +347,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { track_lifetime_uses, opaque_type_parent, from_poly_trait_ref, + binder_depth, hir_id, s: _, } => f @@ -354,6 +357,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { .field("track_lifetime_uses", track_lifetime_uses) .field("opaque_type_parent", opaque_type_parent) .field("from_poly_trait_ref", from_poly_trait_ref) + .field("binder_depth", binder_depth) .field("hir_id", hir_id) .field("s", &"..") .finish(), @@ -618,6 +622,45 @@ fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty:: } } +impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { + fn depth(&self, concanetate: bool) -> u32 { + let mut passed_boundary = false; + let mut scope = self.scope; + loop { + match *scope { + Scope::Root => { + break 0; + } + + Scope::TraitRefBoundary { s, .. } => { + passed_boundary = true; + scope = s; + } + + Scope::Binder { binder_depth, from_poly_trait_ref, .. } => { + break if concanetate { + if passed_boundary || !from_poly_trait_ref { + binder_depth + 1 + } else { + binder_depth + } + } else { + binder_depth + 1 + }; + } + + Scope::Elision { s, .. } + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::TraitRefHackInner { s, .. } + | Scope::Supertrait { s, .. } + | Scope::Body { s, .. } => { + scope = s; + } + } + } + } +} + impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { type Map = Map<'tcx>; @@ -676,6 +719,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { track_lifetime_uses: true, opaque_type_parent: false, from_poly_trait_ref: false, + binder_depth: self.depth(false), }; self.with(scope, move |_old_scope, this| { intravisit::walk_fn(this, fk, fd, b, s, hir_id) @@ -801,6 +845,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { opaque_type_parent: true, track_lifetime_uses, from_poly_trait_ref: false, + binder_depth: self.depth(false), s: ROOT_SCOPE, }; self.with(scope, |old_scope, this| { @@ -870,6 +915,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { track_lifetime_uses: true, opaque_type_parent: false, from_poly_trait_ref: false, + binder_depth: self.depth(false), }; self.with(scope, |old_scope, this| { // a bare fn has no bounds, so everything @@ -1063,6 +1109,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { track_lifetime_uses: true, opaque_type_parent: false, from_poly_trait_ref: false, + binder_depth: this.depth(false), }; this.with(scope, |_old_scope, this| { this.visit_generics(generics); @@ -1083,6 +1130,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { track_lifetime_uses: true, opaque_type_parent: false, from_poly_trait_ref: false, + binder_depth: self.depth(false), }; self.with(scope, |_old_scope, this| { let scope = Scope::TraitRefBoundary { s: this.scope }; @@ -1142,6 +1190,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { track_lifetime_uses: true, opaque_type_parent: true, from_poly_trait_ref: false, + binder_depth: self.depth(false), }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -1211,6 +1260,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { track_lifetime_uses: true, opaque_type_parent: true, from_poly_trait_ref: false, + binder_depth: self.depth(false), }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -1324,6 +1374,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { track_lifetime_uses: true, opaque_type_parent: false, from_poly_trait_ref: true, + binder_depth: this.depth(false), }; this.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &bound_generic_params); @@ -1370,6 +1421,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { track_lifetime_uses: true, opaque_type_parent: false, from_poly_trait_ref: false, + binder_depth: self.depth(false), }; self.with(scope, |_, this| { intravisit::walk_param_bound(this, bound); @@ -1516,6 +1568,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { track_lifetime_uses: true, opaque_type_parent: false, from_poly_trait_ref: true, + binder_depth: self.depth(true), }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params); @@ -2266,6 +2319,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { opaque_type_parent: true, track_lifetime_uses: false, from_poly_trait_ref: false, + binder_depth: self.depth(false), }; self.with(scope, move |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -2323,7 +2377,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // given name or we run out of scopes. // search. let mut late_depth = 0; - let mut in_poly_trait_ref = false; + let mut first_binder_depth = None; let mut scope = self.scope; let mut outermost_body = None; let result = loop { @@ -2341,25 +2395,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { break None; } - Scope::TraitRefBoundary { s, .. } => { - // We've exited nested poly trait refs; mark that we are no longer in nested trait refs. - // We don't increase the late depth because this isn't a `Binder` scope. - // - // This came up in #83737, which boiled down to a case like this: - // - // ``` - // F: for<> Fn(&()) -> Box Future + Unpin>, - // // ^^^^^ - - // ``` - // - // Here, as we traverse upwards from the `dyn for<>` binder, we want to reset `in_poly_trait_ref` - // to false, so that we avoid excess contaenation when we encounter the outer `for<>` binder. - in_poly_trait_ref = false; - scope = s; - } - - Scope::Binder { ref lifetimes, from_poly_trait_ref, s, .. } => { + Scope::Binder { ref lifetimes, s, binder_depth, .. } => { match lifetime_ref.name { LifetimeName::Param(param_name) => { if let Some(&def) = lifetimes.get(¶m_name.normalize_to_macros_2_0()) @@ -2369,47 +2405,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } _ => bug!("expected LifetimeName::Param"), } - - match (from_poly_trait_ref, in_poly_trait_ref) { - // This is the first binder we see that is a poly trait ref; add one to the - // late depth and mark that we're potentially in nested trait refs. - (true, false) => { - in_poly_trait_ref = true; - late_depth += 1; - } - // We've already seen a binder that is a poly trait ref and this one is too, - // that means that they are nested and we are concatenating the bound vars; - // don't increase the late depth. - // - // This happens specifically with associated trait bounds like the following: - // - // ``` - // for<'a> T: Iterator Foo<'a, 'b>> - // ``` - // - // In this case, as we traverse `for<'b>`, we would increment `late_depth` but - // set `in_poly_trait_ref` to true. Then when we traverse `for<'a>`, we would - // not increment `late_depth` again. (NB: Niko thinks this logic is actually - // wrong.) - (true, true) => {} - // We've exited nested poly trait refs; add one to the late depth and mark - // that we are no longer in nested trait refs - (false, true) => { - in_poly_trait_ref = false; - late_depth += 1; - } - // Any other kind of nested binders: just increase late depth. - (false, false) => { - late_depth += 1; - } - } + first_binder_depth = first_binder_depth.or(Some(binder_depth)); + late_depth = first_binder_depth.unwrap_or(binder_depth) - binder_depth + 1; scope = s; } Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } | Scope::TraitRefHackInner { s, .. } - | Scope::Supertrait { s, .. } => { + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => { scope = s; } } @@ -3112,7 +3117,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let span = lifetime_refs[0].span; let mut late_depth = 0; - let mut in_poly_trait_ref = false; + let mut first_binder_depth = None; let mut scope = self.scope; let mut lifetime_names = FxHashSet::default(); let mut lifetime_spans = vec![]; @@ -3123,14 +3128,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Root => break None, - Scope::TraitRefBoundary { s, .. } => { - // We've exited nested poly trait refs; mark that we are no longer in nested trait refs. - // We don't increase the late depth because this isn't a `Binder` scope - in_poly_trait_ref = false; - scope = s; - } - - Scope::Binder { s, ref lifetimes, from_poly_trait_ref, .. } => { + Scope::Binder { s, ref lifetimes, binder_depth, .. } => { // collect named lifetimes for suggestions for name in lifetimes.keys() { if let hir::ParamName::Plain(name) = name { @@ -3138,21 +3136,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { lifetime_spans.push(name.span); } } - // See comments in `resolve_lifetime_ref` - match (from_poly_trait_ref, in_poly_trait_ref) { - (true, false) => { - in_poly_trait_ref = true; - late_depth += 1; - } - (true, true) => {} - (false, true) => { - in_poly_trait_ref = false; - late_depth += 1; - } - (false, false) => { - late_depth += 1; - } - } + first_binder_depth = first_binder_depth.or(Some(binder_depth)); + late_depth = first_binder_depth.unwrap_or(binder_depth) - binder_depth + 1; scope = s; } @@ -3202,7 +3187,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::ObjectLifetimeDefault { s, .. } | Scope::TraitRefHackInner { s, .. } - | Scope::Supertrait { s, .. } => { + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => { scope = s; } } @@ -3308,32 +3294,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) { debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref); let mut late_depth = 0; - let mut in_poly_trait_ref = false; + let mut first_binder_depth = None; let mut scope = self.scope; let lifetime = loop { match *scope { - Scope::TraitRefBoundary { s, .. } => { - // We've exited nested poly trait refs; mark that we are no longer in nested trait refs. - // We don't increase the late depth because this isn't a `Binder` scope - in_poly_trait_ref = false; - scope = s; - } - - Scope::Binder { s, from_poly_trait_ref, .. } => { - match (from_poly_trait_ref, in_poly_trait_ref) { - (true, false) => { - in_poly_trait_ref = true; - late_depth += 1; - } - (true, true) => {} - (false, true) => { - in_poly_trait_ref = false; - late_depth += 1; - } - (false, false) => { - late_depth += 1; - } - } + Scope::Binder { s, binder_depth, .. } => { + first_binder_depth = first_binder_depth.or(Some(binder_depth)); + late_depth = first_binder_depth.unwrap_or(binder_depth) - binder_depth + 1; scope = s; } @@ -3343,7 +3310,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l, - Scope::TraitRefHackInner { s, .. } | Scope::Supertrait { s, .. } => { + Scope::TraitRefHackInner { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => { scope = s; } } From 32942ab8078dd9c266aa5886f98ab32eda310749 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Mon, 12 Apr 2021 09:26:39 -0400 Subject: [PATCH 18/32] A non-minimal set of TraitRefBoundarys to work on removing from_poly_trait_ref --- compiler/rustc_resolve/src/late/lifetimes.rs | 177 ++++++++++--------- 1 file changed, 93 insertions(+), 84 deletions(-) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 88ceb23b72f5b..4e3e4f2c2bcb5 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -638,6 +638,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } Scope::Binder { binder_depth, from_poly_trait_ref, .. } => { + if concanetate && !passed_boundary && !from_poly_trait_ref { + bug!("{:?}", self.scope); + } break if concanetate { if passed_boundary || !from_poly_trait_ref { binder_depth + 1 @@ -850,7 +853,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); - intravisit::walk_item(this, item); + let scope = Scope::TraitRefBoundary { s: this.scope }; + this.with(scope, |_, this| { + intravisit::walk_item(this, item); + }); }); self.missing_named_lifetime_spots.pop(); } @@ -985,9 +991,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // Elided lifetimes are not allowed in non-return // position impl Trait - let scope = Scope::Elision { elide: Elide::Forbid, s: self.scope }; + let scope = Scope::TraitRefBoundary { s: self.scope }; self.with(scope, |_, this| { - intravisit::walk_item(this, opaque_ty); + let scope = Scope::Elision { elide: Elide::Forbid, s: this.scope }; + this.with(scope, |_, this| { + intravisit::walk_item(this, opaque_ty); + }) }); return; @@ -1320,93 +1329,93 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { if !self.trait_definition_only { check_mixed_explicit_and_in_band_defs(self.tcx, &generics.params); } - for param in generics.params { - match param.kind { - GenericParamKind::Lifetime { .. } => {} - GenericParamKind::Type { ref default, .. } => { - walk_list!(self, visit_param_bound, param.bounds); - if let Some(ref ty) = default { - self.visit_ty(&ty); + let scope = Scope::TraitRefBoundary { s: self.scope }; + self.with(scope, |_, this| { + for param in generics.params { + match param.kind { + GenericParamKind::Lifetime { .. } => {} + GenericParamKind::Type { ref default, .. } => { + walk_list!(this, visit_param_bound, param.bounds); + if let Some(ref ty) = default { + this.visit_ty(&ty); + } + } + GenericParamKind::Const { ref ty, .. } => { + let was_in_const_generic = this.is_in_const_generic; + this.is_in_const_generic = true; + walk_list!(this, visit_param_bound, param.bounds); + this.visit_ty(&ty); + this.is_in_const_generic = was_in_const_generic; } } - GenericParamKind::Const { ref ty, .. } => { - let was_in_const_generic = self.is_in_const_generic; - self.is_in_const_generic = true; - walk_list!(self, visit_param_bound, param.bounds); - self.visit_ty(&ty); - self.is_in_const_generic = was_in_const_generic; - } - } - } - for predicate in generics.where_clause.predicates { - match predicate { - &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { - ref bounded_ty, - bounds, - ref bound_generic_params, - .. - }) => { - let (lifetimes, binders): (FxHashMap, Vec<_>) = - bound_generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some(param), - _ => None, - }) - .enumerate() - .map(|(late_bound_idx, param)| { - let pair = - Region::late(late_bound_idx as u32, &self.tcx.hir(), param); - let r = late_region_as_bound_region(self.tcx, &pair.1); - (pair, r) - }) - .unzip(); - self.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone()); - let scope = Scope::TraitRefBoundary { s: self.scope }; - self.with(scope, |_, this| { - if !lifetimes.is_empty() { - let next_early_index = this.next_early_index(); - let scope = Scope::Binder { - hir_id: bounded_ty.hir_id, - lifetimes, - s: this.scope, - next_early_index, - track_lifetime_uses: true, - opaque_type_parent: false, - from_poly_trait_ref: true, - binder_depth: this.depth(false), - }; - this.with(scope, |old_scope, this| { - this.check_lifetime_params(old_scope, &bound_generic_params); + } + for predicate in generics.where_clause.predicates { + match predicate { + &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + ref bounded_ty, + bounds, + ref bound_generic_params, + .. + }) => { + let (lifetimes, binders): (FxHashMap, Vec<_>) = + bound_generic_params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => Some(param), + _ => None, + }) + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = + Region::late(late_bound_idx as u32, &this.tcx.hir(), param); + let r = late_region_as_bound_region(this.tcx, &pair.1); + (pair, r) + }) + .unzip(); + this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone()); + if !lifetimes.is_empty() { + let next_early_index = this.next_early_index(); + let scope = Scope::Binder { + hir_id: bounded_ty.hir_id, + lifetimes, + s: this.scope, + next_early_index, + track_lifetime_uses: true, + opaque_type_parent: false, + from_poly_trait_ref: true, + binder_depth: this.depth(false), + }; + this.with(scope, |old_scope, this| { + this.check_lifetime_params(old_scope, &bound_generic_params); + this.visit_ty(&bounded_ty); + this.trait_ref_hack = Some(bounded_ty.hir_id); + walk_list!(this, visit_param_bound, bounds); + this.trait_ref_hack = None; + }) + } else { this.visit_ty(&bounded_ty); - this.trait_ref_hack = Some(bounded_ty.hir_id); walk_list!(this, visit_param_bound, bounds); - this.trait_ref_hack = None; - }) - } else { - this.visit_ty(&bounded_ty); - walk_list!(this, visit_param_bound, bounds); - } - }) - } - &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { - ref lifetime, - bounds, - .. - }) => { - self.visit_lifetime(lifetime); - walk_list!(self, visit_param_bound, bounds); - } - &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - ref lhs_ty, - ref rhs_ty, - .. - }) => { - self.visit_ty(lhs_ty); - self.visit_ty(rhs_ty); + } + } + &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { + ref lifetime, + bounds, + .. + }) => { + this.visit_lifetime(lifetime); + walk_list!(this, visit_param_bound, bounds); + } + &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { + ref lhs_ty, + ref rhs_ty, + .. + }) => { + this.visit_ty(lhs_ty); + this.visit_ty(rhs_ty); + } } } - } + }) } fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) { From 457c4c133a4bc83da668b5bceac75cd229ff112e Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Tue, 13 Apr 2021 16:58:00 -0400 Subject: [PATCH 19/32] Add BinderScopeType to replace binder_depth and from_poly_trait_ref --- compiler/rustc_resolve/src/late/lifetimes.rs | 197 ++++++++----------- 1 file changed, 86 insertions(+), 111 deletions(-) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 4e3e4f2c2bcb5..58d053aca1ab1 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -244,12 +244,7 @@ enum Scope<'a> { /// of the resulting opaque type. opaque_type_parent: bool, - /// True only if this `Binder` scope is from the quantifiers on a - /// `PolyTraitRef`. This is necessary for `associated_type_bounds`, which - /// requires binders of nested trait refs to be merged. - from_poly_trait_ref: bool, - - binder_depth: u32, + scope_type: BinderScopeType, /// The late bound vars for a given item are stored by `HirId` to be /// queried later. However, if we enter an elision scope, we have to @@ -335,6 +330,13 @@ enum Scope<'a> { Root, } +#[derive(Copy, Clone, Debug)] +enum BinderScopeType { + Other, + PolyTraitRef, + Concatenating, +} + // A helper struct for debugging scopes without printing parent scopes struct TruncatedScopeDebug<'a>(&'a Scope<'a>); @@ -346,8 +348,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { next_early_index, track_lifetime_uses, opaque_type_parent, - from_poly_trait_ref, - binder_depth, + scope_type, hir_id, s: _, } => f @@ -356,8 +357,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { .field("next_early_index", next_early_index) .field("track_lifetime_uses", track_lifetime_uses) .field("opaque_type_parent", opaque_type_parent) - .field("from_poly_trait_ref", from_poly_trait_ref) - .field("binder_depth", binder_depth) + .field("scope_type", scope_type) .field("hir_id", hir_id) .field("s", &"..") .finish(), @@ -622,48 +622,6 @@ fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty:: } } -impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { - fn depth(&self, concanetate: bool) -> u32 { - let mut passed_boundary = false; - let mut scope = self.scope; - loop { - match *scope { - Scope::Root => { - break 0; - } - - Scope::TraitRefBoundary { s, .. } => { - passed_boundary = true; - scope = s; - } - - Scope::Binder { binder_depth, from_poly_trait_ref, .. } => { - if concanetate && !passed_boundary && !from_poly_trait_ref { - bug!("{:?}", self.scope); - } - break if concanetate { - if passed_boundary || !from_poly_trait_ref { - binder_depth + 1 - } else { - binder_depth - } - } else { - binder_depth + 1 - }; - } - - Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } - | Scope::TraitRefHackInner { s, .. } - | Scope::Supertrait { s, .. } - | Scope::Body { s, .. } => { - scope = s; - } - } - } - } -} - impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { type Map = Map<'tcx>; @@ -721,8 +679,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: false, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, }; self.with(scope, move |_old_scope, this| { intravisit::walk_fn(this, fk, fd, b, s, hir_id) @@ -847,8 +804,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index: index + non_lifetime_count, opaque_type_parent: true, track_lifetime_uses, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, s: ROOT_SCOPE, }; self.with(scope, |old_scope, this| { @@ -920,8 +876,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index, track_lifetime_uses: true, opaque_type_parent: false, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, }; self.with(scope, |old_scope, this| { // a bare fn has no bounds, so everything @@ -1117,8 +1072,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: this.scope, track_lifetime_uses: true, opaque_type_parent: false, - from_poly_trait_ref: false, - binder_depth: this.depth(false), + scope_type: BinderScopeType::Other, }; this.with(scope, |_old_scope, this| { this.visit_generics(generics); @@ -1138,8 +1092,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: false, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, }; self.with(scope, |_old_scope, this| { let scope = Scope::TraitRefBoundary { s: this.scope }; @@ -1198,8 +1151,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -1268,8 +1220,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -1373,29 +1324,28 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }) .unzip(); this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone()); - if !lifetimes.is_empty() { - let next_early_index = this.next_early_index(); - let scope = Scope::Binder { - hir_id: bounded_ty.hir_id, - lifetimes, - s: this.scope, - next_early_index, - track_lifetime_uses: true, - opaque_type_parent: false, - from_poly_trait_ref: true, - binder_depth: this.depth(false), - }; - this.with(scope, |old_scope, this| { - this.check_lifetime_params(old_scope, &bound_generic_params); - this.visit_ty(&bounded_ty); - this.trait_ref_hack = Some(bounded_ty.hir_id); - walk_list!(this, visit_param_bound, bounds); - this.trait_ref_hack = None; - }) - } else { + if !lifetimes.is_empty() { + let next_early_index = this.next_early_index(); + let scope = Scope::Binder { + hir_id: bounded_ty.hir_id, + lifetimes, + s: this.scope, + next_early_index, + track_lifetime_uses: true, + opaque_type_parent: false, + scope_type: BinderScopeType::PolyTraitRef, + }; + this.with(scope, |old_scope, this| { + this.check_lifetime_params(old_scope, &bound_generic_params); this.visit_ty(&bounded_ty); + this.trait_ref_hack = Some(bounded_ty.hir_id); walk_list!(this, visit_param_bound, bounds); - } + this.trait_ref_hack = None; + }) + } else { + this.visit_ty(&bounded_ty); + walk_list!(this, visit_param_bound, bounds); + } } &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { ref lifetime, @@ -1429,8 +1379,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index: self.next_early_index(), track_lifetime_uses: true, opaque_type_parent: false, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, }; self.with(scope, |_, this| { intravisit::walk_param_bound(this, bound); @@ -1527,12 +1476,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { break vec![]; } - Scope::Binder { hir_id, from_poly_trait_ref, .. } => { - if !from_poly_trait_ref { - // We should only see super trait lifetimes if there is a `Binder` above - assert!(supertrait_lifetimes.is_empty()); - break vec![]; - } + Scope::Binder { hir_id, .. } => { // Nested poly trait refs have the binders concatenated let mut full_binders = self.map.late_bound_vars.entry(*hir_id).or_default().clone(); @@ -1569,6 +1513,33 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders); if trait_ref_hack.is_none() || has_lifetimes { + let scope_type = { + let mut scope = self.scope; + loop { + match *scope { + Scope::Root | Scope::TraitRefBoundary { .. } => { + break BinderScopeType::PolyTraitRef; + } + + Scope::Binder { scope_type, .. } => { + if let BinderScopeType::Other = scope_type { + bug!( + "Expected all syntacic poly trait refs to be surrounded by a `TraitRefBoundary`" + ) + } + break BinderScopeType::Concatenating; + } + + Scope::Elision { s, .. } + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::TraitRefHackInner { s, .. } + | Scope::Supertrait { s, .. } + | Scope::Body { s, .. } => { + scope = s; + } + } + } + }; let scope = Scope::Binder { hir_id: trait_ref.trait_ref.hir_ref_id, lifetimes, @@ -1576,8 +1547,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index, track_lifetime_uses: true, opaque_type_parent: false, - from_poly_trait_ref: true, - binder_depth: self.depth(true), + scope_type, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params); @@ -2327,8 +2297,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { s: self.scope, opaque_type_parent: true, track_lifetime_uses: false, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, }; self.with(scope, move |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -2386,7 +2355,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // given name or we run out of scopes. // search. let mut late_depth = 0; - let mut first_binder_depth = None; let mut scope = self.scope; let mut outermost_body = None; let result = loop { @@ -2404,7 +2372,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { break None; } - Scope::Binder { ref lifetimes, s, binder_depth, .. } => { + Scope::Binder { ref lifetimes, scope_type, s, .. } => { match lifetime_ref.name { LifetimeName::Param(param_name) => { if let Some(&def) = lifetimes.get(¶m_name.normalize_to_macros_2_0()) @@ -2414,8 +2382,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } _ => bug!("expected LifetimeName::Param"), } - first_binder_depth = first_binder_depth.or(Some(binder_depth)); - late_depth = first_binder_depth.unwrap_or(binder_depth) - binder_depth + 1; + match scope_type { + BinderScopeType::Other => late_depth += 1, + BinderScopeType::PolyTraitRef => late_depth += 1, + BinderScopeType::Concatenating => {} + } scope = s; } @@ -3126,7 +3097,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let span = lifetime_refs[0].span; let mut late_depth = 0; - let mut first_binder_depth = None; let mut scope = self.scope; let mut lifetime_names = FxHashSet::default(); let mut lifetime_spans = vec![]; @@ -3137,7 +3107,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Root => break None, - Scope::Binder { s, ref lifetimes, binder_depth, .. } => { + Scope::Binder { s, ref lifetimes, scope_type, .. } => { // collect named lifetimes for suggestions for name in lifetimes.keys() { if let hir::ParamName::Plain(name) = name { @@ -3145,8 +3115,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { lifetime_spans.push(name.span); } } - first_binder_depth = first_binder_depth.or(Some(binder_depth)); - late_depth = first_binder_depth.unwrap_or(binder_depth) - binder_depth + 1; + match scope_type { + BinderScopeType::Other => late_depth += 1, + BinderScopeType::PolyTraitRef => late_depth += 1, + BinderScopeType::Concatenating => {} + } scope = s; } @@ -3303,13 +3276,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) { debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref); let mut late_depth = 0; - let mut first_binder_depth = None; let mut scope = self.scope; let lifetime = loop { match *scope { - Scope::Binder { s, binder_depth, .. } => { - first_binder_depth = first_binder_depth.or(Some(binder_depth)); - late_depth = first_binder_depth.unwrap_or(binder_depth) - binder_depth + 1; + Scope::Binder { s, scope_type, .. } => { + match scope_type { + BinderScopeType::Other => late_depth += 1, + BinderScopeType::PolyTraitRef => late_depth += 1, + BinderScopeType::Concatenating => {} + } scope = s; } From 9891582897ae5f588022cec6a2f798d7a2883629 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Tue, 20 Apr 2021 16:39:41 -0400 Subject: [PATCH 20/32] Remove TraitRefHackInner and use the concatenating functionality instead of trait_ref_hack --- compiler/rustc_resolve/src/late/lifetimes.rs | 421 ++++++++----------- 1 file changed, 176 insertions(+), 245 deletions(-) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 58d053aca1ab1..62cbbd8e8f705 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -165,29 +165,6 @@ crate struct LifetimeContext<'a, 'tcx> { map: &'a mut NamedRegionMap, scope: ScopeRef<'a>, - /// This is slightly complicated. Our representation for poly-trait-refs contains a single - /// binder and thus we only allow a single level of quantification. However, - /// the syntax of Rust permits quantification in two places, e.g., `T: for <'a> Foo<'a>` - /// and `for <'a, 'b> &'b T: Foo<'a>`. In order to get the De Bruijn indices - /// correct when representing these constraints, we should only introduce one - /// scope. However, we want to support both locations for the quantifier and - /// during lifetime resolution we want precise information (so we can't - /// desugar in an earlier phase). Moreso, an error here doesn't cause a bail - /// from type checking, so we need to be extra careful that we don't lose - /// any bound var information. - /// - /// So, if we encounter a quantifier at the outer scope, we set - /// `trait_ref_hack` to the hir id of the bounded type (and introduce a scope). - /// Then, if we encounter a quantifier at the inner scope, then we know to - /// emit an error. Importantly though, we do have to track the lifetimes - /// defined on the outer scope (i.e. the bounded ty), since we continue - /// to type check after emitting an error; we therefore assume that the bound - /// vars on the inner trait refs come from both quantifiers. - /// - /// If we encounter a quantifier in the inner scope `trait_ref_hack` being - /// `None`, then we just introduce the scope at the inner quantifier as normal. - trait_ref_hack: Option, - /// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax. is_in_fn_syntax: bool, @@ -279,41 +256,6 @@ enum Scope<'a> { s: ScopeRef<'a>, }, - /// This is a particularly interesting consequence of how we handle poly - /// trait refs. See `trait_ref_hack` for additional info. This bit is - /// important w.r.t. querying late-bound vars. - /// - /// To completely understand why this is necessary, first it's important to - /// realize that `T: for<'a> U + for<'a, 'b> V` is actually two separate - /// trait refs: `T: for<'a> U` and `T: for<'b> V` and as such, the late - /// bound vars on each needs to be tracked separately. Also, in this case, - /// are *three* relevant `HirId`s: one for the entire bound and one - /// for each separate one. - /// - /// Next, imagine three different poly trait refs: - /// 1) `for<'a, 'b> T: U<'a, 'b>` - /// 2) `T: for<'a, 'b> U<'a, 'b>` - /// 3) `for<'a> T: for<'b> U<'a, 'b>` - /// - /// First, note that the third example is semantically invalid and an error, - /// but we *must* handle it as valid, since type checking isn't bailed out - /// of. Other than that, if ask for bound vars for each, we expect - /// `['a, 'b]`. If we *didn't* allow binders before `T`, then we would - /// always introduce a binder scope at the inner trait ref. This is great, - /// because later on during type-checking, we will ask "what are the late - /// bound vars on this trait ref". However, because we allow bound vars on - /// the bound itself, we have to have some way of keeping track of the fact - /// that we actually want to store the late bound vars as being associated - /// with the trait ref; this is that. - /// - /// One alternative way to handle this would be to just introduce a new - /// `Binder` scope, but that's semantically a bit different, since bound - /// vars from both `for<...>`s *do* share the same binder level. - TraitRefHackInner { - hir_id: hir::HirId, - s: ScopeRef<'a>, - }, - /// When we have nested trait refs, we concanetate late bound vars for inner /// trait refs from outer ones. But we also need to include any HRTB /// lifetimes encountered when identifying the trait that an associated type @@ -332,9 +274,48 @@ enum Scope<'a> { #[derive(Copy, Clone, Debug)] enum BinderScopeType { - Other, + /// In a syntactic trait ref, this represents the outermost binder. So, if + /// you had `T: for<'a> Foo Baz<'a, 'b>>`, then the `for<'a>` + /// scope uses `PolyTraitRef`. PolyTraitRef, + /// This is slightly complicated. Our representation for poly-trait-refs contains a single + /// binder and thus we only allow a single level of quantification. However, + /// the syntax of Rust permits quantification in two places in where clauses, + /// e.g., `T: for <'a> Foo<'a>` and `for <'a, 'b> &'b T: Foo<'a>`. In order + /// to get the De Bruijn indices correct when representing these constraints, + /// we should only introduce one scope. However, we want to support both + /// locations for the quantifier and during lifetime resolution we want + /// precise information (so we can't desugar in an earlier phase). Moreso, + /// an error here doesn't cause a bail from type checking, so we need to be + /// extra careful that we don't lose any bound var information for *either* + /// syntactic binder and that we track all lifetimes defined in both binders. + /// + /// This mechanism is similar to the concatenation done in nested poly trait + /// refs, i.e. the inner syntactic binder extends upon the lifetimes on the + /// outer syntactic binder. However, we require a separate variant here to + /// distinguish `for<'a> T: for<'b> Foo<'a, 'b>` from + /// `T: for<'a> Bar Foo<'a, 'b>>`. In this case, the innermost + /// `: for<'b> Foo<'a, 'b>` both have a `for<'a>` scope above it. However, + /// in the former case, we must emit an error because this is invalid syntax. + /// Put another way: `PolyTraitRef` and `BoundedTy` behave identically except + /// that `BoundedTy` is used to signal that an error should be emitted if + /// another syntactic binder is found. + BoundedTy, + /// Within a syntactic trait ref, there may be multiple poly trait refs that + /// are nested (under the `associcated_type_bounds` feature). The binders of + /// the innner poly trait refs are extended from the outer poly trait refs + /// and don't increase the late bound depth. If you had + /// `T: for<'a> Foo Baz<'a, 'b>>`, then the `for<'b>` scope + /// would be `Concatenating`. This also used in trait refs in where clauses + /// where we have two binders `for<> T: for<> Foo` (I've intentionally left + /// out any lifetimes because they aren't needed to show the two scopes). + /// See `BoundedTy` for a bit more details, but the inner `for<>` has a scope + /// of `Concatenating`. Concatenating, + /// Any other binder scopes. These are "normal" in that they increase the binder + /// depth, are fully syntactic, don't concatenate, and don't have special syntactical + /// considerations. + Other, } // A helper struct for debugging scopes without printing parent scopes @@ -372,11 +353,6 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { .field("lifetime", lifetime) .field("s", &"..") .finish(), - Scope::TraitRefHackInner { hir_id, s: _ } => f - .debug_struct("TraitRefHackInner") - .field("hir_id", hir_id) - .field("s", &"..") - .finish(), Scope::Supertrait { lifetimes, s: _ } => f .debug_struct("Supertrait") .field("lifetimes", lifetimes) @@ -499,7 +475,6 @@ fn do_resolve( tcx, map: &mut named_region_map, scope: ROOT_SCOPE, - trait_ref_hack: None, is_in_fn_syntax: false, is_in_const_generic: false, trait_definition_only, @@ -1324,28 +1299,25 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }) .unzip(); this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone()); - if !lifetimes.is_empty() { - let next_early_index = this.next_early_index(); - let scope = Scope::Binder { - hir_id: bounded_ty.hir_id, - lifetimes, - s: this.scope, - next_early_index, - track_lifetime_uses: true, - opaque_type_parent: false, - scope_type: BinderScopeType::PolyTraitRef, - }; - this.with(scope, |old_scope, this| { - this.check_lifetime_params(old_scope, &bound_generic_params); - this.visit_ty(&bounded_ty); - this.trait_ref_hack = Some(bounded_ty.hir_id); - walk_list!(this, visit_param_bound, bounds); - this.trait_ref_hack = None; - }) - } else { + let next_early_index = this.next_early_index(); + // Even if there are no lifetimes defined here, we still wrap it in a binder + // scope. If there happens to be a nested poly trait ref (an error), that + // will be `Concatenating` anyways, so we don't have to worry about the depth + // being wrong. + let scope = Scope::Binder { + hir_id: bounded_ty.hir_id, + lifetimes, + s: this.scope, + next_early_index, + track_lifetime_uses: true, + opaque_type_parent: false, + scope_type: BinderScopeType::BoundedTy, + }; + this.with(scope, |old_scope, this| { + this.check_lifetime_params(old_scope, &bound_generic_params); this.visit_ty(&bounded_ty); walk_list!(this, visit_param_bound, bounds); - } + }) } &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { ref lifetime, @@ -1369,8 +1341,37 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) { + // FIXME(jackh726): This is pretty weird. `LangItemTrait` doesn't go + // through the regular poly trait ref code, so we don't get another + // chance to introduce a binder. For now, I'm keeping the existing logic + // of "if there isn't a `BoundedTy` scope above us, add one", but I + // imagine there's a better way to go about this. + let mut scope = self.scope; + let trait_ref_hack = loop { + match scope { + Scope::Body { .. } | Scope::Root => { + break false; + } + + Scope::Elision { s, .. } + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } => { + scope = s; + } + + Scope::TraitRefBoundary { .. } => { + break false; + } + + Scope::Binder { scope_type, lifetimes, .. } => { + let trait_ref_hack = + matches!(scope_type, BinderScopeType::BoundedTy) && !lifetimes.is_empty(); + break trait_ref_hack; + } + } + }; match bound { - hir::GenericBound::LangItemTrait(_, _, hir_id, _) if self.trait_ref_hack.is_none() => { + hir::GenericBound::LangItemTrait(_, _, hir_id, _) if !trait_ref_hack => { self.map.late_bound_vars.insert(*hir_id, vec![]); let scope = Scope::Binder { hir_id: *hir_id, @@ -1398,15 +1399,56 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let should_pop_missing_lt = self.is_trait_ref_fn_scope(trait_ref); - let trait_ref_hack = self.trait_ref_hack.take(); let next_early_index = self.next_early_index(); - // See note on `trait_ref_hack`. If `for<..>` has been defined in both - // the outer and inner part of the trait ref, emit an error. + let mut scope = self.scope; + let mut supertrait_lifetimes = vec![]; + let (mut binders, trait_ref_hack, scope_type) = loop { + match scope { + Scope::Body { .. } | Scope::Root => { + break (vec![], false, BinderScopeType::PolyTraitRef); + } + + Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => { + scope = s; + } + + Scope::Supertrait { s, lifetimes } => { + supertrait_lifetimes = lifetimes.clone(); + scope = s; + } + + Scope::TraitRefBoundary { .. } => { + // We should only see super trait lifetimes if there is a `Binder` above + assert!(supertrait_lifetimes.is_empty()); + break (vec![], false, BinderScopeType::PolyTraitRef); + } + + Scope::Binder { hir_id, scope_type, lifetimes, .. } => { + if let BinderScopeType::Other = scope_type { + bug!( + "Expected all syntacic poly trait refs to be surrounded by a `TraitRefBoundary`" + ) + } + + // Nested poly trait refs have the binders concatenated + let mut full_binders = + self.map.late_bound_vars.entry(*hir_id).or_default().clone(); + full_binders.extend(supertrait_lifetimes.into_iter()); + let trait_ref_hack = + matches!(scope_type, BinderScopeType::BoundedTy) && !lifetimes.is_empty(); + break (full_binders, trait_ref_hack, BinderScopeType::Concatenating); + } + } + }; + + // See note on `BinderScopeType::BoundedTy`. If `for<..>` + // has been defined in both the outer and inner part of the + // trait ref, emit an error. let has_lifetimes = trait_ref.bound_generic_params.iter().any(|param| match param.kind { GenericParamKind::Lifetime { .. } => true, _ => false, }); - if trait_ref_hack.is_some() && has_lifetimes { + if trait_ref_hack && has_lifetimes { struct_span_err!( self.tcx.sess, trait_ref.span, @@ -1416,152 +1458,50 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { .emit(); } - let (binders, lifetimes) = if let Some(hir_id) = trait_ref_hack { - let mut binders = self.map.late_bound_vars.entry(hir_id).or_default().clone(); - let initial_bound_vars = binders.len() as u32; - let mut lifetimes: FxHashMap = FxHashMap::default(); - let binders_iter = trait_ref - .bound_generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some(param), - _ => None, - }) - .enumerate() - .map(|(late_bound_idx, param)| { - let pair = Region::late( - initial_bound_vars + late_bound_idx as u32, - &self.tcx.hir(), - param, - ); - let r = late_region_as_bound_region(self.tcx, &pair.1); - lifetimes.insert(pair.0, pair.1); - r - }); - binders.extend(binders_iter); - - (binders, lifetimes) - } else { - let mut supertrait_lifetimes = vec![]; - let mut scope = self.scope; - let mut outer_binders = loop { - match scope { - Scope::Body { .. } | Scope::Root => { - break vec![]; - } - - Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => { - scope = s; - } - - Scope::TraitRefHackInner { hir_id, .. } => { - // Nested poly trait refs have the binders concatenated - // If we reach `TraitRefHackInner`, then there is only one more `Binder` above us, - // over all the bounds. We don't want this, since all the lifetimes we care about - // are here anyways. - let mut full_binders = - self.map.late_bound_vars.entry(*hir_id).or_default().clone(); - full_binders.extend(supertrait_lifetimes.into_iter()); - break full_binders; - } - - Scope::Supertrait { s, lifetimes } => { - supertrait_lifetimes = lifetimes.clone(); - scope = s; - } - - Scope::TraitRefBoundary { .. } => { - // We should only see super trait lifetimes if there is a `Binder` above - assert!(supertrait_lifetimes.is_empty()); - break vec![]; - } - - Scope::Binder { hir_id, .. } => { - // Nested poly trait refs have the binders concatenated - let mut full_binders = - self.map.late_bound_vars.entry(*hir_id).or_default().clone(); - full_binders.extend(supertrait_lifetimes.into_iter()); - break full_binders; - } - } - }; - let (lifetimes, local_binders): (FxHashMap, Vec<_>) = trait_ref - .bound_generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some(param), - _ => None, - }) - .enumerate() - .map(|(late_bound_idx, param)| { - let pair = Region::late( - outer_binders.len() as u32 + late_bound_idx as u32, - &self.tcx.hir(), - param, - ); - let r = late_region_as_bound_region(self.tcx, &pair.1); - (pair, r) - }) - .unzip(); - - outer_binders.extend(local_binders.into_iter()); - - (outer_binders, lifetimes) - }; + let initial_bound_vars = binders.len() as u32; + let mut lifetimes: FxHashMap = FxHashMap::default(); + let binders_iter = trait_ref + .bound_generic_params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => Some(param), + _ => None, + }) + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = Region::late( + initial_bound_vars + late_bound_idx as u32, + &self.tcx.hir(), + param, + ); + let r = late_region_as_bound_region(self.tcx, &pair.1); + lifetimes.insert(pair.0, pair.1); + r + }); + binders.extend(binders_iter); debug!(?binders); self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders); - if trait_ref_hack.is_none() || has_lifetimes { - let scope_type = { - let mut scope = self.scope; - loop { - match *scope { - Scope::Root | Scope::TraitRefBoundary { .. } => { - break BinderScopeType::PolyTraitRef; - } - - Scope::Binder { scope_type, .. } => { - if let BinderScopeType::Other = scope_type { - bug!( - "Expected all syntacic poly trait refs to be surrounded by a `TraitRefBoundary`" - ) - } - break BinderScopeType::Concatenating; - } + // Always introduce a scope here, even if this is in a where clause and + // we introduced the binders around the bounded Ty. In that case, we + // just reuse the concatenation functionality also present in nested trait + // refs. See `BinderScopeType::BoundedTy` for more details on that case. + let scope = Scope::Binder { + hir_id: trait_ref.trait_ref.hir_ref_id, + lifetimes, + s: self.scope, + next_early_index, + track_lifetime_uses: true, + opaque_type_parent: false, + scope_type, + }; + self.with(scope, |old_scope, this| { + this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params); + walk_list!(this, visit_generic_param, trait_ref.bound_generic_params); + this.visit_trait_ref(&trait_ref.trait_ref); + }); - Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } - | Scope::TraitRefHackInner { s, .. } - | Scope::Supertrait { s, .. } - | Scope::Body { s, .. } => { - scope = s; - } - } - } - }; - let scope = Scope::Binder { - hir_id: trait_ref.trait_ref.hir_ref_id, - lifetimes, - s: self.scope, - next_early_index, - track_lifetime_uses: true, - opaque_type_parent: false, - scope_type, - }; - self.with(scope, |old_scope, this| { - this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params); - walk_list!(this, visit_generic_param, trait_ref.bound_generic_params); - this.visit_trait_ref(&trait_ref.trait_ref); - }); - } else { - let scope = - Scope::TraitRefHackInner { hir_id: trait_ref.trait_ref.hir_ref_id, s: self.scope }; - self.with(scope, |_old_scope, this| { - this.visit_trait_ref(&trait_ref.trait_ref); - }); - } - self.trait_ref_hack = trait_ref_hack; if should_pop_missing_lt { self.missing_named_lifetime_spots.pop(); } @@ -1712,7 +1652,6 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) { Scope::Body { s, .. } | Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } - | Scope::TraitRefHackInner { s, .. } | Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => { scope = s; @@ -1903,12 +1842,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let labels_in_fn = take(&mut self.labels_in_fn); let xcrate_object_lifetime_defaults = take(&mut self.xcrate_object_lifetime_defaults); let missing_named_lifetime_spots = take(&mut self.missing_named_lifetime_spots); - let trait_ref_hack = take(&mut self.trait_ref_hack); let mut this = LifetimeContext { tcx: *tcx, map, scope: &wrap_scope, - trait_ref_hack, is_in_fn_syntax: self.is_in_fn_syntax, is_in_const_generic: self.is_in_const_generic, trait_definition_only: self.trait_definition_only, @@ -1928,7 +1865,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { self.labels_in_fn = this.labels_in_fn; self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults; self.missing_named_lifetime_spots = this.missing_named_lifetime_spots; - self.trait_ref_hack = this.trait_ref_hack; } /// helper method to determine the span to remove when suggesting the @@ -2321,7 +2257,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { | Scope::Body { s, .. } | Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } - | Scope::TraitRefHackInner { s, .. } | Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => scope = s, } @@ -2384,6 +2319,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } match scope_type { BinderScopeType::Other => late_depth += 1, + BinderScopeType::BoundedTy => late_depth += 1, BinderScopeType::PolyTraitRef => late_depth += 1, BinderScopeType::Concatenating => {} } @@ -2392,7 +2328,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } - | Scope::TraitRefHackInner { s, .. } | Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => { scope = s; @@ -2547,7 +2482,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Binder { s, .. } | Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } - | Scope::TraitRefHackInner { s, .. } | Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => { scope = s; @@ -2746,7 +2680,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let mut scope = &*self.scope; let hir_id = loop { match scope { - Scope::Binder { hir_id, .. } | Scope::TraitRefHackInner { hir_id, .. } => { + Scope::Binder { hir_id, .. } => { break *hir_id; } Scope::Body { id, .. } => break id.hir_id, @@ -3117,6 +3051,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } match scope_type { BinderScopeType::Other => late_depth += 1, + BinderScopeType::BoundedTy => late_depth += 1, BinderScopeType::PolyTraitRef => late_depth += 1, BinderScopeType::Concatenating => {} } @@ -3168,7 +3103,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } Scope::ObjectLifetimeDefault { s, .. } - | Scope::TraitRefHackInner { s, .. } | Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => { scope = s; @@ -3282,6 +3216,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Binder { s, scope_type, .. } => { match scope_type { BinderScopeType::Other => late_depth += 1, + BinderScopeType::BoundedTy => late_depth += 1, BinderScopeType::PolyTraitRef => late_depth += 1, BinderScopeType::Concatenating => {} } @@ -3294,9 +3229,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l, - Scope::TraitRefHackInner { s, .. } - | Scope::Supertrait { s, .. } - | Scope::TraitRefBoundary { s, .. } => { + Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => { scope = s; } } @@ -3423,7 +3356,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Body { s, .. } | Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } - | Scope::TraitRefHackInner { s, .. } | Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => { old_scope = s; @@ -3482,7 +3414,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } => break false, Scope::ObjectLifetimeDefault { s, .. } - | Scope::TraitRefHackInner { s, .. } | Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => scope = s, } From 4568e7d62edc52dca67e28ea771978513cf6f393 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Wed, 21 Apr 2021 03:12:04 -0400 Subject: [PATCH 21/32] Move nested quantification check to ast_validation --- .../rustc_ast_passes/src/ast_validation.rs | 47 ++++++++--- compiler/rustc_resolve/src/late/lifetimes.rs | 80 ++++--------------- 2 files changed, 52 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index bb09f701531cf..809660379f326 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -81,6 +81,13 @@ struct AstValidator<'a> { is_assoc_ty_bound_banned: bool, lint_buffer: &'a mut LintBuffer, + + /// This is slightly complicated. Our representation for poly-trait-refs contains a single + /// binder and thus we only allow a single level of quantification. However, + /// the syntax of Rust permits quantification in two places in where clauses, + /// e.g., `T: for <'a> Foo<'a>` and `for <'a, 'b> &'b T: Foo<'a>`. If both are + /// defined, then error. + trait_ref_hack: bool, } impl<'a> AstValidator<'a> { @@ -1213,8 +1220,25 @@ impl<'a> Visitor<'a> for AstValidator<'a> { deny_equality_constraints(self, predicate, generics); } } + walk_list!(self, visit_generic_param, &generics.params); + for predicate in &generics.where_clause.predicates { + match predicate { + WherePredicate::BoundPredicate(bound_pred) => { + // A type binding, eg `for<'c> Foo: Send+Clone+'c` + self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params); - visit::walk_generics(self, generics) + self.visit_ty(&bound_pred.bounded_ty); + + self.trait_ref_hack = !bound_pred.bound_generic_params.is_empty(); + walk_list!(self, visit_param_bound, &bound_pred.bounds); + walk_list!(self, visit_generic_param, &bound_pred.bound_generic_params); + self.trait_ref_hack = false; + } + _ => { + self.visit_where_predicate(predicate); + } + } + } } fn visit_generic_param(&mut self, param: &'a GenericParam) { @@ -1263,17 +1287,21 @@ impl<'a> Visitor<'a> for AstValidator<'a> { visit::walk_pat(self, pat) } - fn visit_where_predicate(&mut self, p: &'a WherePredicate) { - if let &WherePredicate::BoundPredicate(ref bound_predicate) = p { - // A type binding, eg `for<'c> Foo: Send+Clone+'c` - self.check_late_bound_lifetime_defs(&bound_predicate.bound_generic_params); - } - visit::walk_where_predicate(self, p); - } - fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) { self.check_late_bound_lifetime_defs(&t.bound_generic_params); + if self.trait_ref_hack && !t.bound_generic_params.is_empty() { + struct_span_err!( + self.err_handler(), + t.span, + E0316, + "nested quantification of lifetimes" + ) + .emit(); + } + let trait_ref_hack = self.trait_ref_hack; + self.trait_ref_hack = false; visit::walk_poly_trait_ref(self, t, m); + self.trait_ref_hack = trait_ref_hack; } fn visit_variant_data(&mut self, s: &'a VariantData) { @@ -1492,6 +1520,7 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> is_impl_trait_banned: false, is_assoc_ty_bound_banned: false, lint_buffer: lints, + trait_ref_hack: false, }; visit::walk_crate(&mut validator, krate); diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 62cbbd8e8f705..3cccbb06bc426 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -278,29 +278,6 @@ enum BinderScopeType { /// you had `T: for<'a> Foo Baz<'a, 'b>>`, then the `for<'a>` /// scope uses `PolyTraitRef`. PolyTraitRef, - /// This is slightly complicated. Our representation for poly-trait-refs contains a single - /// binder and thus we only allow a single level of quantification. However, - /// the syntax of Rust permits quantification in two places in where clauses, - /// e.g., `T: for <'a> Foo<'a>` and `for <'a, 'b> &'b T: Foo<'a>`. In order - /// to get the De Bruijn indices correct when representing these constraints, - /// we should only introduce one scope. However, we want to support both - /// locations for the quantifier and during lifetime resolution we want - /// precise information (so we can't desugar in an earlier phase). Moreso, - /// an error here doesn't cause a bail from type checking, so we need to be - /// extra careful that we don't lose any bound var information for *either* - /// syntactic binder and that we track all lifetimes defined in both binders. - /// - /// This mechanism is similar to the concatenation done in nested poly trait - /// refs, i.e. the inner syntactic binder extends upon the lifetimes on the - /// outer syntactic binder. However, we require a separate variant here to - /// distinguish `for<'a> T: for<'b> Foo<'a, 'b>` from - /// `T: for<'a> Bar Foo<'a, 'b>>`. In this case, the innermost - /// `: for<'b> Foo<'a, 'b>` both have a `for<'a>` scope above it. However, - /// in the former case, we must emit an error because this is invalid syntax. - /// Put another way: `PolyTraitRef` and `BoundedTy` behave identically except - /// that `BoundedTy` is used to signal that an error should be emitted if - /// another syntactic binder is found. - BoundedTy, /// Within a syntactic trait ref, there may be multiple poly trait refs that /// are nested (under the `associcated_type_bounds` feature). The binders of /// the innner poly trait refs are extended from the outer poly trait refs @@ -309,8 +286,7 @@ enum BinderScopeType { /// would be `Concatenating`. This also used in trait refs in where clauses /// where we have two binders `for<> T: for<> Foo` (I've intentionally left /// out any lifetimes because they aren't needed to show the two scopes). - /// See `BoundedTy` for a bit more details, but the inner `for<>` has a scope - /// of `Concatenating`. + /// The inner `for<>` has a scope of `Concatenating`. Concatenating, /// Any other binder scopes. These are "normal" in that they increase the binder /// depth, are fully syntactic, don't concatenate, and don't have special syntactical @@ -1311,7 +1287,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index, track_lifetime_uses: true, opaque_type_parent: false, - scope_type: BinderScopeType::BoundedTy, + scope_type: BinderScopeType::PolyTraitRef, }; this.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &bound_generic_params); @@ -1344,30 +1320,24 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // FIXME(jackh726): This is pretty weird. `LangItemTrait` doesn't go // through the regular poly trait ref code, so we don't get another // chance to introduce a binder. For now, I'm keeping the existing logic - // of "if there isn't a `BoundedTy` scope above us, add one", but I + // of "if there isn't a Binder scope above us, add one", but I // imagine there's a better way to go about this. let mut scope = self.scope; let trait_ref_hack = loop { match scope { - Scope::Body { .. } | Scope::Root => { + Scope::TraitRefBoundary { .. } | Scope::Body { .. } | Scope::Root => { break false; } + Scope::Binder { .. } => { + break true; + } + Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } | Scope::Supertrait { s, .. } => { scope = s; } - - Scope::TraitRefBoundary { .. } => { - break false; - } - - Scope::Binder { scope_type, lifetimes, .. } => { - let trait_ref_hack = - matches!(scope_type, BinderScopeType::BoundedTy) && !lifetimes.is_empty(); - break trait_ref_hack; - } } }; match bound { @@ -1402,10 +1372,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let next_early_index = self.next_early_index(); let mut scope = self.scope; let mut supertrait_lifetimes = vec![]; - let (mut binders, trait_ref_hack, scope_type) = loop { + let (mut binders, scope_type) = loop { match scope { Scope::Body { .. } | Scope::Root => { - break (vec![], false, BinderScopeType::PolyTraitRef); + break (vec![], BinderScopeType::PolyTraitRef); } Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => { @@ -1420,10 +1390,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { Scope::TraitRefBoundary { .. } => { // We should only see super trait lifetimes if there is a `Binder` above assert!(supertrait_lifetimes.is_empty()); - break (vec![], false, BinderScopeType::PolyTraitRef); + break (vec![], BinderScopeType::PolyTraitRef); } - Scope::Binder { hir_id, scope_type, lifetimes, .. } => { + Scope::Binder { hir_id, scope_type, .. } => { if let BinderScopeType::Other = scope_type { bug!( "Expected all syntacic poly trait refs to be surrounded by a `TraitRefBoundary`" @@ -1434,30 +1404,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let mut full_binders = self.map.late_bound_vars.entry(*hir_id).or_default().clone(); full_binders.extend(supertrait_lifetimes.into_iter()); - let trait_ref_hack = - matches!(scope_type, BinderScopeType::BoundedTy) && !lifetimes.is_empty(); - break (full_binders, trait_ref_hack, BinderScopeType::Concatenating); + break (full_binders, BinderScopeType::Concatenating); } } }; - // See note on `BinderScopeType::BoundedTy`. If `for<..>` - // has been defined in both the outer and inner part of the - // trait ref, emit an error. - let has_lifetimes = trait_ref.bound_generic_params.iter().any(|param| match param.kind { - GenericParamKind::Lifetime { .. } => true, - _ => false, - }); - if trait_ref_hack && has_lifetimes { - struct_span_err!( - self.tcx.sess, - trait_ref.span, - E0316, - "nested quantification of lifetimes" - ) - .emit(); - } - let initial_bound_vars = binders.len() as u32; let mut lifetimes: FxHashMap = FxHashMap::default(); let binders_iter = trait_ref @@ -1486,7 +1437,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // Always introduce a scope here, even if this is in a where clause and // we introduced the binders around the bounded Ty. In that case, we // just reuse the concatenation functionality also present in nested trait - // refs. See `BinderScopeType::BoundedTy` for more details on that case. + // refs. let scope = Scope::Binder { hir_id: trait_ref.trait_ref.hir_ref_id, lifetimes, @@ -2319,7 +2270,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } match scope_type { BinderScopeType::Other => late_depth += 1, - BinderScopeType::BoundedTy => late_depth += 1, BinderScopeType::PolyTraitRef => late_depth += 1, BinderScopeType::Concatenating => {} } @@ -3051,7 +3001,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } match scope_type { BinderScopeType::Other => late_depth += 1, - BinderScopeType::BoundedTy => late_depth += 1, BinderScopeType::PolyTraitRef => late_depth += 1, BinderScopeType::Concatenating => {} } @@ -3216,7 +3165,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Binder { s, scope_type, .. } => { match scope_type { BinderScopeType::Other => late_depth += 1, - BinderScopeType::BoundedTy => late_depth += 1, BinderScopeType::PolyTraitRef => late_depth += 1, BinderScopeType::Concatenating => {} } From 259a368e9eae8e9952d18e211d2fe0a7e5fae714 Mon Sep 17 00:00:00 2001 From: lcnr Date: Sun, 18 Apr 2021 13:57:22 +0200 Subject: [PATCH 22/32] fix name resolution for param defaults --- compiler/rustc_resolve/src/diagnostics.rs | 11 --- compiler/rustc_resolve/src/late.rs | 69 +++++++++++-------- compiler/rustc_resolve/src/lib.rs | 58 +++------------- .../defaults/complex-generic-default-expr.rs | 9 +++ .../complex-generic-default-expr.stderr | 16 +++++ .../defaults/default-on-impl.rs | 9 +++ .../defaults/default-on-impl.stderr | 8 +++ .../defaults/pretty-printing-ast.rs | 3 +- .../defaults/pretty-printing-ast.stdout | 3 +- .../defaults/type-default-const-param-name.rs | 17 +++++ ...ms-in-ct-in-ty-param-lazy-norm.full.stderr | 23 +++++-- ...ams-in-ct-in-ty-param-lazy-norm.min.stderr | 5 +- .../params-in-ct-in-ty-param-lazy-norm.rs | 4 +- .../generics/generic-non-trailing-defaults.rs | 1 + .../generic-non-trailing-defaults.stderr | 9 ++- 15 files changed, 141 insertions(+), 104 deletions(-) create mode 100644 src/test/ui/const-generics/defaults/complex-generic-default-expr.rs create mode 100644 src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr create mode 100644 src/test/ui/const-generics/defaults/default-on-impl.rs create mode 100644 src/test/ui/const-generics/defaults/default-on-impl.stderr create mode 100644 src/test/ui/const-generics/defaults/type-default-const-param-name.rs diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 87e28f7fcc592..c5f12c0c691b3 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -472,17 +472,6 @@ impl<'a> Resolver<'a> { ); err } - ResolutionError::ParamInAnonConstInTyDefault(name) => { - let mut err = self.session.struct_span_err( - span, - "constant values inside of type parameter defaults must not depend on generic parameters", - ); - err.span_label( - span, - format!("the anonymous constant must not depend on the parameter `{}`", name), - ); - err - } ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => { let mut err = self.session.struct_span_err( span, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9321f11f65933..92f21191de430 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -555,18 +555,23 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // provide previous type parameters as they're built. We // put all the parameters on the ban list and then remove // them one by one as they are processed and become available. - let mut default_ban_rib = Rib::new(ForwardGenericParamBanRibKind); - let mut found_default = false; - default_ban_rib.bindings.extend(generics.params.iter().filter_map( - |param| match param.kind { - GenericParamKind::Type { default: Some(_), .. } - | GenericParamKind::Const { default: Some(_), .. } => { - found_default = true; - Some((Ident::with_dummy_span(param.ident.name), Res::Err)) + let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind); + let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind); + for param in generics.params.iter() { + match param.kind { + GenericParamKind::Type { .. } => { + forward_ty_ban_rib + .bindings + .insert(Ident::with_dummy_span(param.ident.name), Res::Err); } - _ => None, - }, - )); + GenericParamKind::Const { .. } => { + forward_const_ban_rib + .bindings + .insert(Ident::with_dummy_span(param.ident.name), Res::Err); + } + GenericParamKind::Lifetime => {} + } + } // rust-lang/rust#61631: The type `Self` is essentially // another type parameter. For ADTs, we consider it @@ -579,7 +584,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // such as in the case of `trait Add`.) if self.diagnostic_metadata.current_self_item.is_some() { // (`Some` if + only if we are in ADT's generics.) - default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); + forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); } for param in &generics.params { @@ -591,32 +596,38 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } if let Some(ref ty) = default { - self.ribs[TypeNS].push(default_ban_rib); - self.with_rib(ValueNS, ForwardGenericParamBanRibKind, |this| { - // HACK: We use an empty `ForwardGenericParamBanRibKind` here which - // is only used to forbid the use of const parameters inside of - // type defaults. - // - // While the rib name doesn't really fit here, it does allow us to use the same - // code for both const and type parameters. - this.visit_ty(ty); - }); - default_ban_rib = self.ribs[TypeNS].pop().unwrap(); + self.ribs[TypeNS].push(forward_ty_ban_rib); + self.ribs[ValueNS].push(forward_const_ban_rib); + self.visit_ty(ty); + forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap(); + forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap(); } // Allow all following defaults to refer to this type parameter. - default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); + forward_ty_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); } - GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { - // FIXME(const_generics_defaults): handle `default` value here - for bound in ¶m.bounds { - self.visit_param_bound(bound); - } + GenericParamKind::Const { ref ty, kw_span: _, ref default } => { + // Const parameters can't have param bounds. + assert!(param.bounds.is_empty()); + self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind)); self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind)); self.visit_ty(ty); self.ribs[TypeNS].pop().unwrap(); self.ribs[ValueNS].pop().unwrap(); + + if let Some(ref expr) = default { + self.ribs[TypeNS].push(forward_ty_ban_rib); + self.ribs[ValueNS].push(forward_const_ban_rib); + self.visit_anon_const(expr); + forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap(); + forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap(); + } + + // Allow all following defaults to refer to this const parameter. + forward_const_ban_rib + .bindings + .remove(&Ident::with_dummy_span(param.ident.name)); } } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 129954381c9ba..1d1969f7e78ab 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -239,8 +239,6 @@ enum ResolutionError<'a> { ForwardDeclaredTyParam, // FIXME(const_generics_defaults) /// ERROR E0770: the type of const parameters must not depend on other generic parameters. ParamInTyOfConstParam(Symbol), - /// constant values inside of type parameter defaults must not depend on generic parameters. - ParamInAnonConstInTyDefault(Symbol), /// generic parameters must not be used inside const evaluations. /// /// This error is only emitted when using `min_const_generics`. @@ -2672,26 +2670,18 @@ impl<'a> Resolver<'a> { } } Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => { - let mut in_ty_param_default = false; for rib in ribs { - let has_generic_params = match rib.kind { + let has_generic_params: HasGenericParams = match rib.kind { NormalRibKind | ClosureOrAsyncRibKind | AssocItemRibKind | ModuleRibKind(..) - | MacroDefinition(..) => { + | MacroDefinition(..) + | ForwardGenericParamBanRibKind => { // Nothing to do. Continue. continue; } - // We only forbid constant items if we are inside of type defaults, - // for example `struct Foo()]>` - ForwardGenericParamBanRibKind => { - // FIXME(const_generic_defaults): we may need to distinguish between - // being in type parameter defaults and const parameter defaults - in_ty_param_default = true; - continue; - } ConstantItemRibKind(trivial, _) => { let features = self.session.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. @@ -2720,19 +2710,7 @@ impl<'a> Resolver<'a> { } } - if in_ty_param_default { - if record_used { - self.report_error( - span, - ResolutionError::ParamInAnonConstInTyDefault( - rib_ident.name, - ), - ); - } - return Res::Err; - } else { - continue; - } + continue; } // This was an attempt to use a type parameter outside its scope. @@ -2770,23 +2748,15 @@ impl<'a> Resolver<'a> { ribs.next(); } - let mut in_ty_param_default = false; for rib in ribs { let has_generic_params = match rib.kind { NormalRibKind | ClosureOrAsyncRibKind | AssocItemRibKind | ModuleRibKind(..) - | MacroDefinition(..) => continue, - - // We only forbid constant items if we are inside of type defaults, - // for example `struct Foo()]>` - ForwardGenericParamBanRibKind => { - // FIXME(const_generic_defaults): we may need to distinguish between - // being in type parameter defaults and const parameter defaults - in_ty_param_default = true; - continue; - } + | MacroDefinition(..) + | ForwardGenericParamBanRibKind => continue, + ConstantItemRibKind(trivial, _) => { let features = self.session.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. @@ -2808,19 +2778,7 @@ impl<'a> Resolver<'a> { return Res::Err; } - if in_ty_param_default { - if record_used { - self.report_error( - span, - ResolutionError::ParamInAnonConstInTyDefault( - rib_ident.name, - ), - ); - } - return Res::Err; - } else { - continue; - } + continue; } ItemRibKind(has_generic_params) => has_generic_params, diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs new file mode 100644 index 0000000000000..ba00e4b15ca15 --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs @@ -0,0 +1,9 @@ +#![feature(const_generics, const_generics_defaults)] +#![allow(incomplete_features)] + +struct Foo; + +struct Bar() }>(T); +//~^ ERROR the size for values of type `T` cannot be known at compilation time + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr new file mode 100644 index 0000000000000..06865fdd8fd3a --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/complex-generic-default-expr.rs:6:62 + | +LL | struct Bar() }>(T); + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub const fn size_of() -> usize { + | - required by this bound in `std::mem::size_of` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/defaults/default-on-impl.rs b/src/test/ui/const-generics/defaults/default-on-impl.rs new file mode 100644 index 0000000000000..2555450a9e7f8 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-on-impl.rs @@ -0,0 +1,9 @@ +#![feature(const_generics, const_generics_defaults)] +#![allow(incomplete_features)] + +struct Foo; + +impl Foo {} +//~^ ERROR defaults for const parameters are only allowed + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/default-on-impl.stderr b/src/test/ui/const-generics/defaults/default-on-impl.stderr new file mode 100644 index 0000000000000..b30b18a7b3c71 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-on-impl.stderr @@ -0,0 +1,8 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default-on-impl.rs:6:12 + | +LL | impl Foo {} + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs index a25d4baca1a97..12a92a10476d5 100644 --- a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs @@ -10,4 +10,5 @@ trait Foo {} fn foo() {} -struct Range; +struct Range; + diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout index f7a1d2ca4b2ef..c514bbe72e1d8 100644 --- a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout @@ -17,4 +17,5 @@ trait Foo { } fn foo() { } struct Range; + FROM>; + diff --git a/src/test/ui/const-generics/defaults/type-default-const-param-name.rs b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs new file mode 100644 index 0000000000000..c0c83cda285da --- /dev/null +++ b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs @@ -0,0 +1,17 @@ +// check-pass +#![feature(const_generics, const_generics_defaults)] +#![allow(incomplete_features)] + +struct N; + +struct Foo(T); + +impl Foo { + fn new() -> Self { + Foo(N) + } +} + +fn main() { + let Foo::<1, N>(N) = Foo::new(); +} diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr index c2b7b206653a6..d8bfab6aa52c8 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr @@ -6,17 +6,26 @@ LL | struct Bar(T); | = note: using type defaults and const parameters in the same parameter list is currently not permitted -error: constant values inside of type parameter defaults must not depend on generic parameters +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 + | +LL | struct Bar(T); + | ^ defaulted generic parameters cannot be forward declared + +error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44 | LL | struct Foo()]>(T, U); - | ^ the anonymous constant must not depend on the parameter `T` - -error: constant values inside of type parameter defaults must not depend on generic parameters - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL | -LL | struct Bar(T); - | ^ the anonymous constant must not depend on the parameter `N` +LL | pub const fn size_of() -> usize { + | - required by this bound in `std::mem::size_of` error: aborting due to 3 previous errors +Some errors have detailed explanations: E0128, E0277. +For more information about an error, try `rustc --explain E0128`. diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr index 4a462c328bf64..44393a30266d6 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -15,11 +15,12 @@ LL | struct Foo()]>(T, U); = note: type parameters may not be used in const expressions = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions -error: constant values inside of type parameter defaults must not depend on generic parameters +error[E0128]: generic parameters with a default cannot use forward declared identifiers --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 | LL | struct Bar(T); - | ^ the anonymous constant must not depend on the parameter `N` + | ^ defaulted generic parameters cannot be forward declared error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0128`. diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs index c7be8bdaf9c3d..8a84afd065c1e 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs @@ -4,12 +4,12 @@ #![cfg_attr(full, allow(incomplete_features))] struct Foo()]>(T, U); -//[full]~^ ERROR constant values inside of type parameter defaults +//[full]~^ ERROR the size for values of type `T` cannot be known at compilation time //[min]~^^ ERROR generic parameters may not be used in const operations // FIXME(const_generics_defaults): We still don't know how to deal with type defaults. struct Bar(T); -//~^ ERROR constant values inside of type parameter defaults +//~^ ERROR generic parameters with a default cannot use forward declared identifiers //~| ERROR generic parameters with a default fn main() {} diff --git a/src/test/ui/generics/generic-non-trailing-defaults.rs b/src/test/ui/generics/generic-non-trailing-defaults.rs index cb2bb2832b70e..16ea71d48c825 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.rs +++ b/src/test/ui/generics/generic-non-trailing-defaults.rs @@ -5,5 +5,6 @@ struct Vec(A, T); struct Foo, C>(A, B, C); //~^ ERROR generic parameters with a default must be trailing +//~| ERROR generic parameters with a default cannot use fn main() {} diff --git a/src/test/ui/generics/generic-non-trailing-defaults.stderr b/src/test/ui/generics/generic-non-trailing-defaults.stderr index 6d76861750335..713ba091b861c 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.stderr +++ b/src/test/ui/generics/generic-non-trailing-defaults.stderr @@ -10,5 +10,12 @@ error: generic parameters with a default must be trailing LL | struct Foo, C>(A, B, C); | ^ -error: aborting due to 2 previous errors +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/generic-non-trailing-defaults.rs:6:23 + | +LL | struct Foo, C>(A, B, C); + | ^ defaulted generic parameters cannot be forward declared + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0128`. From 7cb1dcd48802378929032ad9363c296891443d76 Mon Sep 17 00:00:00 2001 From: lcnr Date: Sun, 18 Apr 2021 14:31:00 +0200 Subject: [PATCH 23/32] loosen ordering restricts for `const_generics_defaults` --- .../rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_feature/src/active.rs | 4 ++ compiler/rustc_hir/src/hir.rs | 4 +- compiler/rustc_middle/src/ty/generics.rs | 2 +- compiler/rustc_typeck/src/astconv/generics.rs | 6 ++- .../defaults/auxiliary/const_defaulty.rs | 2 +- ... complex-generic-default-expr.full.stderr} | 2 +- .../complex-generic-default-expr.min.stderr | 20 +++++++ .../defaults/complex-generic-default-expr.rs | 8 ++- .../const-generics/defaults/const-default.rs | 4 +- ...mpl.stderr => default-on-impl.full.stderr} | 2 +- .../defaults/default-on-impl.min.stderr | 8 +++ .../defaults/default-on-impl.rs | 4 +- .../ui/const-generics/defaults/external.rs | 2 + .../defaults/intermixed-lifetime.full.stderr | 2 +- .../defaults/intermixed-lifetime.min.stderr | 22 ++------ .../defaults/intermixed-lifetime.rs | 10 ++-- .../{mismatch.stderr => mismatch.full.stderr} | 10 ++-- .../defaults/mismatch.min.stderr | 52 +++++++++++++++++++ .../ui/const-generics/defaults/mismatch.rs | 3 +- .../defaults/pretty-printing-ast.stdout | 1 - .../defaults/repr-c-issue-82792.rs | 2 +- .../defaults/simple-defaults.min.stderr | 8 --- .../defaults/simple-defaults.rs | 10 ++-- .../defaults/type-default-const-param-name.rs | 4 +- .../defaults/wrong-order.full.stderr | 15 +----- .../defaults/wrong-order.min.stderr | 4 +- .../ui/const-generics/defaults/wrong-order.rs | 4 +- ...ms-in-ct-in-ty-param-lazy-norm.full.stderr | 4 +- ...ams-in-ct-in-ty-param-lazy-norm.min.stderr | 4 +- .../params-in-ct-in-ty-param-lazy-norm.rs | 1 - 31 files changed, 145 insertions(+), 81 deletions(-) rename src/test/ui/const-generics/defaults/{complex-generic-default-expr.stderr => complex-generic-default-expr.full.stderr} (93%) create mode 100644 src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr rename src/test/ui/const-generics/defaults/{default-on-impl.stderr => default-on-impl.full.stderr} (85%) create mode 100644 src/test/ui/const-generics/defaults/default-on-impl.min.stderr rename src/test/ui/const-generics/defaults/{mismatch.stderr => mismatch.full.stderr} (90%) create mode 100644 src/test/ui/const-generics/defaults/mismatch.min.stderr delete mode 100644 src/test/ui/const-generics/defaults/simple-defaults.min.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index bb09f701531cf..e79392adf74b8 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -754,7 +754,7 @@ fn validate_generic_param_order( GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident), GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { let ty = pprust::ty_to_string(ty); - let unordered = sess.features_untracked().const_generics; + let unordered = sess.features_untracked().unordered_const_ty_params(); (ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty))) } }; diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 6fd1af60fe2d8..80f237148c3d2 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -63,6 +63,10 @@ macro_rules! declare_features { _ => panic!("`{}` was not listed in `declare_features`", feature), } } + + pub fn unordered_const_ty_params(&self) -> bool { + self.const_generics || self.const_generics_defaults + } } }; } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 1051fb8cea279..a70be14546b41 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -296,7 +296,9 @@ impl GenericArg<'_> { match self { GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime, GenericArg::Type(_) => ast::ParamKindOrd::Type, - GenericArg::Const(_) => ast::ParamKindOrd::Const { unordered: feats.const_generics }, + GenericArg::Const(_) => { + ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() } + } } } } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index d30a8693959f3..c8fdbc30d1591 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -36,7 +36,7 @@ impl GenericParamDefKind { GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime, GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type, GenericParamDefKind::Const { .. } => { - ast::ParamKindOrd::Const { unordered: tcx.features().const_generics } + ast::ParamKindOrd::Const { unordered: tcx.features().unordered_const_ty_params() } } } } diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 7a297f2c65f13..2bbb38c294d57 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -286,7 +286,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ParamKindOrd::Const { unordered: tcx .features() - .const_generics, + .unordered_const_ty_params(), } } }, @@ -309,7 +309,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { GenericArg::Lifetime(_) => ParamKindOrd::Lifetime, GenericArg::Type(_) => ParamKindOrd::Type, GenericArg::Const(_) => ParamKindOrd::Const { - unordered: tcx.features().const_generics, + unordered: tcx + .features() + .unordered_const_ty_params(), }, }), Some(&format!( diff --git a/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs index 769b6e952dc9c..6514409698e3e 100644 --- a/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs +++ b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs @@ -1,4 +1,4 @@ -#![feature(const_generics)] +#![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr similarity index 93% rename from src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr rename to src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr index 06865fdd8fd3a..c1444abbd3f32 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/complex-generic-default-expr.rs:6:62 + --> $DIR/complex-generic-default-expr.rs:9:62 | LL | struct Bar() }>(T); | - ^ doesn't have a size known at compile-time diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr new file mode 100644 index 0000000000000..d50a0a61d4949 --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr @@ -0,0 +1,20 @@ +error: generic parameters may not be used in const operations + --> $DIR/complex-generic-default-expr.rs:6:47 + | +LL | struct Foo; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-generic-default-expr.rs:9:62 + | +LL | struct Bar() }>(T); + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs index ba00e4b15ca15..1c25fda8d30ca 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs @@ -1,9 +1,13 @@ -#![feature(const_generics, const_generics_defaults)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] #![allow(incomplete_features)] struct Foo; +//[min]~^ ERROR generic parameters may not be used in const operations struct Bar() }>(T); -//~^ ERROR the size for values of type `T` cannot be known at compilation time +//[min]~^ ERROR generic parameters may not be used in const operations +//[full]~^^ ERROR the size for values of type `T` cannot be known at compilation time fn main() {} diff --git a/src/test/ui/const-generics/defaults/const-default.rs b/src/test/ui/const-generics/defaults/const-default.rs index 150c70770ae51..4fa21b8b1fb78 100644 --- a/src/test/ui/const-generics/defaults/const-default.rs +++ b/src/test/ui/const-generics/defaults/const-default.rs @@ -1,6 +1,6 @@ // run-pass - -#![feature(const_generics)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] diff --git a/src/test/ui/const-generics/defaults/default-on-impl.stderr b/src/test/ui/const-generics/defaults/default-on-impl.full.stderr similarity index 85% rename from src/test/ui/const-generics/defaults/default-on-impl.stderr rename to src/test/ui/const-generics/defaults/default-on-impl.full.stderr index b30b18a7b3c71..c417a26842ed1 100644 --- a/src/test/ui/const-generics/defaults/default-on-impl.stderr +++ b/src/test/ui/const-generics/defaults/default-on-impl.full.stderr @@ -1,5 +1,5 @@ error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/default-on-impl.rs:6:12 + --> $DIR/default-on-impl.rs:8:12 | LL | impl Foo {} | ^ diff --git a/src/test/ui/const-generics/defaults/default-on-impl.min.stderr b/src/test/ui/const-generics/defaults/default-on-impl.min.stderr new file mode 100644 index 0000000000000..c417a26842ed1 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-on-impl.min.stderr @@ -0,0 +1,8 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default-on-impl.rs:8:12 + | +LL | impl Foo {} + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/defaults/default-on-impl.rs b/src/test/ui/const-generics/defaults/default-on-impl.rs index 2555450a9e7f8..735549defeaf0 100644 --- a/src/test/ui/const-generics/defaults/default-on-impl.rs +++ b/src/test/ui/const-generics/defaults/default-on-impl.rs @@ -1,4 +1,6 @@ -#![feature(const_generics, const_generics_defaults)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] #![allow(incomplete_features)] struct Foo; diff --git a/src/test/ui/const-generics/defaults/external.rs b/src/test/ui/const-generics/defaults/external.rs index b39e69ab10b66..32acf567cf2b9 100644 --- a/src/test/ui/const-generics/defaults/external.rs +++ b/src/test/ui/const-generics/defaults/external.rs @@ -1,5 +1,7 @@ // aux-build:const_defaulty.rs // check-pass +// revisions: full min +#![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr index c4a666a829d8c..29d835e36c6eb 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr @@ -1,5 +1,5 @@ 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 = u32>` diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr index 69a490978d1df..985e7b655ece9 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr @@ -1,26 +1,14 @@ 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 types, then consts: `<'a, T = u32, const N: usize>` + | -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const N: usize, T = u32>` -error: type parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:6:32 - | -LL | struct Foo(&'a (), T); - | ---------------------^------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` - -error: lifetime parameters must be declared prior to const parameters +error: lifetime parameters must be declared prior to type parameters --> $DIR/intermixed-lifetime.rs:10:37 | LL | struct Bar(&'a (), T); - | --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` - -error: type parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:10:28 - | -LL | struct Bar(&'a (), T); - | -----------------^----------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` + | --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const N: usize, T = u32>` -error: aborting due to 4 previous errors +error: aborting due to 2 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 9e83bf92a59b9..307e3aaf1fbf3 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs @@ -1,15 +1,13 @@ -// revisions: full min // Checks that lifetimes cannot be interspersed between consts and types. +// revisions: full min #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(full, allow(incomplete_features))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] 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); -//[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 +//~^ Error lifetime parameters must be declared prior to type parameters fn main() {} diff --git a/src/test/ui/const-generics/defaults/mismatch.stderr b/src/test/ui/const-generics/defaults/mismatch.full.stderr similarity index 90% rename from src/test/ui/const-generics/defaults/mismatch.stderr rename to src/test/ui/const-generics/defaults/mismatch.full.stderr index ff72c71c40f0f..be4f364d8ee62 100644 --- a/src/test/ui/const-generics/defaults/mismatch.stderr +++ b/src/test/ui/const-generics/defaults/mismatch.full.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/mismatch.rs:11:28 + --> $DIR/mismatch.rs:12:28 | LL | let e: Example::<13> = (); | ------------- ^^ expected struct `Example`, found `()` @@ -7,7 +7,7 @@ LL | let e: Example::<13> = (); | expected due to this error[E0308]: mismatched types - --> $DIR/mismatch.rs:13:34 + --> $DIR/mismatch.rs:14:34 | LL | let e: Example2:: = (); | ------------------- ^^ expected struct `Example2`, found `()` @@ -18,7 +18,7 @@ LL | let e: Example2:: = (); found unit type `()` error[E0308]: mismatched types - --> $DIR/mismatch.rs:15:34 + --> $DIR/mismatch.rs:16:34 | LL | let e: Example3::<13, u32> = (); | ------------------- ^^ expected struct `Example3`, found `()` @@ -29,7 +29,7 @@ LL | let e: Example3::<13, u32> = (); found unit type `()` error[E0308]: mismatched types - --> $DIR/mismatch.rs:17:28 + --> $DIR/mismatch.rs:18:28 | LL | let e: Example3::<7> = (); | ------------- ^^ expected struct `Example3`, found `()` @@ -40,7 +40,7 @@ LL | let e: Example3::<7> = (); found unit type `()` error[E0308]: mismatched types - --> $DIR/mismatch.rs:21:28 + --> $DIR/mismatch.rs:22:28 | LL | let e: Example4::<7> = (); | ------------- ^^ expected struct `Example4`, found `()` diff --git a/src/test/ui/const-generics/defaults/mismatch.min.stderr b/src/test/ui/const-generics/defaults/mismatch.min.stderr new file mode 100644 index 0000000000000..be4f364d8ee62 --- /dev/null +++ b/src/test/ui/const-generics/defaults/mismatch.min.stderr @@ -0,0 +1,52 @@ +error[E0308]: mismatched types + --> $DIR/mismatch.rs:12:28 + | +LL | let e: Example::<13> = (); + | ------------- ^^ expected struct `Example`, found `()` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:14:34 + | +LL | let e: Example2:: = (); + | ------------------- ^^ expected struct `Example2`, found `()` + | | + | expected due to this + | + = note: expected struct `Example2` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:16:34 + | +LL | let e: Example3::<13, u32> = (); + | ------------------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:18:28 + | +LL | let e: Example3::<7> = (); + | ------------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3<7_usize>` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:22:28 + | +LL | let e: Example4::<7> = (); + | ------------- ^^ expected struct `Example4`, found `()` + | | + | expected due to this + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/defaults/mismatch.rs b/src/test/ui/const-generics/defaults/mismatch.rs index d85b756f538dc..68a640c0a08b3 100644 --- a/src/test/ui/const-generics/defaults/mismatch.rs +++ b/src/test/ui/const-generics/defaults/mismatch.rs @@ -1,4 +1,5 @@ -#![feature(const_generics)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout index c514bbe72e1d8..f549993c413d4 100644 --- a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout @@ -18,4 +18,3 @@ fn foo() { } struct Range; - diff --git a/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs index 18ecf46729977..c64c2974c8f8f 100644 --- a/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs +++ b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs @@ -6,7 +6,7 @@ #![allow(incomplete_features)] #[repr(C)] -pub struct Loaf { +pub struct Loaf { head: [T; N], slice: [T], } diff --git a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr b/src/test/ui/const-generics/defaults/simple-defaults.min.stderr deleted file mode 100644 index 0746c64ac8cf4..0000000000000 --- a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: type parameters must be declared prior to const parameters - --> $DIR/simple-defaults.rs:8:40 - | -LL | struct FixedOutput<'a, const N: usize, T=u32> { - | ---------------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, 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 cb66c7769bb23..c003cb2c5a6ee 100644 --- a/src/test/ui/const-generics/defaults/simple-defaults.rs +++ b/src/test/ui/const-generics/defaults/simple-defaults.rs @@ -1,12 +1,12 @@ -// [full] run-pass -// revisions: min full -// Checks some basic test cases for defaults. +// run-pass +// Checks that type param defaults are allowed after const params. +// revisions: full min #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(full, allow(incomplete_features))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] #![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], } diff --git a/src/test/ui/const-generics/defaults/type-default-const-param-name.rs b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs index c0c83cda285da..e68075ee3c627 100644 --- a/src/test/ui/const-generics/defaults/type-default-const-param-name.rs +++ b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs @@ -1,5 +1,7 @@ // check-pass -#![feature(const_generics, const_generics_defaults)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] #![allow(incomplete_features)] struct N; diff --git a/src/test/ui/const-generics/defaults/wrong-order.full.stderr b/src/test/ui/const-generics/defaults/wrong-order.full.stderr index accc73134d899..eb0bcb2821556 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.full.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.full.stderr @@ -1,19 +1,8 @@ error: generic parameters with a default must be trailing - --> $DIR/wrong-order.rs:4:10 + --> $DIR/wrong-order.rs:6:10 | LL | struct A { | ^ - | - = note: using type defaults and const parameters in the same parameter list is currently not permitted - -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/wrong-order.rs:2:27 - | -LL | #![cfg_attr(full, feature(const_generics))] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error diff --git a/src/test/ui/const-generics/defaults/wrong-order.min.stderr b/src/test/ui/const-generics/defaults/wrong-order.min.stderr index c8f1d471b244b..eb0bcb2821556 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.min.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.min.stderr @@ -1,10 +1,8 @@ error: generic parameters with a default must be trailing - --> $DIR/wrong-order.rs:4:10 + --> $DIR/wrong-order.rs:6:10 | LL | struct A { | ^ - | - = note: using type defaults and const parameters in the same parameter list is currently not permitted error: aborting due to previous error diff --git a/src/test/ui/const-generics/defaults/wrong-order.rs b/src/test/ui/const-generics/defaults/wrong-order.rs index 5c2d9b8ad4751..88e9e96ba43f9 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.rs +++ b/src/test/ui/const-generics/defaults/wrong-order.rs @@ -1,5 +1,7 @@ // revisions: full min -#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] struct A { //~^ ERROR generic parameters with a default must be trailing diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr index d8bfab6aa52c8..cf947a565c454 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr @@ -1,5 +1,5 @@ error: generic parameters with a default must be trailing - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:12 | LL | struct Bar(T); | ^ @@ -7,7 +7,7 @@ LL | struct Bar(T); = note: using type defaults and const parameters in the same parameter list is currently not permitted error[E0128]: generic parameters with a default cannot use forward declared identifiers - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:21 | LL | struct Bar(T); | ^ defaulted generic parameters cannot be forward declared diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr index 44393a30266d6..4c97012f36185 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -1,5 +1,5 @@ error: generic parameters with a default must be trailing - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:12 | LL | struct Bar(T); | ^ @@ -16,7 +16,7 @@ LL | struct Foo()]>(T, U); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0128]: generic parameters with a default cannot use forward declared identifiers - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:21 | LL | struct Bar(T); | ^ defaulted generic parameters cannot be forward declared diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs index 8a84afd065c1e..bf4f9558adc26 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs @@ -7,7 +7,6 @@ struct Foo()]>(T, U); //[full]~^ ERROR the size for values of type `T` cannot be known at compilation time //[min]~^^ ERROR generic parameters may not be used in const operations -// FIXME(const_generics_defaults): We still don't know how to deal with type defaults. struct Bar(T); //~^ ERROR generic parameters with a default cannot use forward declared identifiers //~| ERROR generic parameters with a default From 312b4fdfd281a5ebd740acaf88cc82c47225be23 Mon Sep 17 00:00:00 2001 From: lcnr Date: Sun, 18 Apr 2021 15:14:17 +0200 Subject: [PATCH 24/32] improve wf check for const param defaults --- compiler/rustc_typeck/src/check/wfcheck.rs | 53 ++++++++++++++----- .../complex-generic-default-expr.min.stderr | 4 +- .../defaults/complex-generic-default-expr.rs | 8 ++- .../defaults/const-param-as-default-value.rs | 14 +++++ .../defaults/const-param-in-ty-defaults.rs | 18 +++++++ .../defaults/default-param-wf-concrete.rs | 5 ++ .../defaults/default-param-wf-concrete.stderr | 9 ++++ .../defaults/pretty-printing-ast.rs | 1 - 8 files changed, 94 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/const-generics/defaults/const-param-as-default-value.rs create mode 100644 src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs create mode 100644 src/test/ui/const-generics/defaults/default-param-wf-concrete.rs create mode 100644 src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 887cc42a1dd27..26871d6f0285c 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -728,20 +728,36 @@ fn check_where_clauses<'tcx, 'fcx>( // // Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold. for param in &generics.params { - if let GenericParamDefKind::Type { .. } = param.kind { - if is_our_default(¶m) { - let ty = fcx.tcx.type_of(param.def_id); - // Ignore dependent defaults -- that is, where the default of one type - // parameter includes another (e.g., ``). In those cases, we can't - // be sure if it will error or not as user might always specify the other. - if !ty.needs_subst() { + match param.kind { + GenericParamDefKind::Type { .. } => { + if is_our_default(¶m) { + let ty = fcx.tcx.type_of(param.def_id); + // Ignore dependent defaults -- that is, where the default of one type + // parameter includes another (e.g., ``). In those cases, we can't + // be sure if it will error or not as user might always specify the other. + if !ty.needs_subst() { + fcx.register_wf_obligation( + ty.into(), + fcx.tcx.def_span(param.def_id), + ObligationCauseCode::MiscObligation, + ); + } + } + } + GenericParamDefKind::Const { .. } => { + // FIXME(const_generics_defaults): Figure out if this + // is the behavior we want, see the comment further below. + if is_our_default(¶m) { + let default_ct = tcx.const_param_default(param.def_id); fcx.register_wf_obligation( - ty.into(), + default_ct.into(), fcx.tcx.def_span(param.def_id), ObligationCauseCode::MiscObligation, ); } } + // Doesn't have defaults. + GenericParamDefKind::Lifetime => {} } } @@ -774,14 +790,25 @@ fn check_where_clauses<'tcx, 'fcx>( fcx.tcx.mk_param_from_def(param) } GenericParamDefKind::Const { .. } => { + // FIXME(const_generics_defaults): I(@lcnr) feel like always + // using the const parameter is the right choice here, even + // if it needs substs. + // + // Before stabilizing this we probably want to get some tests + // where this makes a difference and figure out what's the exact + // behavior we want here. + + // If the param has a default, ... if is_our_default(param) { let default_ct = tcx.const_param_default(param.def_id); - // Const params currently have to be concrete. - assert!(!default_ct.needs_subst()); - default_ct.into() - } else { - fcx.tcx.mk_param_from_def(param) + // ... and it's not a dependent default, ... + if !default_ct.needs_subst() { + // ... then substitute it with the default. + return default_ct.into(); + } } + + fcx.tcx.mk_param_from_def(param) } } }); diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr index d50a0a61d4949..7d51e9aa0f3be 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/complex-generic-default-expr.rs:6:47 + --> $DIR/complex-generic-default-expr.rs:10:47 | LL | struct Foo; | ^ cannot perform const operation using `N` @@ -8,7 +8,7 @@ LL | struct Foo; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/complex-generic-default-expr.rs:9:62 + --> $DIR/complex-generic-default-expr.rs:13:62 | LL | struct Bar() }>(T); | ^ cannot perform const operation using `T` diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs index 1c25fda8d30ca..a1c04b5e7c387 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs @@ -1,4 +1,8 @@ -// revisions: full min +// revisions: min +// FIXME(const_generics): add the `full` revision, +// currently causes an ICE as we don't supply substs to +// anon consts in the parameter listing, as that would +// cause that anon const to reference itself. #![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] @@ -8,6 +12,6 @@ struct Foo; struct Bar() }>(T); //[min]~^ ERROR generic parameters may not be used in const operations -//[full]~^^ ERROR the size for values of type `T` cannot be known at compilation time +//[full]~^^ ERROR the size for values of type `T` cannot be known at compilation time fn main() {} diff --git a/src/test/ui/const-generics/defaults/const-param-as-default-value.rs b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs new file mode 100644 index 0000000000000..d9cab34327e9d --- /dev/null +++ b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] +struct Foo([u8; N], [u8; M]); + +fn foo() -> Foo { + let x = [0; N]; + Foo(x, x) +} + +fn main() { + let val = foo::<13>(); + assert_eq!(val.0, val.1); +} diff --git a/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs new file mode 100644 index 0000000000000..e3d78fe2ee0ea --- /dev/null +++ b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs @@ -0,0 +1,18 @@ +// run-pass +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] +// FIXME(const_generics_defaults): while we can allow this, +// we probably won't easily allow this with more complex const operations. +// +// So we have to make a conscious decision here when stabilizing a relaxed parameter ordering. +struct Foo(T); + +impl Foo { + fn new() -> Self { + Foo([0; N]) + } +} + +fn main() { + assert_eq!(Foo::new().0, [0; 10]); +} diff --git a/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs b/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs new file mode 100644 index 0000000000000..4bb56c6a1c08c --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs @@ -0,0 +1,5 @@ +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] +struct Foo; +//~^ ERROR evaluation of constant value failed +fn main() {} diff --git a/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr b/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr new file mode 100644 index 0000000000000..8464ea98bf695 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/default-param-wf-concrete.rs:3:28 + | +LL | struct Foo; + | ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs index 12a92a10476d5..7a57950dfc924 100644 --- a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs @@ -11,4 +11,3 @@ trait Foo {} fn foo() {} struct Range; - From d3e0d2f53dd69bf10b4260760e5fbaddc77c2a3d Mon Sep 17 00:00:00 2001 From: lcnr Date: Sun, 18 Apr 2021 16:43:43 +0200 Subject: [PATCH 25/32] supply substs to anon consts in defaults --- compiler/rustc_typeck/src/astconv/mod.rs | 4 +- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 4 +- compiler/rustc_typeck/src/collect.rs | 39 +++++++++---------- .../complex-generic-default-expr.full.stderr | 24 ++++++------ .../complex-generic-default-expr.min.stderr | 4 +- .../defaults/complex-generic-default-expr.rs | 13 +++---- .../defaults/const-param-as-default-value.rs | 9 +++++ .../defaults/const-param-in-ty-defaults.rs | 4 -- ...ms-in-ct-in-ty-param-lazy-norm.full.stderr | 22 ++--------- ...ams-in-ct-in-ty-param-lazy-norm.min.stderr | 6 +-- .../params-in-ct-in-ty-param-lazy-norm.rs | 4 +- 11 files changed, 62 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index b6de491911ab7..62a1584d16be0 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -513,7 +513,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { GenericParamDefKind::Const { has_default } => { let ty = tcx.at(self.span).type_of(param.def_id); if !infer_args && has_default { - tcx.const_param_default(param.def_id).into() + tcx.const_param_default(param.def_id) + .subst_spanned(tcx, substs.unwrap(), Some(self.span)) + .into() } else { if infer_args { self.astconv.ct_infer(ty, Some(param), self.span).into() diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 9ace455042103..a50f8e1c65599 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1446,7 +1446,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } GenericParamDefKind::Const { has_default, .. } => { if !infer_args && has_default { - tcx.const_param_default(param.def_id).into() + tcx.const_param_default(param.def_id) + .subst_spanned(tcx, substs.unwrap(), Some(self.span)) + .into() } else { self.fcx.var_for_def(self.span, param) } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 1477418d5d8cf..927d8c57191a7 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1316,13 +1316,13 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option Visitor<'v> for AnonConstInParamListDetector { +impl<'v> Visitor<'v> for AnonConstInParamTyDetector { type Map = intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -1330,15 +1330,17 @@ impl<'v> Visitor<'v> for AnonConstInParamListDetector { } fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) { - let prev = self.in_param_list; - self.in_param_list = true; - intravisit::walk_generic_param(self, p); - self.in_param_list = prev; + if let GenericParamKind::Const { ref ty, default: _ } = p.kind { + let prev = self.in_param_ty; + self.in_param_ty = true; + self.visit_ty(ty); + self.in_param_ty = prev; + } } fn visit_anon_const(&mut self, c: &'v hir::AnonConst) { - if self.in_param_list && self.ct == c.hir_id { - self.found_anon_const_in_list = true; + if self.in_param_ty && self.ct == c.hir_id { + self.found_anon_const_in_param_ty = true; } else { intravisit::walk_anon_const(self, c) } @@ -1366,27 +1368,24 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let parent_id = tcx.hir().get_parent_item(hir_id); let parent_def_id = tcx.hir().local_def_id(parent_id); - let mut in_param_list = false; + let mut in_param_ty = false; for (_parent, node) in tcx.hir().parent_iter(hir_id) { if let Some(generics) = node.generics() { - let mut visitor = AnonConstInParamListDetector { - in_param_list: false, - found_anon_const_in_list: false, + let mut visitor = AnonConstInParamTyDetector { + in_param_ty: false, + found_anon_const_in_param_ty: false, ct: hir_id, }; visitor.visit_generics(generics); - in_param_list = visitor.found_anon_const_in_list; + in_param_ty = visitor.found_anon_const_in_param_ty; break; } } - if in_param_list { + if in_param_ty { // We do not allow generic parameters in anon consts if we are inside - // of a param list. - // - // This affects both default type bindings, e.g. `struct()]>(T, U)`, - // and the types of const parameters, e.g. `struct V();`. + // of a const parameter type, e.g. `struct Foo` is not allowed. None } else if tcx.lazy_normalization() { // HACK(eddyb) this provides the correct generics when diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr index c1444abbd3f32..e0e2b6c69f280 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr @@ -1,16 +1,18 @@ -error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/complex-generic-default-expr.rs:9:62 +error: constant expression depends on a generic parameter + --> $DIR/complex-generic-default-expr.rs:6:34 + | +LL | struct Foo; + | ^ + | + = note: this may fail depending on what value the parameter takes + +error: constant expression depends on a generic parameter + --> $DIR/complex-generic-default-expr.rs:10:21 | LL | struct Bar() }>(T); - | - ^ doesn't have a size known at compile-time - | | - | this type parameter needs to be `std::marker::Sized` - | - ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL + | ^^^^^^^^^ | -LL | pub const fn size_of() -> usize { - | - required by this bound in `std::mem::size_of` + = note: this may fail depending on what value the parameter takes -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr index 7d51e9aa0f3be..58abd8db9f09f 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/complex-generic-default-expr.rs:10:47 + --> $DIR/complex-generic-default-expr.rs:6:47 | LL | struct Foo; | ^ cannot perform const operation using `N` @@ -8,7 +8,7 @@ LL | struct Foo; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/complex-generic-default-expr.rs:13:62 + --> $DIR/complex-generic-default-expr.rs:10:62 | LL | struct Bar() }>(T); | ^ cannot perform const operation using `T` diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs index a1c04b5e7c387..a7b712f7b4b86 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs @@ -1,17 +1,14 @@ -// revisions: min -// FIXME(const_generics): add the `full` revision, -// currently causes an ICE as we don't supply substs to -// anon consts in the parameter listing, as that would -// cause that anon const to reference itself. +// revisions: full min #![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] struct Foo; -//[min]~^ ERROR generic parameters may not be used in const operations +//[full]~^ ERROR constant expression depends on a generic parameter +//[min]~^^ ERROR generic parameters may not be used in const operations struct Bar() }>(T); -//[min]~^ ERROR generic parameters may not be used in const operations -//[full]~^^ ERROR the size for values of type `T` cannot be known at compilation time +//[full]~^ ERROR constant expression depends on a generic parameter +//[min]~^^ ERROR generic parameters may not be used in const operations fn main() {} diff --git a/src/test/ui/const-generics/defaults/const-param-as-default-value.rs b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs index d9cab34327e9d..59ac261f44fd5 100644 --- a/src/test/ui/const-generics/defaults/const-param-as-default-value.rs +++ b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs @@ -8,7 +8,16 @@ fn foo() -> Foo { Foo(x, x) } +// To check that we actually apply the correct substs for const param defaults. +fn concrete_foo() -> Foo<13> { + Foo(Default::default(), Default::default()) +} + + fn main() { let val = foo::<13>(); assert_eq!(val.0, val.1); + + let val = concrete_foo(); + assert_eq!(val.0, val.1); } diff --git a/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs index e3d78fe2ee0ea..3f534ca0308ba 100644 --- a/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs +++ b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs @@ -1,10 +1,6 @@ // run-pass #![feature(const_generics_defaults)] #![allow(incomplete_features)] -// FIXME(const_generics_defaults): while we can allow this, -// we probably won't easily allow this with more complex const operations. -// -// So we have to make a conscious decision here when stabilizing a relaxed parameter ordering. struct Foo(T); impl Foo { diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr index cf947a565c454..e8fd9e7769b79 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr @@ -1,5 +1,5 @@ error: generic parameters with a default must be trailing - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:12 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12 | LL | struct Bar(T); | ^ @@ -7,25 +7,11 @@ LL | struct Bar(T); = note: using type defaults and const parameters in the same parameter list is currently not permitted error[E0128]: generic parameters with a default cannot use forward declared identifiers - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:21 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21 | LL | struct Bar(T); | ^ defaulted generic parameters cannot be forward declared -error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44 - | -LL | struct Foo()]>(T, U); - | - ^ doesn't have a size known at compile-time - | | - | this type parameter needs to be `std::marker::Sized` - | - ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL - | -LL | pub const fn size_of() -> usize { - | - required by this bound in `std::mem::size_of` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0128, E0277. -For more information about an error, try `rustc --explain E0128`. +For more information about this error, try `rustc --explain E0128`. diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr index 4c97012f36185..5fa6423306c5a 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -1,5 +1,5 @@ error: generic parameters with a default must be trailing - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:12 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12 | LL | struct Bar(T); | ^ @@ -7,7 +7,7 @@ LL | struct Bar(T); = note: using type defaults and const parameters in the same parameter list is currently not permitted error: generic parameters may not be used in const operations - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:5:44 | LL | struct Foo()]>(T, U); | ^ cannot perform const operation using `T` @@ -16,7 +16,7 @@ LL | struct Foo()]>(T, U); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0128]: generic parameters with a default cannot use forward declared identifiers - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:21 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21 | LL | struct Bar(T); | ^ defaulted generic parameters cannot be forward declared diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs index bf4f9558adc26..76c1b84aef557 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs @@ -1,11 +1,9 @@ // revisions: full min - #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] struct Foo()]>(T, U); -//[full]~^ ERROR the size for values of type `T` cannot be known at compilation time -//[min]~^^ ERROR generic parameters may not be used in const operations +//[min]~^ ERROR generic parameters may not be used in const operations struct Bar(T); //~^ ERROR generic parameters with a default cannot use forward declared identifiers From de2a4601abf69d2eae9845eda20ee5ed7bb9f8af Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 19 Apr 2021 10:55:32 -0700 Subject: [PATCH 26/32] rustc: Use LLVM's new saturating float-to-int intrinsics This commit updates rustc, with an applicable LLVM version, to use LLVM's new `llvm.fpto{u,s}i.sat.*.*` intrinsics to implement saturating floating-point-to-int conversions. This results in a little bit tighter codegen for x86/x86_64, but the main purpose of this is to prepare for upcoming changes to the WebAssembly backend in LLVM where wasm's saturating float-to-int instructions will now be implemented with these intrinsics. This change allows simplifying a good deal of surrounding code, namely removing a lot of wasm-specific behavior. WebAssembly no longer has any special-casing of saturating arithmetic instructions and the need for `fptoint_may_trap` is gone and all handling code for that is now removed. This means that the only wasm-specific logic is in the `fpto{s,u}i` instructions which only get used for "out of bounds is undefined behavior". This does mean that for the WebAssembly target specifically the Rust compiler will no longer be 100% compatible with pre-LLVM 12 versions, but it seems like that's unlikely to be relied on by too many folks. Note that this change does immediately regress the codegen of saturating float-to-int casts on WebAssembly due to the specialization of the LLVM intrinsic not being present in our LLVM fork just yet. I'll be following up with an LLVM update to pull in those patches, but affects a few other SIMD things in flight for WebAssembly so I wanted to separate this change. Eventually the entire `cast_float_to_int` function can be removed when LLVM 12 is the minimum version, but that will require sinking the complexity of it into other backends such as Cranelfit. --- compiler/rustc_codegen_llvm/src/builder.rs | 93 +++------- compiler/rustc_codegen_llvm/src/context.rs | 30 +++- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 168 ++++-------------- .../rustc_codegen_ssa/src/traits/builder.rs | 1 - compiler/rustc_span/src/symbol.rs | 1 - 5 files changed, 86 insertions(+), 207 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index f823792fabe63..b67689ce523f2 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -2,6 +2,7 @@ use crate::common::Funclet; use crate::context::CodegenCx; use crate::llvm::{self, BasicBlock, False}; use crate::llvm::{AtomicOrdering, AtomicRmwBinOp, SynchronizationScope}; +use crate::llvm_util; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; @@ -16,7 +17,7 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::{sym, Span}; +use rustc_span::Span; use rustc_target::abi::{self, Align, Size}; use rustc_target::spec::{HasTargetSpec, Target}; use std::borrow::Cow; @@ -669,81 +670,47 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> { - // WebAssembly has saturating floating point to integer casts if the - // `nontrapping-fptoint` target feature is activated. We'll use those if - // they are available. - if self.sess().target.arch == "wasm32" - && self.sess().target_features.contains(&sym::nontrapping_dash_fptoint) - { + if llvm_util::get_version() >= (12, 0, 0) { let src_ty = self.cx.val_ty(val); let float_width = self.cx.float_width(src_ty); let int_width = self.cx.int_width(dest_ty); - let name = match (int_width, float_width) { - (32, 32) => Some("llvm.wasm.trunc.saturate.unsigned.i32.f32"), - (32, 64) => Some("llvm.wasm.trunc.saturate.unsigned.i32.f64"), - (64, 32) => Some("llvm.wasm.trunc.saturate.unsigned.i64.f32"), - (64, 64) => Some("llvm.wasm.trunc.saturate.unsigned.i64.f64"), - _ => None, - }; - if let Some(name) = name { - let intrinsic = self.get_intrinsic(name); - return Some(self.call(intrinsic, &[val], None)); - } + let name = format!("llvm.fptoui.sat.i{}.f{}", int_width, float_width); + let intrinsic = self.get_intrinsic(&name); + return Some(self.call(intrinsic, &[val], None)); } + None } fn fptosi_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> { - // WebAssembly has saturating floating point to integer casts if the - // `nontrapping-fptoint` target feature is activated. We'll use those if - // they are available. - if self.sess().target.arch == "wasm32" - && self.sess().target_features.contains(&sym::nontrapping_dash_fptoint) - { + if llvm_util::get_version() >= (12, 0, 0) { let src_ty = self.cx.val_ty(val); let float_width = self.cx.float_width(src_ty); let int_width = self.cx.int_width(dest_ty); - let name = match (int_width, float_width) { - (32, 32) => Some("llvm.wasm.trunc.saturate.signed.i32.f32"), - (32, 64) => Some("llvm.wasm.trunc.saturate.signed.i32.f64"), - (64, 32) => Some("llvm.wasm.trunc.saturate.signed.i64.f32"), - (64, 64) => Some("llvm.wasm.trunc.saturate.signed.i64.f64"), - _ => None, - }; - if let Some(name) = name { - let intrinsic = self.get_intrinsic(name); - return Some(self.call(intrinsic, &[val], None)); - } + let name = format!("llvm.fptosi.sat.i{}.f{}", int_width, float_width); + let intrinsic = self.get_intrinsic(&name); + return Some(self.call(intrinsic, &[val], None)); } - None - } - fn fptosui_may_trap(&self, val: &'ll Value, dest_ty: &'ll Type) -> bool { - // Most of the time we'll be generating the `fptosi` or `fptoui` - // instruction for floating-point-to-integer conversions. These - // instructions by definition in LLVM do not trap. For the WebAssembly - // target, however, we'll lower in some cases to intrinsic calls instead - // which may trap. If we detect that this is a situation where we'll be - // using the intrinsics then we report that the call map trap, which - // callers might need to handle. - if !self.wasm_and_missing_nontrapping_fptoint() { - return false; - } - let src_ty = self.cx.val_ty(val); - let float_width = self.cx.float_width(src_ty); - let int_width = self.cx.int_width(dest_ty); - matches!((int_width, float_width), (32, 32) | (32, 64) | (64, 32) | (64, 64)) + None } fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - // When we can, use the native wasm intrinsics which have tighter - // codegen. Note that this has a semantic difference in that the - // intrinsic can trap whereas `fptoui` never traps. That difference, - // however, is handled by `fptosui_may_trap` above. + // On WebAssembly the `fptoui` and `fptosi` instructions currently have + // poor codegen. The reason for this is that the corresponding wasm + // instructions, `i32.trunc_f32_s` for example, will trap when the float + // is out-of-bounds, infinity, or nan. This means that LLVM + // automatically inserts control flow around `fptoui` and `fptosi` + // because the LLVM instruction `fptoui` is defined as producing a + // poison value, not having UB on out-of-bounds values. // - // Note that we skip the wasm intrinsics for vector types where `fptoui` - // must be used instead. - if self.wasm_and_missing_nontrapping_fptoint() { + // This method, however, is only used with non-saturating casts that + // have UB on out-of-bounds values. This means that it's ok if we use + // the raw wasm instruction since out-of-bounds values can do whatever + // we like. To ensure that LLVM picks the right instruction we choose + // the raw wasm intrinsic functions which avoid LLVM inserting all the + // other control flow automatically. + if self.sess().target.arch == "wasm32" { let src_ty = self.cx.val_ty(val); if self.cx.type_kind(src_ty) != TypeKind::Vector { let float_width = self.cx.float_width(src_ty); @@ -765,7 +732,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - if self.wasm_and_missing_nontrapping_fptoint() { + // see `fptoui` above for why wasm is different here + if self.sess().target.arch == "wasm32" { let src_ty = self.cx.val_ty(val); if self.cx.type_kind(src_ty) != TypeKind::Vector { let float_width = self.cx.float_width(src_ty); @@ -1419,9 +1387,4 @@ impl Builder<'a, 'll, 'tcx> { llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint); } } - - fn wasm_and_missing_nontrapping_fptoint(&self) -> bool { - self.sess().target.arch == "wasm32" - && !self.sess().target_features.contains(&sym::nontrapping_dash_fptoint) - } } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 773c0c16328e7..f5c54b11c08e7 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -503,14 +503,6 @@ impl CodegenCx<'b, 'tcx> { let t_f32 = self.type_f32(); let t_f64 = self.type_f64(); - ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f32", fn(t_f32) -> t_i32); - ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f64", fn(t_f64) -> t_i32); - ifn!("llvm.wasm.trunc.saturate.unsigned.i64.f32", fn(t_f32) -> t_i64); - ifn!("llvm.wasm.trunc.saturate.unsigned.i64.f64", fn(t_f64) -> t_i64); - ifn!("llvm.wasm.trunc.saturate.signed.i32.f32", fn(t_f32) -> t_i32); - ifn!("llvm.wasm.trunc.saturate.signed.i32.f64", fn(t_f64) -> t_i32); - ifn!("llvm.wasm.trunc.saturate.signed.i64.f32", fn(t_f32) -> t_i64); - ifn!("llvm.wasm.trunc.saturate.signed.i64.f64", fn(t_f64) -> t_i64); ifn!("llvm.wasm.trunc.unsigned.i32.f32", fn(t_f32) -> t_i32); ifn!("llvm.wasm.trunc.unsigned.i32.f64", fn(t_f64) -> t_i32); ifn!("llvm.wasm.trunc.unsigned.i64.f32", fn(t_f32) -> t_i64); @@ -520,6 +512,28 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.wasm.trunc.signed.i64.f32", fn(t_f32) -> t_i64); ifn!("llvm.wasm.trunc.signed.i64.f64", fn(t_f64) -> t_i64); + ifn!("llvm.fptosi.sat.i8.f32", fn(t_f32) -> t_i8); + ifn!("llvm.fptosi.sat.i16.f32", fn(t_f32) -> t_i16); + ifn!("llvm.fptosi.sat.i32.f32", fn(t_f32) -> t_i32); + ifn!("llvm.fptosi.sat.i64.f32", fn(t_f32) -> t_i64); + ifn!("llvm.fptosi.sat.i128.f32", fn(t_f32) -> t_i128); + ifn!("llvm.fptosi.sat.i8.f64", fn(t_f64) -> t_i8); + ifn!("llvm.fptosi.sat.i16.f64", fn(t_f64) -> t_i16); + ifn!("llvm.fptosi.sat.i32.f64", fn(t_f64) -> t_i32); + ifn!("llvm.fptosi.sat.i64.f64", fn(t_f64) -> t_i64); + ifn!("llvm.fptosi.sat.i128.f64", fn(t_f64) -> t_i128); + + ifn!("llvm.fptoui.sat.i8.f32", fn(t_f32) -> t_i8); + ifn!("llvm.fptoui.sat.i16.f32", fn(t_f32) -> t_i16); + ifn!("llvm.fptoui.sat.i32.f32", fn(t_f32) -> t_i32); + ifn!("llvm.fptoui.sat.i64.f32", fn(t_f32) -> t_i64); + ifn!("llvm.fptoui.sat.i128.f32", fn(t_f32) -> t_i128); + ifn!("llvm.fptoui.sat.i8.f64", fn(t_f64) -> t_i8); + ifn!("llvm.fptoui.sat.i16.f64", fn(t_f64) -> t_i16); + ifn!("llvm.fptoui.sat.i32.f64", fn(t_f64) -> t_i32); + ifn!("llvm.fptoui.sat.i64.f64", fn(t_f64) -> t_i64); + ifn!("llvm.fptoui.sat.i128.f64", fn(t_f64) -> t_i128); + ifn!("llvm.trap", fn() -> void); ifn!("llvm.debugtrap", fn() -> void); ifn!("llvm.frameaddress", fn(t_i32) -> i8p); diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 629cb64d43ee1..9917c23f12150 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -11,7 +11,7 @@ use rustc_apfloat::{ieee, Float, Round, Status}; use rustc_hir::lang_items::LangItem; use rustc_middle::mir; use rustc_middle::ty::cast::{CastTy, IntTy}; -use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout}; +use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt}; use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_span::symbol::sym; @@ -385,10 +385,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.inttoptr(usize_llval, ll_t_out) } (CastTy::Float, CastTy::Int(IntTy::I)) => { - cast_float_to_int(&mut bx, true, llval, ll_t_in, ll_t_out, cast) + cast_float_to_int(&mut bx, true, llval, ll_t_in, ll_t_out) } (CastTy::Float, CastTy::Int(_)) => { - cast_float_to_int(&mut bx, false, llval, ll_t_in, ll_t_out, cast) + cast_float_to_int(&mut bx, false, llval, ll_t_in, ll_t_out) } _ => bug!("unsupported cast: {:?} to {:?}", operand.layout.ty, cast.ty), }; @@ -790,7 +790,6 @@ fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( x: Bx::Value, float_ty: Bx::Type, int_ty: Bx::Type, - int_layout: TyAndLayout<'tcx>, ) -> Bx::Value { if let Some(false) = bx.cx().sess().opts.debugging_opts.saturating_float_casts { return if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; @@ -891,134 +890,39 @@ fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let int_min = bx.cx().const_uint_big(int_ty, int_min(signed, int_width) as u128); let zero = bx.cx().const_uint(int_ty, 0); - // The codegen here differs quite a bit depending on whether our builder's - // `fptosi` and `fptoui` instructions may trap for out-of-bounds values. If - // they don't trap then we can start doing everything inline with a - // `select` instruction because it's ok to execute `fptosi` and `fptoui` - // even if we don't use the results. - if !bx.fptosui_may_trap(x, int_ty) { - // Step 1 ... - let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; - let less_or_nan = bx.fcmp(RealPredicate::RealULT, x, f_min); - let greater = bx.fcmp(RealPredicate::RealOGT, x, f_max); - - // Step 2: We use two comparisons and two selects, with %s1 being the - // result: - // %less_or_nan = fcmp ult %x, %f_min - // %greater = fcmp olt %x, %f_max - // %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result - // %s1 = select %greater, int_ty::MAX, %s0 - // Note that %less_or_nan uses an *unordered* comparison. This - // comparison is true if the operands are not comparable (i.e., if x is - // NaN). The unordered comparison ensures that s1 becomes int_ty::MIN if - // x is NaN. - // - // Performance note: Unordered comparison can be lowered to a "flipped" - // comparison and a negation, and the negation can be merged into the - // select. Therefore, it not necessarily any more expensive than a - // ordered ("normal") comparison. Whether these optimizations will be - // performed is ultimately up to the backend, but at least x86 does - // perform them. - let s0 = bx.select(less_or_nan, int_min, fptosui_result); - let s1 = bx.select(greater, int_max, s0); - - // Step 3: NaN replacement. - // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN. - // Therefore we only need to execute this step for signed integer types. - if signed { - // LLVM has no isNaN predicate, so we use (x == x) instead - let cmp = bx.fcmp(RealPredicate::RealOEQ, x, x); - bx.select(cmp, s1, zero) - } else { - s1 - } + // Step 1 ... + let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; + let less_or_nan = bx.fcmp(RealPredicate::RealULT, x, f_min); + let greater = bx.fcmp(RealPredicate::RealOGT, x, f_max); + + // Step 2: We use two comparisons and two selects, with %s1 being the + // result: + // %less_or_nan = fcmp ult %x, %f_min + // %greater = fcmp olt %x, %f_max + // %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result + // %s1 = select %greater, int_ty::MAX, %s0 + // Note that %less_or_nan uses an *unordered* comparison. This + // comparison is true if the operands are not comparable (i.e., if x is + // NaN). The unordered comparison ensures that s1 becomes int_ty::MIN if + // x is NaN. + // + // Performance note: Unordered comparison can be lowered to a "flipped" + // comparison and a negation, and the negation can be merged into the + // select. Therefore, it not necessarily any more expensive than a + // ordered ("normal") comparison. Whether these optimizations will be + // performed is ultimately up to the backend, but at least x86 does + // perform them. + let s0 = bx.select(less_or_nan, int_min, fptosui_result); + let s1 = bx.select(greater, int_max, s0); + + // Step 3: NaN replacement. + // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN. + // Therefore we only need to execute this step for signed integer types. + if signed { + // LLVM has no isNaN predicate, so we use (x == x) instead + let cmp = bx.fcmp(RealPredicate::RealOEQ, x, x); + bx.select(cmp, s1, zero) } else { - // In this case we cannot execute `fptosi` or `fptoui` and then later - // discard the result. The builder is telling us that these instructions - // will trap on out-of-bounds values, so we need to use basic blocks and - // control flow to avoid executing the `fptosi` and `fptoui` - // instructions. - // - // The general idea of what we're constructing here is, for f64 -> i32: - // - // ;; block so far... %0 is the argument - // %result = alloca i32, align 4 - // %inbound_lower = fcmp oge double %0, 0xC1E0000000000000 - // %inbound_upper = fcmp ole double %0, 0x41DFFFFFFFC00000 - // ;; match (inbound_lower, inbound_upper) { - // ;; (true, true) => %0 can be converted without trapping - // ;; (false, false) => %0 is a NaN - // ;; (true, false) => %0 is too large - // ;; (false, true) => %0 is too small - // ;; } - // ;; - // ;; The (true, true) check, go to %convert if so. - // %inbounds = and i1 %inbound_lower, %inbound_upper - // br i1 %inbounds, label %convert, label %specialcase - // - // convert: - // %cvt = call i32 @llvm.wasm.trunc.signed.i32.f64(double %0) - // store i32 %cvt, i32* %result, align 4 - // br label %done - // - // specialcase: - // ;; Handle the cases where the number is NaN, too large or too small - // - // ;; Either (true, false) or (false, true) - // %is_not_nan = or i1 %inbound_lower, %inbound_upper - // ;; Figure out which saturated value we are interested in if not `NaN` - // %saturated = select i1 %inbound_lower, i32 2147483647, i32 -2147483648 - // ;; Figure out between saturated and NaN representations - // %result_nan = select i1 %is_not_nan, i32 %saturated, i32 0 - // store i32 %result_nan, i32* %result, align 4 - // br label %done - // - // done: - // %r = load i32, i32* %result, align 4 - // ;; ... - let done = bx.build_sibling_block("float_cast_done"); - let mut convert = bx.build_sibling_block("float_cast_convert"); - let mut specialcase = bx.build_sibling_block("float_cast_specialcase"); - - let result = PlaceRef::alloca(bx, int_layout); - result.storage_live(bx); - - // Use control flow to figure out whether we can execute `fptosi` in a - // basic block, or whether we go to a different basic block to implement - // the saturating logic. - let inbound_lower = bx.fcmp(RealPredicate::RealOGE, x, f_min); - let inbound_upper = bx.fcmp(RealPredicate::RealOLE, x, f_max); - let inbounds = bx.and(inbound_lower, inbound_upper); - bx.cond_br(inbounds, convert.llbb(), specialcase.llbb()); - - // Translation of the `convert` basic block - let cvt = if signed { convert.fptosi(x, int_ty) } else { convert.fptoui(x, int_ty) }; - convert.store(cvt, result.llval, result.align); - convert.br(done.llbb()); - - // Translation of the `specialcase` basic block. Note that like above - // we try to be a bit clever here for unsigned conversions. In those - // cases the `int_min` is zero so we don't need two select instructions, - // just one to choose whether we need `int_max` or not. If - // `inbound_lower` is true then we're guaranteed to not be `NaN` and - // since we're greater than zero we must be saturating to `int_max`. If - // `inbound_lower` is false then we're either NaN or less than zero, so - // we saturate to zero. - let result_nan = if signed { - let is_not_nan = specialcase.or(inbound_lower, inbound_upper); - let saturated = specialcase.select(inbound_lower, int_max, int_min); - specialcase.select(is_not_nan, saturated, zero) - } else { - specialcase.select(inbound_lower, int_max, int_min) - }; - specialcase.store(result_nan, result.llval, result.align); - specialcase.br(done.llbb()); - - // Translation of the `done` basic block, positioning ourselves to - // continue from that point as well. - *bx = done; - let ret = bx.load(result.llval, result.align); - result.storage_dead(bx); - ret + s1 } } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index d5bd2780388e6..1bc05f30e5c37 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -171,7 +171,6 @@ pub trait BuilderMethods<'a, 'tcx>: fn sext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn fptoui_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Option; fn fptosi_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Option; - fn fptosui_may_trap(&self, val: Self::Value, dest_ty: Self::Type) -> bool; fn fptoui(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn fptosi(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn uitofp(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 52270f0e6277b..1d1471fdeca04 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -796,7 +796,6 @@ symbols! { non_modrs_mods, none_error, nontemporal_store, - nontrapping_dash_fptoint: "nontrapping-fptoint", noop_method_borrow, noop_method_clone, noop_method_deref, From e34f7e665f1cce1a4d4d473b13f57ef3200b21ad Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Wed, 21 Apr 2021 15:22:46 +0100 Subject: [PATCH 27/32] Update LLVM submodule Fixes #83467 --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index ea6bb2615f04d..0ed6038a318e3 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit ea6bb2615f04d53db11b6a43a14be5c9d1eaebe1 +Subproject commit 0ed6038a318e34e3d76a9e55bdebc4cfd17f902a From b78c0d8a4d5af91a4a55d029293e3ecb879ec142 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Wed, 21 Apr 2021 11:49:59 -0400 Subject: [PATCH 28/32] Review comments --- .../rustc_ast_passes/src/ast_validation.rs | 54 +++++++++---------- compiler/rustc_resolve/src/late/lifetimes.rs | 15 +++--- 2 files changed, 33 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 809660379f326..8a3f76415968e 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -81,13 +81,6 @@ struct AstValidator<'a> { is_assoc_ty_bound_banned: bool, lint_buffer: &'a mut LintBuffer, - - /// This is slightly complicated. Our representation for poly-trait-refs contains a single - /// binder and thus we only allow a single level of quantification. However, - /// the syntax of Rust permits quantification in two places in where clauses, - /// e.g., `T: for <'a> Foo<'a>` and `for <'a, 'b> &'b T: Foo<'a>`. If both are - /// defined, then error. - trait_ref_hack: bool, } impl<'a> AstValidator<'a> { @@ -1227,17 +1220,33 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // A type binding, eg `for<'c> Foo: Send+Clone+'c` self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params); - self.visit_ty(&bound_pred.bounded_ty); - - self.trait_ref_hack = !bound_pred.bound_generic_params.is_empty(); - walk_list!(self, visit_param_bound, &bound_pred.bounds); - walk_list!(self, visit_generic_param, &bound_pred.bound_generic_params); - self.trait_ref_hack = false; - } - _ => { - self.visit_where_predicate(predicate); + // This is slightly complicated. Our representation for poly-trait-refs contains a single + // binder and thus we only allow a single level of quantification. However, + // the syntax of Rust permits quantification in two places in where clauses, + // e.g., `T: for <'a> Foo<'a>` and `for <'a, 'b> &'b T: Foo<'a>`. If both are + // defined, then error. + if !bound_pred.bound_generic_params.is_empty() { + for bound in &bound_pred.bounds { + match bound { + GenericBound::Trait(t, _) => { + if !t.bound_generic_params.is_empty() { + struct_span_err!( + self.err_handler(), + t.span, + E0316, + "nested quantification of lifetimes" + ) + .emit(); + } + } + GenericBound::Outlives(_) => {} + } + } + } } + _ => {} } + self.visit_where_predicate(predicate); } } @@ -1289,19 +1298,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) { self.check_late_bound_lifetime_defs(&t.bound_generic_params); - if self.trait_ref_hack && !t.bound_generic_params.is_empty() { - struct_span_err!( - self.err_handler(), - t.span, - E0316, - "nested quantification of lifetimes" - ) - .emit(); - } - let trait_ref_hack = self.trait_ref_hack; - self.trait_ref_hack = false; visit::walk_poly_trait_ref(self, t, m); - self.trait_ref_hack = trait_ref_hack; } fn visit_variant_data(&mut self, s: &'a VariantData) { @@ -1520,7 +1517,6 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> is_impl_trait_banned: false, is_assoc_ty_bound_banned: false, lint_buffer: lints, - trait_ref_hack: false, }; visit::walk_crate(&mut validator, krate); diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 3cccbb06bc426..dfb6167c20cac 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1323,14 +1323,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // of "if there isn't a Binder scope above us, add one", but I // imagine there's a better way to go about this. let mut scope = self.scope; - let trait_ref_hack = loop { + let (binders, scope_type) = loop { match scope { Scope::TraitRefBoundary { .. } | Scope::Body { .. } | Scope::Root => { - break false; + break (vec![], BinderScopeType::PolyTraitRef); } - Scope::Binder { .. } => { - break true; + Scope::Binder { hir_id, .. } => { + let binders = self.map.late_bound_vars.entry(*hir_id).or_default().clone(); + break (binders, BinderScopeType::Concatenating); } Scope::Elision { s, .. } @@ -1341,8 +1342,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } }; match bound { - hir::GenericBound::LangItemTrait(_, _, hir_id, _) if !trait_ref_hack => { - self.map.late_bound_vars.insert(*hir_id, vec![]); + hir::GenericBound::LangItemTrait(_, _, hir_id, _) => { + self.map.late_bound_vars.insert(*hir_id, binders); let scope = Scope::Binder { hir_id: *hir_id, lifetimes: FxHashMap::default(), @@ -1350,7 +1351,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index: self.next_early_index(), track_lifetime_uses: true, opaque_type_parent: false, - scope_type: BinderScopeType::Other, + scope_type, }; self.with(scope, |_, this| { intravisit::walk_param_bound(this, bound); From eb9b0f6ab7886bf89b1cc00dbc5248bfd62ea21d Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Wed, 21 Apr 2021 13:24:24 +0200 Subject: [PATCH 29/32] Move `sys_common::rwlock::StaticRWLock` etc. to `sys::unix::rwlock` --- library/std/src/sys/unix/os.rs | 2 +- library/std/src/sys/unix/rwlock.rs | 52 ++++++++++++++++++++++++ library/std/src/sys_common/rwlock.rs | 59 ---------------------------- 3 files changed, 53 insertions(+), 60 deletions(-) diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 98e578c5255c7..2b2211feaf1c8 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -21,8 +21,8 @@ use crate::slice; use crate::str; use crate::sys::cvt; use crate::sys::fd; +use crate::sys::rwlock::{RWLockReadGuard, StaticRWLock}; use crate::sys_common::mutex::{StaticMutex, StaticMutexGuard}; -use crate::sys_common::rwlock::{RWLockReadGuard, StaticRWLock}; use crate::vec; use libc::{c_char, c_int, c_void}; diff --git a/library/std/src/sys/unix/rwlock.rs b/library/std/src/sys/unix/rwlock.rs index 2b5067a34f648..d97d9d712fc93 100644 --- a/library/std/src/sys/unix/rwlock.rs +++ b/library/std/src/sys/unix/rwlock.rs @@ -139,3 +139,55 @@ impl RWLock { } } } + +pub struct StaticRWLock(RWLock); + +impl StaticRWLock { + pub const fn new() -> StaticRWLock { + StaticRWLock(RWLock::new()) + } + + /// Acquires shared access to the underlying lock, blocking the current + /// thread to do so. + /// + /// The lock is automatically unlocked when the returned guard is dropped. + #[inline] + pub fn read_with_guard(&'static self) -> RWLockReadGuard { + // SAFETY: All methods require static references, therefore self + // cannot be moved between invocations. + unsafe { + self.0.read(); + } + RWLockReadGuard(&self.0) + } + + /// Acquires write access to the underlying lock, blocking the current thread + /// to do so. + /// + /// The lock is automatically unlocked when the returned guard is dropped. + #[inline] + pub fn write_with_guard(&'static self) -> RWLockWriteGuard { + // SAFETY: All methods require static references, therefore self + // cannot be moved between invocations. + unsafe { + self.0.write(); + } + RWLockWriteGuard(&self.0) + } +} + +pub struct RWLockReadGuard(&'static RWLock); + +impl Drop for RWLockReadGuard { + fn drop(&mut self) { + unsafe { self.0.read_unlock() } + } +} + +pub struct RWLockWriteGuard(&'static RWLock); + +impl Drop for RWLockWriteGuard { + fn drop(&mut self) { + unsafe { self.0.write_unlock() } + } +} diff --git a/library/std/src/sys_common/rwlock.rs b/library/std/src/sys_common/rwlock.rs index 70b31b19f824c..3705d641a1be6 100644 --- a/library/std/src/sys_common/rwlock.rs +++ b/library/std/src/sys_common/rwlock.rs @@ -86,62 +86,3 @@ impl RWLock { self.0.destroy() } } - -// the cfg annotations only exist due to dead code warnings. the code itself is portable -#[cfg(unix)] -pub struct StaticRWLock(RWLock); - -#[cfg(unix)] -impl StaticRWLock { - pub const fn new() -> StaticRWLock { - StaticRWLock(RWLock::new()) - } - - /// Acquires shared access to the underlying lock, blocking the current - /// thread to do so. - /// - /// The lock is automatically unlocked when the returned guard is dropped. - #[inline] - pub fn read_with_guard(&'static self) -> RWLockReadGuard { - // SAFETY: All methods require static references, therefore self - // cannot be moved between invocations. - unsafe { - self.0.read(); - } - RWLockReadGuard(&self.0) - } - - /// Acquires write access to the underlying lock, blocking the current thread - /// to do so. - /// - /// The lock is automatically unlocked when the returned guard is dropped. - #[inline] - pub fn write_with_guard(&'static self) -> RWLockWriteGuard { - // SAFETY: All methods require static references, therefore self - // cannot be moved between invocations. - unsafe { - self.0.write(); - } - RWLockWriteGuard(&self.0) - } -} - -#[cfg(unix)] -pub struct RWLockReadGuard(&'static RWLock); - -#[cfg(unix)] -impl Drop for RWLockReadGuard { - fn drop(&mut self) { - unsafe { self.0.read_unlock() } - } -} - -#[cfg(unix)] -pub struct RWLockWriteGuard(&'static RWLock); - -#[cfg(unix)] -impl Drop for RWLockWriteGuard { - fn drop(&mut self) { - unsafe { self.0.write_unlock() } - } -} From c78724f869add98e0f2af8950f760a37ec35243b Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Wed, 21 Apr 2021 12:26:19 -0400 Subject: [PATCH 30/32] More review changes --- compiler/rustc_resolve/src/late/lifetimes.rs | 144 ++++++++----------- 1 file changed, 59 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index dfb6167c20cac..174df09cbdbb2 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -274,10 +274,8 @@ enum Scope<'a> { #[derive(Copy, Clone, Debug)] enum BinderScopeType { - /// In a syntactic trait ref, this represents the outermost binder. So, if - /// you had `T: for<'a> Foo Baz<'a, 'b>>`, then the `for<'a>` - /// scope uses `PolyTraitRef`. - PolyTraitRef, + /// Any non-concatenating binder scopes. + Normal, /// Within a syntactic trait ref, there may be multiple poly trait refs that /// are nested (under the `associcated_type_bounds` feature). The binders of /// the innner poly trait refs are extended from the outer poly trait refs @@ -288,10 +286,6 @@ enum BinderScopeType { /// out any lifetimes because they aren't needed to show the two scopes). /// The inner `for<>` has a scope of `Concatenating`. Concatenating, - /// Any other binder scopes. These are "normal" in that they increase the binder - /// depth, are fully syntactic, don't concatenate, and don't have special syntactical - /// considerations. - Other, } // A helper struct for debugging scopes without printing parent scopes @@ -573,6 +567,43 @@ fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty:: } } +impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { + /// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref. + fn poly_trait_ref_binder_info(&mut self) -> (Vec, BinderScopeType) { + let mut scope = self.scope; + let mut supertrait_lifetimes = vec![]; + loop { + match scope { + Scope::Body { .. } | Scope::Root => { + break (vec![], BinderScopeType::Normal); + } + + Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => { + scope = s; + } + + Scope::Supertrait { s, lifetimes } => { + supertrait_lifetimes = lifetimes.clone(); + scope = s; + } + + Scope::TraitRefBoundary { .. } => { + // We should only see super trait lifetimes if there is a `Binder` above + assert!(supertrait_lifetimes.is_empty()); + break (vec![], BinderScopeType::Normal); + } + + Scope::Binder { hir_id, .. } => { + // Nested poly trait refs have the binders concatenated + let mut full_binders = + self.map.late_bound_vars.entry(*hir_id).or_default().clone(); + full_binders.extend(supertrait_lifetimes.into_iter()); + break (full_binders, BinderScopeType::Concatenating); + } + } + } + } +} impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { type Map = Map<'tcx>; @@ -630,7 +661,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: false, - scope_type: BinderScopeType::Other, + scope_type: BinderScopeType::Normal, }; self.with(scope, move |_old_scope, this| { intravisit::walk_fn(this, fk, fd, b, s, hir_id) @@ -755,7 +786,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index: index + non_lifetime_count, opaque_type_parent: true, track_lifetime_uses, - scope_type: BinderScopeType::Other, + scope_type: BinderScopeType::Normal, s: ROOT_SCOPE, }; self.with(scope, |old_scope, this| { @@ -827,7 +858,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index, track_lifetime_uses: true, opaque_type_parent: false, - scope_type: BinderScopeType::Other, + scope_type: BinderScopeType::Normal, }; self.with(scope, |old_scope, this| { // a bare fn has no bounds, so everything @@ -1023,7 +1054,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: this.scope, track_lifetime_uses: true, opaque_type_parent: false, - scope_type: BinderScopeType::Other, + scope_type: BinderScopeType::Normal, }; this.with(scope, |_old_scope, this| { this.visit_generics(generics); @@ -1043,7 +1074,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: false, - scope_type: BinderScopeType::Other, + scope_type: BinderScopeType::Normal, }; self.with(scope, |_old_scope, this| { let scope = Scope::TraitRefBoundary { s: this.scope }; @@ -1102,7 +1133,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, - scope_type: BinderScopeType::Other, + scope_type: BinderScopeType::Normal, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -1171,7 +1202,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, - scope_type: BinderScopeType::Other, + scope_type: BinderScopeType::Normal, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -1287,7 +1318,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index, track_lifetime_uses: true, opaque_type_parent: false, - scope_type: BinderScopeType::PolyTraitRef, + scope_type: BinderScopeType::Normal, }; this.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &bound_generic_params); @@ -1317,32 +1348,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) { - // FIXME(jackh726): This is pretty weird. `LangItemTrait` doesn't go - // through the regular poly trait ref code, so we don't get another - // chance to introduce a binder. For now, I'm keeping the existing logic - // of "if there isn't a Binder scope above us, add one", but I - // imagine there's a better way to go about this. - let mut scope = self.scope; - let (binders, scope_type) = loop { - match scope { - Scope::TraitRefBoundary { .. } | Scope::Body { .. } | Scope::Root => { - break (vec![], BinderScopeType::PolyTraitRef); - } - - Scope::Binder { hir_id, .. } => { - let binders = self.map.late_bound_vars.entry(*hir_id).or_default().clone(); - break (binders, BinderScopeType::Concatenating); - } - - Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } - | Scope::Supertrait { s, .. } => { - scope = s; - } - } - }; match bound { hir::GenericBound::LangItemTrait(_, _, hir_id, _) => { + // FIXME(jackh726): This is pretty weird. `LangItemTrait` doesn't go + // through the regular poly trait ref code, so we don't get another + // chance to introduce a binder. For now, I'm keeping the existing logic + // of "if there isn't a Binder scope above us, add one", but I + // imagine there's a better way to go about this. + let (binders, scope_type) = self.poly_trait_ref_binder_info(); + self.map.late_bound_vars.insert(*hir_id, binders); let scope = Scope::Binder { hir_id: *hir_id, @@ -1371,44 +1385,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let should_pop_missing_lt = self.is_trait_ref_fn_scope(trait_ref); let next_early_index = self.next_early_index(); - let mut scope = self.scope; - let mut supertrait_lifetimes = vec![]; - let (mut binders, scope_type) = loop { - match scope { - Scope::Body { .. } | Scope::Root => { - break (vec![], BinderScopeType::PolyTraitRef); - } - - Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => { - scope = s; - } - - Scope::Supertrait { s, lifetimes } => { - supertrait_lifetimes = lifetimes.clone(); - scope = s; - } - - Scope::TraitRefBoundary { .. } => { - // We should only see super trait lifetimes if there is a `Binder` above - assert!(supertrait_lifetimes.is_empty()); - break (vec![], BinderScopeType::PolyTraitRef); - } - - Scope::Binder { hir_id, scope_type, .. } => { - if let BinderScopeType::Other = scope_type { - bug!( - "Expected all syntacic poly trait refs to be surrounded by a `TraitRefBoundary`" - ) - } - - // Nested poly trait refs have the binders concatenated - let mut full_binders = - self.map.late_bound_vars.entry(*hir_id).or_default().clone(); - full_binders.extend(supertrait_lifetimes.into_iter()); - break (full_binders, BinderScopeType::Concatenating); - } - } - }; + let (mut binders, scope_type) = self.poly_trait_ref_binder_info(); let initial_bound_vars = binders.len() as u32; let mut lifetimes: FxHashMap = FxHashMap::default(); @@ -2185,7 +2162,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { s: self.scope, opaque_type_parent: true, track_lifetime_uses: false, - scope_type: BinderScopeType::Other, + scope_type: BinderScopeType::Normal, }; self.with(scope, move |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -2270,8 +2247,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { _ => bug!("expected LifetimeName::Param"), } match scope_type { - BinderScopeType::Other => late_depth += 1, - BinderScopeType::PolyTraitRef => late_depth += 1, + BinderScopeType::Normal => late_depth += 1, BinderScopeType::Concatenating => {} } scope = s; @@ -3001,8 +2977,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } match scope_type { - BinderScopeType::Other => late_depth += 1, - BinderScopeType::PolyTraitRef => late_depth += 1, + BinderScopeType::Normal => late_depth += 1, BinderScopeType::Concatenating => {} } scope = s; @@ -3165,8 +3140,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { match *scope { Scope::Binder { s, scope_type, .. } => { match scope_type { - BinderScopeType::Other => late_depth += 1, - BinderScopeType::PolyTraitRef => late_depth += 1, + BinderScopeType::Normal => late_depth += 1, BinderScopeType::Concatenating => {} } scope = s; From bb91805acefa32c2aedb769b1afe1f154b8e5dca Mon Sep 17 00:00:00 2001 From: Tor Hovland Date: Wed, 21 Apr 2021 21:33:48 +0200 Subject: [PATCH 31/32] Replaced flex gap with margin, for compatibility with older browsers. --- src/librustdoc/html/static/rustdoc.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 415bb608911e5..213ca9ec9e3ea 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -117,7 +117,6 @@ h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) { } h1.fqn { display: flex; - gap: 8px; width: 100%; border-bottom: 1px dashed; margin-top: 0; @@ -465,6 +464,7 @@ h1.fqn > .out-of-band { float: unset; flex: 1; text-align: right; + margin-left: 8px; } h3.impl > .out-of-band { From 6763a40eff7221fc23f22cdac453e2843344a357 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 21 Apr 2021 22:40:19 +0200 Subject: [PATCH 32/32] Bump slice_index_with_ops_bound_pair to 1.53.0 --- library/core/src/slice/index.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 1ef040484c344..f722430354991 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -81,7 +81,7 @@ mod private_slice_index { impl Sealed for ops::RangeInclusive {} #[stable(feature = "slice_get_slice", since = "1.28.0")] impl Sealed for ops::RangeToInclusive {} - #[stable(feature = "slice_index_with_ops_bound_pair", since = "1.51.0")] + #[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")] impl Sealed for (ops::Bound, ops::Bound) {} } @@ -622,7 +622,7 @@ fn into_slice_range( start..end } -#[stable(feature = "slice_index_with_ops_bound_pair", since = "1.51.0")] +#[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")] unsafe impl SliceIndex<[T]> for (ops::Bound, ops::Bound) { type Output = [T];