Skip to content

Rollup of 9 pull requests #142438

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Jun 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d5d4cec
Suggest mut when possbile for temporary value dropped while borrowed
chenyukang Feb 24, 2025
6a5bad3
resolve: Tweak `private_macro_use` lint to be compatible with upcomin…
petrochenkov Jun 2, 2025
585a409
Detect method not being present that is present in other tuple types
estebank Jun 4, 2025
fafc0f2
Report the `unpredictable_function_pointer_comparisons` lint in macro
Urgau Dec 19, 2024
14b3e63
Allow `unpredictable_function_pointer_comparisons` lint in more places
Urgau Dec 19, 2024
8584c7c
chore(doctest): Remove redundant blank lines
sorairolake Jun 12, 2025
975741c
add test for dead code caused by enum variants shadowing an associate…
jdonszelmann Jun 12, 2025
2e7e52e
detect when variants have the same name as an associated function
jdonszelmann Jun 12, 2025
7a0d0de
Remove bootstrap adhoc group
Kobzol Jun 12, 2025
c871bf1
Add myself (WaffleLapkin) to review rotation
WaffleLapkin Jun 12, 2025
488ebee
Remove lower_arg_ty as all callers were passing `None`
oli-obk Jun 12, 2025
ae76150
Rollup merge of #134536 - Urgau:fn-ptr-option, r=compiler-errors,trav…
matthiaskrgr Jun 12, 2025
bfd8abd
Rollup merge of #141069 - chenyukang:yukang-fix-137486-suggest-mut, r…
matthiaskrgr Jun 12, 2025
8b6d55e
Rollup merge of #141934 - petrochenkov:privmacuse, r=compiler-errors
matthiaskrgr Jun 12, 2025
c77191f
Rollup merge of #142034 - estebank:issue-141258, r=davidtwco
matthiaskrgr Jun 12, 2025
79ee8bc
Rollup merge of #142402 - sorairolake:remove-blank-line, r=workingjub…
matthiaskrgr Jun 12, 2025
7cd6944
Rollup merge of #142406 - jdonszelmann:dead-code-enum-variant, r=Waff…
matthiaskrgr Jun 12, 2025
fc010f8
Rollup merge of #142407 - Kobzol:remove-bootstrap-adhoc-group, r=davi…
matthiaskrgr Jun 12, 2025
379238f
Rollup merge of #142408 - WaffleLapkin:rotates-itself, r=WaffleLapkin
matthiaskrgr Jun 12, 2025
7309c10
Rollup merge of #142418 - oli-obk:lower_arg_ty, r=BoxyUwU,fmease
matthiaskrgr Jun 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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![
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
10 changes: 0 additions & 10 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2708,16 +2708,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}

pub fn lower_arg_ty(&self, ty: &hir::Ty<'tcx>, expected_ty: Option<Ty<'tcx>>) -> 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(
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
_hir_id: rustc_hir::HirId,
_hir_ty: Option<&hir::Ty<'_>>,
) -> (Vec<Ty<'tcx>>, 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),
Expand Down
123 changes: 121 additions & 2 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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<ty::Predicate<'tcx>>,
Option<ObligationCause<'tcx>>,
)],
) -> 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,
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 29 additions & 1 deletion compiler/rustc_passes/src/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1114,6 +1141,7 @@ impl<'tcx> DeadVisitor<'tcx> {
name_list,
parent_info,
ignored_derived_impls,
enum_variants_with_same_name,
},
};

Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<EnumVariantSameName<'tcx>>,
#[subdiagnostic]
parent_info: Option<ParentInfo<'tcx>>,
#[subdiagnostic]
ignored_derived_impls: Option<IgnoredDerivedImpls>,
Expand All @@ -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> {
Expand Down
28 changes: 13 additions & 15 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
}
}
Expand Down
26 changes: 20 additions & 6 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 0 additions & 1 deletion library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);")]
Expand Down
Loading