Skip to content

Commit

Permalink
first design
Browse files Browse the repository at this point in the history
Using a special keyword "effect", its possible to
indicate that a type, function or trait is
generic over a effect with the "rust way" of
expressing generics.

The effect keyword also has a role in the where
clause, capable of specifing the keywords beeing
generic (e.g. async, !async, ?async, const +
?async, etc) and the keyword bounds of traits in
generic arguments.

This design also takes into account possible
syntax changes in other proposals and ideas.

- [associated type bounds](rust-lang/rust#52662)
- [return type notation](https://smallcultfollowing.com/babysteps/blog/2023/02/13/return-type-notation-send-bounds-part-2/)
  • Loading branch information
caio-oliv committed Mar 2, 2023
0 parents commit e1a50fd
Showing 1 changed file with 177 additions and 0 deletions.
177 changes: 177 additions & 0 deletions design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
- Name: `keyword-generic-effect-clause`
- Proposed by: [Caio](@CaioOliveira793)
- Original proposal (optional): N/A

# Design

<!-- Please fill out the snippets labeled with "fill me in". If there are any
other examples you want to show, please feel free to append more.-->

## base (reference)

<!-- This is the snippet which is being translated to various scenarios we're
translating from. Please keep this as-is, so we can reference it later.-->

```rust
/// A trimmed-down version of the `std::Iterator` trait.
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
fn size_hint(&self) -> (usize, Option<usize>);
}

/// An adaptation of `Iterator::find` to a free-function
pub fn find<I, T, P>(iter: &mut I, predicate: P) -> Option<T>
where
I: Iterator<Item = T> + Sized,
P: FnMut(&T) -> bool;
```

## always async

<!-- A variant where all items are always `async` -->

```rust
pub trait Iterator<effect>
where
effect: async
{
type Item;

// opt-in for a async effect
fn next(&mut self) -> Option<Self::Item>
where
effect: async;

// the size_hint is left unchanged, since the effect is opt-in
fn size_hint(&self) -> (usize, Option<usize>);
}

// the `effect` generic indicates that this function is generic
// over keywords
pub fn find<I, T, P, effect>(iter: &mut I, predicate: P) -> Option<T>
where
effect: async,
// iterator effect **must** be async
I: Iterator<effect = async>
// a short version is also possible
// I: Iterator<effect = async, Item = T> + Sized,
I: Iterator<Item = T> + Sized,
P: FnMut(&T) -> bool;
```

## maybe async

<!-- A variant where all items are generic over `async` -->

```rust
pub trait Iterator<effect>
where
effect: ?async
{
type Item;

fn next(&mut self) -> Option<Self::Item>
where
effect: ?async;

fn size_hint(&self) -> (usize, Option<usize>);
}

pub fn find<I, T, P, effect>(iter: &mut I, predicate: P) -> Option<T>
where
effect: ?async,
// iterator effect is be **maybe** async
I: Iterator<effect = ?async>
I: Iterator<Item = T> + Sized,
P: FnMut(&T) -> bool;
```

## generic over all modifier keywords

<!-- A variant where all items are generic over all modifier keywords (e.g.
`async`, `const`, `gen`, etc.) -->

```rust
pub trait Iterator<effect>
where
// in order to be generic over all keywords the effect clause must specify all the keywords available
effect: ?async + ?const
{
type Item;

fn next(&mut self) -> Option<Self::Item>
where
effect: ?async + ?const;

// functions without effect anotatios follows the same rules as if
// the trait wasn't generic over a keyword
fn size_hint(&self) -> (usize, Option<usize>);

// ... or possibilly, they could restrict the keywords allowed
fn size_hint(&self) -> (usize, Option<usize>)
where
effect: !async + ?const;
}

pub fn find<I, T, P, effect>(iter: &mut I, predicate: P) -> Option<T>
where
effect: ?async + ?const,
I: Iterator<effect = ?async + ?const, Item = T> + Sized,
P: FnMut(&T) -> bool;
```

# Notes

## Compatiablity

compatible with [associated type bounds](https://github.com/rust-lang/rust/issues/52662):

```rust
pub fn find<I, T, P, effect>(iter: &mut I, predicate: P) -> Option<T>
where
effect: ?async + ?const,
// the choice over ":" or "=" is open
I: Iterator<effect = ?async + ?const>,
// or
<I as Iterator>::effect: ?async + ?const,
// or
I: Iterator<effect: ?async + ?const>,
I: Iterator<Item = T> + Sized,
P: FnMut(&T) -> bool;
```

is also compatible with [return type notation](https://smallcultfollowing.com/babysteps/blog/2023/02/13/return-type-notation-send-bounds-part-2/)

```rust
pub trait HealthCheck<effect>
where
effect: async
{
fn check(&mut self, server: Server)
where
effect: async;
}

fn start_health_check<H, effect>(health_check: H, server: Server)
where
effect: async,
H: HealthCheck<effect: async, check(): Send> + Send + 'static,
```

## explicit all modifiers keywords

The syntax does not give shortans for specifing all modifiers at once.

Positive

- explicit
- backwards compatible to introduce new keywords
- extendable

Negative

- cumbersome to declare all keywords

<!-- Add additional notes, context, and thoughts you want to share about your design
here -->

0 comments on commit e1a50fd

Please sign in to comment.