-
-
Notifications
You must be signed in to change notification settings - Fork 14.6k
Description
While trying out the new impl trait feature #34511, I wrote some incorrect code. The error message was confusing to me. I've simplified the code and in the process found a very similar error message that is much clearer. My example shows both.
The code (which can be run in the playground on nightly):
#![feature(conservative_impl_trait)]
use std::iter;
fn mask<T: Iterator<Item = i32>>(iter: T) -> impl Iterator<Item = i32> {
return iter;
}
// this compile error clearly indicated the role of the impl trait
fn test_clear_error_message(condition: bool) -> impl Iterator<Item = i32> {
if condition {
mask(iter::once(23))
} else {
mask(1..23)
}
}
// this error message is confusing because the compiler has inferred through
// the impl trait, but gives no indication it has done so
fn test_confusing_error_message(condition: bool) -> impl Iterator<Item = i32> {
if condition {
return mask(iter::once(23));
}
mask(1..23)
}
fn main() {
test_clear_error_message(true);
test_confusing_error_message(true);
}The first error message is clear. It indicates that impl trait types are involved and that it has figured out what their underlying types are with this nice notation `impl std::iter::Iterator` (struct `std::iter::Once`).
error[E0308]: if and else have incompatible types
--> src/main.rs:11:5
|
11 | / if condition {
12 | | mask(iter::once(23))
13 | | } else {
14 | | mask(1..23)
15 | | }
| |_____^ expected struct `std::iter::Once`, found struct `std::ops::Range`
|
= note: expected type `impl std::iter::Iterator` (struct `std::iter::Once`)
found type `impl std::iter::Iterator` (struct `std::ops::Range`)
The second error message is the confusing one. I understand that the compiler has inferred the types and that the types the error message names are not impl trait types. However, it's surprising that the real types are leaking out. I feel like the error message needs to indicate that the inference has passed through the impl trait types. I imagine that something similar could happen in a case where one of the two types was coming from code in a third-party crate. That would be very confusing.
error[E0308]: mismatched types
--> src/main.rs:24:10
|
24 | mask(1..23)
| ^^^^^ expected struct `std::iter::Once`, found struct `std::ops::Range`
|
= note: expected type `std::iter::Once<i32>`
found type `std::ops::Range<{integer}>`
Compiler Version
>rustc --version --verbose
rustc 1.25.0-nightly (3ec5a99aa 2018-02-14)
binary: rustc
commit-hash: 3ec5a99aaa0084d97a9e845b34fdf03d1462c475
commit-date: 2018-02-14
host: x86_64-pc-windows-msvc
release: 1.25.0-nightly
LLVM version: 6.0