-
Notifications
You must be signed in to change notification settings - Fork 53
Description
Positional Associated Types
Proposal
Summary and problem statement
It should be possible to abbreviate Future<Output=T>
as Future<T>
.
Motivation, use-cases, and solution sketches
Many of the most-used traits in the rust programming language specify a single associated type:
Iterator<Item=T>
Future<Output=T>
FromStr<Err=T>
Deref<Target=T>
Stream<Item=T>
- and so on
The impl Trait
syntax is intended to make instances of such traits easy to pass and return. But this can be quite verbose in practice, because each of these traits must be written with the associated type explicitly spelled out:
fn deltas(iter: impl Iterator<Item=f32>) -> impl Iterator<Item=f32> {
iter.array_windows().map(|[a, b]| b - a)
}
Worse, it may not be clear to incoming Rust programmers why they have to write Iterator<Item=f32>
instead of Iterator<f32>
. After all, the generics of traits like From<T>
and types like Option<T>
are not named. It can take many months for the difference between generic parameters and associated types to click, and in that time users probably guess at random which they should use for any given trait.
It is worth investigating whether these common cases can be abbreviated:
pub trait Future {
#[positional]
type Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}
impl Logger {
pub fn log_outcome(task: impl Future<String>) {
...
}
}
This should also apply to the dyn Future<T>
and F: Future<T>
syntaxes.
The Iterator<T>
and Future<T>
traits would almost certainly be the first to have positional associated types (PATs) stabilized. But the feature could also be beneficial for some traits with multiple associated types:
pub trait Try: FromResidual<Self::Residual> {
#[positional]
type Output;
#[positional]
type Residual;
fn from_output(output: Self::Output) -> Self;
fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
}
impl Logger {
pub fn log_outcome(task: impl Future<impl Try<impl Display, impl Display>>) {
...
}
}
Note this proposal would not immediately include any of the following use cases:
// PATs in trait implementations
impl Iterator<f32> for MyIterator { }
// Mixing type parameters and PATs
trait MyTrait<T> {
#[positional]
type Extra;
}
// Named type parameters
fn get(&self, key: &impl Borrow<Borrowed=str>) { }
Links and related work
- Discussion in the async foundations Zulip stream
- The
Fut
alias trait - Rules for positional and keyword arguments to Python functions
- Typescript's debate over named type parameters
Initial people involved
- Owner: Sam Sartor
- Liaison: Josh Triplett
What happens now?
This issue is part of the lang-team initiative process. Once this issue is filed, a Zulip topic will be opened for discussion, and the lang-team will review open proposals in its weekly triage meetings. You should receive feedback within a week or two.
This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed.