Skip to content

Commit

Permalink
Do not report an excessive number of overflow errors for an ever-grow…
Browse files Browse the repository at this point in the history
…ing deref impl
  • Loading branch information
compiler-errors committed Sep 12, 2024
1 parent 394c406 commit d8a646f
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 3 deletions.
13 changes: 12 additions & 1 deletion compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2942,7 +2942,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Vec<(Vec<&'tcx ty::FieldDef>, GenericArgsRef<'tcx>)> {
debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);

self.autoderef(span, base_ty)
let mut autoderef = self.autoderef(span, base_ty).silence_errors();
let deref_chain: Vec<_> = autoderef.by_ref().collect();

// Don't probe if we hit the recursion limit, since it may result in
// quadratic blowup if we then try to further deref the results of this
// function. This is a best-effort method, after all.
if autoderef.reached_recursion_limit() {
return vec![];
}

deref_chain
.into_iter()
.filter_map(move |(base_t, _)| {
match base_t.kind() {
ty::Adt(base_def, args) if !base_def.is_enum() => {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If our autoderef loop had reached the recursion limit,
// report an overflow error, but continue going on with
// the truncated autoderef list.
if steps.reached_recursion_limit {
if steps.reached_recursion_limit && !is_suggestion.0 {
self.probe(|_| {
let ty = &steps
.steps
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut ty_str_reported = ty_str.clone();
if let ty::Adt(_, generics) = rcvr_ty.kind() {
if generics.len() > 0 {
let mut autoderef = self.autoderef(span, rcvr_ty);
let mut autoderef = self.autoderef(span, rcvr_ty).silence_errors();
let candidate_found = autoderef.any(|(ty, _)| {
if let ty::Adt(adt_def, _) = ty.kind() {
self.tcx
Expand Down
17 changes: 17 additions & 0 deletions tests/ui/methods/probe-error-on-infinite-deref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use std::ops::Deref;

// Make sure that method probe error reporting doesn't get too tangled up
// on this infinite deref impl. See #130224.

struct Wrap<T>(T);
impl<T> Deref for Wrap<T> {
type Target = Wrap<Wrap<T>>;
fn deref(&self) -> &Wrap<Wrap<T>> { todo!() }
}

fn main() {
Wrap(1).lmao();
//~^ ERROR reached the recursion limit
//~| ERROR reached the recursion limit
//~| ERROR no method named `lmao`
}
30 changes: 30 additions & 0 deletions tests/ui/methods/probe-error-on-infinite-deref.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
--> $DIR/probe-error-on-infinite-deref.rs:13:13
|
LL | Wrap(1).lmao();
| ^^^^ deref recursion limit reached
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`probe_error_on_infinite_deref`)

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}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
--> $DIR/probe-error-on-infinite-deref.rs:13:13
|
LL | Wrap(1).lmao();
| ^^^^ deref recursion limit reached
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`probe_error_on_infinite_deref`)
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0599]: no method named `lmao` found for struct `Wrap<{integer}>` in the current scope
--> $DIR/probe-error-on-infinite-deref.rs:13:13
|
LL | struct Wrap<T>(T);
| -------------- method `lmao` not found for this struct
...
LL | Wrap(1).lmao();
| ^^^^ method not found in `Wrap<{integer}>`

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0055, E0599.
For more information about an error, try `rustc --explain E0055`.

0 comments on commit d8a646f

Please sign in to comment.