From 7ff71e5fb4c025b261f6c7e7eb996b36382c178e Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 13 Jul 2024 12:43:35 +0800 Subject: [PATCH 001/246] Remove invalid help diagnostics for const pointer --- .../src/diagnostics/mutability_errors.rs | 33 ++++++++++++------- ...suggest_raw_pointer_syntax-issue-127562.rs | 7 ++++ ...est_raw_pointer_syntax-issue-127562.stderr | 9 +++++ 3 files changed, 37 insertions(+), 12 deletions(-) create mode 100644 tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.rs create mode 100644 tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 26b0d23b1664..0b6c527b8c08 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1146,6 +1146,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { } // don't create labels for compiler-generated spans Some(_) => None, + // don't create labels for the span not from user's code + None if opt_assignment_rhs_span + .is_some_and(|span| self.infcx.tcx.sess.source_map().is_imported(span)) => + { + None + } None => { let (has_sugg, decl_span, sugg) = if name != kw::SelfLower { suggest_ampmut( @@ -1198,18 +1204,21 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { sugg.push(s); } - err.multipart_suggestion_verbose( - format!( - "consider changing this to be a mutable {pointer_desc}{}", - if is_trait_sig { - " in the `impl` method and the `trait` definition" - } else { - "" - } - ), - sugg, - Applicability::MachineApplicable, - ); + if sugg.iter().all(|(span, _)| !self.infcx.tcx.sess.source_map().is_imported(*span)) + { + err.multipart_suggestion_verbose( + format!( + "consider changing this to be a mutable {pointer_desc}{}", + if is_trait_sig { + " in the `impl` method and the `trait` definition" + } else { + "" + } + ), + sugg, + Applicability::MachineApplicable, + ); + } } Some((false, err_label_span, message, _)) => { let def_id = self.body.source.def_id(); diff --git a/tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.rs b/tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.rs new file mode 100644 index 000000000000..03b736e60b63 --- /dev/null +++ b/tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.rs @@ -0,0 +1,7 @@ +fn main() { + let val = 2; + let ptr = std::ptr::addr_of!(val); + unsafe { + *ptr = 3; //~ ERROR cannot assign to `*ptr`, which is behind a `*const` pointer + } +} diff --git a/tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.stderr b/tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.stderr new file mode 100644 index 000000000000..5396db7940f7 --- /dev/null +++ b/tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.stderr @@ -0,0 +1,9 @@ +error[E0594]: cannot assign to `*ptr`, which is behind a `*const` pointer + --> $DIR/dont_suggest_raw_pointer_syntax-issue-127562.rs:5:9 + | +LL | *ptr = 3; + | ^^^^^^^^ `ptr` is a `*const` pointer, so the data it refers to cannot be written + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0594`. From 9ce811cd004e4f1bb7042d0f3fa4b54ffbe9421f Mon Sep 17 00:00:00 2001 From: Jonathan Birk <1965620+cafce25@users.noreply.github.com> Date: Tue, 30 Jul 2024 14:55:27 +0200 Subject: [PATCH 002/246] Change orphan hint from "only" to "any uncovered type inside..." --- compiler/rustc_hir_analysis/messages.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 367f6e17e7fe..33bda77e3353 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -351,7 +351,7 @@ hir_analysis_only_current_traits_arbitrary = only traits defined in the current hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait -hir_analysis_only_current_traits_label = impl doesn't use only types from inside the current crate +hir_analysis_only_current_traits_label = impl doesn't use any uncovered types from inside the current crate hir_analysis_only_current_traits_name = this is not defined in the current crate because {$name} are always foreign From 86a9959466dd996bd9bc926bd79289fdf7f1790d Mon Sep 17 00:00:00 2001 From: Jonathan Birk Date: Tue, 30 Jul 2024 15:39:04 +0000 Subject: [PATCH 003/246] Adjust orphan note in tests --- tests/ui/coherence/coherence-cow.re_a.stderr | 2 +- tests/ui/coherence/coherence-cow.re_b.stderr | 2 +- tests/ui/coherence/coherence-cow.re_c.stderr | 2 +- .../coherence-fundamental-trait-objects.stderr | 2 +- ...impl-trait-for-marker-trait-negative.stderr | 2 +- ...impl-trait-for-marker-trait-positive.stderr | 2 +- tests/ui/coherence/coherence-impls-copy.stderr | 8 ++++---- tests/ui/coherence/coherence-impls-send.stderr | 6 +++--- .../ui/coherence/coherence-impls-sized.stderr | 6 +++--- .../coherence-negative-impls-copy-bad.stderr | 6 +++--- tests/ui/coherence/coherence-orphan.stderr | 4 ++-- .../coherence-overlapping-pairs.stderr | 2 +- .../coherence-pair-covered-uncovered-1.stderr | 2 +- .../coherence-pair-covered-uncovered.stderr | 2 +- .../ui/coherence/coherence-vec-local-2.stderr | 2 +- tests/ui/coherence/coherence-vec-local.stderr | 2 +- .../coherence_local_err_struct.stderr | 2 +- .../coherence/coherence_local_err_tuple.stderr | 2 +- .../coherence/impl-foreign-for-foreign.stderr | 2 +- .../impl-foreign-for-foreign[foreign].stderr | 6 +++--- ...mpl-foreign-for-fundamental[foreign].stderr | 4 ++-- .../impl-foreign[foreign]-for-foreign.stderr | 2 +- ...gn[fundemental[foreign]]-for-foreign.stderr | 6 +++--- .../impl[t]-foreign-for-foreign[t].stderr | 4 ++-- tests/ui/dropck/drop-on-non-struct.stderr | 2 +- tests/ui/error-codes/E0117.stderr | 2 +- tests/ui/error-codes/e0119/complex-impl.stderr | 2 +- .../issue-99572-impl-trait-on-pointer.rs | 18 +++++++++--------- .../issue-99572-impl-trait-on-pointer.stderr | 4 ++-- tests/ui/issues/issue-67535.stderr | 6 +++--- .../const-and-non-const-impl.stderr | 2 +- .../coherence.classic.stderr | 2 +- .../coherence.next.stderr | 2 +- .../range_patterns_trait_impls2.stderr | 2 +- ...ult-trait-impl-cross-crate-coherence.stderr | 6 +++--- 35 files changed, 64 insertions(+), 64 deletions(-) diff --git a/tests/ui/coherence/coherence-cow.re_a.stderr b/tests/ui/coherence/coherence-cow.re_a.stderr index 0bc017817b67..3e929d4fb337 100644 --- a/tests/ui/coherence/coherence-cow.re_a.stderr +++ b/tests/ui/coherence/coherence-cow.re_a.stderr @@ -5,7 +5,7 @@ LL | impl Remote for Pair> { } | ^^^^^^^^^^^^^^^^^^^---------------- | | | | | `Pair` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-cow.re_b.stderr b/tests/ui/coherence/coherence-cow.re_b.stderr index 9bdb49dcc04f..d267f859aea2 100644 --- a/tests/ui/coherence/coherence-cow.re_b.stderr +++ b/tests/ui/coherence/coherence-cow.re_b.stderr @@ -5,7 +5,7 @@ LL | impl Remote for Pair,T> { } | ^^^^^^^^^^^^^^^^^^^---------------- | | | | | `Pair` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-cow.re_c.stderr b/tests/ui/coherence/coherence-cow.re_c.stderr index dfff2667ebbc..e2671cc3dd15 100644 --- a/tests/ui/coherence/coherence-cow.re_c.stderr +++ b/tests/ui/coherence/coherence-cow.re_c.stderr @@ -5,7 +5,7 @@ LL | impl Remote for Pair,U> { } | ^^^^^^^^^^^^^^^^^^^^^---------------- | | | | | `Pair` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-fundamental-trait-objects.stderr b/tests/ui/coherence/coherence-fundamental-trait-objects.stderr index db6a94748042..a0bf8f23f2c6 100644 --- a/tests/ui/coherence/coherence-fundamental-trait-objects.stderr +++ b/tests/ui/coherence/coherence-fundamental-trait-objects.stderr @@ -5,7 +5,7 @@ LL | impl Misc for dyn Fundamental {} | ^^^^^^^^^^^^^^---------------------- | | | | | `dyn Fundamental` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr index ea38afc40ce8..abe752cb65e9 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr @@ -41,7 +41,7 @@ LL | impl !Send for dyn Marker2 {} | ^^^^^^^^^^^^^^^----------- | | | | | `dyn Marker2` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr index 2a8713bc3279..99a32f1bf934 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr @@ -41,7 +41,7 @@ LL | unsafe impl Send for dyn Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^----------- | | | | | `dyn Marker2` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-impls-copy.stderr b/tests/ui/coherence/coherence-impls-copy.stderr index f529a056b0fd..e8db69fa983d 100644 --- a/tests/ui/coherence/coherence-impls-copy.stderr +++ b/tests/ui/coherence/coherence-impls-copy.stderr @@ -15,7 +15,7 @@ LL | impl Copy for &'static [NotSync] {} | ^^^^^^^^^^^^^^------------------ | | | | | this is not defined in the current crate because slices are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -26,7 +26,7 @@ LL | impl Copy for i32 {} | ^^^^^^^^^^^^^^--- | | | | | `i32` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -43,7 +43,7 @@ LL | impl Copy for (MyType, MyType) {} | ^^^^^^^^^^^^^^---------------- | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -60,7 +60,7 @@ LL | impl Copy for [MyType] {} | ^^^^^^^^^^^^^^-------- | | | | | this is not defined in the current crate because slices are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-impls-send.stderr b/tests/ui/coherence/coherence-impls-send.stderr index e1071846e146..2432e6f22d13 100644 --- a/tests/ui/coherence/coherence-impls-send.stderr +++ b/tests/ui/coherence/coherence-impls-send.stderr @@ -5,7 +5,7 @@ LL | unsafe impl Send for &'static [NotSync] {} | ^^^^^^^^^^^^^^^^^^^^^------------------ | | | | | this is not defined in the current crate because slices are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -16,7 +16,7 @@ LL | unsafe impl Send for (MyType, MyType) {} | ^^^^^^^^^^^^^^^^^^^^^---------------- | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -33,7 +33,7 @@ LL | unsafe impl Send for [MyType] {} | ^^^^^^^^^^^^^^^^^^^^^-------- | | | | | this is not defined in the current crate because slices are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-impls-sized.stderr b/tests/ui/coherence/coherence-impls-sized.stderr index 17a7544521de..5069f752f743 100644 --- a/tests/ui/coherence/coherence-impls-sized.stderr +++ b/tests/ui/coherence/coherence-impls-sized.stderr @@ -23,7 +23,7 @@ LL | impl Sized for (MyType, MyType) {} | ^^^^^^^^^^^^^^^---------------- | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -46,7 +46,7 @@ LL | impl Sized for [MyType] {} | ^^^^^^^^^^^^^^^-------- | | | | | this is not defined in the current crate because slices are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -63,7 +63,7 @@ LL | impl Sized for &'static [NotSync] {} | ^^^^^^^^^^^^^^^------------------ | | | | | this is not defined in the current crate because slices are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr b/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr index 2295d6315d1c..2994d1ce0e54 100644 --- a/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr +++ b/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr @@ -5,7 +5,7 @@ LL | impl !Copy for str {} | ^^^^^^^^^^^^^^^--- | | | | | `str` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -16,7 +16,7 @@ LL | impl !Copy for fn() {} | ^^^^^^^^^^^^^^^---- | | | | | `fn()` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -27,7 +27,7 @@ LL | impl !Copy for () {} | ^^^^^^^^^^^^^^^-- | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-orphan.stderr b/tests/ui/coherence/coherence-orphan.stderr index f6ffae342908..11b90d8bf2a3 100644 --- a/tests/ui/coherence/coherence-orphan.stderr +++ b/tests/ui/coherence/coherence-orphan.stderr @@ -6,7 +6,7 @@ LL | impl TheTrait for isize {} | | | | | | | `isize` is not defined in the current crate | | `usize` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -17,7 +17,7 @@ LL | impl !Send for Vec {} | ^^^^^^^^^^^^^^^---------- | | | | | `Vec` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-overlapping-pairs.stderr b/tests/ui/coherence/coherence-overlapping-pairs.stderr index 4d0a9c6ee140..17bb8dc314d2 100644 --- a/tests/ui/coherence/coherence-overlapping-pairs.stderr +++ b/tests/ui/coherence/coherence-overlapping-pairs.stderr @@ -5,7 +5,7 @@ LL | impl Remote for lib::Pair { } | ^^^^^^^^^^^^^^^^^^^---------------- | | | | | `Pair` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr b/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr index 15cd66e9d09d..f2a3ec4daae6 100644 --- a/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr +++ b/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr @@ -6,7 +6,7 @@ LL | impl Remote1>> for i32 { } | | | | | | | `i32` is not defined in the current crate | | `Pair` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-pair-covered-uncovered.stderr b/tests/ui/coherence/coherence-pair-covered-uncovered.stderr index 359dbe8509d8..e3f85c321537 100644 --- a/tests/ui/coherence/coherence-pair-covered-uncovered.stderr +++ b/tests/ui/coherence/coherence-pair-covered-uncovered.stderr @@ -5,7 +5,7 @@ LL | impl Remote for Pair> { } | ^^^^^^^^^^^^^^^^^^^^^---------------- | | | | | `Pair` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-vec-local-2.stderr b/tests/ui/coherence/coherence-vec-local-2.stderr index e4249710d002..1998dedbbc89 100644 --- a/tests/ui/coherence/coherence-vec-local-2.stderr +++ b/tests/ui/coherence/coherence-vec-local-2.stderr @@ -5,7 +5,7 @@ LL | impl Remote for Vec> { } | ^^^^^^^^^^^^^^^^^^^------------- | | | | | `Vec` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-vec-local.stderr b/tests/ui/coherence/coherence-vec-local.stderr index c465fb1966eb..6e95eb7251f6 100644 --- a/tests/ui/coherence/coherence-vec-local.stderr +++ b/tests/ui/coherence/coherence-vec-local.stderr @@ -5,7 +5,7 @@ LL | impl Remote for Vec { } | ^^^^^^^^^^^^^^^^---------- | | | | | `Vec` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence_local_err_struct.stderr b/tests/ui/coherence/coherence_local_err_struct.stderr index 96572b5a7164..bbf968d5d131 100644 --- a/tests/ui/coherence/coherence_local_err_struct.stderr +++ b/tests/ui/coherence/coherence_local_err_struct.stderr @@ -5,7 +5,7 @@ LL | impl lib::MyCopy for lib::MyStruct { } | ^^^^^^^^^^^^^^^^^^^^^--------------------- | | | | | `MyStruct` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence_local_err_tuple.stderr b/tests/ui/coherence/coherence_local_err_tuple.stderr index 85a063bb34ae..c988e738af4d 100644 --- a/tests/ui/coherence/coherence_local_err_tuple.stderr +++ b/tests/ui/coherence/coherence_local_err_tuple.stderr @@ -5,7 +5,7 @@ LL | impl lib::MyCopy for (MyType,) { } | ^^^^^^^^^^^^^^^^^^^^^--------- | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/impl-foreign-for-foreign.stderr b/tests/ui/coherence/impl-foreign-for-foreign.stderr index 6c74b47a1c48..81ae36c6a53d 100644 --- a/tests/ui/coherence/impl-foreign-for-foreign.stderr +++ b/tests/ui/coherence/impl-foreign-for-foreign.stderr @@ -5,7 +5,7 @@ LL | impl Remote for i32 { | ^^^^^^^^^^^^^^^^--- | | | | | `i32` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr b/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr index e24537bce229..9ac7aeff4612 100644 --- a/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr +++ b/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr @@ -6,7 +6,7 @@ LL | impl Remote1> for i32 { | | | | | | | `i32` is not defined in the current crate | | `Rc` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -18,7 +18,7 @@ LL | impl Remote1> for f64 { | | | | | | | `f64` is not defined in the current crate | | `Rc` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -30,7 +30,7 @@ LL | impl Remote1> for f32 { | | | | | | | `f32` is not defined in the current crate | | `Rc` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr b/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr index 55ea4409e6f3..fff6a6b511e1 100644 --- a/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr +++ b/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr @@ -6,7 +6,7 @@ LL | impl Remote for Box { | | | | | | | `i32` is not defined in the current crate | | `std::alloc::Global` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -18,7 +18,7 @@ LL | impl Remote for Box> { | | | | | | | `Rc` is not defined in the current crate | | `std::alloc::Global` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr b/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr index fe8a34b78cfd..ca8506398621 100644 --- a/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr +++ b/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr @@ -6,7 +6,7 @@ LL | impl Remote1 for f64 { | | | | | | | `f64` is not defined in the current crate | | `u32` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr b/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr index 8e77c13e1116..cc0882095e22 100644 --- a/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr +++ b/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr @@ -7,7 +7,7 @@ LL | impl Remote1> for i32 { | | | `i32` is not defined in the current crate | | `String` is not defined in the current crate | | `std::alloc::Global` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -20,7 +20,7 @@ LL | impl Remote1>> for f64 { | | | `f64` is not defined in the current crate | | `Rc` is not defined in the current crate | | `std::alloc::Global` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -33,7 +33,7 @@ LL | impl Remote1>> for f32 { | | | `f32` is not defined in the current crate | | `Rc` is not defined in the current crate | | `std::alloc::Global` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr b/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr index 92346c29198c..11260b7d64a3 100644 --- a/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr +++ b/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr @@ -5,7 +5,7 @@ LL | impl Remote for Rc { | ^^^^^^^^^^^^^^^^--------- | | | | | `Rc` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -16,7 +16,7 @@ LL | impl Remote for Arc { | ^^^^^^^^^^^^^^^^^^^------ | | | | | `Arc` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/dropck/drop-on-non-struct.stderr b/tests/ui/dropck/drop-on-non-struct.stderr index e8fbe5e97264..ec0b2e0d0b64 100644 --- a/tests/ui/dropck/drop-on-non-struct.stderr +++ b/tests/ui/dropck/drop-on-non-struct.stderr @@ -11,7 +11,7 @@ LL | impl<'a> Drop for &'a mut isize { | ^^^^^^^^^^^^^^^^^^------------- | | | | | `isize` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/error-codes/E0117.stderr b/tests/ui/error-codes/E0117.stderr index f144aa9f72c1..86328e8131ac 100644 --- a/tests/ui/error-codes/E0117.stderr +++ b/tests/ui/error-codes/E0117.stderr @@ -5,7 +5,7 @@ LL | impl Drop for u32 {} | ^^^^^^^^^^^^^^--- | | | | | `u32` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/error-codes/e0119/complex-impl.stderr b/tests/ui/error-codes/e0119/complex-impl.stderr index c0519c60e422..6562593adfaf 100644 --- a/tests/ui/error-codes/e0119/complex-impl.stderr +++ b/tests/ui/error-codes/e0119/complex-impl.stderr @@ -5,7 +5,7 @@ LL | impl External for (Q, R) {} | ^^^^^^^^^^^^^^^^^^^^^------ | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/errors/issue-99572-impl-trait-on-pointer.rs b/tests/ui/errors/issue-99572-impl-trait-on-pointer.rs index 272c6bd3fb78..ae2329ec9c8c 100644 --- a/tests/ui/errors/issue-99572-impl-trait-on-pointer.rs +++ b/tests/ui/errors/issue-99572-impl-trait-on-pointer.rs @@ -5,21 +5,21 @@ use std::{fmt, marker}; struct LocalType; impl fmt::Display for *mut LocalType { -//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types -//~| NOTE impl doesn't use only types from inside the current crate -//~| NOTE `*mut LocalType` is not defined in the current crate because raw pointers are always foreign -//~| NOTE define and implement a trait or new type instead -//~| HELP consider introducing a new wrapper type + //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types + //~| NOTE impl doesn't use any uncovered types from inside the current crate + //~| NOTE `*mut LocalType` is not defined in the current crate because raw pointers are always foreign + //~| NOTE define and implement a trait or new type instead + //~| HELP consider introducing a new wrapper type fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "This not compile") } } impl marker::Copy for *mut T { -//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types -//~| NOTE impl doesn't use only types from inside the current crate -//~| NOTE `*mut T` is not defined in the current crate because raw pointers are always foreign -//~| NOTE define and implement a trait or new type instead + //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types + //~| NOTE impl doesn't use any uncovered types from inside the current crate + //~| NOTE `*mut T` is not defined in the current crate because raw pointers are always foreign + //~| NOTE define and implement a trait or new type instead } fn main() {} diff --git a/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr b/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr index 78d7a47deaac..5809387e9171 100644 --- a/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr +++ b/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr @@ -5,7 +5,7 @@ LL | impl fmt::Display for *mut LocalType { | ^^^^^^^^^^^^^^^^^^^^^^-------------- | | | | | `*mut LocalType` is not defined in the current crate because raw pointers are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead help: consider introducing a new wrapper type @@ -22,7 +22,7 @@ LL | impl marker::Copy for *mut T { | ^^^^^^^^^^^^^^^^^^^^^^^^^------ | | | | | `*mut T` is not defined in the current crate because raw pointers are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/issues/issue-67535.stderr b/tests/ui/issues/issue-67535.stderr index 4d7a02a50969..4bfbf1bffdbe 100644 --- a/tests/ui/issues/issue-67535.stderr +++ b/tests/ui/issues/issue-67535.stderr @@ -6,7 +6,7 @@ LL | impl std::ops::AddAssign for () { | | | | | | | this is not defined in the current crate because tuples are always foreign | | this is not defined in the current crate because this is a foreign trait - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -18,7 +18,7 @@ LL | impl std::ops::AddAssign for [(); 1] { | | | | | | | this is not defined in the current crate because arrays are always foreign | | this is not defined in the current crate because this is a foreign trait - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -30,7 +30,7 @@ LL | impl std::ops::AddAssign for &[u8] { | | | | | | | this is not defined in the current crate because slices are always foreign | | this is not defined in the current crate because this is a foreign trait - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr index 9c1c8df8da45..056cd76075e1 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr @@ -33,7 +33,7 @@ LL | impl const std::ops::Add for i32 { | | | | | | | `i32` is not defined in the current crate | | `i32` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/type-alias-impl-trait/coherence.classic.stderr b/tests/ui/type-alias-impl-trait/coherence.classic.stderr index ff059bc5806d..3930a7513d87 100644 --- a/tests/ui/type-alias-impl-trait/coherence.classic.stderr +++ b/tests/ui/type-alias-impl-trait/coherence.classic.stderr @@ -5,7 +5,7 @@ LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------- | | | | | type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/type-alias-impl-trait/coherence.next.stderr b/tests/ui/type-alias-impl-trait/coherence.next.stderr index dab2786c1f0f..bbda98681884 100644 --- a/tests/ui/type-alias-impl-trait/coherence.next.stderr +++ b/tests/ui/type-alias-impl-trait/coherence.next.stderr @@ -5,7 +5,7 @@ LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------- | | | | | `AliasOfForeignType<()>` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr b/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr index 41f42455bde0..5403b4fd2dc8 100644 --- a/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr +++ b/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr @@ -5,7 +5,7 @@ LL | impl Eq for Y {} | ^^^^^^^^^^^^- | | | | | `(u32) is 1..=` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr b/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr index 32e6e88fc483..65202c136916 100644 --- a/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr +++ b/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr @@ -5,7 +5,7 @@ LL | impl DefaultedTrait for (A,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^---- | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -16,7 +16,7 @@ LL | impl !DefaultedTrait for (B,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^---- | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead @@ -33,7 +33,7 @@ LL | impl DefaultedTrait for lib::Something {} | ^^^^^^^^^^^^^^^^^^^^^^^^----------------- | | | | | `Something` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | impl doesn't use any uncovered types from inside the current crate | = note: define and implement a trait or new type instead From ca94dd5beac8252f03047a1eeb6a7c456b467c03 Mon Sep 17 00:00:00 2001 From: Jonathan Birk Date: Sun, 11 Aug 2024 10:13:50 +0000 Subject: [PATCH 004/246] Add more information link to orphan impls --- compiler/rustc_hir_analysis/messages.ftl | 4 +++- compiler/rustc_hir_analysis/src/errors.rs | 3 +++ tests/ui/coherence/coherence-cow.re_a.stderr | 3 ++- tests/ui/coherence/coherence-cow.re_b.stderr | 3 ++- tests/ui/coherence/coherence-cow.re_c.stderr | 3 ++- .../coherence-fundamental-trait-objects.stderr | 3 ++- ...rence-impl-trait-for-marker-trait-negative.stderr | 3 ++- ...rence-impl-trait-for-marker-trait-positive.stderr | 3 ++- tests/ui/coherence/coherence-impls-copy.stderr | 12 ++++++++---- tests/ui/coherence/coherence-impls-send.stderr | 9 ++++++--- tests/ui/coherence/coherence-impls-sized.stderr | 9 ++++++--- .../coherence-negative-impls-copy-bad.stderr | 9 ++++++--- tests/ui/coherence/coherence-orphan.stderr | 6 ++++-- .../ui/coherence/coherence-overlapping-pairs.stderr | 3 ++- .../coherence-pair-covered-uncovered-1.stderr | 3 ++- .../coherence-pair-covered-uncovered.stderr | 3 ++- tests/ui/coherence/coherence-vec-local-2.stderr | 3 ++- tests/ui/coherence/coherence-vec-local.stderr | 3 ++- tests/ui/coherence/coherence_local_err_struct.stderr | 3 ++- tests/ui/coherence/coherence_local_err_tuple.stderr | 3 ++- tests/ui/coherence/impl-foreign-for-foreign.stderr | 3 ++- .../impl-foreign-for-foreign[foreign].stderr | 9 ++++++--- .../impl-foreign-for-fundamental[foreign].stderr | 6 ++++-- .../impl-foreign[foreign]-for-foreign.stderr | 3 ++- ...-foreign[fundemental[foreign]]-for-foreign.stderr | 9 ++++++--- .../coherence/impl[t]-foreign-for-foreign[t].stderr | 6 ++++-- tests/ui/dropck/drop-on-non-struct.stderr | 3 ++- tests/ui/error-codes/E0117.stderr | 3 ++- tests/ui/error-codes/e0119/complex-impl.stderr | 3 ++- tests/ui/errors/issue-99572-impl-trait-on-pointer.rs | 6 ++++-- .../errors/issue-99572-impl-trait-on-pointer.stderr | 8 +++++--- tests/ui/issues/issue-67535.stderr | 9 ++++++--- .../const-and-non-const-impl.stderr | 3 ++- .../type-alias-impl-trait/coherence.classic.stderr | 3 ++- tests/ui/type-alias-impl-trait/coherence.next.stderr | 3 ++- .../pattern_types/range_patterns_trait_impls2.stderr | 3 ++- ...k-default-trait-impl-cross-crate-coherence.stderr | 9 ++++++--- 37 files changed, 121 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 33bda77e3353..c81f1c62be9c 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -351,7 +351,9 @@ hir_analysis_only_current_traits_arbitrary = only traits defined in the current hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait -hir_analysis_only_current_traits_label = impl doesn't use any uncovered types from inside the current crate +hir_analysis_only_current_traits_label = impl doesn't have any local type before any uncovered type parameters + +hir_analysis_only_current_traits_label_more_info = for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules hir_analysis_only_current_traits_name = this is not defined in the current crate because {$name} are always foreign diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index b1ac973ef2e0..9488f2f86cb3 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1441,6 +1441,7 @@ pub enum OnlyCurrentTraits { Outside { #[primary_span] #[label(hir_analysis_only_current_traits_label)] + #[label(hir_analysis_only_current_traits_label_more_info)] span: Span, #[note(hir_analysis_only_current_traits_note)] note: (), @@ -1449,6 +1450,7 @@ pub enum OnlyCurrentTraits { Primitive { #[primary_span] #[label(hir_analysis_only_current_traits_label)] + #[label(hir_analysis_only_current_traits_label_more_info)] span: Span, #[note(hir_analysis_only_current_traits_note)] note: (), @@ -1457,6 +1459,7 @@ pub enum OnlyCurrentTraits { Arbitrary { #[primary_span] #[label(hir_analysis_only_current_traits_label)] + #[label(hir_analysis_only_current_traits_label_more_info)] span: Span, #[note(hir_analysis_only_current_traits_note)] note: (), diff --git a/tests/ui/coherence/coherence-cow.re_a.stderr b/tests/ui/coherence/coherence-cow.re_a.stderr index 3e929d4fb337..b4331fc475b1 100644 --- a/tests/ui/coherence/coherence-cow.re_a.stderr +++ b/tests/ui/coherence/coherence-cow.re_a.stderr @@ -5,7 +5,8 @@ LL | impl Remote for Pair> { } | ^^^^^^^^^^^^^^^^^^^---------------- | | | | | `Pair` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-cow.re_b.stderr b/tests/ui/coherence/coherence-cow.re_b.stderr index d267f859aea2..b401d9645988 100644 --- a/tests/ui/coherence/coherence-cow.re_b.stderr +++ b/tests/ui/coherence/coherence-cow.re_b.stderr @@ -5,7 +5,8 @@ LL | impl Remote for Pair,T> { } | ^^^^^^^^^^^^^^^^^^^---------------- | | | | | `Pair` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-cow.re_c.stderr b/tests/ui/coherence/coherence-cow.re_c.stderr index e2671cc3dd15..d95beee8139e 100644 --- a/tests/ui/coherence/coherence-cow.re_c.stderr +++ b/tests/ui/coherence/coherence-cow.re_c.stderr @@ -5,7 +5,8 @@ LL | impl Remote for Pair,U> { } | ^^^^^^^^^^^^^^^^^^^^^---------------- | | | | | `Pair` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-fundamental-trait-objects.stderr b/tests/ui/coherence/coherence-fundamental-trait-objects.stderr index a0bf8f23f2c6..4933fb155f73 100644 --- a/tests/ui/coherence/coherence-fundamental-trait-objects.stderr +++ b/tests/ui/coherence/coherence-fundamental-trait-objects.stderr @@ -5,7 +5,8 @@ LL | impl Misc for dyn Fundamental {} | ^^^^^^^^^^^^^^---------------------- | | | | | `dyn Fundamental` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr index abe752cb65e9..c8b215037b9e 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr @@ -41,7 +41,8 @@ LL | impl !Send for dyn Marker2 {} | ^^^^^^^^^^^^^^^----------- | | | | | `dyn Marker2` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr index 99a32f1bf934..02107453a9ff 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr @@ -41,7 +41,8 @@ LL | unsafe impl Send for dyn Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^----------- | | | | | `dyn Marker2` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-impls-copy.stderr b/tests/ui/coherence/coherence-impls-copy.stderr index e8db69fa983d..2de854ed5843 100644 --- a/tests/ui/coherence/coherence-impls-copy.stderr +++ b/tests/ui/coherence/coherence-impls-copy.stderr @@ -15,7 +15,8 @@ LL | impl Copy for &'static [NotSync] {} | ^^^^^^^^^^^^^^------------------ | | | | | this is not defined in the current crate because slices are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -26,7 +27,8 @@ LL | impl Copy for i32 {} | ^^^^^^^^^^^^^^--- | | | | | `i32` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -43,7 +45,8 @@ LL | impl Copy for (MyType, MyType) {} | ^^^^^^^^^^^^^^---------------- | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -60,7 +63,8 @@ LL | impl Copy for [MyType] {} | ^^^^^^^^^^^^^^-------- | | | | | this is not defined in the current crate because slices are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-impls-send.stderr b/tests/ui/coherence/coherence-impls-send.stderr index 2432e6f22d13..a41e9d620e01 100644 --- a/tests/ui/coherence/coherence-impls-send.stderr +++ b/tests/ui/coherence/coherence-impls-send.stderr @@ -5,7 +5,8 @@ LL | unsafe impl Send for &'static [NotSync] {} | ^^^^^^^^^^^^^^^^^^^^^------------------ | | | | | this is not defined in the current crate because slices are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -16,7 +17,8 @@ LL | unsafe impl Send for (MyType, MyType) {} | ^^^^^^^^^^^^^^^^^^^^^---------------- | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -33,7 +35,8 @@ LL | unsafe impl Send for [MyType] {} | ^^^^^^^^^^^^^^^^^^^^^-------- | | | | | this is not defined in the current crate because slices are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-impls-sized.stderr b/tests/ui/coherence/coherence-impls-sized.stderr index 5069f752f743..080d19e075b5 100644 --- a/tests/ui/coherence/coherence-impls-sized.stderr +++ b/tests/ui/coherence/coherence-impls-sized.stderr @@ -23,7 +23,8 @@ LL | impl Sized for (MyType, MyType) {} | ^^^^^^^^^^^^^^^---------------- | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -46,7 +47,8 @@ LL | impl Sized for [MyType] {} | ^^^^^^^^^^^^^^^-------- | | | | | this is not defined in the current crate because slices are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -63,7 +65,8 @@ LL | impl Sized for &'static [NotSync] {} | ^^^^^^^^^^^^^^^------------------ | | | | | this is not defined in the current crate because slices are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr b/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr index 2994d1ce0e54..85937c5f02a8 100644 --- a/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr +++ b/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr @@ -5,7 +5,8 @@ LL | impl !Copy for str {} | ^^^^^^^^^^^^^^^--- | | | | | `str` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -16,7 +17,8 @@ LL | impl !Copy for fn() {} | ^^^^^^^^^^^^^^^---- | | | | | `fn()` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -27,7 +29,8 @@ LL | impl !Copy for () {} | ^^^^^^^^^^^^^^^-- | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-orphan.stderr b/tests/ui/coherence/coherence-orphan.stderr index 11b90d8bf2a3..c10ed013ef25 100644 --- a/tests/ui/coherence/coherence-orphan.stderr +++ b/tests/ui/coherence/coherence-orphan.stderr @@ -6,7 +6,8 @@ LL | impl TheTrait for isize {} | | | | | | | `isize` is not defined in the current crate | | `usize` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -17,7 +18,8 @@ LL | impl !Send for Vec {} | ^^^^^^^^^^^^^^^---------- | | | | | `Vec` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-overlapping-pairs.stderr b/tests/ui/coherence/coherence-overlapping-pairs.stderr index 17bb8dc314d2..448e7b9d5ef1 100644 --- a/tests/ui/coherence/coherence-overlapping-pairs.stderr +++ b/tests/ui/coherence/coherence-overlapping-pairs.stderr @@ -5,7 +5,8 @@ LL | impl Remote for lib::Pair { } | ^^^^^^^^^^^^^^^^^^^---------------- | | | | | `Pair` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr b/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr index f2a3ec4daae6..2e616fefe0ee 100644 --- a/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr +++ b/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr @@ -6,7 +6,8 @@ LL | impl Remote1>> for i32 { } | | | | | | | `i32` is not defined in the current crate | | `Pair` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-pair-covered-uncovered.stderr b/tests/ui/coherence/coherence-pair-covered-uncovered.stderr index e3f85c321537..71a1e4c7ac3f 100644 --- a/tests/ui/coherence/coherence-pair-covered-uncovered.stderr +++ b/tests/ui/coherence/coherence-pair-covered-uncovered.stderr @@ -5,7 +5,8 @@ LL | impl Remote for Pair> { } | ^^^^^^^^^^^^^^^^^^^^^---------------- | | | | | `Pair` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-vec-local-2.stderr b/tests/ui/coherence/coherence-vec-local-2.stderr index 1998dedbbc89..50788e4a990e 100644 --- a/tests/ui/coherence/coherence-vec-local-2.stderr +++ b/tests/ui/coherence/coherence-vec-local-2.stderr @@ -5,7 +5,8 @@ LL | impl Remote for Vec> { } | ^^^^^^^^^^^^^^^^^^^------------- | | | | | `Vec` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence-vec-local.stderr b/tests/ui/coherence/coherence-vec-local.stderr index 6e95eb7251f6..cd102fa1c6d1 100644 --- a/tests/ui/coherence/coherence-vec-local.stderr +++ b/tests/ui/coherence/coherence-vec-local.stderr @@ -5,7 +5,8 @@ LL | impl Remote for Vec { } | ^^^^^^^^^^^^^^^^---------- | | | | | `Vec` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence_local_err_struct.stderr b/tests/ui/coherence/coherence_local_err_struct.stderr index bbf968d5d131..97a26b54a1be 100644 --- a/tests/ui/coherence/coherence_local_err_struct.stderr +++ b/tests/ui/coherence/coherence_local_err_struct.stderr @@ -5,7 +5,8 @@ LL | impl lib::MyCopy for lib::MyStruct { } | ^^^^^^^^^^^^^^^^^^^^^--------------------- | | | | | `MyStruct` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/coherence_local_err_tuple.stderr b/tests/ui/coherence/coherence_local_err_tuple.stderr index c988e738af4d..cdd73be86bfa 100644 --- a/tests/ui/coherence/coherence_local_err_tuple.stderr +++ b/tests/ui/coherence/coherence_local_err_tuple.stderr @@ -5,7 +5,8 @@ LL | impl lib::MyCopy for (MyType,) { } | ^^^^^^^^^^^^^^^^^^^^^--------- | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/impl-foreign-for-foreign.stderr b/tests/ui/coherence/impl-foreign-for-foreign.stderr index 81ae36c6a53d..0f8af5ef0280 100644 --- a/tests/ui/coherence/impl-foreign-for-foreign.stderr +++ b/tests/ui/coherence/impl-foreign-for-foreign.stderr @@ -5,7 +5,8 @@ LL | impl Remote for i32 { | ^^^^^^^^^^^^^^^^--- | | | | | `i32` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr b/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr index 9ac7aeff4612..ae1807f6dd05 100644 --- a/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr +++ b/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr @@ -6,7 +6,8 @@ LL | impl Remote1> for i32 { | | | | | | | `i32` is not defined in the current crate | | `Rc` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -18,7 +19,8 @@ LL | impl Remote1> for f64 { | | | | | | | `f64` is not defined in the current crate | | `Rc` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -30,7 +32,8 @@ LL | impl Remote1> for f32 { | | | | | | | `f32` is not defined in the current crate | | `Rc` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr b/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr index fff6a6b511e1..a3522a75c86c 100644 --- a/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr +++ b/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr @@ -6,7 +6,8 @@ LL | impl Remote for Box { | | | | | | | `i32` is not defined in the current crate | | `std::alloc::Global` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -18,7 +19,8 @@ LL | impl Remote for Box> { | | | | | | | `Rc` is not defined in the current crate | | `std::alloc::Global` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr b/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr index ca8506398621..bf22e73dd09d 100644 --- a/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr +++ b/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr @@ -6,7 +6,8 @@ LL | impl Remote1 for f64 { | | | | | | | `f64` is not defined in the current crate | | `u32` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr b/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr index cc0882095e22..2ab5cca7983c 100644 --- a/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr +++ b/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr @@ -7,7 +7,8 @@ LL | impl Remote1> for i32 { | | | `i32` is not defined in the current crate | | `String` is not defined in the current crate | | `std::alloc::Global` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -20,7 +21,8 @@ LL | impl Remote1>> for f64 { | | | `f64` is not defined in the current crate | | `Rc` is not defined in the current crate | | `std::alloc::Global` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -33,7 +35,8 @@ LL | impl Remote1>> for f32 { | | | `f32` is not defined in the current crate | | `Rc` is not defined in the current crate | | `std::alloc::Global` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr b/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr index 11260b7d64a3..ca9a7d5cd930 100644 --- a/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr +++ b/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr @@ -5,7 +5,8 @@ LL | impl Remote for Rc { | ^^^^^^^^^^^^^^^^--------- | | | | | `Rc` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -16,7 +17,8 @@ LL | impl Remote for Arc { | ^^^^^^^^^^^^^^^^^^^------ | | | | | `Arc` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/dropck/drop-on-non-struct.stderr b/tests/ui/dropck/drop-on-non-struct.stderr index ec0b2e0d0b64..78b7212b6d9f 100644 --- a/tests/ui/dropck/drop-on-non-struct.stderr +++ b/tests/ui/dropck/drop-on-non-struct.stderr @@ -11,7 +11,8 @@ LL | impl<'a> Drop for &'a mut isize { | ^^^^^^^^^^^^^^^^^^------------- | | | | | `isize` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/error-codes/E0117.stderr b/tests/ui/error-codes/E0117.stderr index 86328e8131ac..2bfa78d1954d 100644 --- a/tests/ui/error-codes/E0117.stderr +++ b/tests/ui/error-codes/E0117.stderr @@ -5,7 +5,8 @@ LL | impl Drop for u32 {} | ^^^^^^^^^^^^^^--- | | | | | `u32` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/error-codes/e0119/complex-impl.stderr b/tests/ui/error-codes/e0119/complex-impl.stderr index 6562593adfaf..36618cee0e83 100644 --- a/tests/ui/error-codes/e0119/complex-impl.stderr +++ b/tests/ui/error-codes/e0119/complex-impl.stderr @@ -5,7 +5,8 @@ LL | impl External for (Q, R) {} | ^^^^^^^^^^^^^^^^^^^^^------ | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/errors/issue-99572-impl-trait-on-pointer.rs b/tests/ui/errors/issue-99572-impl-trait-on-pointer.rs index ae2329ec9c8c..61f11a88c614 100644 --- a/tests/ui/errors/issue-99572-impl-trait-on-pointer.rs +++ b/tests/ui/errors/issue-99572-impl-trait-on-pointer.rs @@ -6,7 +6,8 @@ struct LocalType; impl fmt::Display for *mut LocalType { //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types - //~| NOTE impl doesn't use any uncovered types from inside the current crate + //~| NOTE impl doesn't have any local type before any uncovered type parameters + //~| NOTE for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules //~| NOTE `*mut LocalType` is not defined in the current crate because raw pointers are always foreign //~| NOTE define and implement a trait or new type instead //~| HELP consider introducing a new wrapper type @@ -17,7 +18,8 @@ impl fmt::Display for *mut LocalType { impl marker::Copy for *mut T { //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types - //~| NOTE impl doesn't use any uncovered types from inside the current crate + //~| NOTE impl doesn't have any local type before any uncovered type parameters + //~| NOTE for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules //~| NOTE `*mut T` is not defined in the current crate because raw pointers are always foreign //~| NOTE define and implement a trait or new type instead } diff --git a/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr b/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr index 5809387e9171..214618d6636f 100644 --- a/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr +++ b/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr @@ -5,7 +5,8 @@ LL | impl fmt::Display for *mut LocalType { | ^^^^^^^^^^^^^^^^^^^^^^-------------- | | | | | `*mut LocalType` is not defined in the current crate because raw pointers are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead help: consider introducing a new wrapper type @@ -16,13 +17,14 @@ LL ~ impl fmt::Display for WrapperType { | error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/issue-99572-impl-trait-on-pointer.rs:18:1 + --> $DIR/issue-99572-impl-trait-on-pointer.rs:19:1 | LL | impl marker::Copy for *mut T { | ^^^^^^^^^^^^^^^^^^^^^^^^^------ | | | | | `*mut T` is not defined in the current crate because raw pointers are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/issues/issue-67535.stderr b/tests/ui/issues/issue-67535.stderr index 4bfbf1bffdbe..a953a9152144 100644 --- a/tests/ui/issues/issue-67535.stderr +++ b/tests/ui/issues/issue-67535.stderr @@ -6,7 +6,8 @@ LL | impl std::ops::AddAssign for () { | | | | | | | this is not defined in the current crate because tuples are always foreign | | this is not defined in the current crate because this is a foreign trait - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -18,7 +19,8 @@ LL | impl std::ops::AddAssign for [(); 1] { | | | | | | | this is not defined in the current crate because arrays are always foreign | | this is not defined in the current crate because this is a foreign trait - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -30,7 +32,8 @@ LL | impl std::ops::AddAssign for &[u8] { | | | | | | | this is not defined in the current crate because slices are always foreign | | this is not defined in the current crate because this is a foreign trait - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr index 056cd76075e1..4dff35c46e84 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr @@ -33,7 +33,8 @@ LL | impl const std::ops::Add for i32 { | | | | | | | `i32` is not defined in the current crate | | `i32` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/type-alias-impl-trait/coherence.classic.stderr b/tests/ui/type-alias-impl-trait/coherence.classic.stderr index 3930a7513d87..4cd87253b307 100644 --- a/tests/ui/type-alias-impl-trait/coherence.classic.stderr +++ b/tests/ui/type-alias-impl-trait/coherence.classic.stderr @@ -5,7 +5,8 @@ LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------- | | | | | type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/type-alias-impl-trait/coherence.next.stderr b/tests/ui/type-alias-impl-trait/coherence.next.stderr index bbda98681884..886b667b8c8b 100644 --- a/tests/ui/type-alias-impl-trait/coherence.next.stderr +++ b/tests/ui/type-alias-impl-trait/coherence.next.stderr @@ -5,7 +5,8 @@ LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------- | | | | | `AliasOfForeignType<()>` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr b/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr index 5403b4fd2dc8..2d3f8403315d 100644 --- a/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr +++ b/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr @@ -5,7 +5,8 @@ LL | impl Eq for Y {} | ^^^^^^^^^^^^- | | | | | `(u32) is 1..=` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead diff --git a/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr b/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr index 65202c136916..8ee6846eac28 100644 --- a/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr +++ b/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr @@ -5,7 +5,8 @@ LL | impl DefaultedTrait for (A,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^---- | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -16,7 +17,8 @@ LL | impl !DefaultedTrait for (B,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^---- | | | | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead @@ -33,7 +35,8 @@ LL | impl DefaultedTrait for lib::Something {} | ^^^^^^^^^^^^^^^^^^^^^^^^----------------- | | | | | `Something` is not defined in the current crate - | impl doesn't use any uncovered types from inside the current crate + | impl doesn't have any local type before any uncovered type parameters + | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules | = note: define and implement a trait or new type instead From e9cf280ef2ea4550d2305484873a63dfd133abb7 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 16 Oct 2023 23:56:22 -0700 Subject: [PATCH 005/246] warn less about non-exhaustive in ffi Bindgen allows generating `#[non_exhaustive] #[repr(u32)]` enums. This results in nonintuitive nonlocal `improper_ctypes` warnings, even when the types are otherwise perfectly valid in C. Adjust for actual tooling expectations by avoiding warning on simple enums with only unit variants. --- compiler/rustc_lint/src/types.rs | 27 ++++++++++++------- .../improper_ctypes/auxiliary/types.rs | 11 ++++++++ .../improper_ctypes/extern_crate_improper.rs | 10 ++++++- .../extern_crate_improper.stderr | 10 +++---- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 900c496e0330..eef1f0d133ae 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -3,6 +3,7 @@ use std::ops::ControlFlow; use rustc_data_structures::fx::FxHashSet; use rustc_errors::DiagMessage; +use rustc_hir::def::CtorKind; use rustc_hir::{is_range_literal, Expr, ExprKind, Node}; use rustc_middle::bug; use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton}; @@ -1386,15 +1387,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // Empty enums are okay... although sort of useless. return FfiSafe; } - - if def.is_variant_list_non_exhaustive() && !def.did().is_local() { - return FfiUnsafe { - ty, - reason: fluent::lint_improper_ctypes_non_exhaustive, - help: None, - }; - } - // Check for a repr() attribute to specify the size of the // discriminant. if !def.repr().c() && !def.repr().transparent() && def.repr().int.is_none() @@ -1413,8 +1405,25 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { }; } + // non_exhaustive suggests it is possible that someone might break ABI + // see: https://github.com/rust-lang/rust/issues/44109#issuecomment-537583344 + // so warn on complex enums being used outside their crate + let nonexhaustive_nonlocal_ffi = + def.is_variant_list_non_exhaustive() && !def.did().is_local(); + // Check the contained variants. for variant in def.variants() { + // but only warn about really_tagged_union reprs, + // exempt enums with unit ctors like C's (like rust-bindgen) + if nonexhaustive_nonlocal_ffi + && !matches!(variant.ctor_kind(), Some(CtorKind::Const)) + { + return FfiUnsafe { + ty, + reason: fluent::lint_improper_ctypes_non_exhaustive, + help: None, + }; + }; let is_non_exhaustive = variant.is_field_list_non_exhaustive(); if is_non_exhaustive && !variant.def_id.is_local() { return FfiUnsafe { diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs index d6251fcb768f..4dc5932feab4 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs @@ -27,3 +27,14 @@ pub enum NonExhaustiveVariants { #[non_exhaustive] Tuple(u32), #[non_exhaustive] Struct { field: u32 } } + +// Note the absence of repr(C): it's not necessary, and recent C code can now use repr hints too. +#[repr(u32)] +#[non_exhaustive] +pub enum NonExhaustiveCLikeEnum { + One = 1, + Two = 2, + Three = 3, + Four = 4, + Five = 5, +} diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs index 7a9b465bb56f..c7f470fb787a 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs @@ -6,7 +6,10 @@ extern crate types; // This test checks that non-exhaustive types with `#[repr(C)]` from an extern crate are considered // improper. -use types::{NonExhaustiveEnum, NonExhaustiveVariants, NormalStruct, TupleStruct, UnitStruct}; +use types::{ + NonExhaustiveCLikeEnum, NonExhaustiveEnum, NonExhaustiveVariants, + NormalStruct, TupleStruct, UnitStruct, +}; extern "C" { pub fn non_exhaustive_enum(_: NonExhaustiveEnum); @@ -21,4 +24,9 @@ extern "C" { //~^ ERROR `extern` block uses type `NonExhaustiveVariants`, which is not FFI-safe } +// These should pass without remark, as they're C-compatible, despite being "non-exhaustive". +extern "C" { + pub fn non_exhaustive_c_compat_enum(_: NonExhaustiveCLikeEnum); +} + fn main() {} diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr index 43c8e1015e67..afc3d3838ad3 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr @@ -1,5 +1,5 @@ error: `extern` block uses type `NonExhaustiveEnum`, which is not FFI-safe - --> $DIR/extern_crate_improper.rs:12:35 + --> $DIR/extern_crate_improper.rs:15:35 | LL | pub fn non_exhaustive_enum(_: NonExhaustiveEnum); | ^^^^^^^^^^^^^^^^^ not FFI-safe @@ -12,7 +12,7 @@ LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ error: `extern` block uses type `NormalStruct`, which is not FFI-safe - --> $DIR/extern_crate_improper.rs:14:44 + --> $DIR/extern_crate_improper.rs:17:44 | LL | pub fn non_exhaustive_normal_struct(_: NormalStruct); | ^^^^^^^^^^^^ not FFI-safe @@ -20,7 +20,7 @@ LL | pub fn non_exhaustive_normal_struct(_: NormalStruct); = note: this struct is non-exhaustive error: `extern` block uses type `UnitStruct`, which is not FFI-safe - --> $DIR/extern_crate_improper.rs:16:42 + --> $DIR/extern_crate_improper.rs:19:42 | LL | pub fn non_exhaustive_unit_struct(_: UnitStruct); | ^^^^^^^^^^ not FFI-safe @@ -28,7 +28,7 @@ LL | pub fn non_exhaustive_unit_struct(_: UnitStruct); = note: this struct is non-exhaustive error: `extern` block uses type `TupleStruct`, which is not FFI-safe - --> $DIR/extern_crate_improper.rs:18:43 + --> $DIR/extern_crate_improper.rs:21:43 | LL | pub fn non_exhaustive_tuple_struct(_: TupleStruct); | ^^^^^^^^^^^ not FFI-safe @@ -36,7 +36,7 @@ LL | pub fn non_exhaustive_tuple_struct(_: TupleStruct); = note: this struct is non-exhaustive error: `extern` block uses type `NonExhaustiveVariants`, which is not FFI-safe - --> $DIR/extern_crate_improper.rs:20:38 + --> $DIR/extern_crate_improper.rs:23:38 | LL | pub fn non_exhaustive_variant(_: NonExhaustiveVariants); | ^^^^^^^^^^^^^^^^^^^^^ not FFI-safe From 00124800ea83f8ca0c1955dcf1696215b62ce802 Mon Sep 17 00:00:00 2001 From: Christopher Serr Date: Thu, 19 Sep 2024 22:00:22 +0200 Subject: [PATCH 006/246] feat: Highlight exit points of async blocks Async blocks act similar to async functions in that the await keywords are related, but also act like functions where the exit points are related. --- .../crates/ide/src/highlight_related.rs | 164 ++++++++++-------- 1 file changed, 93 insertions(+), 71 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs index 4c8e3fc3040c..97b7ba781295 100644 --- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs +++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs @@ -281,99 +281,95 @@ fn highlight_references( } } -// If `file_id` is None, -pub(crate) fn highlight_exit_points( +fn hl_exit_points( sema: &Semantics<'_, RootDatabase>, - token: SyntaxToken, -) -> FxHashMap> { - fn hl( - sema: &Semantics<'_, RootDatabase>, - def_token: Option, - body: ast::Expr, - ) -> Option>> { - let mut highlights: FxHashMap> = FxHashMap::default(); + def_token: Option, + body: ast::Expr, +) -> Option>> { + let mut highlights: FxHashMap> = FxHashMap::default(); - let mut push_to_highlights = |file_id, range| { - if let Some(FileRange { file_id, range }) = original_frange(sema.db, file_id, range) { - let hrange = HighlightedRange { category: ReferenceCategory::empty(), range }; - highlights.entry(file_id).or_default().insert(hrange); + let mut push_to_highlights = |file_id, range| { + if let Some(FileRange { file_id, range }) = original_frange(sema.db, file_id, range) { + let hrange = HighlightedRange { category: ReferenceCategory::empty(), range }; + highlights.entry(file_id).or_default().insert(hrange); + } + }; + + if let Some(tok) = def_token { + let file_id = sema.hir_file_for(&tok.parent()?); + let range = Some(tok.text_range()); + push_to_highlights(file_id, range); + } + + WalkExpandedExprCtx::new(sema).walk(&body, &mut |_, expr| { + let file_id = sema.hir_file_for(expr.syntax()); + + let range = match &expr { + ast::Expr::TryExpr(try_) => try_.question_mark_token().map(|token| token.text_range()), + ast::Expr::MethodCallExpr(_) | ast::Expr::CallExpr(_) | ast::Expr::MacroExpr(_) + if sema.type_of_expr(&expr).map_or(false, |ty| ty.original.is_never()) => + { + Some(expr.syntax().text_range()) } + _ => None, }; - if let Some(tok) = def_token { - let file_id = sema.hir_file_for(&tok.parent()?); - let range = Some(tok.text_range()); - push_to_highlights(file_id, range); - } + push_to_highlights(file_id, range); + }); - WalkExpandedExprCtx::new(sema).walk(&body, &mut |_, expr| { + // We should handle `return` separately, because when it is used in a `try` block, + // it will exit the outside function instead of the block itself. + WalkExpandedExprCtx::new(sema) + .with_check_ctx(&WalkExpandedExprCtx::is_async_const_block_or_closure) + .walk(&body, &mut |_, expr| { let file_id = sema.hir_file_for(expr.syntax()); let range = match &expr { - ast::Expr::TryExpr(try_) => { - try_.question_mark_token().map(|token| token.text_range()) - } - ast::Expr::MethodCallExpr(_) | ast::Expr::CallExpr(_) | ast::Expr::MacroExpr(_) - if sema.type_of_expr(&expr).map_or(false, |ty| ty.original.is_never()) => - { - Some(expr.syntax().text_range()) - } + ast::Expr::ReturnExpr(expr) => expr.return_token().map(|token| token.text_range()), _ => None, }; push_to_highlights(file_id, range); }); - // We should handle `return` separately, because when it is used in a `try` block, - // it will exit the outside function instead of the block itself. - WalkExpandedExprCtx::new(sema) - .with_check_ctx(&WalkExpandedExprCtx::is_async_const_block_or_closure) - .walk(&body, &mut |_, expr| { - let file_id = sema.hir_file_for(expr.syntax()); + let tail = match body { + ast::Expr::BlockExpr(b) => b.tail_expr(), + e => Some(e), + }; - let range = match &expr { - ast::Expr::ReturnExpr(expr) => { - expr.return_token().map(|token| token.text_range()) - } - _ => None, - }; - - push_to_highlights(file_id, range); - }); - - let tail = match body { - ast::Expr::BlockExpr(b) => b.tail_expr(), - e => Some(e), - }; - - if let Some(tail) = tail { - for_each_tail_expr(&tail, &mut |tail| { - let file_id = sema.hir_file_for(tail.syntax()); - let range = match tail { - ast::Expr::BreakExpr(b) => b - .break_token() - .map_or_else(|| tail.syntax().text_range(), |tok| tok.text_range()), - _ => tail.syntax().text_range(), - }; - push_to_highlights(file_id, Some(range)); - }); - } - Some(highlights) + if let Some(tail) = tail { + for_each_tail_expr(&tail, &mut |tail| { + let file_id = sema.hir_file_for(tail.syntax()); + let range = match tail { + ast::Expr::BreakExpr(b) => b + .break_token() + .map_or_else(|| tail.syntax().text_range(), |tok| tok.text_range()), + _ => tail.syntax().text_range(), + }; + push_to_highlights(file_id, Some(range)); + }); } + Some(highlights) +} +// If `file_id` is None, +pub(crate) fn highlight_exit_points( + sema: &Semantics<'_, RootDatabase>, + token: SyntaxToken, +) -> FxHashMap> { let mut res = FxHashMap::default(); for def in goto_definition::find_fn_or_blocks(sema, &token) { let new_map = match_ast! { match def { - ast::Fn(fn_) => fn_.body().and_then(|body| hl(sema, fn_.fn_token(), body.into())), + ast::Fn(fn_) => fn_.body().and_then(|body| hl_exit_points(sema, fn_.fn_token(), body.into())), ast::ClosureExpr(closure) => { let pipe_tok = closure.param_list().and_then(|p| p.pipe_token()); - closure.body().and_then(|body| hl(sema, pipe_tok, body)) + closure.body().and_then(|body| hl_exit_points(sema, pipe_tok, body)) }, ast::BlockExpr(blk) => match blk.modifier() { - Some(ast::BlockModifier::Async(t)) => hl(sema, Some(t), blk.into()), + Some(ast::BlockModifier::Async(t)) => hl_exit_points(sema, Some(t), blk.into()), Some(ast::BlockModifier::Try(t)) if token.kind() != T![return] => { - hl(sema, Some(t), blk.into()) + hl_exit_points(sema, Some(t), blk.into()) }, _ => continue, }, @@ -520,6 +516,12 @@ pub(crate) fn highlight_yield_points( if block_expr.async_token().is_none() { continue; } + + // Async blocks act similar to closures. So we want to + // highlight their exit points too. + let exit_points = hl_exit_points(sema, block_expr.async_token(), block_expr.clone().into()); + merge_map(&mut res, exit_points); + hl(sema, block_expr.async_token(), Some(block_expr.into())) }, ast::ClosureExpr(closure) => hl(sema, closure.async_token(), closure.body()), @@ -876,6 +878,27 @@ pub async$0 fn foo() { ); } + #[test] + fn test_hl_exit_points_of_async_blocks() { + check( + r#" +pub fn foo() { + let x = async$0 { + // ^^^^^ + 0.await; + // ^^^^^ + 0?; + // ^ + return 0; + // ^^^^^^ + 0 + // ^ + }; +} +"#, + ); + } + #[test] fn test_hl_let_else_yield_points() { check( @@ -925,11 +948,10 @@ async fn foo() { async fn foo() { (async { // ^^^^^ - (async { - 0.await - }).await$0 } - // ^^^^^ - ).await; + (async { 0.await }).await$0 + // ^^^^^^^^^^^^^^^^^^^^^^^^^ + // ^^^^^ + }).await; } "#, ); From a31ef1059f5f9e1a08d52ced7f7e171f8ec474a3 Mon Sep 17 00:00:00 2001 From: Maybe Lapkin Date: Fri, 20 Sep 2024 11:28:43 +0200 Subject: [PATCH 007/246] Add flake.nix and .envrc --- .envrc | 3 ++ .gitignore | 2 ++ src/tools/nix-dev-shell/flake.nix | 33 ++++++++++++++++++ src/tools/nix-dev-shell/x/default.nix | 22 ++++++++++++ src/tools/nix-dev-shell/x/x.rs | 50 +++++++++++++++++++++++++++ 5 files changed, 110 insertions(+) create mode 100644 .envrc create mode 100644 src/tools/nix-dev-shell/flake.nix create mode 100644 src/tools/nix-dev-shell/x/default.nix create mode 100644 src/tools/nix-dev-shell/x/x.rs diff --git a/.envrc b/.envrc new file mode 100644 index 000000000000..ed519d8d9625 --- /dev/null +++ b/.envrc @@ -0,0 +1,3 @@ +if nix flake show path:./src/tools/nix-dev-shell &> /dev/null; then + use flake path:./src/tools/nix-dev-shell +fi diff --git a/.gitignore b/.gitignore index 2e6499081a63..89c62e126b08 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,8 @@ build/ /src/tools/x/target # Created by default with `src/ci/docker/run.sh` /obj/ +# Created by nix dev shell / .envrc +src/tools/nix-dev-shell/flake.lock ## ICE reports rustc-ice-*.txt diff --git a/src/tools/nix-dev-shell/flake.nix b/src/tools/nix-dev-shell/flake.nix new file mode 100644 index 000000000000..8ab5e097427d --- /dev/null +++ b/src/tools/nix-dev-shell/flake.nix @@ -0,0 +1,33 @@ +{ + description = "rustc dev shell"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + x = import ./x { inherit pkgs; }; + in + { + devShells.default = with pkgs; mkShell { + name = "rustc-dev-shell"; + nativeBuildInputs = with pkgs; [ + binutils cmake ninja pkg-config python3 git curl cacert patchelf nix + ]; + buildInputs = with pkgs; [ + openssl glibc.out glibc.static x + ]; + # Avoid creating text files for ICEs. + RUSTC_ICE = "0"; + # Provide `libstdc++.so.6` for the self-contained lld. + LD_LIBRARY_PATH = "${with pkgs; lib.makeLibraryPath [ + stdenv.cc.cc.lib + ]}"; + }; + } + ); +} diff --git a/src/tools/nix-dev-shell/x/default.nix b/src/tools/nix-dev-shell/x/default.nix new file mode 100644 index 000000000000..e6dfbad6f19c --- /dev/null +++ b/src/tools/nix-dev-shell/x/default.nix @@ -0,0 +1,22 @@ +{ + pkgs ? import { }, +}: +pkgs.stdenv.mkDerivation { + name = "x"; + + src = ./x.rs; + dontUnpack = true; + + nativeBuildInputs = with pkgs; [ rustc ]; + + buildPhase = '' + PYTHON=${pkgs.lib.getExe pkgs.python3} rustc -Copt-level=3 --crate-name x $src --out-dir $out/bin + ''; + + meta = with pkgs.lib; { + description = "Helper for rust-lang/rust x.py"; + homepage = "https://github.com/rust-lang/rust/blob/master/src/tools/x"; + license = licenses.mit; + mainProgram = "x"; + }; +} diff --git a/src/tools/nix-dev-shell/x/x.rs b/src/tools/nix-dev-shell/x/x.rs new file mode 100644 index 000000000000..9f83b8fd62e1 --- /dev/null +++ b/src/tools/nix-dev-shell/x/x.rs @@ -0,0 +1,50 @@ +// git clone https://github.com/rust-lang/rust/blob/0ea7ddcc35a2fcaa5da8a7dcfc118c9fb4a63b95/src/tools/x/src/main.rs +// patched to stop doing python probing, stop the probe, please dont, i have a python +//! Run bootstrap from any subdirectory of a rust compiler checkout. +//! +//! We prefer `exec`, to avoid adding an extra process in the process tree. +//! However, since `exec` isn't available on Windows, we indirect through +//! `exec_or_status`, which will call `exec` on unix and `status` on Windows. +//! +//! We use `powershell.exe x.ps1` on Windows, and `sh -c x` on Unix, those are +//! the ones that call `x.py`. We use `sh -c` on Unix, because it is a standard. +//! We also don't use `pwsh` on Windows, because it is not installed by default; + +use std::env; +use std::os::unix::process::CommandExt; +use std::process::{self, Command}; + +fn main() { + match env::args().skip(1).next().as_deref() { + Some("--wrapper-version") => { + println!("0.1.0"); + return; + } + _ => {} + } + let current = match env::current_dir() { + Ok(dir) => dir, + Err(err) => { + eprintln!("Failed to get current directory: {err}"); + process::exit(1); + } + }; + + for dir in current.ancestors() { + let candidate = dir.join("x.py"); + if candidate.exists() { + let mut cmd = Command::new(env!("PYTHON")); + cmd.arg(dir.join("x.py")); + cmd.args(env::args().skip(1)).current_dir(dir); + + let error = cmd.exec(); + eprintln!("Failed to invoke `{:?}`: {}", cmd, error); + } + } + + eprintln!( + "x.py not found. Please run inside of a checkout of `https://github.com/rust-lang/rust`." + ); + + process::exit(1); +} From 002a6b134f910be617722f9d25e0ea8016c2a54e Mon Sep 17 00:00:00 2001 From: Maybe Lapkin Date: Sat, 21 Sep 2024 11:44:38 +0200 Subject: [PATCH 008/246] Add an option of using nix-shell instead of nix flake --- .envrc | 3 --- src/tools/nix-dev-shell/envrc-flake | 8 ++++++++ src/tools/nix-dev-shell/envrc-shell | 7 +++++++ src/tools/nix-dev-shell/shell.nix | 19 +++++++++++++++++++ 4 files changed, 34 insertions(+), 3 deletions(-) delete mode 100644 .envrc create mode 100644 src/tools/nix-dev-shell/envrc-flake create mode 100644 src/tools/nix-dev-shell/envrc-shell create mode 100644 src/tools/nix-dev-shell/shell.nix diff --git a/.envrc b/.envrc deleted file mode 100644 index ed519d8d9625..000000000000 --- a/.envrc +++ /dev/null @@ -1,3 +0,0 @@ -if nix flake show path:./src/tools/nix-dev-shell &> /dev/null; then - use flake path:./src/tools/nix-dev-shell -fi diff --git a/src/tools/nix-dev-shell/envrc-flake b/src/tools/nix-dev-shell/envrc-flake new file mode 100644 index 000000000000..218d88d8721f --- /dev/null +++ b/src/tools/nix-dev-shell/envrc-flake @@ -0,0 +1,8 @@ +# If you want to use this as an .envrc file to create a shell with necessery components +# to develop rustc, use the following command in the root of the rusr checkout: +# +# ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc && echo .envrc >> .git/info/exclude + +if nix flake show path:./src/tools/nix-dev-shell &> /dev/null; then + use flake path:./src/tools/nix-dev-shell +fi diff --git a/src/tools/nix-dev-shell/envrc-shell b/src/tools/nix-dev-shell/envrc-shell new file mode 100644 index 000000000000..fb7231a6c30c --- /dev/null +++ b/src/tools/nix-dev-shell/envrc-shell @@ -0,0 +1,7 @@ +# If you want to use this as an .envrc file to create a shell with necessery components +# to develop rustc, use the following command in the root of the rusr checkout: +# +# ln -s ./src/tools/nix-dev-shell/envrc-shell ./.envrc && echo .envrc >> .git/info/exclude + +use nix ./src/tools/nix-dev-shell/shell.nix + diff --git a/src/tools/nix-dev-shell/shell.nix b/src/tools/nix-dev-shell/shell.nix new file mode 100644 index 000000000000..8a5cbb7c89e4 --- /dev/null +++ b/src/tools/nix-dev-shell/shell.nix @@ -0,0 +1,19 @@ +{ pkgs ? import {} }: +let + x = import ./x { inherit pkgs; }; +in +pkgs.mkShell { + name = "rustc"; + nativeBuildInputs = with pkgs; [ + binutils cmake ninja pkg-config python3 git curl cacert patchelf nix + ]; + buildInputs = with pkgs; [ + openssl glibc.out glibc.static x + ]; + # Avoid creating text files for ICEs. + RUSTC_ICE = "0"; + # Provide `libstdc++.so.6` for the self-contained lld. + LD_LIBRARY_PATH = "${with pkgs; lib.makeLibraryPath [ + stdenv.cc.cc.lib + ]}"; +} From 9f5bfe24eb254fbe3f745062a4c9ce1c76ff800f Mon Sep 17 00:00:00 2001 From: GnomedDev Date: Sat, 21 Sep 2024 12:46:08 +0100 Subject: [PATCH 009/246] Implement lint for regex::Regex compilation inside a loop --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/regex.rs | 62 +++++++++++++++++++++++++++++- tests/ui/regex.rs | 28 +++++++++++++- tests/ui/regex.stderr | 52 ++++++++++++++++++++++++- 5 files changed, 141 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e5d1688e4a7..c385405e08a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5873,6 +5873,7 @@ Released 2018-09-13 [`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref [`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref [`ref_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_patterns +[`regex_creation_in_loops`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_creation_in_loops [`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro [`renamed_function_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#renamed_function_params [`repeat_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_once diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 16c64830e70d..25a224a47ff7 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -637,6 +637,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::ref_patterns::REF_PATTERNS_INFO, crate::reference::DEREF_ADDROF_INFO, crate::regex::INVALID_REGEX_INFO, + crate::regex::REGEX_CREATION_IN_LOOPS_INFO, crate::regex::TRIVIAL_REGEX_INFO, crate::repeat_vec_with_capacity::REPEAT_VEC_WITH_CAPACITY_INFO, crate::reserve_after_initialization::RESERVE_AFTER_INITIALIZATION_INFO, diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index f6ef02b7c233..1671737db018 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -55,6 +55,44 @@ declare_clippy_lint! { "trivial regular expressions" } +declare_clippy_lint! { + /// ### What it does + /// + /// Checks for [regex](https://crates.io/crates/regex) compilation inside a loop with a literal. + /// + /// ### Why is this bad? + /// + /// Compiling a regex is a much more expensive operation than using one, and a compiled regex can be used multiple times. + /// This is documented as an antipattern [on the regex documentation](https://docs.rs/regex/latest/regex/#avoid-re-compiling-regexes-especially-in-a-loop) + /// + /// ### Example + /// ```no_run + /// # let haystacks = [""]; + /// # const MY_REGEX: &str = "a.b"; + /// for haystack in haystacks { + /// let regex = regex::Regex::new(MY_REGEX).unwrap(); + /// if regex.is_match(haystack) { + /// // Perform operation + /// } + /// } + /// ``` + /// can be replaced with + /// ```no_run + /// # let haystacks = [""]; + /// # const MY_REGEX: &str = "a.b"; + /// let regex = regex::Regex::new(MY_REGEX).unwrap(); + /// for haystack in haystacks { + /// if regex.is_match(haystack) { + /// // Perform operation + /// } + /// } + /// ``` + #[clippy::version = "1.83.0"] + pub REGEX_CREATION_IN_LOOPS, + perf, + "regular expression compilation performed in a loop" +} + #[derive(Copy, Clone)] enum RegexKind { Unicode, @@ -66,9 +104,10 @@ enum RegexKind { #[derive(Default)] pub struct Regex { definitions: DefIdMap, + loop_stack: Vec, } -impl_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]); +impl_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX, REGEX_CREATION_IN_LOOPS]); impl<'tcx> LateLintPass<'tcx> for Regex { fn check_crate(&mut self, cx: &LateContext<'tcx>) { @@ -96,12 +135,33 @@ impl<'tcx> LateLintPass<'tcx> for Regex { && let Some(def_id) = path_def_id(cx, fun) && let Some(regex_kind) = self.definitions.get(&def_id) { + if let Some(&loop_span) = self.loop_stack.last() + && (matches!(arg.kind, ExprKind::Lit(_)) || const_str(cx, arg).is_some()) + { + span_lint_and_help( + cx, + REGEX_CREATION_IN_LOOPS, + fun.span, + "compiling a regex in a loop", + Some(loop_span), + "move the regex construction outside this loop", + ); + } + match regex_kind { RegexKind::Unicode => check_regex(cx, arg, true), RegexKind::UnicodeSet => check_set(cx, arg, true), RegexKind::Bytes => check_regex(cx, arg, false), RegexKind::BytesSet => check_set(cx, arg, false), } + } else if let ExprKind::Loop(_, _, _, span) = expr.kind { + self.loop_stack.push(span); + } + } + + fn check_expr_post(&mut self, _: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if matches!(expr.kind, ExprKind::Loop(..)) { + self.loop_stack.pop(); } } } diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index 4fb6c08bb449..3352239892c5 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -5,7 +5,7 @@ clippy::needless_borrow, clippy::needless_borrows_for_generic_args )] -#![warn(clippy::invalid_regex, clippy::trivial_regex)] +#![warn(clippy::invalid_regex, clippy::trivial_regex, clippy::regex_creation_in_loops)] extern crate regex; @@ -118,7 +118,33 @@ fn trivial_regex() { let _ = BRegex::new(r"\b{start}word\b{end}"); } +fn regex_creation_in_loops() { + loop { + let regex = Regex::new("a.b"); + //~^ ERROR: compiling a regex in a loop + let regex = BRegex::new("a.b"); + //~^ ERROR: compiling a regex in a loop + #[allow(clippy::regex_creation_in_loops)] + let allowed_regex = Regex::new("a.b"); + + if true { + let regex = Regex::new("a.b"); + //~^ ERROR: compiling a regex in a loop + } + + for _ in 0..10 { + let nested_regex = Regex::new("a.b"); + //~^ ERROR: compiling a regex in a loop + } + } + + for i in 0..10 { + let dependant_regex = Regex::new(&format!("{i}")); + } +} + fn main() { syntax_error(); trivial_regex(); + regex_creation_in_loops(); } diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index e936208d8d7b..38e14b163167 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -195,5 +195,55 @@ LL | let binary_trivial_empty = BRegex::new("^$"); | = help: consider using `str::is_empty` -error: aborting due to 24 previous errors +error: compiling a regex in a loop + --> tests/ui/regex.rs:123:21 + | +LL | let regex = Regex::new("a.b"); + | ^^^^^^^^^^ + | +help: move the regex construction outside this loop + --> tests/ui/regex.rs:122:5 + | +LL | loop { + | ^^^^ + = note: `-D clippy::regex-creation-in-loops` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::regex_creation_in_loops)]` + +error: compiling a regex in a loop + --> tests/ui/regex.rs:125:21 + | +LL | let regex = BRegex::new("a.b"); + | ^^^^^^^^^^^ + | +help: move the regex construction outside this loop + --> tests/ui/regex.rs:122:5 + | +LL | loop { + | ^^^^ + +error: compiling a regex in a loop + --> tests/ui/regex.rs:131:25 + | +LL | let regex = Regex::new("a.b"); + | ^^^^^^^^^^ + | +help: move the regex construction outside this loop + --> tests/ui/regex.rs:122:5 + | +LL | loop { + | ^^^^ + +error: compiling a regex in a loop + --> tests/ui/regex.rs:136:32 + | +LL | let nested_regex = Regex::new("a.b"); + | ^^^^^^^^^^ + | +help: move the regex construction outside this loop + --> tests/ui/regex.rs:135:9 + | +LL | for _ in 0..10 { + | ^^^^^^^^^^^^^^ + +error: aborting due to 28 previous errors From b522e7a944341d463bf9091bd72faffcc807d875 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Aug 2024 20:39:25 +0200 Subject: [PATCH 010/246] Generate lint list in HTML directly instead of JS --- .github/deploy.sh | 1 - .gitignore | 1 + Cargo.toml | 2 + clippy_dev/src/serve.rs | 2 +- rinja.toml | 8 ++ tests/compile-test.rs | 33 +++++- .../{index.html => index_template.html} | 103 ++++++++--------- util/gh-pages/script.js | 108 ++++++++++-------- 8 files changed, 152 insertions(+), 106 deletions(-) create mode 100644 rinja.toml rename util/gh-pages/{index.html => index_template.html} (79%) diff --git a/.github/deploy.sh b/.github/deploy.sh index 5b4b4be4e36b..6cebbb7801b0 100644 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -9,7 +9,6 @@ echo "Making the docs for master" mkdir out/master/ cp util/gh-pages/index.html out/master cp util/gh-pages/script.js out/master -cp util/gh-pages/lints.json out/master cp util/gh-pages/style.css out/master if [[ -n $TAG_NAME ]]; then diff --git a/.gitignore b/.gitignore index 181b71a658b9..a7c25b29021f 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ out # gh pages docs util/gh-pages/lints.json +util/gh-pages/index.html # rustfmt backups *.rs.bk diff --git a/Cargo.toml b/Cargo.toml index cf810798d8cc..c7383520741b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,6 +39,8 @@ toml = "0.7.3" walkdir = "2.3" filetime = "0.2.9" itertools = "0.12" +pulldown-cmark = "0.11" +rinja = { version = "0.3", default-features = false, features = ["config"] } # UI test dependencies clippy_utils = { path = "clippy_utils" } diff --git a/clippy_dev/src/serve.rs b/clippy_dev/src/serve.rs index cc14cd8dae69..0216d884e2d5 100644 --- a/clippy_dev/src/serve.rs +++ b/clippy_dev/src/serve.rs @@ -19,7 +19,7 @@ pub fn run(port: u16, lint: Option) -> ! { }); loop { - if mtime("util/gh-pages/lints.json") < mtime("clippy_lints/src") { + if mtime("util/gh-pages/index.html") < mtime("clippy_lints/src") { Command::new(env::var("CARGO").unwrap_or("cargo".into())) .arg("collect-metadata") .spawn() diff --git a/rinja.toml b/rinja.toml new file mode 100644 index 000000000000..5fa682788bd0 --- /dev/null +++ b/rinja.toml @@ -0,0 +1,8 @@ +[general] +dirs = ["util/gh-pages/"] +default_syntax = "mixed" + +[[syntax]] +name = "mixed" +expr_start = "{(" +expr_end = ")}" diff --git a/tests/compile-test.rs b/tests/compile-test.rs index af2aa5192577..0bd6ac677702 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -8,6 +8,8 @@ use clippy_config::ClippyConfiguration; use clippy_lints::LintInfo; use clippy_lints::declared_lints::LINTS; use clippy_lints::deprecated_lints::{DEPRECATED, DEPRECATED_VERSION, RENAMED}; +use pulldown_cmark::{Options, Parser, html}; +use rinja::{Template, filters::Safe}; use serde::{Deserialize, Serialize}; use test_utils::IS_RUSTC_TEST_SUITE; use ui_test::custom_flags::Flag; @@ -385,6 +387,22 @@ fn ui_cargo_toml_metadata() { } } +#[derive(Template)] +#[template(path = "index_template.html")] +struct Renderer<'a> { + lints: &'a Vec, +} + +impl<'a> Renderer<'a> { + fn markdown(&self, input: &str) -> Safe { + let parser = Parser::new_ext(input, Options::all()); + let mut html_output = String::new(); + html::push_html(&mut html_output, parser); + // Oh deer, what a hack :O + Safe(html_output.replace(", @@ -559,4 +576,14 @@ impl LintMetadata { applicability: Applicability::Unspecified, } } + + fn applicability_str(&self) -> &str { + match self.applicability { + Applicability::MachineApplicable => "MachineApplicable", + Applicability::HasPlaceholders => "HasPlaceholders", + Applicability::MaybeIncorrect => "MaybeIncorrect", + Applicability::Unspecified => "Unspecified", + _ => panic!("needs to update this code"), + } + } } diff --git a/util/gh-pages/index.html b/util/gh-pages/index_template.html similarity index 79% rename from util/gh-pages/index.html rename to util/gh-pages/index_template.html index f3d7e504fdf8..ee134eaaa98e 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index_template.html @@ -55,16 +55,8 @@ Otherwise, have a great day =^.^= -
- - - - -
+
+
@@ -188,9 +180,7 @@ Otherwise, have a great day =^.^=
- +
- -
-
-

-
- {{lint.id}} - - - 📋 - -
+ {% for lint in lints %} +
+
+

+
+ {(lint.id)} + + + 📋 + +
-
- {{lint.group}} +
+ {(lint.group)} - {{lint.level}} + {(lint.level)} - - + -
-

-
+ + + +

+ + -
-
-
- -
- Applicability: - {{lint.applicability}} - (?) -
- -
- {{lint.group == "deprecated" ? "Deprecated" : "Added"}} in: - {{lint.version}} -
- - - -
- View Source +
+
{(markdown(lint.docs))}
+
+ {# Applicability #} +
+ Applicability: + {( lint.applicability_str() )} + (?) +
+ +
+ {% if lint.group == "deprecated" %}Deprecated{% else %} Added{% endif %} in: + {(lint.version)} +
+ + + +
-
- + + {% endfor %}
diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index 1a5330bc0e57..8942628d5da0 100644 --- a/util/gh-pages/script.js +++ b/util/gh-pages/script.js @@ -1,21 +1,4 @@ (function () { - const md = window.markdownit({ - html: true, - linkify: true, - typographer: true, - highlight: function (str, lang) { - if (lang && hljs.getLanguage(lang)) { - try { - return '
' +
-                        hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
-                        '
'; - } catch (__) {} - } - - return '
' + md.utils.escapeHtml(str) + '
'; - } - }); - function scrollToLint(lintId) { const target = document.getElementById(lintId); if (!target) { @@ -41,15 +24,6 @@ } angular.module("clippy", []) - .filter('markdown', function ($sce) { - return function (text) { - return $sce.trustAsHtml( - md.render(text || '') - // Oh deer, what a hack :O - .replace(' { + if (searchState.timeout !== null) { + clearTimeout(searchState.timeout); + searchState.timeout = null + } + }, + resetInputTimeout: () => { + searchState.clearInputTimeout(); + setTimeout(searchState.filterLints, 50); + }, + filterLints: () => { + let searchStr = searchState.value.trim().toLowerCase(); + if (searchStr.startsWith("clippy::")) { + searchStr = searchStr.slice(8); + } + const terms = searchStr.split(" "); + + onEachLazy(document.querySelectorAll("article"), lint => { + // Search by id + if (lint.id.indexOf(searchStr.replaceAll("-", "_")) !== -1) { + el.style.display = ""; + return; + } + // Search the description + // The use of `for`-loops instead of `foreach` enables us to return early + const docsLowerCase = lint.docs.toLowerCase(); + for (index = 0; index < terms.length; index++) { + // This is more likely and will therefore be checked first + if (docsLowerCase.indexOf(terms[index]) !== -1) { + continue; + } + + if (lint.id.indexOf(terms[index]) !== -1) { + continue; + } + + return false; + } + }); + }, +}; + +function handleInputChanged(event) { + if (event.target !== document.activeElement) { + return; + } + searchState.resetInputTimeout(); +} + function storeValue(settingName, value) { try { localStorage.setItem(`clippy-lint-list-${settingName}`, value); @@ -627,3 +643,5 @@ if (prefersDark.matches && !theme) { } let disableShortcuts = loadValue('disable-shortcuts') === "true"; document.getElementById("disable-shortcuts").checked = disableShortcuts; + +hljs.highlightAll(); From 9661ba07408c901d9521e27ee8453f769ab12744 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Aug 2024 20:47:42 +0200 Subject: [PATCH 011/246] Update `cargo dev serve` command to look over the correct files --- clippy_dev/src/serve.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_dev/src/serve.rs b/clippy_dev/src/serve.rs index 0216d884e2d5..d367fefec619 100644 --- a/clippy_dev/src/serve.rs +++ b/clippy_dev/src/serve.rs @@ -19,7 +19,9 @@ pub fn run(port: u16, lint: Option) -> ! { }); loop { - if mtime("util/gh-pages/index.html") < mtime("clippy_lints/src") { + let index_time = mtime("util/gh-pages/index.html"); + + if index_time < mtime("clippy_lints/src") || index_time < mtime("util/gh-pages/index_template.html") { Command::new(env::var("CARGO").unwrap_or("cargo".into())) .arg("collect-metadata") .spawn() From 0055cebaa3c0ab3cb0921efa20b18b0f291ae3ea Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Aug 2024 20:47:54 +0200 Subject: [PATCH 012/246] Replace search with vanilla JS --- tests/compile-test.rs | 2 +- util/gh-pages/index_template.html | 29 +++++++------ util/gh-pages/script.js | 68 ++++++++++++------------------- 3 files changed, 43 insertions(+), 56 deletions(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 0bd6ac677702..00627dc0bb1f 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -10,7 +10,7 @@ use clippy_lints::declared_lints::LINTS; use clippy_lints::deprecated_lints::{DEPRECATED, DEPRECATED_VERSION, RENAMED}; use pulldown_cmark::{Options, Parser, html}; use rinja::{Template, filters::Safe}; -use serde::{Deserialize, Serialize}; +use serde::Deserialize; use test_utils::IS_RUSTC_TEST_SUITE; use ui_test::custom_flags::Flag; use ui_test::custom_flags::rustfix::RustfixMode; diff --git a/util/gh-pages/index_template.html b/util/gh-pages/index_template.html index ee134eaaa98e..5baa03da2ea4 100644 --- a/util/gh-pages/index_template.html +++ b/util/gh-pages/index_template.html @@ -180,9 +180,9 @@ Otherwise, have a great day =^.^=
- + - @@ -199,22 +199,22 @@ Otherwise, have a great day =^.^=
{% for lint in lints %} -
+

{(lint.id)} - - + 📋
- {(lint.group)} + {(lint.group)} - {(lint.level)} + {(lint.level)} @@ -223,7 +223,7 @@ Otherwise, have a great day =^.^=

-
+
{(markdown(lint.docs))}
{# Applicability #} @@ -232,18 +232,21 @@ Otherwise, have a great day =^.^= {( lint.applicability_str() )} (?)
- + {# Clippy version #}
{% if lint.group == "deprecated" %}Deprecated{% else %} Added{% endif %} in: {(lint.version)}
- + {# Open related issues #} - -
- View Source + + {# Jump to source #} + {% if let Some(id_location) = lint.id_location %} +
+ View Source + {% endif %}
diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index 8942628d5da0..eb563a0f242c 100644 --- a/util/gh-pages/script.js +++ b/util/gh-pages/script.js @@ -361,42 +361,6 @@ return $scope.groups[lint.group]; }; - $scope.bySearch = function (lint, index, array) { - let searchStr = $scope.search; - // It can be `null` I haven't missed this value - if (searchStr == null) { - return true; - } - searchStr = searchStr.toLowerCase(); - if (searchStr.startsWith("clippy::")) { - searchStr = searchStr.slice(8); - } - - // Search by id - if (lint.id.indexOf(searchStr.replaceAll("-", "_")) !== -1) { - return true; - } - - // Search the description - // The use of `for`-loops instead of `foreach` enables us to return early - const terms = searchStr.split(" "); - const docsLowerCase = lint.docs.toLowerCase(); - for (index = 0; index < terms.length; index++) { - // This is more likely and will therefore be checked first - if (docsLowerCase.indexOf(terms[index]) !== -1) { - continue; - } - - if (lint.id.indexOf(terms[index]) !== -1) { - continue; - } - - return false; - } - - return true; - } - $scope.byApplicabilities = function (lint) { return $scope.applicabilities[lint.applicability]; }; @@ -472,6 +436,11 @@ function getQueryVariable(variable) { window.searchState = { timeout: null, inputElem: document.getElementById("search-input"), + lastSearch: '', + clearInput: () => { + searchState.inputElem.value = ""; + searchState.filterLints(); + }, clearInputTimeout: () => { if (searchState.timeout !== null) { clearTimeout(searchState.timeout); @@ -483,32 +452,38 @@ window.searchState = { setTimeout(searchState.filterLints, 50); }, filterLints: () => { - let searchStr = searchState.value.trim().toLowerCase(); + searchState.clearInputTimeout(); + + let searchStr = searchState.inputElem.value.trim().toLowerCase(); if (searchStr.startsWith("clippy::")) { searchStr = searchStr.slice(8); } + if (searchState.lastSearch === searchStr) { + return; + } + searchState.lastSearch = searchStr; const terms = searchStr.split(" "); onEachLazy(document.querySelectorAll("article"), lint => { // Search by id if (lint.id.indexOf(searchStr.replaceAll("-", "_")) !== -1) { - el.style.display = ""; + lint.style.display = ""; return; } // Search the description // The use of `for`-loops instead of `foreach` enables us to return early - const docsLowerCase = lint.docs.toLowerCase(); + const docsLowerCase = lint.textContent.toLowerCase(); for (index = 0; index < terms.length; index++) { // This is more likely and will therefore be checked first if (docsLowerCase.indexOf(terms[index]) !== -1) { - continue; + return; } if (lint.id.indexOf(terms[index]) !== -1) { - continue; + return; } - return false; + lint.style.display = "none"; } }); }, @@ -631,7 +606,16 @@ function generateSettings() { ); } +function generateSearch() { + searchState.inputElem.addEventListener("change", handleInputChanged); + searchState.inputElem.addEventListener("input", handleInputChanged); + searchState.inputElem.addEventListener("keydown", handleInputChanged); + searchState.inputElem.addEventListener("keyup", handleInputChanged); + searchState.inputElem.addEventListener("paste", handleInputChanged); +} + generateSettings(); +generateSearch(); // loading the theme after the initial load const prefersDark = window.matchMedia("(prefers-color-scheme: dark)"); From 574e3dd9226774d5a11cec900ec5322fbf7d6f28 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Aug 2024 22:34:14 +0200 Subject: [PATCH 013/246] Finish porting lint functionalities to vanilla JS --- util/gh-pages/index_template.html | 19 ++- util/gh-pages/script.js | 230 +++++++++++++++++------------- util/gh-pages/style.css | 4 + 3 files changed, 140 insertions(+), 113 deletions(-) diff --git a/util/gh-pages/index_template.html b/util/gh-pages/index_template.html index 5baa03da2ea4..6571283cbf4d 100644 --- a/util/gh-pages/index_template.html +++ b/util/gh-pages/index_template.html @@ -199,14 +199,13 @@ Otherwise, have a great day =^.^=
{% for lint in lints %} -
-
+
{# Open related issues #} {# Jump to source #} {% if let Some(id_location) = lint.id_location %}
- View Source + View Source {% endif %}
@@ -315,7 +313,6 @@ Otherwise, have a great day =^.^= - diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index eb563a0f242c..902827b97e49 100644 --- a/util/gh-pages/script.js +++ b/util/gh-pages/script.js @@ -1,19 +1,4 @@ (function () { - function scrollToLint(lintId) { - const target = document.getElementById(lintId); - if (!target) { - return; - } - target.scrollIntoView(); - } - - function scrollToLintByURL($scope, $location) { - const removeListener = $scope.$on('ngRepeatFinished', function (ngRepeatFinishedEvent) { - scrollToLint($location.path().substring(1)); - removeListener(); - }); - } - function selectGroup($scope, selectedGroup) { const groups = $scope.groups; for (const group in groups) { @@ -365,39 +350,12 @@ return $scope.applicabilities[lint.applicability]; }; - // Show details for one lint - $scope.openLint = function (lint) { - $scope.open[lint.id] = true; - $location.path(lint.id); - }; - $scope.toggleExpansion = function(lints, isExpanded) { lints.forEach(lint => { $scope.open[lint.id] = isExpanded; }); } - $scope.copyToClipboard = function (lint) { - const clipboard = document.getElementById("clipboard-" + lint.id); - if (clipboard) { - let resetClipboardTimeout = null; - const resetClipboardIcon = clipboard.innerHTML; - - function resetClipboard() { - resetClipboardTimeout = null; - clipboard.innerHTML = resetClipboardIcon; - } - - navigator.clipboard.writeText("clippy::" + lint.id); - - clipboard.innerHTML = "✓"; - if (resetClipboardTimeout !== null) { - clearTimeout(resetClipboardTimeout); - } - resetClipboardTimeout = setTimeout(resetClipboard, 1000); - } - } - // Get data $scope.open = {}; $scope.loading = true; @@ -413,8 +371,6 @@ selectGroup($scope, selectedGroup.toLowerCase()); } - scrollToLintByURL($scope, $location); - setTimeout(function () { const el = document.getElementById('filter-input'); if (el) { el.focus() } @@ -433,6 +389,65 @@ function getQueryVariable(variable) { } } +function storeValue(settingName, value) { + try { + localStorage.setItem(`clippy-lint-list-${settingName}`, value); + } catch (e) { } +} + +function loadValue(settingName) { + return localStorage.getItem(`clippy-lint-list-${settingName}`); +} + +function setTheme(theme, store) { + let enableHighlight = false; + let enableNight = false; + let enableAyu = false; + + switch(theme) { + case "ayu": + enableAyu = true; + break; + case "coal": + case "navy": + enableNight = true; + break; + case "rust": + enableHighlight = true; + break; + default: + enableHighlight = true; + theme = "light"; + break; + } + + document.getElementsByTagName("body")[0].className = theme; + + document.getElementById("githubLightHighlight").disabled = enableNight || !enableHighlight; + document.getElementById("githubDarkHighlight").disabled = !enableNight && !enableAyu; + + document.getElementById("styleHighlight").disabled = !enableHighlight; + document.getElementById("styleNight").disabled = !enableNight; + document.getElementById("styleAyu").disabled = !enableAyu; + + if (store) { + storeValue("theme", theme); + } else { + document.getElementById(`theme-choice`).value = theme; + } +} + +// loading the theme after the initial load +const prefersDark = window.matchMedia("(prefers-color-scheme: dark)"); +const theme = loadValue('theme'); +if (prefersDark.matches && !theme) { + setTheme("coal", false); +} else { + setTheme(theme, false); +} +let disableShortcuts = loadValue('disable-shortcuts') === "true"; +document.getElementById("disable-shortcuts").checked = disableShortcuts; + window.searchState = { timeout: null, inputElem: document.getElementById("search-input"), @@ -486,6 +501,11 @@ window.searchState = { lint.style.display = "none"; } }); + if (searchStr.length > 0) { + window.location.hash = `/${searchStr}`; + } else { + window.location.hash = ''; + } }, }; @@ -496,54 +516,6 @@ function handleInputChanged(event) { searchState.resetInputTimeout(); } -function storeValue(settingName, value) { - try { - localStorage.setItem(`clippy-lint-list-${settingName}`, value); - } catch (e) { } -} - -function loadValue(settingName) { - return localStorage.getItem(`clippy-lint-list-${settingName}`); -} - -function setTheme(theme, store) { - let enableHighlight = false; - let enableNight = false; - let enableAyu = false; - - switch(theme) { - case "ayu": - enableAyu = true; - break; - case "coal": - case "navy": - enableNight = true; - break; - case "rust": - enableHighlight = true; - break; - default: - enableHighlight = true; - theme = "light"; - break; - } - - document.getElementsByTagName("body")[0].className = theme; - - document.getElementById("githubLightHighlight").disabled = enableNight || !enableHighlight; - document.getElementById("githubDarkHighlight").disabled = !enableNight && !enableAyu; - - document.getElementById("styleHighlight").disabled = !enableHighlight; - document.getElementById("styleNight").disabled = !enableNight; - document.getElementById("styleAyu").disabled = !enableAyu; - - if (store) { - storeValue("theme", theme); - } else { - document.getElementById(`theme-choice`).value = theme; - } -} - function handleShortcut(ev) { if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts) { return; @@ -584,6 +556,52 @@ function onEachLazy(lazyArray, func) { } } +function expandLintId(lintId) { + searchState.inputElem.value = lintId; + searchState.filterLints(); + + // Expand the lint. + const lintElem = document.getElementById(lintId); + const isCollapsed = lintElem.classList.remove("collapsed"); + lintElem.querySelector(".label-doc-folding").innerText = "-"; +} + +// Show details for one lint +function openLint(event) { + event.preventDefault(); + event.stopPropagation(); + expandLintId(event.target.getAttribute("href").slice(1)); +} + +function expandLint(lintId) { + const lintElem = document.getElementById(lintId); + const isCollapsed = lintElem.classList.toggle("collapsed"); + lintElem.querySelector(".label-doc-folding").innerText = isCollapsed ? "+" : "-"; +} + +function copyToClipboard(event) { + event.preventDefault(); + event.stopPropagation(); + + const clipboard = event.target; + + let resetClipboardTimeout = null; + const resetClipboardIcon = clipboard.innerHTML; + + function resetClipboard() { + resetClipboardTimeout = null; + clipboard.innerHTML = resetClipboardIcon; + } + + navigator.clipboard.writeText("clippy::" + clipboard.parentElement.id.slice(5)); + + clipboard.innerHTML = "✓"; + if (resetClipboardTimeout !== null) { + clearTimeout(resetClipboardTimeout); + } + resetClipboardTimeout = setTimeout(resetClipboard, 1000); +} + function handleBlur(event) { const parent = document.getElementById("settings-dropdown"); if (!parent.contains(document.activeElement) && @@ -617,15 +635,23 @@ function generateSearch() { generateSettings(); generateSearch(); -// loading the theme after the initial load -const prefersDark = window.matchMedia("(prefers-color-scheme: dark)"); -const theme = loadValue('theme'); -if (prefersDark.matches && !theme) { - setTheme("coal", false); -} else { - setTheme(theme, false); +function scrollToLint(lintId) { + const target = document.getElementById(lintId); + if (!target) { + return; + } + target.scrollIntoView(); + expandLintId(lintId); } -let disableShortcuts = loadValue('disable-shortcuts') === "true"; -document.getElementById("disable-shortcuts").checked = disableShortcuts; -hljs.highlightAll(); +// If the page we arrive on has link to a given lint, we scroll to it. +function scrollToLintByURL() { + const lintId = window.location.hash.substring(2); + if (lintId.length > 0) { + scrollToLint(lintId); + } +} + +scrollToLintByURL(); + +onEachLazy(document.querySelectorAll("pre > code.language-rust"), el => hljs.highlightElement(el)); diff --git a/util/gh-pages/style.css b/util/gh-pages/style.css index a9485d511047..9af566b5aa9e 100644 --- a/util/gh-pages/style.css +++ b/util/gh-pages/style.css @@ -396,3 +396,7 @@ body { background: var(--bg); color: var(--fg); } + +article.collapsed .lint-docs { + display: none; +} \ No newline at end of file From f2193c680cc5e2d9cf711af0a9bb92b15887c892 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Aug 2024 23:43:35 +0200 Subject: [PATCH 014/246] Completely remove angular and generate parts of settings in JS --- util/gh-pages/index_template.html | 80 ++--- util/gh-pages/script.js | 469 +++++------------------------- 2 files changed, 102 insertions(+), 447 deletions(-) diff --git a/util/gh-pages/index_template.html b/util/gh-pages/index_template.html index 6571283cbf4d..5a7af7d562ed 100644 --- a/util/gh-pages/index_template.html +++ b/util/gh-pages/index_template.html @@ -25,7 +25,7 @@ Otherwise, have a great day =^.^= - +
@@ -59,121 +59,90 @@ Otherwise, have a great day =^.^=
-
+
-
-
+
-
-
+
-
+
-
@@ -189,10 +158,10 @@ Otherwise, have a great day =^.^=
- -
@@ -315,7 +284,6 @@ Otherwise, have a great day =^.^= - diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index 902827b97e49..6f506956e7c9 100644 --- a/util/gh-pages/script.js +++ b/util/gh-pages/script.js @@ -1,394 +1,3 @@ -(function () { - function selectGroup($scope, selectedGroup) { - const groups = $scope.groups; - for (const group in groups) { - if (groups.hasOwnProperty(group)) { - groups[group] = group === selectedGroup; - } - } - } - - angular.module("clippy", []) - .directive('filterDropdown', function ($document) { - return { - restrict: 'A', - link: function ($scope, $element, $attr) { - $element.bind('click', function (event) { - if (event.target.closest('button')) { - $element.toggleClass('open'); - } else { - $element.addClass('open'); - } - $element.addClass('open-recent'); - }); - - $document.bind('click', function () { - if (!$element.hasClass('open-recent')) { - $element.removeClass('open'); - } - $element.removeClass('open-recent'); - }) - } - } - }) - .directive('onFinishRender', function ($timeout) { - return { - restrict: 'A', - link: function (scope, element, attr) { - if (scope.$last === true) { - $timeout(function () { - scope.$emit(attr.onFinishRender); - }); - } - } - }; - }) - .controller("lintList", function ($scope, $http, $location, $timeout) { - // Level filter - const LEVEL_FILTERS_DEFAULT = {allow: true, warn: true, deny: true, none: true}; - $scope.levels = { ...LEVEL_FILTERS_DEFAULT }; - $scope.byLevels = function (lint) { - return $scope.levels[lint.level]; - }; - - const GROUPS_FILTER_DEFAULT = { - cargo: true, - complexity: true, - correctness: true, - nursery: true, - pedantic: true, - perf: true, - restriction: true, - style: true, - suspicious: true, - deprecated: false, - } - - $scope.groups = { - ...GROUPS_FILTER_DEFAULT - }; - - $scope.versionFilters = { - "≥": {enabled: false, minorVersion: null }, - "≤": {enabled: false, minorVersion: null }, - "=": {enabled: false, minorVersion: null }, - }; - - // Map the versionFilters to the query parameters in a way that is easier to work with in a URL - const versionFilterKeyMap = { - "≥": "gte", - "≤": "lte", - "=": "eq" - }; - const reverseVersionFilterKeyMap = Object.fromEntries( - Object.entries(versionFilterKeyMap).map(([key, value]) => [value, key]) - ); - - const APPLICABILITIES_FILTER_DEFAULT = { - MachineApplicable: true, - MaybeIncorrect: true, - HasPlaceholders: true, - Unspecified: true, - }; - - $scope.applicabilities = { - ...APPLICABILITIES_FILTER_DEFAULT - } - - // loadFromURLParameters retrieves filter settings from the URL parameters and assigns them - // to corresponding $scope variables. - function loadFromURLParameters() { - // Extract parameters from URL - const urlParameters = $location.search(); - - // Define a helper function that assigns URL parameters to a provided scope variable - const handleParameter = (parameter, scopeVariable, defaultValues) => { - if (urlParameters[parameter]) { - const items = urlParameters[parameter].split(','); - for (const key in scopeVariable) { - if (scopeVariable.hasOwnProperty(key)) { - scopeVariable[key] = items.includes(key); - } - } - } else if (defaultValues) { - for (const key in defaultValues) { - if (scopeVariable.hasOwnProperty(key)) { - scopeVariable[key] = defaultValues[key]; - } - } - } - }; - - handleParameter('levels', $scope.levels, LEVEL_FILTERS_DEFAULT); - handleParameter('groups', $scope.groups, GROUPS_FILTER_DEFAULT); - handleParameter('applicabilities', $scope.applicabilities, APPLICABILITIES_FILTER_DEFAULT); - - // Handle 'versions' parameter separately because it needs additional processing - if (urlParameters.versions) { - const versionFilters = urlParameters.versions.split(','); - for (const versionFilter of versionFilters) { - const [key, minorVersion] = versionFilter.split(':'); - const parsedMinorVersion = parseInt(minorVersion); - - // Map the key from the URL parameter to its original form - const originalKey = reverseVersionFilterKeyMap[key]; - - if (originalKey in $scope.versionFilters && !isNaN(parsedMinorVersion)) { - $scope.versionFilters[originalKey].enabled = true; - $scope.versionFilters[originalKey].minorVersion = parsedMinorVersion; - } - } - } - - // Load the search parameter from the URL path - const searchParameter = $location.path().substring(1); // Remove the leading slash - if (searchParameter) { - $scope.search = searchParameter; - $scope.open[searchParameter] = true; - scrollToLintByURL($scope, $location); - } - } - - // updateURLParameter updates the URL parameter with the given key to the given value - function updateURLParameter(filterObj, urlKey, defaultValue = {}, processFilter = filter => filter) { - const parameter = Object.keys(filterObj) - .filter(filter => filterObj[filter]) - .sort() - .map(processFilter) - .filter(Boolean) // Filters out any falsy values, including null - .join(','); - - const defaultParameter = Object.keys(defaultValue) - .filter(filter => defaultValue[filter]) - .sort() - .map(processFilter) - .filter(Boolean) // Filters out any falsy values, including null - .join(','); - - // if we ended up back at the defaults, just remove it from the URL - if (parameter === defaultParameter) { - $location.search(urlKey, null); - } else { - $location.search(urlKey, parameter || null); - } - } - - // updateVersionURLParameter updates the version URL parameter with the given version filters - function updateVersionURLParameter(versionFilters) { - updateURLParameter( - versionFilters, - 'versions', {}, - versionFilter => versionFilters[versionFilter].enabled && versionFilters[versionFilter].minorVersion != null - ? `${versionFilterKeyMap[versionFilter]}:${versionFilters[versionFilter].minorVersion}` - : null - ); - } - - // updateAllURLParameters updates all the URL parameters with the current filter settings - function updateAllURLParameters() { - updateURLParameter($scope.levels, 'levels', LEVEL_FILTERS_DEFAULT); - updateURLParameter($scope.groups, 'groups', GROUPS_FILTER_DEFAULT); - updateVersionURLParameter($scope.versionFilters); - updateURLParameter($scope.applicabilities, 'applicabilities', APPLICABILITIES_FILTER_DEFAULT); - } - - // Add $watches to automatically update URL parameters when the data changes - $scope.$watch('levels', function (newVal, oldVal) { - if (newVal !== oldVal) { - updateURLParameter(newVal, 'levels', LEVEL_FILTERS_DEFAULT); - } - }, true); - - $scope.$watch('groups', function (newVal, oldVal) { - if (newVal !== oldVal) { - updateURLParameter(newVal, 'groups', GROUPS_FILTER_DEFAULT); - } - }, true); - - $scope.$watch('versionFilters', function (newVal, oldVal) { - if (newVal !== oldVal) { - updateVersionURLParameter(newVal); - } - }, true); - - $scope.$watch('applicabilities', function (newVal, oldVal) { - if (newVal !== oldVal) { - updateURLParameter(newVal, 'applicabilities', APPLICABILITIES_FILTER_DEFAULT) - } - }, true); - - // Watch for changes in the URL path and update the search and lint display - $scope.$watch(function () { return $location.path(); }, function (newPath) { - const searchParameter = newPath.substring(1); - if ($scope.search !== searchParameter) { - $scope.search = searchParameter; - $scope.open[searchParameter] = true; - scrollToLintByURL($scope, $location); - } - }); - - let debounceTimeout; - $scope.$watch('search', function (newVal, oldVal) { - if (newVal !== oldVal) { - if (debounceTimeout) { - $timeout.cancel(debounceTimeout); - } - - debounceTimeout = $timeout(function () { - $location.path(newVal); - }, 1000); - } - }); - - $scope.$watch(function () { return $location.search(); }, function (newParameters) { - loadFromURLParameters(); - }, true); - - $scope.updatePath = function () { - if (debounceTimeout) { - $timeout.cancel(debounceTimeout); - } - - $location.path($scope.search); - } - - $scope.toggleLevels = function (value) { - const levels = $scope.levels; - for (const key in levels) { - if (levels.hasOwnProperty(key)) { - levels[key] = value; - } - } - }; - - $scope.toggleGroups = function (value) { - const groups = $scope.groups; - for (const key in groups) { - if (groups.hasOwnProperty(key)) { - groups[key] = value; - } - } - }; - - $scope.toggleApplicabilities = function (value) { - const applicabilities = $scope.applicabilities; - for (const key in applicabilities) { - if (applicabilities.hasOwnProperty(key)) { - applicabilities[key] = value; - } - } - } - - $scope.resetGroupsToDefault = function () { - $scope.groups = { - ...GROUPS_FILTER_DEFAULT - }; - }; - - $scope.selectedValuesCount = function (obj) { - return Object.values(obj).filter(x => x).length; - } - - $scope.clearVersionFilters = function () { - for (const filter in $scope.versionFilters) { - $scope.versionFilters[filter] = { enabled: false, minorVersion: null }; - } - } - - $scope.versionFilterCount = function(obj) { - return Object.values(obj).filter(x => x.enabled).length; - } - - $scope.updateVersionFilters = function() { - for (const filter in $scope.versionFilters) { - const minorVersion = $scope.versionFilters[filter].minorVersion; - - // 1.29.0 and greater - if (minorVersion && minorVersion > 28) { - $scope.versionFilters[filter].enabled = true; - continue; - } - - $scope.versionFilters[filter].enabled = false; - } - } - - $scope.byVersion = function(lint) { - const filters = $scope.versionFilters; - for (const filter in filters) { - if (filters[filter].enabled) { - const minorVersion = filters[filter].minorVersion; - - // Strip the "pre " prefix for pre 1.29.0 lints - const lintVersion = lint.version.startsWith("pre ") ? lint.version.substring(4, lint.version.length) : lint.version; - const lintMinorVersion = lintVersion.substring(2, 4); - - switch (filter) { - // "=" gets the highest priority, since all filters are inclusive - case "=": - return (lintMinorVersion == minorVersion); - case "≥": - if (lintMinorVersion < minorVersion) { return false; } - break; - case "≤": - if (lintMinorVersion > minorVersion) { return false; } - break; - default: - return true - } - } - } - - return true; - } - - $scope.byGroups = function (lint) { - return $scope.groups[lint.group]; - }; - - $scope.byApplicabilities = function (lint) { - return $scope.applicabilities[lint.applicability]; - }; - - $scope.toggleExpansion = function(lints, isExpanded) { - lints.forEach(lint => { - $scope.open[lint.id] = isExpanded; - }); - } - - // Get data - $scope.open = {}; - $scope.loading = true; - - // This will be used to jump into the source code of the version that this documentation is for. - $scope.docVersion = window.location.pathname.split('/')[2] || "master"; - - // Set up the filters from the URL parameters before we start loading the data - loadFromURLParameters(); - - const selectedGroup = getQueryVariable("sel"); - if (selectedGroup) { - selectGroup($scope, selectedGroup.toLowerCase()); - } - - setTimeout(function () { - const el = document.getElementById('filter-input'); - if (el) { el.focus() } - }, 0); - }); -})(); - -function getQueryVariable(variable) { - const query = window.location.search.substring(1); - const vars = query.split('&'); - for (const entry of vars) { - const pair = entry.split('='); - if (decodeURIComponent(pair[0]) == variable) { - return decodeURIComponent(pair[1]); - } - } -} - function storeValue(settingName, value) { try { localStorage.setItem(`clippy-lint-list-${settingName}`, value); @@ -611,6 +220,34 @@ function handleBlur(event) { } } +function toggleExpansion(expand) { + onEachLazy( + document.querySelectorAll("article"), + expand ? el => el.classList.remove("collapsed") : el => el.classList.add("collapsed"), + ); +} + +function generateListOfOptions(list, elementId) { + let html = ''; + let nbEnabled = 0; + for (const [key, value] of Object.entries(list)) { + const attr = value ? " checked" : ""; + html += `\ +
  • \ + \ +
  • `; + if (value) { + nbEnabled += 1; + } + } + + const elem = document.getElementById(elementId); + elem.previousElementSibling.querySelector(".badge").innerText = `${nbEnabled}`; + elem.innerHTML += html; +} + function generateSettings() { const settings = document.getElementById("settings-dropdown"); const settingsButton = settings.querySelector(".settings-icon") @@ -622,6 +259,56 @@ function generateSettings() { settingsMenu.querySelectorAll("input"), el => el.onblur = handleBlur, ); + + const LEVEL_FILTERS_DEFAULT = {allow: true, warn: true, deny: true, none: true}; + generateListOfOptions(LEVEL_FILTERS_DEFAULT, "lint-levels"); + + // Generate lint groups. + const GROUPS_FILTER_DEFAULT = { + cargo: true, + complexity: true, + correctness: true, + deprecated: false, + nursery: true, + pedantic: true, + perf: true, + restriction: true, + style: true, + suspicious: true, + }; + generateListOfOptions(GROUPS_FILTER_DEFAULT, "lint-groups"); + + const APPLICABILITIES_FILTER_DEFAULT = { + Unspecified: true, + Unresolved: true, + MachineApplicable: true, + MaybeIncorrect: true, + HasPlaceholders: true + }; + generateListOfOptions(APPLICABILITIES_FILTER_DEFAULT, "lint-applicabilities"); + + const VERSIONS_FILTERS = { + "≥": {enabled: false, minorVersion: null }, + "≤": {enabled: false, minorVersion: null }, + "=": {enabled: false, minorVersion: null }, + }; + + let html = ''; + for (const kind of ["≥", "≤", "="]) { + html += `\ +
  • \ + \ + 1. \ + \ + .0\ +
  • `; + } + document.getElementById("version-filter-selector").innerHTML += html; } function generateSearch() { From 4484085b18df4b10243b503a21602bb71836e8b3 Mon Sep 17 00:00:00 2001 From: Laiho Date: Mon, 9 Sep 2024 00:58:52 +0300 Subject: [PATCH 015/246] Add fast path for ascii to ascii in str::replace --- library/alloc/src/str.rs | 25 ++++++++++++++++++++++++- library/alloc/src/string.rs | 7 ++++++- library/core/src/str/pattern.rs | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index 32212b61c6e8..709d11c52a06 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -19,7 +19,7 @@ pub use core::str::SplitInclusive; pub use core::str::SplitWhitespace; #[stable(feature = "rust1", since = "1.0.0")] pub use core::str::pattern; -use core::str::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher}; +use core::str::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher, Utf8Pattern}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::str::{Bytes, CharIndices, Chars, from_utf8, from_utf8_mut}; #[stable(feature = "str_escape", since = "1.34.0")] @@ -268,6 +268,18 @@ impl str { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn replace(&self, from: P, to: &str) -> String { + // Fast path for ASCII to ASCII case. + + if let Some(from_byte) = match from.as_utf8_pattern() { + Some(Utf8Pattern::StringPattern([from_byte])) => Some(*from_byte), + Some(Utf8Pattern::CharPattern(c)) => c.as_ascii().map(|ascii_char| ascii_char.to_u8()), + _ => None, + } { + if let [to_byte] = to.as_bytes() { + return unsafe { replace_ascii(self.as_bytes(), from_byte, *to_byte) }; + } + } + let mut result = String::new(); let mut last_end = 0; for (start, part) in self.match_indices(from) { @@ -661,3 +673,14 @@ fn convert_while_ascii(b: &[u8], convert: fn(&u8) -> u8) -> Vec { out } +#[inline] +#[cfg(not(test))] +#[cfg(not(no_global_oom_handling))] +#[allow(dead_code)] +/// Faster implementation of string replacement for ASCII to ASCII cases. +/// Should produce fast vectorized code. +unsafe fn replace_ascii(utf8_bytes: &[u8], from: u8, to: u8) -> String { + let result: Vec = utf8_bytes.iter().map(|b| if *b == from { to } else { *b }).collect(); + // SAFETY: We replaced ascii with ascii on valid utf8 strings. + unsafe { String::from_utf8_unchecked(result) } +} diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index ee878e879e98..0d1600a28aa7 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -53,7 +53,7 @@ use core::ops::AddAssign; #[cfg(not(no_global_oom_handling))] use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::{self, Range, RangeBounds}; -use core::str::pattern::Pattern; +use core::str::pattern::{Pattern, Utf8Pattern}; use core::{fmt, hash, ptr, slice}; #[cfg(not(no_global_oom_handling))] @@ -2424,6 +2424,11 @@ impl<'b> Pattern for &'b String { { self[..].strip_suffix_of(haystack) } + + #[inline] + fn as_utf8_pattern(&self) -> Option> { + Some(Utf8Pattern::StringPattern(self.as_bytes())) + } } macro_rules! impl_eq { diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index 9f1294d76064..eb60effe8138 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -160,6 +160,19 @@ pub trait Pattern: Sized { None } } + + /// Returns the pattern as utf-8 bytes if possible. + fn as_utf8_pattern(&self) -> Option>; +} +/// Result of calling [`Pattern::as_utf8_pattern()`]. +/// Can be used for inspecting the contents of a [`Pattern`] in cases +/// where the underlying representation can be represented as UTF-8. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum Utf8Pattern<'a> { + /// Type returned by String and str types. + StringPattern(&'a [u8]), + /// Type returned by char types. + CharPattern(char), } // Searcher @@ -599,6 +612,11 @@ impl Pattern for char { { self.encode_utf8(&mut [0u8; 4]).strip_suffix_of(haystack) } + + #[inline] + fn as_utf8_pattern(&self) -> Option> { + Some(Utf8Pattern::CharPattern(*self)) + } } ///////////////////////////////////////////////////////////////////////////// @@ -657,6 +675,11 @@ impl Pattern for MultiCharEqPattern { fn into_searcher(self, haystack: &str) -> MultiCharEqSearcher<'_, C> { MultiCharEqSearcher { haystack, char_eq: self.0, char_indices: haystack.char_indices() } } + + #[inline] + fn as_utf8_pattern(&self) -> Option> { + None + } } unsafe impl<'a, C: MultiCharEq> Searcher<'a> for MultiCharEqSearcher<'a, C> { @@ -747,6 +770,11 @@ macro_rules! pattern_methods { { ($pmap)(self).strip_suffix_of(haystack) } + + #[inline] + fn as_utf8_pattern(&self) -> Option> { + None + } }; } @@ -1022,6 +1050,11 @@ impl<'b> Pattern for &'b str { None } } + + #[inline] + fn as_utf8_pattern(&self) -> Option> { + Some(Utf8Pattern::StringPattern(self.as_bytes())) + } } ///////////////////////////////////////////////////////////////////////////// From a235cbd8ac347f323084c99d198f96d27269ec85 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Mon, 23 Sep 2024 11:58:28 -0700 Subject: [PATCH 016/246] `module_name_repetitions`: don't warn if the item is in a private module. Fixes . There is still a warning (as there should be) if the item is reexported by name, but not by glob; that would require further work to examine the names in the glob, and I haven't looked into that. Credit to @Centri3 for suggesting approximately this simple fix in . However, per later comment , I am not making it configuration-dependent, but *always* checking public items in public modules only. --- clippy_lints/src/item_name_repetitions.rs | 33 +++++++++++++++---- clippy_lints/src/literal_representation.rs | 1 - clippy_lints/src/macro_use.rs | 1 - clippy_lints/src/vec.rs | 1 - .../allowed_prefixes/item_name_repetitions.rs | 2 +- .../item_name_repetitions.rs | 2 +- tests/ui/module_name_repetitions.rs | 18 +++++++++- tests/ui/module_name_repetitions.stderr | 8 ++++- 8 files changed, 53 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs index 66a8a3167a4f..511317c8b43f 100644 --- a/clippy_lints/src/item_name_repetitions.rs +++ b/clippy_lints/src/item_name_repetitions.rs @@ -50,11 +50,28 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Detects type names that are prefixed or suffixed by the - /// containing module's name. + /// Detects public item names that are prefixed or suffixed by the + /// containing public module's name. /// /// ### Why is this bad? - /// It requires the user to type the module name twice. + /// It requires the user to type the module name twice in each usage, + /// especially if they choose to import the module rather than its contents. + /// + /// Lack of such repetition is also the style used in the Rust standard library; + /// e.g. `io::Error` and `fmt::Error` rather than `io::IoError` and `fmt::FmtError`; + /// and `array::from_ref` rather than `array::array_from_ref`. + /// + /// ### Known issues + /// Glob re-exports are ignored; e.g. this will not warn even though it should: + /// + /// ```no_run + /// pub mod foo { + /// mod iteration { + /// pub struct FooIter {} + /// } + /// pub use iteration::*; // creates the path `foo::FooIter` + /// } + /// ``` /// /// ### Example /// ```no_run @@ -389,12 +406,12 @@ impl LateLintPass<'_> for ItemNameRepetitions { let item_name = item.ident.name.as_str(); let item_camel = to_camel_case(item_name); if !item.span.from_expansion() && is_present_in_source(cx, item.span) { - if let [.., (mod_name, mod_camel, owner_id)] = &*self.modules { + if let [.., (mod_name, mod_camel, mod_owner_id)] = &*self.modules { // constants don't have surrounding modules if !mod_camel.is_empty() { if mod_name == &item.ident.name && let ItemKind::Mod(..) = item.kind - && (!self.allow_private_module_inception || cx.tcx.visibility(owner_id.def_id).is_public()) + && (!self.allow_private_module_inception || cx.tcx.visibility(mod_owner_id.def_id).is_public()) { span_lint( cx, @@ -403,9 +420,13 @@ impl LateLintPass<'_> for ItemNameRepetitions { "module has the same name as its containing module", ); } + // The `module_name_repetitions` lint should only trigger if the item has the module in its // name. Having the same name is accepted. - if cx.tcx.visibility(item.owner_id).is_public() && item_camel.len() > mod_camel.len() { + if cx.tcx.visibility(item.owner_id).is_public() + && cx.tcx.visibility(mod_owner_id.def_id).is_public() + && item_camel.len() > mod_camel.len() + { let matching = count_match_start(mod_camel, &item_camel); let rmatching = count_match_end(mod_camel, &item_camel); let nchars = mod_camel.chars().count(); diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 81f2a03fb55f..e2dcb20f906d 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -412,7 +412,6 @@ impl LiteralDigitGrouping { } } -#[expect(clippy::module_name_repetitions)] pub struct DecimalLiteralRepresentation { threshold: u64, } diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index bd6b3f1a47b1..d5d6226f0aaa 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -43,7 +43,6 @@ impl MacroRefData { } #[derive(Default)] -#[expect(clippy::module_name_repetitions)] pub struct MacroUseImports { /// the actual import path used and the span of the attribute above it. The value is /// the location, where the lint should be emitted. diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index ce4f41e854d5..0fdef51d6fc5 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -17,7 +17,6 @@ use rustc_middle::ty::layout::LayoutOf; use rustc_session::impl_lint_pass; use rustc_span::{DesugaringKind, Span, sym}; -#[expect(clippy::module_name_repetitions)] pub struct UselessVec { too_large_for_stack: u64, msrv: Msrv, diff --git a/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs b/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs index 4142ced5f6b5..2ae673a6def0 100644 --- a/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs +++ b/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs @@ -1,7 +1,7 @@ #![warn(clippy::module_name_repetitions)] #![allow(dead_code)] -mod foo { +pub mod foo { // #12544 - shouldn't warn if item name consists only of an allowed prefix and a module name. // In this test, allowed prefixes are configured to be ["bar"]. diff --git a/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs b/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs index b132305d01cf..dbd61992c0d6 100644 --- a/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs +++ b/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs @@ -1,7 +1,7 @@ #![warn(clippy::module_name_repetitions)] #![allow(dead_code)] -mod foo { +pub mod foo { // #12544 - shouldn't warn if item name consists only of an allowed prefix and a module name. // In this test, allowed prefixes are configured to be all of the default prefixes and ["bar"]. diff --git a/tests/ui/module_name_repetitions.rs b/tests/ui/module_name_repetitions.rs index b75ef87ab364..71d8ac7a1f0e 100644 --- a/tests/ui/module_name_repetitions.rs +++ b/tests/ui/module_name_repetitions.rs @@ -3,7 +3,7 @@ #![warn(clippy::module_name_repetitions)] #![allow(dead_code)] -mod foo { +pub mod foo { pub fn foo() {} pub fn foo_bar() {} //~^ ERROR: item name starts with its containing module's name @@ -20,6 +20,22 @@ mod foo { // Should not warn pub struct Foobar; + // #8524 - shouldn't warn when item is declared in a private module... + mod error { + pub struct Error; + pub struct FooError; + } + pub use error::Error; + // ... but should still warn when the item is reexported to create a *public* path with repetition. + pub use error::FooError; + //~^ ERROR: item name starts with its containing module's name + + // FIXME: This should also warn because it creates the public path `foo::FooIter`. + mod iter { + pub struct FooIter; + } + pub use iter::*; + // #12544 - shouldn't warn if item name consists only of an allowed prefix and a module name. pub fn to_foo() {} pub fn into_foo() {} diff --git a/tests/ui/module_name_repetitions.stderr b/tests/ui/module_name_repetitions.stderr index bffb08f6f879..8fd8b3948753 100644 --- a/tests/ui/module_name_repetitions.stderr +++ b/tests/ui/module_name_repetitions.stderr @@ -31,5 +31,11 @@ error: item name starts with its containing module's name LL | pub struct Foo7Bar; | ^^^^^^^ -error: aborting due to 5 previous errors +error: item name starts with its containing module's name + --> tests/ui/module_name_repetitions.rs:30:20 + | +LL | pub use error::FooError; + | ^^^^^^^^ + +error: aborting due to 6 previous errors From 4997ee7afcda865406352f755e9e3b44958560bd Mon Sep 17 00:00:00 2001 From: blyxyas Date: Fri, 6 Sep 2024 00:26:02 +0200 Subject: [PATCH 017/246] Turn declare_clippy_lint into a declarative macro --- clippy_lints/Cargo.toml | 1 - clippy_lints/src/declare_clippy_lint.rs | 162 +++++++++++++++++++++ clippy_lints/src/lib.rs | 6 +- clippy_utils/src/lib.rs | 2 +- declare_clippy_lint/Cargo.toml | 13 -- declare_clippy_lint/src/lib.rs | 182 ------------------------ tests/versioncheck.rs | 1 - 7 files changed, 167 insertions(+), 200 deletions(-) create mode 100644 clippy_lints/src/declare_clippy_lint.rs delete mode 100644 declare_clippy_lint/Cargo.toml delete mode 100644 declare_clippy_lint/src/lib.rs diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index d1188940b46a..55f1d31b4add 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -13,7 +13,6 @@ arrayvec = { version = "0.7", default-features = false } cargo_metadata = "0.18" clippy_config = { path = "../clippy_config" } clippy_utils = { path = "../clippy_utils" } -declare_clippy_lint = { path = "../declare_clippy_lint" } itertools = "0.12" quine-mc_cluskey = "0.2" regex-syntax = "0.8" diff --git a/clippy_lints/src/declare_clippy_lint.rs b/clippy_lints/src/declare_clippy_lint.rs new file mode 100644 index 000000000000..b1e39c70baa2 --- /dev/null +++ b/clippy_lints/src/declare_clippy_lint.rs @@ -0,0 +1,162 @@ +#[macro_export] +#[allow(clippy::crate_in_macro_def)] +macro_rules! declare_clippy_lint { + (@ + $(#[doc = $lit:literal])* + pub $lint_name:ident, + $category:ident, + $lintcategory:expr, + $desc:literal, + $version_expr:expr, + $version_lit:literal + ) => { + rustc_session::declare_tool_lint! { + $(#[doc = $lit])* + #[clippy::version = $version_lit] + pub clippy::$lint_name, + $category, + $desc, + report_in_external_macro:true + } + + pub(crate) static ${concat($lint_name, _INFO)}: &'static crate::LintInfo = &crate::LintInfo { + lint: &$lint_name, + category: $lintcategory, + explanation: concat!($($lit,"\n",)*), + location: concat!(file!(), "#L", line!()), + version: $version_expr + }; + }; + ( + $(#[doc = $lit:literal])* + #[clippy::version = $version:literal] + pub $lint_name:ident, + restriction, + $desc:literal + ) => { + declare_clippy_lint! {@ + $(#[doc = $lit])* + pub $lint_name, Allow, crate::LintCategory::Restriction, $desc, + Some($version), $version + } + }; + ( + $(#[doc = $lit:literal])* + #[clippy::version = $version:literal] + pub $lint_name:ident, + style, + $desc:literal + ) => { + declare_clippy_lint! {@ + $(#[doc = $lit])* + pub $lint_name, Warn, crate::LintCategory::Style, $desc, + Some($version), $version + + } + }; + ( + $(#[doc = $lit:literal])* + #[clippy::version = $version:literal] + pub $lint_name:ident, + correctness, + $desc:literal + ) => { + declare_clippy_lint! {@ + $(#[doc = $lit])* + pub $lint_name, Deny, crate::LintCategory::Correctness, $desc, + Some($version), $version + + } + }; + ( + $(#[doc = $lit:literal])* + #[clippy::version = $version:literal] + pub $lint_name:ident, + perf, + $desc:literal + ) => { + declare_clippy_lint! {@ + $(#[doc = $lit])* + pub $lint_name, Warn, crate::LintCategory::Perf, $desc, + Some($version), $version + } + }; + ( + $(#[doc = $lit:literal])* + #[clippy::version = $version:literal] + pub $lint_name:ident, + complexity, + $desc:literal + ) => { + declare_clippy_lint! {@ + $(#[doc = $lit])* + pub $lint_name, Warn, crate::LintCategory::Complexity, $desc, + Some($version), $version + } + }; + ( + $(#[doc = $lit:literal])* + #[clippy::version = $version:literal] + pub $lint_name:ident, + suspicious, + $desc:literal + ) => { + declare_clippy_lint! {@ + $(#[doc = $lit])* + pub $lint_name, Warn, crate::LintCategory::Suspicious, $desc, + Some($version), $version + } + }; + ( + $(#[doc = $lit:literal])* + #[clippy::version = $version:literal] + pub $lint_name:ident, + nursery, + $desc:literal + ) => { + declare_clippy_lint! {@ + $(#[doc = $lit])* + pub $lint_name, Allow, crate::LintCategory::Nursery, $desc, + Some($version), $version + } + }; + ( + $(#[doc = $lit:literal])* + #[clippy::version = $version:literal] + pub $lint_name:ident, + pedantic, + $desc:literal + ) => { + declare_clippy_lint! {@ + $(#[doc = $lit])* + pub $lint_name, Allow, crate::LintCategory::Pedantic, $desc, + Some($version), $version + } + }; + ( + $(#[doc = $lit:literal])* + #[clippy::version = $version:literal] + pub $lint_name:ident, + cargo, + $desc:literal + ) => { + declare_clippy_lint! {@ + $(#[doc = $lit])* + pub $lint_name, Allow, crate::LintCategory::Cargo, $desc, + Some($version), $version + } + }; + + ( + $(#[doc = $lit:literal])* + pub $lint_name:ident, + internal, + $desc:literal + ) => { + declare_clippy_lint! {@ + $(#[doc = $lit])* + pub $lint_name, Allow, crate::LintCategory::Internal, $desc, + None, "0.0.0" + } + }; +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1d41f568f378..efc9fe6f3157 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,6 +1,7 @@ #![feature(array_windows)] #![feature(binary_heap_into_iter_sorted)] #![feature(box_patterns)] +#![feature(macro_metavar_expr_concat)] #![feature(control_flow_enum)] #![feature(f128)] #![feature(f16)] @@ -59,9 +60,10 @@ extern crate rustc_trait_selection; extern crate thin_vec; #[macro_use] -extern crate clippy_utils; +mod declare_clippy_lint; + #[macro_use] -extern crate declare_clippy_lint; +extern crate clippy_utils; #[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))] mod utils; diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index a925549b0bff..bf7484f7902b 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -4,6 +4,7 @@ #![feature(f128)] #![feature(f16)] #![feature(if_let_guard)] +#![feature(macro_metavar_expr_concat)] #![feature(let_chains)] #![feature(never_type)] #![feature(rustc_private)] @@ -129,7 +130,6 @@ use crate::consts::{ConstEvalCtxt, Constant, mir_to_const}; use crate::higher::Range; use crate::ty::{adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type}; use crate::visitors::for_each_expr_without_closures; - use rustc_middle::hir::nested_filter; #[macro_export] diff --git a/declare_clippy_lint/Cargo.toml b/declare_clippy_lint/Cargo.toml deleted file mode 100644 index 67a1f7cc72c5..000000000000 --- a/declare_clippy_lint/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "declare_clippy_lint" -version = "0.1.83" -edition = "2021" -publish = false - -[lib] -proc-macro = true - -[dependencies] -itertools = "0.12" -quote = "1.0.21" -syn = "2.0" diff --git a/declare_clippy_lint/src/lib.rs b/declare_clippy_lint/src/lib.rs deleted file mode 100644 index fefc1a0a6c40..000000000000 --- a/declare_clippy_lint/src/lib.rs +++ /dev/null @@ -1,182 +0,0 @@ -#![feature(let_chains, proc_macro_span)] -// warn on lints, that are included in `rust-lang/rust`s bootstrap -#![warn(rust_2018_idioms, unused_lifetimes)] - -use proc_macro::TokenStream; -use quote::{format_ident, quote}; -use syn::parse::{Parse, ParseStream}; -use syn::{Attribute, Error, Expr, ExprLit, Ident, Lit, LitStr, Meta, Result, Token, parse_macro_input}; - -fn parse_attr(path: [&'static str; LEN], attr: &Attribute) -> Option { - if let Meta::NameValue(name_value) = &attr.meta { - let path_idents = name_value.path.segments.iter().map(|segment| &segment.ident); - - if itertools::equal(path_idents, path) - && let Expr::Lit(ExprLit { lit: Lit::Str(s), .. }) = &name_value.value - { - return Some(s.clone()); - } - } - - None -} - -struct ClippyLint { - attrs: Vec, - version: Option, - explanation: String, - name: Ident, - category: Ident, - description: LitStr, -} - -impl Parse for ClippyLint { - fn parse(input: ParseStream<'_>) -> Result { - let attrs = input.call(Attribute::parse_outer)?; - - let mut in_code = false; - let mut explanation = String::new(); - let mut version = None; - for attr in &attrs { - if let Some(lit) = parse_attr(["doc"], attr) { - let value = lit.value(); - let line = value.strip_prefix(' ').unwrap_or(&value); - - if let Some(lang) = line.strip_prefix("```") { - let tag = lang.split_once(',').map_or(lang, |(left, _)| left); - if !in_code && matches!(tag, "" | "rust" | "ignore" | "should_panic" | "no_run" | "compile_fail") { - explanation += "```rust\n"; - } else { - explanation += line; - explanation.push('\n'); - } - in_code = !in_code; - } else if !(in_code && line.starts_with("# ")) { - explanation += line; - explanation.push('\n'); - } - } else if let Some(lit) = parse_attr(["clippy", "version"], attr) { - if let Some(duplicate) = version.replace(lit) { - return Err(Error::new_spanned(duplicate, "duplicate clippy::version")); - } - } else { - return Err(Error::new_spanned(attr, "unexpected attribute")); - } - } - - input.parse::()?; - let name = input.parse()?; - input.parse::()?; - - let category = input.parse()?; - input.parse::()?; - - let description = input.parse()?; - - Ok(Self { - attrs, - version, - explanation, - name, - category, - description, - }) - } -} - -/// Macro used to declare a Clippy lint. -/// -/// Every lint declaration consists of 4 parts: -/// -/// 1. The documentation, which is used for the website and `cargo clippy --explain` -/// 2. The `LINT_NAME`. See [lint naming][lint_naming] on lint naming conventions. -/// 3. The `lint_level`, which is a mapping from *one* of our lint groups to `Allow`, `Warn` or -/// `Deny`. The lint level here has nothing to do with what lint groups the lint is a part of. -/// 4. The `description` that contains a short explanation on what's wrong with code where the lint -/// is triggered. -/// -/// Currently the categories `style`, `correctness`, `suspicious`, `complexity` and `perf` are -/// enabled by default. As said in the README.md of this repository, if the lint level mapping -/// changes, please update README.md. -/// -/// # Example -/// -/// ```ignore -/// use rustc_session::declare_tool_lint; -/// -/// declare_clippy_lint! { -/// /// ### What it does -/// /// Checks for ... (describe what the lint matches). -/// /// -/// /// ### Why is this bad? -/// /// Supply the reason for linting the code. -/// /// -/// /// ### Example -/// /// ```rust -/// /// Insert a short example of code that triggers the lint -/// /// ``` -/// /// -/// /// Use instead: -/// /// ```rust -/// /// Insert a short example of improved code that doesn't trigger the lint -/// /// ``` -/// #[clippy::version = "1.65.0"] -/// pub LINT_NAME, -/// pedantic, -/// "description" -/// } -/// ``` -/// [lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints -#[proc_macro] -pub fn declare_clippy_lint(input: TokenStream) -> TokenStream { - let ClippyLint { - attrs, - version, - explanation, - name, - category, - description, - } = parse_macro_input!(input as ClippyLint); - - let mut category = category.to_string(); - - let level = format_ident!("{}", match category.as_str() { - "correctness" => "Deny", - "style" | "suspicious" | "complexity" | "perf" => "Warn", - "pedantic" | "restriction" | "cargo" | "nursery" | "internal" => "Allow", - _ => panic!("unknown category {category}"), - },); - - let info_name = format_ident!("{name}_INFO"); - - (&mut category[0..1]).make_ascii_uppercase(); - let category_variant = format_ident!("{category}"); - - let name_span = name.span().unwrap(); - let location = format!("{}#L{}", name_span.source_file().path().display(), name_span.line()); - - let version = match version { - Some(version) => quote!(Some(#version)), - None => quote!(None), - }; - - let output = quote! { - rustc_session::declare_tool_lint! { - #(#attrs)* - pub clippy::#name, - #level, - #description, - report_in_external_macro: true - } - - pub(crate) static #info_name: &'static crate::LintInfo = &crate::LintInfo { - lint: &#name, - category: crate::LintCategory::#category_variant, - explanation: #explanation, - location: #location, - version: #version, - }; - }; - - TokenStream::from(output) -} diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index 683283339376..e29898f068d3 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -24,7 +24,6 @@ fn consistent_clippy_crate_versions() { let clippy_version = read_version("Cargo.toml"); let paths = [ - "declare_clippy_lint/Cargo.toml", "clippy_config/Cargo.toml", "clippy_lints/Cargo.toml", "clippy_utils/Cargo.toml", From 0735031be94cd4f6a102e83e72630fae04a18090 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Wed, 25 Sep 2024 13:42:21 +0200 Subject: [PATCH 018/246] Move tag removing to --explain --- clippy_lints/src/lib.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index efc9fe6f3157..e927d9a2d5bf 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -524,8 +524,28 @@ impl LintInfo { pub fn explain(name: &str) -> i32 { let target = format!("clippy::{}", name.to_ascii_uppercase()); + if let Some(info) = declared_lints::LINTS.iter().find(|info| info.lint.name == target) { - println!("{}", info.explanation); + // Remove tags and hidden code: + let mut explanation = String::with_capacity(128); + let mut in_code = false; + for line in info.explanation.lines().map(|line| line.trim()) { + if let Some(lang) = line.strip_prefix("```") { + let tag = lang.split_once(',').map_or(lang, |(left, _)| left); + if !in_code && matches!(tag, "" | "rust" | "ignore" | "should_panic" | "no_run" | "compile_fail") { + explanation += "```rust\n"; + } else { + explanation += line; + explanation.push('\n'); + } + in_code = !in_code; + } else if !(in_code && line.starts_with("# ")) { + explanation += line; + explanation.push('\n'); + } + } + + println!("{}", explanation); // Check if the lint has configuration let mut mdconf = get_configuration_metadata(); let name = name.to_ascii_lowercase(); From daf730caedb638696ee704e22942617cf5848e5f Mon Sep 17 00:00:00 2001 From: blyxyas Date: Thu, 26 Sep 2024 00:23:38 +0200 Subject: [PATCH 019/246] Add `sanitize_explanation` --- clippy_lints/src/lib.rs | 45 +++++++++++++++++++++++------------------ tests/compile-test.rs | 7 ++++++- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e927d9a2d5bf..0bfbb92dfda5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -522,30 +522,35 @@ impl LintInfo { } } +// Remove code tags and code behind '# 's, as they are not needed for the lint docs and --explain +pub fn sanitize_explanation(raw_docs: &str) -> String { + // Remove tags and hidden code: + let mut explanation = String::with_capacity(128); + let mut in_code = false; + for line in raw_docs.lines().map(|line| line.trim()) { + if let Some(lang) = line.strip_prefix("```") { + let tag = lang.split_once(',').map_or(lang, |(left, _)| left); + if !in_code && matches!(tag, "" | "rust" | "ignore" | "should_panic" | "no_run" | "compile_fail") { + explanation += "```rust\n"; + } else { + explanation += line; + explanation.push('\n'); + } + in_code = !in_code; + } else if !(in_code && line.starts_with("# ")) { + explanation += line; + explanation.push('\n'); + } + } + + explanation +} + pub fn explain(name: &str) -> i32 { let target = format!("clippy::{}", name.to_ascii_uppercase()); if let Some(info) = declared_lints::LINTS.iter().find(|info| info.lint.name == target) { - // Remove tags and hidden code: - let mut explanation = String::with_capacity(128); - let mut in_code = false; - for line in info.explanation.lines().map(|line| line.trim()) { - if let Some(lang) = line.strip_prefix("```") { - let tag = lang.split_once(',').map_or(lang, |(left, _)| left); - if !in_code && matches!(tag, "" | "rust" | "ignore" | "should_panic" | "no_run" | "compile_fail") { - explanation += "```rust\n"; - } else { - explanation += line; - explanation.push('\n'); - } - in_code = !in_code; - } else if !(in_code && line.starts_with("# ")) { - explanation += line; - explanation.push('\n'); - } - } - - println!("{}", explanation); + println!("{}", sanitize_explanation(info.explanation)); // Check if the lint has configuration let mut mdconf = get_configuration_metadata(); let name = name.to_ascii_lowercase(); diff --git a/tests/compile-test.rs b/tests/compile-test.rs index af2aa5192577..23dd41235bdb 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -5,9 +5,9 @@ use cargo_metadata::Message; use cargo_metadata::diagnostic::{Applicability, Diagnostic}; use clippy_config::ClippyConfiguration; -use clippy_lints::LintInfo; use clippy_lints::declared_lints::LINTS; use clippy_lints::deprecated_lints::{DEPRECATED, DEPRECATED_VERSION, RENAMED}; +use clippy_lints::{LintInfo, sanitize_explanation}; use serde::{Deserialize, Serialize}; use test_utils::IS_RUSTC_TEST_SUITE; use ui_test::custom_flags::Flag; @@ -444,7 +444,12 @@ impl DiagnosticCollector { iter::zip(DEPRECATED, DEPRECATED_VERSION) .map(|((lint, reason), version)| LintMetadata::new_deprecated(lint, reason, version)), ) + .map(|mut metadata| { + metadata.docs = sanitize_explanation(&metadata.docs); + metadata + }) .collect(); + metadata.sort_unstable_by(|a, b| a.id.cmp(&b.id)); let json = serde_json::to_string_pretty(&metadata).unwrap(); From d232d094b8e2776a6a1e88f478442fd98e2e70b4 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 18 Sep 2024 10:34:27 -0700 Subject: [PATCH 020/246] Remove the `control_flow_enum` feature from clippy --- clippy_lints/src/lib.rs | 1 - clippy_utils/src/lib.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1d41f568f378..54c3758459c7 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,7 +1,6 @@ #![feature(array_windows)] #![feature(binary_heap_into_iter_sorted)] #![feature(box_patterns)] -#![feature(control_flow_enum)] #![feature(f128)] #![feature(f16)] #![feature(if_let_guard)] diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 6dbc3334157e..6c0413c18086 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1,6 +1,5 @@ #![feature(array_chunks)] #![feature(box_patterns)] -#![feature(control_flow_enum)] #![feature(f128)] #![feature(f16)] #![feature(if_let_guard)] From c8725f70e77a08974a1d51bd360345a2ab7fabc6 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 26 Sep 2024 17:44:59 +0200 Subject: [PATCH 021/246] add proc macro check to needless_return --- clippy_lints/src/returns.rs | 2 +- tests/ui/needless_return.fixed | 8 ++ tests/ui/needless_return.rs | 8 ++ tests/ui/needless_return.stderr | 128 ++++++++++++++++---------------- 4 files changed, 81 insertions(+), 65 deletions(-) diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 3754fdddedfd..6754912f7656 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -407,7 +407,7 @@ fn check_final_expr<'tcx>( } } - if ret_span.from_expansion() { + if ret_span.from_expansion() || is_from_proc_macro(cx, expr) { return; } diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed index c5c570690b45..1507bc50a75e 100644 --- a/tests/ui/needless_return.fixed +++ b/tests/ui/needless_return.fixed @@ -1,3 +1,4 @@ +//@aux-build:proc_macros.rs #![feature(yeet_expr)] #![allow(unused)] #![allow( @@ -9,6 +10,9 @@ )] #![warn(clippy::needless_return)] +extern crate proc_macros; +use proc_macros::with_span; + use std::cell::RefCell; macro_rules! the_answer { @@ -359,4 +363,8 @@ fn issue12907() -> String { "".split("").next().unwrap().to_string() } +fn issue13458() { + with_span!(span return); +} + fn main() {} diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index 738611391dfd..c59bfced6d6f 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -1,3 +1,4 @@ +//@aux-build:proc_macros.rs #![feature(yeet_expr)] #![allow(unused)] #![allow( @@ -9,6 +10,9 @@ )] #![warn(clippy::needless_return)] +extern crate proc_macros; +use proc_macros::with_span; + use std::cell::RefCell; macro_rules! the_answer { @@ -369,4 +373,8 @@ fn issue12907() -> String { return "".split("").next().unwrap().to_string(); } +fn issue13458() { + with_span!(span return); +} + fn main() {} diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr index da0fa220d8c4..d3c2a6badc0f 100644 --- a/tests/ui/needless_return.stderr +++ b/tests/ui/needless_return.stderr @@ -1,5 +1,5 @@ error: unneeded `return` statement - --> tests/ui/needless_return.rs:25:5 + --> tests/ui/needless_return.rs:29:5 | LL | return true; | ^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:29:5 + --> tests/ui/needless_return.rs:33:5 | LL | return true; | ^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:34:5 + --> tests/ui/needless_return.rs:38:5 | LL | return true;;; | ^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:39:5 + --> tests/ui/needless_return.rs:43:5 | LL | return true;; ; ; | ^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:44:9 + --> tests/ui/needless_return.rs:48:9 | LL | return true; | ^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:46:9 + --> tests/ui/needless_return.rs:50:9 | LL | return false; | ^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + false | error: unneeded `return` statement - --> tests/ui/needless_return.rs:52:17 + --> tests/ui/needless_return.rs:56:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -84,7 +84,7 @@ LL | true => false, | ~~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:54:13 + --> tests/ui/needless_return.rs:58:13 | LL | return true; | ^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:61:9 + --> tests/ui/needless_return.rs:65:9 | LL | return true; | ^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:63:16 + --> tests/ui/needless_return.rs:67:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -119,7 +119,7 @@ LL | let _ = || true; | ~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:67:5 + --> tests/ui/needless_return.rs:71:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL + the_answer!() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:70:21 + --> tests/ui/needless_return.rs:74:21 | LL | fn test_void_fun() { | _____________________^ @@ -146,7 +146,7 @@ LL + fn test_void_fun() { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:75:11 + --> tests/ui/needless_return.rs:79:11 | LL | if b { | ___________^ @@ -161,7 +161,7 @@ LL + if b { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:77:13 + --> tests/ui/needless_return.rs:81:13 | LL | } else { | _____________^ @@ -176,7 +176,7 @@ LL + } else { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:85:14 + --> tests/ui/needless_return.rs:89:14 | LL | _ => return, | ^^^^^^ @@ -187,7 +187,7 @@ LL | _ => (), | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:93:24 + --> tests/ui/needless_return.rs:97:24 | LL | let _ = 42; | ________________________^ @@ -202,7 +202,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:96:14 + --> tests/ui/needless_return.rs:100:14 | LL | _ => return, | ^^^^^^ @@ -213,7 +213,7 @@ LL | _ => (), | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:109:9 + --> tests/ui/needless_return.rs:113:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL + String::from("test") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:111:9 + --> tests/ui/needless_return.rs:115:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -237,7 +237,7 @@ LL + String::new() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:133:32 + --> tests/ui/needless_return.rs:137:32 | LL | bar.unwrap_or_else(|_| return) | ^^^^^^ @@ -248,7 +248,7 @@ LL | bar.unwrap_or_else(|_| {}) | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:137:21 + --> tests/ui/needless_return.rs:141:21 | LL | let _ = || { | _____________________^ @@ -263,7 +263,7 @@ LL + let _ = || { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:140:20 + --> tests/ui/needless_return.rs:144:20 | LL | let _ = || return; | ^^^^^^ @@ -274,7 +274,7 @@ LL | let _ = || {}; | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:146:32 + --> tests/ui/needless_return.rs:150:32 | LL | res.unwrap_or_else(|_| return Foo) | ^^^^^^^^^^ @@ -284,18 +284,6 @@ help: remove `return` LL | res.unwrap_or_else(|_| Foo) | ~~~ -error: unneeded `return` statement - --> tests/ui/needless_return.rs:155:5 - | -LL | return true; - | ^^^^^^^^^^^ - | -help: remove `return` - | -LL - return true; -LL + true - | - error: unneeded `return` statement --> tests/ui/needless_return.rs:159:5 | @@ -309,7 +297,19 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:164:9 + --> tests/ui/needless_return.rs:163:5 + | +LL | return true; + | ^^^^^^^^^^^ + | +help: remove `return` + | +LL - return true; +LL + true + | + +error: unneeded `return` statement + --> tests/ui/needless_return.rs:168:9 | LL | return true; | ^^^^^^^^^^^ @@ -321,7 +321,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:166:9 + --> tests/ui/needless_return.rs:170:9 | LL | return false; | ^^^^^^^^^^^^ @@ -333,7 +333,7 @@ LL + false | error: unneeded `return` statement - --> tests/ui/needless_return.rs:172:17 + --> tests/ui/needless_return.rs:176:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -344,7 +344,7 @@ LL | true => false, | ~~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:174:13 + --> tests/ui/needless_return.rs:178:13 | LL | return true; | ^^^^^^^^^^^ @@ -356,7 +356,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:181:9 + --> tests/ui/needless_return.rs:185:9 | LL | return true; | ^^^^^^^^^^^ @@ -368,7 +368,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:183:16 + --> tests/ui/needless_return.rs:187:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -379,7 +379,7 @@ LL | let _ = || true; | ~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:187:5 + --> tests/ui/needless_return.rs:191:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -391,7 +391,7 @@ LL + the_answer!() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:190:33 + --> tests/ui/needless_return.rs:194:33 | LL | async fn async_test_void_fun() { | _________________________________^ @@ -406,7 +406,7 @@ LL + async fn async_test_void_fun() { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:195:11 + --> tests/ui/needless_return.rs:199:11 | LL | if b { | ___________^ @@ -421,7 +421,7 @@ LL + if b { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:197:13 + --> tests/ui/needless_return.rs:201:13 | LL | } else { | _____________^ @@ -436,7 +436,7 @@ LL + } else { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:205:14 + --> tests/ui/needless_return.rs:209:14 | LL | _ => return, | ^^^^^^ @@ -447,7 +447,7 @@ LL | _ => (), | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:218:9 + --> tests/ui/needless_return.rs:222:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -459,7 +459,7 @@ LL + String::from("test") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:220:9 + --> tests/ui/needless_return.rs:224:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -471,7 +471,7 @@ LL + String::new() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:236:5 + --> tests/ui/needless_return.rs:240:5 | LL | return format!("Hello {}", "world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -483,7 +483,7 @@ LL + format!("Hello {}", "world!") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:277:9 + --> tests/ui/needless_return.rs:281:9 | LL | return true; | ^^^^^^^^^^^ @@ -497,7 +497,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:279:9 + --> tests/ui/needless_return.rs:283:9 | LL | return false; | ^^^^^^^^^^^^ @@ -509,7 +509,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:286:13 + --> tests/ui/needless_return.rs:290:13 | LL | return 10; | ^^^^^^^^^ @@ -524,7 +524,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:289:13 + --> tests/ui/needless_return.rs:293:13 | LL | return 100; | ^^^^^^^^^^ @@ -537,7 +537,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:297:9 + --> tests/ui/needless_return.rs:301:9 | LL | return 0; | ^^^^^^^^ @@ -549,7 +549,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:304:13 + --> tests/ui/needless_return.rs:308:13 | LL | return *(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -564,7 +564,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:306:13 + --> tests/ui/needless_return.rs:310:13 | LL | return !*(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -577,7 +577,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:313:20 + --> tests/ui/needless_return.rs:317:20 | LL | let _ = 42; | ____________________^ @@ -594,7 +594,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:320:20 + --> tests/ui/needless_return.rs:324:20 | LL | let _ = 42; return; | ^^^^^^^ @@ -606,7 +606,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:332:9 + --> tests/ui/needless_return.rs:336:9 | LL | return Ok(format!("ok!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -618,7 +618,7 @@ LL + Ok(format!("ok!")) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:334:9 + --> tests/ui/needless_return.rs:338:9 | LL | return Err(format!("err!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -630,7 +630,7 @@ LL + Err(format!("err!")) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:340:9 + --> tests/ui/needless_return.rs:344:9 | LL | return if true { 1 } else { 2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -642,7 +642,7 @@ LL + if true { 1 } else { 2 } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:344:9 + --> tests/ui/needless_return.rs:348:9 | LL | return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -654,7 +654,7 @@ LL + (if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else | error: unneeded `return` statement - --> tests/ui/needless_return.rs:365:5 + --> tests/ui/needless_return.rs:369:5 | LL | return { "a".to_string() } + "b" + { "c" }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -666,7 +666,7 @@ LL + ({ "a".to_string() } + "b" + { "c" }) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:369:5 + --> tests/ui/needless_return.rs:373:5 | LL | return "".split("").next().unwrap().to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From b89c6204da4331d5d7c181e5c999cd34bfc54e10 Mon Sep 17 00:00:00 2001 From: Jonathan Birk Date: Thu, 26 Sep 2024 17:10:03 +0000 Subject: [PATCH 022/246] Make new information notes instead of labels --- compiler/rustc_hir_analysis/messages.ftl | 8 ++--- compiler/rustc_hir_analysis/src/errors.rs | 12 +++---- tests/ui/coherence/coherence-cow.re_a.stderr | 8 ++--- tests/ui/coherence/coherence-cow.re_b.stderr | 8 ++--- tests/ui/coherence/coherence-cow.re_c.stderr | 8 ++--- ...coherence-fundamental-trait-objects.stderr | 8 ++--- ...mpl-trait-for-marker-trait-negative.stderr | 8 ++--- ...mpl-trait-for-marker-trait-positive.stderr | 8 ++--- .../ui/coherence/coherence-impls-copy.stderr | 32 ++++++++--------- .../ui/coherence/coherence-impls-send.stderr | 24 ++++++------- .../ui/coherence/coherence-impls-sized.stderr | 24 ++++++------- .../coherence-negative-impls-copy-bad.stderr | 24 ++++++------- tests/ui/coherence/coherence-orphan.stderr | 18 +++++----- .../coherence-overlapping-pairs.stderr | 8 ++--- .../coherence-pair-covered-uncovered-1.stderr | 10 +++--- .../coherence-pair-covered-uncovered.stderr | 8 ++--- .../ui/coherence/coherence-vec-local-2.stderr | 8 ++--- tests/ui/coherence/coherence-vec-local.stderr | 8 ++--- .../coherence_local_err_struct.stderr | 8 ++--- .../coherence_local_err_tuple.stderr | 8 ++--- .../coherence/impl-foreign-for-foreign.stderr | 8 ++--- .../impl-foreign-for-foreign[foreign].stderr | 30 ++++++++-------- ...pl-foreign-for-fundamental[foreign].stderr | 20 +++++------ .../impl-foreign[foreign]-for-foreign.stderr | 10 +++--- ...n[fundemental[foreign]]-for-foreign.stderr | 36 +++++++++---------- .../impl[t]-foreign-for-foreign[t].stderr | 16 ++++----- tests/ui/dropck/drop-on-non-struct.stderr | 8 ++--- tests/ui/error-codes/E0117.stderr | 8 ++--- .../ui/error-codes/e0119/complex-impl.stderr | 8 ++--- .../issue-99572-impl-trait-on-pointer.stderr | 16 ++++----- tests/ui/issues/issue-67535.stderr | 30 ++++++++-------- .../const-and-non-const-impl.stderr | 10 +++--- .../coherence.classic.stderr | 8 ++--- .../coherence.next.stderr | 8 ++--- .../range_patterns_trait_impls2.stderr | 8 ++--- ...lt-trait-impl-cross-crate-coherence.stderr | 24 ++++++------- 36 files changed, 248 insertions(+), 248 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index c81f1c62be9c..444c4548ccbd 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -351,14 +351,14 @@ hir_analysis_only_current_traits_arbitrary = only traits defined in the current hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait -hir_analysis_only_current_traits_label = impl doesn't have any local type before any uncovered type parameters - -hir_analysis_only_current_traits_label_more_info = for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules - hir_analysis_only_current_traits_name = this is not defined in the current crate because {$name} are always foreign hir_analysis_only_current_traits_note = define and implement a trait or new type instead +hir_analysis_only_current_traits_note_more_info = for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + +hir_analysis_only_current_traits_note_uncovered = impl doesn't have any local type before any uncovered type parameters + hir_analysis_only_current_traits_opaque = type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate hir_analysis_only_current_traits_outside = only traits defined in the current crate can be implemented for types defined outside of the crate diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 9488f2f86cb3..25b79518dbb6 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1440,27 +1440,27 @@ pub enum OnlyCurrentTraits { #[diag(hir_analysis_only_current_traits_outside, code = E0117)] Outside { #[primary_span] - #[label(hir_analysis_only_current_traits_label)] - #[label(hir_analysis_only_current_traits_label_more_info)] span: Span, + #[note(hir_analysis_only_current_traits_note_uncovered)] + #[note(hir_analysis_only_current_traits_note_more_info)] #[note(hir_analysis_only_current_traits_note)] note: (), }, #[diag(hir_analysis_only_current_traits_primitive, code = E0117)] Primitive { #[primary_span] - #[label(hir_analysis_only_current_traits_label)] - #[label(hir_analysis_only_current_traits_label_more_info)] span: Span, + #[note(hir_analysis_only_current_traits_note_uncovered)] + #[note(hir_analysis_only_current_traits_note_more_info)] #[note(hir_analysis_only_current_traits_note)] note: (), }, #[diag(hir_analysis_only_current_traits_arbitrary, code = E0117)] Arbitrary { #[primary_span] - #[label(hir_analysis_only_current_traits_label)] - #[label(hir_analysis_only_current_traits_label_more_info)] span: Span, + #[note(hir_analysis_only_current_traits_note_uncovered)] + #[note(hir_analysis_only_current_traits_note_more_info)] #[note(hir_analysis_only_current_traits_note)] note: (), }, diff --git a/tests/ui/coherence/coherence-cow.re_a.stderr b/tests/ui/coherence/coherence-cow.re_a.stderr index b4331fc475b1..67de3629491d 100644 --- a/tests/ui/coherence/coherence-cow.re_a.stderr +++ b/tests/ui/coherence/coherence-cow.re_a.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | LL | impl Remote for Pair> { } | ^^^^^^^^^^^^^^^^^^^---------------- - | | | - | | `Pair` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `Pair` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-cow.re_b.stderr b/tests/ui/coherence/coherence-cow.re_b.stderr index b401d9645988..360900cc7fff 100644 --- a/tests/ui/coherence/coherence-cow.re_b.stderr +++ b/tests/ui/coherence/coherence-cow.re_b.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | LL | impl Remote for Pair,T> { } | ^^^^^^^^^^^^^^^^^^^---------------- - | | | - | | `Pair` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `Pair` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-cow.re_c.stderr b/tests/ui/coherence/coherence-cow.re_c.stderr index d95beee8139e..73f2aa196fd4 100644 --- a/tests/ui/coherence/coherence-cow.re_c.stderr +++ b/tests/ui/coherence/coherence-cow.re_c.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | LL | impl Remote for Pair,U> { } | ^^^^^^^^^^^^^^^^^^^^^---------------- - | | | - | | `Pair` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `Pair` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-fundamental-trait-objects.stderr b/tests/ui/coherence/coherence-fundamental-trait-objects.stderr index 4933fb155f73..ca43d70e0b1b 100644 --- a/tests/ui/coherence/coherence-fundamental-trait-objects.stderr +++ b/tests/ui/coherence/coherence-fundamental-trait-objects.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl Misc for dyn Fundamental {} | ^^^^^^^^^^^^^^---------------------- - | | | - | | `dyn Fundamental` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `dyn Fundamental` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr index c8b215037b9e..77d1bdee5acf 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr @@ -39,11 +39,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl !Send for dyn Marker2 {} | ^^^^^^^^^^^^^^^----------- - | | | - | | `dyn Marker2` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `dyn Marker2` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)` diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr index 02107453a9ff..f38aeaed0aac 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr @@ -39,11 +39,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | unsafe impl Send for dyn Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^----------- - | | | - | | `dyn Marker2` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `dyn Marker2` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)` diff --git a/tests/ui/coherence/coherence-impls-copy.stderr b/tests/ui/coherence/coherence-impls-copy.stderr index 2de854ed5843..79fe044c4cf4 100644 --- a/tests/ui/coherence/coherence-impls-copy.stderr +++ b/tests/ui/coherence/coherence-impls-copy.stderr @@ -13,11 +13,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl Copy for &'static [NotSync] {} | ^^^^^^^^^^^^^^------------------ - | | | - | | this is not defined in the current crate because slices are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | this is not defined in the current crate because slices are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for primitive types @@ -25,11 +25,11 @@ error[E0117]: only traits defined in the current crate can be implemented for pr | LL | impl Copy for i32 {} | ^^^^^^^^^^^^^^--- - | | | - | | `i32` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `i32` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0206]: the trait `Copy` cannot be implemented for this type @@ -43,11 +43,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl Copy for (MyType, MyType) {} | ^^^^^^^^^^^^^^---------------- - | | | - | | this is not defined in the current crate because tuples are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | this is not defined in the current crate because tuples are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0206]: the trait `Copy` cannot be implemented for this type @@ -61,11 +61,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl Copy for [MyType] {} | ^^^^^^^^^^^^^^-------- - | | | - | | this is not defined in the current crate because slices are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | this is not defined in the current crate because slices are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0206]: the trait `Copy` cannot be implemented for this type diff --git a/tests/ui/coherence/coherence-impls-send.stderr b/tests/ui/coherence/coherence-impls-send.stderr index a41e9d620e01..78e89eb55409 100644 --- a/tests/ui/coherence/coherence-impls-send.stderr +++ b/tests/ui/coherence/coherence-impls-send.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | unsafe impl Send for &'static [NotSync] {} | ^^^^^^^^^^^^^^^^^^^^^------------------ - | | | - | | this is not defined in the current crate because slices are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | this is not defined in the current crate because slices are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types @@ -15,11 +15,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | unsafe impl Send for (MyType, MyType) {} | ^^^^^^^^^^^^^^^^^^^^^---------------- - | | | - | | this is not defined in the current crate because tuples are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | this is not defined in the current crate because tuples are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `&'static NotSync` @@ -33,11 +33,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | unsafe impl Send for [MyType] {} | ^^^^^^^^^^^^^^^^^^^^^-------- - | | | - | | this is not defined in the current crate because slices are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | this is not defined in the current crate because slices are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 4 previous errors diff --git a/tests/ui/coherence/coherence-impls-sized.stderr b/tests/ui/coherence/coherence-impls-sized.stderr index 080d19e075b5..3201f1b25def 100644 --- a/tests/ui/coherence/coherence-impls-sized.stderr +++ b/tests/ui/coherence/coherence-impls-sized.stderr @@ -21,11 +21,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl Sized for (MyType, MyType) {} | ^^^^^^^^^^^^^^^---------------- - | | | - | | this is not defined in the current crate because tuples are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | this is not defined in the current crate because tuples are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0322]: explicit impls for the `Sized` trait are not permitted @@ -45,11 +45,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl Sized for [MyType] {} | ^^^^^^^^^^^^^^^-------- - | | | - | | this is not defined in the current crate because slices are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | this is not defined in the current crate because slices are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0322]: explicit impls for the `Sized` trait are not permitted @@ -63,11 +63,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl Sized for &'static [NotSync] {} | ^^^^^^^^^^^^^^^------------------ - | | | - | | this is not defined in the current crate because slices are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | this is not defined in the current crate because slices are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 9 previous errors diff --git a/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr b/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr index 85937c5f02a8..074cd87ba924 100644 --- a/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr +++ b/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl !Copy for str {} | ^^^^^^^^^^^^^^^--- - | | | - | | `str` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `str` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types @@ -15,11 +15,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl !Copy for fn() {} | ^^^^^^^^^^^^^^^---- - | | | - | | `fn()` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `fn()` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types @@ -27,11 +27,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl !Copy for () {} | ^^^^^^^^^^^^^^^-- - | | | - | | this is not defined in the current crate because tuples are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | this is not defined in the current crate because tuples are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 3 previous errors diff --git a/tests/ui/coherence/coherence-orphan.stderr b/tests/ui/coherence/coherence-orphan.stderr index c10ed013ef25..dcf423e24eed 100644 --- a/tests/ui/coherence/coherence-orphan.stderr +++ b/tests/ui/coherence/coherence-orphan.stderr @@ -3,12 +3,12 @@ error[E0117]: only traits defined in the current crate can be implemented for pr | LL | impl TheTrait for isize {} | ^^^^^---------------^^^^^----- - | | | | - | | | `isize` is not defined in the current crate - | | `usize` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | | + | | `isize` is not defined in the current crate + | `usize` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate @@ -16,11 +16,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | LL | impl !Send for Vec {} | ^^^^^^^^^^^^^^^---------- - | | | - | | `Vec` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `Vec` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 2 previous errors diff --git a/tests/ui/coherence/coherence-overlapping-pairs.stderr b/tests/ui/coherence/coherence-overlapping-pairs.stderr index 448e7b9d5ef1..6e7a90ac369c 100644 --- a/tests/ui/coherence/coherence-overlapping-pairs.stderr +++ b/tests/ui/coherence/coherence-overlapping-pairs.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | LL | impl Remote for lib::Pair { } | ^^^^^^^^^^^^^^^^^^^---------------- - | | | - | | `Pair` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `Pair` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr b/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr index 2e616fefe0ee..d7890d156cae 100644 --- a/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr +++ b/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr @@ -3,12 +3,12 @@ error[E0117]: only traits defined in the current crate can be implemented for pr | LL | impl Remote1>> for i32 { } | ^^^^^^^^^^^--------------------------^^^^^--- - | | | | - | | | `i32` is not defined in the current crate - | | `Pair` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | | + | | `i32` is not defined in the current crate + | `Pair` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-pair-covered-uncovered.stderr b/tests/ui/coherence/coherence-pair-covered-uncovered.stderr index 71a1e4c7ac3f..fa3d170f81d4 100644 --- a/tests/ui/coherence/coherence-pair-covered-uncovered.stderr +++ b/tests/ui/coherence/coherence-pair-covered-uncovered.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | LL | impl Remote for Pair> { } | ^^^^^^^^^^^^^^^^^^^^^---------------- - | | | - | | `Pair` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `Pair` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-vec-local-2.stderr b/tests/ui/coherence/coherence-vec-local-2.stderr index 50788e4a990e..cb12275cf01c 100644 --- a/tests/ui/coherence/coherence-vec-local-2.stderr +++ b/tests/ui/coherence/coherence-vec-local-2.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | LL | impl Remote for Vec> { } | ^^^^^^^^^^^^^^^^^^^------------- - | | | - | | `Vec` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `Vec` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-vec-local.stderr b/tests/ui/coherence/coherence-vec-local.stderr index cd102fa1c6d1..9278b9458d56 100644 --- a/tests/ui/coherence/coherence-vec-local.stderr +++ b/tests/ui/coherence/coherence-vec-local.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | LL | impl Remote for Vec { } | ^^^^^^^^^^^^^^^^---------- - | | | - | | `Vec` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `Vec` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence_local_err_struct.stderr b/tests/ui/coherence/coherence_local_err_struct.stderr index 97a26b54a1be..280dd57bd42d 100644 --- a/tests/ui/coherence/coherence_local_err_struct.stderr +++ b/tests/ui/coherence/coherence_local_err_struct.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | LL | impl lib::MyCopy for lib::MyStruct { } | ^^^^^^^^^^^^^^^^^^^^^--------------------- - | | | - | | `MyStruct` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `MyStruct` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence_local_err_tuple.stderr b/tests/ui/coherence/coherence_local_err_tuple.stderr index cdd73be86bfa..d07adab0014e 100644 --- a/tests/ui/coherence/coherence_local_err_tuple.stderr +++ b/tests/ui/coherence/coherence_local_err_tuple.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl lib::MyCopy for (MyType,) { } | ^^^^^^^^^^^^^^^^^^^^^--------- - | | | - | | this is not defined in the current crate because tuples are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | this is not defined in the current crate because tuples are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/coherence/impl-foreign-for-foreign.stderr b/tests/ui/coherence/impl-foreign-for-foreign.stderr index 0f8af5ef0280..4ff965290c88 100644 --- a/tests/ui/coherence/impl-foreign-for-foreign.stderr +++ b/tests/ui/coherence/impl-foreign-for-foreign.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for pr | LL | impl Remote for i32 { | ^^^^^^^^^^^^^^^^--- - | | | - | | `i32` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `i32` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr b/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr index ae1807f6dd05..ce5376f98cb7 100644 --- a/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr +++ b/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr @@ -3,12 +3,12 @@ error[E0117]: only traits defined in the current crate can be implemented for pr | LL | impl Remote1> for i32 { | ^^^^^----------------^^^^^--- - | | | | - | | | `i32` is not defined in the current crate - | | `Rc` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | | + | | `i32` is not defined in the current crate + | `Rc` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for primitive types @@ -16,12 +16,12 @@ error[E0117]: only traits defined in the current crate can be implemented for pr | LL | impl Remote1> for f64 { | ^^^^^------------------^^^^^--- - | | | | - | | | `f64` is not defined in the current crate - | | `Rc` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | | + | | `f64` is not defined in the current crate + | `Rc` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for primitive types @@ -29,12 +29,12 @@ error[E0117]: only traits defined in the current crate can be implemented for pr | LL | impl Remote1> for f32 { | ^^^^^^^^--------------^^^^^--- - | | | | - | | | `f32` is not defined in the current crate - | | `Rc` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | | + | | `f32` is not defined in the current crate + | `Rc` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 3 previous errors diff --git a/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr b/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr index a3522a75c86c..596f8436567a 100644 --- a/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr +++ b/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr @@ -3,12 +3,12 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | LL | impl Remote for Box { | ^^^^^------^^^^^-------- - | | | | - | | | `i32` is not defined in the current crate - | | `std::alloc::Global` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | | + | | `i32` is not defined in the current crate + | `std::alloc::Global` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate @@ -16,12 +16,12 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | LL | impl Remote for Box> { | ^^^^^^^^------^^^^^---------- - | | | | - | | | `Rc` is not defined in the current crate - | | `std::alloc::Global` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | | + | | `Rc` is not defined in the current crate + | `std::alloc::Global` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 2 previous errors diff --git a/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr b/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr index bf22e73dd09d..d9dd2b8a8c62 100644 --- a/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr +++ b/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr @@ -3,12 +3,12 @@ error[E0117]: only traits defined in the current crate can be implemented for pr | LL | impl Remote1 for f64 { | ^^^^^------------^^^^^--- - | | | | - | | | `f64` is not defined in the current crate - | | `u32` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | | + | | `f64` is not defined in the current crate + | `u32` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr b/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr index 2ab5cca7983c..91f1886142cf 100644 --- a/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr +++ b/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr @@ -3,13 +3,13 @@ error[E0117]: only traits defined in the current crate can be implemented for pr | LL | impl Remote1> for i32 { | ^^^^^--------------------^^^^^--- - | | | | - | | | `i32` is not defined in the current crate - | | `String` is not defined in the current crate - | | `std::alloc::Global` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | | + | | `i32` is not defined in the current crate + | `String` is not defined in the current crate + | `std::alloc::Global` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for primitive types @@ -17,13 +17,13 @@ error[E0117]: only traits defined in the current crate can be implemented for pr | LL | impl Remote1>> for f64 { | ^^^^^---------------------^^^^^--- - | | | | - | | | `f64` is not defined in the current crate - | | `Rc` is not defined in the current crate - | | `std::alloc::Global` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | | + | | `f64` is not defined in the current crate + | `Rc` is not defined in the current crate + | `std::alloc::Global` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for primitive types @@ -31,13 +31,13 @@ error[E0117]: only traits defined in the current crate can be implemented for pr | LL | impl Remote1>> for f32 { | ^^^^^^^^-------------------^^^^^--- - | | | | - | | | `f32` is not defined in the current crate - | | `Rc` is not defined in the current crate - | | `std::alloc::Global` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | | + | | `f32` is not defined in the current crate + | `Rc` is not defined in the current crate + | `std::alloc::Global` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 3 previous errors diff --git a/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr b/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr index ca9a7d5cd930..306a5d1610d7 100644 --- a/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr +++ b/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | LL | impl Remote for Rc { | ^^^^^^^^^^^^^^^^--------- - | | | - | | `Rc` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `Rc` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate @@ -15,11 +15,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | LL | impl Remote for Arc { | ^^^^^^^^^^^^^^^^^^^------ - | | | - | | `Arc` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `Arc` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 2 previous errors diff --git a/tests/ui/dropck/drop-on-non-struct.stderr b/tests/ui/dropck/drop-on-non-struct.stderr index 78b7212b6d9f..9495642e45e4 100644 --- a/tests/ui/dropck/drop-on-non-struct.stderr +++ b/tests/ui/dropck/drop-on-non-struct.stderr @@ -9,11 +9,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl<'a> Drop for &'a mut isize { | ^^^^^^^^^^^^^^^^^^------------- - | | | - | | `isize` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `isize` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions diff --git a/tests/ui/error-codes/E0117.stderr b/tests/ui/error-codes/E0117.stderr index 2bfa78d1954d..f6e80e593044 100644 --- a/tests/ui/error-codes/E0117.stderr +++ b/tests/ui/error-codes/E0117.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for pr | LL | impl Drop for u32 {} | ^^^^^^^^^^^^^^--- - | | | - | | `u32` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `u32` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions diff --git a/tests/ui/error-codes/e0119/complex-impl.stderr b/tests/ui/error-codes/e0119/complex-impl.stderr index 36618cee0e83..b7e434c4afe3 100644 --- a/tests/ui/error-codes/e0119/complex-impl.stderr +++ b/tests/ui/error-codes/e0119/complex-impl.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl External for (Q, R) {} | ^^^^^^^^^^^^^^^^^^^^^------ - | | | - | | this is not defined in the current crate because tuples are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | this is not defined in the current crate because tuples are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr b/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr index 214618d6636f..bd40b059e580 100644 --- a/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr +++ b/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl fmt::Display for *mut LocalType { | ^^^^^^^^^^^^^^^^^^^^^^-------------- - | | | - | | `*mut LocalType` is not defined in the current crate because raw pointers are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `*mut LocalType` is not defined in the current crate because raw pointers are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead help: consider introducing a new wrapper type | @@ -21,11 +21,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl marker::Copy for *mut T { | ^^^^^^^^^^^^^^^^^^^^^^^^^------ - | | | - | | `*mut T` is not defined in the current crate because raw pointers are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `*mut T` is not defined in the current crate because raw pointers are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-67535.stderr b/tests/ui/issues/issue-67535.stderr index a953a9152144..2afa2199a6af 100644 --- a/tests/ui/issues/issue-67535.stderr +++ b/tests/ui/issues/issue-67535.stderr @@ -3,12 +3,12 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl std::ops::AddAssign for () { | ^^^^^-------------------^^^^^-- - | | | | - | | | this is not defined in the current crate because tuples are always foreign - | | this is not defined in the current crate because this is a foreign trait - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | | + | | this is not defined in the current crate because tuples are always foreign + | this is not defined in the current crate because this is a foreign trait | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types @@ -16,12 +16,12 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl std::ops::AddAssign for [(); 1] { | ^^^^^-------------------^^^^^------- - | | | | - | | | this is not defined in the current crate because arrays are always foreign - | | this is not defined in the current crate because this is a foreign trait - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | | + | | this is not defined in the current crate because arrays are always foreign + | this is not defined in the current crate because this is a foreign trait | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types @@ -29,12 +29,12 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl std::ops::AddAssign for &[u8] { | ^^^^^-------------------^^^^^----- - | | | | - | | | this is not defined in the current crate because slices are always foreign - | | this is not defined in the current crate because this is a foreign trait - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | | + | | this is not defined in the current crate because slices are always foreign + | this is not defined in the current crate because this is a foreign trait | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 3 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr index 4dff35c46e84..cf7af41cd4e4 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr @@ -30,12 +30,12 @@ error[E0117]: only traits defined in the current crate can be implemented for pr | LL | impl const std::ops::Add for i32 { | ^^^^^^^^^^^-------------^^^^^--- - | | | | - | | | `i32` is not defined in the current crate - | | `i32` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | | + | | `i32` is not defined in the current crate + | `i32` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 4 previous errors diff --git a/tests/ui/type-alias-impl-trait/coherence.classic.stderr b/tests/ui/type-alias-impl-trait/coherence.classic.stderr index 4cd87253b307..98badeef382d 100644 --- a/tests/ui/type-alias-impl-trait/coherence.classic.stderr +++ b/tests/ui/type-alias-impl-trait/coherence.classic.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------- - | | | - | | type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/coherence.next.stderr b/tests/ui/type-alias-impl-trait/coherence.next.stderr index 886b667b8c8b..8d7183831109 100644 --- a/tests/ui/type-alias-impl-trait/coherence.next.stderr +++ b/tests/ui/type-alias-impl-trait/coherence.next.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------- - | | | - | | `AliasOfForeignType<()>` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `AliasOfForeignType<()>` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr b/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr index 2d3f8403315d..df56db031ed1 100644 --- a/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr +++ b/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl Eq for Y {} | ^^^^^^^^^^^^- - | | | - | | `(u32) is 1..=` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `(u32) is 1..=` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 1 previous error diff --git a/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr b/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr index 8ee6846eac28..c7d714dcb1ad 100644 --- a/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr +++ b/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr @@ -3,11 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl DefaultedTrait for (A,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^---- - | | | - | | this is not defined in the current crate because tuples are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | this is not defined in the current crate because tuples are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types @@ -15,11 +15,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | LL | impl !DefaultedTrait for (B,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^---- - | | | - | | this is not defined in the current crate because tuples are always foreign - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | this is not defined in the current crate because tuples are always foreign | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0321]: cross-crate traits with a default impl, like `DefaultedTrait`, can only be implemented for a struct/enum type defined in the current crate @@ -33,11 +33,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | LL | impl DefaultedTrait for lib::Something {} | ^^^^^^^^^^^^^^^^^^^^^^^^----------------- - | | | - | | `Something` is not defined in the current crate - | impl doesn't have any local type before any uncovered type parameters - | for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + | | + | `Something` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error: aborting due to 4 previous errors From 1598aa4f83d249bbef1c8593274eb09b1d58f6ba Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sun, 25 Aug 2024 16:54:46 +0100 Subject: [PATCH 023/246] Make destructors on `extern "C"` frames to be executed --- .../src/abort_unwinding_calls.rs | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index d889bc90c9d7..84c8a91b0825 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -51,11 +51,20 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { // This will filter to functions with `extern "C-unwind"` ABIs, for // example. for block in body.basic_blocks.as_mut() { + let Some(terminator) = &mut block.terminator else { continue }; + let span = terminator.source_info.span; + + // If we see an `UnwindResume` terminator inside a function that cannot unwind, we need + // to replace it with `UnwindTerminate`. + if let TerminatorKind::UnwindResume = &terminator.kind + && !body_can_unwind + { + terminator.kind = TerminatorKind::UnwindTerminate(UnwindTerminateReason::Abi); + } + if block.is_cleanup { continue; } - let Some(terminator) = &block.terminator else { continue }; - let span = terminator.source_info.span; let call_can_unwind = match &terminator.kind { TerminatorKind::Call { func, .. } => { @@ -87,14 +96,18 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { if !call_can_unwind { // If this function call can't unwind, then there's no need for it // to have a landing pad. This means that we can remove any cleanup - // registered for it. + // registered for it (and turn it into `UnwindAction::Unreachable`). let cleanup = block.terminator_mut().unwind_mut().unwrap(); *cleanup = UnwindAction::Unreachable; - } else if !body_can_unwind { + } else if !body_can_unwind + && matches!(terminator.unwind(), Some(UnwindAction::Continue)) + { // Otherwise if this function can unwind, then if the outer function // can also unwind there's nothing to do. If the outer function - // can't unwind, however, we need to change the landing pad for this - // function call to one that aborts. + // can't unwind, however, we need to ensure that any `UnwindAction::Continue` + // is replaced with terminate. For those with `UnwindAction::Cleanup`, + // cleanup will still happen, and terminate will happen afterwards handled by + // the `UnwindResume` -> `UnwindTerminate` terminator replacement. let cleanup = block.terminator_mut().unwind_mut().unwrap(); *cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi); } From 8f63b6a7454c05f512515946a0e9ca7e3b904144 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 28 Aug 2024 18:00:21 +0100 Subject: [PATCH 024/246] Add and adapt tests --- ...c_abort.main.AbortUnwindingCalls.after.mir | 6 +++- tests/mir-opt/asm_unwind_panic_abort.rs | 4 ++- tests/mir-opt/c_unwind_terminate.rs | 25 +++++++++++++ ...rminate.test.AbortUnwindingCalls.after.mir | 36 +++++++++++++++++++ tests/ui/panics/panic-in-ffi.rs | 9 +++++ tests/ui/panics/panic-in-ffi.run.stderr | 3 +- 6 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 tests/mir-opt/c_unwind_terminate.rs create mode 100644 tests/mir-opt/c_unwind_terminate.test.AbortUnwindingCalls.after.mir diff --git a/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir b/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir index 005b3ee3b249..0ea9937e2a24 100644 --- a/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir +++ b/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir @@ -7,7 +7,7 @@ fn main() -> () { bb0: { StorageLive(_1); _1 = const (); - asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind terminate(abi)]; + asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind: bb2]; } bb1: { @@ -15,4 +15,8 @@ fn main() -> () { _0 = const (); return; } + + bb2 (cleanup): { + terminate(abi); + } } diff --git a/tests/mir-opt/asm_unwind_panic_abort.rs b/tests/mir-opt/asm_unwind_panic_abort.rs index fff609421244..4ae76cbd16fe 100644 --- a/tests/mir-opt/asm_unwind_panic_abort.rs +++ b/tests/mir-opt/asm_unwind_panic_abort.rs @@ -10,7 +10,9 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: asm!( - // CHECK-SAME: unwind terminate(abi) + // CHECK-SAME: unwind: [[unwind:bb.*]]] + // CHECK: [[unwind]] (cleanup) + // CHECK-NEXT: terminate(abi) unsafe { std::arch::asm!("", options(may_unwind)); } diff --git a/tests/mir-opt/c_unwind_terminate.rs b/tests/mir-opt/c_unwind_terminate.rs new file mode 100644 index 000000000000..64524e74d28e --- /dev/null +++ b/tests/mir-opt/c_unwind_terminate.rs @@ -0,0 +1,25 @@ +//@ needs-unwind + +struct Noise; +impl Drop for Noise { + fn drop(&mut self) { + eprintln!("Noisy Drop"); + } +} + +fn panic() { + panic!(); +} + +// EMIT_MIR c_unwind_terminate.test.AbortUnwindingCalls.after.mir +extern "C" fn test() { + // CHECK-LABEL: fn test( + // CHECK: drop + // CHECK-SAME: unwind: [[unwind:bb.*]]] + // CHECK: [[unwind]] (cleanup) + // CHECK-NEXT: terminate(abi) + let _val = Noise; + panic(); +} + +fn main() {} diff --git a/tests/mir-opt/c_unwind_terminate.test.AbortUnwindingCalls.after.mir b/tests/mir-opt/c_unwind_terminate.test.AbortUnwindingCalls.after.mir new file mode 100644 index 000000000000..dd792d743cc5 --- /dev/null +++ b/tests/mir-opt/c_unwind_terminate.test.AbortUnwindingCalls.after.mir @@ -0,0 +1,36 @@ +// MIR for `test` after AbortUnwindingCalls + +fn test() -> () { + let mut _0: (); + let _1: Noise; + let _2: (); + scope 1 { + debug _val => _1; + } + + bb0: { + StorageLive(_1); + _1 = Noise; + StorageLive(_2); + _2 = panic() -> [return: bb1, unwind: bb3]; + } + + bb1: { + StorageDead(_2); + _0 = const (); + drop(_1) -> [return: bb2, unwind: bb4]; + } + + bb2: { + StorageDead(_1); + return; + } + + bb3 (cleanup): { + drop(_1) -> [return: bb4, unwind terminate(cleanup)]; + } + + bb4 (cleanup): { + terminate(abi); + } +} diff --git a/tests/ui/panics/panic-in-ffi.rs b/tests/ui/panics/panic-in-ffi.rs index 88f45f9a871d..c0ae1899f4c2 100644 --- a/tests/ui/panics/panic-in-ffi.rs +++ b/tests/ui/panics/panic-in-ffi.rs @@ -2,13 +2,22 @@ //@ exec-env:RUST_BACKTRACE=0 //@ check-run-results //@ error-pattern: panic in a function that cannot unwind +//@ error-pattern: Noisy Drop //@ normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" //@ normalize-stderr-test: "\n +at [^\n]+" -> "" //@ normalize-stderr-test: "(core/src/panicking\.rs):[0-9]+:[0-9]+" -> "$1:$$LINE:$$COL" //@ needs-unwind //@ ignore-emscripten "RuntimeError" junk in output +struct Noise; +impl Drop for Noise { + fn drop(&mut self) { + eprintln!("Noisy Drop"); + } +} + extern "C" fn panic_in_ffi() { + let _val = Noise; panic!("Test"); } diff --git a/tests/ui/panics/panic-in-ffi.run.stderr b/tests/ui/panics/panic-in-ffi.run.stderr index fc70847ad9a3..58f5187f0daf 100644 --- a/tests/ui/panics/panic-in-ffi.run.stderr +++ b/tests/ui/panics/panic-in-ffi.run.stderr @@ -1,6 +1,7 @@ -thread 'main' panicked at $DIR/panic-in-ffi.rs:12:5: +thread 'main' panicked at $DIR/panic-in-ffi.rs:21:5: Test note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +Noisy Drop thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: panic in a function that cannot unwind stack backtrace: From 55834a362c1e849bbab9cb0adc641a22be598d7e Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 26 Sep 2024 17:49:14 +0200 Subject: [PATCH 025/246] deal with differing syntax contexts for subexpressions in check_proc_macro --- clippy_utils/src/check_proc_macro.rs | 135 ++++++++++++++++----------- tests/ui/dbg_macro/dbg_macro.fixed | 2 +- tests/ui/dbg_macro/dbg_macro.rs | 2 +- 3 files changed, 83 insertions(+), 56 deletions(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 9143d292f670..9a18bff3c7af 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -141,62 +141,89 @@ fn path_search_pat(path: &Path<'_>) -> (Pat, Pat) { /// Get the search patterns to use for the given expression fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) { - match e.kind { - ExprKind::ConstBlock(_) => (Pat::Str("const"), Pat::Str("}")), - // Parenthesis are trimmed from the text before the search patterns are matched. - // See: `span_matches_pat` - ExprKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")), - ExprKind::Unary(UnOp::Deref, e) => (Pat::Str("*"), expr_search_pat(tcx, e).1), - ExprKind::Unary(UnOp::Not, e) => (Pat::Str("!"), expr_search_pat(tcx, e).1), - ExprKind::Unary(UnOp::Neg, e) => (Pat::Str("-"), expr_search_pat(tcx, e).1), - ExprKind::Lit(lit) => lit_search_pat(&lit.node), - ExprKind::Array(_) | ExprKind::Repeat(..) => (Pat::Str("["), Pat::Str("]")), - ExprKind::Call(e, []) | ExprKind::MethodCall(_, e, [], _) => (expr_search_pat(tcx, e).0, Pat::Str("(")), - ExprKind::Call(first, [.., last]) - | ExprKind::MethodCall(_, first, [.., last], _) - | ExprKind::Binary(_, first, last) - | ExprKind::Tup([first, .., last]) - | ExprKind::Assign(first, last, _) - | ExprKind::AssignOp(_, first, last) => (expr_search_pat(tcx, first).0, expr_search_pat(tcx, last).1), - ExprKind::Tup([e]) | ExprKind::DropTemps(e) => expr_search_pat(tcx, e), - ExprKind::Cast(e, _) | ExprKind::Type(e, _) => (expr_search_pat(tcx, e).0, Pat::Str("")), - ExprKind::Let(let_expr) => (Pat::Str("let"), expr_search_pat(tcx, let_expr.init).1), - ExprKind::If(..) => (Pat::Str("if"), Pat::Str("}")), - ExprKind::Loop(_, Some(_), _, _) | ExprKind::Block(_, Some(_)) => (Pat::Str("'"), Pat::Str("}")), - ExprKind::Loop(_, None, LoopSource::Loop, _) => (Pat::Str("loop"), Pat::Str("}")), - ExprKind::Loop(_, None, LoopSource::While, _) => (Pat::Str("while"), Pat::Str("}")), - ExprKind::Loop(_, None, LoopSource::ForLoop, _) | ExprKind::Match(_, _, MatchSource::ForLoopDesugar) => { - (Pat::Str("for"), Pat::Str("}")) - }, - ExprKind::Match(_, _, MatchSource::Normal) => (Pat::Str("match"), Pat::Str("}")), - ExprKind::Match(e, _, MatchSource::TryDesugar(_)) => (expr_search_pat(tcx, e).0, Pat::Str("?")), - ExprKind::Match(e, _, MatchSource::AwaitDesugar) | ExprKind::Yield(e, YieldSource::Await { .. }) => { - (expr_search_pat(tcx, e).0, Pat::Str("await")) - }, - ExprKind::Closure(&Closure { body, .. }) => (Pat::Str(""), expr_search_pat(tcx, tcx.hir().body(body).value).1), - ExprKind::Block( - Block { - rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided), - .. + fn expr_search_pat_inner(tcx: TyCtxt<'_>, e: &Expr<'_>, outer_span: Span) -> (Pat, Pat) { + // The expression can have subexpressions in different contexts, in which case + // building up a search pattern from the macro expansion would lead to false positives; + // e.g. `return format!(..)` would be considered to be from a proc macro + // if we build up a pattern for the macro expansion and compare it to the invocation `format!()`. + // So instead we return an empty pattern such that `span_matches_pat` always returns true. + if !e.span.eq_ctxt(outer_span) { + return (Pat::Str(""), Pat::Str("")); + } + + match e.kind { + ExprKind::ConstBlock(_) => (Pat::Str("const"), Pat::Str("}")), + // Parenthesis are trimmed from the text before the search patterns are matched. + // See: `span_matches_pat` + ExprKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")), + ExprKind::Unary(UnOp::Deref, e) => (Pat::Str("*"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Unary(UnOp::Not, e) => (Pat::Str("!"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Unary(UnOp::Neg, e) => (Pat::Str("-"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Lit(lit) => lit_search_pat(&lit.node), + ExprKind::Array(_) | ExprKind::Repeat(..) => (Pat::Str("["), Pat::Str("]")), + ExprKind::Call(e, []) | ExprKind::MethodCall(_, e, [], _) => { + (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Str("(")) }, - None, - ) => (Pat::Str("unsafe"), Pat::Str("}")), - ExprKind::Block(_, None) => (Pat::Str("{"), Pat::Str("}")), - ExprKind::Field(e, name) => (expr_search_pat(tcx, e).0, Pat::Sym(name.name)), - ExprKind::Index(e, _, _) => (expr_search_pat(tcx, e).0, Pat::Str("]")), - ExprKind::Path(ref path) => qpath_search_pat(path), - ExprKind::AddrOf(_, _, e) => (Pat::Str("&"), expr_search_pat(tcx, e).1), - ExprKind::Break(Destination { label: None, .. }, None) => (Pat::Str("break"), Pat::Str("break")), - ExprKind::Break(Destination { label: Some(name), .. }, None) => (Pat::Str("break"), Pat::Sym(name.ident.name)), - ExprKind::Break(_, Some(e)) => (Pat::Str("break"), expr_search_pat(tcx, e).1), - ExprKind::Continue(Destination { label: None, .. }) => (Pat::Str("continue"), Pat::Str("continue")), - ExprKind::Continue(Destination { label: Some(name), .. }) => (Pat::Str("continue"), Pat::Sym(name.ident.name)), - ExprKind::Ret(None) => (Pat::Str("return"), Pat::Str("return")), - ExprKind::Ret(Some(e)) => (Pat::Str("return"), expr_search_pat(tcx, e).1), - ExprKind::Struct(path, _, _) => (qpath_search_pat(path).0, Pat::Str("}")), - ExprKind::Yield(e, YieldSource::Yield) => (Pat::Str("yield"), expr_search_pat(tcx, e).1), - _ => (Pat::Str(""), Pat::Str("")), + ExprKind::Call(first, [.., last]) + | ExprKind::MethodCall(_, first, [.., last], _) + | ExprKind::Binary(_, first, last) + | ExprKind::Tup([first, .., last]) + | ExprKind::Assign(first, last, _) + | ExprKind::AssignOp(_, first, last) => ( + expr_search_pat_inner(tcx, first, outer_span).0, + expr_search_pat_inner(tcx, last, outer_span).1, + ), + ExprKind::Tup([e]) | ExprKind::DropTemps(e) => expr_search_pat_inner(tcx, e, outer_span), + ExprKind::Cast(e, _) | ExprKind::Type(e, _) => (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Str("")), + ExprKind::Let(let_expr) => (Pat::Str("let"), expr_search_pat_inner(tcx, let_expr.init, outer_span).1), + ExprKind::If(..) => (Pat::Str("if"), Pat::Str("}")), + ExprKind::Loop(_, Some(_), _, _) | ExprKind::Block(_, Some(_)) => (Pat::Str("'"), Pat::Str("}")), + ExprKind::Loop(_, None, LoopSource::Loop, _) => (Pat::Str("loop"), Pat::Str("}")), + ExprKind::Loop(_, None, LoopSource::While, _) => (Pat::Str("while"), Pat::Str("}")), + ExprKind::Loop(_, None, LoopSource::ForLoop, _) | ExprKind::Match(_, _, MatchSource::ForLoopDesugar) => { + (Pat::Str("for"), Pat::Str("}")) + }, + ExprKind::Match(_, _, MatchSource::Normal) => (Pat::Str("match"), Pat::Str("}")), + ExprKind::Match(e, _, MatchSource::TryDesugar(_)) => { + (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Str("?")) + }, + ExprKind::Match(e, _, MatchSource::AwaitDesugar) | ExprKind::Yield(e, YieldSource::Await { .. }) => { + (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Str("await")) + }, + ExprKind::Closure(&Closure { body, .. }) => ( + Pat::Str(""), + expr_search_pat_inner(tcx, tcx.hir().body(body).value, outer_span).1, + ), + ExprKind::Block( + Block { + rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided), + .. + }, + None, + ) => (Pat::Str("unsafe"), Pat::Str("}")), + ExprKind::Block(_, None) => (Pat::Str("{"), Pat::Str("}")), + ExprKind::Field(e, name) => (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Sym(name.name)), + ExprKind::Index(e, _, _) => (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Str("]")), + ExprKind::Path(ref path) => qpath_search_pat(path), + ExprKind::AddrOf(_, _, e) => (Pat::Str("&"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Break(Destination { label: None, .. }, None) => (Pat::Str("break"), Pat::Str("break")), + ExprKind::Break(Destination { label: Some(name), .. }, None) => { + (Pat::Str("break"), Pat::Sym(name.ident.name)) + }, + ExprKind::Break(_, Some(e)) => (Pat::Str("break"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Continue(Destination { label: None, .. }) => (Pat::Str("continue"), Pat::Str("continue")), + ExprKind::Continue(Destination { label: Some(name), .. }) => { + (Pat::Str("continue"), Pat::Sym(name.ident.name)) + }, + ExprKind::Ret(None) => (Pat::Str("return"), Pat::Str("return")), + ExprKind::Ret(Some(e)) => (Pat::Str("return"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Struct(path, _, _) => (qpath_search_pat(path).0, Pat::Str("}")), + ExprKind::Yield(e, YieldSource::Yield) => (Pat::Str("yield"), expr_search_pat_inner(tcx, e, outer_span).1), + _ => (Pat::Str(""), Pat::Str("")), + } } + + expr_search_pat_inner(tcx, e, e.span) } fn fn_header_search_pat(header: FnHeader) -> Pat { diff --git a/tests/ui/dbg_macro/dbg_macro.fixed b/tests/ui/dbg_macro/dbg_macro.fixed index e35251914233..bda9221a5e1e 100644 --- a/tests/ui/dbg_macro/dbg_macro.fixed +++ b/tests/ui/dbg_macro/dbg_macro.fixed @@ -1,5 +1,5 @@ #![warn(clippy::dbg_macro)] -#![allow(clippy::unnecessary_operation, clippy::no_effect)] +#![allow(clippy::unnecessary_operation, clippy::no_effect, clippy::unit_arg)] fn foo(n: u32) -> u32 { if let Some(n) = n.checked_sub(4) { n } else { n } diff --git a/tests/ui/dbg_macro/dbg_macro.rs b/tests/ui/dbg_macro/dbg_macro.rs index 80606c2db054..8244254026be 100644 --- a/tests/ui/dbg_macro/dbg_macro.rs +++ b/tests/ui/dbg_macro/dbg_macro.rs @@ -1,5 +1,5 @@ #![warn(clippy::dbg_macro)] -#![allow(clippy::unnecessary_operation, clippy::no_effect)] +#![allow(clippy::unnecessary_operation, clippy::no_effect, clippy::unit_arg)] fn foo(n: u32) -> u32 { if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } From 8115a1843e4ab020695ba67968e7921ecaaf524b Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 30 Sep 2024 19:26:16 +0300 Subject: [PATCH 026/246] Comment out cast checks for unknown ptr kind Just like we don't check for types containing unknown. --- .../crates/hir-ty/src/infer/cast.rs | 19 ++++--- .../src/handlers/invalid_cast.rs | 54 ++++++++++++------- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs index caa3960a227c..5d5bff08644c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs @@ -70,8 +70,9 @@ pub enum CastError { NeedViaThinPtr, NeedViaInt, NonScalar, - UnknownCastPtrKind, - UnknownExprPtrKind, + // We don't want to report errors with unknown types currently. + // UnknownCastPtrKind, + // UnknownExprPtrKind, } impl CastError { @@ -272,9 +273,10 @@ impl CastCheck { match (src_kind, dst_kind) { (Some(PointerKind::Error), _) | (_, Some(PointerKind::Error)) => Ok(()), - (_, None) => Err(CastError::UnknownCastPtrKind), + // (_, None) => Err(CastError::UnknownCastPtrKind), + // (None, _) => Err(CastError::UnknownExprPtrKind), + (_, None) | (None, _) => Ok(()), (_, Some(PointerKind::Thin)) => Ok(()), - (None, _) => Err(CastError::UnknownExprPtrKind), (Some(PointerKind::Thin), _) => Err(CastError::SizedUnsizedCast), (Some(PointerKind::VTable(src_tty)), Some(PointerKind::VTable(dst_tty))) => { let principal = |tty: &Binders| { @@ -315,7 +317,8 @@ impl CastCheck { expr_ty: &Ty, ) -> Result<(), CastError> { match pointer_kind(expr_ty, table).map_err(|_| CastError::Unknown)? { - None => Err(CastError::UnknownExprPtrKind), + // None => Err(CastError::UnknownExprPtrKind), + None => Ok(()), Some(PointerKind::Error) => Ok(()), Some(PointerKind::Thin) => Ok(()), _ => Err(CastError::NeedViaThinPtr), @@ -328,7 +331,8 @@ impl CastCheck { cast_ty: &Ty, ) -> Result<(), CastError> { match pointer_kind(cast_ty, table).map_err(|_| CastError::Unknown)? { - None => Err(CastError::UnknownCastPtrKind), + // None => Err(CastError::UnknownCastPtrKind), + None => Ok(()), Some(PointerKind::Error) => Ok(()), Some(PointerKind::Thin) => Ok(()), Some(PointerKind::VTable(_)) => Err(CastError::IntToFatCast), @@ -343,7 +347,8 @@ impl CastCheck { cast_ty: &Ty, ) -> Result<(), CastError> { match pointer_kind(cast_ty, table).map_err(|_| CastError::Unknown)? { - None => Err(CastError::UnknownCastPtrKind), + // None => Err(CastError::UnknownCastPtrKind), + None => Ok(()), Some(PointerKind::Error) => Ok(()), Some(PointerKind::Thin) => Ok(()), _ => Err(CastError::IllegalCast), diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs index ad4baf5e3a40..4bd29b8c79b6 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs @@ -95,10 +95,10 @@ pub(crate) fn invalid_cast(ctx: &DiagnosticsContext<'_>, d: &hir::InvalidCast) - DiagnosticCode::RustcHardError("E0605"), format_ty!(ctx, "non-primitive cast: `{}` as `{}`", d.expr_ty, d.cast_ty), ), - CastError::UnknownCastPtrKind | CastError::UnknownExprPtrKind => ( - DiagnosticCode::RustcHardError("E0641"), - "cannot cast to a pointer of an unknown kind".to_owned(), - ), + // CastError::UnknownCastPtrKind | CastError::UnknownExprPtrKind => ( + // DiagnosticCode::RustcHardError("E0641"), + // "cannot cast to a pointer of an unknown kind".to_owned(), + // ), }; Diagnostic::new(code, message, display_range) } @@ -457,20 +457,20 @@ fn foo() { ); } - #[test] - fn order_dependent_cast_inference() { - check_diagnostics( - r#" -//- minicore: sized -fn main() { - let x = &"hello"; - let mut y = 0 as *const _; - //^^^^^^^^^^^^^ error: cannot cast to a pointer of an unknown kind - y = x as *const _; -} -"#, - ); - } + // #[test] + // fn order_dependent_cast_inference() { + // check_diagnostics( + // r#" + // //- minicore: sized + // fn main() { + // let x = &"hello"; + // let mut y = 0 as *const _; + // //^^^^^^^^^^^^^ error: cannot cast to a pointer of an unknown kind + // y = x as *const _; + // } + // "#, + // ); + // } #[test] fn ptr_to_ptr_different_regions() { @@ -1111,4 +1111,22 @@ fn foo() { "#, ); } + + #[test] + fn cast_isize_to_infer_pointer() { + check_diagnostics( + r#" +//- minicore: coerce_unsized +struct Foo {} + +struct Wrap<'a>(&'a mut Foo); + +fn main() { + let lparam: isize = 0; + + let _wrap = Wrap(unsafe { &mut *(lparam as *mut _) }); +} + "#, + ); + } } From d1dec199eea9678b0b3d728100ff356b0cd6f216 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Mon, 2 Sep 2024 02:20:35 -0400 Subject: [PATCH 027/246] Add manual_ignore_cast_cmp lint --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/manual_ignore_case_cmp.rs | 127 +++++ tests/ui/manual_ignore_case_cmp.fixed | 107 ++++ tests/ui/manual_ignore_case_cmp.rs | 107 ++++ tests/ui/manual_ignore_case_cmp.stderr | 546 +++++++++++++++++++++ 7 files changed, 891 insertions(+) create mode 100644 clippy_lints/src/manual_ignore_case_cmp.rs create mode 100644 tests/ui/manual_ignore_case_cmp.fixed create mode 100644 tests/ui/manual_ignore_case_cmp.rs create mode 100644 tests/ui/manual_ignore_case_cmp.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d253d52531e..98be47ec5a19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5621,6 +5621,7 @@ Released 2018-09-13 [`manual_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find_map [`manual_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_flatten [`manual_hash_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one +[`manual_ignore_case_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ignore_case_cmp [`manual_inspect`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_inspect [`manual_instant_elapsed`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_instant_elapsed [`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 9cec672beb00..0b37dffd7323 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -306,6 +306,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::manual_float_methods::MANUAL_IS_FINITE_INFO, crate::manual_float_methods::MANUAL_IS_INFINITE_INFO, crate::manual_hash_one::MANUAL_HASH_ONE_INFO, + crate::manual_ignore_case_cmp::MANUAL_IGNORE_CASE_CMP_INFO, crate::manual_is_ascii_check::MANUAL_IS_ASCII_CHECK_INFO, crate::manual_is_power_of_two::MANUAL_IS_POWER_OF_TWO_INFO, crate::manual_let_else::MANUAL_LET_ELSE_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1d41f568f378..56722e7f537b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -206,6 +206,7 @@ mod manual_clamp; mod manual_div_ceil; mod manual_float_methods; mod manual_hash_one; +mod manual_ignore_case_cmp; mod manual_is_ascii_check; mod manual_is_power_of_two; mod manual_let_else; @@ -944,5 +945,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(manual_is_power_of_two::ManualIsPowerOfTwo)); store.register_late_pass(|_| Box::new(non_zero_suggestions::NonZeroSuggestions)); store.register_late_pass(move |_| Box::new(unused_trait_names::UnusedTraitNames::new(conf))); + store.register_late_pass(|_| Box::new(manual_ignore_case_cmp::ManualIgnoreCaseCmp)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/manual_ignore_case_cmp.rs b/clippy_lints/src/manual_ignore_case_cmp.rs new file mode 100644 index 000000000000..dabfac3f6137 --- /dev/null +++ b/clippy_lints/src/manual_ignore_case_cmp.rs @@ -0,0 +1,127 @@ +use crate::manual_ignore_case_cmp::MatchType::{Literal, ToAscii}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::{get_type_diagnostic_name, is_type_diagnostic_item, is_type_lang_item}; +use rustc_ast::LitKind; +use rustc_errors::Applicability; +use rustc_hir::ExprKind::{Binary, Lit, MethodCall}; +use rustc_hir::{BinOpKind, Expr, LangItem}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; +use rustc_middle::ty::{Ty, UintTy}; +use rustc_session::declare_lint_pass; +use rustc_span::{Span, sym}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for manual case-insensitive ASCII comparison. + /// + /// ### Why is this bad? + /// The `eq_ignore_ascii_case` method is faster because it does not allocate + /// memory for the new strings, and it is more readable. + /// + /// ### Example + /// ```no_run + /// fn compare(a: &str, b: &str) -> bool { + /// a.to_ascii_lowercase() == b.to_ascii_lowercase() || a.to_ascii_lowercase() == "abc" + /// } + /// ``` + /// Use instead: + /// ```no_run + /// fn compare(a: &str, b: &str) -> bool { + /// a.eq_ignore_ascii_case(b) || a.eq_ignore_ascii_case("abc") + /// } + /// ``` + #[clippy::version = "1.82.0"] + pub MANUAL_IGNORE_CASE_CMP, + perf, + "manual case-insensitive ASCII comparison" +} + +declare_lint_pass!(ManualIgnoreCaseCmp => [MANUAL_IGNORE_CASE_CMP]); + +enum MatchType<'a, 'b> { + ToAscii(bool, Ty<'a>), + Literal(&'b LitKind), +} + +fn get_ascii_type<'a, 'b>(cx: &LateContext<'a>, kind: rustc_hir::ExprKind<'b>) -> Option<(Span, MatchType<'a, 'b>)> { + if let MethodCall(path, expr, _, _) = kind { + let is_lower = match path.ident.name.as_str() { + "to_ascii_lowercase" => true, + "to_ascii_uppercase" => false, + _ => return None, + }; + let ty_raw = cx.typeck_results().expr_ty(expr); + let ty = ty_raw.peel_refs(); + if needs_ref_to_cmp(cx, ty) + || ty.is_str() + || ty.is_slice() + || matches!(get_type_diagnostic_name(cx, ty), Some(sym::OsStr | sym::OsString)) + { + return Some((expr.span, ToAscii(is_lower, ty_raw))); + } + } else if let Lit(expr) = kind { + return Some((expr.span, Literal(&expr.node))); + } + None +} + +/// Returns true if the type needs to be dereferenced to be compared +fn needs_ref_to_cmp(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { + ty.is_char() + || *ty.kind() == ty::Uint(UintTy::U8) + || is_type_diagnostic_item(cx, ty, sym::Vec) + || is_type_lang_item(cx, ty, LangItem::String) +} + +impl LateLintPass<'_> for ManualIgnoreCaseCmp { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { + // check if expression represents a comparison of two strings + // using .to_ascii_lowercase() or .to_ascii_uppercase() methods, + // or one of the sides is a literal + // Offer to replace it with .eq_ignore_ascii_case() method + if let Binary(op, left, right) = &expr.kind + && (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne) + && let Some((left_span, left_val)) = get_ascii_type(cx, left.kind) + && let Some((right_span, right_val)) = get_ascii_type(cx, right.kind) + && match (&left_val, &right_val) { + (ToAscii(l_lower, ..), ToAscii(r_lower, ..)) if l_lower == r_lower => true, + (ToAscii(..), Literal(..)) | (Literal(..), ToAscii(..)) => true, + _ => false, + } + { + let deref = match right_val { + ToAscii(_, ty) if needs_ref_to_cmp(cx, ty) => "&", + ToAscii(..) => "", + Literal(ty) => { + if let LitKind::Char(_) | LitKind::Byte(_) = ty { + "&" + } else { + "" + } + }, + }; + let neg = if op.node == BinOpKind::Ne { "!" } else { "" }; + span_lint_and_then( + cx, + MANUAL_IGNORE_CASE_CMP, + expr.span, + "manual case-insensitive ASCII comparison", + |diag| { + let mut app = Applicability::MachineApplicable; + diag.span_suggestion_verbose( + expr.span, + "consider using `.eq_ignore_ascii_case()` instead", + format!( + "{neg}{}.eq_ignore_ascii_case({deref}{})", + snippet_with_applicability(cx, left_span, "_", &mut app), + snippet_with_applicability(cx, right_span, "_", &mut app) + ), + app, + ); + }, + ); + } + } +} diff --git a/tests/ui/manual_ignore_case_cmp.fixed b/tests/ui/manual_ignore_case_cmp.fixed new file mode 100644 index 000000000000..53a124f59c8d --- /dev/null +++ b/tests/ui/manual_ignore_case_cmp.fixed @@ -0,0 +1,107 @@ +#![allow(clippy::all)] +#![deny(clippy::manual_ignore_case_cmp)] + +use std::ffi::{OsStr, OsString}; + +fn main() {} + +fn variants(a: &str, b: &str) { + if a.eq_ignore_ascii_case(b) { + return; + } + if a.eq_ignore_ascii_case(b) { + return; + } + let r = a.eq_ignore_ascii_case(b); + let r = r || a.eq_ignore_ascii_case(b); + r && a.eq_ignore_ascii_case(&b.to_uppercase()); + // != + if !a.eq_ignore_ascii_case(b) { + return; + } + if !a.eq_ignore_ascii_case(b) { + return; + } + let r = !a.eq_ignore_ascii_case(b); + let r = r || !a.eq_ignore_ascii_case(b); + r && !a.eq_ignore_ascii_case(&b.to_uppercase()); +} + +fn unsupported(a: char, b: char) { + // TODO:: these are rare, and might not be worth supporting + a.to_ascii_lowercase() == char::to_ascii_lowercase(&b); + char::to_ascii_lowercase(&a) == b.to_ascii_lowercase(); + char::to_ascii_lowercase(&a) == char::to_ascii_lowercase(&b); +} + +fn char(a: char, b: char) { + a.eq_ignore_ascii_case(&b); + a.to_ascii_lowercase() == *&b.to_ascii_lowercase(); + *&a.to_ascii_lowercase() == b.to_ascii_lowercase(); + a.eq_ignore_ascii_case(&'a'); + 'a'.eq_ignore_ascii_case(&b); +} +fn u8(a: u8, b: u8) { + a.eq_ignore_ascii_case(&b); + a.eq_ignore_ascii_case(&b'a'); + b'a'.eq_ignore_ascii_case(&b); +} +fn ref_str(a: &str, b: &str) { + a.eq_ignore_ascii_case(b); + a.to_uppercase().eq_ignore_ascii_case(b); + a.eq_ignore_ascii_case("a"); + "a".eq_ignore_ascii_case(b); +} +fn ref_ref_str(a: &&str, b: &&str) { + a.eq_ignore_ascii_case(b); + a.to_uppercase().eq_ignore_ascii_case(b); + a.eq_ignore_ascii_case("a"); + "a".eq_ignore_ascii_case(b); +} +fn string(a: String, b: String) { + a.eq_ignore_ascii_case(&b); + a.eq_ignore_ascii_case("a"); + "a".eq_ignore_ascii_case(&b); + &a.to_ascii_lowercase() == &b.to_ascii_lowercase(); + &&a.to_ascii_lowercase() == &&b.to_ascii_lowercase(); + a.eq_ignore_ascii_case("a"); + "a".eq_ignore_ascii_case(&b); +} +fn ref_string(a: String, b: &String) { + a.eq_ignore_ascii_case(b); + a.eq_ignore_ascii_case("a"); + "a".eq_ignore_ascii_case(b); + + b.eq_ignore_ascii_case(&a); + b.eq_ignore_ascii_case("a"); + "a".eq_ignore_ascii_case(&a); +} +fn string_ref_str(a: String, b: &str) { + a.eq_ignore_ascii_case(b); + a.eq_ignore_ascii_case("a"); + "a".eq_ignore_ascii_case(b); + + b.eq_ignore_ascii_case(&a); + b.eq_ignore_ascii_case("a"); + "a".eq_ignore_ascii_case(&a); +} +fn ref_u8slice(a: &[u8], b: &[u8]) { + a.eq_ignore_ascii_case(b); +} +fn u8vec(a: Vec, b: Vec) { + a.eq_ignore_ascii_case(&b); +} +fn ref_u8vec(a: Vec, b: &Vec) { + a.eq_ignore_ascii_case(b); + b.eq_ignore_ascii_case(&a); +} +fn ref_osstr(a: &OsStr, b: &OsStr) { + a.eq_ignore_ascii_case(b); +} +fn osstring(a: OsString, b: OsString) { + a.eq_ignore_ascii_case(b); +} +fn ref_osstring(a: OsString, b: &OsString) { + a.eq_ignore_ascii_case(b); + b.eq_ignore_ascii_case(a); +} diff --git a/tests/ui/manual_ignore_case_cmp.rs b/tests/ui/manual_ignore_case_cmp.rs new file mode 100644 index 000000000000..2a4d84b30ace --- /dev/null +++ b/tests/ui/manual_ignore_case_cmp.rs @@ -0,0 +1,107 @@ +#![allow(clippy::all)] +#![deny(clippy::manual_ignore_case_cmp)] + +use std::ffi::{OsStr, OsString}; + +fn main() {} + +fn variants(a: &str, b: &str) { + if a.to_ascii_lowercase() == b.to_ascii_lowercase() { + return; + } + if a.to_ascii_uppercase() == b.to_ascii_uppercase() { + return; + } + let r = a.to_ascii_lowercase() == b.to_ascii_lowercase(); + let r = r || a.to_ascii_uppercase() == b.to_ascii_uppercase(); + r && a.to_ascii_lowercase() == b.to_uppercase().to_ascii_lowercase(); + // != + if a.to_ascii_lowercase() != b.to_ascii_lowercase() { + return; + } + if a.to_ascii_uppercase() != b.to_ascii_uppercase() { + return; + } + let r = a.to_ascii_lowercase() != b.to_ascii_lowercase(); + let r = r || a.to_ascii_uppercase() != b.to_ascii_uppercase(); + r && a.to_ascii_lowercase() != b.to_uppercase().to_ascii_lowercase(); +} + +fn unsupported(a: char, b: char) { + // TODO:: these are rare, and might not be worth supporting + a.to_ascii_lowercase() == char::to_ascii_lowercase(&b); + char::to_ascii_lowercase(&a) == b.to_ascii_lowercase(); + char::to_ascii_lowercase(&a) == char::to_ascii_lowercase(&b); +} + +fn char(a: char, b: char) { + a.to_ascii_lowercase() == b.to_ascii_lowercase(); + a.to_ascii_lowercase() == *&b.to_ascii_lowercase(); + *&a.to_ascii_lowercase() == b.to_ascii_lowercase(); + a.to_ascii_lowercase() == 'a'; + 'a' == b.to_ascii_lowercase(); +} +fn u8(a: u8, b: u8) { + a.to_ascii_lowercase() == b.to_ascii_lowercase(); + a.to_ascii_lowercase() == b'a'; + b'a' == b.to_ascii_lowercase(); +} +fn ref_str(a: &str, b: &str) { + a.to_ascii_lowercase() == b.to_ascii_lowercase(); + a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase(); + a.to_ascii_lowercase() == "a"; + "a" == b.to_ascii_lowercase(); +} +fn ref_ref_str(a: &&str, b: &&str) { + a.to_ascii_lowercase() == b.to_ascii_lowercase(); + a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase(); + a.to_ascii_lowercase() == "a"; + "a" == b.to_ascii_lowercase(); +} +fn string(a: String, b: String) { + a.to_ascii_lowercase() == b.to_ascii_lowercase(); + a.to_ascii_lowercase() == "a"; + "a" == b.to_ascii_lowercase(); + &a.to_ascii_lowercase() == &b.to_ascii_lowercase(); + &&a.to_ascii_lowercase() == &&b.to_ascii_lowercase(); + a.to_ascii_lowercase() == "a"; + "a" == b.to_ascii_lowercase(); +} +fn ref_string(a: String, b: &String) { + a.to_ascii_lowercase() == b.to_ascii_lowercase(); + a.to_ascii_lowercase() == "a"; + "a" == b.to_ascii_lowercase(); + + b.to_ascii_lowercase() == a.to_ascii_lowercase(); + b.to_ascii_lowercase() == "a"; + "a" == a.to_ascii_lowercase(); +} +fn string_ref_str(a: String, b: &str) { + a.to_ascii_lowercase() == b.to_ascii_lowercase(); + a.to_ascii_lowercase() == "a"; + "a" == b.to_ascii_lowercase(); + + b.to_ascii_lowercase() == a.to_ascii_lowercase(); + b.to_ascii_lowercase() == "a"; + "a" == a.to_ascii_lowercase(); +} +fn ref_u8slice(a: &[u8], b: &[u8]) { + a.to_ascii_lowercase() == b.to_ascii_lowercase(); +} +fn u8vec(a: Vec, b: Vec) { + a.to_ascii_lowercase() == b.to_ascii_lowercase(); +} +fn ref_u8vec(a: Vec, b: &Vec) { + a.to_ascii_lowercase() == b.to_ascii_lowercase(); + b.to_ascii_lowercase() == a.to_ascii_lowercase(); +} +fn ref_osstr(a: &OsStr, b: &OsStr) { + a.to_ascii_lowercase() == b.to_ascii_lowercase(); +} +fn osstring(a: OsString, b: OsString) { + a.to_ascii_lowercase() == b.to_ascii_lowercase(); +} +fn ref_osstring(a: OsString, b: &OsString) { + a.to_ascii_lowercase() == b.to_ascii_lowercase(); + b.to_ascii_lowercase() == a.to_ascii_lowercase(); +} diff --git a/tests/ui/manual_ignore_case_cmp.stderr b/tests/ui/manual_ignore_case_cmp.stderr new file mode 100644 index 000000000000..11e8b8aebb54 --- /dev/null +++ b/tests/ui/manual_ignore_case_cmp.stderr @@ -0,0 +1,546 @@ +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:9:8 + | +LL | if a.to_ascii_lowercase() == b.to_ascii_lowercase() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui/manual_ignore_case_cmp.rs:2:9 + | +LL | #![deny(clippy::manual_ignore_case_cmp)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | if a.eq_ignore_ascii_case(b) { + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:12:8 + | +LL | if a.to_ascii_uppercase() == b.to_ascii_uppercase() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | if a.eq_ignore_ascii_case(b) { + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:15:13 + | +LL | let r = a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | let r = a.eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:16:18 + | +LL | let r = r || a.to_ascii_uppercase() == b.to_ascii_uppercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | let r = r || a.eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:17:10 + | +LL | r && a.to_ascii_lowercase() == b.to_uppercase().to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | r && a.eq_ignore_ascii_case(&b.to_uppercase()); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:19:8 + | +LL | if a.to_ascii_lowercase() != b.to_ascii_lowercase() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | if !a.eq_ignore_ascii_case(b) { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:22:8 + | +LL | if a.to_ascii_uppercase() != b.to_ascii_uppercase() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | if !a.eq_ignore_ascii_case(b) { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:25:13 + | +LL | let r = a.to_ascii_lowercase() != b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | let r = !a.eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:26:18 + | +LL | let r = r || a.to_ascii_uppercase() != b.to_ascii_uppercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | let r = r || !a.eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:27:10 + | +LL | r && a.to_ascii_lowercase() != b.to_uppercase().to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | r && !a.eq_ignore_ascii_case(&b.to_uppercase()); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:38:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case(&b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:41:5 + | +LL | a.to_ascii_lowercase() == 'a'; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case(&'a'); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:42:5 + | +LL | 'a' == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | 'a'.eq_ignore_ascii_case(&b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:45:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case(&b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:46:5 + | +LL | a.to_ascii_lowercase() == b'a'; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case(&b'a'); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:47:5 + | +LL | b'a' == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | b'a'.eq_ignore_ascii_case(&b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:50:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:51:5 + | +LL | a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.to_uppercase().eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:52:5 + | +LL | a.to_ascii_lowercase() == "a"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case("a"); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:53:5 + | +LL | "a" == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | "a".eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:56:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:57:5 + | +LL | a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.to_uppercase().eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:58:5 + | +LL | a.to_ascii_lowercase() == "a"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case("a"); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:59:5 + | +LL | "a" == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | "a".eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:62:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case(&b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:63:5 + | +LL | a.to_ascii_lowercase() == "a"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case("a"); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:64:5 + | +LL | "a" == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | "a".eq_ignore_ascii_case(&b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:67:5 + | +LL | a.to_ascii_lowercase() == "a"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case("a"); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:68:5 + | +LL | "a" == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | "a".eq_ignore_ascii_case(&b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:71:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:72:5 + | +LL | a.to_ascii_lowercase() == "a"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case("a"); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:73:5 + | +LL | "a" == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | "a".eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:75:5 + | +LL | b.to_ascii_lowercase() == a.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | b.eq_ignore_ascii_case(&a); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:76:5 + | +LL | b.to_ascii_lowercase() == "a"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | b.eq_ignore_ascii_case("a"); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:77:5 + | +LL | "a" == a.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | "a".eq_ignore_ascii_case(&a); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:80:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:81:5 + | +LL | a.to_ascii_lowercase() == "a"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case("a"); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:82:5 + | +LL | "a" == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | "a".eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:84:5 + | +LL | b.to_ascii_lowercase() == a.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | b.eq_ignore_ascii_case(&a); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:85:5 + | +LL | b.to_ascii_lowercase() == "a"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | b.eq_ignore_ascii_case("a"); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:86:5 + | +LL | "a" == a.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | "a".eq_ignore_ascii_case(&a); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:89:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:92:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case(&b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:95:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:96:5 + | +LL | b.to_ascii_lowercase() == a.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | b.eq_ignore_ascii_case(&a); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:99:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:102:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:105:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | a.eq_ignore_ascii_case(b); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:106:5 + | +LL | b.to_ascii_lowercase() == a.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL | b.eq_ignore_ascii_case(a); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 49 previous errors + From 13e2633f193838eadcddd5bf5842b9ce0a1f17dd Mon Sep 17 00:00:00 2001 From: blyxyas Date: Tue, 1 Oct 2024 19:39:18 +0200 Subject: [PATCH 028/246] Also sanitize configuration --- clippy_config/src/conf.rs | 24 ++++++++++++++++++++++++ clippy_config/src/lib.rs | 2 +- clippy_lints/src/lib.rs | 26 +------------------------- tests/compile-test.rs | 6 +----- 4 files changed, 27 insertions(+), 31 deletions(-) diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 757620341ccc..df13be800988 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -97,6 +97,30 @@ impl ConfError { } } +// Remove code tags and code behind '# 's, as they are not needed for the lint docs and --explain +pub fn sanitize_explanation(raw_docs: &str) -> String { + // Remove tags and hidden code: + let mut explanation = String::with_capacity(128); + let mut in_code = false; + for line in raw_docs.lines().map(str::trim) { + if let Some(lang) = line.strip_prefix("```") { + let tag = lang.split_once(',').map_or(lang, |(left, _)| left); + if !in_code && matches!(tag, "" | "rust" | "ignore" | "should_panic" | "no_run" | "compile_fail") { + explanation += "```rust\n"; + } else { + explanation += line; + explanation.push('\n'); + } + in_code = !in_code; + } else if !(in_code && line.starts_with("# ")) { + explanation += line; + explanation.push('\n'); + } + } + + explanation +} + macro_rules! wrap_option { () => { None diff --git a/clippy_config/src/lib.rs b/clippy_config/src/lib.rs index c63d98a0a13f..42651521f8d7 100644 --- a/clippy_config/src/lib.rs +++ b/clippy_config/src/lib.rs @@ -26,5 +26,5 @@ mod metadata; pub mod msrvs; pub mod types; -pub use conf::{Conf, get_configuration_metadata, lookup_conf_file}; +pub use conf::{Conf, get_configuration_metadata, lookup_conf_file, sanitize_explanation}; pub use metadata::ClippyConfiguration; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0bfbb92dfda5..71e7b56408e2 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -396,7 +396,7 @@ mod zero_sized_map_values; mod zombie_processes; // end lints modules, do not remove this comment, it’s used in `update_lints` -use clippy_config::{Conf, get_configuration_metadata}; +use clippy_config::{Conf, get_configuration_metadata, sanitize_explanation}; use clippy_utils::macros::FormatArgsStorage; use rustc_data_structures::fx::FxHashSet; use rustc_lint::{Lint, LintId}; @@ -522,30 +522,6 @@ impl LintInfo { } } -// Remove code tags and code behind '# 's, as they are not needed for the lint docs and --explain -pub fn sanitize_explanation(raw_docs: &str) -> String { - // Remove tags and hidden code: - let mut explanation = String::with_capacity(128); - let mut in_code = false; - for line in raw_docs.lines().map(|line| line.trim()) { - if let Some(lang) = line.strip_prefix("```") { - let tag = lang.split_once(',').map_or(lang, |(left, _)| left); - if !in_code && matches!(tag, "" | "rust" | "ignore" | "should_panic" | "no_run" | "compile_fail") { - explanation += "```rust\n"; - } else { - explanation += line; - explanation.push('\n'); - } - in_code = !in_code; - } else if !(in_code && line.starts_with("# ")) { - explanation += line; - explanation.push('\n'); - } - } - - explanation -} - pub fn explain(name: &str) -> i32 { let target = format!("clippy::{}", name.to_ascii_uppercase()); diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 23dd41235bdb..8734bd413649 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -5,9 +5,9 @@ use cargo_metadata::Message; use cargo_metadata::diagnostic::{Applicability, Diagnostic}; use clippy_config::ClippyConfiguration; +use clippy_lints::LintInfo; use clippy_lints::declared_lints::LINTS; use clippy_lints::deprecated_lints::{DEPRECATED, DEPRECATED_VERSION, RENAMED}; -use clippy_lints::{LintInfo, sanitize_explanation}; use serde::{Deserialize, Serialize}; use test_utils::IS_RUSTC_TEST_SUITE; use ui_test::custom_flags::Flag; @@ -444,10 +444,6 @@ impl DiagnosticCollector { iter::zip(DEPRECATED, DEPRECATED_VERSION) .map(|((lint, reason), version)| LintMetadata::new_deprecated(lint, reason, version)), ) - .map(|mut metadata| { - metadata.docs = sanitize_explanation(&metadata.docs); - metadata - }) .collect(); metadata.sort_unstable_by(|a, b| a.id.cmp(&b.id)); From 3ac3c3495173d2b93c585e0df37667f7633b9ab5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 22:23:44 -0400 Subject: [PATCH 029/246] Remove crashes and fix tests --- tests/ui/crashes/ice-12284.rs | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 tests/ui/crashes/ice-12284.rs diff --git a/tests/ui/crashes/ice-12284.rs b/tests/ui/crashes/ice-12284.rs deleted file mode 100644 index 8d1dbface8eb..000000000000 --- a/tests/ui/crashes/ice-12284.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![allow(incomplete_features)] -#![feature(unnamed_fields)] - -#[repr(C)] -struct Foo { - _: struct { - }, -} - -fn main() {} From 22129b18c02049a7fe14c4a81b399a4ca553785e Mon Sep 17 00:00:00 2001 From: SabrinaJewson Date: Tue, 1 Oct 2024 22:09:31 +0100 Subject: [PATCH 030/246] fix: correctly parse `use` in generic parameters --- .../parser/src/grammar/generic_params.rs | 2 +- .../test_data/parser/err/0055_impl_use.rast | 26 +++++++++++++++++++ .../test_data/parser/err/0055_impl_use.rs | 2 ++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/tools/rust-analyzer/crates/parser/test_data/parser/err/0055_impl_use.rast create mode 100644 src/tools/rust-analyzer/crates/parser/test_data/parser/err/0055_impl_use.rs diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs index e0fa753fa70a..ecfabca092c3 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs @@ -145,7 +145,7 @@ fn type_bound(p: &mut Parser<'_>) -> bool { T![for] => types::for_type(p, false), // test precise_capturing // fn captures<'a: 'a, 'b: 'b, T>() -> impl Sized + use<'b, T> {} - T![use] => { + T![use] if p.nth_at(1, T![<]) => { p.bump_any(); generic_param_list(p) } diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0055_impl_use.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0055_impl_use.rast new file mode 100644 index 000000000000..751f007df943 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0055_impl_use.rast @@ -0,0 +1,26 @@ +SOURCE_FILE + IMPL + IMPL_KW "impl" + GENERIC_PARAM_LIST + L_ANGLE "<" + TYPE_PARAM + NAME + IDENT "T" + COLON ":" + WHITESPACE "\n" + TYPE_BOUND_LIST + ERROR + USE_KW "use" + WHITESPACE " " + MACRO_CALL + PATH + PATH_SEGMENT + NAME_REF + IDENT "std" + SEMICOLON ";" + WHITESPACE "\n" +error 8: expected R_ANGLE +error 8: expected type +error 11: expected `{` +error 15: expected BANG +error 15: expected `{`, `[`, `(` diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0055_impl_use.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0055_impl_use.rs new file mode 100644 index 000000000000..571552bda849 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0055_impl_use.rs @@ -0,0 +1,2 @@ +impl Date: Wed, 2 Oct 2024 16:47:05 +0100 Subject: [PATCH 031/246] fix: Join rustfmt overrideCommand with project root When providing a custom rustfmt command, join it with the project root instead of the workspace root. This fixes rust-analyzer getting the wrong invocation path in projects containing subprojects. This makes the behaviour consistent with how a custom path provided in rust-analyzer.procMacro.server behaves already. Resolves issue #18222 --- .../crates/rust-analyzer/src/handlers/request.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index 9773d8dbce01..3a1770d770d7 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -2201,14 +2201,14 @@ fn run_rustfmt( let cmd = Utf8PathBuf::from(&command); let target_spec = TargetSpec::for_file(snap, file_id)?; let mut cmd = match target_spec { - Some(TargetSpec::Cargo(spec)) => { - // approach: if the command name contains a path separator, join it with the workspace root. + Some(TargetSpec::Cargo(_)) => { + // approach: if the command name contains a path separator, join it with the project root. // however, if the path is absolute, joining will result in the absolute path being preserved. // as a fallback, rely on $PATH-based discovery. let cmd_path = if command.contains(std::path::MAIN_SEPARATOR) || (cfg!(windows) && command.contains('/')) { - spec.workspace_root.join(cmd).into() + snap.config.root_path().join(cmd).into() } else { cmd }; From ce22fd34d9c35ad08da74d82bea4227f8dba77f7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 2 Oct 2024 21:52:44 -0400 Subject: [PATCH 032/246] Remove redundant in_trait from hir::TyKind::OpaqueDef --- clippy_lints/src/extra_unused_type_parameters.rs | 2 +- clippy_lints/src/lifetimes.rs | 2 +- clippy_lints/src/manual_async_fn.rs | 2 +- clippy_utils/src/hir_utils.rs | 3 +-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/extra_unused_type_parameters.rs b/clippy_lints/src/extra_unused_type_parameters.rs index bf9388b4a70f..a7fb9535e790 100644 --- a/clippy_lints/src/extra_unused_type_parameters.rs +++ b/clippy_lints/src/extra_unused_type_parameters.rs @@ -199,7 +199,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> { fn visit_ty(&mut self, t: &'tcx Ty<'tcx>) { if let Some((def_id, _)) = t.peel_refs().as_generic_param() { self.ty_params.remove(&def_id); - } else if let TyKind::OpaqueDef(id, _, _) = t.kind { + } else if let TyKind::OpaqueDef(id, _) = t.kind { // Explicitly walk OpaqueDef. Normally `walk_ty` would do the job, but it calls // `visit_nested_item`, which checks that `Self::NestedFilter::INTER` is set. We're // using `OnlyBodies`, so the check ends up failing and the type isn't fully walked. diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 755afe959b37..d3cc5ea628c7 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -523,7 +523,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &'tcx Ty<'_>) { match ty.kind { - TyKind::OpaqueDef(item, bounds, _) => { + TyKind::OpaqueDef(item, bounds) => { let map = self.cx.tcx.hir(); let item = map.item(item); let len = self.lts.len(); diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs index fc3bba9e5123..7097c85156c3 100644 --- a/clippy_lints/src/manual_async_fn.rs +++ b/clippy_lints/src/manual_async_fn.rs @@ -105,7 +105,7 @@ fn future_trait_ref<'tcx>( cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>, ) -> Option<(&'tcx TraitRef<'tcx>, Vec)> { - if let TyKind::OpaqueDef(item_id, bounds, false) = ty.kind + if let TyKind::OpaqueDef(item_id, bounds) = ty.kind && let item = cx.tcx.hir().item(item_id) && let ItemKind::OpaqueTy(opaque) = &item.kind && let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| { diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 76900379ac78..b2d75125ccdb 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -1115,9 +1115,8 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } }, TyKind::Path(ref qpath) => self.hash_qpath(qpath), - TyKind::OpaqueDef(_, arg_list, in_trait) => { + TyKind::OpaqueDef(_, arg_list) => { self.hash_generic_args(arg_list); - in_trait.hash(&mut self.s); }, TyKind::TraitObject(_, lifetime, _) => { self.hash_lifetime(lifetime); From cbd64a4868a84e980101be7779b7b17156dff383 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 2 Oct 2024 22:04:18 -0400 Subject: [PATCH 033/246] Use named fields for OpaqueTyOrigin --- clippy_lints/src/len_zero.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 8bc2a56af993..0cbcdbeb90ae 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -313,7 +313,7 @@ fn extract_future_output<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<& kind: ItemKind::OpaqueTy(opaque), .. } = item - && let OpaqueTyOrigin::AsyncFn(_) = opaque.origin + && let OpaqueTyOrigin::AsyncFn { .. } = opaque.origin && let [GenericBound::Trait(trait_ref, _)] = &opaque.bounds && let Some(segment) = trait_ref.trait_ref.path.segments.last() && let Some(generic_args) = segment.args From 2080634d336ac73a00aa256993ee035da7226aca Mon Sep 17 00:00:00 2001 From: coekjan Date: Wed, 2 Oct 2024 23:51:52 +0800 Subject: [PATCH 034/246] Fix lint `manual_slice_size_calculation` when the slice is ref more than once --- .../src/manual_slice_size_calculation.rs | 14 +++++----- tests/ui/manual_slice_size_calculation.fixed | 4 +++ tests/ui/manual_slice_size_calculation.rs | 4 +++ tests/ui/manual_slice_size_calculation.stderr | 26 ++++++++++++++----- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/manual_slice_size_calculation.rs b/clippy_lints/src/manual_slice_size_calculation.rs index b24a0f4695a6..a984a7f95205 100644 --- a/clippy_lints/src/manual_slice_size_calculation.rs +++ b/clippy_lints/src/manual_slice_size_calculation.rs @@ -45,10 +45,11 @@ impl<'tcx> LateLintPass<'tcx> for ManualSliceSizeCalculation { && !expr.span.from_expansion() // Does not apply inside const because size_of_val is not cost in stable. && !is_in_const_context(cx) - && let Some(receiver) = simplify(cx, left, right) + && let Some((receiver, refs_count)) = simplify(cx, left, right) { let ctxt = expr.span.ctxt(); let mut app = Applicability::MachineApplicable; + let deref = "*".repeat(refs_count - 1); let val_name = snippet_with_context(cx, receiver.span, ctxt, "slice", &mut app).0; let Some(sugg) = std_or_core(cx) else { return }; @@ -58,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualSliceSizeCalculation { expr.span, "manual slice size calculation", "try", - format!("{sugg}::mem::size_of_val({val_name})"), + format!("{sugg}::mem::size_of_val({deref}{val_name})"), app, ); } @@ -69,7 +70,7 @@ fn simplify<'tcx>( cx: &LateContext<'tcx>, expr1: &'tcx Expr<'tcx>, expr2: &'tcx Expr<'tcx>, -) -> Option<&'tcx Expr<'tcx>> { +) -> Option<(&'tcx Expr<'tcx>, usize)> { let expr1 = expr_or_init(cx, expr1); let expr2 = expr_or_init(cx, expr2); @@ -80,13 +81,14 @@ fn simplify_half<'tcx>( cx: &LateContext<'tcx>, expr1: &'tcx Expr<'tcx>, expr2: &'tcx Expr<'tcx>, -) -> Option<&'tcx Expr<'tcx>> { +) -> Option<(&'tcx Expr<'tcx>, usize)> { if !expr1.span.from_expansion() // expr1 is `[T1].len()`? && let ExprKind::MethodCall(method_path, receiver, _, _) = expr1.kind && method_path.ident.name == sym::len && let receiver_ty = cx.typeck_results().expr_ty(receiver) - && let ty::Slice(ty1) = receiver_ty.peel_refs().kind() + && let (receiver_ty, refs_count) = clippy_utils::ty::walk_ptrs_ty_depth(receiver_ty) + && let ty::Slice(ty1) = receiver_ty.kind() // expr2 is `size_of::()`? && let ExprKind::Call(func, _) = expr2.kind && let ExprKind::Path(ref func_qpath) = func.kind @@ -96,7 +98,7 @@ fn simplify_half<'tcx>( // T1 == T2? && *ty1 == ty2 { - Some(receiver) + Some((receiver, refs_count)) } else { None } diff --git a/tests/ui/manual_slice_size_calculation.fixed b/tests/ui/manual_slice_size_calculation.fixed index 62b372f4b8d9..0603b30e3465 100644 --- a/tests/ui/manual_slice_size_calculation.fixed +++ b/tests/ui/manual_slice_size_calculation.fixed @@ -10,11 +10,15 @@ use proc_macros::external; fn main() { let v_i32 = Vec::::new(); let s_i32 = v_i32.as_slice(); + let s_i32_ref = &s_i32; + let s_i32_ref_ref = &s_i32_ref; // True positives: let _ = std::mem::size_of_val(s_i32); // WARNING let _ = std::mem::size_of_val(s_i32); // WARNING let _ = std::mem::size_of_val(s_i32) * 5; // WARNING + let _ = std::mem::size_of_val(*s_i32_ref); // WARNING + let _ = std::mem::size_of_val(**s_i32_ref_ref); // WARNING let len = s_i32.len(); let size = size_of::(); diff --git a/tests/ui/manual_slice_size_calculation.rs b/tests/ui/manual_slice_size_calculation.rs index d59f5fd8b942..14093e653c09 100644 --- a/tests/ui/manual_slice_size_calculation.rs +++ b/tests/ui/manual_slice_size_calculation.rs @@ -10,11 +10,15 @@ use proc_macros::external; fn main() { let v_i32 = Vec::::new(); let s_i32 = v_i32.as_slice(); + let s_i32_ref = &s_i32; + let s_i32_ref_ref = &s_i32_ref; // True positives: let _ = s_i32.len() * size_of::(); // WARNING let _ = size_of::() * s_i32.len(); // WARNING let _ = size_of::() * s_i32.len() * 5; // WARNING + let _ = size_of::() * s_i32_ref.len(); // WARNING + let _ = size_of::() * s_i32_ref_ref.len(); // WARNING let len = s_i32.len(); let size = size_of::(); diff --git a/tests/ui/manual_slice_size_calculation.stderr b/tests/ui/manual_slice_size_calculation.stderr index 4bd8a4fdf17b..0397f3a4969a 100644 --- a/tests/ui/manual_slice_size_calculation.stderr +++ b/tests/ui/manual_slice_size_calculation.stderr @@ -1,5 +1,5 @@ error: manual slice size calculation - --> tests/ui/manual_slice_size_calculation.rs:15:13 + --> tests/ui/manual_slice_size_calculation.rs:17:13 | LL | let _ = s_i32.len() * size_of::(); // WARNING | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` @@ -8,40 +8,52 @@ LL | let _ = s_i32.len() * size_of::(); // WARNING = help: to override `-D warnings` add `#[allow(clippy::manual_slice_size_calculation)]` error: manual slice size calculation - --> tests/ui/manual_slice_size_calculation.rs:16:13 + --> tests/ui/manual_slice_size_calculation.rs:18:13 | LL | let _ = size_of::() * s_i32.len(); // WARNING | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` error: manual slice size calculation - --> tests/ui/manual_slice_size_calculation.rs:17:13 + --> tests/ui/manual_slice_size_calculation.rs:19:13 | LL | let _ = size_of::() * s_i32.len() * 5; // WARNING | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` +error: manual slice size calculation + --> tests/ui/manual_slice_size_calculation.rs:20:13 + | +LL | let _ = size_of::() * s_i32_ref.len(); // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(*s_i32_ref)` + error: manual slice size calculation --> tests/ui/manual_slice_size_calculation.rs:21:13 | +LL | let _ = size_of::() * s_i32_ref_ref.len(); // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(**s_i32_ref_ref)` + +error: manual slice size calculation + --> tests/ui/manual_slice_size_calculation.rs:25:13 + | LL | let _ = len * size_of::(); // WARNING | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` error: manual slice size calculation - --> tests/ui/manual_slice_size_calculation.rs:22:13 + --> tests/ui/manual_slice_size_calculation.rs:26:13 | LL | let _ = s_i32.len() * size; // WARNING | ^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` error: manual slice size calculation - --> tests/ui/manual_slice_size_calculation.rs:23:13 + --> tests/ui/manual_slice_size_calculation.rs:27:13 | LL | let _ = len * size; // WARNING | ^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` error: manual slice size calculation - --> tests/ui/manual_slice_size_calculation.rs:25:13 + --> tests/ui/manual_slice_size_calculation.rs:29:13 | LL | let _ = external!(&[1u64][..]).len() * size_of::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(external!(&[1u64][..]))` -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors From aeb548a4f76c742608c2b7154461814440048506 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 14 Aug 2024 16:40:00 +0200 Subject: [PATCH 035/246] Put back interactions with settings menus --- util/gh-pages/index_template.html | 78 ++++++++++------------------ util/gh-pages/script.js | 85 +++++++++++++++++++------------ util/gh-pages/style.css | 14 ++++- 3 files changed, 91 insertions(+), 86 deletions(-) diff --git a/util/gh-pages/index_template.html b/util/gh-pages/index_template.html index 5a7af7d562ed..a18948a20604 100644 --- a/util/gh-pages/index_template.html +++ b/util/gh-pages/index_template.html @@ -27,7 +27,7 @@ Otherwise, have a great day =^.^=
    -
    +
    Theme
    - All - +
  • - +
  • -
    +
    -
    -
    -
    - - -
    +
    + +
    -
    +
    -