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:
parent
2b5ddf36fd
commit
284a8a9ce7
7 changed files with 64 additions and 51 deletions
|
@ -83,7 +83,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
/// version (resolve_vars_if_possible), this version will
|
/// version (resolve_vars_if_possible), this version will
|
||||||
/// also select obligations if it seems useful, in an effort
|
/// also select obligations if it seems useful, in an effort
|
||||||
/// to get more type information.
|
/// 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);
|
debug!("resolve_vars_with_obligations(ty={:?})", ty);
|
||||||
|
|
||||||
// No Infer()? Nothing needs doing.
|
// No Infer()? Nothing needs doing.
|
||||||
|
@ -103,7 +111,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// possible. This can help substantially when there are
|
// possible. This can help substantially when there are
|
||||||
// indirect dependencies that don't seem worth tracking
|
// indirect dependencies that don't seem worth tracking
|
||||||
// precisely.
|
// precisely.
|
||||||
self.select_obligations_where_possible(false, |_| {});
|
self.select_obligations_where_possible(false, mutate_fulfillment_errors);
|
||||||
ty = self.resolve_vars_if_possible(ty);
|
ty = self.resolve_vars_if_possible(ty);
|
||||||
|
|
||||||
debug!("resolve_vars_with_obligations: ty={:?}", ty);
|
debug!("resolve_vars_with_obligations: ty={:?}", ty);
|
||||||
|
|
|
@ -354,8 +354,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("checking the argument");
|
|
||||||
let formal_ty = formal_tys[i];
|
let formal_ty = formal_tys[i];
|
||||||
|
debug!("checking argument {}: {:?} = {:?}", i, arg, formal_ty);
|
||||||
|
|
||||||
// The special-cased logic below has three functions:
|
// The special-cased logic below has three functions:
|
||||||
// 1. Provide as good of an expected type as possible.
|
// 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
|
// to, which is `expected_ty` if `rvalue_hint` returns an
|
||||||
// `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
|
// `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
|
||||||
let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty);
|
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
|
// We're processing function arguments so we definitely want to use
|
||||||
// two-phase borrows.
|
// two-phase borrows.
|
||||||
self.demand_coerce(&arg, checked_ty, coerce_ty, None, AllowTwoPhase::Yes);
|
self.demand_coerce(&arg, checked_ty, coerce_ty, None, AllowTwoPhase::Yes);
|
||||||
|
|
|
@ -10,10 +10,10 @@ LL | f1(2i32, 4u32);
|
||||||
| ~~~
|
| ~~~
|
||||||
|
|
||||||
error[E0277]: the trait bound `u32: Foo` is not satisfied
|
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);
|
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`
|
note: required by a bound in `f1`
|
||||||
--> $DIR/associated-types-path-2.rs:13:14
|
--> $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
|
--> $DIR/associated-types-path-2.rs:29:5
|
||||||
|
|
|
|
||||||
LL | f1(2u32, 4u32);
|
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
|
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);
|
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`
|
note: required by a bound in `f1`
|
||||||
--> $DIR/associated-types-path-2.rs:13:14
|
--> $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
|
--> $DIR/associated-types-path-2.rs:35:5
|
||||||
|
|
|
|
||||||
LL | f1(2u32, 4i32);
|
LL | f1(2u32, 4i32);
|
||||||
| ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
|
| ^^ the trait `Foo` is not implemented for `u32`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/associated-types-path-2.rs:41:18
|
--> $DIR/associated-types-path-2.rs:41:18
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
error[E0631]: type mismatch in closure arguments
|
error[E0631]: type mismatch in closure arguments
|
||||||
--> $DIR/issue-62529-1.rs:80:10
|
--> $DIR/issue-62529-1.rs:80:10
|
||||||
|
|
|
|
||||||
LL | task(annotate(
|
LL | task(annotate(
|
||||||
| ^^^^^^^^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
|
| __________^
|
||||||
...
|
LL | |
|
||||||
LL | |value: &mut usize| {
|
LL | |
|
||||||
| ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
|
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`
|
note: required by a bound in `annotate`
|
||||||
--> $DIR/issue-62529-1.rs:44:8
|
--> $DIR/issue-62529-1.rs:44:8
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error[E0277]: the trait bound `&u32: Foo` is not satisfied
|
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)
|
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`
|
note: required by a bound in `trigger_error`
|
||||||
--> $DIR/issue-60218.rs:13:72
|
--> $DIR/issue-60218.rs:13:72
|
||||||
|
|
|
@ -44,8 +44,6 @@ fn f9<X: ?Sized>(x1: Box<S<X>>) {
|
||||||
fn f10<X: ?Sized>(x1: Box<S<X>>) {
|
fn f10<X: ?Sized>(x1: Box<S<X>>) {
|
||||||
f5(&(32, *x1));
|
f5(&(32, *x1));
|
||||||
//~^ ERROR the size for values of type
|
//~^ ERROR the size for values of type
|
||||||
//~| ERROR the size for values of type
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {}
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
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>>) {
|
LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
|
||||||
| - this type parameter needs to be `std::marker::Sized`
|
| - this type parameter needs to be `std::marker::Sized`
|
||||||
LL | f5(&(32, *x1));
|
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>`
|
note: required because it appears within the type `S<X>`
|
||||||
--> $DIR/unsized3.rs:28:8
|
--> $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>>) {
|
LL + fn f10<X>(x1: Box<S<X>>) {
|
||||||
|
|
|
|
||||||
|
|
||||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
error: aborting due to 5 previous errors
|
||||||
--> $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
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue