Skip to content

Commit 716e6b5

Browse files
authored
Merge pull request #23 from mominul/master
2 parents 7c6af11 + 82411d0 commit 716e6b5

File tree

1 file changed

+157
-0
lines changed

1 file changed

+157
-0
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
- Name: `effect-as-a-clause`
2+
- Proposed by: [@mominul](https://github.com/mominul) [@satvikpendem](https://github.com/satvikpendem)
3+
- Original proposal (optional): (https://github.com/rust-lang/keyword-generics-initiative/issues/14)
4+
5+
# Design
6+
We want to propose the usage of the `effect` clause to achieve operation genericity, for example:
7+
```rust
8+
trait Read {
9+
fn read(&mut self, buf: &mut [u8]) -> Result<usize>
10+
effect
11+
async;
12+
13+
fn read_to_string(&mut self, buf: &mut String) -> Result<usize>
14+
effect
15+
async
16+
{ .. }
17+
}
18+
19+
/// Function to read from the file into a string which may exhibit async or const effect
20+
fn read_to_string(path: &str) -> io::Result<String>
21+
effect
22+
async, const
23+
{
24+
let mut string = String::new();
25+
26+
// We can be conditional over the context the function has been called from,
27+
// only when the function declaration has the `effect` clause
28+
if async || !async {
29+
let mut file = File::open("foo.txt")?; // File implements Read
30+
// Because `read_to_string` is also an `effect` function that may or may not exhibit
31+
// async-ness par the declaration, we can use it on both contexts (async/sync)
32+
// we are placing the condition on.
33+
file.read_to_string(&mut string)?; // .await will be inferred.
34+
} else { // must be const
35+
// As the `read_to_string` doesn't exhibit const-ness, we'll need to handle it ourselves.
36+
string = include_str!(path).to_string();
37+
}
38+
39+
Ok(string)
40+
}
41+
42+
/// A normal function
43+
fn read() {
44+
let data = read_to_string("hello.txt").unwrap();
45+
}
46+
47+
/// A async function
48+
async fn read() {
49+
let data = read_to_string("hello.txt").await.unwrap();
50+
}
51+
52+
/// A const function
53+
const fn read() {
54+
let data = read_to_string("hello.txt").unwrap();
55+
}
56+
```
57+
So in a nutshell, a function declaration with an `effect` clause is a special type of function that **may** or **may not** exhibit async or const behavior(effect) and it **depends on the context of the function being called from** and we can **execute a different piece of code according to the context** from the function was called from too (like the `const_eval_select`, resolves [#6](https://github.com/rust-lang/keyword-generics-initiative/issues/6)):
58+
59+
```rust
60+
fn function() -> Result<()>
61+
effect
62+
async, const
63+
{
64+
// ...
65+
if async {
66+
// code for handling stuff asynchronously
67+
} else if const {
68+
// code for handling stuff `const`-way
69+
else {
70+
// code for handling stuff synchronously
71+
}
72+
// ...
73+
}
74+
```
75+
## base (reference)
76+
77+
<!-- This is the snippet which is being translated to various scenarios we're
78+
translating from. Please keep this as-is, so we can reference it later.-->
79+
80+
```rust
81+
/// A trimmed-down version of the `std::Iterator` trait.
82+
pub trait Iterator {
83+
type Item;
84+
fn next(&mut self) -> Option<Self::Item>;
85+
fn size_hint(&self) -> (usize, Option<usize>);
86+
}
87+
88+
/// An adaptation of `Iterator::find` to a free-function
89+
pub fn find<I, T, P>(iter: &mut I, predicate: P) -> Option<T>
90+
where
91+
I: Iterator<Item = T> + Sized,
92+
P: FnMut(&T) -> bool;
93+
```
94+
95+
## always async
96+
97+
<!-- A variant where all items are always `async` -->
98+
99+
```rust
100+
pub trait Iterator {
101+
type Item;
102+
async fn next(&mut self) -> Option<Self::Item>;
103+
fn size_hint(&self) -> (usize, Option<usize>);
104+
}
105+
106+
pub async fn find<I, T, P>(iter: &mut I, predicate: P) -> Option<T>
107+
where
108+
I: Iterator<Item = T> + Sized,
109+
P: async FnMut(&T) -> bool;
110+
```
111+
112+
## maybe async
113+
114+
<!-- A variant where all items are generic over `async` -->
115+
116+
```rust
117+
pub trait Iterator {
118+
type Item;
119+
fn next(&mut self) -> Option<Self::Item>
120+
effect async;
121+
fn size_hint(&self) -> (usize, Option<usize>);
122+
}
123+
124+
pub fn find<I, T, P>(iter: &mut I, predicate: P) -> Option<T>
125+
where
126+
I: Iterator<Item = T> + Sized,
127+
P: FnMut(&T) -> bool effect async;
128+
effect
129+
async
130+
```
131+
132+
## generic over all modifier keywords
133+
134+
<!-- A variant where all items are generic over all modifier keywords (e.g.
135+
`async`, `const`, `gen`, etc.) -->
136+
137+
```rust
138+
pub trait Iterator {
139+
type Item;
140+
fn next(&mut self) -> Option<Self::Item>
141+
effect async, const;
142+
fn size_hint(&self) -> (usize, Option<usize>);
143+
}
144+
145+
pub fn find<I, T, P>(iter: &mut I, predicate: P) -> Option<T>
146+
where
147+
I: Iterator<Item = T> + Sized,
148+
P: FnMut(&T) -> bool effect async, const;
149+
effect
150+
async, const
151+
```
152+
153+
# Notes
154+
155+
<!-- Add additional notes, context, and thoughts you want to share about your design
156+
here -->
157+
We can introduce `maybe` keyword instead of `effect` if it seems more appropriate terminology for the semantics described in this proposal.

0 commit comments

Comments
 (0)