From 1aad89d11ca9e52fa0442c75bb3d9dee9635cbb7 Mon Sep 17 00:00:00 2001 From: Charles Celerier Date: Wed, 10 Jul 2024 03:22:44 +0000 Subject: [PATCH 01/15] Add match arm for Fuchsia status code upon an abort in a test This change adds ZX_TASK_RETCODE_EXCEPTION_KILL as an expected status code upon an abort in a test on Fuchsia. Tests fixes #127539 --- library/test/src/test_result.rs | 11 +++++++++++ .../test-attrs/test-panic-abort-nocapture.run.stderr | 4 ++-- tests/ui/test-attrs/test-panic-abort.run.stdout | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs index bb32c70d66311..cecf747f5311f 100644 --- a/library/test/src/test_result.rs +++ b/library/test/src/test_result.rs @@ -21,6 +21,14 @@ pub const TR_OK: i32 = 50; #[cfg(windows)] const STATUS_ABORTED: i32 = 0xC0000409u32 as i32; +// On Zircon (the Fuchsia kernel), an abort from userspace calls the +// LLVM implementation of __builtin_trap(), e.g., ud2 on x86, which +// raises a kernel exception. If a userspace process does not +// otherwise arrange exception handling, the kernel kills the process +// with this return code. +#[cfg(target_os = "fuchsia")] +const ZX_TASK_RETCODE_EXCEPTION_KILL: i32 = -1028; + #[derive(Debug, Clone, PartialEq)] pub enum TestResult { TrOk, @@ -105,6 +113,9 @@ pub fn get_result_from_exit_code( } None => unreachable!("status.code() returned None but status.signal() was None"), }, + // Upon an abort, Fuchsia returns the status code ZX_TASK_RETCODE_EXCEPTION_KILL. + #[cfg(target_os = "fuchsia")] + Some(ZX_TASK_RETCODE_EXCEPTION_KILL) => TestResult::TrFailed, #[cfg(not(unix))] None => TestResult::TrFailedMsg(format!("unknown return code")), #[cfg(any(windows, unix))] diff --git a/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr b/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr index 4c94518d4d197..16001b3eecd4d 100644 --- a/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr +++ b/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr @@ -1,9 +1,9 @@ -thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:35:5: +thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:34:5: assertion `left == right` failed left: 2 right: 4 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:29:5: +thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:28:5: assertion `left == right` failed left: 2 right: 4 diff --git a/tests/ui/test-attrs/test-panic-abort.run.stdout b/tests/ui/test-attrs/test-panic-abort.run.stdout index 25105f38fcf78..f5d14e77da963 100644 --- a/tests/ui/test-attrs/test-panic-abort.run.stdout +++ b/tests/ui/test-attrs/test-panic-abort.run.stdout @@ -17,7 +17,7 @@ hello, world testing123 ---- it_fails stderr ---- testing321 -thread 'main' panicked at $DIR/test-panic-abort.rs:40:5: +thread 'main' panicked at $DIR/test-panic-abort.rs:39:5: assertion `left == right` failed left: 2 right: 5 From deb8ebb39b1fa8ab1436bf224df434273a6c58c6 Mon Sep 17 00:00:00 2001 From: Charles Celerier Date: Wed, 10 Jul 2024 03:43:15 +0000 Subject: [PATCH 02/15] Update name of Windows abort constant to match platform documentation --- library/test/src/test_result.rs | 4 ++-- tests/ui/test-attrs/test-panic-abort-nocapture.rs | 1 - tests/ui/test-attrs/test-panic-abort.rs | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs index cecf747f5311f..98c54f038da6c 100644 --- a/library/test/src/test_result.rs +++ b/library/test/src/test_result.rs @@ -19,7 +19,7 @@ pub const TR_OK: i32 = 50; // On Windows we use __fastfail to abort, which is documented to use this // exception code. #[cfg(windows)] -const STATUS_ABORTED: i32 = 0xC0000409u32 as i32; +const STATUS_FAIL_FAST_EXCEPTION: i32 = 0xC0000409u32 as i32; // On Zircon (the Fuchsia kernel), an abort from userspace calls the // LLVM implementation of __builtin_trap(), e.g., ud2 on x86, which @@ -104,7 +104,7 @@ pub fn get_result_from_exit_code( let result = match status.code() { Some(TR_OK) => TestResult::TrOk, #[cfg(windows)] - Some(STATUS_ABORTED) => TestResult::TrFailed, + Some(STATUS_FAIL_FAST_EXCEPTION) => TestResult::TrFailed, #[cfg(unix)] None => match status.signal() { Some(libc::SIGABRT) => TestResult::TrFailed, diff --git a/tests/ui/test-attrs/test-panic-abort-nocapture.rs b/tests/ui/test-attrs/test-panic-abort-nocapture.rs index c2c3d6d547d6c..f3485d9c1fa99 100644 --- a/tests/ui/test-attrs/test-panic-abort-nocapture.rs +++ b/tests/ui/test-attrs/test-panic-abort-nocapture.rs @@ -10,7 +10,6 @@ //@ ignore-wasm no panic or subprocess support //@ ignore-emscripten no panic or subprocess support //@ ignore-sgx no subprocess support -//@ ignore-fuchsia code returned as ZX_TASK_RETCODE_EXCEPTION_KILL, FIXME (#127539) #![cfg(test)] diff --git a/tests/ui/test-attrs/test-panic-abort.rs b/tests/ui/test-attrs/test-panic-abort.rs index 0c44acaffd77b..84740161a708d 100644 --- a/tests/ui/test-attrs/test-panic-abort.rs +++ b/tests/ui/test-attrs/test-panic-abort.rs @@ -10,7 +10,6 @@ //@ ignore-wasm no panic or subprocess support //@ ignore-emscripten no panic or subprocess support //@ ignore-sgx no subprocess support -//@ ignore-fuchsia code returned as ZX_TASK_RETCODE_EXCEPTION_KILL, FIXME (#127539) #![cfg(test)] #![feature(test)] From 03bfa3690ef0d0acf6ea0dd0e4ea832d6eeb5524 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 17 Jul 2024 21:19:44 +1000 Subject: [PATCH 03/15] Rename `MatchPair` to `MatchPairTree` In #120904, `MatchPair` became able to store other match pairs as children, forming a tree. That has made the old name confusing, so this patch renames the type to `MatchPairTree`. --- .../src/build/matches/match_pair.rs | 46 ++++++++++--------- .../rustc_mir_build/src/build/matches/mod.rs | 18 ++++---- .../src/build/matches/simplify.rs | 4 +- .../rustc_mir_build/src/build/matches/test.rs | 4 +- .../rustc_mir_build/src/build/matches/util.rs | 6 +-- 5 files changed, 41 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/match_pair.rs b/compiler/rustc_mir_build/src/build/matches/match_pair.rs index 2f540478674d7..95fec154918a5 100644 --- a/compiler/rustc_mir_build/src/build/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/build/matches/match_pair.rs @@ -3,37 +3,37 @@ use rustc_middle::thir::{self, *}; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use crate::build::expr::as_place::{PlaceBase, PlaceBuilder}; -use crate::build::matches::{FlatPat, MatchPair, TestCase}; +use crate::build::matches::{FlatPat, MatchPairTree, TestCase}; use crate::build::Builder; impl<'a, 'tcx> Builder<'a, 'tcx> { - /// Builds and returns [`MatchPair`] trees, one for each pattern in + /// Builds and returns [`MatchPairTree`] subtrees, one for each pattern in /// `subpatterns`, representing the fields of a [`PatKind::Variant`] or /// [`PatKind::Leaf`]. /// - /// Used internally by [`MatchPair::new`]. + /// Used internally by [`MatchPairTree::for_pattern`]. fn field_match_pairs<'pat>( &mut self, place: PlaceBuilder<'tcx>, subpatterns: &'pat [FieldPat<'tcx>], - ) -> Vec> { + ) -> Vec> { subpatterns .iter() .map(|fieldpat| { let place = place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty)); - MatchPair::new(place, &fieldpat.pattern, self) + MatchPairTree::for_pattern(place, &fieldpat.pattern, self) }) .collect() } - /// Builds [`MatchPair`] trees for the prefix/middle/suffix parts of an + /// Builds [`MatchPairTree`] subtrees for the prefix/middle/suffix parts of an /// array pattern or slice pattern, and adds those trees to `match_pairs`. /// - /// Used internally by [`MatchPair::new`]. + /// Used internally by [`MatchPairTree::for_pattern`]. fn prefix_slice_suffix<'pat>( &mut self, - match_pairs: &mut Vec>, + match_pairs: &mut Vec>, place: &PlaceBuilder<'tcx>, prefix: &'pat [Box>], opt_slice: &'pat Option>>, @@ -52,7 +52,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| { let elem = ProjectionElem::ConstantIndex { offset: idx as u64, min_length, from_end: false }; - MatchPair::new(place.clone_project(elem), subpattern, self) + MatchPairTree::for_pattern(place.clone_project(elem), subpattern, self) })); if let Some(subslice_pat) = opt_slice { @@ -62,7 +62,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { to: if exact_size { min_length - suffix_len } else { suffix_len }, from_end: !exact_size, }); - match_pairs.push(MatchPair::new(subslice, subslice_pat, self)); + match_pairs.push(MatchPairTree::for_pattern(subslice, subslice_pat, self)); } match_pairs.extend(suffix.iter().rev().enumerate().map(|(idx, subpattern)| { @@ -73,19 +73,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { from_end: !exact_size, }; let place = place.clone_project(elem); - MatchPair::new(place, subpattern, self) + MatchPairTree::for_pattern(place, subpattern, self) })); } } -impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { - /// Recursively builds a `MatchPair` tree for the given pattern and its +impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> { + /// Recursively builds a match pair tree for the given pattern and its /// subpatterns. - pub(in crate::build) fn new( + pub(in crate::build) fn for_pattern( mut place_builder: PlaceBuilder<'tcx>, pattern: &'pat Pat<'tcx>, cx: &mut Builder<'_, 'tcx>, - ) -> MatchPair<'pat, 'tcx> { + ) -> MatchPairTree<'pat, 'tcx> { // Force the place type to the pattern's type. // FIXME(oli-obk): can we use this to simplify slice/array pattern hacks? if let Some(resolved) = place_builder.resolve_upvar(cx) { @@ -138,7 +138,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { variance, }); - subpairs.push(MatchPair::new(place_builder, subpattern, cx)); + subpairs.push(MatchPairTree::for_pattern(place_builder, subpattern, cx)); TestCase::Irrefutable { ascription, binding: None } } @@ -152,7 +152,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { if let Some(subpattern) = subpattern.as_ref() { // this is the `x @ P` case; have to keep matching against `P` now - subpairs.push(MatchPair::new(place_builder, subpattern, cx)); + subpairs.push(MatchPairTree::for_pattern(place_builder, subpattern, cx)); } TestCase::Irrefutable { ascription: None, binding } } @@ -182,7 +182,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { super::Ascription { annotation, source, variance: ty::Contravariant } }); - subpairs.push(MatchPair::new(place_builder, pattern, cx)); + subpairs.push(MatchPairTree::for_pattern(place_builder, pattern, cx)); TestCase::Irrefutable { ascription, binding: None } } @@ -231,7 +231,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { } PatKind::Deref { ref subpattern } => { - subpairs.push(MatchPair::new(place_builder.deref(), subpattern, cx)); + subpairs.push(MatchPairTree::for_pattern(place_builder.deref(), subpattern, cx)); default_irrefutable() } @@ -242,13 +242,17 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, subpattern.ty, mutability), pattern.span, ); - subpairs.push(MatchPair::new(PlaceBuilder::from(temp).deref(), subpattern, cx)); + subpairs.push(MatchPairTree::for_pattern( + PlaceBuilder::from(temp).deref(), + subpattern, + cx, + )); TestCase::Deref { temp, mutability } } PatKind::Never => TestCase::Never, }; - MatchPair { place, test_case, subpairs, pattern } + MatchPairTree { place, test_case, subpairs, pattern } } } diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index fc4e9ebec0a87..535ee8946f2ea 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1028,15 +1028,15 @@ impl<'tcx> PatternExtraData<'tcx> { #[derive(Debug, Clone)] struct FlatPat<'pat, 'tcx> { /// To match the pattern, all of these must be satisfied... - // Invariant: all the `MatchPair`s are recursively simplified. + // Invariant: all the match pairs are recursively simplified. // Invariant: or-patterns must be sorted to the end. - match_pairs: Vec>, + match_pairs: Vec>, extra_data: PatternExtraData<'tcx>, } impl<'tcx, 'pat> FlatPat<'pat, 'tcx> { - /// Creates a `FlatPat` containing a simplified [`MatchPair`] list/forest + /// Creates a `FlatPat` containing a simplified [`MatchPairTree`] list/forest /// for the given pattern. fn new( place: PlaceBuilder<'tcx>, @@ -1044,7 +1044,7 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> { cx: &mut Builder<'_, 'tcx>, ) -> Self { // First, recursively build a tree of match pairs for the given pattern. - let mut match_pairs = vec![MatchPair::new(place, pattern, cx)]; + let mut match_pairs = vec![MatchPairTree::for_pattern(place, pattern, cx)]; let mut extra_data = PatternExtraData { span: pattern.span, bindings: Vec::new(), @@ -1061,9 +1061,9 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> { #[derive(Debug)] struct Candidate<'pat, 'tcx> { /// For the candidate to match, all of these must be satisfied... - // Invariant: all the `MatchPair`s are recursively simplified. + // Invariant: all the match pairs are recursively simplified. // Invariant: or-patterns must be sorted at the end. - match_pairs: Vec>, + match_pairs: Vec>, /// ...and if this is non-empty, one of these subcandidates also has to match... // Invariant: at the end of the algorithm, this must never contain a `is_never` candidate @@ -1122,7 +1122,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> { /// Returns whether the first match pair of this candidate is an or-pattern. fn starts_with_or_pattern(&self) -> bool { - matches!(&*self.match_pairs, [MatchPair { test_case: TestCase::Or { .. }, .. }, ..]) + matches!(&*self.match_pairs, [MatchPairTree { test_case: TestCase::Or { .. }, .. }, ..]) } /// Visit the leaf candidates (those with no subcandidates) contained in @@ -1202,7 +1202,7 @@ impl<'pat, 'tcx> TestCase<'pat, 'tcx> { /// Each node also has a list of subpairs (possibly empty) that must also match, /// and a reference to the THIR pattern it represents. #[derive(Debug, Clone)] -pub(crate) struct MatchPair<'pat, 'tcx> { +pub(crate) struct MatchPairTree<'pat, 'tcx> { /// This place... /// /// --- @@ -1625,7 +1625,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn create_or_subcandidates<'pat>( &mut self, candidate: &mut Candidate<'pat, 'tcx>, - match_pair: MatchPair<'pat, 'tcx>, + match_pair: MatchPairTree<'pat, 'tcx>, ) { let TestCase::Or { pats } = match_pair.test_case else { bug!() }; debug!("expanding or-pattern: candidate={:#?}\npats={:#?}", candidate, pats); diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 543301c71a0ec..20310f6082108 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -12,7 +12,7 @@ //! sort of test: for example, testing which variant an enum is, or //! testing a value against a constant. -use crate::build::matches::{MatchPair, PatternExtraData, TestCase}; +use crate::build::matches::{MatchPairTree, PatternExtraData, TestCase}; use crate::build::Builder; use tracing::{debug, instrument}; @@ -24,7 +24,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { #[instrument(skip(self), level = "debug")] pub(super) fn simplify_match_pairs<'pat>( &mut self, - match_pairs: &mut Vec>, + match_pairs: &mut Vec>, extra_data: &mut PatternExtraData<'tcx>, ) { // In order to please the borrow checker, in a pattern like `x @ pat` we must lower the diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index d29874a5ad4ba..fb59cee99c067 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -5,7 +5,7 @@ // identify what tests are needed, perform the tests, and then filter // the candidates based on the result. -use crate::build::matches::{Candidate, MatchPair, Test, TestBranch, TestCase, TestKind}; +use crate::build::matches::{Candidate, MatchPairTree, Test, TestBranch, TestCase, TestKind}; use crate::build::Builder; use rustc_data_structures::fx::FxIndexMap; use rustc_hir::{LangItem, RangeEnd}; @@ -26,7 +26,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Identifies what test is needed to decide if `match_pair` is applicable. /// /// It is a bug to call this with a not-fully-simplified pattern. - pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> { + pub(super) fn test<'pat>(&mut self, match_pair: &MatchPairTree<'pat, 'tcx>) -> Test<'tcx> { let kind = match match_pair.test_case { TestCase::Variant { adt_def, variant_index: _ } => TestKind::Switch { adt_def }, diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index e67fc843285e6..8fe8069b3455d 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -1,7 +1,7 @@ use std::marker::PhantomData; use crate::build::expr::as_place::PlaceBase; -use crate::build::matches::{Binding, Candidate, FlatPat, MatchPair, TestCase}; +use crate::build::matches::{Binding, Candidate, FlatPat, MatchPairTree, TestCase}; use crate::build::Builder; use rustc_data_structures::fx::FxIndexMap; use rustc_middle::mir::*; @@ -152,7 +152,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { } } - fn visit_match_pair(&mut self, match_pair: &MatchPair<'_, 'tcx>) { + fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'_, 'tcx>) { if let TestCase::Or { pats, .. } = &match_pair.test_case { for flat_pat in pats.iter() { self.visit_flat_pat(flat_pat) @@ -260,7 +260,7 @@ where } } - fn visit_match_pair(&mut self, match_pair: &MatchPair<'_, 'tcx>) { + fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'_, 'tcx>) { if let TestCase::Or { pats, .. } = &match_pair.test_case { // All the or-alternatives should bind the same locals, so we only visit the first one. self.visit_flat_pat(&pats[0]) From 411fcb6b2df7337377626680ef5ec5d99b5eba23 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 17 Jul 2024 21:41:42 +1000 Subject: [PATCH 04/15] Rename `test` to `pick_test_for_match_pair` --- compiler/rustc_mir_build/src/build/matches/mod.rs | 4 ++-- compiler/rustc_mir_build/src/build/matches/test.rs | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 535ee8946f2ea..6910b32cfa7ae 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1809,8 +1809,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// [`Range`]: TestKind::Range fn pick_test(&mut self, candidates: &[&mut Candidate<'_, 'tcx>]) -> (Place<'tcx>, Test<'tcx>) { // Extract the match-pair from the highest priority candidate - let match_pair = &candidates.first().unwrap().match_pairs[0]; - let test = self.test(match_pair); + let match_pair = &candidates[0].match_pairs[0]; + let test = self.pick_test_for_match_pair(match_pair); // Unwrap is ok after simplification. let match_place = match_pair.place.unwrap(); debug!(?test, ?match_pair); diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index fb59cee99c067..6f2d2022ac564 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -26,7 +26,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Identifies what test is needed to decide if `match_pair` is applicable. /// /// It is a bug to call this with a not-fully-simplified pattern. - pub(super) fn test<'pat>(&mut self, match_pair: &MatchPairTree<'pat, 'tcx>) -> Test<'tcx> { + pub(super) fn pick_test_for_match_pair<'pat>( + &mut self, + match_pair: &MatchPairTree<'pat, 'tcx>, + ) -> Test<'tcx> { let kind = match match_pair.test_case { TestCase::Variant { adt_def, variant_index: _ } => TestKind::Switch { adt_def }, From 3716a3fd3104915b9663a335fa92222ae3e179de Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 17 Jul 2024 15:56:16 -0400 Subject: [PATCH 05/15] Mention that type parameters are used recursively --- compiler/rustc_hir_analysis/messages.ftl | 5 ++ .../rustc_hir_analysis/src/check/wfcheck.rs | 83 ++++++++++++++----- compiler/rustc_hir_analysis/src/errors.rs | 15 ++++ .../inherent-impls-overflow.next.stderr | 23 ++--- .../inherent-impls-overflow.rs | 4 +- tests/ui/traits/issue-105231.rs | 4 +- tests/ui/traits/issue-105231.stderr | 22 +++-- .../ui/variance/variance-unused-type-param.rs | 2 +- .../variance-unused-type-param.stderr | 10 ++- 9 files changed, 119 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 24c5377a3b125..b37c19ed8a8d4 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -382,6 +382,10 @@ hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is no hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias .label = `Self` is not a generic argument, but an alias to the type of the {$what} +hir_analysis_recursive_generic_parameter = {$param_def_kind} `{$param_name}` is only used recursively + .label = {$param_def_kind} must be used non-recursively in the definition + .note = all type parameters must be used in a non-recursive way in order to constrain its variance + hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}` .note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}` @@ -549,6 +553,7 @@ hir_analysis_unused_generic_parameter = {$param_def_kind} `{$param_name}` is never used .label = unused {$param_def_kind} .const_param_help = if you intended `{$param_name}` to be a const parameter, use `const {$param_name}: /* Type */` instead + hir_analysis_unused_generic_parameter_adt_help = consider removing `{$param_name}`, referring to it in a field, or using a marker such as `{$phantom_data}` hir_analysis_unused_generic_parameter_adt_no_phantom_data_help = diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index b2ef07d65c5b4..a4bff9272af64 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -4,12 +4,12 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Par use crate::errors; use crate::fluent_generated as fluent; -use hir::intravisit::Visitor; +use hir::intravisit::{self, Visitor}; use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; use rustc_hir as hir; -use rustc_hir::def::DefKind; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::ItemKind; @@ -1799,7 +1799,7 @@ fn receiver_is_implemented<'tcx>( fn check_variances_for_type_defn<'tcx>( tcx: TyCtxt<'tcx>, - item: &hir::Item<'tcx>, + item: &'tcx hir::Item<'tcx>, hir_generics: &hir::Generics<'tcx>, ) { let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id); @@ -1886,21 +1886,21 @@ fn check_variances_for_type_defn<'tcx>( hir::ParamName::Error => {} _ => { let has_explicit_bounds = explicitly_bounded_params.contains(¶meter); - report_bivariance(tcx, hir_param, has_explicit_bounds, item.kind); + report_bivariance(tcx, hir_param, has_explicit_bounds, item); } } } } -fn report_bivariance( - tcx: TyCtxt<'_>, - param: &rustc_hir::GenericParam<'_>, +fn report_bivariance<'tcx>( + tcx: TyCtxt<'tcx>, + param: &'tcx hir::GenericParam<'tcx>, has_explicit_bounds: bool, - item_kind: ItemKind<'_>, + item: &'tcx hir::Item<'tcx>, ) -> ErrorGuaranteed { let param_name = param.name.ident(); - let help = match item_kind { + let help = match item.kind { ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => { if let Some(def_id) = tcx.lang_items().phantom_data() { errors::UnusedGenericParameterHelp::Adt { @@ -1915,19 +1915,60 @@ fn report_bivariance( item_kind => bug!("report_bivariance: unexpected item kind: {item_kind:?}"), }; - let const_param_help = - matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds) - .then_some(()); + let mut usage_spans = vec![]; + intravisit::walk_item( + &mut CollectUsageSpans { spans: &mut usage_spans, param_def_id: param.def_id.to_def_id() }, + item, + ); - let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter { - span: param.span, - param_name, - param_def_kind: tcx.def_descr(param.def_id.to_def_id()), - help, - const_param_help, - }); - diag.code(E0392); - diag.emit() + if usage_spans.is_empty() { + let const_param_help = + matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds) + .then_some(()); + + let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter { + span: param.span, + param_name, + param_def_kind: tcx.def_descr(param.def_id.to_def_id()), + help, + const_param_help, + }); + diag.code(E0392); + diag.emit() + } else { + let diag = tcx.dcx().create_err(errors::RecursiveGenericParameter { + spans: usage_spans, + param_span: param.span, + param_name, + param_def_kind: tcx.def_descr(param.def_id.to_def_id()), + help, + note: (), + }); + diag.emit() + } +} + +struct CollectUsageSpans<'a> { + spans: &'a mut Vec, + param_def_id: DefId, +} + +impl<'tcx> Visitor<'tcx> for CollectUsageSpans<'_> { + type Result = (); + + fn visit_generics(&mut self, _g: &'tcx rustc_hir::Generics<'tcx>) -> Self::Result { + // Skip the generics. We only care about fields, not where clause/param bounds. + } + + fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) -> Self::Result { + if let hir::TyKind::Path(hir::QPath::Resolved(None, qpath)) = t.kind + && let Res::Def(DefKind::TyParam, def_id) = qpath.res + && def_id == self.param_def_id + { + self.spans.push(t.span); + } + intravisit::walk_ty(self, t); + } } impl<'tcx> WfCheckingCtxt<'_, 'tcx> { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 0ee87a13e9e37..2edd8f54adba0 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1603,6 +1603,21 @@ pub(crate) struct UnusedGenericParameter { pub const_param_help: Option<()>, } +#[derive(Diagnostic)] +#[diag(hir_analysis_recursive_generic_parameter)] +pub(crate) struct RecursiveGenericParameter { + #[primary_span] + pub spans: Vec, + #[label] + pub param_span: Span, + pub param_name: Ident, + pub param_def_kind: &'static str, + #[subdiagnostic] + pub help: UnusedGenericParameterHelp, + #[note] + pub note: (), +} + #[derive(Subdiagnostic)] pub(crate) enum UnusedGenericParameterHelp { #[help(hir_analysis_unused_generic_parameter_adt_help)] diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr index 944fe8aa8e596..b60fdea004eb3 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr @@ -4,23 +4,27 @@ error[E0275]: overflow evaluating the requirement `Loop == _` LL | impl Loop {} | ^^^^ -error[E0392]: type parameter `T` is never used - --> $DIR/inherent-impls-overflow.rs:14:12 +error: type parameter `T` is only used recursively + --> $DIR/inherent-impls-overflow.rs:14:24 | LL | type Poly0 = Poly1<(T,)>; - | ^ unused type parameter + | - ^ + | | + | type parameter must be used non-recursively in the definition | = help: consider removing `T` or referring to it in the body of the type alias - = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + = note: all type parameters must be used in a non-recursive way in order to constrain its variance -error[E0392]: type parameter `T` is never used - --> $DIR/inherent-impls-overflow.rs:17:12 +error: type parameter `T` is only used recursively + --> $DIR/inherent-impls-overflow.rs:17:24 | LL | type Poly1 = Poly0<(T,)>; - | ^ unused type parameter + | - ^ + | | + | type parameter must be used non-recursively in the definition | = help: consider removing `T` or referring to it in the body of the type alias - = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + = note: all type parameters must be used in a non-recursive way in order to constrain its variance error[E0275]: overflow evaluating the requirement `Poly0<()> == _` --> $DIR/inherent-impls-overflow.rs:21:6 @@ -32,5 +36,4 @@ LL | impl Poly0<()> {} error: aborting due to 4 previous errors -Some errors have detailed explanations: E0275, E0392. -For more information about an error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs index 98f0d811a47be..1397695a3fe41 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs @@ -13,10 +13,10 @@ impl Loop {} type Poly0 = Poly1<(T,)>; //[current]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>` -//[next]~^^ ERROR type parameter `T` is never used +//[next]~^^ ERROR type parameter `T` is only used recursively type Poly1 = Poly0<(T,)>; //[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` -//[next]~^^ ERROR type parameter `T` is never used +//[next]~^^ ERROR type parameter `T` is only used recursively impl Poly0<()> {} //[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs index 89b2da4452a5c..7338642beefa6 100644 --- a/tests/ui/traits/issue-105231.rs +++ b/tests/ui/traits/issue-105231.rs @@ -1,9 +1,9 @@ //~ ERROR overflow evaluating the requirement `A>>>>>>: Send` struct A(B); //~^ ERROR recursive types `A` and `B` have infinite size -//~| ERROR `T` is never used +//~| ERROR `T` is only used recursively struct B(A>); -//~^ ERROR `T` is never used +//~^ ERROR `T` is only used recursively trait Foo {} impl Foo for T where T: Send {} impl Foo for B {} diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr index 6467a438375c9..6fd73b29f2148 100644 --- a/tests/ui/traits/issue-105231.stderr +++ b/tests/ui/traits/issue-105231.stderr @@ -15,23 +15,27 @@ LL | LL ~ struct B(Box>>); | -error[E0392]: type parameter `T` is never used - --> $DIR/issue-105231.rs:2:10 +error: type parameter `T` is only used recursively + --> $DIR/issue-105231.rs:2:15 | LL | struct A(B); - | ^ unused type parameter + | - ^ + | | + | type parameter must be used non-recursively in the definition | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + = note: all type parameters must be used in a non-recursive way in order to constrain its variance -error[E0392]: type parameter `T` is never used - --> $DIR/issue-105231.rs:5:10 +error: type parameter `T` is only used recursively + --> $DIR/issue-105231.rs:5:17 | LL | struct B(A>); - | ^ unused type parameter + | - ^ + | | + | type parameter must be used non-recursively in the definition | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + = note: all type parameters must be used in a non-recursive way in order to constrain its variance error[E0275]: overflow evaluating the requirement `A>>>>>>: Send` | @@ -44,5 +48,5 @@ LL | struct B(A>); error: aborting due to 4 previous errors -Some errors have detailed explanations: E0072, E0275, E0392. +Some errors have detailed explanations: E0072, E0275. For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/variance/variance-unused-type-param.rs b/tests/ui/variance/variance-unused-type-param.rs index d111406436478..7e35f59fd8478 100644 --- a/tests/ui/variance/variance-unused-type-param.rs +++ b/tests/ui/variance/variance-unused-type-param.rs @@ -11,8 +11,8 @@ enum SomeEnum { Nothing } // Here T might *appear* used, but in fact it isn't. enum ListCell { -//~^ ERROR parameter `T` is never used Cons(Box>), + //~^ ERROR parameter `T` is only used recursively Nil } diff --git a/tests/ui/variance/variance-unused-type-param.stderr b/tests/ui/variance/variance-unused-type-param.stderr index 3011b7bd18fa7..212db564ac4a6 100644 --- a/tests/ui/variance/variance-unused-type-param.stderr +++ b/tests/ui/variance/variance-unused-type-param.stderr @@ -16,14 +16,16 @@ LL | enum SomeEnum { Nothing } = help: consider removing `A`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `A` to be a const parameter, use `const A: /* Type */` instead -error[E0392]: type parameter `T` is never used - --> $DIR/variance-unused-type-param.rs:13:15 +error: type parameter `T` is only used recursively + --> $DIR/variance-unused-type-param.rs:14:23 | LL | enum ListCell { - | ^ unused type parameter + | - type parameter must be used non-recursively in the definition +LL | Cons(Box>), + | ^ | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + = note: all type parameters must be used in a non-recursive way in order to constrain its variance error[E0392]: type parameter `T` is never used --> $DIR/variance-unused-type-param.rs:19:19 From a0a251a6882b410a72069feb67ab7342d1b0e409 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 17 Jul 2024 16:36:21 -0400 Subject: [PATCH 06/15] Account for self ty alias --- compiler/rustc_hir_analysis/messages.ftl | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 15 ++++++++----- .../inherent-impls-overflow.next.stderr | 4 ++-- tests/ui/traits/issue-105231.stderr | 4 ++-- .../ui/variance/variance-unused-type-param.rs | 3 +++ .../variance-unused-type-param.stderr | 21 ++++++++++++++----- 6 files changed, 34 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index b37c19ed8a8d4..ac46f981d9812 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -384,7 +384,7 @@ hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` hir_analysis_recursive_generic_parameter = {$param_def_kind} `{$param_name}` is only used recursively .label = {$param_def_kind} must be used non-recursively in the definition - .note = all type parameters must be used in a non-recursive way in order to constrain its variance + .note = all type parameters must be used in a non-recursive way in order to constrain their variance hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}` .note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}` diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index a4bff9272af64..ffe3e61d9cf63 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1961,11 +1961,16 @@ impl<'tcx> Visitor<'tcx> for CollectUsageSpans<'_> { } fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) -> Self::Result { - if let hir::TyKind::Path(hir::QPath::Resolved(None, qpath)) = t.kind - && let Res::Def(DefKind::TyParam, def_id) = qpath.res - && def_id == self.param_def_id - { - self.spans.push(t.span); + if let hir::TyKind::Path(hir::QPath::Resolved(None, qpath)) = t.kind { + if let Res::Def(DefKind::TyParam, def_id) = qpath.res + && def_id == self.param_def_id + { + self.spans.push(t.span); + return; + } else if let Res::SelfTyAlias { .. } = qpath.res { + self.spans.push(t.span); + return; + } } intravisit::walk_ty(self, t); } diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr index b60fdea004eb3..192b5eebdaac8 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr @@ -13,7 +13,7 @@ LL | type Poly0 = Poly1<(T,)>; | type parameter must be used non-recursively in the definition | = help: consider removing `T` or referring to it in the body of the type alias - = note: all type parameters must be used in a non-recursive way in order to constrain its variance + = note: all type parameters must be used in a non-recursive way in order to constrain their variance error: type parameter `T` is only used recursively --> $DIR/inherent-impls-overflow.rs:17:24 @@ -24,7 +24,7 @@ LL | type Poly1 = Poly0<(T,)>; | type parameter must be used non-recursively in the definition | = help: consider removing `T` or referring to it in the body of the type alias - = note: all type parameters must be used in a non-recursive way in order to constrain its variance + = note: all type parameters must be used in a non-recursive way in order to constrain their variance error[E0275]: overflow evaluating the requirement `Poly0<()> == _` --> $DIR/inherent-impls-overflow.rs:21:6 diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr index 6fd73b29f2148..d3014a79ad605 100644 --- a/tests/ui/traits/issue-105231.stderr +++ b/tests/ui/traits/issue-105231.stderr @@ -24,7 +24,7 @@ LL | struct A(B); | type parameter must be used non-recursively in the definition | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = note: all type parameters must be used in a non-recursive way in order to constrain its variance + = note: all type parameters must be used in a non-recursive way in order to constrain their variance error: type parameter `T` is only used recursively --> $DIR/issue-105231.rs:5:17 @@ -35,7 +35,7 @@ LL | struct B(A>); | type parameter must be used non-recursively in the definition | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = note: all type parameters must be used in a non-recursive way in order to constrain its variance + = note: all type parameters must be used in a non-recursive way in order to constrain their variance error[E0275]: overflow evaluating the requirement `A>>>>>>: Send` | diff --git a/tests/ui/variance/variance-unused-type-param.rs b/tests/ui/variance/variance-unused-type-param.rs index 7e35f59fd8478..ada57ab0d0939 100644 --- a/tests/ui/variance/variance-unused-type-param.rs +++ b/tests/ui/variance/variance-unused-type-param.rs @@ -16,6 +16,9 @@ enum ListCell { Nil } +struct SelfTyAlias(Box); +//~^ ERROR parameter `T` is only used recursively + struct WithBounds {} //~^ ERROR parameter `T` is never used diff --git a/tests/ui/variance/variance-unused-type-param.stderr b/tests/ui/variance/variance-unused-type-param.stderr index 212db564ac4a6..1a45bcba45a0f 100644 --- a/tests/ui/variance/variance-unused-type-param.stderr +++ b/tests/ui/variance/variance-unused-type-param.stderr @@ -25,10 +25,21 @@ LL | Cons(Box>), | ^ | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = note: all type parameters must be used in a non-recursive way in order to constrain its variance + = note: all type parameters must be used in a non-recursive way in order to constrain their variance + +error: type parameter `T` is only used recursively + --> $DIR/variance-unused-type-param.rs:19:27 + | +LL | struct SelfTyAlias(Box); + | - ^^^^ + | | + | type parameter must be used non-recursively in the definition + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = note: all type parameters must be used in a non-recursive way in order to constrain their variance error[E0392]: type parameter `T` is never used - --> $DIR/variance-unused-type-param.rs:19:19 + --> $DIR/variance-unused-type-param.rs:22:19 | LL | struct WithBounds {} | ^ unused type parameter @@ -36,7 +47,7 @@ LL | struct WithBounds {} = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` error[E0392]: type parameter `T` is never used - --> $DIR/variance-unused-type-param.rs:22:24 + --> $DIR/variance-unused-type-param.rs:25:24 | LL | struct WithWhereBounds where T: Sized {} | ^ unused type parameter @@ -44,13 +55,13 @@ LL | struct WithWhereBounds where T: Sized {} = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` error[E0392]: type parameter `T` is never used - --> $DIR/variance-unused-type-param.rs:25:27 + --> $DIR/variance-unused-type-param.rs:28:27 | LL | struct WithOutlivesBounds {} | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0392`. From c02d0de871a99b08d013bd79941889fca53ae3c4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 17 Jul 2024 18:05:21 -0400 Subject: [PATCH 07/15] Account for structs that have unused params in nested types in fields --- compiler/rustc_hir_analysis/messages.ftl | 1 + .../rustc_hir_analysis/src/check/check.rs | 1 + .../rustc_hir_analysis/src/check/wfcheck.rs | 117 ++++++++++++++---- compiler/rustc_hir_analysis/src/errors.rs | 2 + .../inherent-impls-overflow.next.stderr | 23 ++-- .../inherent-impls-overflow.rs | 4 +- .../ui/variance/variance-unused-type-param.rs | 5 + .../variance-unused-type-param.stderr | 14 ++- 8 files changed, 129 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index ac46f981d9812..b43559f422533 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -553,6 +553,7 @@ hir_analysis_unused_generic_parameter = {$param_def_kind} `{$param_name}` is never used .label = unused {$param_def_kind} .const_param_help = if you intended `{$param_name}` to be a const parameter, use `const {$param_name}: /* Type */` instead + .usage_spans = `{$param_name}` is named here, but is likely unused in the containing type hir_analysis_unused_generic_parameter_adt_help = consider removing `{$param_name}`, referring to it in a field, or using a marker such as `{$phantom_data}` diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index bf8ef18c04fcc..dbc265ad3ff32 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1572,6 +1572,7 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD param_name, param_def_kind: tcx.def_descr(param.def_id), help: errors::UnusedGenericParameterHelp::TyAlias { param_name }, + usage_spans: vec![], const_param_help, }); diag.code(E0091); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index ffe3e61d9cf63..809427f86eef1 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1921,33 +1921,102 @@ fn report_bivariance<'tcx>( item, ); - if usage_spans.is_empty() { - let const_param_help = - matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds) - .then_some(()); - - let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter { - span: param.span, - param_name, - param_def_kind: tcx.def_descr(param.def_id.to_def_id()), - help, - const_param_help, - }); - diag.code(E0392); - diag.emit() - } else { - let diag = tcx.dcx().create_err(errors::RecursiveGenericParameter { - spans: usage_spans, - param_span: param.span, - param_name, - param_def_kind: tcx.def_descr(param.def_id.to_def_id()), - help, - note: (), - }); - diag.emit() + if !usage_spans.is_empty() { + // First, check if the ADT is (probably) cyclical. We say probably here, since + // we're not actually looking into substitutions, just walking through fields. + // And we only recurse into the fields of ADTs, and not the hidden types of + // opaques or anything else fancy. + let item_def_id = item.owner_id.to_def_id(); + let is_probably_cyclical = if matches!( + tcx.def_kind(item_def_id), + DefKind::Struct | DefKind::Union | DefKind::Enum + ) { + IsProbablyCyclical { tcx, adt_def_id: item_def_id, seen: Default::default() } + .visit_all_fields(tcx.adt_def(item_def_id)) + .is_break() + } else { + false + }; + // If the ADT is cyclical, then if at least one usage of the type parameter or + // the `Self` alias is present in the, then it's probably a cyclical struct, and + // we should call those parameter usages recursive rather than just saying they're + // unused... + // + // We currently report *all* of the parameter usages, since computing the exact + // subset is very involved, and the fact we're mentioning recursion at all is + // likely to guide the user in the right direction. + if is_probably_cyclical { + let diag = tcx.dcx().create_err(errors::RecursiveGenericParameter { + spans: usage_spans, + param_span: param.span, + param_name, + param_def_kind: tcx.def_descr(param.def_id.to_def_id()), + help, + note: (), + }); + return diag.emit(); + } + } + + let const_param_help = + matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds) + .then_some(()); + + let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter { + span: param.span, + param_name, + param_def_kind: tcx.def_descr(param.def_id.to_def_id()), + usage_spans, + help, + const_param_help, + }); + diag.code(E0392); + diag.emit() +} + +/// Detects cases where an ADT is trivially cyclical -- we want to detect this so +/// /we only mention that its parameters are used cyclically if the ADT is truly +/// cyclical. +/// +/// Notably, we don't consider substitutions here, so this may have false positives. +struct IsProbablyCyclical<'tcx> { + tcx: TyCtxt<'tcx>, + adt_def_id: DefId, + seen: FxHashSet, +} + +impl<'tcx> IsProbablyCyclical<'tcx> { + fn visit_all_fields(&mut self, adt_def: ty::AdtDef<'tcx>) -> ControlFlow<(), ()> { + for field in adt_def.all_fields() { + self.tcx.type_of(field.did).instantiate_identity().visit_with(self)?; + } + + ControlFlow::Continue(()) } } +impl<'tcx> TypeVisitor> for IsProbablyCyclical<'tcx> { + type Result = ControlFlow<(), ()>; + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> { + if let Some(adt_def) = t.ty_adt_def() { + if adt_def.did() == self.adt_def_id { + return ControlFlow::Break(()); + } + + if self.seen.insert(adt_def.did()) { + self.visit_all_fields(adt_def)?; + } + } + + t.super_visit_with(self) + } +} + +/// Collect usages of the `param_def_id` and `Res::SelfTyAlias` in the HIR. +/// +/// This is used to report places where the user has used parameters in a +/// non-variance-constraining way for better bivariance errors. struct CollectUsageSpans<'a> { spans: &'a mut Vec, param_def_id: DefId, diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 2edd8f54adba0..cec295e1c151a 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1597,6 +1597,8 @@ pub(crate) struct UnusedGenericParameter { pub span: Span, pub param_name: Ident, pub param_def_kind: &'static str, + #[label(hir_analysis_usage_spans)] + pub usage_spans: Vec, #[subdiagnostic] pub help: UnusedGenericParameterHelp, #[help(hir_analysis_const_param_help)] diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr index 192b5eebdaac8..48e7da9661210 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr @@ -4,27 +4,27 @@ error[E0275]: overflow evaluating the requirement `Loop == _` LL | impl Loop {} | ^^^^ -error: type parameter `T` is only used recursively - --> $DIR/inherent-impls-overflow.rs:14:24 +error[E0392]: type parameter `T` is never used + --> $DIR/inherent-impls-overflow.rs:14:12 | LL | type Poly0 = Poly1<(T,)>; - | - ^ + | ^ - `T` is named here, but is likely unused in the containing type | | - | type parameter must be used non-recursively in the definition + | unused type parameter | = help: consider removing `T` or referring to it in the body of the type alias - = note: all type parameters must be used in a non-recursive way in order to constrain their variance + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -error: type parameter `T` is only used recursively - --> $DIR/inherent-impls-overflow.rs:17:24 +error[E0392]: type parameter `T` is never used + --> $DIR/inherent-impls-overflow.rs:17:12 | LL | type Poly1 = Poly0<(T,)>; - | - ^ + | ^ - `T` is named here, but is likely unused in the containing type | | - | type parameter must be used non-recursively in the definition + | unused type parameter | = help: consider removing `T` or referring to it in the body of the type alias - = note: all type parameters must be used in a non-recursive way in order to constrain their variance + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error[E0275]: overflow evaluating the requirement `Poly0<()> == _` --> $DIR/inherent-impls-overflow.rs:21:6 @@ -36,4 +36,5 @@ LL | impl Poly0<()> {} error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0275`. +Some errors have detailed explanations: E0275, E0392. +For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs index 1397695a3fe41..98f0d811a47be 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs @@ -13,10 +13,10 @@ impl Loop {} type Poly0 = Poly1<(T,)>; //[current]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>` -//[next]~^^ ERROR type parameter `T` is only used recursively +//[next]~^^ ERROR type parameter `T` is never used type Poly1 = Poly0<(T,)>; //[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` -//[next]~^^ ERROR type parameter `T` is only used recursively +//[next]~^^ ERROR type parameter `T` is never used impl Poly0<()> {} //[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` diff --git a/tests/ui/variance/variance-unused-type-param.rs b/tests/ui/variance/variance-unused-type-param.rs index ada57ab0d0939..ef3c41ca5560c 100644 --- a/tests/ui/variance/variance-unused-type-param.rs +++ b/tests/ui/variance/variance-unused-type-param.rs @@ -28,4 +28,9 @@ struct WithWhereBounds where T: Sized {} struct WithOutlivesBounds {} //~^ ERROR parameter `T` is never used +struct DoubleNothing { +//~^ ERROR parameter `T` is never used + s: SomeStruct, +} + fn main() {} diff --git a/tests/ui/variance/variance-unused-type-param.stderr b/tests/ui/variance/variance-unused-type-param.stderr index 1a45bcba45a0f..c747532e62836 100644 --- a/tests/ui/variance/variance-unused-type-param.stderr +++ b/tests/ui/variance/variance-unused-type-param.stderr @@ -62,6 +62,18 @@ LL | struct WithOutlivesBounds {} | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` -error: aborting due to 7 previous errors +error[E0392]: type parameter `T` is never used + --> $DIR/variance-unused-type-param.rs:31:22 + | +LL | struct DoubleNothing { + | ^ unused type parameter +LL | +LL | s: SomeStruct, + | - `T` is named here, but is likely unused in the containing type + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0392`. From 0c5864f9064b7280972628c64cd83647127ddfb9 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 18 Jul 2024 14:50:49 +0300 Subject: [PATCH 08/15] check default config profiles on CI Signed-off-by: onur-ozkan --- src/ci/docker/host-x86_64/mingw-check/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 0d9c21c4487bf..c8d505406ff01 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -46,6 +46,8 @@ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 # We disable optimized compiler built-ins because that requires a C toolchain for the target. # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs. ENV SCRIPT python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ + # Ensure that default config profiles are not broken + for config_file in ../src/bootstrap/defaults/*.toml; do python3 ../x.py build --dry-run --config "$config_file"; done python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ python3 ../x.py clippy bootstrap -Dwarnings && \ python3 ../x.py clippy compiler library -Aclippy::all -Dclippy::correctness && \ From 6310da9ab9bbe61ae72232d93f2d518dd1be986d Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 18 Jul 2024 15:13:08 +0300 Subject: [PATCH 09/15] remove `debug-logging` default from tools profile `debug-logging` conflicts with `download-rustc` option, and doesn't really make sense to enable it for a profile that is used for tool development. Signed-off-by: onur-ozkan --- src/bootstrap/defaults/config.tools.toml | 4 ---- src/bootstrap/src/utils/change_tracker.rs | 5 +++++ src/ci/docker/host-x86_64/mingw-check/Dockerfile | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/defaults/config.tools.toml b/src/bootstrap/defaults/config.tools.toml index 6e6c366002792..75ad37ce33549 100644 --- a/src/bootstrap/defaults/config.tools.toml +++ b/src/bootstrap/defaults/config.tools.toml @@ -1,10 +1,6 @@ # These defaults are meant for contributors to tools which build on the # compiler, but do not modify it directly. [rust] -# This enables `RUSTC_LOG=debug`, avoiding confusing situations -# where adding `debug!()` appears to do nothing. -# However, it makes running the compiler slightly slower. -debug-logging = true # This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower. incremental = true # Download rustc from CI instead of building it from source. diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index ccab25e55a9c3..6a7c5c0f9b779 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -200,4 +200,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "`llvm.lld` is enabled by default for the dist profile. If set to false, `lld` will not be included in the dist build.", }, + ChangeInfo { + change_id: 127913, + severity: ChangeSeverity::Warning, + summary: "`debug-logging` option has been removed from the default `tools` profile.", + }, ]; diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index c8d505406ff01..bb1941f489bd6 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -47,7 +47,7 @@ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs. ENV SCRIPT python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ # Ensure that default config profiles are not broken - for config_file in ../src/bootstrap/defaults/*.toml; do python3 ../x.py build --dry-run --config "$config_file"; done + for config_file in ../src/bootstrap/defaults/*.toml; do python3 ../x.py build --dry-run --config \"$$config_file\"; done && \ python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ python3 ../x.py clippy bootstrap -Dwarnings && \ python3 ../x.py clippy compiler library -Aclippy::all -Dclippy::correctness && \ From 5901c8c0cbb45a9f17440b983ffd30112a70ba4f Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 18 Jul 2024 16:31:19 +0300 Subject: [PATCH 10/15] create `check-default-config-profiles.sh` for `mingw-check` Signed-off-by: onur-ozkan --- src/ci/docker/host-x86_64/mingw-check/Dockerfile | 4 ++-- .../mingw-check/check-default-config-profiles.sh | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100755 src/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index bb1941f489bd6..571378774be01 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -37,6 +37,7 @@ RUN sh /scripts/sccache.sh COPY host-x86_64/mingw-check/reuse-requirements.txt /tmp/ RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-requirements.txt +COPY host-x86_64/mingw-check/check-default-config-profiles.sh /scripts/ COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/ @@ -46,8 +47,7 @@ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 # We disable optimized compiler built-ins because that requires a C toolchain for the target. # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs. ENV SCRIPT python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ - # Ensure that default config profiles are not broken - for config_file in ../src/bootstrap/defaults/*.toml; do python3 ../x.py build --dry-run --config \"$$config_file\"; done && \ + /scripts/check-default-config-profiles.sh && \ python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ python3 ../x.py clippy bootstrap -Dwarnings && \ python3 ../x.py clippy compiler library -Aclippy::all -Dclippy::correctness && \ diff --git a/src/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh b/src/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh new file mode 100755 index 0000000000000..d706927d6d950 --- /dev/null +++ b/src/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# Runs bootstrap (in dry-run mode) with each default config profile to ensure they are not broken. + +set -euo pipefail + +config_dir="../src/bootstrap/defaults" + +# Loop through each configuration file in the directory +for config_file in "$config_dir"/*.toml; +do + python3 ../x.py check --config $config_file --dry-run +done From 67ec1326ee4e360b92dc6a6a3834bf8948532770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 16 Jul 2024 22:43:30 +0000 Subject: [PATCH 11/15] =?UTF-8?q?Fix=20ICE=20in=20suggestion=20caused=20by?= =?UTF-8?q?=20`=E2=A9=B5`=20being=20recovered=20as=20`=3D=3D`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The second suggestion shown here would previously incorrectly assume that the span corresponding to `⩵` was 2 bytes wide composed by 2 1 byte wide chars, so a span pointing at `==` could point only at one of the `=` to remove it. Instead, we now replace the whole thing (as we should have the whole time): ``` error: unknown start of token: \u{2a75} --> $DIR/unicode-double-equals-recovery.rs:1:16 | LL | const A: usize ⩵ 2; | ^ | help: Unicode character '⩵' (Two Consecutive Equals Signs) looks like '==' (Double Equals Sign), but it is not | LL | const A: usize == 2; | ~~ error: unexpected `==` --> $DIR/unicode-double-equals-recovery.rs:1:16 | LL | const A: usize ⩵ 2; | ^ | help: try using `=` instead | LL | const A: usize = 2; | ~ ``` --- compiler/rustc_parse/src/errors.rs | 3 +-- .../rustc_parse/src/parser/diagnostics.rs | 5 +--- .../ui/parser/issues/issue-101477-enum.stderr | 5 ++-- .../ui/parser/issues/issue-101477-let.stderr | 5 ++-- .../recover/unicode-double-equals-recovery.rs | 3 +++ .../unicode-double-equals-recovery.stderr | 24 +++++++++++++++++++ 6 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 tests/ui/parser/recover/unicode-double-equals-recovery.rs create mode 100644 tests/ui/parser/recover/unicode-double-equals-recovery.stderr diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 4222486034ba3..da0701efddb46 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -660,9 +660,8 @@ pub(crate) struct RemoveLet { #[diag(parse_use_eq_instead)] pub(crate) struct UseEqInstead { #[primary_span] + #[suggestion(style = "verbose", applicability = "machine-applicable", code = "=")] pub span: Span, - #[suggestion(style = "verbose", applicability = "machine-applicable", code = "")] - pub suggestion: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 0da7fefe6ed21..f24478581b89a 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -566,10 +566,7 @@ impl<'a> Parser<'a> { && expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Eq))) { // Likely typo: `=` → `==` in let expr or enum item - return Err(self.dcx().create_err(UseEqInstead { - span: self.token.span, - suggestion: self.token.span.with_lo(self.token.span.lo() + BytePos(1)), - })); + return Err(self.dcx().create_err(UseEqInstead { span: self.token.span })); } if self.token.is_keyword(kw::Move) && self.prev_token.is_keyword(kw::Async) { diff --git a/tests/ui/parser/issues/issue-101477-enum.stderr b/tests/ui/parser/issues/issue-101477-enum.stderr index c6dadeab8b33f..8d4efdd17f7b2 100644 --- a/tests/ui/parser/issues/issue-101477-enum.stderr +++ b/tests/ui/parser/issues/issue-101477-enum.stderr @@ -7,9 +7,8 @@ LL | B == 2 = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` help: try using `=` instead | -LL - B == 2 -LL + B = 2 - | +LL | B = 2 + | ~ error: expected item, found `==` --> $DIR/issue-101477-enum.rs:6:7 diff --git a/tests/ui/parser/issues/issue-101477-let.stderr b/tests/ui/parser/issues/issue-101477-let.stderr index 59e90c8102f75..d2671abbdea9e 100644 --- a/tests/ui/parser/issues/issue-101477-let.stderr +++ b/tests/ui/parser/issues/issue-101477-let.stderr @@ -6,9 +6,8 @@ LL | let x == 2; | help: try using `=` instead | -LL - let x == 2; -LL + let x = 2; - | +LL | let x = 2; + | ~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/recover/unicode-double-equals-recovery.rs b/tests/ui/parser/recover/unicode-double-equals-recovery.rs new file mode 100644 index 0000000000000..589f0a559bb00 --- /dev/null +++ b/tests/ui/parser/recover/unicode-double-equals-recovery.rs @@ -0,0 +1,3 @@ +const A: usize ⩵ 2; +//~^ ERROR unknown start of token: \u{2a75} +//~| ERROR unexpected `==` diff --git a/tests/ui/parser/recover/unicode-double-equals-recovery.stderr b/tests/ui/parser/recover/unicode-double-equals-recovery.stderr new file mode 100644 index 0000000000000..6e10dcce04a32 --- /dev/null +++ b/tests/ui/parser/recover/unicode-double-equals-recovery.stderr @@ -0,0 +1,24 @@ +error: unknown start of token: \u{2a75} + --> $DIR/unicode-double-equals-recovery.rs:1:16 + | +LL | const A: usize ⩵ 2; + | ^ + | +help: Unicode character '⩵' (Two Consecutive Equals Signs) looks like '==' (Double Equals Sign), but it is not + | +LL | const A: usize == 2; + | ~~ + +error: unexpected `==` + --> $DIR/unicode-double-equals-recovery.rs:1:16 + | +LL | const A: usize ⩵ 2; + | ^ + | +help: try using `=` instead + | +LL | const A: usize = 2; + | ~ + +error: aborting due to 2 previous errors + From 8dbb63a58591ed05f5b89398157b3212951858d2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 18 Jul 2024 13:01:52 -0400 Subject: [PATCH 12/15] Remove tag field from relations --- .../src/type_check/relate_tys.rs | 4 --- .../src/error_reporting/infer/mod.rs | 4 --- .../src/infer/outlives/test_type_match.rs | 15 ++++------- .../rustc_infer/src/infer/relate/combine.rs | 4 ++- .../src/infer/relate/generalize.rs | 4 --- compiler/rustc_infer/src/infer/relate/glb.rs | 9 +++---- .../rustc_infer/src/infer/relate/lattice.rs | 2 -- compiler/rustc_infer/src/infer/relate/lub.rs | 8 ++---- .../src/infer/relate/type_relating.rs | 9 +++---- .../src/traits/select/_match.rs | 12 +++------ compiler/rustc_type_ir/src/relate.rs | 25 +++++++++++-------- 11 files changed, 34 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index ea4a94e57b3b8..8da4d80badfec 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -313,10 +313,6 @@ impl<'bccx, 'tcx> TypeRelation> for NllTypeRelating<'_, 'bccx, 'tcx self.type_checker.infcx.tcx } - fn tag(&self) -> &'static str { - "nll::subtype" - } - #[instrument(skip(self, info), level = "trace", ret)] fn relate_with_variance>>( &mut self, diff --git a/compiler/rustc_infer/src/error_reporting/infer/mod.rs b/compiler/rustc_infer/src/error_reporting/infer/mod.rs index a4af721cf7547..1401d16108a37 100644 --- a/compiler/rustc_infer/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/mod.rs @@ -1934,10 +1934,6 @@ impl<'tcx> TypeRelation> for SameTypeModuloInfer<'_, 'tcx> { self.0.tcx } - fn tag(&self) -> &'static str { - "SameTypeModuloInfer" - } - fn relate_with_variance>>( &mut self, _variance: ty::Variance, diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs index d60d9113d91bf..c63eeaf812c4e 100644 --- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs +++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs @@ -110,7 +110,7 @@ impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> { /// Binds the pattern variable `br` to `value`; returns an `Err` if the pattern /// is already bound to a different value. - #[instrument(level = "debug", skip(self))] + #[instrument(level = "trace", skip(self))] fn bind( &mut self, br: ty::BoundRegion, @@ -133,10 +133,6 @@ impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> { } impl<'tcx> TypeRelation> for MatchAgainstHigherRankedOutlives<'tcx> { - fn tag(&self) -> &'static str { - "MatchAgainstHigherRankedOutlives" - } - fn cx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -154,13 +150,12 @@ impl<'tcx> TypeRelation> for MatchAgainstHigherRankedOutlives<'tcx> if variance != ty::Bivariant { self.relate(a, b) } else { Ok(a) } } - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self), level = "trace")] fn regions( &mut self, pattern: ty::Region<'tcx>, value: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { - debug!("self.pattern_depth = {:?}", self.pattern_depth); if let ty::RegionKind::ReBound(depth, br) = pattern.kind() && depth == self.pattern_depth { @@ -172,7 +167,7 @@ impl<'tcx> TypeRelation> for MatchAgainstHigherRankedOutlives<'tcx> } } - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self), level = "trace")] fn tys(&mut self, pattern: Ty<'tcx>, value: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { // FIXME(non_lifetime_binders): What to do here? if matches!(pattern.kind(), ty::Error(_) | ty::Bound(..)) { @@ -185,13 +180,12 @@ impl<'tcx> TypeRelation> for MatchAgainstHigherRankedOutlives<'tcx> } } - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self), level = "trace")] fn consts( &mut self, pattern: ty::Const<'tcx>, value: ty::Const<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { - debug!("{}.consts({:?}, {:?})", self.tag(), pattern, value); if pattern == value { Ok(pattern) } else { @@ -199,6 +193,7 @@ impl<'tcx> TypeRelation> for MatchAgainstHigherRankedOutlives<'tcx> } } + #[instrument(skip(self), level = "trace")] fn binders( &mut self, pattern: ty::Binder<'tcx, T>, diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index c93b89756f936..1dc03de4c8ba0 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -79,6 +79,7 @@ impl<'tcx> InferCtxt<'tcx> { where R: PredicateEmittingRelation>, { + debug!("super_combine_tys::<{}>({:?}, {:?})", std::any::type_name::(), a, b); debug_assert!(!a.has_escaping_bound_vars()); debug_assert!(!b.has_escaping_bound_vars()); @@ -174,9 +175,10 @@ impl<'tcx> InferCtxt<'tcx> { where R: PredicateEmittingRelation>, { - debug!("{}.consts({:?}, {:?})", relation.tag(), a, b); + debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::(), a, b); debug_assert!(!a.has_escaping_bound_vars()); debug_assert!(!b.has_escaping_bound_vars()); + if a == b { return Ok(a); } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index ace439545b84b..30cfbcae6b263 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -401,10 +401,6 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { self.infcx.tcx } - fn tag(&self) -> &'static str { - "Generalizer" - } - fn relate_item_args( &mut self, item_def_id: DefId, diff --git a/compiler/rustc_infer/src/infer/relate/glb.rs b/compiler/rustc_infer/src/infer/relate/glb.rs index 819a47fcf93fb..4f2cf2c43e7cc 100644 --- a/compiler/rustc_infer/src/infer/relate/glb.rs +++ b/compiler/rustc_infer/src/infer/relate/glb.rs @@ -23,10 +23,6 @@ impl<'combine, 'infcx, 'tcx> Glb<'combine, 'infcx, 'tcx> { } impl<'tcx> TypeRelation> for Glb<'_, '_, 'tcx> { - fn tag(&self) -> &'static str { - "Glb" - } - fn cx(&self) -> TyCtxt<'tcx> { self.fields.tcx() } @@ -47,17 +43,17 @@ impl<'tcx> TypeRelation> for Glb<'_, '_, 'tcx> { } } + #[instrument(skip(self), level = "trace")] fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { lattice::super_lattice_tys(self, a, b) } + #[instrument(skip(self), level = "trace")] fn regions( &mut self, a: ty::Region<'tcx>, b: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { - debug!("{}.regions({:?}, {:?})", self.tag(), a, b); - let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone())); // GLB(&'static u8, &'a u8) == &RegionLUB('static, 'a) u8 == &'static u8 Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().lub_regions( @@ -68,6 +64,7 @@ impl<'tcx> TypeRelation> for Glb<'_, '_, 'tcx> { )) } + #[instrument(skip(self), level = "trace")] fn consts( &mut self, a: ty::Const<'tcx>, diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs index 46e7466141a58..d1d870715622f 100644 --- a/compiler/rustc_infer/src/infer/relate/lattice.rs +++ b/compiler/rustc_infer/src/infer/relate/lattice.rs @@ -56,8 +56,6 @@ pub fn super_lattice_tys<'a, 'tcx: 'a, L>( where L: LatticeDir<'a, 'tcx>, { - debug!("{}", this.tag()); - if a == b { return Ok(a); } diff --git a/compiler/rustc_infer/src/infer/relate/lub.rs b/compiler/rustc_infer/src/infer/relate/lub.rs index 56d325c5dc1fd..2eb20f311cf4a 100644 --- a/compiler/rustc_infer/src/infer/relate/lub.rs +++ b/compiler/rustc_infer/src/infer/relate/lub.rs @@ -23,10 +23,6 @@ impl<'combine, 'infcx, 'tcx> Lub<'combine, 'infcx, 'tcx> { } impl<'tcx> TypeRelation> for Lub<'_, '_, 'tcx> { - fn tag(&self) -> &'static str { - "Lub" - } - fn cx(&self) -> TyCtxt<'tcx> { self.fields.tcx() } @@ -51,13 +47,12 @@ impl<'tcx> TypeRelation> for Lub<'_, '_, 'tcx> { lattice::super_lattice_tys(self, a, b) } + #[instrument(skip(self), level = "trace")] fn regions( &mut self, a: ty::Region<'tcx>, b: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { - debug!("{}.regions({:?}, {:?})", self.tag(), a, b); - let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone())); // LUB(&'static u8, &'a u8) == &RegionGLB('static, 'a) u8 == &'a u8 Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions( @@ -68,6 +63,7 @@ impl<'tcx> TypeRelation> for Lub<'_, '_, 'tcx> { )) } + #[instrument(skip(self), level = "trace")] fn consts( &mut self, a: ty::Const<'tcx>, diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 97bd858defbca..3fe3535428626 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -28,10 +28,6 @@ impl<'combine, 'infcx, 'tcx> TypeRelating<'combine, 'infcx, 'tcx> { } impl<'tcx> TypeRelation> for TypeRelating<'_, '_, 'tcx> { - fn tag(&self) -> &'static str { - "TypeRelating" - } - fn cx(&self) -> TyCtxt<'tcx> { self.fields.infcx.tcx } @@ -71,7 +67,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, '_, 'tcx> { r } - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self), level = "trace")] fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { if a == b { return Ok(a); @@ -166,12 +162,12 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, '_, 'tcx> { Ok(a) } + #[instrument(skip(self), level = "trace")] fn regions( &mut self, a: ty::Region<'tcx>, b: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { - debug!("{}.regions({:?}, {:?})", self.tag(), a, b); let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone())); match self.ambient_variance { @@ -209,6 +205,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, '_, 'tcx> { Ok(a) } + #[instrument(skip(self), level = "trace")] fn consts( &mut self, a: ty::Const<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/_match.rs b/compiler/rustc_trait_selection/src/traits/select/_match.rs index 8676f30a53b6e..7ead65721f9bb 100644 --- a/compiler/rustc_trait_selection/src/traits/select/_match.rs +++ b/compiler/rustc_trait_selection/src/traits/select/_match.rs @@ -3,7 +3,7 @@ use rustc_infer::infer::relate::{ }; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, InferConst, Ty, TyCtxt}; -use tracing::{debug, instrument}; +use tracing::instrument; /// A type "A" *matches* "B" if the fresh types in B could be /// instantiated with values so as to make it equal to A. Matching is @@ -32,10 +32,6 @@ impl<'tcx> MatchAgainstFreshVars<'tcx> { } impl<'tcx> TypeRelation> for MatchAgainstFreshVars<'tcx> { - fn tag(&self) -> &'static str { - "MatchAgainstFreshVars" - } - fn cx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -50,7 +46,7 @@ impl<'tcx> TypeRelation> for MatchAgainstFreshVars<'tcx> { self.relate(a, b) } - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self), level = "trace")] fn regions( &mut self, a: ty::Region<'tcx>, @@ -59,7 +55,7 @@ impl<'tcx> TypeRelation> for MatchAgainstFreshVars<'tcx> { Ok(a) } - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self), level = "trace")] fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { if a == b { return Ok(a); @@ -83,12 +79,12 @@ impl<'tcx> TypeRelation> for MatchAgainstFreshVars<'tcx> { } } + #[instrument(skip(self), level = "trace")] fn consts( &mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { - debug!("{}.consts({:?}, {:?})", self.tag(), a, b); if a == b { return Ok(a); } diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index a8f48d14af5ce..ae840ec021033 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -1,7 +1,7 @@ use std::iter; use rustc_ast_ir::Mutability; -use tracing::{debug, instrument}; +use tracing::{instrument, trace}; use crate::error::{ExpectedFound, TypeError}; use crate::fold::TypeFoldable; @@ -58,9 +58,6 @@ impl VarianceDiagInfo { pub trait TypeRelation: Sized { fn cx(&self) -> I; - /// Returns a static string we can use for printouts. - fn tag(&self) -> &'static str; - /// Generic relation routine suitable for most anything. fn relate>(&mut self, a: T, b: T) -> RelateResult { Relate::relate(self, a, b) @@ -69,17 +66,13 @@ pub trait TypeRelation: Sized { /// Relate the two args for the given item. The default /// is to look up the variance for the item and proceed /// accordingly. + #[instrument(skip(self), level = "trace")] fn relate_item_args( &mut self, item_def_id: I::DefId, a_arg: I::GenericArgs, b_arg: I::GenericArgs, ) -> RelateResult { - debug!( - "relate_item_args(item_def_id={:?}, a_arg={:?}, b_arg={:?})", - item_def_id, a_arg, b_arg - ); - let cx = self.cx(); let opt_variances = cx.variances_of(item_def_id); relate_args_with_variances(self, item_def_id, opt_variances, a_arg, b_arg, true) @@ -571,7 +564,12 @@ pub fn structurally_relate_consts>( mut a: I::Const, mut b: I::Const, ) -> RelateResult { - debug!("{}.structurally_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b); + trace!( + "structurally_relate_consts::<{}>(a = {:?}, b = {:?})", + std::any::type_name::(), + a, + b + ); let cx = relation.cx(); if cx.features().generic_const_exprs() { @@ -579,7 +577,12 @@ pub fn structurally_relate_consts>( b = cx.expand_abstract_consts(b); } - debug!("{}.structurally_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b); + trace!( + "structurally_relate_consts::<{}>(normed_a = {:?}, normed_b = {:?})", + std::any::type_name::(), + a, + b + ); // Currently, the values that can be unified are primitive types, // and those that derive both `PartialEq` and `Eq`, corresponding From abf92c049dcdacdadb0a7f45426df30f2dbdb0dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 11 Jul 2024 20:12:48 +0000 Subject: [PATCH 13/15] Use more accurate span for `addr_of!` suggestion Use a multipart suggestion instead of a single whole-span replacement: ``` error[E0796]: creating a shared reference to a mutable static --> $DIR/reference-to-mut-static-unsafe-fn.rs:10:18 | LL | let _y = &X; | ^^ shared reference to mutable static | = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior help: use `addr_of!` instead to create a raw pointer | LL | let _y = addr_of!(X); | ~~~~~~~~~ + ``` --- compiler/rustc_hir_analysis/src/check/errs.rs | 35 ++++++++----- compiler/rustc_hir_analysis/src/errors.rs | 52 +++++-------------- .../ui/abi/statics/static-mut-foreign.stderr | 4 +- .../borrowck-access-permissions.stderr | 2 +- ...rowck-unsafe-static-mutable-borrows.stderr | 2 +- tests/ui/borrowck/issue-20801.stderr | 2 +- ...5492-borrowck-migrate-scans-parents.stderr | 6 +-- tests/ui/consts/const_let_assign2.stderr | 2 +- ...issue-23338-ensure-param-drop-order.stderr | 2 +- .../drop/issue-23611-enum-swap-in-drop.stderr | 2 +- tests/ui/issues/issue-54410.stderr | 2 +- ...local-static-mut-borrow-outlives-fn.stderr | 2 +- .../reference-to-mut-static-safe.e2021.stderr | 2 +- .../reference-to-mut-static-safe.e2024.stderr | 2 +- .../reference-to-mut-static-unsafe-fn.stderr | 12 ++--- .../reference-to-mut-static.e2021.stderr | 12 ++--- .../reference-to-mut-static.e2024.stderr | 12 ++--- .../ui/static/safe-extern-statics-mut.stderr | 4 +- tests/ui/statics/issue-15261.stderr | 2 +- tests/ui/statics/static-mut-xc.stderr | 4 +- tests/ui/statics/static-recursive.stderr | 2 +- 21 files changed, 74 insertions(+), 91 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs index 17cb20df75463..19a0476e63016 100644 --- a/compiler/rustc_hir_analysis/src/check/errs.rs +++ b/compiler/rustc_hir_analysis/src/check/errs.rs @@ -1,5 +1,4 @@ use rustc_hir as hir; -use rustc_hir_pretty::qpath_to_string; use rustc_lint_defs::builtin::STATIC_MUT_REFS; use rustc_middle::ty::{Mutability, TyCtxt}; use rustc_span::Span; @@ -12,9 +11,17 @@ pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) { let hir_id = expr.hir_id; if let hir::ExprKind::AddrOf(borrow_kind, m, expr) = expr.kind && matches!(borrow_kind, hir::BorrowKind::Ref) - && let Some(var) = path_if_static_mut(tcx, expr) + && path_if_static_mut(expr) { - handle_static_mut_ref(tcx, span, var, span.edition().at_least_rust_2024(), m, hir_id); + handle_static_mut_ref( + tcx, + span, + span.with_hi(expr.span.lo()), + span.shrink_to_hi(), + span.edition().at_least_rust_2024(), + m, + hir_id, + ); } } @@ -24,12 +31,13 @@ pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) { && let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind && let hir::ByRef::Yes(rmutbl) = ba.0 && let Some(init) = loc.init - && let Some(var) = path_if_static_mut(tcx, init) + && path_if_static_mut(init) { handle_static_mut_ref( tcx, init.span, - var, + init.span.shrink_to_lo(), + init.span.shrink_to_hi(), loc.span.edition().at_least_rust_2024(), rmutbl, stmt.hir_id, @@ -37,38 +45,39 @@ pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) { } } -fn path_if_static_mut(tcx: TyCtxt<'_>, expr: &hir::Expr<'_>) -> Option { +fn path_if_static_mut(expr: &hir::Expr<'_>) -> bool { if let hir::ExprKind::Path(qpath) = expr.kind && let hir::QPath::Resolved(_, path) = qpath && let hir::def::Res::Def(def_kind, _) = path.res && let hir::def::DefKind::Static { safety: _, mutability: Mutability::Mut, nested: false } = def_kind { - return Some(qpath_to_string(&tcx, &qpath)); + return true; } - None + false } fn handle_static_mut_ref( tcx: TyCtxt<'_>, span: Span, - var: String, + lo: Span, + hi: Span, e2024: bool, mutable: Mutability, hir_id: hir::HirId, ) { if e2024 { let (sugg, shared) = if mutable == Mutability::Mut { - (errors::StaticMutRefSugg::Mut { span, var }, "mutable") + (errors::MutRefSugg::Mut { lo, hi }, "mutable") } else { - (errors::StaticMutRefSugg::Shared { span, var }, "shared") + (errors::MutRefSugg::Shared { lo, hi }, "shared") }; tcx.dcx().emit_err(errors::StaticMutRef { span, sugg, shared }); } else { let (sugg, shared) = if mutable == Mutability::Mut { - (errors::RefOfMutStaticSugg::Mut { span, var }, "mutable") + (errors::MutRefSugg::Mut { lo, hi }, "mutable") } else { - (errors::RefOfMutStaticSugg::Shared { span, var }, "shared") + (errors::MutRefSugg::Shared { lo, hi }, "shared") }; tcx.emit_node_span_lint( STATIC_MUT_REFS, diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 0ee87a13e9e37..1e94fde792646 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1500,33 +1500,33 @@ pub struct StaticMutRef<'a> { #[label] pub span: Span, #[subdiagnostic] - pub sugg: StaticMutRefSugg, + pub sugg: MutRefSugg, pub shared: &'a str, } #[derive(Subdiagnostic)] -pub enum StaticMutRefSugg { - #[suggestion( +pub enum MutRefSugg { + #[multipart_suggestion( hir_analysis_suggestion, style = "verbose", - code = "addr_of!({var})", applicability = "maybe-incorrect" )] Shared { - #[primary_span] - span: Span, - var: String, + #[suggestion_part(code = "addr_of!(")] + lo: Span, + #[suggestion_part(code = ")")] + hi: Span, }, - #[suggestion( + #[multipart_suggestion( hir_analysis_suggestion_mut, style = "verbose", - code = "addr_of_mut!({var})", applicability = "maybe-incorrect" )] Mut { - #[primary_span] - span: Span, - var: String, + #[suggestion_part(code = "addr_of_mut!(")] + lo: Span, + #[suggestion_part(code = ")")] + hi: Span, }, } @@ -1539,36 +1539,10 @@ pub struct RefOfMutStatic<'a> { #[label] pub span: Span, #[subdiagnostic] - pub sugg: RefOfMutStaticSugg, + pub sugg: MutRefSugg, pub shared: &'a str, } -#[derive(Subdiagnostic)] -pub enum RefOfMutStaticSugg { - #[suggestion( - hir_analysis_suggestion, - style = "verbose", - code = "addr_of!({var})", - applicability = "maybe-incorrect" - )] - Shared { - #[primary_span] - span: Span, - var: String, - }, - #[suggestion( - hir_analysis_suggestion_mut, - style = "verbose", - code = "addr_of_mut!({var})", - applicability = "maybe-incorrect" - )] - Mut { - #[primary_span] - span: Span, - var: String, - }, -} - #[derive(Diagnostic)] #[diag(hir_analysis_not_supported_delegation)] pub struct NotSupportedDelegation<'a> { diff --git a/tests/ui/abi/statics/static-mut-foreign.stderr b/tests/ui/abi/statics/static-mut-foreign.stderr index 983325c1abd09..0c4bd5382a1f0 100644 --- a/tests/ui/abi/statics/static-mut-foreign.stderr +++ b/tests/ui/abi/statics/static-mut-foreign.stderr @@ -11,7 +11,7 @@ LL | static_bound(&rust_dbg_static_mut); help: use `addr_of!` instead to create a raw pointer | LL | static_bound(addr_of!(rust_dbg_static_mut)); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~ + warning: creating a mutable reference to mutable static is discouraged --> $DIR/static-mut-foreign.rs:33:22 @@ -25,7 +25,7 @@ LL | static_bound_set(&mut rust_dbg_static_mut); help: use `addr_of_mut!` instead to create a raw pointer | LL | static_bound_set(addr_of_mut!(rust_dbg_static_mut)); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~ + warning: 2 warnings emitted diff --git a/tests/ui/borrowck/borrowck-access-permissions.stderr b/tests/ui/borrowck/borrowck-access-permissions.stderr index 11e2b63bd6cd7..36e259fa6e8ee 100644 --- a/tests/ui/borrowck/borrowck-access-permissions.stderr +++ b/tests/ui/borrowck/borrowck-access-permissions.stderr @@ -11,7 +11,7 @@ LL | let _y2 = &mut static_x_mut; help: use `addr_of_mut!` instead to create a raw pointer | LL | let _y2 = addr_of_mut!(static_x_mut); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~ + error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-access-permissions.rs:10:19 diff --git a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr index 354d70eb1ad49..a727c9414c556 100644 --- a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr +++ b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr @@ -11,7 +11,7 @@ LL | let sfoo: *mut Foo = &mut SFOO; help: use `addr_of_mut!` instead to create a raw pointer | LL | let sfoo: *mut Foo = addr_of_mut!(SFOO); - | ~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~ + warning: 1 warning emitted diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr index c1d06ac3e2196..769b34831c120 100644 --- a/tests/ui/borrowck/issue-20801.stderr +++ b/tests/ui/borrowck/issue-20801.stderr @@ -11,7 +11,7 @@ LL | unsafe { &mut GLOBAL_MUT_T } help: use `addr_of_mut!` instead to create a raw pointer | LL | unsafe { addr_of_mut!(GLOBAL_MUT_T) } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~ + error[E0507]: cannot move out of a mutable reference --> $DIR/issue-20801.rs:27:22 diff --git a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr index ff5ec1db34634..72fd0d8ce161e 100644 --- a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr +++ b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr @@ -11,7 +11,7 @@ LL | c1(&mut Y); help: use `addr_of_mut!` instead to create a raw pointer | LL | c1(addr_of_mut!(Y)); - | ~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~ + warning: creating a mutable reference to mutable static is discouraged --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:27:16 @@ -25,7 +25,7 @@ LL | c1(&mut Z); help: use `addr_of_mut!` instead to create a raw pointer | LL | c1(addr_of_mut!(Z)); - | ~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~ + warning: creating a mutable reference to mutable static is discouraged --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:64:37 @@ -39,7 +39,7 @@ LL | borrowck_closures_unique::e(&mut X); help: use `addr_of_mut!` instead to create a raw pointer | LL | borrowck_closures_unique::e(addr_of_mut!(X)); - | ~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~ + error[E0594]: cannot assign to `x`, as it is not declared as mutable --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:9:46 diff --git a/tests/ui/consts/const_let_assign2.stderr b/tests/ui/consts/const_let_assign2.stderr index 5ae8fd353dd78..87b94a7be67e2 100644 --- a/tests/ui/consts/const_let_assign2.stderr +++ b/tests/ui/consts/const_let_assign2.stderr @@ -11,7 +11,7 @@ LL | let ptr = unsafe { &mut BB }; help: use `addr_of_mut!` instead to create a raw pointer | LL | let ptr = unsafe { addr_of_mut!(BB) }; - | ~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~ + warning: 1 warning emitted diff --git a/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr b/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr index de1194e74b40d..9126e6023913d 100644 --- a/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr +++ b/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr @@ -11,7 +11,7 @@ LL | (mem::size_of_val(&trails) * 8) as u32 help: use `addr_of!` instead to create a raw pointer | LL | (mem::size_of_val(addr_of!(trails)) * 8) as u32 - | ~~~~~~~~~~~~~~~~ + | ~~~~~~~~~ + warning: 1 warning emitted diff --git a/tests/ui/drop/issue-23611-enum-swap-in-drop.stderr b/tests/ui/drop/issue-23611-enum-swap-in-drop.stderr index bdf46abea8a1f..6da8741680274 100644 --- a/tests/ui/drop/issue-23611-enum-swap-in-drop.stderr +++ b/tests/ui/drop/issue-23611-enum-swap-in-drop.stderr @@ -11,7 +11,7 @@ LL | (mem::size_of_val(&trails) * 8) as u32 help: use `addr_of!` instead to create a raw pointer | LL | (mem::size_of_val(addr_of!(trails)) * 8) as u32 - | ~~~~~~~~~~~~~~~~ + | ~~~~~~~~~ + warning: 1 warning emitted diff --git a/tests/ui/issues/issue-54410.stderr b/tests/ui/issues/issue-54410.stderr index 7cc67ab72c396..6cc5cd95e2f7d 100644 --- a/tests/ui/issues/issue-54410.stderr +++ b/tests/ui/issues/issue-54410.stderr @@ -19,7 +19,7 @@ LL | println!("{:p}", unsafe { &symbol }); help: use `addr_of!` instead to create a raw pointer | LL | println!("{:p}", unsafe { addr_of!(symbol) }); - | ~~~~~~~~~~~~~~~~ + | ~~~~~~~~~ + error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr index 82065cc06ea1d..a6d4f9a2a5cb1 100644 --- a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr +++ b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr @@ -11,7 +11,7 @@ LL | S1 { a: unsafe { &mut X1 } } help: use `addr_of_mut!` instead to create a raw pointer | LL | S1 { a: unsafe { addr_of_mut!(X1) } } - | ~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~ + warning: 1 warning emitted diff --git a/tests/ui/static/reference-to-mut-static-safe.e2021.stderr b/tests/ui/static/reference-to-mut-static-safe.e2021.stderr index 9ea34290e36d6..9fdfc00dfcd91 100644 --- a/tests/ui/static/reference-to-mut-static-safe.e2021.stderr +++ b/tests/ui/static/reference-to-mut-static-safe.e2021.stderr @@ -11,7 +11,7 @@ LL | let _x = &X; help: use `addr_of!` instead to create a raw pointer | LL | let _x = addr_of!(X); - | ~~~~~~~~~~~ + | ~~~~~~~~~ + error[E0133]: use of mutable static is unsafe and requires unsafe function or block --> $DIR/reference-to-mut-static-safe.rs:9:15 diff --git a/tests/ui/static/reference-to-mut-static-safe.e2024.stderr b/tests/ui/static/reference-to-mut-static-safe.e2024.stderr index c57b418d7b2e2..b3e0c84d1d89d 100644 --- a/tests/ui/static/reference-to-mut-static-safe.e2024.stderr +++ b/tests/ui/static/reference-to-mut-static-safe.e2024.stderr @@ -8,7 +8,7 @@ LL | let _x = &X; help: use `addr_of!` instead to create a raw pointer | LL | let _x = addr_of!(X); - | ~~~~~~~~~~~ + | ~~~~~~~~~ + error[E0133]: use of mutable static is unsafe and requires unsafe block --> $DIR/reference-to-mut-static-safe.rs:9:15 diff --git a/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr b/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr index b24943cf59363..ca9cfbf7ac787 100644 --- a/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr +++ b/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr @@ -8,7 +8,7 @@ LL | let _y = &X; help: use `addr_of!` instead to create a raw pointer | LL | let _y = addr_of!(X); - | ~~~~~~~~~~~ + | ~~~~~~~~~ + error[E0796]: creating a shared reference to a mutable static --> $DIR/reference-to-mut-static-unsafe-fn.rs:13:22 @@ -20,7 +20,7 @@ LL | let ref _a = X; help: use `addr_of!` instead to create a raw pointer | LL | let ref _a = addr_of!(X); - | ~~~~~~~~~~~ + | +++++++++ + error[E0796]: creating a mutable reference to a mutable static --> $DIR/reference-to-mut-static-unsafe-fn.rs:16:26 @@ -32,7 +32,7 @@ LL | let ref mut _a = X; help: use `addr_of_mut!` instead to create a raw pointer | LL | let ref mut _a = addr_of_mut!(X); - | ~~~~~~~~~~~~~~~ + | +++++++++++++ + error[E0796]: creating a shared reference to a mutable static --> $DIR/reference-to-mut-static-unsafe-fn.rs:19:25 @@ -44,7 +44,7 @@ LL | let (_b, _c) = (&X, &mut Y); help: use `addr_of!` instead to create a raw pointer | LL | let (_b, _c) = (addr_of!(X), &mut Y); - | ~~~~~~~~~~~ + | ~~~~~~~~~ + error[E0796]: creating a mutable reference to a mutable static --> $DIR/reference-to-mut-static-unsafe-fn.rs:19:29 @@ -56,7 +56,7 @@ LL | let (_b, _c) = (&X, &mut Y); help: use `addr_of_mut!` instead to create a raw pointer | LL | let (_b, _c) = (&X, addr_of_mut!(Y)); - | ~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~ + error[E0796]: creating a shared reference to a mutable static --> $DIR/reference-to-mut-static-unsafe-fn.rs:23:13 @@ -68,7 +68,7 @@ LL | foo(&X); help: use `addr_of!` instead to create a raw pointer | LL | foo(addr_of!(X)); - | ~~~~~~~~~~~ + | ~~~~~~~~~ + error: aborting due to 6 previous errors diff --git a/tests/ui/static/reference-to-mut-static.e2021.stderr b/tests/ui/static/reference-to-mut-static.e2021.stderr index f477e5ac6c5c2..667d7602f34a5 100644 --- a/tests/ui/static/reference-to-mut-static.e2021.stderr +++ b/tests/ui/static/reference-to-mut-static.e2021.stderr @@ -15,7 +15,7 @@ LL | #![deny(static_mut_refs)] help: use `addr_of!` instead to create a raw pointer | LL | let _y = addr_of!(X); - | ~~~~~~~~~~~ + | ~~~~~~~~~ + error: creating a mutable reference to mutable static is discouraged --> $DIR/reference-to-mut-static.rs:20:18 @@ -29,7 +29,7 @@ LL | let _y = &mut X; help: use `addr_of_mut!` instead to create a raw pointer | LL | let _y = addr_of_mut!(X); - | ~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~ + error: creating a shared reference to mutable static is discouraged --> $DIR/reference-to-mut-static.rs:28:22 @@ -43,7 +43,7 @@ LL | let ref _a = X; help: use `addr_of!` instead to create a raw pointer | LL | let ref _a = addr_of!(X); - | ~~~~~~~~~~~ + | +++++++++ + error: creating a shared reference to mutable static is discouraged --> $DIR/reference-to-mut-static.rs:32:25 @@ -57,7 +57,7 @@ LL | let (_b, _c) = (&X, &Y); help: use `addr_of!` instead to create a raw pointer | LL | let (_b, _c) = (addr_of!(X), &Y); - | ~~~~~~~~~~~ + | ~~~~~~~~~ + error: creating a shared reference to mutable static is discouraged --> $DIR/reference-to-mut-static.rs:32:29 @@ -71,7 +71,7 @@ LL | let (_b, _c) = (&X, &Y); help: use `addr_of!` instead to create a raw pointer | LL | let (_b, _c) = (&X, addr_of!(Y)); - | ~~~~~~~~~~~ + | ~~~~~~~~~ + error: creating a shared reference to mutable static is discouraged --> $DIR/reference-to-mut-static.rs:38:13 @@ -85,7 +85,7 @@ LL | foo(&X); help: use `addr_of!` instead to create a raw pointer | LL | foo(addr_of!(X)); - | ~~~~~~~~~~~ + | ~~~~~~~~~ + error: aborting due to 6 previous errors diff --git a/tests/ui/static/reference-to-mut-static.e2024.stderr b/tests/ui/static/reference-to-mut-static.e2024.stderr index b18e214e84fea..e77f43554666c 100644 --- a/tests/ui/static/reference-to-mut-static.e2024.stderr +++ b/tests/ui/static/reference-to-mut-static.e2024.stderr @@ -8,7 +8,7 @@ LL | let _y = &X; help: use `addr_of!` instead to create a raw pointer | LL | let _y = addr_of!(X); - | ~~~~~~~~~~~ + | ~~~~~~~~~ + error[E0796]: creating a mutable reference to a mutable static --> $DIR/reference-to-mut-static.rs:20:18 @@ -20,7 +20,7 @@ LL | let _y = &mut X; help: use `addr_of_mut!` instead to create a raw pointer | LL | let _y = addr_of_mut!(X); - | ~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~ + error[E0796]: creating a shared reference to a mutable static --> $DIR/reference-to-mut-static.rs:28:22 @@ -32,7 +32,7 @@ LL | let ref _a = X; help: use `addr_of!` instead to create a raw pointer | LL | let ref _a = addr_of!(X); - | ~~~~~~~~~~~ + | +++++++++ + error[E0796]: creating a shared reference to a mutable static --> $DIR/reference-to-mut-static.rs:32:25 @@ -44,7 +44,7 @@ LL | let (_b, _c) = (&X, &Y); help: use `addr_of!` instead to create a raw pointer | LL | let (_b, _c) = (addr_of!(X), &Y); - | ~~~~~~~~~~~ + | ~~~~~~~~~ + error[E0796]: creating a shared reference to a mutable static --> $DIR/reference-to-mut-static.rs:32:29 @@ -56,7 +56,7 @@ LL | let (_b, _c) = (&X, &Y); help: use `addr_of!` instead to create a raw pointer | LL | let (_b, _c) = (&X, addr_of!(Y)); - | ~~~~~~~~~~~ + | ~~~~~~~~~ + error[E0796]: creating a shared reference to a mutable static --> $DIR/reference-to-mut-static.rs:38:13 @@ -68,7 +68,7 @@ LL | foo(&X); help: use `addr_of!` instead to create a raw pointer | LL | foo(addr_of!(X)); - | ~~~~~~~~~~~ + | ~~~~~~~~~ + error: aborting due to 6 previous errors diff --git a/tests/ui/static/safe-extern-statics-mut.stderr b/tests/ui/static/safe-extern-statics-mut.stderr index 9a4b651405f23..7705a897e2717 100644 --- a/tests/ui/static/safe-extern-statics-mut.stderr +++ b/tests/ui/static/safe-extern-statics-mut.stderr @@ -11,7 +11,7 @@ LL | let rb = &B; help: use `addr_of!` instead to create a raw pointer | LL | let rb = addr_of!(B); - | ~~~~~~~~~~~ + | ~~~~~~~~~ + warning: creating a shared reference to mutable static is discouraged --> $DIR/safe-extern-statics-mut.rs:15:15 @@ -25,7 +25,7 @@ LL | let xrb = &XB; help: use `addr_of!` instead to create a raw pointer | LL | let xrb = addr_of!(XB); - | ~~~~~~~~~~~~ + | ~~~~~~~~~ + error[E0133]: use of mutable static is unsafe and requires unsafe function or block --> $DIR/safe-extern-statics-mut.rs:11:13 diff --git a/tests/ui/statics/issue-15261.stderr b/tests/ui/statics/issue-15261.stderr index c31793f3d8f15..6035eef5b7140 100644 --- a/tests/ui/statics/issue-15261.stderr +++ b/tests/ui/statics/issue-15261.stderr @@ -11,7 +11,7 @@ LL | static n: &'static usize = unsafe { &n_mut }; help: use `addr_of!` instead to create a raw pointer | LL | static n: &'static usize = unsafe { addr_of!(n_mut) }; - | ~~~~~~~~~~~~~~~ + | ~~~~~~~~~ + warning: 1 warning emitted diff --git a/tests/ui/statics/static-mut-xc.stderr b/tests/ui/statics/static-mut-xc.stderr index d381328c07178..9751f754332c9 100644 --- a/tests/ui/statics/static-mut-xc.stderr +++ b/tests/ui/statics/static-mut-xc.stderr @@ -11,7 +11,7 @@ LL | static_bound(&static_mut_xc::a); help: use `addr_of!` instead to create a raw pointer | LL | static_bound(addr_of!(static_mut_xc::a)); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~ + warning: creating a mutable reference to mutable static is discouraged --> $DIR/static-mut-xc.rs:30:22 @@ -25,7 +25,7 @@ LL | static_bound_set(&mut static_mut_xc::a); help: use `addr_of_mut!` instead to create a raw pointer | LL | static_bound_set(addr_of_mut!(static_mut_xc::a)); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~ + warning: 2 warnings emitted diff --git a/tests/ui/statics/static-recursive.stderr b/tests/ui/statics/static-recursive.stderr index cd285c6c2a463..a7a1a1610afbb 100644 --- a/tests/ui/statics/static-recursive.stderr +++ b/tests/ui/statics/static-recursive.stderr @@ -11,7 +11,7 @@ LL | static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 }; help: use `addr_of!` instead to create a raw pointer | LL | static mut S: *const u8 = unsafe { addr_of!(S) as *const *const u8 as *const u8 }; - | ~~~~~~~~~~~ + | ~~~~~~~~~ + warning: 1 warning emitted From fed059270a2fda61b7ea7393ed7b3f78d33fad32 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 17 Jul 2024 14:33:10 +0200 Subject: [PATCH 14/15] Wrap too long item name and improve the item list display a bit --- src/librustdoc/html/static/css/rustdoc.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index cb8b82e8bde0a..a305335e0b3e5 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -2174,6 +2174,14 @@ in src-script.js and main.js padding: 2px 4px; box-shadow: 0 0 4px var(--main-background-color); } + + .item-table > li > .item-name { + width: 33%; + } + .item-table > li > div { + padding-bottom: 5px; + word-break: break-all; + } } @media print { From c820a2392ce90722c2d8d0e1050b6194ac532b78 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 18 Jul 2024 20:48:10 +0200 Subject: [PATCH 15/15] Add test for size of items in the items list --- tests/rustdoc-gui/src/lib2/lib.rs | 1 + tests/rustdoc-gui/type-declation-overflow.goml | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/rustdoc-gui/src/lib2/lib.rs b/tests/rustdoc-gui/src/lib2/lib.rs index b467b04405233..2467c7adae1a3 100644 --- a/tests/rustdoc-gui/src/lib2/lib.rs +++ b/tests/rustdoc-gui/src/lib2/lib.rs @@ -117,6 +117,7 @@ pub mod too_long { pub type ReallyLongTypeNameLongLongLong = Option *const u8>; + /// Short doc. pub const ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong: u32 = 0; /// This also has a really long doccomment. Lorem ipsum dolor sit amet, diff --git a/tests/rustdoc-gui/type-declation-overflow.goml b/tests/rustdoc-gui/type-declation-overflow.goml index 3709aa102661f..fdf84c3fd2950 100644 --- a/tests/rustdoc-gui/type-declation-overflow.goml +++ b/tests/rustdoc-gui/type-declation-overflow.goml @@ -16,7 +16,11 @@ assert-property: ("pre.item-decl", {"scrollWidth": "1324"}) // In the table-ish view on the module index, the name should not be wrapped more than necessary. go-to: "file://" + |DOC_PATH| + "/lib2/too_long/index.html" -assert-property: (".item-table .struct", {"offsetWidth": "684"}) + +// We'll ensure that items with short documentation have the same width. +store-property: ("//*[@class='item-table']//*[@class='struct']/..", {"offsetWidth": offset_width}) +assert: |offset_width| == "277" +assert-property: ("//*[@class='item-table']//*[@class='constant']/..", {"offsetWidth": |offset_width|}) // We now make the same check on type declaration... go-to: "file://" + |DOC_PATH| + "/lib2/too_long/type.ReallyLongTypeNameLongLongLong.html"