From d5d4cecee9a3456ec0ec6011090c947fe5409995 Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 24 Feb 2025 11:04:04 +0800 Subject: [PATCH 01/11] Suggest mut when possbile for temporary value dropped while borrowed --- .../src/diagnostics/conflict_errors.rs | 14 ++++++- tests/ui/coroutine/auto-trait-regions.stderr | 4 +- .../sugg-mut-for-binding-issue-137486.fixed | 23 ++++++++++++ .../nll/sugg-mut-for-binding-issue-137486.rs | 21 +++++++++++ .../sugg-mut-for-binding-issue-137486.stderr | 37 +++++++++++++++++++ 5 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 tests/ui/nll/sugg-mut-for-binding-issue-137486.fixed create mode 100644 tests/ui/nll/sugg-mut-for-binding-issue-137486.rs create mode 100644 tests/ui/nll/sugg-mut-for-binding-issue-137486.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 3b7d31b1b13bd..d0e014971f442 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -3229,8 +3229,20 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { Applicability::MaybeIncorrect, ); } + + let mutability = if matches!(borrow.kind(), BorrowKind::Mut { .. }) { + "mut " + } else { + "" + }; + if !is_format_arguments_item { - let addition = format!("let binding = {};\n{}", s, " ".repeat(p)); + let addition = format!( + "let {}binding = {};\n{}", + mutability, + s, + " ".repeat(p) + ); err.multipart_suggestion_verbose( msg, vec![ diff --git a/tests/ui/coroutine/auto-trait-regions.stderr b/tests/ui/coroutine/auto-trait-regions.stderr index a9a0bde2ba019..a3b5a5f006e61 100644 --- a/tests/ui/coroutine/auto-trait-regions.stderr +++ b/tests/ui/coroutine/auto-trait-regions.stderr @@ -11,7 +11,7 @@ LL | assert_foo(a); | help: consider using a `let` binding to create a longer lived value | -LL ~ let binding = true; +LL ~ let mut binding = true; LL ~ let a = A(&mut binding, &mut true, No); | @@ -28,7 +28,7 @@ LL | assert_foo(a); | help: consider using a `let` binding to create a longer lived value | -LL ~ let binding = true; +LL ~ let mut binding = true; LL ~ let a = A(&mut true, &mut binding, No); | diff --git a/tests/ui/nll/sugg-mut-for-binding-issue-137486.fixed b/tests/ui/nll/sugg-mut-for-binding-issue-137486.fixed new file mode 100644 index 0000000000000..ee9d9a373de00 --- /dev/null +++ b/tests/ui/nll/sugg-mut-for-binding-issue-137486.fixed @@ -0,0 +1,23 @@ +//@ run-rustfix +#![allow(unused_assignments)] + +use std::pin::Pin; +fn main() { + let mut s = String::from("hello"); + let mut ref_s = &mut s; + + let mut binding = String::from("world"); + ref_s = &mut binding; //~ ERROR temporary value dropped while borrowed [E0716] + + print!("r1 = {}", ref_s); + + let mut val: u8 = 5; + let mut s = Pin::new(&mut val); + let mut ref_s = &mut s; + + let mut val2: u8 = 10; + let mut binding = Pin::new(&mut val2); + ref_s = &mut binding; //~ ERROR temporary value dropped while borrowed [E0716] + + print!("r1 = {}", ref_s); +} diff --git a/tests/ui/nll/sugg-mut-for-binding-issue-137486.rs b/tests/ui/nll/sugg-mut-for-binding-issue-137486.rs new file mode 100644 index 0000000000000..8f7ea7561077d --- /dev/null +++ b/tests/ui/nll/sugg-mut-for-binding-issue-137486.rs @@ -0,0 +1,21 @@ +//@ run-rustfix +#![allow(unused_assignments)] + +use std::pin::Pin; +fn main() { + let mut s = String::from("hello"); + let mut ref_s = &mut s; + + ref_s = &mut String::from("world"); //~ ERROR temporary value dropped while borrowed [E0716] + + print!("r1 = {}", ref_s); + + let mut val: u8 = 5; + let mut s = Pin::new(&mut val); + let mut ref_s = &mut s; + + let mut val2: u8 = 10; + ref_s = &mut Pin::new(&mut val2); //~ ERROR temporary value dropped while borrowed [E0716] + + print!("r1 = {}", ref_s); +} diff --git a/tests/ui/nll/sugg-mut-for-binding-issue-137486.stderr b/tests/ui/nll/sugg-mut-for-binding-issue-137486.stderr new file mode 100644 index 0000000000000..8432725f60ad3 --- /dev/null +++ b/tests/ui/nll/sugg-mut-for-binding-issue-137486.stderr @@ -0,0 +1,37 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/sugg-mut-for-binding-issue-137486.rs:9:18 + | +LL | ref_s = &mut String::from("world"); + | ^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +LL | +LL | print!("r1 = {}", ref_s); + | ----- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let mut binding = String::from("world"); +LL ~ ref_s = &mut binding; + | + +error[E0716]: temporary value dropped while borrowed + --> $DIR/sugg-mut-for-binding-issue-137486.rs:18:18 + | +LL | ref_s = &mut Pin::new(&mut val2); + | ^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +LL | +LL | print!("r1 = {}", ref_s); + | ----- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let mut binding = Pin::new(&mut val2); +LL ~ ref_s = &mut binding; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0716`. From 6a5bad36a87a6f3420839f95175498ae413c817a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 2 Jun 2025 19:03:55 +0300 Subject: [PATCH 02/11] resolve: Tweak `private_macro_use` lint to be compatible with upcoming macro prelude changes --- .../rustc_resolve/src/build_reduced_graph.rs | 28 +++++++++---------- compiler/rustc_resolve/src/imports.rs | 4 ++- compiler/rustc_resolve/src/lib.rs | 26 +++++++++++++---- 3 files changed, 36 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index c30ed781f35f3..650a827ba5644 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1098,22 +1098,20 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.potentially_unused_imports.push(import); module.for_each_child(self, |this, ident, ns, binding| { if ns == MacroNS { - let imported_binding = - if this.r.is_accessible_from(binding.vis, this.parent_scope.module) { - this.r.import(binding, import) - } else if !this.r.is_builtin_macro(binding.res()) - && !this.r.macro_use_prelude.contains_key(&ident.name) - { - // - `!r.is_builtin_macro(res)` excluding the built-in macros such as `Debug` or `Hash`. - // - `!r.macro_use_prelude.contains_key(name)` excluding macros defined in other extern - // crates such as `std`. - // FIXME: This branch should eventually be removed. - let import = macro_use_import(this, span, true); - this.r.import(binding, import) - } else { + let import = if this.r.is_accessible_from(binding.vis, this.parent_scope.module) + { + import + } else { + // FIXME: This branch is used for reporting the `private_macro_use` lint + // and should eventually be removed. + if this.r.macro_use_prelude.contains_key(&ident.name) { + // Do not override already existing entries with compatibility entries. return; - }; - this.add_macro_use_binding(ident.name, imported_binding, span, allow_shadowing); + } + macro_use_import(this, span, true) + }; + let import_binding = this.r.import(binding, import); + this.add_macro_use_binding(ident.name, import_binding, span, allow_shadowing); } }); } else { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 816efd0d5fa2d..e989209e177a3 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -133,7 +133,9 @@ impl<'ra> std::fmt::Debug for ImportKind<'ra> { .field("target", target) .field("id", id) .finish(), - MacroUse { .. } => f.debug_struct("MacroUse").finish(), + MacroUse { warn_private } => { + f.debug_struct("MacroUse").field("warn_private", warn_private).finish() + } MacroExport => f.debug_struct("MacroExport").finish(), } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 9ba70abd4d933..ea8715b82547f 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1934,12 +1934,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } if let NameBindingKind::Import { import, binding } = used_binding.kind { if let ImportKind::MacroUse { warn_private: true } = import.kind { - self.lint_buffer().buffer_lint( - PRIVATE_MACRO_USE, - import.root_id, - ident.span, - BuiltinLintDiag::MacroIsPrivate(ident), - ); + // Do not report the lint if the macro name resolves in stdlib prelude + // even without the problematic `macro_use` import. + let found_in_stdlib_prelude = self.prelude.is_some_and(|prelude| { + self.maybe_resolve_ident_in_module( + ModuleOrUniformRoot::Module(prelude), + ident, + MacroNS, + &ParentScope::module(self.empty_module, self), + None, + ) + .is_ok() + }); + if !found_in_stdlib_prelude { + self.lint_buffer().buffer_lint( + PRIVATE_MACRO_USE, + import.root_id, + ident.span, + BuiltinLintDiag::MacroIsPrivate(ident), + ); + } } // Avoid marking `extern crate` items that refer to a name from extern prelude, // but not introduce it, as used if they are accessed from lexical scope. From 585a40963ea59808e74803f8610659a505b145e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 4 Jun 2025 18:18:06 +0000 Subject: [PATCH 03/11] Detect method not being present that is present in other tuple types When a method is not present because of a trait bound not being met, and that trait bound is on a tuple, we check if making the tuple have no borrowed types makes the method to be found and highlight it if it does. This is a common problem for Bevy in particular and ORMs in general. --- .../rustc_hir_typeck/src/method/suggest.rs | 123 +++++++++++++++++- tests/ui/methods/missing-bound-on-tuple.rs | 39 ++++++ .../ui/methods/missing-bound-on-tuple.stderr | 58 +++++++++ 3 files changed, 218 insertions(+), 2 deletions(-) create mode 100644 tests/ui/methods/missing-bound-on-tuple.rs create mode 100644 tests/ui/methods/missing-bound-on-tuple.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 7b71f5de7569f..54e0a42e79944 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -14,7 +14,9 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; -use rustc_errors::{Applicability, Diag, MultiSpan, StashKey, pluralize, struct_span_code_err}; +use rustc_errors::{ + Applicability, Diag, DiagStyledString, MultiSpan, StashKey, pluralize, struct_span_code_err, +}; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; @@ -1569,7 +1571,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params || suggested_derive { + if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() + || restrict_type_params + || suggested_derive + || self.lookup_alternative_tuple_impls(&mut err, &unsatisfied_predicates) + { } else { self.suggest_traits_to_import( &mut err, @@ -1744,6 +1750,119 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit() } + /// If the predicate failure is caused by an unmet bound on a tuple, recheck if the bound would + /// succeed if all the types on the tuple had no borrows. This is a common problem for libraries + /// like Bevy and ORMs, which rely heavily on traits being implemented on tuples. + fn lookup_alternative_tuple_impls( + &self, + err: &mut Diag<'_>, + unsatisfied_predicates: &[( + ty::Predicate<'tcx>, + Option>, + Option>, + )], + ) -> bool { + let mut found_tuple = false; + for (pred, root, _ob) in unsatisfied_predicates { + let mut preds = vec![pred]; + if let Some(root) = root { + // We will look at both the current predicate and the root predicate that caused it + // to be needed. If calling something like `<(A, &B)>::default()`, then `pred` is + // `&B: Default` and `root` is `(A, &B): Default`, which is the one we are checking + // for further down, so we check both. + preds.push(root); + } + for pred in preds { + if let Some(clause) = pred.as_clause() + && let Some(clause) = clause.as_trait_clause() + && let ty = clause.self_ty().skip_binder() + && let ty::Tuple(types) = ty.kind() + { + let path = clause.skip_binder().trait_ref.print_only_trait_path(); + let def_id = clause.def_id(); + let ty = Ty::new_tup( + self.tcx, + self.tcx.mk_type_list_from_iter(types.iter().map(|ty| ty.peel_refs())), + ); + let args = ty::GenericArgs::for_item(self.tcx, def_id, |param, _| { + if param.index == 0 { + ty.into() + } else { + self.infcx.var_for_def(DUMMY_SP, param) + } + }); + if self + .infcx + .type_implements_trait(def_id, args, self.param_env) + .must_apply_modulo_regions() + { + // "`Trait` is implemented for `(A, B)` but not for `(A, &B)`" + let mut msg = DiagStyledString::normal(format!("`{path}` ")); + msg.push_highlighted("is"); + msg.push_normal(" implemented for `("); + let len = types.len(); + for (i, t) in types.iter().enumerate() { + msg.push( + format!("{}", with_forced_trimmed_paths!(t.peel_refs())), + t.peel_refs() != t, + ); + if i < len - 1 { + msg.push_normal(", "); + } + } + msg.push_normal(")` but "); + msg.push_highlighted("not"); + msg.push_normal(" for `("); + for (i, t) in types.iter().enumerate() { + msg.push( + format!("{}", with_forced_trimmed_paths!(t)), + t.peel_refs() != t, + ); + if i < len - 1 { + msg.push_normal(", "); + } + } + msg.push_normal(")`"); + + // Find the span corresponding to the impl that was found to point at it. + if let Some(impl_span) = self + .tcx + .all_impls(def_id) + .filter(|&impl_def_id| { + let header = self.tcx.impl_trait_header(impl_def_id).unwrap(); + let trait_ref = header.trait_ref.instantiate( + self.tcx, + self.infcx.fresh_args_for_item(DUMMY_SP, impl_def_id), + ); + + let value = ty::fold_regions(self.tcx, ty, |_, _| { + self.tcx.lifetimes.re_erased + }); + // FIXME: Don't bother dealing with non-lifetime binders here... + if value.has_escaping_bound_vars() { + return false; + } + self.infcx.can_eq(ty::ParamEnv::empty(), trait_ref.self_ty(), value) + && header.polarity == ty::ImplPolarity::Positive + }) + .map(|impl_def_id| self.tcx.def_span(impl_def_id)) + .next() + { + err.highlighted_span_note(impl_span, msg.0); + } else { + err.highlighted_note(msg.0); + } + found_tuple = true; + } + // If `pred` was already on the tuple, we don't need to look at the root + // obligation too. + break; + } + } + } + found_tuple + } + /// If an appropriate error source is not found, check method chain for possible candidates fn lookup_segments_chain_for_no_match_method( &self, diff --git a/tests/ui/methods/missing-bound-on-tuple.rs b/tests/ui/methods/missing-bound-on-tuple.rs new file mode 100644 index 0000000000000..25deabf59267b --- /dev/null +++ b/tests/ui/methods/missing-bound-on-tuple.rs @@ -0,0 +1,39 @@ +trait WorksOnDefault { + fn do_something() {} +} + +impl WorksOnDefault for T {} +//~^ NOTE the following trait bounds were not satisfied +//~| NOTE unsatisfied trait bound introduced here + +trait Foo {} + +trait WorksOnFoo { + fn do_be_do() {} +} + +impl WorksOnFoo for T {} +//~^ NOTE the following trait bounds were not satisfied +//~| NOTE unsatisfied trait bound introduced here + +impl Foo for (A, B, C) {} +//~^ NOTE `Foo` is implemented for `(i32, u32, String)` +impl Foo for i32 {} +impl Foo for &i32 {} +impl Foo for u32 {} +impl Foo for String {} + +fn main() { + let _success = <(i32, u32, String)>::do_something(); + let _failure = <(i32, &u32, String)>::do_something(); //~ ERROR E0599 + //~^ NOTE `Default` is implemented for `(i32, u32, String)` + //~| NOTE function or associated item cannot be called on + let _success = <(i32, u32, String)>::do_be_do(); + let _failure = <(i32, &u32, String)>::do_be_do(); //~ ERROR E0599 + //~^ NOTE function or associated item cannot be called on + let _success = <(i32, u32, String)>::default(); + let _failure = <(i32, &u32, String)>::default(); //~ ERROR E0599 + //~^ NOTE `Default` is implemented for `(i32, u32, String)` + //~| NOTE function or associated item cannot be called on + //~| NOTE the following trait bounds were not satisfied +} diff --git a/tests/ui/methods/missing-bound-on-tuple.stderr b/tests/ui/methods/missing-bound-on-tuple.stderr new file mode 100644 index 0000000000000..f3e0897e5e645 --- /dev/null +++ b/tests/ui/methods/missing-bound-on-tuple.stderr @@ -0,0 +1,58 @@ +error[E0599]: the function or associated item `do_something` exists for tuple `(i32, &u32, String)`, but its trait bounds were not satisfied + --> $DIR/missing-bound-on-tuple.rs:28:43 + | +LL | let _failure = <(i32, &u32, String)>::do_something(); + | ^^^^^^^^^^^^ function or associated item cannot be called on `(i32, &u32, String)` due to unsatisfied trait bounds + | +note: the following trait bounds were not satisfied: + `&(i32, &u32, String): Default` + `&mut (i32, &u32, String): Default` + `(i32, &u32, String): Default` + --> $DIR/missing-bound-on-tuple.rs:5:9 + | +LL | impl WorksOnDefault for T {} + | ^^^^^^^ -------------- - + | | + | unsatisfied trait bound introduced here +note: `Default` is implemented for `(i32, u32, String)` but not for `(i32, &u32, String)` + --> $SRC_DIR/core/src/tuple.rs:LL:COL + = note: this error originates in the macro `tuple_impls` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0599]: the function or associated item `do_be_do` exists for tuple `(i32, &u32, String)`, but its trait bounds were not satisfied + --> $DIR/missing-bound-on-tuple.rs:32:43 + | +LL | let _failure = <(i32, &u32, String)>::do_be_do(); + | ^^^^^^^^ function or associated item cannot be called on `(i32, &u32, String)` due to unsatisfied trait bounds + | +note: the following trait bounds were not satisfied: + `&(i32, &u32, String): Foo` + `&mut (i32, &u32, String): Foo` + `(i32, &u32, String): Foo` + --> $DIR/missing-bound-on-tuple.rs:15:9 + | +LL | impl WorksOnFoo for T {} + | ^^^ ---------- - + | | + | unsatisfied trait bound introduced here +note: `Foo` is implemented for `(i32, u32, String)` but not for `(i32, &u32, String)` + --> $DIR/missing-bound-on-tuple.rs:19:1 + | +LL | impl Foo for (A, B, C) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: the function or associated item `default` exists for tuple `(i32, &u32, String)`, but its trait bounds were not satisfied + --> $DIR/missing-bound-on-tuple.rs:35:43 + | +LL | let _failure = <(i32, &u32, String)>::default(); + | ^^^^^^^ function or associated item cannot be called on `(i32, &u32, String)` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `&u32: Default` + which is required by `(i32, &u32, String): Default` +note: `Default` is implemented for `(i32, u32, String)` but not for `(i32, &u32, String)` + --> $SRC_DIR/core/src/tuple.rs:LL:COL + = note: this error originates in the macro `tuple_impls` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. From fafc0f249f8d6c2eabd2c75dca536f04ddead79f Mon Sep 17 00:00:00 2001 From: Urgau Date: Thu, 19 Dec 2024 22:07:05 +0100 Subject: [PATCH 04/11] Report the `unpredictable_function_pointer_comparisons` lint in macro --- compiler/rustc_lint/src/types.rs | 3 +- tests/ui/lint/fn-ptr-comparisons-some.rs | 2 +- tests/ui/lint/fn-ptr-comparisons-some.stderr | 13 ++++- tests/ui/lint/fn-ptr-comparisons-weird.rs | 22 +++++++++ tests/ui/lint/fn-ptr-comparisons-weird.stderr | 47 ++++++++++++++++--- tests/ui/lint/fn-ptr-comparisons.fixed | 2 - tests/ui/lint/fn-ptr-comparisons.rs | 2 - tests/ui/lint/fn-ptr-comparisons.stderr | 24 +++++----- 8 files changed, 90 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index fec23354c9122..aaba0c14b1ce4 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -196,7 +196,8 @@ declare_lint! { /// same address after being merged together. UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS, Warn, - "detects unpredictable function pointer comparisons" + "detects unpredictable function pointer comparisons", + report_in_external_macro } #[derive(Copy, Clone, Default)] diff --git a/tests/ui/lint/fn-ptr-comparisons-some.rs b/tests/ui/lint/fn-ptr-comparisons-some.rs index 152e16b9884ba..c6ddd759baa37 100644 --- a/tests/ui/lint/fn-ptr-comparisons-some.rs +++ b/tests/ui/lint/fn-ptr-comparisons-some.rs @@ -12,6 +12,6 @@ fn main() { let _ = Some::(func) == Some(func as unsafe extern "C" fn()); //~^ WARN function pointer comparisons - // Undecided as of https://github.com/rust-lang/rust/pull/134536 assert_eq!(Some::(func), Some(func as unsafe extern "C" fn())); + //~^ WARN function pointer comparisons } diff --git a/tests/ui/lint/fn-ptr-comparisons-some.stderr b/tests/ui/lint/fn-ptr-comparisons-some.stderr index eefad05b676de..522c4399bce1d 100644 --- a/tests/ui/lint/fn-ptr-comparisons-some.stderr +++ b/tests/ui/lint/fn-ptr-comparisons-some.stderr @@ -9,5 +9,16 @@ LL | let _ = Some::(func) == Some(func as unsafe extern "C" fn()); = note: for more information visit = note: `#[warn(unpredictable_function_pointer_comparisons)]` on by default -warning: 1 warning emitted +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons-some.rs:15:5 + | +LL | assert_eq!(Some::(func), Some(func as unsafe extern "C" fn())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit + = note: this warning originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 2 warnings emitted diff --git a/tests/ui/lint/fn-ptr-comparisons-weird.rs b/tests/ui/lint/fn-ptr-comparisons-weird.rs index 171fbfb87279d..4d756cb49df0f 100644 --- a/tests/ui/lint/fn-ptr-comparisons-weird.rs +++ b/tests/ui/lint/fn-ptr-comparisons-weird.rs @@ -1,5 +1,23 @@ //@ check-pass +#[derive(PartialEq, Eq)] +struct A { + f: fn(), + //~^ WARN function pointer comparisons +} + +#[allow(unpredictable_function_pointer_comparisons)] +#[derive(PartialEq, Eq)] +struct AllowedAbove { + f: fn(), +} + +#[derive(PartialEq, Eq)] +#[allow(unpredictable_function_pointer_comparisons)] +struct AllowedBelow { + f: fn(), +} + fn main() { let f: fn() = main; let g: fn() = main; @@ -12,4 +30,8 @@ fn main() { //~^ WARN function pointer comparisons let _ = f < g; //~^ WARN function pointer comparisons + let _ = assert_eq!(g, g); + //~^ WARN function pointer comparisons + let _ = assert_ne!(g, g); + //~^ WARN function pointer comparisons } diff --git a/tests/ui/lint/fn-ptr-comparisons-weird.stderr b/tests/ui/lint/fn-ptr-comparisons-weird.stderr index f237166392238..2014e519c2538 100644 --- a/tests/ui/lint/fn-ptr-comparisons-weird.stderr +++ b/tests/ui/lint/fn-ptr-comparisons-weird.stderr @@ -1,5 +1,19 @@ warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons-weird.rs:7:13 + --> $DIR/fn-ptr-comparisons-weird.rs:5:5 + | +LL | #[derive(PartialEq, Eq)] + | --------- in this derive macro expansion +LL | struct A { +LL | f: fn(), + | ^^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit + = note: `#[warn(unpredictable_function_pointer_comparisons)]` on by default + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons-weird.rs:25:13 | LL | let _ = f > g; | ^^^^^ @@ -7,10 +21,9 @@ LL | let _ = f > g; = note: the address of the same function can vary between different codegen units = note: furthermore, different functions could have the same address after being merged together = note: for more information visit - = note: `#[warn(unpredictable_function_pointer_comparisons)]` on by default warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons-weird.rs:9:13 + --> $DIR/fn-ptr-comparisons-weird.rs:27:13 | LL | let _ = f >= g; | ^^^^^^ @@ -20,7 +33,7 @@ LL | let _ = f >= g; = note: for more information visit warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons-weird.rs:11:13 + --> $DIR/fn-ptr-comparisons-weird.rs:29:13 | LL | let _ = f <= g; | ^^^^^^ @@ -30,7 +43,7 @@ LL | let _ = f <= g; = note: for more information visit warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons-weird.rs:13:13 + --> $DIR/fn-ptr-comparisons-weird.rs:31:13 | LL | let _ = f < g; | ^^^^^ @@ -39,5 +52,27 @@ LL | let _ = f < g; = note: furthermore, different functions could have the same address after being merged together = note: for more information visit -warning: 4 warnings emitted +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons-weird.rs:33:13 + | +LL | let _ = assert_eq!(g, g); + | ^^^^^^^^^^^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit + = note: this warning originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons-weird.rs:35:13 + | +LL | let _ = assert_ne!(g, g); + | ^^^^^^^^^^^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit + = note: this warning originates in the macro `assert_ne` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 7 warnings emitted diff --git a/tests/ui/lint/fn-ptr-comparisons.fixed b/tests/ui/lint/fn-ptr-comparisons.fixed index 22f16177a0446..41cdb7bf6aea0 100644 --- a/tests/ui/lint/fn-ptr-comparisons.fixed +++ b/tests/ui/lint/fn-ptr-comparisons.fixed @@ -11,7 +11,6 @@ extern "C" fn c() {} extern "C" fn args(_a: i32) -> i32 { 0 } -#[derive(PartialEq, Eq)] struct A { f: fn(), } @@ -52,7 +51,6 @@ fn main() { let _ = std::ptr::fn_addr_eq(t, test as unsafe extern "C" fn()); //~^ WARN function pointer comparisons - let _ = a1 == a2; // should not warn let _ = std::ptr::fn_addr_eq(a1.f, a2.f); //~^ WARN function pointer comparisons } diff --git a/tests/ui/lint/fn-ptr-comparisons.rs b/tests/ui/lint/fn-ptr-comparisons.rs index 90a8ab5c926b6..c2601d6adfba4 100644 --- a/tests/ui/lint/fn-ptr-comparisons.rs +++ b/tests/ui/lint/fn-ptr-comparisons.rs @@ -11,7 +11,6 @@ extern "C" fn c() {} extern "C" fn args(_a: i32) -> i32 { 0 } -#[derive(PartialEq, Eq)] struct A { f: fn(), } @@ -52,7 +51,6 @@ fn main() { let _ = t == test; //~^ WARN function pointer comparisons - let _ = a1 == a2; // should not warn let _ = a1.f == a2.f; //~^ WARN function pointer comparisons } diff --git a/tests/ui/lint/fn-ptr-comparisons.stderr b/tests/ui/lint/fn-ptr-comparisons.stderr index e699332389864..5913acca16bbc 100644 --- a/tests/ui/lint/fn-ptr-comparisons.stderr +++ b/tests/ui/lint/fn-ptr-comparisons.stderr @@ -1,5 +1,5 @@ warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons.rs:26:13 + --> $DIR/fn-ptr-comparisons.rs:25:13 | LL | let _ = f == a; | ^^^^^^ @@ -15,7 +15,7 @@ LL + let _ = std::ptr::fn_addr_eq(f, a as fn()); | warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons.rs:28:13 + --> $DIR/fn-ptr-comparisons.rs:27:13 | LL | let _ = f != a; | ^^^^^^ @@ -30,7 +30,7 @@ LL + let _ = !std::ptr::fn_addr_eq(f, a as fn()); | warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons.rs:30:13 + --> $DIR/fn-ptr-comparisons.rs:29:13 | LL | let _ = f == g; | ^^^^^^ @@ -45,7 +45,7 @@ LL + let _ = std::ptr::fn_addr_eq(f, g); | warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons.rs:32:13 + --> $DIR/fn-ptr-comparisons.rs:31:13 | LL | let _ = f == f; | ^^^^^^ @@ -60,7 +60,7 @@ LL + let _ = std::ptr::fn_addr_eq(f, f); | warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons.rs:34:13 + --> $DIR/fn-ptr-comparisons.rs:33:13 | LL | let _ = g == g; | ^^^^^^ @@ -75,7 +75,7 @@ LL + let _ = std::ptr::fn_addr_eq(g, g); | warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons.rs:36:13 + --> $DIR/fn-ptr-comparisons.rs:35:13 | LL | let _ = g == g; | ^^^^^^ @@ -90,7 +90,7 @@ LL + let _ = std::ptr::fn_addr_eq(g, g); | warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons.rs:38:13 + --> $DIR/fn-ptr-comparisons.rs:37:13 | LL | let _ = &g == &g; | ^^^^^^^^ @@ -105,7 +105,7 @@ LL + let _ = std::ptr::fn_addr_eq(g, g); | warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons.rs:40:13 + --> $DIR/fn-ptr-comparisons.rs:39:13 | LL | let _ = a as fn() == g; | ^^^^^^^^^^^^^^ @@ -120,7 +120,7 @@ LL + let _ = std::ptr::fn_addr_eq(a as fn(), g); | warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons.rs:44:13 + --> $DIR/fn-ptr-comparisons.rs:43:13 | LL | let _ = cfn == c; | ^^^^^^^^ @@ -135,7 +135,7 @@ LL + let _ = std::ptr::fn_addr_eq(cfn, c as extern "C" fn()); | warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons.rs:48:13 + --> $DIR/fn-ptr-comparisons.rs:47:13 | LL | let _ = argsfn == args; | ^^^^^^^^^^^^^^ @@ -150,7 +150,7 @@ LL + let _ = std::ptr::fn_addr_eq(argsfn, args as extern "C" fn(i32) -> i32) | warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons.rs:52:13 + --> $DIR/fn-ptr-comparisons.rs:51:13 | LL | let _ = t == test; | ^^^^^^^^^ @@ -165,7 +165,7 @@ LL + let _ = std::ptr::fn_addr_eq(t, test as unsafe extern "C" fn()); | warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - --> $DIR/fn-ptr-comparisons.rs:56:13 + --> $DIR/fn-ptr-comparisons.rs:54:13 | LL | let _ = a1.f == a2.f; | ^^^^^^^^^^^^ From 14b3e630129a3c89020e79bf7f0f1e60f6a6e93a Mon Sep 17 00:00:00 2001 From: Urgau Date: Thu, 19 Dec 2024 22:33:49 +0100 Subject: [PATCH 05/11] Allow `unpredictable_function_pointer_comparisons` lint in more places --- library/core/src/task/wake.rs | 1 + tests/ui/issues/issue-28561.rs | 1 + tests/ui/mir/mir_refs_correct.rs | 2 ++ tests/ui/nullable-pointer-iotareduction.rs | 2 ++ 4 files changed, 6 insertions(+) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 9b8fefe42af60..bb7efe582f7a3 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -104,6 +104,7 @@ impl RawWaker { /// synchronization. This is because [`LocalWaker`] is not thread safe itself, so it cannot /// be sent across threads. #[stable(feature = "futures_api", since = "1.36.0")] +#[allow(unpredictable_function_pointer_comparisons)] #[derive(PartialEq, Copy, Clone, Debug)] pub struct RawWakerVTable { /// This function will be called when the [`RawWaker`] gets cloned, e.g. when diff --git a/tests/ui/issues/issue-28561.rs b/tests/ui/issues/issue-28561.rs index f9b0ceb22fc66..642b2193a4f9b 100644 --- a/tests/ui/issues/issue-28561.rs +++ b/tests/ui/issues/issue-28561.rs @@ -37,6 +37,7 @@ struct Array { } #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[allow(unpredictable_function_pointer_comparisons)] struct Fn { f00: fn(), f01: fn(A), diff --git a/tests/ui/mir/mir_refs_correct.rs b/tests/ui/mir/mir_refs_correct.rs index fc23c8c3631eb..f1832d90a0f56 100644 --- a/tests/ui/mir/mir_refs_correct.rs +++ b/tests/ui/mir/mir_refs_correct.rs @@ -1,6 +1,8 @@ //@ run-pass //@ aux-build:mir_external_refs.rs +#![allow(unpredictable_function_pointer_comparisons)] + extern crate mir_external_refs as ext; struct S(#[allow(dead_code)] u8); diff --git a/tests/ui/nullable-pointer-iotareduction.rs b/tests/ui/nullable-pointer-iotareduction.rs index fa837dab51b6c..1b73164c9fc74 100644 --- a/tests/ui/nullable-pointer-iotareduction.rs +++ b/tests/ui/nullable-pointer-iotareduction.rs @@ -8,6 +8,8 @@ // trying to get assert failure messages that at least identify which case // failed. +#![allow(unpredictable_function_pointer_comparisons)] + enum E { Thing(isize, T), #[allow(dead_code)] Nothing((), ((), ()), [i8; 0]) } impl E { fn is_none(&self) -> bool { From 8584c7c6a4441ee5d1500bc80816ce6c1eb026c9 Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Thu, 12 Jun 2025 16:29:09 +0900 Subject: [PATCH 06/11] chore(doctest): Remove redundant blank lines --- library/core/src/num/int_macros.rs | 1 - library/core/src/num/mod.rs | 1 - library/core/src/slice/ascii.rs | 1 - 3 files changed, 3 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 65560f63c1859..3a7bc902f93cd 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -239,7 +239,6 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// #[doc = concat!("let n = -1", stringify!($SelfT), ";")] /// #[doc = concat!("assert_eq!(n.cast_unsigned(), ", stringify!($UnsignedT), "::MAX);")] diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 5c73bddbef2d1..ab2fcff61cd12 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -1053,7 +1053,6 @@ impl u8 { /// # Examples /// /// ``` - /// /// assert_eq!("0", b'0'.escape_ascii().to_string()); /// assert_eq!("\\t", b'\t'.escape_ascii().to_string()); /// assert_eq!("\\r", b'\r'.escape_ascii().to_string()); diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index d91f8bba548fc..b4d9a1b1ca4fd 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -128,7 +128,6 @@ impl [u8] { /// # Examples /// /// ``` - /// /// let s = b"0\t\r\n'\"\\\x9d"; /// let escaped = s.escape_ascii().to_string(); /// assert_eq!(escaped, "0\\t\\r\\n\\'\\\"\\\\\\x9d"); From 975741c29417034e9026e53fba16f3b7d5c5721b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Thu, 12 Jun 2025 11:59:42 +0200 Subject: [PATCH 07/11] add test for dead code caused by enum variants shadowing an associated function --- .../ui/enum/dead-code-associated-function.rs | 20 +++++++++++++++++++ .../enum/dead-code-associated-function.stderr | 20 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/ui/enum/dead-code-associated-function.rs create mode 100644 tests/ui/enum/dead-code-associated-function.stderr diff --git a/tests/ui/enum/dead-code-associated-function.rs b/tests/ui/enum/dead-code-associated-function.rs new file mode 100644 index 0000000000000..d172ceb41dde4 --- /dev/null +++ b/tests/ui/enum/dead-code-associated-function.rs @@ -0,0 +1,20 @@ +//@ check-pass +#![warn(dead_code)] + +enum E { + F(), + C(), +} + +impl E { + #[expect(non_snake_case)] + fn F() {} + //~^ WARN: associated items `F` and `C` are never used + + const C: () = (); +} + +fn main() { + let _: E = E::F(); + let _: E = E::C(); +} diff --git a/tests/ui/enum/dead-code-associated-function.stderr b/tests/ui/enum/dead-code-associated-function.stderr new file mode 100644 index 0000000000000..df968783c27af --- /dev/null +++ b/tests/ui/enum/dead-code-associated-function.stderr @@ -0,0 +1,20 @@ +warning: associated items `F` and `C` are never used + --> $DIR/dead-code-associated-function.rs:11:8 + | +LL | impl E { + | ------ associated items in this implementation +LL | #[expect(non_snake_case)] +LL | fn F() {} + | ^ +... +LL | const C: () = (); + | ^ + | +note: the lint level is defined here + --> $DIR/dead-code-associated-function.rs:2:9 + | +LL | #![warn(dead_code)] + | ^^^^^^^^^ + +warning: 1 warning emitted + From 2e7e52e07cec3adb2b14ce17faffe039216ed9d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Thu, 12 Jun 2025 10:21:30 +0200 Subject: [PATCH 08/11] detect when variants have the same name as an associated function --- compiler/rustc_passes/messages.ftl | 3 ++ compiler/rustc_passes/src/dead.rs | 30 ++++++++++++++++++- compiler/rustc_passes/src/errors.rs | 12 ++++++++ .../enum/dead-code-associated-function.stderr | 10 +++++++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index a4ef065ea2c83..81c7b42b105b5 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -290,6 +290,9 @@ passes_duplicate_lang_item_crate_depends = .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path} .second_definition_path = second definition in `{$crate_name}` loaded from {$path} +passes_enum_variant_same_name = + it is impossible to refer to the {$descr} `{$dead_name}` because it is shadowed by this enum variant with the same name + passes_export_name = attribute should be applied to a free function, impl method or static .label = not a free function, impl method or static diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index e597c819a3aae..4257d8e8d16bd 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -14,7 +14,7 @@ use rustc_errors::MultiSpan; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, Node, PatKind, QPath, TyKind}; +use rustc_hir::{self as hir, ImplItem, ImplItemKind, Node, PatKind, QPath, TyKind}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; @@ -936,7 +936,9 @@ enum ShouldWarnAboutField { #[derive(Debug, Copy, Clone, PartialEq, Eq)] enum ReportOn { + /// Report on something that hasn't got a proper name to refer to TupleField, + /// Report on something that has got a name, which could be a field but also a method NamedField, } @@ -1061,6 +1063,31 @@ impl<'tcx> DeadVisitor<'tcx> { None }; + let enum_variants_with_same_name = dead_codes + .iter() + .filter_map(|dead_item| { + if let Node::ImplItem(ImplItem { + kind: ImplItemKind::Fn(..) | ImplItemKind::Const(..), + .. + }) = tcx.hir_node_by_def_id(dead_item.def_id) + && let Some(impl_did) = tcx.opt_parent(dead_item.def_id.to_def_id()) + && let DefKind::Impl { of_trait: false } = tcx.def_kind(impl_did) + && let ty::Adt(maybe_enum, _) = tcx.type_of(impl_did).skip_binder().kind() + && maybe_enum.is_enum() + && let Some(variant) = + maybe_enum.variants().iter().find(|i| i.name == dead_item.name) + { + Some(crate::errors::EnumVariantSameName { + descr: tcx.def_descr(dead_item.def_id.to_def_id()), + dead_name: dead_item.name, + variant_span: tcx.def_span(variant.def_id), + }) + } else { + None + } + }) + .collect(); + let diag = match report_on { ReportOn::TupleField => { let tuple_fields = if let Some(parent_id) = parent_item @@ -1114,6 +1141,7 @@ impl<'tcx> DeadVisitor<'tcx> { name_list, parent_info, ignored_derived_impls, + enum_variants_with_same_name, }, }; diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 74ce92624bd49..74c89f0c698b5 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1478,6 +1478,9 @@ pub(crate) enum MultipleDeadCodes<'tcx> { participle: &'tcx str, name_list: DiagSymbolList, #[subdiagnostic] + // only on DeadCodes since it's never a problem for tuple struct fields + enum_variants_with_same_name: Vec>, + #[subdiagnostic] parent_info: Option>, #[subdiagnostic] ignored_derived_impls: Option, @@ -1498,6 +1501,15 @@ pub(crate) enum MultipleDeadCodes<'tcx> { }, } +#[derive(Subdiagnostic)] +#[note(passes_enum_variant_same_name)] +pub(crate) struct EnumVariantSameName<'tcx> { + #[primary_span] + pub variant_span: Span, + pub dead_name: Symbol, + pub descr: &'tcx str, +} + #[derive(Subdiagnostic)] #[label(passes_parent_info)] pub(crate) struct ParentInfo<'tcx> { diff --git a/tests/ui/enum/dead-code-associated-function.stderr b/tests/ui/enum/dead-code-associated-function.stderr index df968783c27af..e3c1a4c81a491 100644 --- a/tests/ui/enum/dead-code-associated-function.stderr +++ b/tests/ui/enum/dead-code-associated-function.stderr @@ -10,6 +10,16 @@ LL | fn F() {} LL | const C: () = (); | ^ | +note: it is impossible to refer to the associated function `F` because it is shadowed by this enum variant with the same name + --> $DIR/dead-code-associated-function.rs:5:5 + | +LL | F(), + | ^ +note: it is impossible to refer to the associated constant `C` because it is shadowed by this enum variant with the same name + --> $DIR/dead-code-associated-function.rs:6:5 + | +LL | C(), + | ^ note: the lint level is defined here --> $DIR/dead-code-associated-function.rs:2:9 | From 7a0d0de0e171e58e479bb3ed8923e37e78b728f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 12 Jun 2025 12:34:22 +0200 Subject: [PATCH 09/11] Remove bootstrap adhoc group It corresponds 1:1 to the bootstrap team, and with the review preferences we shouldn't need it. --- triagebot.toml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 52d18d2ca4b25..739685e718a9e 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1240,13 +1240,6 @@ libs = [ "@thomcc", "@ibraheemdev", ] -bootstrap = [ - "@Mark-Simulacrum", - "@albertlarsan68", - "@kobzol", - "@jieyouxu", - "@clubby789", -] infra-ci = [ "@Mark-Simulacrum", "@Kobzol", From c871bf196f707c68a3c9765df9a429bfe05ddb08 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Thu, 12 Jun 2025 13:06:01 +0200 Subject: [PATCH 10/11] Add myself (WaffleLapkin) to review rotation --- triagebot.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 52d18d2ca4b25..4cf42b34ff958 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1229,6 +1229,7 @@ compiler = [ "@oli-obk", "@petrochenkov", "@SparrowLii", + "@WaffleLapkin", "@wesleywiser", ] libs = [ @@ -1266,6 +1267,7 @@ codegen = [ "@dianqk", "@saethlin", "@workingjubilee", + "@WaffleLapkin", ] query-system = [ "@oli-obk", From 488ebeecbea225606dccb610dea216a4bbdcb69c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 12 Jun 2025 15:03:34 +0000 Subject: [PATCH 11/11] Remove lower_arg_ty as all callers were passing `None` --- compiler/rustc_hir_analysis/src/collect.rs | 2 +- compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 10 ---------- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 2 +- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e1df0d60452d6..6e22ac5a28a85 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -494,7 +494,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { // Only visit the type looking for `_` if we didn't fix the type above visitor.visit_ty_unambig(a); - self.lowerer().lower_arg_ty(a, None) + self.lowerer().lower_ty(a) }) .collect(); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 4deb47dfff8ce..bf407cbaccb5a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2708,16 +2708,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - pub fn lower_arg_ty(&self, ty: &hir::Ty<'tcx>, expected_ty: Option>) -> Ty<'tcx> { - match ty.kind { - hir::TyKind::Infer(()) if let Some(expected_ty) = expected_ty => { - self.record_ty(ty.hir_id, expected_ty, ty.span); - expected_ty - } - _ => self.lower_ty(ty), - } - } - /// Lower a function type from the HIR to our internal notion of a function signature. #[instrument(level = "debug", skip(self, hir_id, safety, abi, decl, generics, hir_ty), ret)] pub fn lower_fn_ty( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 393556928af89..e979798a40294 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -382,7 +382,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { _hir_id: rustc_hir::HirId, _hir_ty: Option<&hir::Ty<'_>>, ) -> (Vec>, Ty<'tcx>) { - let input_tys = decl.inputs.iter().map(|a| self.lowerer().lower_arg_ty(a, None)).collect(); + let input_tys = decl.inputs.iter().map(|a| self.lowerer().lower_ty(a)).collect(); let output_ty = match decl.output { hir::FnRetTy::Return(output) => self.lowerer().lower_ty(output),