Skip to content

Support for inferred return types (_) in function signatures #3682

Open

Description

@hagz0r

Short Description:

Add the ability to use the underscore character (_) (or similar) to indicate the return type in function signatures in Rust.

This would allow the compiler to automatically determine the type of the return value based on the function body, simplifying syntax in cases where the type is obvious from context.

Motivation:

Currently in Rust, when writing functions, you must explicitly specify the return type in the signature. In many cases, the type of the return value is obvious from context, and having to explicitly specify it adds unnecessary verbosity. Supporting automatic output of the return type will:

  • Simplify function signatures.
  • Reduce the probability of errors related to incorrect return type specification.
  • Increase code readability by focusing on the logic of the function rather than its types.

Examples:

fn add(x: i32, y: i32) -> _ {
    x + y
}


// In this case, the compiler will automatically determine that the returned type is `i32`.
fn concatenate(s1: &str, s2: &str) -> _  {
    format!(“{}{}”, s1, s2)
}
// Here the compiler will output the type `String`.

С++ References

auto add(int x, int y) {
    return x + y;
}
// int

auto concatenate(const std::string& s1, const std::string& s2) {
    return s1 + s2;
}
// std::string.

Unresolved issues:

Should this function be limited to certain types of functions (for example, functions with a single return statement)?

How will this function interact with the existing type inference mechanisms in Rust, especially in more complex cases involving universal functions or multiple returned data?

Future opportunities:
Extending the idea of type inference to other parts of the function signature, such as parameter types, where appropriate.

Conclusion:

The ability to automatically determine the type of the return value in function signatures will provide more convenient and readable encoding, especially in simple cases when the type of the return value is obvious from the context. However, care should be taken to ensure that this function does not introduce unnecessary ambiguity and does not complicate debugging.

Activity

  1. petar-dambovaliev commented on Aug 23, 2024

    @petar-dambovaliev

    I don't like this. I want to see a function signature and know what it returns.
    Your proposal will make it so i need to read the function body to see that.

  2. hagz0r commented on Aug 23, 2024

    @hagz0r
    Author

    I don't like this. I want to see a function signature and know what it returns. Your proposal will make it so i need to read the function body to see that.

    No. The function body will define return type as it is.
    You still will see function signature like fn add(x: i32, y: i32) -> i32; in your IDE

    It will be easier for you to write code, it will not affect users of your lib, etc. It will be the same

  3. jongiddy commented on Aug 23, 2024

    @jongiddy

    The Rust norm is to be explicit in the function signatures to ensure that the interface to the function is correct, and then validate the function implementation against that. See, for example, this FAQ answer..

  4. lebensterben commented on Aug 23, 2024

    @lebensterben

    You still will see function signature like fn add(x: i32, y: i32) -> i32; in your IDE

    One doesn't necessarily have IDE, especially when reading foreign code.

  5. kennytm commented on Aug 23, 2024

    @kennytm
    Member

    to reduce repetition #3444 i.e. putting the inference on the value rather than the type is getting more traction.

    // instead of
    fn rotate(angle: f64) -> _ {
        let (s, c) = angle.sin_cos();
        Mat2 { entries: [[c, -s], [s, c]] }
    }
    
    // you write
    fn rotate(angle: f64) -> Mat2<f64> {
        let (s, c) = angle.sin_cos();
        _ { entries: [[c, -s], [s, c]] }
    }
  6. hagz0r commented on Aug 23, 2024

    @hagz0r
    Author

    The Rust norm is to be explicit in the function signatures to ensure that the interface to the function is correct, and then validate the function implementation against that. See, for example, this FAQ answer..

    It's just syntax sugar, it does not affect the language itself
    the function still returns one type of value as it was

    The problem with foreign code reading via eyes, not tools is open for discussion

  7. compiler-errors commented on Aug 23, 2024

    @compiler-errors
    Contributor

    It's just syntax sugar, it does not affect the language itself

    Extending the type system to allow function signatures to infer their return types is not syntax sugar. It affects the language and the type system. It doesn't matter if the function returns a single value.

    For example,

    fn a() -> _ { i32 }
    fn b() {
        let val = a();
    }
    

    Now introduces a dependency edge between type-checking a and type-checking b that did not exist before. I don't think this is feasible to support (outside of diagnostics, which is naturally allowed to fail gracefully), nor do I think it's desirable.

  8. fiveseven-lambda commented on Aug 27, 2024

    @fiveseven-lambda

    F# supports both

    • Return type inference, and
    • Mutual recursion.

    The following answers suggest that it is not so simple.
    https://stackoverflow.com/questions/900585/why-are-functions-in-ocaml-f-not-recursive-by-default/904715#904715

    One possibility is to simply do a dependency analysis on all the definitions in a scope, and reorder them into the smallest possible groups.

  9. changed the title [-] Support for automatic output of return type in function signatures[/-] [+] Support for inferred return types (`_`) in function signatures[/+] on Dec 3, 2024
  10. added
    T-langRelevant to the language team, which will review and decide on the RFC.
    T-typesRelevant to the types team, which will review and decide on the RFC.
    on Dec 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-langRelevant to the language team, which will review and decide on the RFC.T-typesRelevant to the types team, which will review and decide on the RFC.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions