Skip to content

Confusing Error Message with Impl Trait in E0308 #48290

@WalkerCodeRanger

Description

@WalkerCodeRanger

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.C-enhancementCategory: An issue proposing an enhancement or a PR with one.D-confusingDiagnostics: Confusing error or lint that should be reworked.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.WG-diagnosticsWorking group: Diagnostics

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions