Skip to content

anyhow Result + collect = missleading error messages #129269

@wiiznokes

Description

@wiiznokes

Code

use std::fmt::Display;
use anyhow::Result;

#[derive(Debug)]
pub struct Error {}

impl std::error::Error for Error {}

impl Display for Error {
    fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        todo!()
    }
}

#[derive(Ord, PartialEq, PartialOrd, Eq)]
pub struct Version {}

fn parse(_s: &str) -> std::result::Result<Version, Error> {
    todo!()
}

pub fn error1(lines: &[&str]) -> Result<Vec<Version>> {
    let mut tags = lines.iter().map(|e| parse(e)).collect()?;

    tags.sort();

    Ok(tags)
}

pub fn error2(lines: &[&str]) -> Result<Vec<Version>> {
    let mut tags: Vec<Version> = lines.iter().map(|e| parse(e)).collect()?;
    tags.sort();

    Ok(tags)
}

pub fn error3(lines: &[&str]) -> Result<Vec<Version>> {
    let mut tags = lines.iter().map(|e| parse(e)).collect::<Vec<_>>()?;
    tags.sort();

    Ok(tags)
}

pub fn error4(lines: &[&str]) -> Result<Vec<Version>> {
    let mut tags = lines
        .iter()
        .map(|e| parse(e))
        .collect::<Result<Vec<Version>>>()?;
    tags.sort();

    Ok(tags)
}

pub fn correct(lines: &[&str]) -> Result<Vec<Version>> {
    let mut tags = lines
        .iter()
        .map(|e| parse(e))
        .collect::<Result<Vec<Version>, _>>()?;
    tags.sort();

    Ok(tags)
}

Current output

error[E0282]: type annotations needed
  --> src/lib.rs:23:9
   |
23 |     let mut tags = lines.iter().map(|e| parse(e)).collect()?;
   |         ^^^^^^^^
24 |
25 |     tags.sort();
   |     ---- type must be known at this point
   |
help: consider giving `tags` an explicit type
   |
23 |     let mut tags: /* Type */ = lines.iter().map(|e| parse(e)).collect()?;
   |                 ++++++++++++

error[E0283]: type annotations needed
    --> src/lib.rs:31:65
     |
31   |     let mut tags: Vec<Version> = lines.iter().map(|e| parse(e)).collect()?;
     |                                                                 ^^^^^^^ cannot infer type of the type parameter `B` declared on the method `collect`
     |
     = note: cannot satisfy `_: FromIterator<Result<Version, Error>>`
note: required by a bound in `collect`
    --> /home/fedasus/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:2001:19
     |
2001 |     fn collect<B: FromIterator<Self::Item>>(self) -> B
     |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
help: consider specifying the generic argument
     |
31   |     let mut tags: Vec<Version> = lines.iter().map(|e| parse(e)).collect::<Vec<_>>()?;
     |                                                                        ++++++++++

error[E0277]: the `?` operator can only be applied to values that implement `Try`
  --> src/lib.rs:38:20
   |
38 |     let mut tags = lines.iter().map(|e| parse(e)).collect::<Vec<_>>()?;
   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `Vec<Result<Version, Error>>`
   |
   = help: the trait `Try` is not implemented for `Vec<Result<Version, Error>>`

error[E0277]: a value of type `Result<Vec<Version>, anyhow::Error>` cannot be built from an iterator over elements of type `Result<Version, Error>`
    --> src/lib.rs:48:20
     |
48   |         .collect::<Result<Vec<Version>>>()?;
     |          -------   ^^^^^^^^^^^^^^^^^^^^ value of type `Result<Vec<Version>, anyhow::Error>` cannot be built from `std::iter::Iterator<Item=Result<Version, Error>>`
     |          |
     |          required by a bound introduced by this call
     |
     = help: the trait `FromIterator<Result<Version, Error>>` is not implemented for `Result<Vec<Version>, anyhow::Error>`
     = help: the trait `FromIterator<Result<Version, anyhow::Error>>` is implemented for `Result<Vec<Version>, anyhow::Error>`
     = help: for that trait implementation, expected `anyhow::Error`, found `Error`
note: the method call chain might not have had the expected associated types
    --> src/lib.rs:47:10
     |
45   |     let mut tags = lines
     |                    ----- this expression has type `&[&str]`
46   |         .iter()
     |          ------ `Iterator::Item` is `&&str` here
47   |         .map(|e| parse(e))
     |          ^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `Result<Version, Error>` here
note: required by a bound in `collect`
    --> /home/fedasus/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:2001:19
     |
2001 |     fn collect<B: FromIterator<Self::Item>>(self) -> B
     |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`

Some errors have detailed explanations: E0277, E0282, E0283.
For more information about an error, try `rustc --explain E0277`.

Desired output

  1. suggest let mut tags: Vec<Version> fix nothing
  2. suggest .collect::<Vec<_>> but the desired type is Result<...>
  3. I don't quite understand how the , _ help rustc to infer the type.

I'm sorry if this is expected error messages. Feel free to close if this is the case

Rationale and extra context

No response

Other cases

No response

Rust Version

rustc 1.80.0 (051478957 2024-07-21)
binary: rustc
commit-hash: 051478957371ee0084a7c0913941d2a8c4757bb9
commit-date: 2024-07-21
host: x86_64-unknown-linux-gnu
release: 1.80.0
LLVM version: 18.1.7

Anything else?

No response

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsA-inferenceArea: Type inferenceD-confusingDiagnostics: Confusing error or lint that should be reworked.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions