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

RFC for allowing eliding more type parameters. #1196

Closed
wants to merge 4 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions text/0000-prefix-type-params.md
Original file line number Diff line number Diff line change
@@ -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::<u8, _>` and `foo::<u8>` 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, U, V>() -> T {
// ...
}

// equivalent:
let x: u8 = foo();
let y = foo::<u8, _, _>();
```

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::<u8>();
let w = foo::<u8, _>();
```

One concrete motivation for this is a new design for the
`rand::random` to allow more flexibility. It would have signature:

```rust
fn random<T: Rand, D: IntoRand<T>>(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::<u8, _>(..)`. Since it is easily deducable, the second
parameter can usually be left as `_`. It would hence be nicer to be
able to write `random::<u8>`.

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::<u8, ...>`. This defeats much of the syntactic point,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this alternative is my personal preference (though perhaps with two periods rather than three).

I see why @huonw prefers his proposal, but on the flip side: How do I now specify "these are the exact type parameters, and if another gets added, I want to be told at compile time" ? (Think of it like not having a _ => ... match arm...)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(of course one might reasonably point out that we already do not have a way to express "these are the exact type parameters" when dealing with a struct/enum with default type params" ...)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have any cases in mind where it's important to know that one is specifying all of the parameters? It seems to me that most cases where adding new parameters requires external adjustment will fail to compile, but I could very very easily be wrong.

and also means it is less helpful for backwards-compatibility
tricks.

# Unresolved questions

None right now.