Skip to content

Commit 14c806c

Browse files
committed
Fix some code blocks
HTML blocks are ended with a blank line, causing these to not render correctly.
1 parent 80bf4c9 commit 14c806c

File tree

1 file changed

+26
-52
lines changed

1 file changed

+26
-52
lines changed

content/Project-Goals-2025-October-Update.md

Lines changed: 26 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,7 @@ Design a language feature to solve Field Projections <a href='https://github.com
165165
<h3>Field Representing Types</h3>
166166
<p>Since projections now decompose, we have no need from a design perspective for multi-level FRTs. So <code>field_of!(Foo, bar.baz)</code> is no longer required to work. Thus we have decided to restrict FRTs to only a single field and get rid of the path. This simplifies the implementation in the compiler and also avoids certain difficult questions such as the locality of FRTs (if we had a path, we would have to walk the path and it is local, if all structs included in the path are local). Now with only a single field, the FRT is local if the struct is.</p>
167167
<p>We also discovered that it is a good idea to make FRTs inhabited (they still are ZSTs), since then it allows the following pattern to work:</p>
168-
<pre><code class="language-rust">fn project_free_standing&lt;F: Field&gt;(_: Field, r: &amp;F::Base) -&gt; &amp;F::Type { ... }
169-
168+
<pre><code class="language-rust">fn project_free_standing&lt;F: Field&gt;(_: Field, r: &amp;F::Base) -&gt; &amp;F::Type { ... }<br>
170169
// can now call the function without turbofish:
171170
let my_field = project_free_standing(field_of!(MyStruct, my_field), &amp;my_struct);
172171
</code></pre>
@@ -188,13 +187,11 @@ let my_field = project_free_standing(field_of!(MyStruct, my_field), &amp;my_stru
188187
<p>This goes into a similar direction as the reborrowing project goal https://github.com/rust-lang/rust-project-goals/issues/399, however, it needs extra borrow checker support.</p>
189188
<pre><code class="language-rust">fn add(x: cell::RefMut&lt;'_, i32&gt;, step: i32) {
190189
*x = *x + step;
191-
}
192-
190+
}<br>
193191
struct Point {
194192
x: i32,
195193
y: i32,
196-
}
197-
194+
}<br>
198195
fn example(p: cell::RefMut&lt;'_, Point&gt;) {
199196
let y: cell::Ref&lt;'_, i32&gt; = coerce_shared!(p.[@y][]);
200197
let y2 = coerce_shared!(p.[@y][]); // can project twice if both are coerced
@@ -229,11 +226,9 @@ fn example(p: cell::RefMut&lt;'_, Point&gt;) {
229226
<pre><code class="language-rust">// still need a common super trait for `Project` &amp; `ProjectMut`
230227
pub trait Projectable {
231228
type Target: ?Sized;
232-
}
233-
229+
}<br>
234230
pub unsafe trait Project: Projectable {
235-
type Output&lt;F: Field&lt;Base = Self::Target&gt;&gt;;
236-
231+
type Output&lt;F: Field&lt;Base = Self::Target&gt;&gt;;<br>
237232
unsafe fn project&lt;F: Field&lt;Base = Self::Target&gt;&gt;(
238233
this: *const Self,
239234
) -&gt; Self::Output&lt;F&gt;;
@@ -242,8 +237,7 @@ pub unsafe trait Project: Projectable {
242237
<h4>Are FRTs even necessary?</h4>
243238
<p>With this change we can also think about getting rid of FRTs entirely. For example we could have the following <code>Project</code> trait:</p>
244239
<pre><code class="language-rust">pub unsafe trait Project: Projectable {
245-
type Output&lt;F&gt;;
246-
240+
type Output&lt;F&gt;;<br>
247241
unsafe fn project&lt;const OFFSET: usize, F&gt;(
248242
this: *const Self,
249243
) -&gt; Self::Output&lt;F&gt;;
@@ -260,42 +254,32 @@ pub unsafe trait Project: Projectable {
260254
main_work: Work&lt;Self, 0&gt;,
261255
aux_work: Work&lt;Self, 1&gt;,
262256
// more fields ...
263-
}
264-
257+
}<br>
265258
// Then you call a macro to implement the unsafe `HasWork` trait safely.
266259
// It asserts that there is a field of type `Work&lt;MyDriver, 0&gt;` at the given field
267260
// (and also exposes its offset).
268261
impl_has_work!(impl HasWork&lt;MyDriver, 0&gt; for MyDriver { self.main_work });
269-
impl_has_work!(impl HasWork&lt;MyDriver, 1&gt; for MyDriver { self.aux_work });
270-
271-
// Then you implement `WorkItem` twice:
272-
262+
impl_has_work!(impl HasWork&lt;MyDriver, 1&gt; for MyDriver { self.aux_work });<br>
263+
// Then you implement `WorkItem` twice:<br>
273264
impl WorkItem&lt;0&gt; for MyDriver {
274-
type Pointer = Arc&lt;Self&gt;;
275-
265+
type Pointer = Arc&lt;Self&gt;;<br>
276266
fn run(this: Self::Pointer) {
277267
println!(&quot;doing the main work here&quot;);
278268
}
279-
}
280-
269+
}<br>
281270
impl WorkItem&lt;1&gt; for MyDriver {
282-
type Pointer = Arc&lt;Self&gt;;
283-
271+
type Pointer = Arc&lt;Self&gt;;<br>
284272
fn run(this: Self::Pointer) {
285273
println!(&quot;doing the aux work here&quot;);
286274
}
287-
}
288-
289-
// And finally you can call `enqueue` on a `Queue`:
290-
275+
}<br>
276+
// And finally you can call `enqueue` on a `Queue`:<br>
291277
let my_driver = Arc::new(MyDriver::new());
292278
let queue: &amp;'static Queue = kernel::workqueue::system_highpri();
293-
queue.enqueue::&lt;_, 0&gt;(my_driver.clone()).expect(&quot;my_driver is not yet enqueued for id 0&quot;);
294-
279+
queue.enqueue::&lt;_, 0&gt;(my_driver.clone()).expect(&quot;my_driver is not yet enqueued for id 0&quot;);<br>
295280
// there are different queues
296281
let queue = kernel::workqueue::system_long();
297-
queue.enqueue::&lt;_, 1&gt;(my_driver.clone()).expect(&quot;my_driver is not yet enqueued for id 1&quot;);
298-
282+
queue.enqueue::&lt;_, 1&gt;(my_driver.clone()).expect(&quot;my_driver is not yet enqueued for id 1&quot;);<br>
299283
// cannot insert multiple times:
300284
assert!(queue.enqueue::&lt;_, 1&gt;(my_driver.clone()).is_err());
301285
</code></pre>
@@ -305,36 +289,29 @@ assert!(queue.enqueue::&lt;_, 1&gt;(my_driver.clone()).is_err());
305289
main_work: Work&lt;field_of!(Self, main_work)&gt;,
306290
aux_work: Work&lt;field_of!(Self, aux_work)&gt;,
307291
// more fields ...
308-
}
309-
292+
}<br>
310293
impl WorkItem&lt;field_of!(MyDriver, main_work)&gt; for MyDriver {
311-
type Pointer = Arc&lt;Self&gt;;
312-
294+
type Pointer = Arc&lt;Self&gt;;<br>
313295
fn run(this: Self::Pointer) {
314296
println!(&quot;doing the main work here&quot;);
315297
}
316-
}
317-
298+
}<br>
318299
impl WorkItem&lt;field_of!(MyDriver, aux_work)&gt; for MyDriver {
319-
type Pointer = Arc&lt;Self&gt;;
320-
300+
type Pointer = Arc&lt;Self&gt;;<br>
321301
fn run(this: Self::Pointer) {
322302
println!(&quot;doing the aux work here&quot;);
323303
}
324-
}
325-
304+
}<br>
326305
let my_driver = Arc::new(MyDriver::new());
327306
let queue: &amp;'static Queue = kernel::workqueue::system_highpri();
328307
queue
329308
.enqueue(my_driver.clone(), field_of!(MyDriver, main_work))
330309
// ^ using Gary's idea to avoid turbofish
331-
.expect(&quot;my_driver is not yet enqueued for main_work&quot;);
332-
310+
.expect(&quot;my_driver is not yet enqueued for main_work&quot;);<br>
333311
let queue = kernel::workqueue::system_long();
334312
queue
335313
.enqueue(my_driver.clone(), field_of!(MyDriver, aux_work))
336-
.expect(&quot;my_driver is not yet enqueued for aux_work&quot;);
337-
314+
.expect(&quot;my_driver is not yet enqueued for aux_work&quot;);<br>
338315
assert!(queue.enqueue(my_driver.clone(), field_of!(MyDriver, aux_work)).is_err());
339316
</code></pre>
340317
<p>This makes it overall a lot more readable (by providing sensible names instead of magic numbers), and maintainable (we can add a new variant without worrying about which IDs are unused). It also avoids the <code>unsafe</code> <code>HasWork</code> trait and the need to write the <code>impl_has_work!</code> macro for each <code>Work</code> field.</p>
@@ -350,14 +327,11 @@ assert!(queue.enqueue(my_driver.clone(), field_of!(MyDriver, aux_work)).is_err()
350327
<p>In the current proposal the <code>Project::project</code> function is <code>unsafe</code>, because it takes a raw pointer as an argument. This is pretty unusual for an operator trait (it would be the first). <a href="https://github.com/tmandry">Tyler Mandry</a> thought about a way of making it safe by introducing &quot;partial struct types&quot;. This new type is spelled <code>Struct.F</code> where <code>F</code> is an FRT of that struct. It's like <code>Struct</code>, but with the restriction that only the field represented by <code>F</code> can be accessed. So for example <code>&amp;Struct.F</code> would point to <code>Struct</code>, but only allow one to read that single field. This way we could design the <code>Project</code> trait in a safe manner:</p>
351328
<pre><code class="language-rust">// governs conversion of `Self` to `Narrowed&lt;F&gt;` &amp; replaces Projectable
352329
pub unsafe trait NarrowPointee {
353-
type Target;
354-
330+
type Target;<br>
355331
type Narrowed&lt;F: Field&lt;Base = Self::Target&gt;&gt;;
356-
}
357-
332+
}<br>
358333
pub trait Project: NarrowPointee {
359-
type Output&lt;F: Field&lt;Base = Self::Type&gt;&gt;;
360-
334+
type Output&lt;F: Field&lt;Base = Self::Type&gt;&gt;;<br>
361335
fn project(narrowed: Self::Narrowed&lt;F&gt;) -&gt; Self::Output&lt;F&gt;;
362336
}
363337
</code></pre>

0 commit comments

Comments
 (0)