Skip to content

Commit 74b6933

Browse files
authored
Rollup merge of rust-lang#121826 - estebank:e0277-root-obligation-2, r=oli-obk
Use root obligation on E0277 for some cases When encountering trait bound errors that satisfy some heuristics that tell us that the relevant trait for the user comes from the root obligation and not the current obligation, we use the root predicate for the main message. This allows to talk about "X doesn't implement Pattern<'_>" over the most specific case that just happened to fail, like "char doesn't implement Fn(&mut char)" in `tests/ui/traits/suggest-dereferences/root-obligation.rs` The heuristics are: - the type of the leaf predicate is (roughly) the same as the type from the root predicate, as a proxy for "we care about the root" - the leaf trait and the root trait are different, so as to avoid talking about `&mut T: Trait` and instead remain talking about `T: Trait` instead - the root trait is not `Unsize`, as to avoid talking about it in `tests/ui/coercion/coerce-issue-49593-box-never.rs`. ``` error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied --> $DIR/root-obligation.rs:6:38 | LL | .filter(|c| "aeiou".contains(c)) | -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>` | | | required by a bound introduced by this call | = note: required for `&char` to implement `FnOnce<(char,)>` = note: required for `&char` to implement `Pattern<'_>` note: required by a bound in `core::str::<impl str>::contains` --> $SRC_DIR/core/src/str/mod.rs:LL:COL help: consider dereferencing here | LL | .filter(|c| "aeiou".contains(*c)) | + ``` Fix rust-lang#79359, fix rust-lang#119983, fix rust-lang#118779, cc rust-lang#118415 (the suggestion needs to change), cc rust-lang#121398 (doesn't fix the underlying issue).
2 parents dfaeba0 + 660ab62 commit 74b6933

File tree

4 files changed

+51
-35
lines changed

4 files changed

+51
-35
lines changed

core/src/future/future.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ use crate::task::{Context, Poll};
3030
#[lang = "future_trait"]
3131
#[diagnostic::on_unimplemented(
3232
label = "`{Self}` is not a future",
33-
message = "`{Self}` is not a future",
34-
note = "{Self} must be a future or must implement `IntoFuture` to be awaited"
33+
message = "`{Self}` is not a future"
3534
)]
3635
pub trait Future {
3736
/// The type of value produced on completion.

core/src/future/into_future.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ use crate::future::Future;
100100
/// ```
101101
#[stable(feature = "into_future", since = "1.64.0")]
102102
#[rustc_diagnostic_item = "IntoFuture"]
103+
#[diagnostic::on_unimplemented(
104+
label = "`{Self}` is not a future",
105+
message = "`{Self}` is not a future",
106+
note = "{Self} must be a future or must implement `IntoFuture` to be awaited"
107+
)]
103108
pub trait IntoFuture {
104109
/// The output that the future will produce on completion.
105110
#[stable(feature = "into_future", since = "1.64.0")]

core/src/iter/traits/collect.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,49 @@ pub trait FromIterator<A>: Sized {
236236
/// ```
237237
#[rustc_diagnostic_item = "IntoIterator"]
238238
#[rustc_skip_array_during_method_dispatch]
239+
#[rustc_on_unimplemented(
240+
on(
241+
_Self = "core::ops::range::RangeTo<Idx>",
242+
label = "if you meant to iterate until a value, add a starting value",
243+
note = "`..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a \
244+
bounded `Range`: `0..end`"
245+
),
246+
on(
247+
_Self = "core::ops::range::RangeToInclusive<Idx>",
248+
label = "if you meant to iterate until a value (including it), add a starting value",
249+
note = "`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \
250+
to have a bounded `RangeInclusive`: `0..=end`"
251+
),
252+
on(
253+
_Self = "[]",
254+
label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
255+
),
256+
on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"),
257+
on(
258+
_Self = "alloc::vec::Vec<T, A>",
259+
label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
260+
),
261+
on(
262+
_Self = "&str",
263+
label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
264+
),
265+
on(
266+
_Self = "alloc::string::String",
267+
label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
268+
),
269+
on(
270+
_Self = "{integral}",
271+
note = "if you want to iterate between `start` until a value `end`, use the exclusive range \
272+
syntax `start..end` or the inclusive range syntax `start..=end`"
273+
),
274+
on(
275+
_Self = "{float}",
276+
note = "if you want to iterate between `start` until a value `end`, use the exclusive range \
277+
syntax `start..end` or the inclusive range syntax `start..=end`"
278+
),
279+
label = "`{Self}` is not an iterator",
280+
message = "`{Self}` is not an iterator"
281+
)]
239282
#[stable(feature = "rust1", since = "1.0.0")]
240283
pub trait IntoIterator {
241284
/// The type of the elements being iterated over.

core/src/iter/traits/iterator.rs

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,42 +28,11 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
2828
#[rustc_on_unimplemented(
2929
on(
3030
_Self = "core::ops::range::RangeTo<Idx>",
31-
label = "if you meant to iterate until a value, add a starting value",
32-
note = "`..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a \
33-
bounded `Range`: `0..end`"
31+
note = "you might have meant to use a bounded `Range`"
3432
),
3533
on(
3634
_Self = "core::ops::range::RangeToInclusive<Idx>",
37-
label = "if you meant to iterate until a value (including it), add a starting value",
38-
note = "`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \
39-
to have a bounded `RangeInclusive`: `0..=end`"
40-
),
41-
on(
42-
_Self = "[]",
43-
label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
44-
),
45-
on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"),
46-
on(
47-
_Self = "alloc::vec::Vec<T, A>",
48-
label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
49-
),
50-
on(
51-
_Self = "&str",
52-
label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
53-
),
54-
on(
55-
_Self = "alloc::string::String",
56-
label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
57-
),
58-
on(
59-
_Self = "{integral}",
60-
note = "if you want to iterate between `start` until a value `end`, use the exclusive range \
61-
syntax `start..end` or the inclusive range syntax `start..=end`"
62-
),
63-
on(
64-
_Self = "{float}",
65-
note = "if you want to iterate between `start` until a value `end`, use the exclusive range \
66-
syntax `start..end` or the inclusive range syntax `start..=end`"
35+
note = "you might have meant to use a bounded `RangeInclusive`"
6736
),
6837
label = "`{Self}` is not an iterator",
6938
message = "`{Self}` is not an iterator"

0 commit comments

Comments
 (0)