// Remove all the hir desugaring contexts while maintaining the macro contexts.
span.remove_mark();
}
- let mut suggested = false;
-
- let mut expr_finder = super::FindExprBySpan { span, result: None };
+ let mut expr_finder = super::FindExprBySpan::new(span);
let Some(hir::Node::Expr(body)) = self.tcx.hir().find(obligation.cause.body_id) else {
return false;
};
expr_finder.visit_expr(&body);
+ let mut maybe_suggest = |suggested_ty, count, suggestions| {
+ // Remapping bound vars here
+ let trait_pred_and_suggested_ty =
+ trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
+
+ let new_obligation = self.mk_trait_obligation_with_new_self_ty(
+ obligation.param_env,
+ trait_pred_and_suggested_ty,
+ );
+
+ if self.predicate_may_hold(&new_obligation) {
+ let msg = if count == 1 {
+ "consider removing the leading `&`-reference".to_string()
+ } else {
+ format!("consider removing {count} leading `&`-references")
+ };
+
+ err.multipart_suggestion_verbose(
+ &msg,
+ suggestions,
+ Applicability::MachineApplicable,
+ );
+ true
+ } else {
+ false
+ }
+ };
+
+ // Maybe suggest removal of borrows from types in type parameters, like in
+ // `src/test/ui/not-panic/not-panic-safe.rs`.
let mut count = 0;
let mut suggestions = vec![];
- let Some(mut expr) = expr_finder.result else { return false; };
// Skipping binder here, remapping below
let mut suggested_ty = trait_pred.self_ty().skip_binder();
+ if let Some(mut hir_ty) = expr_finder.ty_result {
+ while let hir::TyKind::Ref(_, mut_ty) = &hir_ty.kind {
+ count += 1;
+ let span = hir_ty.span.until(mut_ty.ty.span);
+ suggestions.push((span, String::new()));
+
+ let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
+ break;
+ };
+ suggested_ty = *inner_ty;
+
+ hir_ty = mut_ty.ty;
+
+ if maybe_suggest(suggested_ty, count, suggestions.clone()) {
+ return true;
+ }
+ }
+ }
+ // Maybe suggest removal of borrows from expressions, like in `for i in &&&foo {}`.
+ let Some(mut expr) = expr_finder.result else { return false; };
+ let mut count = 0;
+ let mut suggestions = vec![];
+ // Skipping binder here, remapping below
+ let mut suggested_ty = trait_pred.self_ty().skip_binder();
'outer: loop {
while let hir::ExprKind::AddrOf(_, _, borrowed) = expr.kind {
count += 1;
suggestions.push((span, String::new()));
let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
- break;
+ break 'outer;
};
suggested_ty = *inner_ty;
expr = borrowed;
- // Remapping bound vars here
- let trait_pred_and_suggested_ty =
- trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
-
- let new_obligation = self.mk_trait_obligation_with_new_self_ty(
- obligation.param_env,
- trait_pred_and_suggested_ty,
- );
-
- if self.predicate_may_hold(&new_obligation) {
- let msg = if count == 1 {
- "consider removing the leading `&`-reference".to_string()
- } else {
- format!("consider removing {count} leading `&`-references")
- };
-
- err.multipart_suggestion_verbose(
- &msg,
- suggestions,
- Applicability::MachineApplicable,
- );
- suggested = true;
- break 'outer;
+ if maybe_suggest(suggested_ty, count, suggestions.clone()) {
+ return true;
}
}
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
break 'outer;
}
}
- suggested
+ false
}
fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic) {
LL | assert_copy::<&'static mut isize>();
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'static mut isize`
|
- = help: the trait `Copy` is implemented for `isize`
note: required by a bound in `assert_copy`
--> $DIR/kindck-copy.rs:5:18
|
LL | fn assert_copy<T:Copy>() { }
| ^^^^ required by this bound in `assert_copy`
+help: consider removing the leading `&`-reference
+ |
+LL - assert_copy::<&'static mut isize>();
+LL + assert_copy::<isize>();
+ |
error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied
--> $DIR/kindck-copy.rs:28:19
LL | assert_copy::<&'a mut isize>();
| ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut isize`
|
- = help: the trait `Copy` is implemented for `isize`
note: required by a bound in `assert_copy`
--> $DIR/kindck-copy.rs:5:18
|
LL | fn assert_copy<T:Copy>() { }
| ^^^^ required by this bound in `assert_copy`
+help: consider removing the leading `&`-reference
+ |
+LL - assert_copy::<&'a mut isize>();
+LL + assert_copy::<isize>();
+ |
error[E0277]: the trait bound `Box<isize>: Copy` is not satisfied
--> $DIR/kindck-copy.rs:31:19
-error[E0277]: the type `&mut i32` may not be safely transferred across an unwind boundary
+error[E0277]: the type `&mut &mut &i32` may not be safely transferred across an unwind boundary
--> $DIR/not-panic-safe.rs:8:14
|
-LL | assert::<&mut i32>();
- | ^^^^^^^^ `&mut i32` may not be safely transferred across an unwind boundary
+LL | assert::<&mut &mut &i32>();
+ | ^^^^^^^^^^^^^^ `&mut &mut &i32` may not be safely transferred across an unwind boundary
|
- = help: the trait `UnwindSafe` is not implemented for `&mut i32`
- = note: `UnwindSafe` is implemented for `&i32`, but not for `&mut i32`
+ = help: the trait `UnwindSafe` is not implemented for `&mut &mut &i32`
+ = note: `UnwindSafe` is implemented for `&&mut &i32`, but not for `&mut &mut &i32`
note: required by a bound in `assert`
--> $DIR/not-panic-safe.rs:5:14
|
LL | fn assert<T: UnwindSafe + ?Sized>() {}
| ^^^^^^^^^^ required by this bound in `assert`
+help: consider removing 2 leading `&`-references
+ |
+LL - assert::<&mut &mut &i32>();
+LL + assert::<&i32>();
+ |
error: aborting due to previous error