Skip to content

Commit d8a646f

Browse files
Do not report an excessive number of overflow errors for an ever-growing deref impl
1 parent 394c406 commit d8a646f

File tree

5 files changed

+61
-3
lines changed

5 files changed

+61
-3
lines changed

Diff for: compiler/rustc_hir_typeck/src/expr.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -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() => {

Diff for: 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

Diff for: compiler/rustc_hir_typeck/src/method/suggest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
672672
let mut ty_str_reported = ty_str.clone();
673673
if let ty::Adt(_, generics) = rcvr_ty.kind() {
674674
if generics.len() > 0 {
675-
let mut autoderef = self.autoderef(span, rcvr_ty);
675+
let mut autoderef = self.autoderef(span, rcvr_ty).silence_errors();
676676
let candidate_found = autoderef.any(|(ty, _)| {
677677
if let ty::Adt(adt_def, _) = ty.kind() {
678678
self.tcx

Diff for: tests/ui/methods/probe-error-on-infinite-deref.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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 reached the recursion limit
16+
//~| ERROR no method named `lmao`
17+
}
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error[E0055]: reached the recursion limit while auto-dereferencing `Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<{integer}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
2+
--> $DIR/probe-error-on-infinite-deref.rs:13:13
3+
|
4+
LL | Wrap(1).lmao();
5+
| ^^^^ deref recursion limit reached
6+
|
7+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`probe_error_on_infinite_deref`)
8+
9+
error[E0055]: reached the recursion limit while auto-dereferencing `Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<{integer}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
10+
--> $DIR/probe-error-on-infinite-deref.rs:13:13
11+
|
12+
LL | Wrap(1).lmao();
13+
| ^^^^ deref recursion limit reached
14+
|
15+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`probe_error_on_infinite_deref`)
16+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
17+
18+
error[E0599]: no method named `lmao` found for struct `Wrap<{integer}>` in the current scope
19+
--> $DIR/probe-error-on-infinite-deref.rs:13:13
20+
|
21+
LL | struct Wrap<T>(T);
22+
| -------------- method `lmao` not found for this struct
23+
...
24+
LL | Wrap(1).lmao();
25+
| ^^^^ method not found in `Wrap<{integer}>`
26+
27+
error: aborting due to 3 previous errors
28+
29+
Some errors have detailed explanations: E0055, E0599.
30+
For more information about an error, try `rustc --explain E0055`.

0 commit comments

Comments
 (0)