Skip to content

Commit bb3a3c5

Browse files
committed
Auto merge of #142438 - matthiaskrgr:rollup-u1jdnhz, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #134536 (Lint on fn pointers comparisons in external macros) - #141069 (Suggest mut when possbile for temporary value dropped while borrowed) - #141934 (resolve: Tweak `private_macro_use` lint to be compatible with upcoming macro prelude changes) - #142034 (Detect method not being present that is present in other tuple types) - #142402 (chore(doctest): Remove redundant blank lines) - #142406 (Note when enum variants shadow an associated function) - #142407 (Remove bootstrap adhoc group) - #142408 (Add myself (WaffleLapkin) to review rotation) - #142418 (Remove lower_arg_ty as all callers were passing `None`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 573a015 + 7309c10 commit bb3a3c5

35 files changed

+544
-75
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3229,8 +3229,20 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
32293229
Applicability::MaybeIncorrect,
32303230
);
32313231
}
3232+
3233+
let mutability = if matches!(borrow.kind(), BorrowKind::Mut { .. }) {
3234+
"mut "
3235+
} else {
3236+
""
3237+
};
3238+
32323239
if !is_format_arguments_item {
3233-
let addition = format!("let binding = {};\n{}", s, " ".repeat(p));
3240+
let addition = format!(
3241+
"let {}binding = {};\n{}",
3242+
mutability,
3243+
s,
3244+
" ".repeat(p)
3245+
);
32343246
err.multipart_suggestion_verbose(
32353247
msg,
32363248
vec![

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
494494

495495
// Only visit the type looking for `_` if we didn't fix the type above
496496
visitor.visit_ty_unambig(a);
497-
self.lowerer().lower_arg_ty(a, None)
497+
self.lowerer().lower_ty(a)
498498
})
499499
.collect();
500500

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2708,16 +2708,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
27082708
}
27092709
}
27102710

2711-
pub fn lower_arg_ty(&self, ty: &hir::Ty<'tcx>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> {
2712-
match ty.kind {
2713-
hir::TyKind::Infer(()) if let Some(expected_ty) = expected_ty => {
2714-
self.record_ty(ty.hir_id, expected_ty, ty.span);
2715-
expected_ty
2716-
}
2717-
_ => self.lower_ty(ty),
2718-
}
2719-
}
2720-
27212711
/// Lower a function type from the HIR to our internal notion of a function signature.
27222712
#[instrument(level = "debug", skip(self, hir_id, safety, abi, decl, generics, hir_ty), ret)]
27232713
pub fn lower_fn_ty(

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
382382
_hir_id: rustc_hir::HirId,
383383
_hir_ty: Option<&hir::Ty<'_>>,
384384
) -> (Vec<Ty<'tcx>>, Ty<'tcx>) {
385-
let input_tys = decl.inputs.iter().map(|a| self.lowerer().lower_arg_ty(a, None)).collect();
385+
let input_tys = decl.inputs.iter().map(|a| self.lowerer().lower_ty(a)).collect();
386386

387387
let output_ty = match decl.output {
388388
hir::FnRetTy::Return(output) => self.lowerer().lower_ty(output),

compiler/rustc_hir_typeck/src/method/suggest.rs

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
1414
use rustc_data_structures::sorted_map::SortedMap;
1515
use rustc_data_structures::unord::UnordSet;
1616
use rustc_errors::codes::*;
17-
use rustc_errors::{Applicability, Diag, MultiSpan, StashKey, pluralize, struct_span_code_err};
17+
use rustc_errors::{
18+
Applicability, Diag, DiagStyledString, MultiSpan, StashKey, pluralize, struct_span_code_err,
19+
};
1820
use rustc_hir::def::{CtorKind, DefKind, Res};
1921
use rustc_hir::def_id::DefId;
2022
use rustc_hir::intravisit::{self, Visitor};
@@ -1569,7 +1571,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15691571
);
15701572
}
15711573

1572-
if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params || suggested_derive {
1574+
if rcvr_ty.is_numeric() && rcvr_ty.is_fresh()
1575+
|| restrict_type_params
1576+
|| suggested_derive
1577+
|| self.lookup_alternative_tuple_impls(&mut err, &unsatisfied_predicates)
1578+
{
15731579
} else {
15741580
self.suggest_traits_to_import(
15751581
&mut err,
@@ -1744,6 +1750,119 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17441750
err.emit()
17451751
}
17461752

1753+
/// If the predicate failure is caused by an unmet bound on a tuple, recheck if the bound would
1754+
/// succeed if all the types on the tuple had no borrows. This is a common problem for libraries
1755+
/// like Bevy and ORMs, which rely heavily on traits being implemented on tuples.
1756+
fn lookup_alternative_tuple_impls(
1757+
&self,
1758+
err: &mut Diag<'_>,
1759+
unsatisfied_predicates: &[(
1760+
ty::Predicate<'tcx>,
1761+
Option<ty::Predicate<'tcx>>,
1762+
Option<ObligationCause<'tcx>>,
1763+
)],
1764+
) -> bool {
1765+
let mut found_tuple = false;
1766+
for (pred, root, _ob) in unsatisfied_predicates {
1767+
let mut preds = vec![pred];
1768+
if let Some(root) = root {
1769+
// We will look at both the current predicate and the root predicate that caused it
1770+
// to be needed. If calling something like `<(A, &B)>::default()`, then `pred` is
1771+
// `&B: Default` and `root` is `(A, &B): Default`, which is the one we are checking
1772+
// for further down, so we check both.
1773+
preds.push(root);
1774+
}
1775+
for pred in preds {
1776+
if let Some(clause) = pred.as_clause()
1777+
&& let Some(clause) = clause.as_trait_clause()
1778+
&& let ty = clause.self_ty().skip_binder()
1779+
&& let ty::Tuple(types) = ty.kind()
1780+
{
1781+
let path = clause.skip_binder().trait_ref.print_only_trait_path();
1782+
let def_id = clause.def_id();
1783+
let ty = Ty::new_tup(
1784+
self.tcx,
1785+
self.tcx.mk_type_list_from_iter(types.iter().map(|ty| ty.peel_refs())),
1786+
);
1787+
let args = ty::GenericArgs::for_item(self.tcx, def_id, |param, _| {
1788+
if param.index == 0 {
1789+
ty.into()
1790+
} else {
1791+
self.infcx.var_for_def(DUMMY_SP, param)
1792+
}
1793+
});
1794+
if self
1795+
.infcx
1796+
.type_implements_trait(def_id, args, self.param_env)
1797+
.must_apply_modulo_regions()
1798+
{
1799+
// "`Trait` is implemented for `(A, B)` but not for `(A, &B)`"
1800+
let mut msg = DiagStyledString::normal(format!("`{path}` "));
1801+
msg.push_highlighted("is");
1802+
msg.push_normal(" implemented for `(");
1803+
let len = types.len();
1804+
for (i, t) in types.iter().enumerate() {
1805+
msg.push(
1806+
format!("{}", with_forced_trimmed_paths!(t.peel_refs())),
1807+
t.peel_refs() != t,
1808+
);
1809+
if i < len - 1 {
1810+
msg.push_normal(", ");
1811+
}
1812+
}
1813+
msg.push_normal(")` but ");
1814+
msg.push_highlighted("not");
1815+
msg.push_normal(" for `(");
1816+
for (i, t) in types.iter().enumerate() {
1817+
msg.push(
1818+
format!("{}", with_forced_trimmed_paths!(t)),
1819+
t.peel_refs() != t,
1820+
);
1821+
if i < len - 1 {
1822+
msg.push_normal(", ");
1823+
}
1824+
}
1825+
msg.push_normal(")`");
1826+
1827+
// Find the span corresponding to the impl that was found to point at it.
1828+
if let Some(impl_span) = self
1829+
.tcx
1830+
.all_impls(def_id)
1831+
.filter(|&impl_def_id| {
1832+
let header = self.tcx.impl_trait_header(impl_def_id).unwrap();
1833+
let trait_ref = header.trait_ref.instantiate(
1834+
self.tcx,
1835+
self.infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
1836+
);
1837+
1838+
let value = ty::fold_regions(self.tcx, ty, |_, _| {
1839+
self.tcx.lifetimes.re_erased
1840+
});
1841+
// FIXME: Don't bother dealing with non-lifetime binders here...
1842+
if value.has_escaping_bound_vars() {
1843+
return false;
1844+
}
1845+
self.infcx.can_eq(ty::ParamEnv::empty(), trait_ref.self_ty(), value)
1846+
&& header.polarity == ty::ImplPolarity::Positive
1847+
})
1848+
.map(|impl_def_id| self.tcx.def_span(impl_def_id))
1849+
.next()
1850+
{
1851+
err.highlighted_span_note(impl_span, msg.0);
1852+
} else {
1853+
err.highlighted_note(msg.0);
1854+
}
1855+
found_tuple = true;
1856+
}
1857+
// If `pred` was already on the tuple, we don't need to look at the root
1858+
// obligation too.
1859+
break;
1860+
}
1861+
}
1862+
}
1863+
found_tuple
1864+
}
1865+
17471866
/// If an appropriate error source is not found, check method chain for possible candidates
17481867
fn lookup_segments_chain_for_no_match_method(
17491868
&self,

compiler/rustc_lint/src/types.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ declare_lint! {
196196
/// same address after being merged together.
197197
UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
198198
Warn,
199-
"detects unpredictable function pointer comparisons"
199+
"detects unpredictable function pointer comparisons",
200+
report_in_external_macro
200201
}
201202

202203
#[derive(Copy, Clone, Default)]

compiler/rustc_passes/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,9 @@ passes_duplicate_lang_item_crate_depends =
290290
.first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path}
291291
.second_definition_path = second definition in `{$crate_name}` loaded from {$path}
292292
293+
passes_enum_variant_same_name =
294+
it is impossible to refer to the {$descr} `{$dead_name}` because it is shadowed by this enum variant with the same name
295+
293296
passes_export_name =
294297
attribute should be applied to a free function, impl method or static
295298
.label = not a free function, impl method or static

compiler/rustc_passes/src/dead.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_errors::MultiSpan;
1414
use rustc_hir::def::{CtorOf, DefKind, Res};
1515
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
1616
use rustc_hir::intravisit::{self, Visitor};
17-
use rustc_hir::{self as hir, Node, PatKind, QPath, TyKind};
17+
use rustc_hir::{self as hir, ImplItem, ImplItemKind, Node, PatKind, QPath, TyKind};
1818
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1919
use rustc_middle::middle::privacy::Level;
2020
use rustc_middle::query::Providers;
@@ -936,7 +936,9 @@ enum ShouldWarnAboutField {
936936

937937
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
938938
enum ReportOn {
939+
/// Report on something that hasn't got a proper name to refer to
939940
TupleField,
941+
/// Report on something that has got a name, which could be a field but also a method
940942
NamedField,
941943
}
942944

@@ -1061,6 +1063,31 @@ impl<'tcx> DeadVisitor<'tcx> {
10611063
None
10621064
};
10631065

1066+
let enum_variants_with_same_name = dead_codes
1067+
.iter()
1068+
.filter_map(|dead_item| {
1069+
if let Node::ImplItem(ImplItem {
1070+
kind: ImplItemKind::Fn(..) | ImplItemKind::Const(..),
1071+
..
1072+
}) = tcx.hir_node_by_def_id(dead_item.def_id)
1073+
&& let Some(impl_did) = tcx.opt_parent(dead_item.def_id.to_def_id())
1074+
&& let DefKind::Impl { of_trait: false } = tcx.def_kind(impl_did)
1075+
&& let ty::Adt(maybe_enum, _) = tcx.type_of(impl_did).skip_binder().kind()
1076+
&& maybe_enum.is_enum()
1077+
&& let Some(variant) =
1078+
maybe_enum.variants().iter().find(|i| i.name == dead_item.name)
1079+
{
1080+
Some(crate::errors::EnumVariantSameName {
1081+
descr: tcx.def_descr(dead_item.def_id.to_def_id()),
1082+
dead_name: dead_item.name,
1083+
variant_span: tcx.def_span(variant.def_id),
1084+
})
1085+
} else {
1086+
None
1087+
}
1088+
})
1089+
.collect();
1090+
10641091
let diag = match report_on {
10651092
ReportOn::TupleField => {
10661093
let tuple_fields = if let Some(parent_id) = parent_item
@@ -1114,6 +1141,7 @@ impl<'tcx> DeadVisitor<'tcx> {
11141141
name_list,
11151142
parent_info,
11161143
ignored_derived_impls,
1144+
enum_variants_with_same_name,
11171145
},
11181146
};
11191147

compiler/rustc_passes/src/errors.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,9 @@ pub(crate) enum MultipleDeadCodes<'tcx> {
14781478
participle: &'tcx str,
14791479
name_list: DiagSymbolList,
14801480
#[subdiagnostic]
1481+
// only on DeadCodes since it's never a problem for tuple struct fields
1482+
enum_variants_with_same_name: Vec<EnumVariantSameName<'tcx>>,
1483+
#[subdiagnostic]
14811484
parent_info: Option<ParentInfo<'tcx>>,
14821485
#[subdiagnostic]
14831486
ignored_derived_impls: Option<IgnoredDerivedImpls>,
@@ -1498,6 +1501,15 @@ pub(crate) enum MultipleDeadCodes<'tcx> {
14981501
},
14991502
}
15001503

1504+
#[derive(Subdiagnostic)]
1505+
#[note(passes_enum_variant_same_name)]
1506+
pub(crate) struct EnumVariantSameName<'tcx> {
1507+
#[primary_span]
1508+
pub variant_span: Span,
1509+
pub dead_name: Symbol,
1510+
pub descr: &'tcx str,
1511+
}
1512+
15011513
#[derive(Subdiagnostic)]
15021514
#[label(passes_parent_info)]
15031515
pub(crate) struct ParentInfo<'tcx> {

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,22 +1098,20 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
10981098
self.r.potentially_unused_imports.push(import);
10991099
module.for_each_child(self, |this, ident, ns, binding| {
11001100
if ns == MacroNS {
1101-
let imported_binding =
1102-
if this.r.is_accessible_from(binding.vis, this.parent_scope.module) {
1103-
this.r.import(binding, import)
1104-
} else if !this.r.is_builtin_macro(binding.res())
1105-
&& !this.r.macro_use_prelude.contains_key(&ident.name)
1106-
{
1107-
// - `!r.is_builtin_macro(res)` excluding the built-in macros such as `Debug` or `Hash`.
1108-
// - `!r.macro_use_prelude.contains_key(name)` excluding macros defined in other extern
1109-
// crates such as `std`.
1110-
// FIXME: This branch should eventually be removed.
1111-
let import = macro_use_import(this, span, true);
1112-
this.r.import(binding, import)
1113-
} else {
1101+
let import = if this.r.is_accessible_from(binding.vis, this.parent_scope.module)
1102+
{
1103+
import
1104+
} else {
1105+
// FIXME: This branch is used for reporting the `private_macro_use` lint
1106+
// and should eventually be removed.
1107+
if this.r.macro_use_prelude.contains_key(&ident.name) {
1108+
// Do not override already existing entries with compatibility entries.
11141109
return;
1115-
};
1116-
this.add_macro_use_binding(ident.name, imported_binding, span, allow_shadowing);
1110+
}
1111+
macro_use_import(this, span, true)
1112+
};
1113+
let import_binding = this.r.import(binding, import);
1114+
this.add_macro_use_binding(ident.name, import_binding, span, allow_shadowing);
11171115
}
11181116
});
11191117
} else {

compiler/rustc_resolve/src/imports.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@ impl<'ra> std::fmt::Debug for ImportKind<'ra> {
133133
.field("target", target)
134134
.field("id", id)
135135
.finish(),
136-
MacroUse { .. } => f.debug_struct("MacroUse").finish(),
136+
MacroUse { warn_private } => {
137+
f.debug_struct("MacroUse").field("warn_private", warn_private).finish()
138+
}
137139
MacroExport => f.debug_struct("MacroExport").finish(),
138140
}
139141
}

compiler/rustc_resolve/src/lib.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,12 +1934,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
19341934
}
19351935
if let NameBindingKind::Import { import, binding } = used_binding.kind {
19361936
if let ImportKind::MacroUse { warn_private: true } = import.kind {
1937-
self.lint_buffer().buffer_lint(
1938-
PRIVATE_MACRO_USE,
1939-
import.root_id,
1940-
ident.span,
1941-
BuiltinLintDiag::MacroIsPrivate(ident),
1942-
);
1937+
// Do not report the lint if the macro name resolves in stdlib prelude
1938+
// even without the problematic `macro_use` import.
1939+
let found_in_stdlib_prelude = self.prelude.is_some_and(|prelude| {
1940+
self.maybe_resolve_ident_in_module(
1941+
ModuleOrUniformRoot::Module(prelude),
1942+
ident,
1943+
MacroNS,
1944+
&ParentScope::module(self.empty_module, self),
1945+
None,
1946+
)
1947+
.is_ok()
1948+
});
1949+
if !found_in_stdlib_prelude {
1950+
self.lint_buffer().buffer_lint(
1951+
PRIVATE_MACRO_USE,
1952+
import.root_id,
1953+
ident.span,
1954+
BuiltinLintDiag::MacroIsPrivate(ident),
1955+
);
1956+
}
19431957
}
19441958
// Avoid marking `extern crate` items that refer to a name from extern prelude,
19451959
// but not introduce it, as used if they are accessed from lexical scope.

library/core/src/num/int_macros.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,6 @@ macro_rules! int_impl {
239239
/// Basic usage:
240240
///
241241
/// ```
242-
///
243242
#[doc = concat!("let n = -1", stringify!($SelfT), ";")]
244243
///
245244
#[doc = concat!("assert_eq!(n.cast_unsigned(), ", stringify!($UnsignedT), "::MAX);")]

0 commit comments

Comments
 (0)