From d1380a18447e9509cc9cd5307edcb4e22ca0351b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 23 Jul 2023 13:56:03 -0400 Subject: [PATCH] Use erased self type when autoderefing for trait error suggestion --- .../src/traits/error_reporting/suggestions.rs | 10 +++---- .../dont-autoderef-ty-with-escaping-var.rs | 22 +++++++++++++++ ...dont-autoderef-ty-with-escaping-var.stderr | 27 +++++++++++++++++++ 3 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 tests/ui/traits/dont-autoderef-ty-with-escaping-var.rs create mode 100644 tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 073a2a2b1a0..3494e819b2e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -776,18 +776,14 @@ fn suggest_dereferences( real_trait_pred = parent_trait_pred; } - let real_ty = real_trait_pred.self_ty(); // We `erase_late_bound_regions` here because `make_subregion` does not handle // `ReLateBound`, and we don't particularly care about the regions. - if !self.can_eq( - obligation.param_env, - self.tcx.erase_late_bound_regions(real_ty), - arg_ty, - ) { + let real_ty = self.tcx.erase_late_bound_regions(real_trait_pred.self_ty()); + if !self.can_eq(obligation.param_env, real_ty, arg_ty) { continue; } - if let ty::Ref(region, base_ty, mutbl) = *real_ty.skip_binder().kind() { + if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() { let autoderef = (self.autoderef_steps)(base_ty); if let Some(steps) = autoderef.into_iter().enumerate().find_map(|(steps, (ty, obligations))| { diff --git a/tests/ui/traits/dont-autoderef-ty-with-escaping-var.rs b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.rs new file mode 100644 index 00000000000..d5ba3847ac3 --- /dev/null +++ b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.rs @@ -0,0 +1,22 @@ +// issue:113951 + +trait Foo<'x, T> {} + +trait RefFoo { + fn ref_foo(&self); +} + +impl RefFoo for T +where + for<'a> &'a mut Vec<&'a u32>: Foo<'static, T>, +{ + fn ref_foo(&self) {} +} + +fn coerce_lifetime2() { + >::ref_foo(unknown); + //~^ ERROR cannot find value `unknown` in this scope + //~| ERROR the trait bound `for<'a> &'a mut Vec<&'a u32>: Foo<'static, i32>` is not satisfied +} + +fn main() {} diff --git a/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr new file mode 100644 index 00000000000..934d20b2267 --- /dev/null +++ b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr @@ -0,0 +1,27 @@ +error[E0425]: cannot find value `unknown` in this scope + --> $DIR/dont-autoderef-ty-with-escaping-var.rs:17:35 + | +LL | >::ref_foo(unknown); + | ^^^^^^^ not found in this scope + +error[E0277]: the trait bound `for<'a> &'a mut Vec<&'a u32>: Foo<'static, i32>` is not satisfied + --> $DIR/dont-autoderef-ty-with-escaping-var.rs:17:35 + | +LL | >::ref_foo(unknown); + | ----------------------------- ^^^^^^^ the trait `for<'a> Foo<'static, i32>` is not implemented for `&'a mut Vec<&'a u32>` + | | + | required by a bound introduced by this call + | +note: required for `i32` to implement `RefFoo` + --> $DIR/dont-autoderef-ty-with-escaping-var.rs:9:9 + | +LL | impl RefFoo for T + | ^^^^^^^^^ ^ +LL | where +LL | for<'a> &'a mut Vec<&'a u32>: Foo<'static, T>, + | --------------- unsatisfied trait bound introduced here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0425. +For more information about an error, try `rustc --explain E0277`.