From 5461fd4250c5e535ae653bd6f0f8392dede5b484 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 10 Feb 2024 23:49:16 +0000 Subject: [PATCH 01/18] Gracefully handle non-WF alias in assemble_alias_bound_candidates_recur --- .../src/solve/assembly/mod.rs | 8 ++++++-- .../in-trait/alias-bounds-when-not-wf.rs | 19 +++++++++++++++++++ .../in-trait/alias-bounds-when-not-wf.stderr | 17 +++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs create mode 100644 tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 81c0cfea85a77..6833d2ae330ce 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{fast_reject, TypeFoldable}; use rustc_middle::ty::{ToPredicate, TypeVisitableExt}; -use rustc_span::ErrorGuaranteed; +use rustc_span::{ErrorGuaranteed, DUMMY_SP}; use std::fmt::Debug; pub(super) mod structural_traits; @@ -612,7 +612,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) => (kind, alias_ty), ty::Alias(ty::Inherent | ty::Weak, _) => { - unreachable!("Weak and Inherent aliases should have been normalized away already") + self.tcx().sess.dcx().span_delayed_bug( + DUMMY_SP, + format!("could not normalize {self_ty}, it is not WF"), + ); + return; } }; diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs new file mode 100644 index 0000000000000..229a918cdd2e6 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs @@ -0,0 +1,19 @@ +// compile-flags: -Znext-solver + +#![feature(lazy_type_alias)] +//~^ WARN the feature `lazy_type_alias` is incomplete + +trait Foo {} + +type A = T; + +struct W(T); + +// For `W>` to be WF, `A: Sized` must hold. However, when assembling +// alias bounds for `A`, we try to normalize it, but it doesn't hold because +// `usize: Foo` doesn't hold. Therefore we ICE, because we don't expect to still +// encounter weak types in `assemble_alias_bound_candidates_recur`. +fn hello(_: W>) {} +//~^ ERROR the type `W>` is not well-formed + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr new file mode 100644 index 0000000000000..5df27ac3bc6a3 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr @@ -0,0 +1,17 @@ +warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/alias-bounds-when-not-wf.rs:3:12 + | +LL | #![feature(lazy_type_alias)] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #112792 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: the type `W>` is not well-formed + --> $DIR/alias-bounds-when-not-wf.rs:16:13 + | +LL | fn hello(_: W>) {} + | ^^^^^^^^^^^ + +error: aborting due to 1 previous error; 1 warning emitted + From 1fa75af1737e9bb08d8d9e4b919a93370364ebc5 Mon Sep 17 00:00:00 2001 From: Caio Date: Sun, 11 Feb 2024 08:02:32 -0300 Subject: [PATCH 02/18] Add test --- tests/ui/typeck/issue-116864.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/ui/typeck/issue-116864.rs diff --git a/tests/ui/typeck/issue-116864.rs b/tests/ui/typeck/issue-116864.rs new file mode 100644 index 0000000000000..88c3f7866082a --- /dev/null +++ b/tests/ui/typeck/issue-116864.rs @@ -0,0 +1,31 @@ +// compile-flags: -Znext-solver +// check-pass +// edition: 2021 + +use std::future::Future; + +trait Baz { + type Param; +} + +trait FnMutFut: FnMut(P) -> Self::Future { + type Future: Future; +} + +impl FnMutFut for F +where + F: FnMut(P) -> FUT, + FUT: Future, +{ + type Future = FUT; +} + +async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) +where + BAZ: Baz, +{ + cb(&1i32).await; +} + +fn main() { +} From 89abbb0b4048cc45cb39aafd759a9625bb843dd8 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sun, 11 Feb 2024 09:12:35 -0300 Subject: [PATCH 03/18] Add ChrisDenton to review queue --- triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index ef3f3693e6174..ed2ea7798fd1c 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -811,7 +811,7 @@ project-stable-mir = [ "/library/panic_abort" = ["libs"] "/library/panic_unwind" = ["libs"] "/library/proc_macro" = ["@petrochenkov"] -"/library/std" = ["libs"] +"/library/std" = ["libs", "@ChrisDenton"] "/library/std/src/sys/pal/windows" = ["@ChrisDenton"] "/library/stdarch" = ["libs"] "/library/test" = ["libs"] From d5de9a610556642da338e62c53f04ce4cc7f02b6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 11 Feb 2024 14:46:20 +0100 Subject: [PATCH 04/18] check_consts: fix some duplicate errors by not calling check_static unnecessarily --- .../src/transform/check_consts/check.rs | 8 +++-- .../ui/consts/issue-17718-const-bad-values.rs | 1 - .../issue-17718-const-bad-values.stderr | 15 +------- .../const_refers_to_static.32bit.stderr | 5 --- .../const_refers_to_static.64bit.stderr | 5 --- ..._refers_to_static_cross_crate.32bit.stderr | 35 ------------------- ..._refers_to_static_cross_crate.64bit.stderr | 35 ------------------- .../mutable_references_err.32bit.stderr | 15 -------- .../mutable_references_err.64bit.stderr | 15 -------- .../feature-gate-const-refs-to-static.rs | 1 - .../feature-gate-const-refs-to-static.stderr | 15 +------- tests/ui/thread-local/thread-local-static.rs | 1 - .../thread-local/thread-local-static.stderr | 14 +------- 13 files changed, 8 insertions(+), 157 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 28dc69859fd77..43048dc41d3c2 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -619,9 +619,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { if base_ty.is_unsafe_ptr() { if place_ref.projection.is_empty() { let decl = &self.body.local_decls[place_ref.local]; - if let LocalInfo::StaticRef { def_id, .. } = *decl.local_info() { - let span = decl.source_info.span; - self.check_static(def_id, span); + // If this is a static, then this is not really dereferencing a pointer, + // just directly accessing a static. That is not subject to any feature + // gates (except for the one about whether statics can even be used, but + // that is checked already by `visit_operand`). + if let LocalInfo::StaticRef { .. } = *decl.local_info() { return; } } diff --git a/tests/ui/consts/issue-17718-const-bad-values.rs b/tests/ui/consts/issue-17718-const-bad-values.rs index af50fed972df8..2b593a192ee9f 100644 --- a/tests/ui/consts/issue-17718-const-bad-values.rs +++ b/tests/ui/consts/issue-17718-const-bad-values.rs @@ -4,7 +4,6 @@ const C1: &'static mut [usize] = &mut []; static mut S: usize = 3; const C2: &'static mut usize = unsafe { &mut S }; //~^ ERROR: referencing statics in constants -//~| ERROR: referencing statics in constants //~| WARN mutable reference of mutable static is discouraged [static_mut_ref] fn main() {} diff --git a/tests/ui/consts/issue-17718-const-bad-values.stderr b/tests/ui/consts/issue-17718-const-bad-values.stderr index cda94490155c0..92bab1ab53ef4 100644 --- a/tests/ui/consts/issue-17718-const-bad-values.stderr +++ b/tests/ui/consts/issue-17718-const-bad-values.stderr @@ -31,20 +31,7 @@ LL | const C2: &'static mut usize = unsafe { &mut S }; = note: `static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable. = help: to fix this, the value can be extracted to a `const` and then used. -error[E0658]: referencing statics in constants is unstable - --> $DIR/issue-17718-const-bad-values.rs:5:46 - | -LL | const C2: &'static mut usize = unsafe { &mut S }; - | ^ - | - = note: see issue #119618 for more information - = help: add `#![feature(const_refs_to_static)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = note: `static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable. - = help: to fix this, the value can be extracted to a `const` and then used. - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted Some errors have detailed explanations: E0658, E0764. For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr index 35b9ed6735e80..9e76b87385844 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr @@ -49,11 +49,6 @@ help: skipping check for `const_refs_to_static` feature | LL | const READ_MUT: u32 = unsafe { MUTABLE }; | ^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static.rs:18:32 - | -LL | const READ_MUT: u32 = unsafe { MUTABLE }; - | ^^^^^^^ help: skipping check for `const_refs_to_static` feature --> $DIR/const_refers_to_static.rs:24:18 | diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr index 8511673b684fb..989d3c75cd684 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr @@ -49,11 +49,6 @@ help: skipping check for `const_refs_to_static` feature | LL | const READ_MUT: u32 = unsafe { MUTABLE }; | ^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static.rs:18:32 - | -LL | const READ_MUT: u32 = unsafe { MUTABLE }; - | ^^^^^^^ help: skipping check for `const_refs_to_static` feature --> $DIR/const_refers_to_static.rs:24:18 | diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr index a2c9034c831b8..e280fe622ecbe 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr @@ -83,21 +83,6 @@ help: skipping check for `const_refs_to_static` feature | LL | unsafe { &static_cross_crate::ZERO } | ^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:12:15 - | -LL | unsafe { &static_cross_crate::ZERO } - | ^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:18:15 - | -LL | unsafe { &static_cross_crate::ZERO[0] } - | ^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:18:15 - | -LL | unsafe { &static_cross_crate::ZERO[0] } - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_refs_to_static` feature --> $DIR/const_refers_to_static_cross_crate.rs:18:15 | @@ -113,26 +98,6 @@ help: skipping check for `const_refs_to_static` feature | LL | match static_cross_crate::OPT_ZERO { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:28:15 - | -LL | match static_cross_crate::OPT_ZERO { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:28:15 - | -LL | match static_cross_crate::OPT_ZERO { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:28:15 - | -LL | match static_cross_crate::OPT_ZERO { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:28:15 - | -LL | match static_cross_crate::OPT_ZERO { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors; 2 warnings emitted diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr index 2b44a8b12fa3f..9bca60485c08b 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr @@ -83,21 +83,6 @@ help: skipping check for `const_refs_to_static` feature | LL | unsafe { &static_cross_crate::ZERO } | ^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:12:15 - | -LL | unsafe { &static_cross_crate::ZERO } - | ^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:18:15 - | -LL | unsafe { &static_cross_crate::ZERO[0] } - | ^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:18:15 - | -LL | unsafe { &static_cross_crate::ZERO[0] } - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_refs_to_static` feature --> $DIR/const_refers_to_static_cross_crate.rs:18:15 | @@ -113,26 +98,6 @@ help: skipping check for `const_refs_to_static` feature | LL | match static_cross_crate::OPT_ZERO { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:28:15 - | -LL | match static_cross_crate::OPT_ZERO { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:28:15 - | -LL | match static_cross_crate::OPT_ZERO { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:28:15 - | -LL | match static_cross_crate::OPT_ZERO { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:28:15 - | -LL | match static_cross_crate::OPT_ZERO { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors; 2 warnings emitted diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr index b60f9a24f8c7a..401cf46710afd 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr @@ -114,11 +114,6 @@ help: skipping check for `const_refs_to_static` feature | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; | ^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/mutable_references_err.rs:32:40 - | -LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; - | ^^^ help: skipping check that does not even have a feature gate --> $DIR/mutable_references_err.rs:32:35 | @@ -144,16 +139,6 @@ help: skipping check for `const_refs_to_static` feature | LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE }; | ^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/mutable_references_err.rs:47:44 - | -LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE }; - | ^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/mutable_references_err.rs:51:45 - | -LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF }; - | ^^^^^^^^^^^ help: skipping check for `const_refs_to_static` feature --> $DIR/mutable_references_err.rs:51:45 | diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr index 1e5d4bd890b99..0eb01f5b77388 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr @@ -114,11 +114,6 @@ help: skipping check for `const_refs_to_static` feature | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; | ^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/mutable_references_err.rs:32:40 - | -LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; - | ^^^ help: skipping check that does not even have a feature gate --> $DIR/mutable_references_err.rs:32:35 | @@ -144,16 +139,6 @@ help: skipping check for `const_refs_to_static` feature | LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE }; | ^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/mutable_references_err.rs:47:44 - | -LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE }; - | ^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/mutable_references_err.rs:51:45 - | -LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF }; - | ^^^^^^^^^^^ help: skipping check for `const_refs_to_static` feature --> $DIR/mutable_references_err.rs:51:45 | diff --git a/tests/ui/feature-gates/feature-gate-const-refs-to-static.rs b/tests/ui/feature-gates/feature-gate-const-refs-to-static.rs index c020bb37a9999..008b754dc6cf3 100644 --- a/tests/ui/feature-gates/feature-gate-const-refs-to-static.rs +++ b/tests/ui/feature-gates/feature-gate-const-refs-to-static.rs @@ -6,7 +6,6 @@ const C1_READ: () = { assert!(*C1 == 0); }; const C2: *const i32 = unsafe { std::ptr::addr_of!(S_MUT) }; //~ERROR: referencing statics in constants is unstable -//~^ERROR: referencing statics in constants is unstable fn main() { } diff --git a/tests/ui/feature-gates/feature-gate-const-refs-to-static.stderr b/tests/ui/feature-gates/feature-gate-const-refs-to-static.stderr index f94cff5b55047..5af484712501e 100644 --- a/tests/ui/feature-gates/feature-gate-const-refs-to-static.stderr +++ b/tests/ui/feature-gates/feature-gate-const-refs-to-static.stderr @@ -22,19 +22,6 @@ LL | const C2: *const i32 = unsafe { std::ptr::addr_of!(S_MUT) }; = note: `static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable. = help: to fix this, the value can be extracted to a `const` and then used. -error[E0658]: referencing statics in constants is unstable - --> $DIR/feature-gate-const-refs-to-static.rs:8:52 - | -LL | const C2: *const i32 = unsafe { std::ptr::addr_of!(S_MUT) }; - | ^^^^^ - | - = note: see issue #119618 for more information - = help: add `#![feature(const_refs_to_static)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = note: `static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable. - = help: to fix this, the value can be extracted to a `const` and then used. - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/thread-local/thread-local-static.rs b/tests/ui/thread-local/thread-local-static.rs index 7b69ffed197a1..dac9259a6a63b 100644 --- a/tests/ui/thread-local/thread-local-static.rs +++ b/tests/ui/thread-local/thread-local-static.rs @@ -12,7 +12,6 @@ const fn g(x: &mut [u32; 8]) { //~^^ ERROR thread-local statics cannot be accessed //~| ERROR mutable references are not allowed //~| ERROR use of mutable static is unsafe - //~| referencing statics } fn main() {} diff --git a/tests/ui/thread-local/thread-local-static.stderr b/tests/ui/thread-local/thread-local-static.stderr index d91742686c691..3dd1e2d40001c 100644 --- a/tests/ui/thread-local/thread-local-static.stderr +++ b/tests/ui/thread-local/thread-local-static.stderr @@ -37,18 +37,6 @@ error[E0625]: thread-local statics cannot be accessed at compile-time LL | std::mem::swap(x, &mut STATIC_VAR_2) | ^^^^^^^^^^^^ -error[E0658]: referencing statics in constant functions is unstable - --> $DIR/thread-local-static.rs:10:28 - | -LL | std::mem::swap(x, &mut STATIC_VAR_2) - | ^^^^^^^^^^^^ - | - = note: see issue #119618 for more information - = help: add `#![feature(const_refs_to_static)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = note: `static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable. - = help: to fix this, the value can be extracted to a `const` and then used. - error[E0658]: mutable references are not allowed in constant functions --> $DIR/thread-local-static.rs:10:23 | @@ -59,7 +47,7 @@ LL | std::mem::swap(x, &mut STATIC_VAR_2) = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 4 previous errors; 1 warning emitted Some errors have detailed explanations: E0133, E0625, E0658. For more information about an error, try `rustc --explain E0133`. From e13de311d58467a61ca1b33adedeec5f62fd1cad Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 11 Feb 2024 14:59:38 +0100 Subject: [PATCH 05/18] make Primary/Secondary importance consistent between CellBorrow and MutBorrow --- .../src/transform/check_consts/ops.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index a9d472d377cd6..0c93cfaa54647 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -409,11 +409,6 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow { fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status { Status::Unstable(sym::const_refs_to_cell) } - fn importance(&self) -> DiagnosticImportance { - // The cases that cannot possibly work will already emit a `CellBorrow`, so we should - // not additionally emit a feature gate error if activating the feature gate won't work. - DiagnosticImportance::Secondary - } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx .sess @@ -427,6 +422,11 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow { /// it in the future for static items. pub struct CellBorrow; impl<'tcx> NonConstOp<'tcx> for CellBorrow { + fn importance(&self) -> DiagnosticImportance { + // Most likely the code will try to do mutation with these borrows, which + // triggers its own errors. Only show this one if that does not happen. + DiagnosticImportance::Secondary + } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { // FIXME: Maybe a more elegant solution to this if else case if let hir::ConstContext::Static(_) = ccx.const_kind() { @@ -459,8 +459,8 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow { } fn importance(&self) -> DiagnosticImportance { - // If there were primary errors (like non-const function calls), do not emit further - // errors about mutable references. + // Most likely the code will try to do mutation with these borrows, which + // triggers its own errors. Only show this one if that does not happen. DiagnosticImportance::Secondary } From 792fa24595c9a65249dd8de815549f3641548ad3 Mon Sep 17 00:00:00 2001 From: ripytide Date: Sun, 11 Feb 2024 15:21:58 +0000 Subject: [PATCH 06/18] improve `btree_cursors` functions documentation --- library/alloc/src/collections/btree/map.rs | 217 ++++++++++++--------- 1 file changed, 130 insertions(+), 87 deletions(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index b585e2082f137..724a070818da4 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -2522,10 +2522,17 @@ impl BTreeMap { self.len() == 0 } - /// Returns a [`Cursor`] pointing to the first gap above the given bound. + /// Returns a [`Cursor`] pointing at the gap before the smallest key + /// greater than the given bound. /// - /// Passing [`Bound::Unbounded`] will return a cursor pointing to the start - /// of the map. + /// Passing [`Bound::Included(x)`] will return a cursor pointing to the + /// gap before the smallest key greater than or equal to `x`. + /// + /// Passing [`Bound::Excluded(x)`] will return a cursor pointing to the + /// gap before the smallest key greater than `x`. + /// + /// Passing [`Bound::Unbounded`] will return a cursor pointing to the + /// gap before the smallest key in the map. /// /// # Examples /// @@ -2535,17 +2542,24 @@ impl BTreeMap { /// use std::collections::BTreeMap; /// use std::ops::Bound; /// - /// let mut a = BTreeMap::new(); - /// a.insert(1, "a"); - /// a.insert(2, "b"); - /// a.insert(3, "c"); - /// a.insert(4, "d"); - /// let cursor = a.lower_bound(Bound::Included(&2)); + /// let map = BTreeMap::from([ + /// (1, "a"), + /// (2, "b"), + /// (3, "c"), + /// (4, "d"), + /// ]); + /// + /// let cursor = map.lower_bound(Bound::Included(&2)); /// assert_eq!(cursor.peek_prev(), Some((&1, &"a"))); /// assert_eq!(cursor.peek_next(), Some((&2, &"b"))); - /// let cursor = a.lower_bound(Bound::Excluded(&2)); + /// + /// let cursor = map.lower_bound(Bound::Excluded(&2)); /// assert_eq!(cursor.peek_prev(), Some((&2, &"b"))); /// assert_eq!(cursor.peek_next(), Some((&3, &"c"))); + /// + /// let cursor = map.lower_bound(Bound::Unbounded); + /// assert_eq!(cursor.peek_prev(), None); + /// assert_eq!(cursor.peek_next(), Some((&1, &"a"))); /// ``` #[unstable(feature = "btree_cursors", issue = "107540")] pub fn lower_bound(&self, bound: Bound<&Q>) -> Cursor<'_, K, V> @@ -2561,11 +2575,17 @@ impl BTreeMap { Cursor { current: Some(edge), root: self.root.as_ref() } } - /// Returns a [`CursorMut`] pointing to the first gap above the given bound. + /// Returns a [`CursorMut`] pointing at the gap before the smallest key + /// greater than the given bound. /// + /// Passing [`Bound::Included(x)`] will return a cursor pointing to the + /// gap before the smallest key greater than or equal to `x`. /// - /// Passing [`Bound::Unbounded`] will return a cursor pointing to the start - /// of the map. + /// Passing [`Bound::Excluded(x)`] will return a cursor pointing to the + /// gap before the smallest key greater than `x`. + /// + /// Passing [`Bound::Unbounded`] will return a cursor pointing to the + /// gap before the smallest key in the map. /// /// # Examples /// @@ -2575,17 +2595,24 @@ impl BTreeMap { /// use std::collections::BTreeMap; /// use std::ops::Bound; /// - /// let mut a = BTreeMap::new(); - /// a.insert(1, "a"); - /// a.insert(2, "b"); - /// a.insert(3, "c"); - /// a.insert(4, "d"); - /// let mut cursor = a.lower_bound_mut(Bound::Included(&2)); + /// let mut map = BTreeMap::from([ + /// (1, "a"), + /// (2, "b"), + /// (3, "c"), + /// (4, "d"), + /// ]); + /// + /// let mut cursor = map.lower_bound_mut(Bound::Included(&2)); /// assert_eq!(cursor.peek_prev(), Some((&1, &mut "a"))); /// assert_eq!(cursor.peek_next(), Some((&2, &mut "b"))); - /// let mut cursor = a.lower_bound_mut(Bound::Excluded(&2)); + /// + /// let mut cursor = map.lower_bound_mut(Bound::Excluded(&2)); /// assert_eq!(cursor.peek_prev(), Some((&2, &mut "b"))); /// assert_eq!(cursor.peek_next(), Some((&3, &mut "c"))); + /// + /// let mut cursor = map.lower_bound_mut(Bound::Unbounded); + /// assert_eq!(cursor.peek_prev(), None); + /// assert_eq!(cursor.peek_next(), Some((&1, &mut "a"))); /// ``` #[unstable(feature = "btree_cursors", issue = "107540")] pub fn lower_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, K, V, A> @@ -2618,10 +2645,17 @@ impl BTreeMap { } } - /// Returns a [`Cursor`] pointing at the last gap below the given bound. + /// Returns a [`Cursor`] pointing at the gap after the greatest key + /// smaller than the given bound. /// - /// Passing [`Bound::Unbounded`] will return a cursor pointing to the end - /// of the map. + /// Passing [`Bound::Included(x)`] will return a cursor pointing to the + /// gap after the greatest key smaller than or equal to `x`. + /// + /// Passing [`Bound::Excluded(x)`] will return a cursor pointing to the + /// gap after the greatest key smaller than `x`. + /// + /// Passing [`Bound::Unbounded`] will return a cursor pointing to the + /// gap after the greatest key in the map. /// /// # Examples /// @@ -2631,17 +2665,24 @@ impl BTreeMap { /// use std::collections::BTreeMap; /// use std::ops::Bound; /// - /// let mut a = BTreeMap::new(); - /// a.insert(1, "a"); - /// a.insert(2, "b"); - /// a.insert(3, "c"); - /// a.insert(4, "d"); - /// let cursor = a.upper_bound(Bound::Included(&3)); - /// assert_eq!(cursor.peek_prev(), Some((&3, &"c"))); - /// assert_eq!(cursor.peek_next(), Some((&4, &"d"))); - /// let cursor = a.upper_bound(Bound::Excluded(&3)); + /// let map = BTreeMap::from([ + /// (1, "a"), + /// (2, "b"), + /// (3, "c"), + /// (4, "d"), + /// ]); + /// + /// let cursor = map.upper_bound(Bound::Included(&3)); + /// assert_eq!(cursor.peek_prev(), Some((&3, &"d"))); + /// assert_eq!(cursor.peek_next(), Some((&4, &"c"))); + /// + /// let cursor = map.upper_bound(Bound::Excluded(&3)); /// assert_eq!(cursor.peek_prev(), Some((&2, &"b"))); /// assert_eq!(cursor.peek_next(), Some((&3, &"c"))); + /// + /// let cursor = map.upper_bound(Bound::Unbounded); + /// assert_eq!(cursor.peek_prev(), Some((&4, &"d"))); + /// assert_eq!(cursor.peek_next(), None); /// ``` #[unstable(feature = "btree_cursors", issue = "107540")] pub fn upper_bound(&self, bound: Bound<&Q>) -> Cursor<'_, K, V> @@ -2657,10 +2698,17 @@ impl BTreeMap { Cursor { current: Some(edge), root: self.root.as_ref() } } - /// Returns a [`CursorMut`] pointing at the last gap below the given bound. + /// Returns a [`CursorMut`] pointing at the gap after the greatest key + /// smaller than the given bound. /// - /// Passing [`Bound::Unbounded`] will return a cursor pointing to the end - /// of the map. + /// Passing [`Bound::Included(x)`] will return a cursor pointing to the + /// gap after the greatest key smaller than or equal to `x`. + /// + /// Passing [`Bound::Excluded(x)`] will return a cursor pointing to the + /// gap after the greatest key smaller than `x`. + /// + /// Passing [`Bound::Unbounded`] will return a cursor pointing to the + /// gap after the greatest key in the map. /// /// # Examples /// @@ -2670,17 +2718,24 @@ impl BTreeMap { /// use std::collections::BTreeMap; /// use std::ops::Bound; /// - /// let mut a = BTreeMap::new(); - /// a.insert(1, "a"); - /// a.insert(2, "b"); - /// a.insert(3, "c"); - /// a.insert(4, "d"); - /// let mut cursor = a.upper_bound_mut(Bound::Included(&3)); + /// let mut map = BTreeMap::from([ + /// (1, "a"), + /// (2, "b"), + /// (3, "c"), + /// (4, "d"), + /// ]); + /// + /// let mut cursor = map.upper_bound_mut(Bound::Included(&3)); /// assert_eq!(cursor.peek_prev(), Some((&3, &mut "c"))); /// assert_eq!(cursor.peek_next(), Some((&4, &mut "d"))); - /// let mut cursor = a.upper_bound_mut(Bound::Excluded(&3)); + /// + /// let mut cursor = map.upper_bound_mut(Bound::Excluded(&3)); /// assert_eq!(cursor.peek_prev(), Some((&2, &mut "b"))); /// assert_eq!(cursor.peek_next(), Some((&3, &mut "c"))); + /// + /// let mut cursor = map.upper_bound_mut(Bound::Unbounded); + /// assert_eq!(cursor.peek_prev(), Some((&4, &mut "d"))); + /// assert_eq!(cursor.peek_next(), None); /// ``` #[unstable(feature = "btree_cursors", issue = "107540")] pub fn upper_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, K, V, A> @@ -3040,8 +3095,8 @@ impl<'a, K, V, A> CursorMutKey<'a, K, V, A> { // Now the tree editing operations impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> { - /// Inserts a new element into the `BTreeMap` in the gap that the - /// `CursorMutKey` is currently pointing to. + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. /// /// After the insertion the cursor will be pointing at the gap before the /// newly inserted element. @@ -3083,8 +3138,8 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> { *self.length += 1; } - /// Inserts a new element into the `BTreeMap` in the gap that the - /// `CursorMutKey` is currently pointing to. + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. /// /// After the insertion the cursor will be pointing at the gap after the /// newly inserted element. @@ -3129,19 +3184,16 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> { *self.length += 1; } - /// Inserts a new element into the `BTreeMap` in the gap that the - /// `CursorMutKey` is currently pointing to. + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. /// /// After the insertion the cursor will be pointing at the gap before the /// newly inserted element. /// - /// # Panics - /// - /// This function panics if: - /// - the given key compares less than or equal to the current element (if - /// any). - /// - the given key compares greater than or equal to the next element (if - /// any). + /// If the inserted key is not greater than the key before the cursor + /// (if any), or if it not less than the key after the cursor (if any), + /// then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the keys of the map. #[unstable(feature = "btree_cursors", issue = "107540")] pub fn insert_after(&mut self, key: K, value: V) -> Result<(), UnorderedKeyError> { if let Some((prev, _)) = self.peek_prev() { @@ -3160,19 +3212,16 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> { Ok(()) } - /// Inserts a new element into the `BTreeMap` in the gap that the - /// `CursorMutKey` is currently pointing to. + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. /// /// After the insertion the cursor will be pointing at the gap after the /// newly inserted element. /// - /// # Panics - /// - /// This function panics if: - /// - the given key compares greater than or equal to the current element - /// (if any). - /// - the given key compares less than or equal to the previous element (if - /// any). + /// If the inserted key is not greater than the key before the cursor + /// (if any), or if it not less than the key after the cursor (if any), + /// then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the keys of the map. #[unstable(feature = "btree_cursors", issue = "107540")] pub fn insert_before(&mut self, key: K, value: V) -> Result<(), UnorderedKeyError> { if let Some((prev, _)) = self.peek_prev() { @@ -3239,10 +3288,10 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> { } impl<'a, K: Ord, V, A: Allocator + Clone> CursorMut<'a, K, V, A> { - /// Inserts a new element into the `BTreeMap` in the gap that the - /// `CursorMut` is currently pointing to. + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. /// - /// After the insertion the cursor will be pointing at the gap before the + /// After the insertion the cursor will be pointing at the gap after the /// newly inserted element. /// /// # Safety @@ -3257,8 +3306,8 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMut<'a, K, V, A> { unsafe { self.inner.insert_after_unchecked(key, value) } } - /// Inserts a new element into the `BTreeMap` in the gap that the - /// `CursorMut` is currently pointing to. + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. /// /// After the insertion the cursor will be pointing at the gap after the /// newly inserted element. @@ -3275,37 +3324,31 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMut<'a, K, V, A> { unsafe { self.inner.insert_before_unchecked(key, value) } } - /// Inserts a new element into the `BTreeMap` in the gap that the - /// `CursorMut` is currently pointing to. + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. /// /// After the insertion the cursor will be pointing at the gap before the /// newly inserted element. /// - /// # Panics - /// - /// This function panics if: - /// - the given key compares less than or equal to the current element (if - /// any). - /// - the given key compares greater than or equal to the next element (if - /// any). + /// If the inserted key is not greater than the key before the cursor + /// (if any), or if it not less than the key after the cursor (if any), + /// then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the keys of the map. #[unstable(feature = "btree_cursors", issue = "107540")] pub fn insert_after(&mut self, key: K, value: V) -> Result<(), UnorderedKeyError> { self.inner.insert_after(key, value) } - /// Inserts a new element into the `BTreeMap` in the gap that the - /// `CursorMut` is currently pointing to. + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. /// /// After the insertion the cursor will be pointing at the gap after the /// newly inserted element. /// - /// # Panics - /// - /// This function panics if: - /// - the given key compares greater than or equal to the current element - /// (if any). - /// - the given key compares less than or equal to the previous element (if - /// any). + /// If the inserted key is not greater than the key before the cursor + /// (if any), or if it not less than the key after the cursor (if any), + /// then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the keys of the map. #[unstable(feature = "btree_cursors", issue = "107540")] pub fn insert_before(&mut self, key: K, value: V) -> Result<(), UnorderedKeyError> { self.inner.insert_before(key, value) From f4153390527cc6396d19f68097d34a7a3a1e7edb Mon Sep 17 00:00:00 2001 From: ripytide Date: Sun, 11 Feb 2024 16:18:40 +0000 Subject: [PATCH 07/18] fix incorrect doctest --- library/alloc/src/collections/btree/map.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 724a070818da4..770b68c3dded0 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -2673,8 +2673,8 @@ impl BTreeMap { /// ]); /// /// let cursor = map.upper_bound(Bound::Included(&3)); - /// assert_eq!(cursor.peek_prev(), Some((&3, &"d"))); - /// assert_eq!(cursor.peek_next(), Some((&4, &"c"))); + /// assert_eq!(cursor.peek_prev(), Some((&3, &"c"))); + /// assert_eq!(cursor.peek_next(), Some((&4, &"d"))); /// /// let cursor = map.upper_bound(Bound::Excluded(&3)); /// assert_eq!(cursor.peek_prev(), Some((&2, &"b"))); From 9789e88cfe7f50ac46d04175e32df4329d75024e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 11 Feb 2024 19:17:42 +0000 Subject: [PATCH 08/18] Check that the ABI of the instance we are inlining is correct --- compiler/rustc_mir_transform/src/inline.rs | 12 ++++++++ tests/ui/mir/inline-wrong-abi.rs | 32 ++++++++++++++++++++++ tests/ui/mir/inline-wrong-abi.stderr | 12 ++++++++ 3 files changed, 56 insertions(+) create mode 100644 tests/ui/mir/inline-wrong-abi.rs create mode 100644 tests/ui/mir/inline-wrong-abi.stderr diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index be19bd8349ed4..956d855ab81a2 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -2,6 +2,7 @@ use crate::deref_separator::deref_finder; use rustc_attr::InlineAttr; use rustc_const_eval::transform::validate::validate_types; +use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; use rustc_index::Idx; @@ -384,6 +385,17 @@ impl<'tcx> Inliner<'tcx> { } let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args); + + // Additionally, check that the body that we're inlining actually agrees + // with the ABI of the trait that the item comes from. + if let InstanceDef::Item(instance_def_id) = callee.def + && self.tcx.def_kind(instance_def_id) == DefKind::AssocFn + && let instance_fn_sig = self.tcx.fn_sig(instance_def_id).skip_binder() + && instance_fn_sig.abi() != fn_sig.abi() + { + return None; + } + let source_info = SourceInfo { span: fn_span, ..terminator.source_info }; return Some(CallSite { callee, fn_sig, block: bb, source_info }); diff --git a/tests/ui/mir/inline-wrong-abi.rs b/tests/ui/mir/inline-wrong-abi.rs new file mode 100644 index 0000000000000..1f61a5dcfbe6d --- /dev/null +++ b/tests/ui/mir/inline-wrong-abi.rs @@ -0,0 +1,32 @@ +// compile-flags: -Zpolymorphize=on -Zinline-mir=yes -Zmir-opt-level=0 + +#![feature(fn_traits, unboxed_closures)] +struct Foo(T); + +impl Fn<()> for Foo { + extern "C" fn call(&self, _: ()) -> T { + //~^ ERROR method `call` has an incompatible type for trait + match *self { + Foo(t) => t, + } + } +} + +impl FnMut<()> for Foo { + extern "rust-call" fn call_mut(&mut self, _: ()) -> T { + self.call(()) + } +} + +impl FnOnce<()> for Foo { + type Output = T; + + extern "rust-call" fn call_once(self, _: ()) -> T { + self.call(()) + } +} + +fn main() { + let t: u8 = 1; + println!("{}", Foo(t)()); +} diff --git a/tests/ui/mir/inline-wrong-abi.stderr b/tests/ui/mir/inline-wrong-abi.stderr new file mode 100644 index 0000000000000..e44899eb92a5c --- /dev/null +++ b/tests/ui/mir/inline-wrong-abi.stderr @@ -0,0 +1,12 @@ +error[E0053]: method `call` has an incompatible type for trait + --> $DIR/inline-wrong-abi.rs:7:5 + | +LL | extern "C" fn call(&self, _: ()) -> T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "rust-call" fn, found "C" fn + | + = note: expected signature `extern "rust-call" fn(&Foo<_>, ()) -> _` + found signature `extern "C" fn(&Foo<_>, ()) -> _` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0053`. From f34d9da7db8447e5616f964bfa65b09a7b45ba3a Mon Sep 17 00:00:00 2001 From: ripytide Date: Sun, 11 Feb 2024 17:15:43 +0000 Subject: [PATCH 09/18] fix intra-doc links --- library/alloc/src/collections/btree/map.rs | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 770b68c3dded0..2b8ddf14ff30b 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -2525,13 +2525,13 @@ impl BTreeMap { /// Returns a [`Cursor`] pointing at the gap before the smallest key /// greater than the given bound. /// - /// Passing [`Bound::Included(x)`] will return a cursor pointing to the + /// Passing `Bound::Included(x)` will return a cursor pointing to the /// gap before the smallest key greater than or equal to `x`. /// - /// Passing [`Bound::Excluded(x)`] will return a cursor pointing to the + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the /// gap before the smallest key greater than `x`. /// - /// Passing [`Bound::Unbounded`] will return a cursor pointing to the + /// Passing `Bound::Unbounded` will return a cursor pointing to the /// gap before the smallest key in the map. /// /// # Examples @@ -2578,13 +2578,13 @@ impl BTreeMap { /// Returns a [`CursorMut`] pointing at the gap before the smallest key /// greater than the given bound. /// - /// Passing [`Bound::Included(x)`] will return a cursor pointing to the + /// Passing `Bound::Included(x)` will return a cursor pointing to the /// gap before the smallest key greater than or equal to `x`. /// - /// Passing [`Bound::Excluded(x)`] will return a cursor pointing to the + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the /// gap before the smallest key greater than `x`. /// - /// Passing [`Bound::Unbounded`] will return a cursor pointing to the + /// Passing `Bound::Unbounded` will return a cursor pointing to the /// gap before the smallest key in the map. /// /// # Examples @@ -2648,13 +2648,13 @@ impl BTreeMap { /// Returns a [`Cursor`] pointing at the gap after the greatest key /// smaller than the given bound. /// - /// Passing [`Bound::Included(x)`] will return a cursor pointing to the + /// Passing `Bound::Included(x)` will return a cursor pointing to the /// gap after the greatest key smaller than or equal to `x`. /// - /// Passing [`Bound::Excluded(x)`] will return a cursor pointing to the + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the /// gap after the greatest key smaller than `x`. /// - /// Passing [`Bound::Unbounded`] will return a cursor pointing to the + /// Passing `Bound::Unbounded` will return a cursor pointing to the /// gap after the greatest key in the map. /// /// # Examples @@ -2701,13 +2701,13 @@ impl BTreeMap { /// Returns a [`CursorMut`] pointing at the gap after the greatest key /// smaller than the given bound. /// - /// Passing [`Bound::Included(x)`] will return a cursor pointing to the + /// Passing `Bound::Included(x)` will return a cursor pointing to the /// gap after the greatest key smaller than or equal to `x`. /// - /// Passing [`Bound::Excluded(x)`] will return a cursor pointing to the + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the /// gap after the greatest key smaller than `x`. /// - /// Passing [`Bound::Unbounded`] will return a cursor pointing to the + /// Passing `Bound::Unbounded` will return a cursor pointing to the /// gap after the greatest key in the map. /// /// # Examples From c35983a74817599ab363adf2a6ef6b4cf2e7c5b6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 8 Feb 2024 16:02:20 +1100 Subject: [PATCH 10/18] Reorder the diagnostic API methods. The current order is almost perfectly random. This commit puts them into a predictable order in their own impl block, going from the highest level (`Block`) to the lowest (`Expect`). Within each level this is the order: - struct_err, err - struct_span_err, span_err - create_err, emit_err The first one in each pair creates a diagnostic, the second one creates *and* emits a diagnostic. Not every method is present for every level. The diff is messy, but other than moving methods around, the only thing it does is create the new `impl DiagCtxt` block with its own comment. --- compiler/rustc_errors/src/lib.rs | 617 ++++++++++++++++--------------- 1 file changed, 311 insertions(+), 306 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index ab3ad0e9d6843..4c0bb763dc180 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -718,217 +718,6 @@ impl DiagCtxt { self.inner.borrow_mut().emit_stashed_diagnostics() } - /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. - /// - /// An `emit` call on the builder will only emit if `can_emit_warnings` is `true`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_span_warn( - &self, - span: impl Into, - msg: impl Into, - ) -> DiagnosticBuilder<'_, ()> { - self.struct_warn(msg).with_span(span) - } - - /// Construct a builder at the `Warning` level with the `msg`. - /// - /// An `emit` call on the builder will only emit if `can_emit_warnings` is `true`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_warn(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Warning, msg) - } - - /// Construct a builder at the `Allow` level with the `msg`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_allow(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Allow, msg) - } - - /// Construct a builder at the `Expect` level with the `msg`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_expect( - &self, - msg: impl Into, - id: LintExpectationId, - ) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Expect(id), msg) - } - - /// Construct a builder at the `Error` level at the given `span` and with the `msg`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_span_err( - &self, - span: impl Into, - msg: impl Into, - ) -> DiagnosticBuilder<'_> { - self.struct_err(msg).with_span(span) - } - - /// Construct a builder at the `Error` level with the `msg`. - // FIXME: This method should be removed (every error should have an associated error code). - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_err(&self, msg: impl Into) -> DiagnosticBuilder<'_> { - DiagnosticBuilder::new(self, Error, msg) - } - - /// Construct a builder at the `Fatal` level at the given `span` and with the `msg`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_span_fatal( - &self, - span: impl Into, - msg: impl Into, - ) -> DiagnosticBuilder<'_, FatalAbort> { - self.struct_fatal(msg).with_span(span) - } - - /// Construct a builder at the `Fatal` level with the `msg`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_fatal( - &self, - msg: impl Into, - ) -> DiagnosticBuilder<'_, FatalAbort> { - DiagnosticBuilder::new(self, Fatal, msg) - } - - /// Construct a builder at the `Help` level with the `msg`. - #[rustc_lint_diagnostics] - pub fn struct_help(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Help, msg) - } - - /// Construct a builder at the `Note` level with the `msg`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_note(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Note, msg) - } - - /// Construct a builder at the `Bug` level with the `msg`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_bug(&self, msg: impl Into) -> DiagnosticBuilder<'_, BugAbort> { - DiagnosticBuilder::new(self, Bug, msg) - } - - /// Construct a builder at the `Bug` level at the given `span` with the `msg`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_span_bug( - &self, - span: impl Into, - msg: impl Into, - ) -> DiagnosticBuilder<'_, BugAbort> { - self.struct_bug(msg).with_span(span) - } - - #[rustc_lint_diagnostics] - #[track_caller] - pub fn span_fatal(&self, span: impl Into, msg: impl Into) -> ! { - self.struct_span_fatal(span, msg).emit() - } - - #[rustc_lint_diagnostics] - #[track_caller] - pub fn span_err( - &self, - span: impl Into, - msg: impl Into, - ) -> ErrorGuaranteed { - self.struct_span_err(span, msg).emit() - } - - #[rustc_lint_diagnostics] - #[track_caller] - pub fn span_warn(&self, span: impl Into, msg: impl Into) { - self.struct_span_warn(span, msg).emit() - } - - #[track_caller] - pub fn span_bug(&self, span: impl Into, msg: impl Into) -> ! { - self.struct_span_bug(span, msg).emit() - } - - /// Ensures that compilation cannot succeed. - /// - /// If this function has been called but no errors have been emitted and - /// compilation succeeds, it will cause an internal compiler error (ICE). - /// - /// This can be used in code paths that should never run on successful compilations. - /// For example, it can be used to create an [`ErrorGuaranteed`] - /// (but you should prefer threading through the [`ErrorGuaranteed`] from an error emission - /// directly). - #[track_caller] - pub fn delayed_bug(&self, msg: impl Into) -> ErrorGuaranteed { - DiagnosticBuilder::::new(self, DelayedBug, msg).emit() - } - - /// Like `delayed_bug`, but takes an additional span. - /// - /// Note: this function used to be called `delay_span_bug`. It was renamed - /// to match similar functions like `span_err`, `span_warn`, etc. - #[track_caller] - pub fn span_delayed_bug( - &self, - sp: impl Into, - msg: impl Into, - ) -> ErrorGuaranteed { - DiagnosticBuilder::::new(self, DelayedBug, msg).with_span(sp).emit() - } - - /// Ensures that a diagnostic is printed. See `Level::GoodPathDelayedBug`. - pub fn good_path_delayed_bug(&self, msg: impl Into) { - DiagnosticBuilder::<()>::new(self, GoodPathDelayedBug, msg).emit() - } - - #[track_caller] - #[rustc_lint_diagnostics] - pub fn span_note(&self, span: impl Into, msg: impl Into) { - self.struct_span_note(span, msg).emit() - } - - #[track_caller] - #[rustc_lint_diagnostics] - pub fn struct_span_note( - &self, - span: impl Into, - msg: impl Into, - ) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Note, msg).with_span(span) - } - - #[rustc_lint_diagnostics] - pub fn fatal(&self, msg: impl Into) -> ! { - self.struct_fatal(msg).emit() - } - - #[rustc_lint_diagnostics] - pub fn err(&self, msg: impl Into) -> ErrorGuaranteed { - self.struct_err(msg).emit() - } - - #[rustc_lint_diagnostics] - pub fn warn(&self, msg: impl Into) { - self.struct_warn(msg).emit() - } - - #[rustc_lint_diagnostics] - pub fn note(&self, msg: impl Into) { - self.struct_note(msg).emit() - } - - #[rustc_lint_diagnostics] - pub fn bug(&self, msg: impl Into) -> ! { - self.struct_bug(msg).emit() - } - /// This excludes lint errors, delayed bugs, and stashed errors. #[inline] pub fn err_count(&self) -> usize { @@ -1077,43 +866,155 @@ impl DiagCtxt { self.inner.borrow_mut().emit_diagnostic(diagnostic) } - #[track_caller] - pub fn emit_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> ErrorGuaranteed { - self.create_err(err).emit() + pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { + self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type); } - #[track_caller] - pub fn create_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> DiagnosticBuilder<'a> { - err.into_diagnostic(self, Error) + pub fn emit_future_breakage_report(&self) { + let mut inner = self.inner.borrow_mut(); + let diags = std::mem::take(&mut inner.future_breakage_diagnostics); + if !diags.is_empty() { + inner.emitter.emit_future_breakage_report(diags); + } } - #[track_caller] - pub fn create_warn<'a>( - &'a self, - warning: impl IntoDiagnostic<'a, ()>, - ) -> DiagnosticBuilder<'a, ()> { - warning.into_diagnostic(self, Warning) - } + pub fn emit_unused_externs( + &self, + lint_level: rustc_lint_defs::Level, + loud: bool, + unused_externs: &[&str], + ) { + let mut inner = self.inner.borrow_mut(); - #[track_caller] - pub fn emit_warn<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) { - self.create_warn(warning).emit() - } + if loud && lint_level.is_error() { + inner.lint_err_count += 1; + inner.panic_if_treat_err_as_bug(); + } - #[track_caller] - pub fn create_almost_fatal<'a>( - &'a self, - fatal: impl IntoDiagnostic<'a, FatalError>, - ) -> DiagnosticBuilder<'a, FatalError> { - fatal.into_diagnostic(self, Fatal) + inner.emitter.emit_unused_externs(lint_level, unused_externs) } - #[track_caller] - pub fn emit_almost_fatal<'a>( + pub fn update_unstable_expectation_id( + &self, + unstable_to_stable: &FxIndexMap, + ) { + let mut inner = self.inner.borrow_mut(); + let diags = std::mem::take(&mut inner.unstable_expect_diagnostics); + inner.check_unstable_expect_diagnostics = true; + + if !diags.is_empty() { + inner.suppressed_expected_diag = true; + for mut diag in diags.into_iter() { + diag.update_unstable_expectation_id(unstable_to_stable); + + // Here the diagnostic is given back to `emit_diagnostic` where it was first + // intercepted. Now it should be processed as usual, since the unstable expectation + // id is now stable. + inner.emit_diagnostic(diag); + } + } + + inner + .stashed_diagnostics + .values_mut() + .for_each(|diag| diag.update_unstable_expectation_id(unstable_to_stable)); + inner + .future_breakage_diagnostics + .iter_mut() + .for_each(|diag| diag.update_unstable_expectation_id(unstable_to_stable)); + } + + /// This methods steals all [`LintExpectationId`]s that are stored inside + /// [`DiagCtxtInner`] and indicate that the linked expectation has been fulfilled. + #[must_use] + pub fn steal_fulfilled_expectation_ids(&self) -> FxHashSet { + assert!( + self.inner.borrow().unstable_expect_diagnostics.is_empty(), + "`DiagCtxtInner::unstable_expect_diagnostics` should be empty at this point", + ); + std::mem::take(&mut self.inner.borrow_mut().fulfilled_expectations) + } + + pub fn flush_delayed(&self) { + self.inner.borrow_mut().flush_delayed(DelayedBugKind::Normal); + } +} + +// This `impl` block contains only the public diagnostic creation/emission API. +// +// Functions beginning with `struct_`/`create_` create a diagnostic. Other +// functions create and emit a diagnostic all in one go. +impl DiagCtxt { + /// Construct a builder at the `Bug` level with the `msg`. + #[rustc_lint_diagnostics] + #[track_caller] + pub fn struct_bug(&self, msg: impl Into) -> DiagnosticBuilder<'_, BugAbort> { + DiagnosticBuilder::new(self, Bug, msg) + } + + #[rustc_lint_diagnostics] + pub fn bug(&self, msg: impl Into) -> ! { + self.struct_bug(msg).emit() + } + + /// Construct a builder at the `Bug` level at the given `span` with the `msg`. + #[rustc_lint_diagnostics] + #[track_caller] + pub fn struct_span_bug( + &self, + span: impl Into, + msg: impl Into, + ) -> DiagnosticBuilder<'_, BugAbort> { + self.struct_bug(msg).with_span(span) + } + + pub fn span_bug(&self, span: impl Into, msg: impl Into) -> ! { + self.struct_span_bug(span, msg).emit() + } + + #[track_caller] + pub fn create_bug<'a>( &'a self, - fatal: impl IntoDiagnostic<'a, FatalError>, - ) -> FatalError { - self.create_almost_fatal(fatal).emit() + bug: impl IntoDiagnostic<'a, BugAbort>, + ) -> DiagnosticBuilder<'a, BugAbort> { + bug.into_diagnostic(self, Bug) + } + + #[track_caller] + pub fn emit_bug<'a>(&'a self, bug: impl IntoDiagnostic<'a, diagnostic_builder::BugAbort>) -> ! { + self.create_bug(bug).emit() + } + + /// Construct a builder at the `Fatal` level with the `msg`. + #[rustc_lint_diagnostics] + #[track_caller] + pub fn struct_fatal( + &self, + msg: impl Into, + ) -> DiagnosticBuilder<'_, FatalAbort> { + DiagnosticBuilder::new(self, Fatal, msg) + } + + #[rustc_lint_diagnostics] + pub fn fatal(&self, msg: impl Into) -> ! { + self.struct_fatal(msg).emit() + } + + /// Construct a builder at the `Fatal` level at the given `span` and with the `msg`. + #[rustc_lint_diagnostics] + #[track_caller] + pub fn struct_span_fatal( + &self, + span: impl Into, + msg: impl Into, + ) -> DiagnosticBuilder<'_, FatalAbort> { + self.struct_fatal(msg).with_span(span) + } + + #[rustc_lint_diagnostics] + #[track_caller] + pub fn span_fatal(&self, span: impl Into, msg: impl Into) -> ! { + self.struct_span_fatal(span, msg).emit() } #[track_caller] @@ -1130,102 +1031,206 @@ impl DiagCtxt { } #[track_caller] - pub fn create_bug<'a>( + pub fn create_almost_fatal<'a>( &'a self, - bug: impl IntoDiagnostic<'a, BugAbort>, - ) -> DiagnosticBuilder<'a, BugAbort> { - bug.into_diagnostic(self, Bug) + fatal: impl IntoDiagnostic<'a, FatalError>, + ) -> DiagnosticBuilder<'a, FatalError> { + fatal.into_diagnostic(self, Fatal) } #[track_caller] - pub fn emit_bug<'a>(&'a self, bug: impl IntoDiagnostic<'a, diagnostic_builder::BugAbort>) -> ! { - self.create_bug(bug).emit() + pub fn emit_almost_fatal<'a>( + &'a self, + fatal: impl IntoDiagnostic<'a, FatalError>, + ) -> FatalError { + self.create_almost_fatal(fatal).emit() } + /// Construct a builder at the `Error` level with the `msg`. + // FIXME: This method should be removed (every error should have an associated error code). + #[rustc_lint_diagnostics] #[track_caller] - pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, ()>) { - self.create_note(note).emit() + pub fn struct_err(&self, msg: impl Into) -> DiagnosticBuilder<'_> { + DiagnosticBuilder::new(self, Error, msg) + } + + #[rustc_lint_diagnostics] + pub fn err(&self, msg: impl Into) -> ErrorGuaranteed { + self.struct_err(msg).emit() } + /// Construct a builder at the `Error` level at the given `span` and with the `msg`. + #[rustc_lint_diagnostics] #[track_caller] - pub fn create_note<'a>( - &'a self, - note: impl IntoDiagnostic<'a, ()>, - ) -> DiagnosticBuilder<'a, ()> { - note.into_diagnostic(self, Note) + pub fn struct_span_err( + &self, + span: impl Into, + msg: impl Into, + ) -> DiagnosticBuilder<'_> { + self.struct_err(msg).with_span(span) } - pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { - self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type); + #[rustc_lint_diagnostics] + #[track_caller] + pub fn span_err( + &self, + span: impl Into, + msg: impl Into, + ) -> ErrorGuaranteed { + self.struct_span_err(span, msg).emit() } - pub fn emit_future_breakage_report(&self) { - let mut inner = self.inner.borrow_mut(); - let diags = std::mem::take(&mut inner.future_breakage_diagnostics); - if !diags.is_empty() { - inner.emitter.emit_future_breakage_report(diags); - } + #[track_caller] + pub fn create_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> DiagnosticBuilder<'a> { + err.into_diagnostic(self, Error) } - pub fn emit_unused_externs( + #[track_caller] + pub fn emit_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> ErrorGuaranteed { + self.create_err(err).emit() + } + + /// Ensures that compilation cannot succeed. + /// + /// If this function has been called but no errors have been emitted and + /// compilation succeeds, it will cause an internal compiler error (ICE). + /// + /// This can be used in code paths that should never run on successful compilations. + /// For example, it can be used to create an [`ErrorGuaranteed`] + /// (but you should prefer threading through the [`ErrorGuaranteed`] from an error emission + /// directly). + #[track_caller] + pub fn delayed_bug(&self, msg: impl Into) -> ErrorGuaranteed { + DiagnosticBuilder::::new(self, DelayedBug, msg).emit() + } + + /// Like `delayed_bug`, but takes an additional span. + /// + /// Note: this function used to be called `delay_span_bug`. It was renamed + /// to match similar functions like `span_err`, `span_warn`, etc. + #[track_caller] + pub fn span_delayed_bug( &self, - lint_level: rustc_lint_defs::Level, - loud: bool, - unused_externs: &[&str], - ) { - let mut inner = self.inner.borrow_mut(); + sp: impl Into, + msg: impl Into, + ) -> ErrorGuaranteed { + DiagnosticBuilder::::new(self, DelayedBug, msg).with_span(sp).emit() + } - if loud && lint_level.is_error() { - inner.lint_err_count += 1; - inner.panic_if_treat_err_as_bug(); - } + /// Ensures that a diagnostic is printed. See `Level::GoodPathDelayedBug`. + pub fn good_path_delayed_bug(&self, msg: impl Into) { + DiagnosticBuilder::<()>::new(self, GoodPathDelayedBug, msg).emit() + } - inner.emitter.emit_unused_externs(lint_level, unused_externs) + /// Construct a builder at the `Warning` level with the `msg`. + /// + /// An `emit` call on the builder will only emit if `can_emit_warnings` is `true`. + #[rustc_lint_diagnostics] + #[track_caller] + pub fn struct_warn(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { + DiagnosticBuilder::new(self, Warning, msg) } - pub fn update_unstable_expectation_id( + #[rustc_lint_diagnostics] + pub fn warn(&self, msg: impl Into) { + self.struct_warn(msg).emit() + } + + /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. + /// + /// An `emit` call on the builder will only emit if `can_emit_warnings` is `true`. + #[rustc_lint_diagnostics] + #[track_caller] + pub fn struct_span_warn( &self, - unstable_to_stable: &FxIndexMap, - ) { - let mut inner = self.inner.borrow_mut(); - let diags = std::mem::take(&mut inner.unstable_expect_diagnostics); - inner.check_unstable_expect_diagnostics = true; + span: impl Into, + msg: impl Into, + ) -> DiagnosticBuilder<'_, ()> { + self.struct_warn(msg).with_span(span) + } - if !diags.is_empty() { - inner.suppressed_expected_diag = true; - for mut diag in diags.into_iter() { - diag.update_unstable_expectation_id(unstable_to_stable); + #[rustc_lint_diagnostics] + #[track_caller] + pub fn span_warn(&self, span: impl Into, msg: impl Into) { + self.struct_span_warn(span, msg).emit() + } - // Here the diagnostic is given back to `emit_diagnostic` where it was first - // intercepted. Now it should be processed as usual, since the unstable expectation - // id is now stable. - inner.emit_diagnostic(diag); - } - } + #[track_caller] + pub fn create_warn<'a>( + &'a self, + warning: impl IntoDiagnostic<'a, ()>, + ) -> DiagnosticBuilder<'a, ()> { + warning.into_diagnostic(self, Warning) + } - inner - .stashed_diagnostics - .values_mut() - .for_each(|diag| diag.update_unstable_expectation_id(unstable_to_stable)); - inner - .future_breakage_diagnostics - .iter_mut() - .for_each(|diag| diag.update_unstable_expectation_id(unstable_to_stable)); + #[track_caller] + pub fn emit_warn<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) { + self.create_warn(warning).emit() } - /// This methods steals all [`LintExpectationId`]s that are stored inside - /// [`DiagCtxtInner`] and indicate that the linked expectation has been fulfilled. - #[must_use] - pub fn steal_fulfilled_expectation_ids(&self) -> FxHashSet { - assert!( - self.inner.borrow().unstable_expect_diagnostics.is_empty(), - "`DiagCtxtInner::unstable_expect_diagnostics` should be empty at this point", - ); - std::mem::take(&mut self.inner.borrow_mut().fulfilled_expectations) + /// Construct a builder at the `Note` level with the `msg`. + #[rustc_lint_diagnostics] + #[track_caller] + pub fn struct_note(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { + DiagnosticBuilder::new(self, Note, msg) } - pub fn flush_delayed(&self) { - self.inner.borrow_mut().flush_delayed(DelayedBugKind::Normal); + #[rustc_lint_diagnostics] + pub fn note(&self, msg: impl Into) { + self.struct_note(msg).emit() + } + + #[track_caller] + #[rustc_lint_diagnostics] + pub fn struct_span_note( + &self, + span: impl Into, + msg: impl Into, + ) -> DiagnosticBuilder<'_, ()> { + DiagnosticBuilder::new(self, Note, msg).with_span(span) + } + + #[track_caller] + #[rustc_lint_diagnostics] + pub fn span_note(&self, span: impl Into, msg: impl Into) { + self.struct_span_note(span, msg).emit() + } + + #[track_caller] + pub fn create_note<'a>( + &'a self, + note: impl IntoDiagnostic<'a, ()>, + ) -> DiagnosticBuilder<'a, ()> { + note.into_diagnostic(self, Note) + } + + #[track_caller] + pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, ()>) { + self.create_note(note).emit() + } + + /// Construct a builder at the `Help` level with the `msg`. + #[rustc_lint_diagnostics] + pub fn struct_help(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { + DiagnosticBuilder::new(self, Help, msg) + } + + /// Construct a builder at the `Allow` level with the `msg`. + #[rustc_lint_diagnostics] + #[track_caller] + pub fn struct_allow(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { + DiagnosticBuilder::new(self, Allow, msg) + } + + /// Construct a builder at the `Expect` level with the `msg`. + #[rustc_lint_diagnostics] + #[track_caller] + pub fn struct_expect( + &self, + msg: impl Into, + id: LintExpectationId, + ) -> DiagnosticBuilder<'_, ()> { + DiagnosticBuilder::new(self, Expect(id), msg) } } From b7b6ebca0c0fb38575ae7a48cd324a6008cba3d4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 8 Feb 2024 16:09:30 +1100 Subject: [PATCH 11/18] Fix inconsistencies in the diagnostic API methods. - Remove low-value comments about functionality that is obvious. - Add missing `track_caller` attributes -- every method should have one. - Adjust `rustc_lint_diagnostic` attributes. Every method involving a `impl Into` or `impl Into` argument should have one, except for those producing bugs, which aren't user-facing. --- compiler/rustc_errors/src/lib.rs | 53 +++++++++++++------------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 4c0bb763dc180..192df36248e0e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -945,20 +945,19 @@ impl DiagCtxt { // Functions beginning with `struct_`/`create_` create a diagnostic. Other // functions create and emit a diagnostic all in one go. impl DiagCtxt { - /// Construct a builder at the `Bug` level with the `msg`. - #[rustc_lint_diagnostics] + // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. #[track_caller] pub fn struct_bug(&self, msg: impl Into) -> DiagnosticBuilder<'_, BugAbort> { DiagnosticBuilder::new(self, Bug, msg) } - #[rustc_lint_diagnostics] + // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. + #[track_caller] pub fn bug(&self, msg: impl Into) -> ! { self.struct_bug(msg).emit() } - /// Construct a builder at the `Bug` level at the given `span` with the `msg`. - #[rustc_lint_diagnostics] + // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. #[track_caller] pub fn struct_span_bug( &self, @@ -968,6 +967,8 @@ impl DiagCtxt { self.struct_bug(msg).with_span(span) } + // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. + #[track_caller] pub fn span_bug(&self, span: impl Into, msg: impl Into) -> ! { self.struct_span_bug(span, msg).emit() } @@ -981,11 +982,10 @@ impl DiagCtxt { } #[track_caller] - pub fn emit_bug<'a>(&'a self, bug: impl IntoDiagnostic<'a, diagnostic_builder::BugAbort>) -> ! { + pub fn emit_bug<'a>(&'a self, bug: impl IntoDiagnostic<'a, BugAbort>) -> ! { self.create_bug(bug).emit() } - /// Construct a builder at the `Fatal` level with the `msg`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_fatal( @@ -996,11 +996,11 @@ impl DiagCtxt { } #[rustc_lint_diagnostics] + #[track_caller] pub fn fatal(&self, msg: impl Into) -> ! { self.struct_fatal(msg).emit() } - /// Construct a builder at the `Fatal` level at the given `span` and with the `msg`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_span_fatal( @@ -1046,7 +1046,6 @@ impl DiagCtxt { self.create_almost_fatal(fatal).emit() } - /// Construct a builder at the `Error` level with the `msg`. // FIXME: This method should be removed (every error should have an associated error code). #[rustc_lint_diagnostics] #[track_caller] @@ -1055,11 +1054,11 @@ impl DiagCtxt { } #[rustc_lint_diagnostics] + #[track_caller] pub fn err(&self, msg: impl Into) -> ErrorGuaranteed { self.struct_err(msg).emit() } - /// Construct a builder at the `Error` level at the given `span` and with the `msg`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_span_err( @@ -1090,24 +1089,18 @@ impl DiagCtxt { self.create_err(err).emit() } - /// Ensures that compilation cannot succeed. - /// - /// If this function has been called but no errors have been emitted and - /// compilation succeeds, it will cause an internal compiler error (ICE). - /// - /// This can be used in code paths that should never run on successful compilations. - /// For example, it can be used to create an [`ErrorGuaranteed`] - /// (but you should prefer threading through the [`ErrorGuaranteed`] from an error emission - /// directly). + /// Ensures that an error is printed. See `Level::DelayedBug`. + // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. #[track_caller] pub fn delayed_bug(&self, msg: impl Into) -> ErrorGuaranteed { DiagnosticBuilder::::new(self, DelayedBug, msg).emit() } - /// Like `delayed_bug`, but takes an additional span. + /// Ensures that an error is printed. See `Level::DelayedBug`. /// /// Note: this function used to be called `delay_span_bug`. It was renamed /// to match similar functions like `span_err`, `span_warn`, etc. + // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. #[track_caller] pub fn span_delayed_bug( &self, @@ -1118,13 +1111,12 @@ impl DiagCtxt { } /// Ensures that a diagnostic is printed. See `Level::GoodPathDelayedBug`. + // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. + #[track_caller] pub fn good_path_delayed_bug(&self, msg: impl Into) { DiagnosticBuilder::<()>::new(self, GoodPathDelayedBug, msg).emit() } - /// Construct a builder at the `Warning` level with the `msg`. - /// - /// An `emit` call on the builder will only emit if `can_emit_warnings` is `true`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_warn(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { @@ -1132,13 +1124,11 @@ impl DiagCtxt { } #[rustc_lint_diagnostics] + #[track_caller] pub fn warn(&self, msg: impl Into) { self.struct_warn(msg).emit() } - /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. - /// - /// An `emit` call on the builder will only emit if `can_emit_warnings` is `true`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_span_warn( @@ -1168,7 +1158,6 @@ impl DiagCtxt { self.create_warn(warning).emit() } - /// Construct a builder at the `Note` level with the `msg`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_note(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { @@ -1176,12 +1165,13 @@ impl DiagCtxt { } #[rustc_lint_diagnostics] + #[track_caller] pub fn note(&self, msg: impl Into) { self.struct_note(msg).emit() } - #[track_caller] #[rustc_lint_diagnostics] + #[track_caller] pub fn struct_span_note( &self, span: impl Into, @@ -1190,8 +1180,8 @@ impl DiagCtxt { DiagnosticBuilder::new(self, Note, msg).with_span(span) } - #[track_caller] #[rustc_lint_diagnostics] + #[track_caller] pub fn span_note(&self, span: impl Into, msg: impl Into) { self.struct_span_note(span, msg).emit() } @@ -1209,20 +1199,18 @@ impl DiagCtxt { self.create_note(note).emit() } - /// Construct a builder at the `Help` level with the `msg`. #[rustc_lint_diagnostics] + #[track_caller] pub fn struct_help(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { DiagnosticBuilder::new(self, Help, msg) } - /// Construct a builder at the `Allow` level with the `msg`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_allow(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { DiagnosticBuilder::new(self, Allow, msg) } - /// Construct a builder at the `Expect` level with the `msg`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_expect( @@ -1589,6 +1577,7 @@ pub enum Level { ForceWarning(Option), /// A warning about the code being compiled. Does not prevent compilation from finishing. + /// Will be skipped if `can_emit_warnings` is false. Warning, /// A message giving additional context. From 2bcbc16caf17351ef3f8d5e9faee98b48387d589 Mon Sep 17 00:00:00 2001 From: yukang Date: Sun, 11 Feb 2024 14:47:30 +0800 Subject: [PATCH 12/18] remove a bunch of dead parameters in fn --- .../src/diagnostics/conflict_errors.rs | 1 - compiler/rustc_borrowck/src/lib.rs | 3 +-- compiler/rustc_borrowck/src/path_utils.rs | 1 - .../src/polonius/loan_invalidations.rs | 1 - .../rustc_borrowck/src/region_infer/mod.rs | 6 +++--- .../src/transform/check_consts/resolver.rs | 8 +++----- .../rustc_hir_analysis/src/check/region.rs | 9 ++------- .../src/impl_wf_check/min_specialization.rs | 6 +----- compiler/rustc_hir_typeck/src/expr.rs | 3 +-- .../rustc_hir_typeck/src/expr_use_visitor.rs | 2 +- .../rustc_hir_typeck/src/mem_categorization.rs | 18 ++++++------------ compiler/rustc_mir_transform/src/coroutine.rs | 4 ++-- .../rustc_mir_transform/src/instsimplify.rs | 15 ++++----------- compiler/rustc_passes/src/check_attr.rs | 4 ++-- .../src/typeid/typeid_itanium_cxx_abi.rs | 14 ++++---------- .../error_reporting/type_err_ctxt_ext.rs | 6 ------ 16 files changed, 30 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index f87269960bc84..d764374a5c9ca 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -3020,7 +3020,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// assignment to `x.f`). pub(crate) fn report_illegal_reassignment( &mut self, - _location: Location, (place, span): (Place<'tcx>, Span), assigned_span: Span, err_place: Place<'tcx>, diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 4dba34c11f945..e8ffab9307eb5 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1036,7 +1036,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self, self.infcx.tcx, self.body, - location, (sd, place_span.0), &borrow_set, |borrow_index| borrows_in_scope.contains(borrow_index), @@ -2174,7 +2173,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // report the error as an illegal reassignment let init = &self.move_data.inits[init_index]; let assigned_span = init.span(self.body); - self.report_illegal_reassignment(location, (place, span), assigned_span, place); + self.report_illegal_reassignment((place, span), assigned_span, place); } else { self.report_mutability_error(place, span, the_place_err, error_access, location) } diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs index adafad7fa2fde..88b20bba9fb03 100644 --- a/compiler/rustc_borrowck/src/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -27,7 +27,6 @@ pub(super) fn each_borrow_involving_path<'tcx, F, I, S>( s: &mut S, tcx: TyCtxt<'tcx>, body: &Body<'tcx>, - _location: Location, access_place: (AccessDepth, Place<'tcx>), borrow_set: &BorrowSet<'tcx>, is_candidate: I, diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index 93aae1a7f9762..10941cadcbb25 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -340,7 +340,6 @@ impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> { self, self.tcx, self.body, - location, (sd, place), self.borrow_set, |_| true, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 3153b709ffe38..34d60fc8f6e17 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -662,7 +662,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { polonius_output: Option>, ) -> (Option>, RegionErrors<'tcx>) { let mir_def_id = body.source.def_id(); - self.propagate_constraints(body); + self.propagate_constraints(); let mut errors_buffer = RegionErrors::new(infcx.tcx); @@ -716,8 +716,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// for each region variable until all the constraints are /// satisfied. Note that some values may grow **too** large to be /// feasible, but we check this later. - #[instrument(skip(self, _body), level = "debug")] - fn propagate_constraints(&mut self, _body: &Body<'tcx>) { + #[instrument(skip(self), level = "debug")] + fn propagate_constraints(&mut self) { debug!("constraints={:#?}", { let mut constraints: Vec<_> = self.outlives_constraints().collect(); constraints.sort_by_key(|c| (c.sup, c.sub)); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs index a23922c778ff0..2c835f6750f75 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs @@ -96,7 +96,7 @@ where }); } - fn address_of_allows_mutation(&self, _mt: mir::Mutability, _place: mir::Place<'tcx>) -> bool { + fn address_of_allows_mutation(&self) -> bool { // Exact set of permissions granted by AddressOf is undecided. Conservatively assume that // it might allow mutation until resolution of #56604. true @@ -171,10 +171,8 @@ where self.super_rvalue(rvalue, location); match rvalue { - mir::Rvalue::AddressOf(mt, borrowed_place) => { - if !borrowed_place.is_indirect() - && self.address_of_allows_mutation(*mt, *borrowed_place) - { + mir::Rvalue::AddressOf(_mt, borrowed_place) => { + if !borrowed_place.is_indirect() && self.address_of_allows_mutation() { let place_ty = borrowed_place.ty(self.ccx.body, self.ccx.tcx).ty; if Q::in_any_value_of_ty(self.ccx, place_ty) { self.state.qualif.insert(borrowed_place.local); diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 1c0a1a6951398..0f5fd7e99b776 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -16,7 +16,6 @@ use rustc_index::Idx; use rustc_middle::middle::region::*; use rustc_middle::ty::TyCtxt; use rustc_span::source_map; -use rustc_span::Span; use super::errs::{maybe_expr_static_mut, maybe_stmt_static_mut}; @@ -72,11 +71,7 @@ struct RegionResolutionVisitor<'tcx> { } /// Records the lifetime of a local variable as `cx.var_parent` -fn record_var_lifetime( - visitor: &mut RegionResolutionVisitor<'_>, - var_id: hir::ItemLocalId, - _sp: Span, -) { +fn record_var_lifetime(visitor: &mut RegionResolutionVisitor<'_>, var_id: hir::ItemLocalId) { match visitor.cx.var_parent { None => { // this can happen in extern fn declarations like @@ -210,7 +205,7 @@ fn resolve_pat<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, pat: &'tcx hir // If this is a binding then record the lifetime of that binding. if let PatKind::Binding(..) = pat.kind { - record_var_lifetime(visitor, pat.hir_id.local_id, pat.span); + record_var_lifetime(visitor, pat.hir_id.local_id); } debug!("resolve_pat - pre-increment {} pat = {:?}", visitor.expr_and_pat_count, pat); diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 1b6a39d8162e0..ec8ea77b74960 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -425,9 +425,7 @@ fn check_predicates<'tcx>( let mut res = Ok(()); for (clause, span) in impl1_predicates { - if !impl2_predicates - .iter() - .any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span)) + if !impl2_predicates.iter().any(|pred2| trait_predicates_eq(clause.as_predicate(), *pred2)) { res = res.and(check_specialization_on(tcx, clause, span)) } @@ -459,10 +457,8 @@ fn check_predicates<'tcx>( /// /// So we make that check in this function and try to raise a helpful error message. fn trait_predicates_eq<'tcx>( - _tcx: TyCtxt<'tcx>, predicate1: ty::Predicate<'tcx>, predicate2: ty::Predicate<'tcx>, - _span: Span, ) -> bool { // FIXME(effects) predicate1 == predicate2 diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 292b85eb97f7f..71d1cef3c9b60 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -346,7 +346,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ExprKind::DropTemps(e) => self.check_expr_with_expectation(e, expected), ExprKind::Array(args) => self.check_expr_array(args, expected, expr), - ExprKind::ConstBlock(ref block) => self.check_expr_const_block(block, expected, expr), + ExprKind::ConstBlock(ref block) => self.check_expr_const_block(block, expected), ExprKind::Repeat(element, ref count) => { self.check_expr_repeat(element, count, expected, expr) } @@ -1493,7 +1493,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, block: &'tcx hir::ConstBlock, expected: Expectation<'tcx>, - _expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let body = self.tcx.hir().body(block.body); diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 3ecf6c5e428be..04fb7bcf4f3b4 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -142,7 +142,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { let param_ty = return_if_err!(self.mc.pat_ty_adjusted(param.pat)); debug!("consume_body: param_ty = {:?}", param_ty); - let param_place = self.mc.cat_rvalue(param.hir_id, param.pat.span, param_ty); + let param_place = self.mc.cat_rvalue(param.hir_id, param_ty); self.walk_irrefutable_pat(¶m_place, param.pat); } diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index f9297550c573c..fefaf9967253b 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -273,7 +273,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { deref.region, ty::TypeAndMut { ty: target, mutbl: deref.mutbl }, ); - self.cat_rvalue(expr.hir_id, expr.span, ref_ty) + self.cat_rvalue(expr.hir_id, ref_ty) } else { previous()? }; @@ -285,7 +285,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { | adjustment::Adjust::Borrow(_) | adjustment::Adjust::DynStar => { // Result is an rvalue. - Ok(self.cat_rvalue(expr.hir_id, expr.span, target)) + Ok(self.cat_rvalue(expr.hir_id, target)) } } } @@ -374,7 +374,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { | hir::ExprKind::Repeat(..) | hir::ExprKind::InlineAsm(..) | hir::ExprKind::OffsetOf(..) - | hir::ExprKind::Err(_) => Ok(self.cat_rvalue(expr.hir_id, expr.span, expr_ty)), + | hir::ExprKind::Err(_) => Ok(self.cat_rvalue(expr.hir_id, expr_ty)), } } @@ -396,7 +396,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { | DefKind::AssocFn, _, ) - | Res::SelfCtor(..) => Ok(self.cat_rvalue(hir_id, span, expr_ty)), + | Res::SelfCtor(..) => Ok(self.cat_rvalue(hir_id, expr_ty)), Res::Def(DefKind::Static(_), _) => { Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::StaticItem, Vec::new())) @@ -433,13 +433,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } #[instrument(level = "debug", skip(self), ret)] - pub(crate) fn cat_rvalue( - &self, - hir_id: hir::HirId, - // FIXME: remove - _span: Span, - expr_ty: Ty<'tcx>, - ) -> PlaceWithHirId<'tcx> { + pub(crate) fn cat_rvalue(&self, hir_id: hir::HirId, expr_ty: Ty<'tcx>) -> PlaceWithHirId<'tcx> { PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new()) } @@ -487,7 +481,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { }; let ref_ty = Ty::new_ref(self.tcx(), region, ty::TypeAndMut { ty: place_ty, mutbl }); - let base = self.cat_rvalue(expr.hir_id, expr.span, ref_ty); + let base = self.cat_rvalue(expr.hir_id, ref_ty); self.cat_deref(expr, base) } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 297b2fa143de2..a0851aa557b86 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -726,7 +726,7 @@ fn replace_resume_ty_local<'tcx>( /// The async lowering step and the type / lifetime inference / checking are /// still using the `resume` argument for the time being. After this transform, /// the coroutine body doesn't have the `resume` argument. -fn transform_gen_context<'tcx>(_tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +fn transform_gen_context<'tcx>(body: &mut Body<'tcx>) { // This leaves the local representing the `resume` argument in place, // but turns it into a regular local variable. This is cheaper than // adjusting all local references in the body after removing it. @@ -1733,7 +1733,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { // Remove the context argument within generator bodies. if matches!(coroutine_kind, CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) { - transform_gen_context(tcx, body); + transform_gen_context(body); } // The original arguments to the function are no longer arguments, mark them as such. diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index f65eb5cbea938..06df89c10370d 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -29,17 +29,14 @@ impl<'tcx> MirPass<'tcx> for InstSimplify { ctx.simplify_bool_cmp(&statement.source_info, rvalue); ctx.simplify_ref_deref(&statement.source_info, rvalue); ctx.simplify_len(&statement.source_info, rvalue); - ctx.simplify_cast(&statement.source_info, rvalue); + ctx.simplify_cast(rvalue); } _ => {} } } ctx.simplify_primitive_clone(block.terminator.as_mut().unwrap(), &mut block.statements); - ctx.simplify_intrinsic_assert( - block.terminator.as_mut().unwrap(), - &mut block.statements, - ); + ctx.simplify_intrinsic_assert(block.terminator.as_mut().unwrap()); ctx.simplify_nounwind_call(block.terminator.as_mut().unwrap()); simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap()); } @@ -143,7 +140,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { } } - fn simplify_cast(&self, _source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) { + fn simplify_cast(&self, rvalue: &mut Rvalue<'tcx>) { if let Rvalue::Cast(kind, operand, cast_ty) = rvalue { let operand_ty = operand.ty(self.local_decls, self.tcx); if operand_ty == *cast_ty { @@ -277,11 +274,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { } } - fn simplify_intrinsic_assert( - &self, - terminator: &mut Terminator<'tcx>, - _statements: &mut Vec>, - ) { + fn simplify_intrinsic_assert(&self, terminator: &mut Terminator<'tcx>) { let TerminatorKind::Call { func, target, .. } = &mut terminator.kind else { return; }; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ec704dec352da..d771a97ec59a6 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -197,7 +197,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::unstable | sym::stable | sym::rustc_allowed_through_unstable_modules - | sym::rustc_promotable => self.check_stability_promotable(attr, span, target), + | sym::rustc_promotable => self.check_stability_promotable(attr, target), sym::link_ordinal => self.check_link_ordinal(attr, span, target), sym::rustc_confusables => self.check_confusables(attr, target), sym::rustc_safe_intrinsic => { @@ -2102,7 +2102,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_stability_promotable(&self, attr: &Attribute, _span: Span, target: Target) -> bool { + fn check_stability_promotable(&self, attr: &Attribute, target: Target) -> bool { match target { Target::Expression => { self.dcx().emit_err(errors::StabilityPromotable { attr_span: attr.span }); diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 9d1b92e106803..1a1aed61feda2 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -261,12 +261,7 @@ fn encode_predicates<'tcx>( } /// Encodes a region using the Itanium C++ ABI as a vendor extended type. -fn encode_region<'tcx>( - _tcx: TyCtxt<'tcx>, - region: Region<'tcx>, - dict: &mut FxHashMap, usize>, - _options: EncodeTyOptions, -) -> String { +fn encode_region<'tcx>(region: Region<'tcx>, dict: &mut FxHashMap, usize>) -> String { // u6region[I[][]E] as vendor extended type let mut s = String::new(); match region.kind() { @@ -314,7 +309,7 @@ fn encode_args<'tcx>( for arg in args { match arg.unpack() { GenericArgKind::Lifetime(region) => { - s.push_str(&encode_region(tcx, region, dict, options)); + s.push_str(&encode_region(region, dict)); } GenericArgKind::Type(ty) => { s.push_str(&encode_ty(tcx, ty, dict, options)); @@ -703,7 +698,7 @@ fn encode_ty<'tcx>( ty::DynStar => "u7dynstarI", }); s.push_str(&encode_predicates(tcx, predicates, dict, options)); - s.push_str(&encode_region(tcx, *region, dict, options)); + s.push_str(&encode_region(*region, dict)); s.push('E'); compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); typeid.push_str(&s); @@ -735,7 +730,6 @@ fn encode_ty<'tcx>( fn transform_predicates<'tcx>( tcx: TyCtxt<'tcx>, predicates: &List>, - _options: EncodeTyOptions, ) -> &'tcx List> { let predicates: Vec> = predicates .iter() @@ -967,7 +961,7 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio ty::Dynamic(predicates, _region, kind) => { ty = Ty::new_dynamic( tcx, - transform_predicates(tcx, predicates, options), + transform_predicates(tcx, predicates), tcx.lifetimes.re_erased, *kind, ); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 07e4fef9dd4f2..2e824060d1bb3 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -615,8 +615,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let UnsatisfiedConst(unsatisfied_const) = self .maybe_add_note_for_unsatisfied_const( - &obligation, - trait_ref, &trait_predicate, &mut err, span, @@ -1480,8 +1478,6 @@ pub(super) trait InferCtxtPrivExt<'tcx> { fn maybe_add_note_for_unsatisfied_const( &self, - obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, trait_predicate: &ty::PolyTraitPredicate<'tcx>, err: &mut Diagnostic, span: Span, @@ -3359,8 +3355,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn maybe_add_note_for_unsatisfied_const( &self, - _obligation: &PredicateObligation<'tcx>, - _trait_ref: ty::PolyTraitRef<'tcx>, _trait_predicate: &ty::PolyTraitPredicate<'tcx>, _err: &mut Diagnostic, _span: Span, From fc7693d63b2f3736b7d847c8c3d9c7219c4bea4a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 12 Feb 2024 04:51:21 +0000 Subject: [PATCH 13/18] Clean inlined type alias with correct param-env --- src/librustdoc/clean/mod.rs | 4 +++- .../rustdoc-ui/normalize-in-inlined-type-alias.rs | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc-ui/normalize-in-inlined-type-alias.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 89977934cde9f..abd0b3562d211 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1840,7 +1840,9 @@ fn maybe_expand_private_type_alias<'tcx>( } } - Some(cx.enter_alias(args, def_id.to_def_id(), |cx| clean_ty(&ty, cx))) + Some(cx.enter_alias(args, def_id.to_def_id(), |cx| { + cx.with_param_env(def_id.to_def_id(), |cx| clean_ty(&ty, cx)) + })) } pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type { diff --git a/tests/rustdoc-ui/normalize-in-inlined-type-alias.rs b/tests/rustdoc-ui/normalize-in-inlined-type-alias.rs new file mode 100644 index 0000000000000..45e04a70c0913 --- /dev/null +++ b/tests/rustdoc-ui/normalize-in-inlined-type-alias.rs @@ -0,0 +1,14 @@ +// check-pass +// compile-flags: -Znormalize-docs + +trait Woo { + type Assoc; +} + +impl Woo for () { + type Assoc = (); +} + +type Alias

= <() as Woo

>::Assoc; + +pub fn hello() -> Alias {} From 30774b00610bb3ab3339931f5eba21574d35a39a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 9 Feb 2024 16:12:18 +1100 Subject: [PATCH 14/18] Remove final unwanted `unchecked_error_guaranteed` calls. Now that error counts can't go up and down due to stashing/stealing, we have a nice property: (err_count > 0) iff (an ErrorGuaranteed has been produced) So we can now record `ErrorGuaranteed`s within `DiagCtxt` and use that in methods like `has_error`, instead of checking that the count is greater than 0 and calling `unchecked_error_guaranteed` to create the `ErrorGuaranteed`. In fact, we can record a `Vec` and use its length to count the number, instead of maintaining a separate count. --- compiler/rustc_errors/src/lib.rs | 118 +++++++++++++++++-------------- 1 file changed, 65 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index ab3ad0e9d6843..fc5a8ef13f0b8 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -428,10 +428,14 @@ pub struct DiagCtxt { struct DiagCtxtInner { flags: DiagCtxtFlags, - /// The number of lint errors that have been emitted, including duplicates. - lint_err_count: usize, - /// The number of non-lint errors that have been emitted, including duplicates. - err_count: usize, + /// The error guarantees from all emitted errors. The length gives the error count. + err_guars: Vec, + /// The error guarantee from all emitted lint errors. The length gives the + /// lint error count. + lint_err_guars: Vec, + /// The delayed bugs and their error guarantees. + delayed_bugs: Vec<(DelayedDiagnostic, ErrorGuaranteed)>, + good_path_delayed_bugs: Vec, /// The number of stashed errors. Unlike the other counts, this can go up /// and down, so it doesn't guarantee anything. @@ -447,8 +451,6 @@ struct DiagCtxtInner { has_printed: bool, emitter: Box, - delayed_bugs: Vec, - good_path_delayed_bugs: Vec, /// This flag indicates that an expected diagnostic was emitted and suppressed. /// This is used for the `good_path_delayed_bugs` check. suppressed_expected_diag: bool, @@ -560,7 +562,7 @@ impl Drop for DiagCtxtInner { fn drop(&mut self) { self.emit_stashed_diagnostics(); - if !self.has_errors() { + if self.err_guars.is_empty() { self.flush_delayed(DelayedBugKind::Normal) } @@ -604,15 +606,15 @@ impl DiagCtxt { Self { inner: Lock::new(DiagCtxtInner { flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() }, - lint_err_count: 0, - err_count: 0, + err_guars: Vec::new(), + lint_err_guars: Vec::new(), + delayed_bugs: Vec::new(), + good_path_delayed_bugs: Vec::new(), stashed_err_count: 0, deduplicated_err_count: 0, deduplicated_warn_count: 0, has_printed: false, emitter, - delayed_bugs: Vec::new(), - good_path_delayed_bugs: Vec::new(), suppressed_expected_diag: false, taught_diagnostics: Default::default(), emitted_diagnostic_codes: Default::default(), @@ -661,14 +663,14 @@ impl DiagCtxt { /// the overall count of emitted error diagnostics. pub fn reset_err_count(&self) { let mut inner = self.inner.borrow_mut(); - inner.lint_err_count = 0; - inner.err_count = 0; inner.stashed_err_count = 0; inner.deduplicated_err_count = 0; inner.deduplicated_warn_count = 0; inner.has_printed = false; // actually free the underlying memory (which `clear` would not do) + inner.err_guars = Default::default(); + inner.lint_err_guars = Default::default(); inner.delayed_bugs = Default::default(); inner.good_path_delayed_bugs = Default::default(); inner.taught_diagnostics = Default::default(); @@ -932,7 +934,7 @@ impl DiagCtxt { /// This excludes lint errors, delayed bugs, and stashed errors. #[inline] pub fn err_count(&self) -> usize { - self.inner.borrow().err_count + self.inner.borrow().err_guars.len() } /// This excludes normal errors, lint errors and delayed bugs. Unless @@ -946,36 +948,19 @@ impl DiagCtxt { /// This excludes lint errors, delayed bugs, and stashed errors. pub fn has_errors(&self) -> Option { - self.inner.borrow().has_errors().then(|| { - // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. - #[allow(deprecated)] - ErrorGuaranteed::unchecked_error_guaranteed() - }) + self.inner.borrow().has_errors() } /// This excludes delayed bugs and stashed errors. Unless absolutely /// necessary, prefer `has_errors` to this method. pub fn has_errors_or_lint_errors(&self) -> Option { - let inner = self.inner.borrow(); - let result = inner.has_errors() || inner.lint_err_count > 0; - result.then(|| { - // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. - #[allow(deprecated)] - ErrorGuaranteed::unchecked_error_guaranteed() - }) + self.inner.borrow().has_errors_or_lint_errors() } /// This excludes stashed errors. Unless absolutely necessary, prefer /// `has_errors` or `has_errors_or_lint_errors` to this method. pub fn has_errors_or_lint_errors_or_delayed_bugs(&self) -> Option { - let inner = self.inner.borrow(); - let result = - inner.has_errors() || inner.lint_err_count > 0 || !inner.delayed_bugs.is_empty(); - result.then(|| { - // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. - #[allow(deprecated)] - ErrorGuaranteed::unchecked_error_guaranteed() - }) + self.inner.borrow().has_errors_or_lint_errors_or_delayed_bugs() } pub fn print_error_count(&self, registry: &Registry) { @@ -1055,7 +1040,7 @@ impl DiagCtxt { pub fn abort_if_errors(&self) { let mut inner = self.inner.borrow_mut(); inner.emit_stashed_diagnostics(); - if inner.has_errors() { + if !inner.err_guars.is_empty() { FatalError.raise(); } } @@ -1175,8 +1160,21 @@ impl DiagCtxt { ) { let mut inner = self.inner.borrow_mut(); + // This "error" is an odd duck. + // - It's only produce with JSON output. + // - It's not emitted the usual way, via `emit_diagnostic`. + // - The `$message_type` field is "unused_externs" rather than the usual + // "diagnosic". + // + // We count it as a lint error because it has a lint level. The value + // of `loud` (which comes from "unused-externs" or + // "unused-externs-silent"), also affects whether it's treated like a + // hard error or not. if loud && lint_level.is_error() { - inner.lint_err_count += 1; + // This `unchecked_error_guaranteed` is valid. It is where the + // `ErrorGuaranteed` for unused_extern errors originates. + #[allow(deprecated)] + inner.lint_err_guars.push(ErrorGuaranteed::unchecked_error_guaranteed()); inner.panic_if_treat_err_as_bug(); } @@ -1236,7 +1234,7 @@ impl DiagCtxt { impl DiagCtxtInner { /// Emit all stashed diagnostics. fn emit_stashed_diagnostics(&mut self) { - let has_errors = self.has_errors(); + let has_errors = !self.err_guars.is_empty(); for (_, diag) in std::mem::take(&mut self.stashed_diagnostics).into_iter() { // Decrement the count tracking the stash; emitting will increment it. if diag.is_error() { @@ -1298,9 +1296,13 @@ impl DiagCtxtInner { // when an error is first emitted, also), but maybe there's a case // in which that's not sound? otherwise this is really inefficient. let backtrace = std::backtrace::Backtrace::capture(); - self.delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); + // This `unchecked_error_guaranteed` is valid. It is where the + // `ErrorGuaranteed` for delayed bugs originates. #[allow(deprecated)] - return Some(ErrorGuaranteed::unchecked_error_guaranteed()); + let guar = ErrorGuaranteed::unchecked_error_guaranteed(); + self.delayed_bugs + .push((DelayedDiagnostic::with_backtrace(diagnostic, backtrace), guar)); + return Some(guar); } GoodPathDelayedBug => { let backtrace = std::backtrace::Backtrace::capture(); @@ -1334,7 +1336,6 @@ impl DiagCtxtInner { !self.emitted_diagnostics.insert(diagnostic_hash) }; - let level = diagnostic.level; let is_error = diagnostic.is_error(); let is_lint = diagnostic.is_lint.is_some(); @@ -1373,36 +1374,47 @@ impl DiagCtxtInner { } if is_error { + // This `unchecked_error_guaranteed` is valid. It is where the + // `ErrorGuaranteed` for errors and lint errors originates. + #[allow(deprecated)] + let guar = ErrorGuaranteed::unchecked_error_guaranteed(); + guaranteed = Some(guar); if is_lint { - self.lint_err_count += 1; + self.lint_err_guars.push(guar); } else { - self.err_count += 1; + self.err_guars.push(guar); } self.panic_if_treat_err_as_bug(); } - - #[allow(deprecated)] - if level == Level::Error { - guaranteed = Some(ErrorGuaranteed::unchecked_error_guaranteed()); - } }); guaranteed } fn treat_err_as_bug(&self) -> bool { - self.flags.treat_err_as_bug.is_some_and(|c| self.err_count + self.lint_err_count >= c.get()) + self.flags + .treat_err_as_bug + .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() >= c.get()) } // Use this one before incrementing `err_count`. fn treat_next_err_as_bug(&self) -> bool { self.flags .treat_err_as_bug - .is_some_and(|c| self.err_count + self.lint_err_count + 1 >= c.get()) + .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() + 1 >= c.get()) + } + + fn has_errors(&self) -> Option { + self.err_guars.get(0).copied() + } + + fn has_errors_or_lint_errors(&self) -> Option { + self.has_errors().or_else(|| self.lint_err_guars.get(0).copied()) } - fn has_errors(&self) -> bool { - self.err_count > 0 + fn has_errors_or_lint_errors_or_delayed_bugs(&self) -> Option { + self.has_errors_or_lint_errors() + .or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied()) } fn failure_note(&mut self, msg: impl Into) { @@ -1412,7 +1424,7 @@ impl DiagCtxtInner { fn flush_delayed(&mut self, kind: DelayedBugKind) { let (bugs, note1) = match kind { DelayedBugKind::Normal => ( - std::mem::take(&mut self.delayed_bugs), + std::mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect(), "no errors encountered even though delayed bugs were created", ), DelayedBugKind::GoodPath => ( @@ -1477,7 +1489,7 @@ impl DiagCtxtInner { fn panic_if_treat_err_as_bug(&self) { if self.treat_err_as_bug() { let n = self.flags.treat_err_as_bug.map(|c| c.get()).unwrap(); - assert_eq!(n, self.err_count + self.lint_err_count); + assert_eq!(n, self.err_guars.len() + self.lint_err_guars.len()); if n == 1 { panic!("aborting due to `-Z treat-err-as-bug=1`"); } else { From e0a0cc29710828066da211abf605e6c75c7410fc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 12 Feb 2024 15:18:18 +1100 Subject: [PATCH 15/18] Remove `dcx` arg from `ReportErrorExt::add_args`. Because it also has a `DiagnosticBuilder` arg, which contains a `dcx` reference. Also rename some `builder` variables as `diag`, because that's the usual name. --- .../rustc_const_eval/src/const_eval/error.rs | 2 +- compiler/rustc_const_eval/src/errors.rs | 134 ++++++++---------- .../src/interpret/eval_context.rs | 2 +- 3 files changed, 62 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 71085c2b2a5cf..80d02589900f6 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -151,7 +151,7 @@ where let mut err = tcx.dcx().create_err(err); let msg = error.diagnostic_message(); - error.add_args(tcx.dcx(), &mut err); + error.add_args(&mut err); // Use *our* span to label the interp error err.span_label(our_span, msg); diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index a649526c1964a..11679ab77e351 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -426,7 +426,7 @@ pub struct UndefinedBehavior { pub trait ReportErrorExt { /// Returns the diagnostic message for this error. fn diagnostic_message(&self) -> DiagnosticMessage; - fn add_args(self, dcx: &DiagCtxt, builder: &mut DiagnosticBuilder<'_, G>); + fn add_args(self, diag: &mut DiagnosticBuilder<'_, G>); fn debug(self) -> String where @@ -434,11 +434,11 @@ pub trait ReportErrorExt { { ty::tls::with(move |tcx| { let dcx = tcx.dcx(); - let mut builder = dcx.struct_allow(DiagnosticMessage::Str(String::new().into())); + let mut diag = dcx.struct_allow(DiagnosticMessage::Str(String::new().into())); let message = self.diagnostic_message(); - self.add_args(dcx, &mut builder); - let s = dcx.eagerly_translate_to_string(message, builder.args()); - builder.cancel(); + self.add_args(&mut diag); + let s = dcx.eagerly_translate_to_string(message, diag.args()); + diag.cancel(); s }) } @@ -505,20 +505,17 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { } } - fn add_args( - self, - dcx: &DiagCtxt, - builder: &mut DiagnosticBuilder<'_, G>, - ) { + fn add_args(self, diag: &mut DiagnosticBuilder<'_, G>) { use UndefinedBehaviorInfo::*; + let dcx = diag.dcx; match self { Ub(_) => {} Custom(custom) => { (custom.add_args)(&mut |name, value| { - builder.arg(name, value); + diag.arg(name, value); }); } - ValidationError(e) => e.add_args(dcx, builder), + ValidationError(e) => e.add_args(diag), Unreachable | DivisionByZero @@ -533,20 +530,18 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { | UninhabitedEnumVariantWritten(_) | UninhabitedEnumVariantRead(_) => {} BoundsCheckFailed { len, index } => { - builder.arg("len", len); - builder.arg("index", index); + diag.arg("len", len); + diag.arg("index", index); } UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => { - builder.arg("pointer", ptr); + diag.arg("pointer", ptr); } PointerUseAfterFree(alloc_id, msg) => { - builder - .arg("alloc_id", alloc_id) + diag.arg("alloc_id", alloc_id) .arg("bad_pointer_message", bad_pointer_message(msg, dcx)); } PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => { - builder - .arg("alloc_id", alloc_id) + diag.arg("alloc_id", alloc_id) .arg("alloc_size", alloc_size.bytes()) .arg("ptr_offset", ptr_offset) .arg("ptr_size", ptr_size.bytes()) @@ -554,47 +549,47 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { } DanglingIntPointer(ptr, msg) => { if ptr != 0 { - builder.arg("pointer", format!("{ptr:#x}[noalloc]")); + diag.arg("pointer", format!("{ptr:#x}[noalloc]")); } - builder.arg("bad_pointer_message", bad_pointer_message(msg, dcx)); + diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx)); } AlignmentCheckFailed(Misalignment { required, has }, msg) => { - builder.arg("required", required.bytes()); - builder.arg("has", has.bytes()); - builder.arg("msg", format!("{msg:?}")); + diag.arg("required", required.bytes()); + diag.arg("has", has.bytes()); + diag.arg("msg", format!("{msg:?}")); } WriteToReadOnly(alloc) | DerefFunctionPointer(alloc) | DerefVTablePointer(alloc) => { - builder.arg("allocation", alloc); + diag.arg("allocation", alloc); } InvalidBool(b) => { - builder.arg("value", format!("{b:02x}")); + diag.arg("value", format!("{b:02x}")); } InvalidChar(c) => { - builder.arg("value", format!("{c:08x}")); + diag.arg("value", format!("{c:08x}")); } InvalidTag(tag) => { - builder.arg("tag", format!("{tag:x}")); + diag.arg("tag", format!("{tag:x}")); } InvalidStr(err) => { - builder.arg("err", format!("{err}")); + diag.arg("err", format!("{err}")); } InvalidUninitBytes(Some((alloc, info))) => { - builder.arg("alloc", alloc); - builder.arg("access", info.access); - builder.arg("uninit", info.bad); + diag.arg("alloc", alloc); + diag.arg("access", info.access); + diag.arg("uninit", info.bad); } ScalarSizeMismatch(info) => { - builder.arg("target_size", info.target_size); - builder.arg("data_size", info.data_size); + diag.arg("target_size", info.target_size); + diag.arg("data_size", info.data_size); } InvalidNichedEnumVariantWritten { enum_ty } => { - builder.arg("ty", enum_ty.to_string()); + diag.arg("ty", enum_ty.to_string()); } AbiMismatchArgument { caller_ty, callee_ty } | AbiMismatchReturn { caller_ty, callee_ty } => { - builder.arg("caller_ty", caller_ty.to_string()); - builder.arg("callee_ty", callee_ty.to_string()); + diag.arg("caller_ty", caller_ty.to_string()); + diag.arg("callee_ty", callee_ty.to_string()); } } } @@ -674,7 +669,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { } } - fn add_args(self, dcx: &DiagCtxt, err: &mut DiagnosticBuilder<'_, G>) { + fn add_args(self, err: &mut DiagnosticBuilder<'_, G>) { use crate::fluent_generated as fluent; use rustc_middle::mir::interpret::ValidationErrorKind::*; @@ -684,12 +679,12 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { } let message = if let Some(path) = self.path { - dcx.eagerly_translate_to_string( + err.dcx.eagerly_translate_to_string( fluent::const_eval_validation_front_matter_invalid_value_with_path, [("path".into(), DiagnosticArgValue::Str(path.into()))].iter().map(|(a, b)| (a, b)), ) } else { - dcx.eagerly_translate_to_string( + err.dcx.eagerly_translate_to_string( fluent::const_eval_validation_front_matter_invalid_value, [].into_iter(), ) @@ -700,7 +695,6 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { fn add_range_arg( r: WrappingRange, max_hi: u128, - dcx: &DiagCtxt, err: &mut DiagnosticBuilder<'_, G>, ) { let WrappingRange { start: lo, end: hi } = r; @@ -724,7 +718,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { ("hi".into(), DiagnosticArgValue::Str(hi.to_string().into())), ]; let args = args.iter().map(|(a, b)| (a, b)); - let message = dcx.eagerly_translate_to_string(msg, args); + let message = err.dcx.eagerly_translate_to_string(msg, args); err.arg("in_range", message); } @@ -746,7 +740,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { ExpectedKind::EnumTag => fluent::const_eval_validation_expected_enum_tag, ExpectedKind::Str => fluent::const_eval_validation_expected_str, }; - let msg = dcx.eagerly_translate_to_string(msg, [].into_iter()); + let msg = err.dcx.eagerly_translate_to_string(msg, [].into_iter()); err.arg("expected", msg); } InvalidEnumTag { value } @@ -757,11 +751,11 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { err.arg("value", value); } NullablePtrOutOfRange { range, max_value } | PtrOutOfRange { range, max_value } => { - add_range_arg(range, max_value, dcx, err) + add_range_arg(range, max_value, err) } OutOfRange { range, max_value, value } => { err.arg("value", value); - add_range_arg(range, max_value, dcx, err); + add_range_arg(range, max_value, err); } UnalignedPtr { required_bytes, found_bytes, .. } => { err.arg("required_bytes", required_bytes); @@ -802,13 +796,13 @@ impl ReportErrorExt for UnsupportedOpInfo { UnsupportedOpInfo::ExternStatic(_) => const_eval_extern_static, } } - fn add_args(self, _: &DiagCtxt, builder: &mut DiagnosticBuilder<'_, G>) { + fn add_args(self, diag: &mut DiagnosticBuilder<'_, G>) { use crate::fluent_generated::*; use UnsupportedOpInfo::*; if let ReadPointerAsInt(_) | OverwritePartialPointer(_) | ReadPartialPointer(_) = self { - builder.help(const_eval_ptr_as_bytes_1); - builder.help(const_eval_ptr_as_bytes_2); + diag.help(const_eval_ptr_as_bytes_1); + diag.help(const_eval_ptr_as_bytes_2); } match self { // `ReadPointerAsInt(Some(info))` is never printed anyway, it only serves as an error to @@ -816,10 +810,10 @@ impl ReportErrorExt for UnsupportedOpInfo { // print. So it's not worth the effort of having diagnostics that can print the `info`. UnsizedLocal | Unsupported(_) | ReadPointerAsInt(_) => {} OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => { - builder.arg("ptr", ptr); + diag.arg("ptr", ptr); } ThreadLocalStatic(did) | ExternStatic(did) => { - builder.arg("did", format!("{did:?}")); + diag.arg("did", format!("{did:?}")); } } } @@ -835,18 +829,14 @@ impl<'tcx> ReportErrorExt for InterpError<'tcx> { InterpError::MachineStop(e) => e.diagnostic_message(), } } - fn add_args( - self, - dcx: &DiagCtxt, - builder: &mut DiagnosticBuilder<'_, G>, - ) { + fn add_args(self, diag: &mut DiagnosticBuilder<'_, G>) { match self { - InterpError::UndefinedBehavior(ub) => ub.add_args(dcx, builder), - InterpError::Unsupported(e) => e.add_args(dcx, builder), - InterpError::InvalidProgram(e) => e.add_args(dcx, builder), - InterpError::ResourceExhaustion(e) => e.add_args(dcx, builder), + InterpError::UndefinedBehavior(ub) => ub.add_args(diag), + InterpError::Unsupported(e) => e.add_args(diag), + InterpError::InvalidProgram(e) => e.add_args(diag), + InterpError::ResourceExhaustion(e) => e.add_args(diag), InterpError::MachineStop(e) => e.add_args(&mut |name, value| { - builder.arg(name, value); + diag.arg(name, value); }), } } @@ -864,28 +854,24 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { } } } - fn add_args( - self, - dcx: &DiagCtxt, - builder: &mut DiagnosticBuilder<'_, G>, - ) { + fn add_args(self, diag: &mut DiagnosticBuilder<'_, G>) { match self { InvalidProgramInfo::TooGeneric | InvalidProgramInfo::AlreadyReported(_) => {} InvalidProgramInfo::Layout(e) => { - // The level doesn't matter, `diag` is consumed without it being used. + // The level doesn't matter, `dummy_diag` is consumed without it being used. let dummy_level = Level::Bug; - let diag: DiagnosticBuilder<'_, ()> = - e.into_diagnostic().into_diagnostic(dcx, dummy_level); - for (name, val) in diag.args() { - builder.arg(name.clone(), val.clone()); + let dummy_diag: DiagnosticBuilder<'_, ()> = + e.into_diagnostic().into_diagnostic(diag.dcx, dummy_level); + for (name, val) in dummy_diag.args() { + diag.arg(name.clone(), val.clone()); } - diag.cancel(); + dummy_diag.cancel(); } InvalidProgramInfo::FnAbiAdjustForForeignAbi( AdjustForForeignAbiError::Unsupported { arch, abi }, ) => { - builder.arg("arch", arch); - builder.arg("abi", abi.name()); + diag.arg("arch", arch); + diag.arg("abi", abi.name()); } } } @@ -900,7 +886,7 @@ impl ReportErrorExt for ResourceExhaustionInfo { ResourceExhaustionInfo::AddressSpaceFull => const_eval_address_space_full, } } - fn add_args(self, _: &DiagCtxt, _: &mut DiagnosticBuilder<'_, G>) {} + fn add_args(self, _: &mut DiagnosticBuilder<'_, G>) {} } impl rustc_errors::IntoDiagnosticArg for InternKind { diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index dd9dfe3fe7983..ff90059203ac5 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -445,7 +445,7 @@ pub fn format_interp_error<'tcx>(dcx: &DiagCtxt, e: InterpErrorInfo<'tcx>) -> St #[allow(rustc::untranslatable_diagnostic)] let mut diag = dcx.struct_allow(""); let msg = e.diagnostic_message(); - e.add_args(dcx, &mut diag); + e.add_args(&mut diag); let s = dcx.eagerly_translate_to_string(msg, diag.args()); diag.cancel(); s From d4b77f64e4085f06caf5bd4ef8ae3c64d681eeff Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 12 Feb 2024 15:26:59 +1100 Subject: [PATCH 16/18] Tweak delayed bug mentions. Now that we have both `delayed_bug` and `span_delayed_bug`, it makes sense to use the generic term "delayed bug" more. --- compiler/rustc_errors/src/lib.rs | 6 +++--- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 6 +++--- .../rustc_infer/src/infer/canonical/canonicalizer.rs | 2 +- compiler/rustc_interface/src/queries.rs | 6 +++--- compiler/rustc_middle/src/query/mod.rs | 6 +++--- compiler/rustc_middle/src/ty/region.rs | 8 ++++---- compiler/rustc_middle/src/ty/visit.rs | 2 +- compiler/rustc_middle/src/util/bug.rs | 12 ++++++------ compiler/rustc_span/src/symbol.rs | 2 +- src/tools/clippy/tests/integration.rs | 2 +- .../rust-analyzer/crates/hir-def/src/attr/builtin.rs | 2 +- tests/incremental/delayed_span_bug.rs | 4 ++-- tests/ui/treat-err-as-bug/span_delayed_bug.rs | 4 ++-- tests/ui/treat-err-as-bug/span_delayed_bug.stderr | 4 ++-- 15 files changed, 34 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index fc5a8ef13f0b8..2a68443ee38ed 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -411,8 +411,8 @@ impl CodeSuggestion { /// or `.span_bug` rather than a failed assertion, etc. pub struct ExplicitBug; -/// Signifies that the compiler died with an explicit call to `.delay_*_bug` -/// rather than a failed assertion, etc. +/// Signifies that the compiler died due to a delayed bug rather than a failed +/// assertion, etc. pub struct DelayedBugPanic; /// A `DiagCtxt` deals with errors and other compiler output. @@ -1446,7 +1446,7 @@ impl DiagCtxtInner { { let _ = write!( &mut out, - "delayed span bug: {}\n{}\n", + "delayed bug: {}\n{}\n", bug.inner .messages .iter() diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 019cc1c847e91..6aedd2a5e3341 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -806,7 +806,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing), rustc_attr!( TEST, rustc_error, Normal, - template!(Word, List: "span_delayed_bug_from_inside_query"), WarnFollowingWordOnly + template!(Word, List: "delayed_bug_from_inside_query"), WarnFollowingWordOnly ), rustc_attr!(TEST, rustc_dump_user_args, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing), diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 646a84b043c82..1bdfa452360cc 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -118,9 +118,9 @@ where return Err(err); } else { // HACK(oli-obk): tests/ui/specialization/min_specialization/specialize_on_type_error.rs - // causes an error (span_delayed_bug) during normalization, without reporting an error, - // so we need to act as if no error happened, in order to let our callers continue and - // report an error later in check_impl_items_against_trait. + // causes an delayed bug during normalization, without reporting an error, so we need + // to act as if no error happened, in order to let our callers continue and report an + // error later in check_impl_items_against_trait. return Ok(()); } } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 156a4f7101763..99882a42abc38 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -191,7 +191,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse { // // rust-lang/rust#57464: `impl Trait` can leak local // scopes (in manner violating typeck). Therefore, use - // `span_delayed_bug` to allow type error over an ICE. + // `delayed_bug` to allow type error over an ICE. canonicalizer .tcx .dcx() diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index e66ea6f2ca961..2a4eefb7f771b 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -194,16 +194,16 @@ impl<'tcx> Queries<'tcx> { let Some((def_id, _)) = tcx.entry_fn(()) else { return }; for attr in tcx.get_attrs(def_id, sym::rustc_error) { match attr.meta_item_list() { - // Check if there is a `#[rustc_error(span_delayed_bug_from_inside_query)]`. + // Check if there is a `#[rustc_error(delayed_bug_from_inside_query)]`. Some(list) if list.iter().any(|list_item| { matches!( list_item.ident().map(|i| i.name), - Some(sym::span_delayed_bug_from_inside_query) + Some(sym::delayed_bug_from_inside_query) ) }) => { - tcx.ensure().trigger_span_delayed_bug(def_id); + tcx.ensure().trigger_delayed_bug(def_id); } // Bare `#[rustc_error]`. diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 938fba0ed0981..5fe736c904735 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -108,9 +108,9 @@ pub use plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsure, TyCtxtEnsureWithValue // Queries marked with `fatal_cycle` do not need the latter implementation, // as they will raise an fatal error on query cycles instead. rustc_queries! { - /// This exists purely for testing the interactions between span_delayed_bug and incremental. - query trigger_span_delayed_bug(key: DefId) { - desc { "triggering a span delayed bug for testing incremental" } + /// This exists purely for testing the interactions between delayed bugs and incremental. + query trigger_delayed_bug(key: DefId) { + desc { "triggering a delayed bug for testing incremental" } } /// Collects the list of all tools registered using `#![register_tool]`. diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 75be380704e1f..1191d7fca32a4 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -82,8 +82,8 @@ impl<'tcx> Region<'tcx> { tcx.intern_region(ty::ReError(reported)) } - /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` to ensure it - /// gets used. + /// Constructs a `RegionKind::ReError` region and registers a delayed bug to ensure it gets + /// used. #[track_caller] pub fn new_error_misc(tcx: TyCtxt<'tcx>) -> Region<'tcx> { Region::new_error_with_message( @@ -93,8 +93,8 @@ impl<'tcx> Region<'tcx> { ) } - /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` with the given - /// `msg` to ensure it gets used. + /// Constructs a `RegionKind::ReError` region and registers a delayed bug with the given `msg` + /// to ensure it gets used. #[track_caller] pub fn new_error_with_message>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index a750a86d25707..7acdb931f1ae7 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -55,7 +55,7 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable> { } fn error_reported(&self) -> Result<(), ErrorGuaranteed> { if self.references_error() { - // We must include lint errors and span delayed bugs here. + // We must include lint errors and delayed bugs here. if let Some(reported) = ty::tls::with(|tcx| tcx.dcx().has_errors_or_lint_errors_or_delayed_bugs()) { diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs index d1a3dbbf5d3b9..a67ec99158210 100644 --- a/compiler/rustc_middle/src/util/bug.rs +++ b/compiler/rustc_middle/src/util/bug.rs @@ -38,16 +38,16 @@ fn opt_span_bug_fmt>( }) } -/// A query to trigger a `span_delayed_bug`. Clearly, if one has a `tcx` one can already trigger a -/// `span_delayed_bug`, so what is the point of this? It exists to help us test `span_delayed_bug`'s -/// interactions with the query system and incremental. -pub fn trigger_span_delayed_bug(tcx: TyCtxt<'_>, key: rustc_hir::def_id::DefId) { +/// A query to trigger a delayed bug. Clearly, if one has a `tcx` one can already trigger a +/// delayed bug, so what is the point of this? It exists to help us test the interaction of delayed +/// bugs with the query system and incremental. +pub fn trigger_delayed_bug(tcx: TyCtxt<'_>, key: rustc_hir::def_id::DefId) { tcx.dcx().span_delayed_bug( tcx.def_span(key), - "delayed span bug triggered by #[rustc_error(span_delayed_bug_from_inside_query)]", + "delayed bug triggered by #[rustc_error(delayed_bug_from_inside_query)]", ); } pub fn provide(providers: &mut crate::query::Providers) { - *providers = crate::query::Providers { trigger_span_delayed_bug, ..*providers }; + *providers = crate::query::Providers { trigger_delayed_bug, ..*providers }; } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index aa912c93c08c6..83eca6c032bbc 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -655,6 +655,7 @@ symbols! { default_method_body_is_const, default_type_parameter_fallback, default_type_params, + delayed_bug_from_inside_query, deny, deprecated, deprecated_safe, @@ -1579,7 +1580,6 @@ symbols! { slice_patterns, slicing_syntax, soft, - span_delayed_bug_from_inside_query, specialization, speed, spotlight, diff --git a/src/tools/clippy/tests/integration.rs b/src/tools/clippy/tests/integration.rs index 267f095f9c20f..7f4500826ff6c 100644 --- a/src/tools/clippy/tests/integration.rs +++ b/src/tools/clippy/tests/integration.rs @@ -77,7 +77,7 @@ fn integration_test() { // the repo basically just contains a span_delayed_bug that forces rustc/clippy to panic: /* #![feature(rustc_attrs)] - #[rustc_error(span_delayed_bug_from_inside_query)] + #[rustc_error(delayed_bug_from_inside_query)] fn main() {} */ diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs index b20ee9e5bf6c8..55b9a1dfdcb91 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs @@ -650,7 +650,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing), rustc_attr!( TEST, rustc_error, Normal, - template!(Word, List: "span_delayed_bug_from_inside_query"), WarnFollowingWordOnly + template!(Word, List: "delayed_bug_from_inside_query"), WarnFollowingWordOnly ), rustc_attr!(TEST, rustc_dump_user_args, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing), diff --git a/tests/incremental/delayed_span_bug.rs b/tests/incremental/delayed_span_bug.rs index cc9831fff96d5..5c9d3c2c1d52f 100644 --- a/tests/incremental/delayed_span_bug.rs +++ b/tests/incremental/delayed_span_bug.rs @@ -1,8 +1,8 @@ // revisions: cfail1 cfail2 // should-ice -// error-pattern: delayed span bug triggered by #[rustc_error(span_delayed_bug_from_inside_query)] +// error-pattern: delayed bug triggered by #[rustc_error(delayed_bug_from_inside_query)] #![feature(rustc_attrs)] -#[rustc_error(span_delayed_bug_from_inside_query)] +#[rustc_error(delayed_bug_from_inside_query)] fn main() {} diff --git a/tests/ui/treat-err-as-bug/span_delayed_bug.rs b/tests/ui/treat-err-as-bug/span_delayed_bug.rs index 8b9526bf3f966..1ea14aee6c459 100644 --- a/tests/ui/treat-err-as-bug/span_delayed_bug.rs +++ b/tests/ui/treat-err-as-bug/span_delayed_bug.rs @@ -1,12 +1,12 @@ // compile-flags: -Ztreat-err-as-bug -Zeagerly-emit-delayed-bugs // failure-status: 101 // error-pattern: aborting due to `-Z treat-err-as-bug=1` -// error-pattern: [trigger_span_delayed_bug] triggering a span delayed bug for testing incremental +// error-pattern: [trigger_delayed_bug] triggering a delayed bug for testing incremental // normalize-stderr-test "note: .*\n\n" -> "" // normalize-stderr-test "thread 'rustc' panicked.*:\n.*\n" -> "" // rustc-env:RUST_BACKTRACE=0 #![feature(rustc_attrs)] -#[rustc_error(span_delayed_bug_from_inside_query)] +#[rustc_error(delayed_bug_from_inside_query)] fn main() {} diff --git a/tests/ui/treat-err-as-bug/span_delayed_bug.stderr b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr index a61ffaea8c242..f0e8cd0ddb961 100644 --- a/tests/ui/treat-err-as-bug/span_delayed_bug.stderr +++ b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr @@ -1,4 +1,4 @@ -error: internal compiler error: delayed span bug triggered by #[rustc_error(span_delayed_bug_from_inside_query)] +error: internal compiler error: delayed bug triggered by #[rustc_error(delayed_bug_from_inside_query)] --> $DIR/span_delayed_bug.rs:12:1 | LL | fn main() {} @@ -7,5 +7,5 @@ LL | fn main() {} error: the compiler unexpectedly panicked. this is a bug. query stack during panic: -#0 [trigger_span_delayed_bug] triggering a span delayed bug for testing incremental +#0 [trigger_delayed_bug] triggering a delayed bug for testing incremental end of query stack From 1f39c8b08f2a9d30916a77beaf518f8d58d13a62 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 12 Feb 2024 16:34:39 +1100 Subject: [PATCH 17/18] Change level used in `print_error_count`. From `Fatal` to `Error`. It has no functional effect, but `Error` makes more sense and lines up better with the `Warning` level used just above. --- compiler/rustc_errors/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 2a68443ee38ed..16077b3d98fa6 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -993,10 +993,10 @@ impl DiagCtxt { .emit_diagnostic(Diagnostic::new(Warning, DiagnosticMessage::Str(warnings))); } (_, 0) => { - inner.emit_diagnostic(Diagnostic::new(Fatal, errors)); + inner.emit_diagnostic(Diagnostic::new(Error, errors)); } (_, _) => { - inner.emit_diagnostic(Diagnostic::new(Fatal, format!("{errors}; {warnings}"))); + inner.emit_diagnostic(Diagnostic::new(Error, format!("{errors}; {warnings}"))); } } From 95c5b060004928984b6b76a9ef67a3ca7147568c Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 11 Feb 2024 23:26:06 +0100 Subject: [PATCH 18/18] fix ICE for deref coercions with type errors --- compiler/rustc_hir_analysis/src/autoderef.rs | 8 ++++---- .../rustc_hir_analysis/src/check/wfcheck.rs | 10 +++++++--- tests/ui/coercion/type-errors.rs | 19 +++++++++++++++---- tests/ui/coercion/type-errors.stderr | 14 +++++++++++++- 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index 5bc904e5930ce..f2ceb4702643a 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -91,10 +91,6 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> { return None; }; - if new_ty.references_error() { - return None; - } - self.state.steps.push((self.state.cur_ty, kind)); debug!( "autoderef stage #{:?} is {:?} from {:?}", @@ -137,6 +133,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { debug!("overloaded_deref_ty({:?})", ty); let tcx = self.infcx.tcx; + if ty.references_error() { + return None; + } + // let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]); let cause = traits::ObligationCause::misc(self.span, self.body_id); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 646a84b043c82..bf22c70ebfd57 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1635,6 +1635,12 @@ fn check_method_receiver<'tcx>( let receiver_ty = sig.inputs()[0]; let receiver_ty = wfcx.normalize(span, None, receiver_ty); + // If the receiver already has errors reported, consider it valid to avoid + // unnecessary errors (#58712). + if receiver_ty.references_error() { + return Ok(()); + } + if tcx.features().arbitrary_self_types { if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) { // Report error; `arbitrary_self_types` was enabled. @@ -1749,9 +1755,7 @@ fn receiver_is_valid<'tcx>( } } else { debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty); - // If the receiver already has errors reported due to it, consider it valid to avoid - // unnecessary errors (#58712). - return receiver_ty.references_error(); + return false; } } diff --git a/tests/ui/coercion/type-errors.rs b/tests/ui/coercion/type-errors.rs index a2f0e55f1b931..a86789907a055 100644 --- a/tests/ui/coercion/type-errors.rs +++ b/tests/ui/coercion/type-errors.rs @@ -1,15 +1,26 @@ -// Regression test for an ICE: https://github.com/rust-lang/rust/issues/120884 +// Test that we don't ICE for coercions with type errors. // We still need to properly go through coercions between types with errors instead of // shortcutting and returning success, because we need the adjustments for building the MIR. pub fn has_error() -> TypeError {} //~^ ERROR cannot find type `TypeError` in this scope +// https://github.com/rust-lang/rust/issues/120884 +// Casting a function item to a data pointer in valid in HIR, but invalid in MIR. +// We need an adjustment (ReifyFnPointer) to insert a cast from the function item +// to a function pointer as a separate MIR statement. pub fn cast() -> *const u8 { - // Casting a function item to a data pointer in valid in HIR, but invalid in MIR. - // We need an adjustment (ReifyFnPointer) to insert a cast from the function item - // to a function pointer as a separate MIR statement. has_error as *const u8 } +// https://github.com/rust-lang/rust/issues/120945 +// This one ICEd, because we skipped the builtin deref from `&TypeError` to `TypeError`. +pub fn autoderef_source(e: &TypeError) { + //~^ ERROR cannot find type `TypeError` in this scope + autoderef_target(e) +} + +pub fn autoderef_target(_: &TypeError) {} +//~^ ERROR cannot find type `TypeError` in this scope + fn main() {} diff --git a/tests/ui/coercion/type-errors.stderr b/tests/ui/coercion/type-errors.stderr index 489cd9ddf130e..14deb785f75aa 100644 --- a/tests/ui/coercion/type-errors.stderr +++ b/tests/ui/coercion/type-errors.stderr @@ -4,6 +4,18 @@ error[E0412]: cannot find type `TypeError` in this scope LL | pub fn has_error() -> TypeError {} | ^^^^^^^^^ not found in this scope -error: aborting due to 1 previous error +error[E0412]: cannot find type `TypeError` in this scope + --> $DIR/type-errors.rs:18:29 + | +LL | pub fn autoderef_source(e: &TypeError) { + | ^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `TypeError` in this scope + --> $DIR/type-errors.rs:23:29 + | +LL | pub fn autoderef_target(_: &TypeError) {} + | ^^^^^^^^^ not found in this scope + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0412`.