Point at argument instead of call for their obligations

When an obligation is introduced by a specific `fn` argument, point at
the argument instead of the `fn` call if the obligation fails to be
fulfilled.
This commit is contained in:
Esteban Kuber 2021-09-07 07:42:44 +00:00
parent 2b5ddf36fd
commit 284a8a9ce7
7 changed files with 64 additions and 51 deletions

View File

@ -83,7 +83,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// version (resolve_vars_if_possible), this version will
/// also select obligations if it seems useful, in an effort
/// to get more type information.
pub(in super::super) fn resolve_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
pub(in super::super) fn resolve_vars_with_obligations(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
self.resolve_vars_with_obligations_and_mutate_fulfillment(ty, |_| {})
}
pub(in super::super) fn resolve_vars_with_obligations_and_mutate_fulfillment(
&self,
mut ty: Ty<'tcx>,
mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
) -> Ty<'tcx> {
debug!("resolve_vars_with_obligations(ty={:?})", ty);
// No Infer()? Nothing needs doing.
@ -103,7 +111,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// possible. This can help substantially when there are
// indirect dependencies that don't seem worth tracking
// precisely.
self.select_obligations_where_possible(false, |_| {});
self.select_obligations_where_possible(false, mutate_fulfillment_errors);
ty = self.resolve_vars_if_possible(ty);
debug!("resolve_vars_with_obligations: ty={:?}", ty);

View File

@ -354,8 +354,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
continue;
}
debug!("checking the argument");
let formal_ty = formal_tys[i];
debug!("checking argument {}: {:?} = {:?}", i, arg, formal_ty);
// The special-cased logic below has three functions:
// 1. Provide as good of an expected type as possible.
@ -367,6 +367,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// to, which is `expected_ty` if `rvalue_hint` returns an
// `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty);
// Cause selection errors caused by resolving a single argument to point at the
// argument and not the call. This is otherwise redundant with the `demand_coerce`
// call immediately after, but it lets us customize the span pointed to in the
// fulfillment error to be more accurate.
let _ = self.resolve_vars_with_obligations_and_mutate_fulfillment(
coerce_ty,
|errors| {
// This is not coming from a macro or a `derive`.
if sp.desugaring_kind().is_none()
&& !arg.span.from_expansion()
// Do not change the spans of `async fn`s.
&& !matches!(
expr.kind,
hir::ExprKind::Call(
hir::Expr {
kind: hir::ExprKind::Path(hir::QPath::LangItem(_, _)),
..
},
_
)
) {
for error in errors {
error.obligation.cause.make_mut().span = arg.span;
error.points_at_arg_span = true;
}
}
},
);
// We're processing function arguments so we definitely want to use
// two-phase borrows.
self.demand_coerce(&arg, checked_ty, coerce_ty, None, AllowTwoPhase::Yes);

View File

@ -10,10 +10,10 @@ LL | f1(2i32, 4u32);
| ~~~
error[E0277]: the trait bound `u32: Foo` is not satisfied
--> $DIR/associated-types-path-2.rs:29:5
--> $DIR/associated-types-path-2.rs:29:14
|
LL | f1(2u32, 4u32);
| ^^ the trait `Foo` is not implemented for `u32`
| ^^^^ the trait `Foo` is not implemented for `u32`
|
note: required by a bound in `f1`
--> $DIR/associated-types-path-2.rs:13:14
@ -25,13 +25,13 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied
--> $DIR/associated-types-path-2.rs:29:5
|
LL | f1(2u32, 4u32);
| ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
| ^^ the trait `Foo` is not implemented for `u32`
error[E0277]: the trait bound `u32: Foo` is not satisfied
--> $DIR/associated-types-path-2.rs:35:5
--> $DIR/associated-types-path-2.rs:35:14
|
LL | f1(2u32, 4i32);
| ^^ the trait `Foo` is not implemented for `u32`
| ^^^^ the trait `Foo` is not implemented for `u32`
|
note: required by a bound in `f1`
--> $DIR/associated-types-path-2.rs:13:14
@ -43,7 +43,7 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied
--> $DIR/associated-types-path-2.rs:35:5
|
LL | f1(2u32, 4i32);
| ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
| ^^ the trait `Foo` is not implemented for `u32`
error[E0308]: mismatched types
--> $DIR/associated-types-path-2.rs:41:18

View File

@ -1,11 +1,17 @@
error[E0631]: type mismatch in closure arguments
--> $DIR/issue-62529-1.rs:80:10
|
LL | task(annotate(
| ^^^^^^^^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
...
LL | |value: &mut usize| {
| ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
LL | task(annotate(
| __________^
LL | |
LL | |
LL | | Annotate::<RefMutFamily<usize>>::new(),
LL | | |value: &mut usize| {
| | ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
LL | | *value = 2;
LL | | }
LL | | ));
| |_____^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
|
note: required by a bound in `annotate`
--> $DIR/issue-62529-1.rs:44:8

View File

@ -1,8 +1,8 @@
error[E0277]: the trait bound `&u32: Foo` is not satisfied
--> $DIR/issue-60218.rs:18:5
--> $DIR/issue-60218.rs:18:27
|
LL | trigger_error(vec![], |x: &u32| x)
| ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32`
| ^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32`
|
note: required by a bound in `trigger_error`
--> $DIR/issue-60218.rs:13:72

View File

@ -44,8 +44,6 @@ fn f9<X: ?Sized>(x1: Box<S<X>>) {
fn f10<X: ?Sized>(x1: Box<S<X>>) {
f5(&(32, *x1));
//~^ ERROR the size for values of type
//~| ERROR the size for values of type
}
pub fn main() {
}
pub fn main() {}

View File

@ -93,12 +93,12 @@ LL + fn f9<X>(x1: Box<S<X>>) {
|
error[E0277]: the size for values of type `X` cannot be known at compilation time
--> $DIR/unsized3.rs:45:9
--> $DIR/unsized3.rs:45:8
|
LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
| - this type parameter needs to be `std::marker::Sized`
LL | f5(&(32, *x1));
| ^^^^^^^^^ doesn't have a size known at compile-time
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
note: required because it appears within the type `S<X>`
--> $DIR/unsized3.rs:28:8
@ -113,35 +113,6 @@ LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
LL + fn f10<X>(x1: Box<S<X>>) {
|
error[E0277]: the size for values of type `X` cannot be known at compilation time
--> $DIR/unsized3.rs:45:8
|
LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
| - this type parameter needs to be `std::marker::Sized`
LL | f5(&(32, *x1));
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
note: required because it appears within the type `S<X>`
--> $DIR/unsized3.rs:28:8
|
LL | struct S<X: ?Sized> {
| ^
= note: required because it appears within the type `({integer}, S<X>)`
note: required by a bound in `f5`
--> $DIR/unsized3.rs:24:7
|
LL | fn f5<Y>(x: &Y) {}
| ^ required by this bound in `f5`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
LL + fn f10<X>(x1: Box<S<X>>) {
|
help: consider relaxing the implicit `Sized` restriction
|
LL | fn f5<Y: ?Sized>(x: &Y) {}
| ++++++++
error: aborting due to 6 previous errors
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0277`.