Skip to content

Commit 0a985f2

Browse files
committed
Tweak unsatisfied HRTB errors
1 parent a44881d commit 0a985f2

11 files changed

+148
-62
lines changed

src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs

+31-22
Original file line numberDiff line numberDiff line change
@@ -192,23 +192,28 @@ impl NiceRegionError<'me, 'tcx> {
192192
vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs
193193
);
194194

195-
let mut err = self.tcx().sess.struct_span_err(
196-
cause.span(self.tcx()),
197-
&format!(
198-
"implementation of `{}` is not general enough",
199-
self.tcx().def_path_str(trait_def_id),
200-
),
195+
let span = cause.span(self.tcx());
196+
let msg = format!(
197+
"implementation of `{}` is not general enough",
198+
self.tcx().def_path_str(trait_def_id),
199+
);
200+
let mut err = self.tcx().sess.struct_span_err(span, &msg);
201+
err.span_label(
202+
self.tcx().def_span(trait_def_id),
203+
format!("trait `{}` defined here", self.tcx().def_path_str(trait_def_id)),
201204
);
202205

203-
match cause.code {
204-
ObligationCauseCode::ItemObligation(def_id) => {
205-
err.note(&format!(
206-
"Due to a where-clause on `{}`,",
207-
self.tcx().def_path_str(def_id),
208-
));
209-
}
210-
_ => (),
211-
}
206+
let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = cause.code {
207+
err.span_label(span, "doesn't satisfy where-clause");
208+
err.span_label(
209+
self.tcx().def_span(def_id),
210+
&format!("due to a where-clause on `{}`...", self.tcx().def_path_str(def_id)),
211+
);
212+
true
213+
} else {
214+
err.span_label(span, &msg);
215+
false
216+
};
212217

213218
let expected_trait_ref = self.infcx.resolve_vars_if_possible(&ty::TraitRef {
214219
def_id: trait_def_id,
@@ -295,6 +300,7 @@ impl NiceRegionError<'me, 'tcx> {
295300
expected_has_vid,
296301
actual_has_vid,
297302
any_self_ty_has_vid,
303+
leading_ellipsis,
298304
);
299305

300306
err
@@ -318,6 +324,7 @@ impl NiceRegionError<'me, 'tcx> {
318324
expected_has_vid: Option<usize>,
319325
actual_has_vid: Option<usize>,
320326
any_self_ty_has_vid: bool,
327+
leading_ellipsis: bool,
321328
) {
322329
// HACK(eddyb) maybe move this in a more central location.
323330
#[derive(Copy, Clone)]
@@ -392,13 +399,15 @@ impl NiceRegionError<'me, 'tcx> {
392399

393400
let mut note = if passive_voice {
394401
format!(
395-
"`{}` would have to be implemented for the type `{}`",
402+
"{}`{}` would have to be implemented for the type `{}`",
403+
if leading_ellipsis { "..." } else { "" },
396404
expected_trait_ref,
397405
expected_trait_ref.map(|tr| tr.self_ty()),
398406
)
399407
} else {
400408
format!(
401-
"`{}` must implement `{}`",
409+
"{}`{}` must implement `{}`",
410+
if leading_ellipsis { "..." } else { "" },
402411
expected_trait_ref.map(|tr| tr.self_ty()),
403412
expected_trait_ref,
404413
)
@@ -407,20 +416,20 @@ impl NiceRegionError<'me, 'tcx> {
407416
match (has_sub, has_sup) {
408417
(Some(n1), Some(n2)) => {
409418
let _ = write!(note,
410-
", for any two lifetimes `'{}` and `'{}`",
419+
", for any two lifetimes `'{}` and `'{}`...",
411420
std::cmp::min(n1, n2),
412421
std::cmp::max(n1, n2),
413422
);
414423
}
415424
(Some(n), _) | (_, Some(n)) => {
416425
let _ = write!(note,
417-
", for any lifetime `'{}`",
426+
", for any lifetime `'{}`...",
418427
n,
419428
);
420429
}
421430
(None, None) => if let Some(n) = expected_has_vid {
422431
let _ = write!(note,
423-
", for some specific lifetime `'{}`",
432+
", for some specific lifetime `'{}`...",
424433
n,
425434
);
426435
},
@@ -439,13 +448,13 @@ impl NiceRegionError<'me, 'tcx> {
439448

440449
let mut note = if passive_voice {
441450
format!(
442-
"but `{}` is actually implemented for the type `{}`",
451+
"...but `{}` is actually implemented for the type `{}`",
443452
actual_trait_ref,
444453
actual_trait_ref.map(|tr| tr.self_ty()),
445454
)
446455
} else {
447456
format!(
448-
"but `{}` actually implements `{}`",
457+
"...but `{}` actually implements `{}`",
449458
actual_trait_ref.map(|tr| tr.self_ty()),
450459
actual_trait_ref,
451460
)
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
error: implementation of `Foo` is not general enough
22
--> $DIR/auto-trait-regions.rs:30:5
33
|
4+
LL | auto trait Foo {}
5+
| ----------------- trait `Foo` defined here
6+
...
47
LL | assert_foo(gen);
5-
| ^^^^^^^^^^
8+
| ^^^^^^^^^^ implementation of `Foo` is not general enough
69
|
7-
= note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0`
8-
= note: but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1`
10+
= note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0`...
11+
= note: ...but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1`
912

1013
error: implementation of `Foo` is not general enough
1114
--> $DIR/auto-trait-regions.rs:48:5
1215
|
16+
LL | auto trait Foo {}
17+
| ----------------- trait `Foo` defined here
18+
...
1319
LL | assert_foo(gen);
14-
| ^^^^^^^^^^
20+
| ^^^^^^^^^^ implementation of `Foo` is not general enough
1521
|
16-
= note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`
17-
= note: but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
22+
= note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`...
23+
= note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
1824

1925
error: aborting due to 2 previous errors
2026

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// ignore-compare-mode-nll
2+
// ^ This code works in nll mode.
3+
4+
fn main() {
5+
test::<FooS>(&mut 42); //~ ERROR implementation of `Foo` is not general enough
6+
}
7+
8+
trait Foo<'a> {}
9+
10+
struct FooS<'a> {
11+
data: &'a mut u32,
12+
}
13+
14+
impl<'a, 'b: 'a> Foo<'b> for FooS<'a> {}
15+
16+
fn test<'a, F>(data: &'a mut u32) where F: for<'b> Foo<'b> {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error: implementation of `Foo` is not general enough
2+
--> $DIR/due-to-where-clause.rs:5:5
3+
|
4+
LL | test::<FooS>(&mut 42);
5+
| ^^^^^^^^^^^^ doesn't satisfy where-clause
6+
...
7+
LL | trait Foo<'a> {}
8+
| ---------------- trait `Foo` defined here
9+
...
10+
LL | fn test<'a, F>(data: &'a mut u32) where F: for<'b> Foo<'b> {}
11+
| ------------------------------------------------------------- due to a where-clause on `test`...
12+
|
13+
= note: ...`FooS<'_>` must implement `Foo<'0>`, for any lifetime `'0`...
14+
= note: ...but `FooS<'_>` actually implements `Foo<'1>`, for some specific lifetime `'1`
15+
16+
error: aborting due to previous error
17+
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
error: implementation of `Deserialize` is not general enough
22
--> $DIR/hrtb-cache-issue-54302.rs:19:5
33
|
4+
LL | trait Deserialize<'de> {}
5+
| ------------------------- trait `Deserialize` defined here
6+
...
47
LL | assert_deserialize_owned::<&'static str>();
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough
69
|
7-
= note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`
8-
= note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
10+
= note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`...
11+
= note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
912

1013
error: aborting due to previous error
1114

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
error: implementation of `Stream` is not general enough
22
--> $DIR/issue-30786.rs:108:22
33
|
4-
LL | let map = source.map(|x: &_| x);
5-
| ^^^
4+
LL | / pub trait Stream {
5+
LL | | type Item;
6+
LL | | fn next(self) -> Option<Self::Item>;
7+
LL | | }
8+
| |_- trait `Stream` defined here
9+
...
10+
LL | let map = source.map(|x: &_| x);
11+
| ^^^ implementation of `Stream` is not general enough
612
|
7-
= note: `Stream` would have to be implemented for the type `&'0 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for any lifetime `'0`
8-
= note: but `Stream` is actually implemented for the type `&'1 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for some specific lifetime `'1`
13+
= note: `Stream` would have to be implemented for the type `&'0 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for any lifetime `'0`...
14+
= note: ...but `Stream` is actually implemented for the type `&'1 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for some specific lifetime `'1`
915

1016
error: aborting due to previous error
1117

src/test/ui/hrtb/issue-30786.nll.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error: higher-ranked subtype error
2-
--> $DIR/issue-30786.rs:112:18
2+
--> $DIR/issue-30786.rs:113:18
33
|
44
LL | let filter = map.filter(|x: &_| true);
55
| ^^^^^^^^^^^^^^^^^^^^^^^^
66

77
error: higher-ranked subtype error
8-
--> $DIR/issue-30786.rs:114:17
8+
--> $DIR/issue-30786.rs:115:17
99
|
1010
LL | let count = filter.count(); // Assert that we still have a valid stream.
1111
| ^^^^^^^^^^^^^^

src/test/ui/hrtb/issue-30786.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
//[nll]compile-flags: -Z borrowck=mir
1818

19-
pub trait Stream {
19+
pub trait Stream { //[migrate]~ NOTE trait `Stream` defined here
2020
type Item;
2121
fn next(self) -> Option<Self::Item>;
2222
}
@@ -109,6 +109,7 @@ fn main() {
109109
//[migrate]~^ ERROR implementation of `Stream` is not general enough
110110
//[migrate]~| NOTE `Stream` would have to be implemented for the type `&'0 mut Map
111111
//[migrate]~| NOTE but `Stream` is actually implemented for the type `&'1
112+
//[migrate]~| NOTE implementation of `Stream` is not general enough
112113
let filter = map.filter(|x: &_| true);
113114
//[nll]~^ ERROR higher-ranked subtype error
114115
let count = filter.count(); // Assert that we still have a valid stream.
+37-17
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,58 @@
11
error: implementation of `Foo` is not general enough
22
--> $DIR/issue-54302-cases.rs:63:5
33
|
4-
LL | <u32 as RefFoo<u32>>::ref_foo(a)
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6-
|
7-
= note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`
8-
= note: but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
4+
LL | / trait Foo<'x, T> {
5+
LL | | fn foo(self) -> &'x T;
6+
LL | | }
7+
| |_- trait `Foo` defined here
8+
...
9+
LL | <u32 as RefFoo<u32>>::ref_foo(a)
10+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
11+
|
12+
= note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
13+
= note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
914

1015
error: implementation of `Foo` is not general enough
1116
--> $DIR/issue-54302-cases.rs:69:5
1217
|
13-
LL | <i32 as RefFoo<i32>>::ref_foo(a)
14-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
LL | / trait Foo<'x, T> {
19+
LL | | fn foo(self) -> &'x T;
20+
LL | | }
21+
| |_- trait `Foo` defined here
22+
...
23+
LL | <i32 as RefFoo<i32>>::ref_foo(a)
24+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
1525
|
16-
= note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`
17-
= note: but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1`
26+
= note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`...
27+
= note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1`
1828

1929
error: implementation of `Foo` is not general enough
2030
--> $DIR/issue-54302-cases.rs:75:5
2131
|
22-
LL | <u64 as RefFoo<u64>>::ref_foo(a)
23-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32+
LL | / trait Foo<'x, T> {
33+
LL | | fn foo(self) -> &'x T;
34+
LL | | }
35+
| |_- trait `Foo` defined here
36+
...
37+
LL | <u64 as RefFoo<u64>>::ref_foo(a)
38+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
2439
|
25-
= note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`
26-
= note: but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1`
40+
= note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`...
41+
= note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1`
2742

2843
error: implementation of `Foo` is not general enough
2944
--> $DIR/issue-54302-cases.rs:81:5
3045
|
31-
LL | <i64 as RefFoo<i64>>::ref_foo(a)
32-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46+
LL | / trait Foo<'x, T> {
47+
LL | | fn foo(self) -> &'x T;
48+
LL | | }
49+
| |_- trait `Foo` defined here
50+
...
51+
LL | <i64 as RefFoo<i64>>::ref_foo(a)
52+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
3353
|
34-
= note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`
35-
= note: but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1`
54+
= note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`...
55+
= note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1`
3656

3757
error: aborting due to 4 previous errors
3858

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

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
error: implementation of `Deserialize` is not general enough
22
--> $DIR/issue-54302.rs:13:5
33
|
4+
LL | trait Deserialize<'de> {}
5+
| ------------------------- trait `Deserialize` defined here
6+
...
47
LL | assert_deserialize_owned::<&'static str>();
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough
69
|
7-
= note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`
8-
= note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
10+
= note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`...
11+
= note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
912

1013
error: aborting due to previous error
1114

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

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
error: implementation of `DistributedIteratorMulti` is not general enough
22
--> $DIR/issue-55731.rs:48:5
33
|
4-
LL | multi(Map {
5-
| ^^^^^
4+
LL | / trait DistributedIteratorMulti<Source> {
5+
LL | | type Item;
6+
LL | | }
7+
| |_- trait `DistributedIteratorMulti` defined here
8+
...
9+
LL | multi(Map {
10+
| ^^^^^ implementation of `DistributedIteratorMulti` is not general enough
611
|
7-
= note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`
8-
= note: but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1`
12+
= note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`...
13+
= note: ...but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1`
914

1015
error: aborting due to previous error
1116

0 commit comments

Comments
 (0)