@@ -279,6 +279,54 @@ against [Semantic Versioning][semver].
279279
280280[ semver ] : https://doc.rust-lang.org/cargo/reference/semver.html
281281
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+
282330# Reference-level explanation
283331[ reference-level-explanation ] : #reference-level-explanation
284332
@@ -300,6 +348,7 @@ their call sites. To enable experimentation, a nightly-only library feature
300348Procedure:
301349
3023501 . 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.
3033522 . Validate ` #[safety::checked] ` on HIR nodes whose ` ExprKind ` is one of
304353 - ** direct unsafe nodes** : ` Call ` , ` MethodCall ` that invoke an unsafe function/method, or
305354 - ** indirect unsafe nodes** : ` Block ` (unsafe), ` Let ` , ` Assign ` , ` AssignOp ` .
@@ -312,8 +361,10 @@ Procedure:
312361 3 . Any node that carries ` #[safety::checked] ` must contain ** exactly one** unsafe call/method;
313362 otherwise emit a diagnostic. * (We intentionally stop at this simple rule; splitting complex
314363 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).
317368
318369[ HIR ExprKind ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/enum.ExprKind.html
319370
@@ -328,6 +379,26 @@ documentation hover in `#[safety::checked]` as per tag definitions on unsafe cal
328379Maybe some logics on safety tags like collecting tag definitions need to be extracted to a shared
329380crate for both Clippy and Rust-Analyzer to use.
330381
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+
331402# Drawbacks
332403[ drawbacks ] : #drawbacks
333404
@@ -358,12 +429,17 @@ to implement them.
358429 be tied to internal APIs and specific toolchains. Extending Rust-Analyzer is therefore the only
359430 practical way to give users first-class IDE support.
360431
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+
361436We therefore seek approvals from the following teams:
362437
3634381 . ** Library team** – to allow the tagging of unsafe operations and to expose tag items as public
364439 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.
3674434 . ** Compiler team** – to reserve the ` safety ` namespace and gate the feature via
368444 ` #![feature(safety_tags)] ` for the namespace and tag APIs in standard libraries.
369445
@@ -521,51 +597,6 @@ struct, enum, or union is neither needed nor permitted.
521597# Future possibilities
522598[ future-possibilities ] : #future-possibilities
523599
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-
569600## Discharge One Tag from ` any = { Option1, Option2 } `
570601
571602Sometimes it’s useful to declare a set of safety tags on an unsafe function while discharging only
0 commit comments