Skip to content

Commit c52c23b

Browse files
committed
Auto merge of rust-lang#130444 - matthiaskrgr:rollup-onlrjva, r=matthiaskrgr
Rollup of 3 pull requests Successful merges: - rust-lang#130033 (Don't call `fn_arg_names` query for non-`fn` foreign items in resolver) - rust-lang#130282 (Do not report an excessive number of overflow errors for an ever-growing deref impl) - rust-lang#130437 (Avoid crashing on variadic functions when producing arg-mismatch errors) r? `@ghost` `@rustbot` modify labels: rollup
2 parents fd2c811 + 14ee69c commit c52c23b

17 files changed

+196
-94
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1049,7 +1049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10491049
/// trait or region sub-obligations. (presumably we could, but it's not
10501050
/// particularly important for diagnostics...)
10511051
pub(crate) fn deref_once_mutably_for_diagnostic(&self, expr_ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
1052-
self.autoderef(DUMMY_SP, expr_ty).nth(1).and_then(|(deref_ty, _)| {
1052+
self.autoderef(DUMMY_SP, expr_ty).silence_errors().nth(1).and_then(|(deref_ty, _)| {
10531053
self.infcx
10541054
.type_implements_trait(
10551055
self.tcx.lang_items().deref_mut_trait()?,

compiler/rustc_hir_typeck/src/expr.rs

+31-16
Original file line numberDiff line numberDiff line change
@@ -2864,13 +2864,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
28642864
(expr_t, "")
28652865
};
28662866
for (found_fields, args) in
2867-
self.get_field_candidates_considering_privacy(span, ty, mod_id, id)
2867+
self.get_field_candidates_considering_privacy_for_diag(span, ty, mod_id, id)
28682868
{
28692869
let field_names = found_fields.iter().map(|field| field.name).collect::<Vec<_>>();
28702870
let mut candidate_fields: Vec<_> = found_fields
28712871
.into_iter()
28722872
.filter_map(|candidate_field| {
2873-
self.check_for_nested_field_satisfying(
2873+
self.check_for_nested_field_satisfying_condition_for_diag(
28742874
span,
28752875
&|candidate_field, _| candidate_field.ident(self.tcx()) == field,
28762876
candidate_field,
@@ -2933,7 +2933,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
29332933
.with_span_label(field.span, "private field")
29342934
}
29352935

2936-
pub(crate) fn get_field_candidates_considering_privacy(
2936+
pub(crate) fn get_field_candidates_considering_privacy_for_diag(
29372937
&self,
29382938
span: Span,
29392939
base_ty: Ty<'tcx>,
@@ -2942,7 +2942,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
29422942
) -> Vec<(Vec<&'tcx ty::FieldDef>, GenericArgsRef<'tcx>)> {
29432943
debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);
29442944

2945-
self.autoderef(span, base_ty)
2945+
let mut autoderef = self.autoderef(span, base_ty).silence_errors();
2946+
let deref_chain: Vec<_> = autoderef.by_ref().collect();
2947+
2948+
// Don't probe if we hit the recursion limit, since it may result in
2949+
// quadratic blowup if we then try to further deref the results of this
2950+
// function. This is a best-effort method, after all.
2951+
if autoderef.reached_recursion_limit() {
2952+
return vec![];
2953+
}
2954+
2955+
deref_chain
2956+
.into_iter()
29462957
.filter_map(move |(base_t, _)| {
29472958
match base_t.kind() {
29482959
ty::Adt(base_def, args) if !base_def.is_enum() => {
@@ -2975,7 +2986,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
29752986

29762987
/// This method is called after we have encountered a missing field error to recursively
29772988
/// search for the field
2978-
pub(crate) fn check_for_nested_field_satisfying(
2989+
pub(crate) fn check_for_nested_field_satisfying_condition_for_diag(
29792990
&self,
29802991
span: Span,
29812992
matches: &impl Fn(&ty::FieldDef, Ty<'tcx>) -> bool,
@@ -3000,20 +3011,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30003011
if matches(candidate_field, field_ty) {
30013012
return Some(field_path);
30023013
} else {
3003-
for (nested_fields, subst) in
3004-
self.get_field_candidates_considering_privacy(span, field_ty, mod_id, hir_id)
3014+
for (nested_fields, subst) in self
3015+
.get_field_candidates_considering_privacy_for_diag(
3016+
span, field_ty, mod_id, hir_id,
3017+
)
30053018
{
30063019
// recursively search fields of `candidate_field` if it's a ty::Adt
30073020
for field in nested_fields {
3008-
if let Some(field_path) = self.check_for_nested_field_satisfying(
3009-
span,
3010-
matches,
3011-
field,
3012-
subst,
3013-
field_path.clone(),
3014-
mod_id,
3015-
hir_id,
3016-
) {
3021+
if let Some(field_path) = self
3022+
.check_for_nested_field_satisfying_condition_for_diag(
3023+
span,
3024+
matches,
3025+
field,
3026+
subst,
3027+
field_path.clone(),
3028+
mod_id,
3029+
hir_id,
3030+
)
3031+
{
30173032
return Some(field_path);
30183033
}
30193034
}

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -2619,9 +2619,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26192619
is_method: bool,
26202620
) -> Option<Vec<(Option<&hir::GenericParam<'_>>, &hir::Param<'_>)>> {
26212621
let fn_node = self.tcx.hir().get_if_local(def_id)?;
2622+
let fn_decl = fn_node.fn_decl()?;
26222623

2623-
let generic_params: Vec<Option<&hir::GenericParam<'_>>> = fn_node
2624-
.fn_decl()?
2624+
let generic_params: Vec<Option<&hir::GenericParam<'_>>> = fn_decl
26252625
.inputs
26262626
.into_iter()
26272627
.skip(if is_method { 1 } else { 0 })
@@ -2642,7 +2642,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26422642
})
26432643
.collect();
26442644

2645-
let params: Vec<&hir::Param<'_>> = self
2645+
let mut params: Vec<&hir::Param<'_>> = self
26462646
.tcx
26472647
.hir()
26482648
.body(fn_node.body_id()?)
@@ -2651,7 +2651,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26512651
.skip(if is_method { 1 } else { 0 })
26522652
.collect();
26532653

2654-
Some(generic_params.into_iter().zip_eq(params).collect())
2654+
// The surrounding code expects variadic functions to not have a parameter representing
2655+
// the "..." parameter. This is already true of the FnDecl but not of the body params, so
2656+
// we drop it if it exists.
2657+
2658+
if fn_decl.c_variadic {
2659+
params.pop();
2660+
}
2661+
2662+
debug_assert_eq!(params.len(), generic_params.len());
2663+
Some(generic_params.into_iter().zip(params).collect())
26552664
}
26562665
}
26572666

compiler/rustc_hir_typeck/src/method/probe.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
375375
// If our autoderef loop had reached the recursion limit,
376376
// report an overflow error, but continue going on with
377377
// the truncated autoderef list.
378-
if steps.reached_recursion_limit {
378+
if steps.reached_recursion_limit && !is_suggestion.0 {
379379
self.probe(|_| {
380380
let ty = &steps
381381
.steps

compiler/rustc_hir_typeck/src/method/suggest.rs

+28-21
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6262
// It might seem that we can use `predicate_must_hold_modulo_regions`,
6363
// but since a Dummy binder is used to fill in the FnOnce trait's arguments,
6464
// type resolution always gives a "maybe" here.
65-
if self.autoderef(span, ty).any(|(ty, _)| {
65+
if self.autoderef(span, ty).silence_errors().any(|(ty, _)| {
6666
info!("check deref {:?} error", ty);
6767
matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
6868
}) {
6969
return false;
7070
}
7171

72-
self.autoderef(span, ty).any(|(ty, _)| {
72+
self.autoderef(span, ty).silence_errors().any(|(ty, _)| {
7373
info!("check deref {:?} impl FnOnce", ty);
7474
self.probe(|_| {
7575
let trait_ref =
@@ -90,7 +90,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9090
}
9191

9292
fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
93-
self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
93+
self.autoderef(span, ty)
94+
.silence_errors()
95+
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
9496
}
9597

9698
fn impl_into_iterator_should_be_iterator(
@@ -672,7 +674,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
672674
let mut ty_str_reported = ty_str.clone();
673675
if let ty::Adt(_, generics) = rcvr_ty.kind() {
674676
if generics.len() > 0 {
675-
let mut autoderef = self.autoderef(span, rcvr_ty);
677+
let mut autoderef = self.autoderef(span, rcvr_ty).silence_errors();
676678
let candidate_found = autoderef.any(|(ty, _)| {
677679
if let ty::Adt(adt_def, _) = ty.kind() {
678680
self.tcx
@@ -2237,6 +2239,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22372239
let impl_ty = self.tcx.type_of(*impl_did).instantiate_identity();
22382240
let target_ty = self
22392241
.autoderef(sugg_span, rcvr_ty)
2242+
.silence_errors()
22402243
.find(|(rcvr_ty, _)| {
22412244
DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify(*rcvr_ty, impl_ty)
22422245
})
@@ -2352,17 +2355,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23522355
err: &mut Diag<'_>,
23532356
) -> bool {
23542357
let tcx = self.tcx;
2355-
let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
2356-
ty::Adt(def, args) if !def.is_enum() => {
2357-
let variant = &def.non_enum_variant();
2358-
tcx.find_field_index(item_name, variant).map(|index| {
2359-
let field = &variant.fields[index];
2360-
let field_ty = field.ty(tcx, args);
2361-
(field, field_ty)
2362-
})
2363-
}
2364-
_ => None,
2365-
});
2358+
let field_receiver =
2359+
self.autoderef(span, rcvr_ty).silence_errors().find_map(|(ty, _)| match ty.kind() {
2360+
ty::Adt(def, args) if !def.is_enum() => {
2361+
let variant = &def.non_enum_variant();
2362+
tcx.find_field_index(item_name, variant).map(|index| {
2363+
let field = &variant.fields[index];
2364+
let field_ty = field.ty(tcx, args);
2365+
(field, field_ty)
2366+
})
2367+
}
2368+
_ => None,
2369+
});
23662370
if let Some((field, field_ty)) = field_receiver {
23672371
let scope = tcx.parent_module_from_def_id(self.body_id);
23682372
let is_accessible = field.vis.is_accessible_from(scope, tcx);
@@ -2675,9 +2679,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26752679
) {
26762680
if let SelfSource::MethodCall(expr) = source {
26772681
let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id();
2678-
for (fields, args) in
2679-
self.get_field_candidates_considering_privacy(span, actual, mod_id, expr.hir_id)
2680-
{
2682+
for (fields, args) in self.get_field_candidates_considering_privacy_for_diag(
2683+
span,
2684+
actual,
2685+
mod_id,
2686+
expr.hir_id,
2687+
) {
26812688
let call_expr = self.tcx.hir().expect_expr(self.tcx.parent_hir_id(expr.hir_id));
26822689

26832690
let lang_items = self.tcx.lang_items();
@@ -2693,7 +2700,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26932700
let mut candidate_fields: Vec<_> = fields
26942701
.into_iter()
26952702
.filter_map(|candidate_field| {
2696-
self.check_for_nested_field_satisfying(
2703+
self.check_for_nested_field_satisfying_condition_for_diag(
26972704
span,
26982705
&|_, field_ty| {
26992706
self.lookup_probe_for_diagnostic(
@@ -3195,7 +3202,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31953202
let SelfSource::QPath(ty) = self_source else {
31963203
return;
31973204
};
3198-
for (deref_ty, _) in self.autoderef(DUMMY_SP, rcvr_ty).skip(1) {
3205+
for (deref_ty, _) in self.autoderef(DUMMY_SP, rcvr_ty).silence_errors().skip(1) {
31993206
if let Ok(pick) = self.probe_for_name(
32003207
Mode::Path,
32013208
item_name,
@@ -4221,7 +4228,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
42214228
return is_local(rcvr_ty);
42224229
}
42234230

4224-
self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
4231+
self.autoderef(span, rcvr_ty).silence_errors().any(|(ty, _)| is_local(ty))
42254232
}
42264233
}
42274234

compiler/rustc_hir_typeck/src/pat.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2533,6 +2533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25332533
err.help("the semantics of slice patterns changed recently; see issue #62254");
25342534
} else if self
25352535
.autoderef(span, expected_ty)
2536+
.silence_errors()
25362537
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
25372538
&& let Some(span) = ti.span
25382539
&& let Some(_) = ti.origin_expr

compiler/rustc_resolve/src/late/diagnostics.rs

+25-24
Original file line numberDiff line numberDiff line change
@@ -2068,33 +2068,34 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
20682068
) {
20692069
let res = binding.res();
20702070
if filter_fn(res) {
2071-
let def_id = res.def_id();
2072-
let has_self = match def_id.as_local() {
2073-
Some(def_id) => {
2074-
self.r.delegation_fn_sigs.get(&def_id).map_or(false, |sig| sig.has_self)
2075-
}
2076-
None => self
2077-
.r
2078-
.tcx
2079-
.fn_arg_names(def_id)
2080-
.first()
2081-
.is_some_and(|ident| ident.name == kw::SelfLower),
2082-
};
2083-
if has_self {
2084-
return Some(AssocSuggestion::MethodWithSelf { called });
2085-
} else {
2086-
match res {
2087-
Res::Def(DefKind::AssocFn, _) => {
2071+
match res {
2072+
Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => {
2073+
let has_self = match def_id.as_local() {
2074+
Some(def_id) => self
2075+
.r
2076+
.delegation_fn_sigs
2077+
.get(&def_id)
2078+
.map_or(false, |sig| sig.has_self),
2079+
None => self
2080+
.r
2081+
.tcx
2082+
.fn_arg_names(def_id)
2083+
.first()
2084+
.is_some_and(|ident| ident.name == kw::SelfLower),
2085+
};
2086+
if has_self {
2087+
return Some(AssocSuggestion::MethodWithSelf { called });
2088+
} else {
20882089
return Some(AssocSuggestion::AssocFn { called });
20892090
}
2090-
Res::Def(DefKind::AssocConst, _) => {
2091-
return Some(AssocSuggestion::AssocConst);
2092-
}
2093-
Res::Def(DefKind::AssocTy, _) => {
2094-
return Some(AssocSuggestion::AssocType);
2095-
}
2096-
_ => {}
20972091
}
2092+
Res::Def(DefKind::AssocConst, _) => {
2093+
return Some(AssocSuggestion::AssocConst);
2094+
}
2095+
Res::Def(DefKind::AssocTy, _) => {
2096+
return Some(AssocSuggestion::AssocType);
2097+
}
2098+
_ => {}
20982099
}
20992100
}
21002101
}

tests/crashes/130372-1.rs

-9
This file was deleted.

tests/crashes/130372-2.rs

-11
This file was deleted.

tests/crashes/130372-3.rs

-7
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use std::ops::Deref;
2+
3+
// Make sure that method probe error reporting doesn't get too tangled up
4+
// on this infinite deref impl. See #130224.
5+
6+
struct Wrap<T>(T);
7+
impl<T> Deref for Wrap<T> {
8+
type Target = Wrap<Wrap<T>>;
9+
fn deref(&self) -> &Wrap<Wrap<T>> { todo!() }
10+
}
11+
12+
fn main() {
13+
Wrap(1).lmao();
14+
//~^ ERROR reached the recursion limit
15+
//~| ERROR no method named `lmao`
16+
}

0 commit comments

Comments
 (0)