Account for type params
This commit is contained in:
parent
2024aa48b4
commit
ce83be4af8
4 changed files with 81 additions and 38 deletions
|
@ -1363,19 +1363,70 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
// Remove all the hir desugaring contexts while maintaining the macro contexts.
|
// Remove all the hir desugaring contexts while maintaining the macro contexts.
|
||||||
span.remove_mark();
|
span.remove_mark();
|
||||||
}
|
}
|
||||||
let mut suggested = false;
|
let mut expr_finder = super::FindExprBySpan::new(span);
|
||||||
|
|
||||||
let mut expr_finder = super::FindExprBySpan { span, result: None };
|
|
||||||
let Some(hir::Node::Expr(body)) = self.tcx.hir().find(obligation.cause.body_id) else {
|
let Some(hir::Node::Expr(body)) = self.tcx.hir().find(obligation.cause.body_id) else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
expr_finder.visit_expr(&body);
|
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 count = 0;
|
||||||
let mut suggestions = vec![];
|
let mut suggestions = vec![];
|
||||||
let Some(mut expr) = expr_finder.result else { return false; };
|
|
||||||
// Skipping binder here, remapping below
|
// Skipping binder here, remapping below
|
||||||
let mut suggested_ty = trait_pred.self_ty().skip_binder();
|
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 {
|
'outer: loop {
|
||||||
while let hir::ExprKind::AddrOf(_, _, borrowed) = expr.kind {
|
while let hir::ExprKind::AddrOf(_, _, borrowed) = expr.kind {
|
||||||
count += 1;
|
count += 1;
|
||||||
|
@ -1387,35 +1438,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
suggestions.push((span, String::new()));
|
suggestions.push((span, String::new()));
|
||||||
|
|
||||||
let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
|
let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
|
||||||
break;
|
break 'outer;
|
||||||
};
|
};
|
||||||
suggested_ty = *inner_ty;
|
suggested_ty = *inner_ty;
|
||||||
|
|
||||||
expr = borrowed;
|
expr = borrowed;
|
||||||
|
|
||||||
// Remapping bound vars here
|
if maybe_suggest(suggested_ty, count, suggestions.clone()) {
|
||||||
let trait_pred_and_suggested_ty =
|
return true;
|
||||||
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 let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
|
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
|
||||||
|
@ -1431,7 +1461,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
break 'outer;
|
break 'outer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
suggested
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic) {
|
fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic) {
|
||||||
|
|
|
@ -4,12 +4,16 @@ error[E0277]: the trait bound `&'static mut isize: Copy` is not satisfied
|
||||||
LL | assert_copy::<&'static mut isize>();
|
LL | assert_copy::<&'static mut isize>();
|
||||||
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'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`
|
note: required by a bound in `assert_copy`
|
||||||
--> $DIR/kindck-copy.rs:5:18
|
--> $DIR/kindck-copy.rs:5:18
|
||||||
|
|
|
|
||||||
LL | fn assert_copy<T:Copy>() { }
|
LL | fn assert_copy<T:Copy>() { }
|
||||||
| ^^^^ required by this bound in `assert_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
|
error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied
|
||||||
--> $DIR/kindck-copy.rs:28:19
|
--> $DIR/kindck-copy.rs:28:19
|
||||||
|
@ -17,12 +21,16 @@ error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied
|
||||||
LL | assert_copy::<&'a mut isize>();
|
LL | assert_copy::<&'a mut isize>();
|
||||||
| ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'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`
|
note: required by a bound in `assert_copy`
|
||||||
--> $DIR/kindck-copy.rs:5:18
|
--> $DIR/kindck-copy.rs:5:18
|
||||||
|
|
|
|
||||||
LL | fn assert_copy<T:Copy>() { }
|
LL | fn assert_copy<T:Copy>() { }
|
||||||
| ^^^^ required by this bound in `assert_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
|
error[E0277]: the trait bound `Box<isize>: Copy` is not satisfied
|
||||||
--> $DIR/kindck-copy.rs:31:19
|
--> $DIR/kindck-copy.rs:31:19
|
||||||
|
|
|
@ -5,6 +5,6 @@ use std::panic::UnwindSafe;
|
||||||
fn assert<T: UnwindSafe + ?Sized>() {}
|
fn assert<T: UnwindSafe + ?Sized>() {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
assert::<&mut i32>();
|
assert::<&mut &mut &i32>();
|
||||||
//~^ ERROR the type `&mut i32` may not be safely transferred across an unwind boundary
|
//~^ ERROR the type `&mut &mut &i32` may not be safely transferred across an unwind boundary
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,21 @@
|
||||||
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
|
--> $DIR/not-panic-safe.rs:8:14
|
||||||
|
|
|
|
||||||
LL | assert::<&mut i32>();
|
LL | assert::<&mut &mut &i32>();
|
||||||
| ^^^^^^^^ `&mut i32` may not be safely transferred across an unwind boundary
|
| ^^^^^^^^^^^^^^ `&mut &mut &i32` may not be safely transferred across an unwind boundary
|
||||||
|
|
|
|
||||||
= help: the trait `UnwindSafe` is not implemented for `&mut i32`
|
= help: the trait `UnwindSafe` is not implemented for `&mut &mut &i32`
|
||||||
= note: `UnwindSafe` is implemented for `&i32`, but not for `&mut i32`
|
= note: `UnwindSafe` is implemented for `&&mut &i32`, but not for `&mut &mut &i32`
|
||||||
note: required by a bound in `assert`
|
note: required by a bound in `assert`
|
||||||
--> $DIR/not-panic-safe.rs:5:14
|
--> $DIR/not-panic-safe.rs:5:14
|
||||||
|
|
|
|
||||||
LL | fn assert<T: UnwindSafe + ?Sized>() {}
|
LL | fn assert<T: UnwindSafe + ?Sized>() {}
|
||||||
| ^^^^^^^^^^ required by this bound in `assert`
|
| ^^^^^^^^^^ 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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue