Skip to content

Commit e7281d0

Browse files
authored
Rollup merge of #94746 - notriddle:notriddle/method-rustc-on-unimplemented, r=davidtwco
diagnostics: use rustc_on_unimplemented to recommend `[].iter()` To make this work, the `#[rustc_on_unimplemented]` data needs to be used to report method resolution errors, which is most of what this commit does. Fixes #94581
2 parents fe034cb + 32d7f81 commit e7281d0

File tree

11 files changed

+258
-162
lines changed

11 files changed

+258
-162
lines changed

compiler/rustc_middle/src/ty/sty.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1886,6 +1886,15 @@ impl<'tcx> Ty<'tcx> {
18861886
}
18871887
}
18881888

1889+
#[inline]
1890+
pub fn is_array_slice(self) -> bool {
1891+
match self.kind() {
1892+
Slice(_) => true,
1893+
RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => matches!(ty.kind(), Slice(_)),
1894+
_ => false,
1895+
}
1896+
}
1897+
18891898
#[inline]
18901899
pub fn is_array(self) -> bool {
18911900
matches!(self.kind(), Array(..))

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::iter;
1111

1212
use super::InferCtxtPrivExt;
1313

14-
crate trait InferCtxtExt<'tcx> {
14+
pub trait InferCtxtExt<'tcx> {
1515
/*private*/
1616
fn impl_similar_to(
1717
&self,
@@ -204,6 +204,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
204204
flags.push((sym::_Self, Some("{integral}".to_owned())));
205205
}
206206

207+
if self_ty.is_array_slice() {
208+
flags.push((sym::_Self, Some("&[]".to_owned())));
209+
}
210+
207211
if let ty::Array(aty, len) = self_ty.kind() {
208212
flags.push((sym::_Self, Some("[]".to_owned())));
209213
flags.push((sym::_Self, Some(format!("[{}]", aty))));

compiler/rustc_typeck/src/check/method/suggest.rs

+209-153
Large diffs are not rendered by default.

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

+5
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
3434
note = "`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \
3535
to have a bounded `RangeInclusive`: `0..=end`"
3636
),
37+
on(
38+
_Self = "[]",
39+
label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
40+
),
41+
on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"),
3742
on(
3843
_Self = "&str",
3944
label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0599]: the method `to_string` exists for raw pointer `*const u8`, but its trait bounds were not satisfied
1+
error[E0599]: `*const u8` doesn't implement `std::fmt::Display`
22
--> $DIR/issue-21596.rs:4:22
33
|
44
LL | println!("{}", z.to_string());
5-
| ^^^^^^^^^ method cannot be called on `*const u8` due to unsatisfied trait bounds
5+
| ^^^^^^^^^ `*const u8` cannot be formatted with the default formatter
66
|
77
= note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref
88
= note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn get_slice() -> &'static [i32] {
2+
&[1, 2, 3, 4]
3+
}
4+
5+
fn main() {
6+
let sqsum = get_slice().map(|i| i * i).sum(); //~ ERROR [E0599]
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0599]: `&'static [i32]` is not an iterator
2+
--> $DIR/issue-94581.rs:6:29
3+
|
4+
LL | let sqsum = get_slice().map(|i| i * i).sum();
5+
| ^^^ `&'static [i32]` is not an iterator; try calling `.iter()`
6+
|
7+
= note: the following trait bounds were not satisfied:
8+
`&'static [i32]: Iterator`
9+
which is required by `&mut &'static [i32]: Iterator`
10+
`[i32]: Iterator`
11+
which is required by `&mut [i32]: Iterator`
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0599`.

src/test/ui/methods/method-call-err-msg.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ fn main() {
1616

1717
let y = Foo;
1818
y.zero()
19-
.take() //~ ERROR the method
19+
.take() //~ ERROR not an iterator
2020
.one(0);
2121
y.three::<usize>(); //~ ERROR this function takes 3 arguments but 0 arguments were supplied
2222
}

src/test/ui/methods/method-call-err-msg.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ note: associated function defined here
4040
LL | fn two(self, _: isize, _: isize) -> Foo { self }
4141
| ^^^ ---- -------- --------
4242

43-
error[E0599]: the method `take` exists for struct `Foo`, but its trait bounds were not satisfied
43+
error[E0599]: `Foo` is not an iterator
4444
--> $DIR/method-call-err-msg.rs:19:7
4545
|
4646
LL | pub struct Foo;
@@ -50,7 +50,7 @@ LL | pub struct Foo;
5050
| doesn't satisfy `Foo: Iterator`
5151
...
5252
LL | .take()
53-
| ^^^^ method cannot be called on `Foo` due to unsatisfied trait bounds
53+
| ^^^^ `Foo` is not an iterator
5454
|
5555
= note: the following trait bounds were not satisfied:
5656
`Foo: Iterator`

src/test/ui/mismatched_types/issue-36053-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
use std::iter::once;
66
fn main() {
77
once::<&str>("str").fuse().filter(|a: &str| true).count();
8-
//~^ ERROR the method
8+
//~^ ERROR not an iterator
99
//~| ERROR type mismatch in closure arguments
1010
}

src/test/ui/mismatched_types/issue-36053-2.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ note: required by a bound in `filter`
1212
LL | P: FnMut(&Self::Item) -> bool,
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `filter`
1414

15-
error[E0599]: the method `count` exists for struct `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>`, but its trait bounds were not satisfied
15+
error[E0599]: `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` is not an iterator
1616
--> $DIR/issue-36053-2.rs:7:55
1717
|
1818
LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
19-
| -------------- ^^^^^ method cannot be called on `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` due to unsatisfied trait bounds
19+
| -------------- ^^^^^ `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` is not an iterator
2020
| |
2121
| doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool`
2222
| doesn't satisfy `_: FnMut<(&&str,)>`

0 commit comments

Comments
 (0)