Account for type params

This commit is contained in:
Esteban Küber 2023-01-01 19:35:53 -08:00
parent 2024aa48b4
commit ce83be4af8
4 changed files with 81 additions and 38 deletions

View File

@ -1363,19 +1363,70 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// 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;
@ -1387,35 +1438,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
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
@ -1431,7 +1461,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
break 'outer;
}
}
suggested
false
}
fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic) {

View File

@ -4,12 +4,16 @@ error[E0277]: the trait bound `&'static mut isize: Copy` is not satisfied
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
@ -17,12 +21,16 @@ error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied
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

View File

@ -5,6 +5,6 @@ use std::panic::UnwindSafe;
fn assert<T: UnwindSafe + ?Sized>() {}
fn main() {
assert::<&mut i32>();
//~^ ERROR the type `&mut i32` may not be safely transferred across an unwind boundary
assert::<&mut &mut &i32>();
//~^ ERROR the type `&mut &mut &i32` may not be safely transferred across an unwind boundary
}

View File

@ -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
|
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