Skip to content

[control flow analysis] Special treatment for Err( )? #51588

@DCjanus

Description

@DCjanus

I don't know this issue should be feature request or bug report.

I have code like this:

#[derive(Debug, Fail)]
#[fail(display = "Target can't open: {:?}", path)]
struct NotExists {
    path: PathBuf
}

#[derive(Debug, Fail)]
#[fail(display = "Target is not file: {:?}", path)]
struct NotFile {
    path: PathBuf
}

fn foo() -> Result<(), failure::Error> {
    let path = PathBuf::from("Rust/is/the/best/language");
    if path.exists() {
        Err(NotExists { path })?
    }
    if path.is_dir() {
        Err(NotFile { path })?
    }
    unimplemented!()
}

The compiler error is:

24 |         Err(NotExists { path })?
   |                         ---- value moved here
25 |     }
26 |     if path.is_dir() {
   |        ^^^^ value used here after move

Obviously, Err(foo)? equals return Err(foo.into());, that means there should be no use after moved error.

There are two other ways to achieve the goal:

    if path.exists() {
        Err(NotExists { path })?
    } else if path.is_dir() {
        Err(NotFile { path })?
    } else {
        unimplemented!()
    }

or

    if path.exists() {
        return Err(NotExists { path }.into());
    }

I think with control flow analysis, compiler should be able to pass my origin code(Err(foo)? version).

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-inferenceArea: Type inferenceA-type-systemArea: Type systemC-feature-requestCategory: A feature request, i.e: not implemented / a PR.T-langRelevant to the language teamT-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions