Abstract
I propose weak-generic functions for Rust.
Weak generics allows for a reduction and simplification of appropriate code.
This idea of weak-generics is similar to languages such as Python. All functions are implicitly generic, and there is no safety. However, because Rust is strongly typed, per-function-call type checking for weak-generic functions is plausible and sound.
Currently, functions must be fully annotated with types. This can clutter code and could be an additional hurdle to learning Rust. My proposal is to allow function parameters to not have a specified type, but instead a sort of weak-generic. This would allow for the following code to be equivalent:
fn x(a: i32, b: i32) -> i32 {
a+b
}
fn y(a, b) -> i32 {
a+b
}
Motivation
Adding weak-generics to Rust would make it easier for new programmers to learn Rust. They would not need to fully grasp the concepts of trait bounds and lifetimes to effectively use "weak-generic" functions.
In short, weak-generics do not add syntax, they actually remove syntax and improve the developed experience.
Teaching
The following code does not compile due to no trait bounds:
fn x<T>(a: T, b: T) -> i32 {
a+b
}
However, the following code, that uses proposed weak-generics, would:
fn x(a, b) -> i32 {
a+b
}
fn main() {
let _ = x(1,2);
}
This could be taught (simply) as:
The Rust compiler takes the types of the input parameters (i32
) and fills in the types for all intermediate results. Then, it checks to see if the types implement the Add
trait so that the input parameters can be added.
Or, for a more in-depth view:
The Rust compiler builds up a graph of types through the execution flow of the function at compile time based on the input types (implicitly i32
here). It then validates the trait implementations to satisfy method and operator trait bounds.
Implementation overview
To acomplish this, the Rust compiler will need to type-check all individual function calls to weak-generic functions. Because where
clauses would not be used here, it is necessary to check all function bodies and execution paths.
Thoughts?
I would appreciate community thoughts on this proposal, as I believe it would really improve the developer experience and learning curve. I have not yet created a sample implementation, and plan on doing so. However, I would also appreciate some pointers to resources that can help me with implementing this type of major syntactical and type-checking change to my fork of Rust.
Thank you!