@@ -279,6 +279,54 @@ against [Semantic Versioning][semver].
279
279
280
280
[ semver ] : https://doc.rust-lang.org/cargo/reference/semver.html
281
281
282
+ NOTE:
283
+ * ` requires ` or ` checked ` can be specified multiple times, and they will be merged together.
284
+ * Duplicate tags in ` requires ` will trigger errors.
285
+ * Duplicate tags in ` checked ` will trigger warning-by-default diagnostics.
286
+ * the scope of a tag is limited to the defined unsafe function, so identical tag name on different
287
+ unsafe functions won't affect with each other.
288
+
289
+ ## Auto Generate Safety Docs from Tags
290
+
291
+ Since tag definitions duplicate safety comments, we propose ` rustdoc ` can recognize
292
+ ` #[safety::requires] ` attributes and render them into safety docs.
293
+
294
+ For ` ptr::read ` , the existing comments are replaced with safety tags:
295
+
296
+ ``` rust
297
+ /// # Safety
298
+ /// Behavior is undefined if any of the following conditions are violated:
299
+ /// * `src` must be [valid] for reads.
300
+ /// * `src` must be properly aligned. Use [`read_unaligned`] if this is not the case.
301
+ /// * `src` must point to a properly initialized value of type `T`.
302
+ /// # Examples
303
+ pub const unsafe fn read <T >(src : * const T ) -> T { ... }
304
+ ```
305
+
306
+ ``` rust
307
+ /// # Safety
308
+ /// Behavior is undefined if any of the following conditions are violated:
309
+ #[safety:: requires {
310
+ ValidPtr = " `src` must be [valid] for reads" ;
311
+ Aligned = " `src` must be properly aligned. Use [`read_unaligned`] if this is not the case" ;
312
+ Initialized = " `src` must point to a properly initialized value of type `T`"
313
+ }]
314
+ /// # Examples
315
+ pub const unsafe fn read <T >(src : * const T ) -> T { ... }
316
+ ```
317
+
318
+ Each ` Tag = "desc" ` item is rendered as `` `Tag`: desc `` list item.
319
+
320
+ ``` rust
321
+ /// # Safety
322
+ /// Behavior is undefined if any of the following conditions are violated:
323
+ /// * `ValidPtr`: `src` must be [valid] for reads.
324
+ /// * `Aligned`: `src` must be properly aligned. Use [`read_unaligned`] if this is not the case.
325
+ /// * `Initialized`: `src` must point to a properly initialized value of type `T`.
326
+ /// # Examples
327
+ pub const unsafe fn read <T >(src : * const T ) -> T { ... }
328
+ ```
329
+
282
330
# Reference-level explanation
283
331
[ reference-level-explanation ] : #reference-level-explanation
284
332
@@ -300,6 +348,7 @@ their call sites. To enable experimentation, a nightly-only library feature
300
348
Procedure:
301
349
302
350
1 . Validate ` #[safety::requires] ` only appears on unsafe functions if the attribute exists.
351
+ - Merge tags in multiple ` requires ` on the same function. Emit error if tag name duplicates.
303
352
2 . Validate ` #[safety::checked] ` on HIR nodes whose ` ExprKind ` is one of
304
353
- ** direct unsafe nodes** : ` Call ` , ` MethodCall ` that invoke an unsafe function/method, or
305
354
- ** indirect unsafe nodes** : ` Block ` (unsafe), ` Let ` , ` Assign ` , ` AssignOp ` .
@@ -312,8 +361,10 @@ Procedure:
312
361
3 . Any node that carries ` #[safety::checked] ` must contain ** exactly one** unsafe call/method;
313
362
otherwise emit a diagnostic. * (We intentionally stop at this simple rule; splitting complex
314
363
unsafe expressions into separate annotated nodes is considered good style.)*
315
- 4 . Make sure tags in ` #[safety::checked] ` correspond to their definitions.
316
- 5 . Diagnostics are emitted at the current Clippy lint level (warning or error).
364
+ 4 . Merge tags in multiple ` checked ` on the same node. Emit a diagnostic if tag name duplicates.
365
+ 5 . Make sure checked tags correspond to their definitions. Emit a diagnostic if the tag doesn't
366
+ have a definition on the call.
367
+ 6 . Diagnostics are emitted at the current Clippy lint level (warning or error).
317
368
318
369
[ HIR ExprKind ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/enum.ExprKind.html
319
370
@@ -328,6 +379,26 @@ documentation hover in `#[safety::checked]` as per tag definitions on unsafe cal
328
379
Maybe some logics on safety tags like collecting tag definitions need to be extracted to a shared
329
380
crate for both Clippy and Rust-Analyzer to use.
330
381
382
+ ## Implementation in Rustdoc
383
+
384
+ Treat ` #[safety::requires] ` tool attributes on unsafe functions as ` #[doc] ` attributes, and extract
385
+ tag names and definitions to render as item list:
386
+
387
+ ``` rust
388
+ #[safety:: requires(Tag1 = " definition1" )]
389
+ #[safety:: requires(Tag2 = " definition2" )]
390
+ ```
391
+
392
+ will be rendered if in markdown syntax
393
+
394
+ ``` md
395
+ * `Tag1`: definition1
396
+ * `Tag2`: definition2
397
+ ```
398
+
399
+ It'd be good if tag names have a special css class like background color to be attractive. Tag
400
+ styling is not required in this RFC, and can be implemented later as an improvement.
401
+
331
402
# Drawbacks
332
403
[ drawbacks ] : #drawbacks
333
404
@@ -358,12 +429,17 @@ to implement them.
358
429
be tied to internal APIs and specific toolchains. Extending Rust-Analyzer is therefore the only
359
430
practical way to give users first-class IDE support.
360
431
432
+ 4 . Avoid safety comment duplication. Tag definitions and safety requirements share identical prose,
433
+ so we only need one way to render them. Generating safety docs through safety tags prevents
434
+ verbosity and inconsistency.
435
+
361
436
We therefore seek approvals from the following teams:
362
437
363
438
1 . ** Library team** – to allow the tagging of unsafe operations and to expose tag items as public
364
439
APIs.
365
- 2 . ** Clippy team** – to integrate tag checking into the linter.
366
- 3 . ** Rust-Analyzer team** – to add IDE support for tags.
440
+ 2 . ** Clippy team** – to integrate tag checking into the linter.
441
+ 3 . ** Rust-Analyzer team** – to add IDE support for tags.
442
+ 3 . ** Rustdoc team** – to render tags to docs.
367
443
4 . ** Compiler team** – to reserve the ` safety ` namespace and gate the feature via
368
444
` #![feature(safety_tags)] ` for the namespace and tag APIs in standard libraries.
369
445
@@ -521,51 +597,6 @@ struct, enum, or union is neither needed nor permitted.
521
597
# Future possibilities
522
598
[ future-possibilities ] : #future-possibilities
523
599
524
- ## Better Rustdoc Rendering
525
-
526
- Because tags are surfaced as a part of API, rustdoc can render documentation of tags by displaying
527
- each tag name, its optional description, and possible deprecated state below the tagged function or
528
- other unsafe item.
529
-
530
- ## Generate Safety Docs from Tags
531
-
532
- We can take structured safety comments one step further by turning the explanatory prose into
533
- explicit tag reasons.
534
-
535
- For ` ptr::read ` , the existing comments are replaced with safety tags:
536
-
537
- ``` rust
538
- /// * `src` must be [valid] for reads.
539
- /// * `src` must be properly aligned. Use [`read_unaligned`] if this is not the case.
540
- /// * `src` must point to a properly initialized value of type `T`.
541
- pub const unsafe fn read <T >(src : * const T ) -> T { ... }
542
- ```
543
-
544
- ``` rust
545
- #[safety {
546
- ValidPtr = " `src` must be [valid] for reads" ;
547
- Aligned = " `src` must be properly aligned. Use [`read_unaligned`] if this is not the case" ;
548
- Initialized = " `src` must point to a properly initialized value of type `T`"
549
- }]
550
- pub const unsafe fn read <T >(src : * const T ) -> T { ... }
551
- ```
552
-
553
- ` #[safety] ` becomes a procedural macro that expands to both ` #[doc] ` attributes and the
554
- ` #[safety::requires] ` attribute.
555
-
556
- ``` rust
557
- /// # Safety
558
- ///
559
- /// - ValidPtr: `src` must be [valid] for reads
560
- /// - Aligned: `src` must be properly aligned. Use [`read_unaligned`] if this is not the case
561
- /// - Initialized: `src` must point to a properly initialized value of type `T`
562
- #[safety:: requires { ValidPtr = " ..." , Aligned = " ..." , Initialized = " ..." }]
563
- pub const unsafe fn read <T >(src : * const T ) -> T { ... }
564
- ```
565
-
566
- With support for tag arguments, safety documentation can be made more precise and contextual by
567
- dynamically injecting the argument values into the reason strings.
568
-
569
600
## Discharge One Tag from ` any = { Option1, Option2 } `
570
601
571
602
Sometimes it’s useful to declare a set of safety tags on an unsafe function while discharging only
0 commit comments