Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 284a8a9

Browse files
committed
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.
1 parent 2b5ddf3 commit 284a8a9

File tree

7 files changed

+63
-50
lines changed

7 files changed

+63
-50
lines changed

compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8383
/// version (resolve_vars_if_possible), this version will
8484
/// also select obligations if it seems useful, in an effort
8585
/// to get more type information.
86-
pub(in super::super) fn resolve_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
86+
pub(in super::super) fn resolve_vars_with_obligations(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
87+
self.resolve_vars_with_obligations_and_mutate_fulfillment(ty, |_| {})
88+
}
89+
90+
pub(in super::super) fn resolve_vars_with_obligations_and_mutate_fulfillment(
91+
&self,
92+
mut ty: Ty<'tcx>,
93+
mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
94+
) -> Ty<'tcx> {
8795
debug!("resolve_vars_with_obligations(ty={:?})", ty);
8896

8997
// No Infer()? Nothing needs doing.
@@ -103,7 +111,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
103111
// possible. This can help substantially when there are
104112
// indirect dependencies that don't seem worth tracking
105113
// precisely.
106-
self.select_obligations_where_possible(false, |_| {});
114+
self.select_obligations_where_possible(false, mutate_fulfillment_errors);
107115
ty = self.resolve_vars_if_possible(ty);
108116

109117
debug!("resolve_vars_with_obligations: ty={:?}", ty);

compiler/rustc_typeck/src/check/fn_ctxt/checks.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
354354
continue;
355355
}
356356

357-
debug!("checking the argument");
358357
let formal_ty = formal_tys[i];
358+
debug!("checking argument {}: {:?} = {:?}", i, arg, formal_ty);
359359

360360
// The special-cased logic below has three functions:
361361
// 1. Provide as good of an expected type as possible.
@@ -367,6 +367,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
367367
// to, which is `expected_ty` if `rvalue_hint` returns an
368368
// `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
369369
let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty);
370+
371+
// Cause selection errors caused by resolving a single argument to point at the
372+
// argument and not the call. This is otherwise redundant with the `demand_coerce`
373+
// call immediately after, but it lets us customize the span pointed to in the
374+
// fulfillment error to be more accurate.
375+
let _ = self.resolve_vars_with_obligations_and_mutate_fulfillment(
376+
coerce_ty,
377+
|errors| {
378+
// This is not coming from a macro or a `derive`.
379+
if sp.desugaring_kind().is_none()
380+
&& !arg.span.from_expansion()
381+
// Do not change the spans of `async fn`s.
382+
&& !matches!(
383+
expr.kind,
384+
hir::ExprKind::Call(
385+
hir::Expr {
386+
kind: hir::ExprKind::Path(hir::QPath::LangItem(_, _)),
387+
..
388+
},
389+
_
390+
)
391+
) {
392+
for error in errors {
393+
error.obligation.cause.make_mut().span = arg.span;
394+
error.points_at_arg_span = true;
395+
}
396+
}
397+
},
398+
);
399+
370400
// We're processing function arguments so we definitely want to use
371401
// two-phase borrows.
372402
self.demand_coerce(&arg, checked_ty, coerce_ty, None, AllowTwoPhase::Yes);

src/test/ui/associated-types/associated-types-path-2.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ LL | f1(2i32, 4u32);
1010
| ~~~
1111

1212
error[E0277]: the trait bound `u32: Foo` is not satisfied
13-
--> $DIR/associated-types-path-2.rs:29:5
13+
--> $DIR/associated-types-path-2.rs:29:14
1414
|
1515
LL | f1(2u32, 4u32);
16-
| ^^ the trait `Foo` is not implemented for `u32`
16+
| ^^^^ the trait `Foo` is not implemented for `u32`
1717
|
1818
note: required by a bound in `f1`
1919
--> $DIR/associated-types-path-2.rs:13:14
@@ -25,13 +25,13 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied
2525
--> $DIR/associated-types-path-2.rs:29:5
2626
|
2727
LL | f1(2u32, 4u32);
28-
| ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
28+
| ^^ the trait `Foo` is not implemented for `u32`
2929

3030
error[E0277]: the trait bound `u32: Foo` is not satisfied
31-
--> $DIR/associated-types-path-2.rs:35:5
31+
--> $DIR/associated-types-path-2.rs:35:14
3232
|
3333
LL | f1(2u32, 4i32);
34-
| ^^ the trait `Foo` is not implemented for `u32`
34+
| ^^^^ the trait `Foo` is not implemented for `u32`
3535
|
3636
note: required by a bound in `f1`
3737
--> $DIR/associated-types-path-2.rs:13:14
@@ -43,7 +43,7 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied
4343
--> $DIR/associated-types-path-2.rs:35:5
4444
|
4545
LL | f1(2u32, 4i32);
46-
| ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
46+
| ^^ the trait `Foo` is not implemented for `u32`
4747

4848
error[E0308]: mismatched types
4949
--> $DIR/associated-types-path-2.rs:41:18

src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
error[E0631]: type mismatch in closure arguments
22
--> $DIR/issue-62529-1.rs:80:10
33
|
4-
LL | task(annotate(
5-
| ^^^^^^^^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
6-
...
7-
LL | |value: &mut usize| {
8-
| ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
4+
LL | task(annotate(
5+
| __________^
6+
LL | |
7+
LL | |
8+
LL | | Annotate::<RefMutFamily<usize>>::new(),
9+
LL | | |value: &mut usize| {
10+
| | ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
11+
LL | | *value = 2;
12+
LL | | }
13+
LL | | ));
14+
| |_____^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
915
|
1016
note: required by a bound in `annotate`
1117
--> $DIR/issue-62529-1.rs:44:8

src/test/ui/issues/issue-60218.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0277]: the trait bound `&u32: Foo` is not satisfied
2-
--> $DIR/issue-60218.rs:18:5
2+
--> $DIR/issue-60218.rs:18:27
33
|
44
LL | trigger_error(vec![], |x: &u32| x)
5-
| ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32`
5+
| ^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32`
66
|
77
note: required by a bound in `trigger_error`
88
--> $DIR/issue-60218.rs:13:72

src/test/ui/unsized/unsized3.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ fn f9<X: ?Sized>(x1: Box<S<X>>) {
4444
fn f10<X: ?Sized>(x1: Box<S<X>>) {
4545
f5(&(32, *x1));
4646
//~^ ERROR the size for values of type
47-
//~| ERROR the size for values of type
4847
}
4948

50-
pub fn main() {
51-
}
49+
pub fn main() {}

src/test/ui/unsized/unsized3.stderr

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -92,27 +92,6 @@ LL - fn f9<X: ?Sized>(x1: Box<S<X>>) {
9292
LL + fn f9<X>(x1: Box<S<X>>) {
9393
|
9494

95-
error[E0277]: the size for values of type `X` cannot be known at compilation time
96-
--> $DIR/unsized3.rs:45:9
97-
|
98-
LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
99-
| - this type parameter needs to be `std::marker::Sized`
100-
LL | f5(&(32, *x1));
101-
| ^^^^^^^^^ doesn't have a size known at compile-time
102-
|
103-
note: required because it appears within the type `S<X>`
104-
--> $DIR/unsized3.rs:28:8
105-
|
106-
LL | struct S<X: ?Sized> {
107-
| ^
108-
= note: required because it appears within the type `({integer}, S<X>)`
109-
= note: tuples must have a statically known size to be initialized
110-
help: consider removing the `?Sized` bound to make the type parameter `Sized`
111-
|
112-
LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
113-
LL + fn f10<X>(x1: Box<S<X>>) {
114-
|
115-
11695
error[E0277]: the size for values of type `X` cannot be known at compilation time
11796
--> $DIR/unsized3.rs:45:8
11897
|
@@ -127,21 +106,13 @@ note: required because it appears within the type `S<X>`
127106
LL | struct S<X: ?Sized> {
128107
| ^
129108
= note: required because it appears within the type `({integer}, S<X>)`
130-
note: required by a bound in `f5`
131-
--> $DIR/unsized3.rs:24:7
132-
|
133-
LL | fn f5<Y>(x: &Y) {}
134-
| ^ required by this bound in `f5`
109+
= note: tuples must have a statically known size to be initialized
135110
help: consider removing the `?Sized` bound to make the type parameter `Sized`
136111
|
137112
LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
138113
LL + fn f10<X>(x1: Box<S<X>>) {
139114
|
140-
help: consider relaxing the implicit `Sized` restriction
141-
|
142-
LL | fn f5<Y: ?Sized>(x: &Y) {}
143-
| ++++++++
144115

145-
error: aborting due to 6 previous errors
116+
error: aborting due to 5 previous errors
146117

147118
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)