From 1681226e637e5e3f7172fd279357643de6b8828c Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 9 Jul 2015 09:23:10 -0700 Subject: [PATCH 1/4] RFC for allowing eliding more type parameters. --- text/0000-prefix-type-params.md | 79 +++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 text/0000-prefix-type-params.md diff --git a/text/0000-prefix-type-params.md b/text/0000-prefix-type-params.md new file mode 100644 index 00000000000..db98bf5c31e --- /dev/null +++ b/text/0000-prefix-type-params.md @@ -0,0 +1,79 @@ +- Feature Name: prefix_type_param +- Start Date: 2015-07-08 +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary + +Let specified generic type parameter lists be abbreviated, that is, +`foo::` and `foo::` are equivalent. + +# Motivation + +There are times when generic functions need to have their type +parameters specified, requiring the use of the `::<...>` +syntax. Before this RFC, doing this would require every type parameter +to have something written, even if it was just `_`. + +```rust +fn foo() -> T { + // ... +} + +// equivalent: +let x: u8 = foo(); +let y = foo::(); +``` + +It is very possible to have APIs that only require a subset of the +type parameters to be specified in the common case (the rest can be +correctly deduced from other information). It is syntactically nice to +allow not writing `_` when it seems "obviously" unnecessary. The above +example could be written: + +```rust +let z = foo::(); +let w = foo::(); +``` + +One concrete motivation for this is a new design for the +`rand::random` to allow more flexibility. It would have signature: + +```rust +fn random>(d: D) -> T +``` + +Generally, the type `D` can be deduced from the call itself, but the +return type requires more information. Either an external type hint +like `let x: u8 = random(..);`, or an explicit function annotation +`random::(..)`. Since it is easily deducable, the second +parameter can usually be left as `_`. It would hence be nicer to be +able to write `random::`. + +This also makes it easier to add type parameters without downstream +code having to change. + +# Detailed design + +When the compiler handles a type-specified function, instead of +emitting `error: too few type parameters provided: expected N +parameter(s) , found M parameter(s) [E0089]`, it mechanically fills in +the remaining `N - M` parameters with `_`. + +# Drawbacks + +None right now. + +# Alternatives + +- Type ascription may solve much of the motivation for doing this, + since it becomes easier to type-hint things. E.g. the `random` + example can becomes `random(..): u8`. +- Require noting that parameters have been left to inference, + e.g. `random::`. This defeats much of the syntactic point, + and also means it is less helpful for backwards-compatibility + tricks. + +# Unresolved questions + +None right now. From a129cb52b2139fc76c707bf1c4086e5fe638f5e3 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 9 Jul 2015 17:17:15 -0700 Subject: [PATCH 2/4] Minor updates from feedback. --- text/0000-prefix-type-params.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/text/0000-prefix-type-params.md b/text/0000-prefix-type-params.md index db98bf5c31e..45ca3efab39 100644 --- a/text/0000-prefix-type-params.md +++ b/text/0000-prefix-type-params.md @@ -60,9 +60,17 @@ emitting `error: too few type parameters provided: expected N parameter(s) , found M parameter(s) [E0089]`, it mechanically fills in the remaining `N - M` parameters with `_`. +This RFC only applies to expressions. It is not proposing that it be +legal to abbreviate `let x: Foo` as `let x: Foo`. + # Drawbacks -None right now. +- It is not possible to specify that all type parameters are + specified, so that it is an error and requires adjustment if more + are added upstream. It isn't so clear to the author which default is + right (syntax for "closing" a specification list could be added if + the version in this RFC is decided to be the right default but being + definite is still desirable). # Alternatives From b0267f8c4618672e2bf7e632ebc85a800439ac33 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 3 Dec 2015 23:20:50 +1100 Subject: [PATCH 3/4] Add API evolution to motivation. --- text/0000-prefix-type-params.md | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/text/0000-prefix-type-params.md b/text/0000-prefix-type-params.md index 45ca3efab39..489c6694daf 100644 --- a/text/0000-prefix-type-params.md +++ b/text/0000-prefix-type-params.md @@ -36,7 +36,38 @@ let z = foo::(); let w = foo::(); ``` -One concrete motivation for this is a new design for the +A major motivation for this is it allows generalising a function by +adding new (usually-inferrable) type parameters to a function, without +breaking users who already specify existing parameters. This makes the +API evolution story for Rust code more flexible. For example, consider +these two definitions of `foo`: + +``` rust +fn foo(x: &str) { ... } +fn foo(x: U) { ... } +``` + +A library version `1.0.0` might include the first `foo`, and users +would call it like `foo::("bar")`. Later, it is +realised that `foo` can be generalised to the second one (presumably +with some trait bounds on `U`, in practice), and so `1.1.0` is +released with the new definition, which would unfortunately break our +existing caller, with an message like: + +``` +error: too few type parameters provided: expected 2 parameters, found 1 parameter [E0089] + foo::("bar") + ^~~~~~~~~~ +``` + +This case can be completely addressed by instead calling `foo::`, letting the compiler do all the work to infer `U`. This RFC +allows this this `_` insertion to happen implicitly, and so the +`1.1.0` release with its new definition of `foo` would not break the +`foo::("bar")` call at all: it would just continue to work. + + +Another concrete motivation for this is a new design for the `rand::random` to allow more flexibility. It would have signature: ```rust From 83e8e4cff3acc7a402ae32ee80350c01d4a9d5ff Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Fri, 4 Dec 2015 09:15:58 +1100 Subject: [PATCH 4/4] Add explicit opt-in to elision as alternatives. --- text/0000-prefix-type-params.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/text/0000-prefix-type-params.md b/text/0000-prefix-type-params.md index 489c6694daf..a30c2c56a7d 100644 --- a/text/0000-prefix-type-params.md +++ b/text/0000-prefix-type-params.md @@ -112,6 +112,9 @@ legal to abbreviate `let x: Foo` as `let x: Foo`. e.g. `random::`. This defeats much of the syntactic point, and also means it is less helpful for backwards-compatibility tricks. +- Require opting-in for parameters that can be elided, e.g. have a + "default" type parameter of `_`, `fn foo()` would + allow `foo::` but not `foo::`. # Unresolved questions