Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Match is not smart enough to deduce the only possible catch-all type #51479

Closed
Disasm opened this issue Jun 10, 2018 · 5 comments
Closed

Match is not smart enough to deduce the only possible catch-all type #51479

Disasm opened this issue Jun 10, 2018 · 5 comments
Labels
A-inference Area: Type inference C-feature-request Category: A feature request, i.e: not implemented / a PR.

Comments

@Disasm
Copy link
Contributor

Disasm commented Jun 10, 2018

This example compiles successfully:

fn f2() -> Result<i32, String> {
    unimplemented!()
}

fn f1() -> Result<i64, String> {
    match f2() {
        Ok(value) => Ok(value as i64),
        Err(err) => Err(err),
    }
}

However, this example does not:

fn f2() -> Result<i32, String> {
    unimplemented!()
}

fn f1() -> Result<i64, String> {
    match f2() {
        Ok(value) => Ok(value as i64),
        err => err,
    }
}

Obviously, err can only be of Err(e) kind so it's correct to return it from f1().

@stokhos stokhos added C-feature-request Category: A feature request, i.e: not implemented / a PR. A-inference Area: Type inference labels Jun 10, 2018
@estebank
Copy link
Contributor

This is because err is of type Result<i32, String>::Err, which doesn't autocast to Result<i64, String>::Err. They are in effect two different types.

That being said, for this case the idiomatic code would be

fn f1() -> Result<i64, String> {
    f2().map(|v| v as i64)
}

or

fn f1() -> Result<i64, String> {
    Ok(f2()? as i64)
}

@dtolnay
Copy link
Member

dtolnay commented Jun 11, 2018

The Err(err) => Err(err) match arm is not a no-op, it is doing:

match f2() {
    Ok(value) => Ok(value as i64),
    Err::<i32, String>(err) => Err::<i64, String>(err),
}

Accepting err => err when only the error types are the same may break code in which err => err establishes that the ok types are the same. For example:

fn f2<T>() -> Result<T, String> {
    unimplemented!()
}

fn f1() -> Result<i64, String> {
    match f2() {
        Ok(value) => Ok(value as i64),
        err => err,
    }
}

This compiles today but an implicit conversion from Err::<T1, String> to Err::<T2, String> would make the choice of T type parameter for f2 ambiguous.

@estebank
Copy link
Contributor

Cc #47560

@Spoonbender
Copy link

Triage: no change

Since the reason is known and is a non-bug, can we close this issue?

@estebank
Copy link
Contributor

estebank commented Mar 24, 2022

@Spoonbender potentially, but I would like it if we had a structured suggestion for the presented cases, but I understand it might be too niche of a situation to make it worth it to handle it.

The original request would probably be better served as a t-lang request (which I would likely expect would be considered a bad idea).


Edit: let's close it, at least for now. I would like the suggestion to exist, but don't think this is necessarily the ticket for that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-inference Area: Type inference C-feature-request Category: A feature request, i.e: not implemented / a PR.
Projects
None yet
Development

No branches or pull requests

5 participants