Hi! I’ve encountered the anon parameters issue a couple of times recently, so I decided to write up a pre-RFC. The main question is “Is it worth pursuing at all?” The issues is super minor, but annoys me personally a lot All the typos, grammar and language changes can be suggested directly on GitHub.
- Feature Name: deprecate_anonymous_parameters
- Start Date: 2016-07-19
- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)
Summary
Currently Rust allows anonymous parameters in trait methods:
trait T {
fn foo(i32);
fn bar_with_default_impl(String, String) {
}
}
This RFC proposes to deprecate this syntax. This RFC intentionally does not propose to remove this syntax.
Motivation
Anonymous parameters are a historic accident. They do not pose any significant problems, but lead to a number of annoyances.
-
Surprising pattern syntax in traits
trait T { fn foo(x: i32); // Ok fn bar(&x: &i32); // Ok fn baz(&&x: &&i32); // Ok fn quux(&&&x: &&&i32); // Syntax error }
-
Inconsistency between default implementations in traits and implementations in impl blocks
trait T { fn foo((x, y): (usize, usize)) { // Syntax error } } impl T for S { fn foo((x, y): (usize, usize)) { // Ok } }
-
Inconsistency between method declarations in traits and in extern blocks
trait T { fn foo(i32); // Ok } extern "C" { fn foo(i32); // Syntax error }
-
Slightly more complicated syntax analysis for LL style parsers. The parser must guess if it currently parses a pattern or a type.
-
Small complications for source code analyzers (e.g. IntelliJ Rust) and potential alternative implementations.
None of these issues is significant, but they exist.
Detailed design
Removing anonymous parameters from the language is formally a breaking change. The breakage can be trivially and potentially automatically fixed by adding _:
(suggested by @nagisa):
trait T {
fn foo(_: i32);
fn bar_with_default_impl(_: String, _: String) {
}
}
However this is also a major breaking change from the practical point of view. Parameter names are rarely omitted, but it happens. For example, std::fmt::Display
is currently defined as follows:
trait Display {
fn fmt(&self, &mut Formatter) -> Result;
}
So the proposal is just to deprecate this syntax in the hope that the removal would become feasible and practical in the future. The hypothetical future may include:
- Rust 2.0 release.
- A tool to automatically fix deprecation warnings.
- Storing crates on crates.io in “elaborated” syntax independent format.
Enabling deprecation early makes potential future removal easier in practice.
Drawbacks
There are a number of drawbacks:
-
Deprecation will require code changes across the community without bringing any noticeable immediate benefits.
-
It is not clear if it will ever be possible to remove this syntax entirely.
Alternatives
-
Status quo.
-
Decide on the precise removal plan prior to deprecation.
-
Try to solve the underlying annoyances in some other way. For example, unbounded look ahead can be used in the parser to allow both anonymous parameters and the full pattern syntax.
Unresolved questions
-
How often are anonymous parameters used in practice?
-
Is there a consensus that anonymous parameters are not a useful language feature?