Skip to content

Commit 4be51c8

Browse files
committed
Point at type param when it's cause of unfulfilled obligation
1 parent 4e0437e commit 4be51c8

30 files changed

+176
-109
lines changed

src/librustc_typeck/check/callee.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
263263

264264
fn confirm_builtin_call(
265265
&self,
266-
call_expr: &hir::Expr,
266+
call_expr: &'tcx hir::Expr,
267267
callee_ty: Ty<'tcx>,
268268
arg_exprs: &'tcx [hir::Expr],
269269
expected: Expectation<'tcx>,
@@ -425,7 +425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
425425
);
426426
self.check_argument_types(
427427
call_expr.span,
428-
call_expr.span,
428+
call_expr,
429429
inputs,
430430
&expected_arg_tys[..],
431431
arg_exprs,
@@ -439,7 +439,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
439439

440440
fn confirm_deferred_closure_call(
441441
&self,
442-
call_expr: &hir::Expr,
442+
call_expr: &'tcx hir::Expr,
443443
arg_exprs: &'tcx [hir::Expr],
444444
expected: Expectation<'tcx>,
445445
fn_sig: ty::FnSig<'tcx>,
@@ -458,7 +458,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
458458

459459
self.check_argument_types(
460460
call_expr.span,
461-
call_expr.span,
461+
call_expr,
462462
fn_sig.inputs(),
463463
&expected_arg_tys,
464464
arg_exprs,
@@ -472,14 +472,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
472472

473473
fn confirm_overloaded_call(
474474
&self,
475-
call_expr: &hir::Expr,
475+
call_expr: &'tcx hir::Expr,
476476
arg_exprs: &'tcx [hir::Expr],
477477
expected: Expectation<'tcx>,
478478
method_callee: MethodCallee<'tcx>,
479479
) -> Ty<'tcx> {
480480
let output_type = self.check_method_argument_types(
481481
call_expr.span,
482-
call_expr.span,
482+
call_expr,
483483
Ok(method_callee),
484484
arg_exprs,
485485
TupleArgumentsFlag::TupleArguments,

src/librustc_typeck/check/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
796796
// Call the generic checker.
797797
self.check_method_argument_types(
798798
span,
799-
expr.span,
799+
expr,
800800
method,
801801
&args[1..],
802802
DontTupleArguments,

src/librustc_typeck/check/mod.rs

+70-9
Original file line numberDiff line numberDiff line change
@@ -3070,12 +3070,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30703070
fn check_method_argument_types(
30713071
&self,
30723072
sp: Span,
3073-
expr_sp: Span,
3073+
expr: &'tcx hir::Expr,
30743074
method: Result<MethodCallee<'tcx>, ()>,
30753075
args_no_rcvr: &'tcx [hir::Expr],
30763076
tuple_arguments: TupleArgumentsFlag,
30773077
expected: Expectation<'tcx>,
30783078
) -> Ty<'tcx> {
3079+
30793080
let has_error = match method {
30803081
Ok(method) => {
30813082
method.substs.references_error() || method.sig.references_error()
@@ -3090,8 +3091,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30903091
TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..])],
30913092
};
30923093

3093-
self.check_argument_types(sp, expr_sp, &err_inputs[..], &[], args_no_rcvr,
3094-
false, tuple_arguments, None);
3094+
self.check_argument_types(
3095+
sp,
3096+
expr,
3097+
&err_inputs[..],
3098+
&[],
3099+
args_no_rcvr,
3100+
false,
3101+
tuple_arguments,
3102+
None,
3103+
);
30953104
return self.tcx.types.err;
30963105
}
30973106

@@ -3103,9 +3112,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31033112
method.sig.output(),
31043113
&method.sig.inputs()[1..]
31053114
);
3106-
self.check_argument_types(sp, expr_sp, &method.sig.inputs()[1..], &expected_arg_tys[..],
3107-
args_no_rcvr, method.sig.c_variadic, tuple_arguments,
3108-
self.tcx.hir().span_if_local(method.def_id));
3115+
self.check_argument_types(
3116+
sp,
3117+
expr,
3118+
&method.sig.inputs()[1..],
3119+
&expected_arg_tys[..],
3120+
args_no_rcvr,
3121+
method.sig.c_variadic,
3122+
tuple_arguments,
3123+
self.tcx.hir().span_if_local(method.def_id),
3124+
);
31093125
method.sig.output()
31103126
}
31113127

@@ -3182,7 +3198,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31823198
fn check_argument_types(
31833199
&self,
31843200
sp: Span,
3185-
expr_sp: Span,
3201+
expr: &'tcx hir::Expr,
31863202
fn_inputs: &[Ty<'tcx>],
31873203
expected_arg_tys: &[Ty<'tcx>],
31883204
args: &'tcx [hir::Expr],
@@ -3191,7 +3207,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31913207
def_span: Option<Span>,
31923208
) {
31933209
let tcx = self.tcx;
3194-
31953210
// Grab the argument types, supplying fresh type variables
31963211
// if the wrong number of arguments were supplied
31973212
let supplied_arg_count = if tuple_arguments == DontTupleArguments {
@@ -3225,7 +3240,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32253240
err.span_label(def_s, "defined here");
32263241
}
32273242
if sugg_unit {
3228-
let sugg_span = tcx.sess.source_map().end_point(expr_sp);
3243+
let sugg_span = tcx.sess.source_map().end_point(expr.span);
32293244
// remove closing `)` from the span
32303245
let sugg_span = sugg_span.shrink_to_lo();
32313246
err.span_suggestion(
@@ -3319,6 +3334,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
33193334
// the call. This helps coercions.
33203335
if check_closures {
33213336
self.select_obligations_where_possible(false, |errors| {
3337+
self.point_at_type_arg_instead_of_call_if_possible(errors, expr);
33223338
self.point_at_arg_instead_of_call_if_possible(
33233339
errors,
33243340
&final_arg_types[..],
@@ -3456,6 +3472,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
34563472
}
34573473
}
34583474

3475+
/// Given a vec of evaluated `FullfillmentError`s and an `fn` call expression, we walk the
3476+
/// `PathSegment`s and resolve their type parameters to see if any of the `FullfillmentError`s
3477+
/// were caused by them. If they were, we point at the corresponding type argument's span
3478+
/// instead of the `fn` call path span.
3479+
fn point_at_type_arg_instead_of_call_if_possible(
3480+
&self,
3481+
errors: &mut Vec<traits::FulfillmentError<'_>>,
3482+
call_expr: &'tcx hir::Expr,
3483+
) {
3484+
if let hir::ExprKind::Call(path, _args) = &call_expr.node {
3485+
if let hir::ExprKind::Path(qpath) = &path.node {
3486+
if let hir::QPath::Resolved(_self, path) = &qpath {
3487+
for error in errors {
3488+
if let ty::Predicate::Trait(predicate) = error.obligation.predicate {
3489+
// If any of the type arguments in this path segment caused the
3490+
// `FullfillmentError`, point at its span (#61860).
3491+
for segment in &path.segments {
3492+
if let Some(args) = &segment.args {
3493+
for arg in &args.args {
3494+
if let hir::GenericArg::Type(hir_ty) = &arg {
3495+
if let hir::TyKind::Path(
3496+
hir::QPath::TypeRelative(..),
3497+
) = &hir_ty.node {
3498+
// Avoid ICE with associated types. As this is best
3499+
// effort only, it's ok to ignore the case. It
3500+
// would trigger in `is_send::<T::AssocType>();`
3501+
// from `typeck-default-trait-impl-assoc-type.rs`.
3502+
} else {
3503+
let ty = AstConv::ast_ty_to_ty(self, hir_ty);
3504+
let ty = self.resolve_vars_if_possible(&ty);
3505+
if ty == predicate.skip_binder().self_ty() {
3506+
error.obligation.cause.span = hir_ty.span;
3507+
}
3508+
}
3509+
}
3510+
}
3511+
}
3512+
}
3513+
}
3514+
}
3515+
}
3516+
}
3517+
}
3518+
}
3519+
34593520
// AST fragment checking
34603521
fn check_lit(&self,
34613522
lit: &hir::Lit,

src/test/ui/associated-types/associated-types-eq-hr.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ LL | bar::<IntStruct>();
2727
found type `&usize`
2828

2929
error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
30-
--> $DIR/associated-types-eq-hr.rs:91:5
30+
--> $DIR/associated-types-eq-hr.rs:91:17
3131
|
3232
LL | fn tuple_one<T>()
3333
| ---------
3434
LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>
3535
| ---------------------------------------------------------- required by this bound in `tuple_one`
3636
...
3737
LL | tuple_one::<Tuple>();
38-
| ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
38+
| ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
3939
|
4040
= help: the following implementations were found:
4141
<Tuple as TheTrait<(&'a isize, &'a isize)>>
@@ -52,15 +52,15 @@ LL | tuple_one::<Tuple>();
5252
| ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime
5353

5454
error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
55-
--> $DIR/associated-types-eq-hr.rs:97:5
55+
--> $DIR/associated-types-eq-hr.rs:97:17
5656
|
5757
LL | fn tuple_two<T>()
5858
| ---------
5959
LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>
6060
| ---------------------------------------------------------- required by this bound in `tuple_two`
6161
...
6262
LL | tuple_two::<Tuple>();
63-
| ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
63+
| ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
6464
|
6565
= help: the following implementations were found:
6666
<Tuple as TheTrait<(&'a isize, &'a isize)>>
@@ -77,15 +77,15 @@ LL | tuple_two::<Tuple>();
7777
| ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime
7878

7979
error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
80-
--> $DIR/associated-types-eq-hr.rs:107:5
80+
--> $DIR/associated-types-eq-hr.rs:107:18
8181
|
8282
LL | fn tuple_four<T>()
8383
| ----------
8484
LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)>
8585
| ------------------------------------------- required by this bound in `tuple_four`
8686
...
8787
LL | tuple_four::<Tuple>();
88-
| ^^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
88+
| ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
8989
|
9090
= help: the following implementations were found:
9191
<Tuple as TheTrait<(&'a isize, &'a isize)>>

src/test/ui/extern/extern-types-not-sync-send.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
error[E0277]: `A` cannot be shared between threads safely
2-
--> $DIR/extern-types-not-sync-send.rs:13:5
2+
--> $DIR/extern-types-not-sync-send.rs:13:19
33
|
44
LL | fn assert_sync<T: ?Sized + Sync>() { }
55
| ----------- ---- required by this bound in `assert_sync`
66
...
77
LL | assert_sync::<A>();
8-
| ^^^^^^^^^^^^^^^^ `A` cannot be shared between threads safely
8+
| ^ `A` cannot be shared between threads safely
99
|
1010
= help: the trait `std::marker::Sync` is not implemented for `A`
1111

1212
error[E0277]: `A` cannot be sent between threads safely
13-
--> $DIR/extern-types-not-sync-send.rs:16:5
13+
--> $DIR/extern-types-not-sync-send.rs:16:19
1414
|
1515
LL | fn assert_send<T: ?Sized + Send>() { }
1616
| ----------- ---- required by this bound in `assert_send`
1717
...
1818
LL | assert_send::<A>();
19-
| ^^^^^^^^^^^^^^^^ `A` cannot be sent between threads safely
19+
| ^ `A` cannot be sent between threads safely
2020
|
2121
= help: the trait `std::marker::Send` is not implemented for `A`
2222

src/test/ui/extern/extern-types-unsized.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0277]: the size for values of type `A` cannot be known at compilation time
2-
--> $DIR/extern-types-unsized.rs:22:5
2+
--> $DIR/extern-types-unsized.rs:22:20
33
|
44
LL | fn assert_sized<T>() { }
55
| ------------ - required by this bound in `assert_sized`
66
...
77
LL | assert_sized::<A>();
8-
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
8+
| ^ doesn't have a size known at compile-time
99
|
1010
= help: the trait `std::marker::Sized` is not implemented for `A`
1111
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

src/test/ui/hrtb/hrtb-conflate-regions.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied
2-
--> $DIR/hrtb-conflate-regions.rs:27:10
2+
--> $DIR/hrtb-conflate-regions.rs:27:22
33
|
44
LL | fn want_foo2<T>()
55
| ---------
66
LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)>
77
| -------------------------------------- required by this bound in `want_foo2`
88
...
99
LL | fn b() { want_foo2::<SomeStruct>(); }
10-
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct`
10+
| ^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct`
1111
|
1212
= help: the following implementations were found:
1313
<SomeStruct as Foo<(&'a isize, &'a isize)>>

src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: the trait bound `(): Trait<for<'b> fn(&'b u32)>` is not satisfied
2-
--> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5
2+
--> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:11
33
|
44
LL | fn foo<T>()
55
| ---
@@ -8,7 +8,7 @@ LL | T: Trait<for<'b> fn(&'b u32)>,
88
| -------------------------- required by this bound in `foo`
99
...
1010
LL | foo::<()>();
11-
| ^^^^^^^^^ the trait `Trait<for<'b> fn(&'b u32)>` is not implemented for `()`
11+
| ^^ the trait `Trait<for<'b> fn(&'b u32)>` is not implemented for `()`
1212
|
1313
= help: the following implementations were found:
1414
<() as Trait<fn(&'a u32)>>

src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: the trait bound `(): Trait<for<'b> fn(fn(&'b u32))>` is not satisfied
2-
--> $DIR/hrtb-exists-forall-trait-covariant.rs:36:5
2+
--> $DIR/hrtb-exists-forall-trait-covariant.rs:36:11
33
|
44
LL | fn foo<T>()
55
| ---
@@ -8,7 +8,7 @@ LL | T: Trait<for<'b> fn(fn(&'b u32))>,
88
| ------------------------------ required by this bound in `foo`
99
...
1010
LL | foo::<()>();
11-
| ^^^^^^^^^ the trait `Trait<for<'b> fn(fn(&'b u32))>` is not implemented for `()`
11+
| ^^ the trait `Trait<for<'b> fn(fn(&'b u32))>` is not implemented for `()`
1212
|
1313
= help: the following implementations were found:
1414
<() as Trait<fn(fn(&'a u32))>>

src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: the trait bound `(): Trait<for<'b> fn(std::cell::Cell<&'b u32>)>` is not satisfied
2-
--> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5
2+
--> $DIR/hrtb-exists-forall-trait-invariant.rs:28:11
33
|
44
LL | fn foo<T>()
55
| ---
@@ -8,7 +8,7 @@ LL | T: Trait<for<'b> fn(Cell<&'b u32>)>,
88
| -------------------------------- required by this bound in `foo`
99
...
1010
LL | foo::<()>();
11-
| ^^^^^^^^^ the trait `Trait<for<'b> fn(std::cell::Cell<&'b u32>)>` is not implemented for `()`
11+
| ^^ the trait `Trait<for<'b> fn(std::cell::Cell<&'b u32>)>` is not implemented for `()`
1212
|
1313
= help: the following implementations were found:
1414
<() as Trait<fn(std::cell::Cell<&'a u32>)>>

src/test/ui/hrtb/hrtb-just-for-static.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied
2-
--> $DIR/hrtb-just-for-static.rs:24:5
2+
--> $DIR/hrtb-just-for-static.rs:24:17
33
|
44
LL | fn want_hrtb<T>()
55
| ---------
66
LL | where T : for<'a> Foo<&'a isize>
77
| ---------------------- required by this bound in `want_hrtb`
88
...
99
LL | want_hrtb::<StaticInt>()
10-
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt`
10+
| ^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt`
1111
|
1212
= help: the following implementations were found:
1313
<StaticInt as Foo<&'static isize>>
1414

1515
error[E0277]: the trait bound `for<'a> &'a u32: Foo<&'a isize>` is not satisfied
16-
--> $DIR/hrtb-just-for-static.rs:30:5
16+
--> $DIR/hrtb-just-for-static.rs:30:17
1717
|
1818
LL | fn want_hrtb<T>()
1919
| ---------
2020
LL | where T : for<'a> Foo<&'a isize>
2121
| ---------------------- required by this bound in `want_hrtb`
2222
...
2323
LL | want_hrtb::<&'a u32>()
24-
| ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `&'a u32`
24+
| ^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `&'a u32`
2525
|
2626
= help: the following implementations were found:
2727
<&'a u32 as Foo<&'a isize>>

0 commit comments

Comments
 (0)