Skip to content

Commit e6bec64

Browse files
authored
Unrolled build for rust-lang#121826
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 5a1e544 + 40f9dcc commit e6bec64

File tree

58 files changed

+212
-157
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+212
-157
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
166166
return false;
167167
}
168168

169-
match ty.kind() {
169+
match ty.peel_refs().kind() {
170170
ty::Param(param) => {
171171
let generics = self.tcx.generics_of(self.body_id);
172172
let generic_param = generics.type_param(&param, self.tcx);
@@ -184,7 +184,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
184184
}
185185
}
186186
}
187-
ty::Alias(ty::AliasKind::Opaque, _) => {
187+
ty::Slice(..) | ty::Adt(..) | ty::Alias(ty::AliasKind::Opaque, _) => {
188188
for unsatisfied in unsatisfied_predicates.iter() {
189189
if is_iterator_predicate(unsatisfied.0, self.tcx) {
190190
return true;

compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs

+54-5
Original file line numberDiff line numberDiff line change
@@ -416,9 +416,59 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
416416
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
417417
let trait_predicate = bound_predicate.rebind(trait_predicate);
418418
let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
419-
let trait_ref = trait_predicate.to_poly_trait_ref();
420419

421-
if let Some(guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) {
420+
// Let's use the root obligation as the main message, when we care about the
421+
// most general case ("X doesn't implement Pattern<'_>") over the case that
422+
// happened to fail ("char doesn't implement Fn(&mut char)").
423+
//
424+
// We rely on a few heuristics to identify cases where this root
425+
// obligation is more important than the leaf obligation:
426+
let (main_trait_predicate, o) = if let ty::PredicateKind::Clause(
427+
ty::ClauseKind::Trait(root_pred)
428+
) = root_obligation.predicate.kind().skip_binder()
429+
&& !trait_predicate.self_ty().skip_binder().has_escaping_bound_vars()
430+
&& !root_pred.self_ty().has_escaping_bound_vars()
431+
// The type of the leaf predicate is (roughly) the same as the type
432+
// from the root predicate, as a proxy for "we care about the root"
433+
// FIXME: this doesn't account for trivial derefs, but works as a first
434+
// approximation.
435+
&& (
436+
// `T: Trait` && `&&T: OtherTrait`, we want `OtherTrait`
437+
self.can_eq(
438+
obligation.param_env,
439+
trait_predicate.self_ty().skip_binder(),
440+
root_pred.self_ty().peel_refs(),
441+
)
442+
// `&str: Iterator` && `&str: IntoIterator`, we want `IntoIterator`
443+
|| self.can_eq(
444+
obligation.param_env,
445+
trait_predicate.self_ty().skip_binder(),
446+
root_pred.self_ty(),
447+
)
448+
)
449+
// The leaf trait and the root trait are different, so as to avoid
450+
// talking about `&mut T: Trait` and instead remain talking about
451+
// `T: Trait` instead
452+
&& trait_predicate.def_id() != root_pred.def_id()
453+
// The root trait is not `Unsize`, as to avoid talking about it in
454+
// `tests/ui/coercion/coerce-issue-49593-box-never.rs`.
455+
&& Some(root_pred.def_id()) != self.tcx.lang_items().unsize_trait()
456+
{
457+
(
458+
self.resolve_vars_if_possible(
459+
root_obligation.predicate.kind().rebind(root_pred),
460+
),
461+
root_obligation,
462+
)
463+
} else {
464+
(trait_predicate, &obligation)
465+
};
466+
let trait_ref = main_trait_predicate.to_poly_trait_ref();
467+
468+
if let Some(guar) = self.emit_specialized_closure_kind_error(
469+
&obligation,
470+
trait_ref,
471+
) {
422472
return guar;
423473
}
424474

@@ -459,8 +509,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
459509
notes,
460510
parent_label,
461511
append_const_msg,
462-
} = self.on_unimplemented_note(trait_ref, &obligation, &mut long_ty_file);
463-
512+
} = self.on_unimplemented_note(trait_ref, o, &mut long_ty_file);
464513
let have_alt_message = message.is_some() || label.is_some();
465514
let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id());
466515
let is_unsize =
@@ -483,7 +532,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
483532
};
484533

485534
let err_msg = self.get_standard_error_message(
486-
&trait_predicate,
535+
&main_trait_predicate,
487536
message,
488537
predicate_is_const,
489538
append_const_msg,

library/core/src/future/future.rs

+1-2
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.

library/core/src/future/into_future.rs

+5
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")]

library/core/src/iter/traits/collect.rs

+43
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.

library/core/src/iter/traits/iterator.rs

+2-33
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"

tests/ui/associated-types/substs-ppaux.normal.stderr

+2-3
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,12 @@ help: use parentheses to call this function
7070
LL | let x: () = foo::<'static>();
7171
| ++
7272

73-
error[E0277]: the size for values of type `str` cannot be known at compilation time
73+
error[E0277]: the trait bound `str: Foo<'_, '_, u8>` is not satisfied
7474
--> $DIR/substs-ppaux.rs:49:6
7575
|
7676
LL | <str as Foo<u8>>::bar;
77-
| ^^^ doesn't have a size known at compile-time
77+
| ^^^ the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'_, '_, u8>`
7878
|
79-
= help: the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'_, '_, u8>`
8079
note: required for `str` to implement `Foo<'_, '_, u8>`
8180
--> $DIR/substs-ppaux.rs:11:17
8281
|

tests/ui/associated-types/substs-ppaux.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,6 @@ fn foo<'z>() where &'z (): Sized {
4747
//[normal]~| found fn item `fn() {foo::<'static>}`
4848

4949
<str as Foo<u8>>::bar;
50-
//[verbose]~^ ERROR the size for values of type
51-
//[normal]~^^ ERROR the size for values of type
50+
//[verbose]~^ ERROR the trait bound `str: Foo<'?0, '?1, u8>` is not satisfied
51+
//[normal]~^^ ERROR the trait bound `str: Foo<'_, '_, u8>` is not satisfied
5252
}

tests/ui/associated-types/substs-ppaux.verbose.stderr

+2-3
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,12 @@ help: use parentheses to call this function
7070
LL | let x: () = foo::<'static>();
7171
| ++
7272

73-
error[E0277]: the size for values of type `str` cannot be known at compilation time
73+
error[E0277]: the trait bound `str: Foo<'?0, '?1, u8>` is not satisfied
7474
--> $DIR/substs-ppaux.rs:49:6
7575
|
7676
LL | <str as Foo<u8>>::bar;
77-
| ^^^ doesn't have a size known at compile-time
77+
| ^^^ the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'?0, '?1, u8>`
7878
|
79-
= help: the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'?0, '?1, u8>`
8079
note: required for `str` to implement `Foo<'?0, '?1, u8>`
8180
--> $DIR/substs-ppaux.rs:11:17
8281
|

tests/ui/async-await/async-error-span.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ LL | fn get_future() -> impl Future<Output = ()> {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
66
|
77
= help: the trait `Future` is not implemented for `()`
8-
= note: () must be a future or must implement `IntoFuture` to be awaited
98

109
error[E0282]: type annotations needed
1110
--> $DIR/async-error-span.rs:13:9

tests/ui/async-await/coroutine-not-future.stderr

-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ LL | takes_future(returns_coroutine());
4949
| required by a bound introduced by this call
5050
|
5151
= help: the trait `Future` is not implemented for `impl Coroutine<Yield = (), Return = ()>`
52-
= note: impl Coroutine<Yield = (), Return = ()> must be a future or must implement `IntoFuture` to be awaited
5352
note: required by a bound in `takes_future`
5453
--> $DIR/coroutine-not-future.rs:17:26
5554
|
@@ -69,7 +68,6 @@ LL | | });
6968
| |_____^ `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}` is not a future
7069
|
7170
= help: the trait `Future` is not implemented for `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}`
72-
= note: {coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23} must be a future or must implement `IntoFuture` to be awaited
7371
note: required by a bound in `takes_future`
7472
--> $DIR/coroutine-not-future.rs:17:26
7573
|

tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ impl Signed for i32 { }
1717
fn main() {
1818
is_defaulted::<&'static i32>();
1919
is_defaulted::<&'static u32>();
20-
//~^ ERROR `u32: Signed` is not satisfied
20+
//~^ ERROR the trait bound `&'static u32: Defaulted` is not satisfied
2121
}

tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0277]: the trait bound `u32: Signed` is not satisfied
1+
error[E0277]: the trait bound `&'static u32: Defaulted` is not satisfied
22
--> $DIR/typeck-default-trait-impl-precedence.rs:19:20
33
|
44
LL | is_defaulted::<&'static u32>();
5-
| ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`, which is required by `&'static u32: Defaulted`
5+
| ^^^^^^^^^^^^ the trait `Signed` is not implemented for `&'static u32`, which is required by `&'static u32: Defaulted`
66
|
77
note: required for `&'static u32` to implement `Defaulted`
88
--> $DIR/typeck-default-trait-impl-precedence.rs:10:19

tests/ui/coroutine/gen_block_is_no_future.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ LL | fn foo() -> impl std::future::Future {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^ `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21}` is not a future
66
|
77
= help: the trait `Future` is not implemented for `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21}`
8-
= note: {gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21} must be a future or must implement `IntoFuture` to be awaited
98

109
error: aborting due to 1 previous error
1110

tests/ui/feature-gates/feature-gate-trivial_bounds.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ LL | fn use_for() where i32: Iterator {
7474
| ^^^^^^^^^^^^^ `i32` is not an iterator
7575
|
7676
= help: the trait `Iterator` is not implemented for `i32`
77-
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
7877
= help: see issue #48214
7978
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
8079

tests/ui/for/issue-20605.current.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0277]: the size for values of type `dyn Iterator<Item = &'a mut u8>` cannot be known at compilation time
1+
error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator
22
--> $DIR/issue-20605.rs:5:17
33
|
44
LL | for item in *things { *item = 0 }

tests/ui/for/issue-20605.next.stderr

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
error[E0277]: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
1+
error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator
22
--> $DIR/issue-20605.rs:5:17
33
|
44
LL | for item in *things { *item = 0 }
5-
| ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
5+
| ^^^^^^^ `dyn Iterator<Item = &'a mut u8>` is not an iterator
6+
|
7+
= help: the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
68

79
error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
810
--> $DIR/issue-20605.rs:5:17

tests/ui/for/issue-20605.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
fn changer<'a>(mut things: Box<dyn Iterator<Item=&'a mut u8>>) {
55
for item in *things { *item = 0 }
6-
//[current]~^ ERROR the size for values of type
7-
//[next]~^^ ERROR the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
6+
//[current]~^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
7+
//[next]~^^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
88
//[next]~| ERROR the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
99
//[next]~| ERROR the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
1010
//[next]~| ERROR the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed

tests/ui/impl-trait/issues/issue-83919.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ LL | fn get_fut(&self) -> Self::Fut {
55
| ^^^^^^^^^ `{integer}` is not a future
66
|
77
= help: the trait `Future` is not implemented for `{integer}`
8-
= note: {integer} must be a future or must implement `IntoFuture` to be awaited
98

109
error: aborting due to 1 previous error
1110

tests/ui/issues-71798.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ LL | *x
1414
| -- return type was inferred to be `u32` here
1515
|
1616
= help: the trait `Future` is not implemented for `u32`
17-
= note: u32 must be a future or must implement `IntoFuture` to be awaited
1817

1918
error: aborting due to 2 previous errors
2019

tests/ui/iterators/bound.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ LL | struct T(S<u8>);
55
| ^^^^^ `u8` is not an iterator
66
|
77
= help: the trait `Iterator` is not implemented for `u8`
8-
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
98
note: required by a bound in `S`
109
--> $DIR/bound.rs:1:13
1110
|
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//@ run-rustfix
2+
fn main() {
3+
let _ = vec![true, false].into_iter().map(|v| !v).collect::<Vec<_>>();
4+
//~^ ERROR no method named `map` found for struct `Vec<bool>` in the current scope
5+
}
+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1+
//@ run-rustfix
12
fn main() {
2-
vec![true, false].map(|v| !v).collect::<Vec<_>>();
3-
//~^ ERROR `Vec<bool>` is not an iterator
3+
let _ = vec![true, false].map(|v| !v).collect::<Vec<_>>();
4+
//~^ ERROR no method named `map` found for struct `Vec<bool>` in the current scope
45
}

0 commit comments

Comments
 (0)