From 973510749d955d72a8bf6f27775df3a5f8d652f2 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sat, 20 Aug 2022 15:54:39 +0900 Subject: [PATCH] remove unnecessary string searchings remove unnecessary string searchings for checking if function arguments have `&` and `&mut` --- .../src/traits/error_reporting/suggestions.rs | 31 ++++++++++--------- .../suggest-deferences/issue-39029.stderr | 10 +++--- .../suggest-deferences/issue-62530.stderr | 10 +++--- .../suggest-deferences/multiple-0.stderr | 10 +++--- 4 files changed, 35 insertions(+), 26 deletions(-) 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 219413121d812..168834159e705 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -671,7 +671,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { // It only make sense when suggesting dereferences for arguments - let ObligationCauseCode::FunctionArgumentObligation { .. } = obligation.cause.code() else { + let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() else { return false; }; let param_env = obligation.param_env; @@ -702,19 +702,22 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { Some(steps).filter(|_| self.predicate_may_hold(&obligation)) }) { if steps > 0 { - if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(span) { - // Don't care about `&mut` because `DerefMut` is used less - // often and user will not expect autoderef happens. - if src.starts_with('&') && !src.starts_with("&mut ") { - let derefs = "*".repeat(steps); - err.span_suggestion( - span, - "consider dereferencing here", - format!("&{}{}", derefs, &src[1..]), - Applicability::MachineApplicable, - ); - return true; - } + // Don't care about `&mut` because `DerefMut` is used less + // often and user will not expect autoderef happens. + if let Some(hir::Node::Expr(hir::Expr { + kind: + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, expr), + .. + })) = self.tcx.hir().find(*arg_hir_id) + { + let derefs = "*".repeat(steps); + err.span_suggestion_verbose( + expr.span.shrink_to_lo(), + "consider dereferencing here", + derefs, + Applicability::MachineApplicable, + ); + return true; } } } else if real_trait_pred != trait_pred { diff --git a/src/test/ui/traits/suggest-deferences/issue-39029.stderr b/src/test/ui/traits/suggest-deferences/issue-39029.stderr index 5c324cd38a3ab..d256431c4cca8 100644 --- a/src/test/ui/traits/suggest-deferences/issue-39029.stderr +++ b/src/test/ui/traits/suggest-deferences/issue-39029.stderr @@ -2,10 +2,8 @@ error[E0277]: the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied --> $DIR/issue-39029.rs:16:37 | LL | let _errors = TcpListener::bind(&bad); - | ----------------- ^^^^ - | | | - | | the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs` - | | help: consider dereferencing here: `&*bad` + | ----------------- ^^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs` + | | | required by a bound introduced by this call | = note: required because of the requirements on the impl of `ToSocketAddrs` for `&NoToSocketAddrs` @@ -14,6 +12,10 @@ note: required by a bound in `TcpListener::bind` | LL | pub fn bind(addr: A) -> io::Result { | ^^^^^^^^^^^^^ required by this bound in `TcpListener::bind` +help: consider dereferencing here + | +LL | let _errors = TcpListener::bind(&*bad); + | + error: aborting due to previous error diff --git a/src/test/ui/traits/suggest-deferences/issue-62530.stderr b/src/test/ui/traits/suggest-deferences/issue-62530.stderr index d129328dae8ef..e47ae0b65af0e 100644 --- a/src/test/ui/traits/suggest-deferences/issue-62530.stderr +++ b/src/test/ui/traits/suggest-deferences/issue-62530.stderr @@ -2,10 +2,8 @@ error[E0277]: the trait bound `&String: SomeTrait` is not satisfied --> $DIR/issue-62530.rs:13:26 | LL | takes_type_parameter(&string); // Error - | -------------------- ^^^^^^^ - | | | - | | the trait `SomeTrait` is not implemented for `&String` - | | help: consider dereferencing here: `&*string` + | -------------------- ^^^^^^^ the trait `SomeTrait` is not implemented for `&String` + | | | required by a bound introduced by this call | note: required by a bound in `takes_type_parameter` @@ -13,6 +11,10 @@ note: required by a bound in `takes_type_parameter` | LL | fn takes_type_parameter(_x: T) where T: SomeTrait {} | ^^^^^^^^^ required by this bound in `takes_type_parameter` +help: consider dereferencing here + | +LL | takes_type_parameter(&*string); // Error + | + error: aborting due to previous error diff --git a/src/test/ui/traits/suggest-deferences/multiple-0.stderr b/src/test/ui/traits/suggest-deferences/multiple-0.stderr index efb3c7d123f70..6a4d4b8d5212f 100644 --- a/src/test/ui/traits/suggest-deferences/multiple-0.stderr +++ b/src/test/ui/traits/suggest-deferences/multiple-0.stderr @@ -2,10 +2,8 @@ error[E0277]: the trait bound `&Baz: Happy` is not satisfied --> $DIR/multiple-0.rs:34:9 | LL | foo(&baz); - | --- ^^^^ - | | | - | | the trait `Happy` is not implemented for `&Baz` - | | help: consider dereferencing here: `&***baz` + | --- ^^^^ the trait `Happy` is not implemented for `&Baz` + | | | required by a bound introduced by this call | note: required by a bound in `foo` @@ -13,6 +11,10 @@ note: required by a bound in `foo` | LL | fn foo(_: T) where T: Happy {} | ^^^^^ required by this bound in `foo` +help: consider dereferencing here + | +LL | foo(&***baz); + | +++ error: aborting due to previous error