Skip to content

Commit c5735da

Browse files
Re-org/cleanup
1 parent 8e71d6d commit c5735da

File tree

3 files changed

+205
-239
lines changed

3 files changed

+205
-239
lines changed

src/frontend.rs

Lines changed: 196 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
// For docs see frontend_with_compile_fail_tests.rs
2-
#![allow(missing_docs)]
3-
41
/// Invoke an `unsafe` function, but isolate `unsafe {...}` only for the function invocation itself.
52
/// - If `$fn` (the function itself) is NOT given as an identifier/qualified path, but it's given as
63
/// an expression, then this expression is treated as if evaluated **outside** `unsafe {...}`.
@@ -17,6 +14,76 @@
1714
/// `unsafe.`
1815
/// - Some arguments. The given expression (which evaluates to the function to be called) is
1916
/// `unsafe.`
17+
/// ```compile_fail
18+
/// // @TODO Docs: at your crate's top level, use either self::prudent, or crate:;prudent (but NOT
19+
/// // just prudent, which will fail, fortunately).
20+
#[doc = include_str!("../violations_coverage/unsafe_fn/sneaked_unsafe/fn_expr_zero_args.rs")]
21+
/// ```
22+
///
23+
/// ## Some arguments
24+
/// The given expression (which evaluates to the function to be called) is `unsafe.`
25+
/// ```compile_fail
26+
#[doc = include_str!("../violations_coverage/unsafe_fn/sneaked_unsafe/fn_expr_some_args.rs")]
27+
/// ```
28+
///
29+
/// A passed parameter (expression that evaluates to a value passed to the target `unsafe` function as an argument) itself is `unsafe.`
30+
/// ```compile_fail
31+
#[doc = include_str!("../violations_coverage/unsafe_fn/sneaked_unsafe/arg.rs")]
32+
/// ```
33+
///
34+
/// The target function is safe, hence no need for `unsafe_fn`. Zero args.
35+
/// ```compile_fail
36+
#[doc = include_str!("../violations_coverage/unsafe_fn/fn_unused_unsafe/zero_args.rs")]
37+
/// ```
38+
///
39+
/// The target function is safe, hence no need for `unsafe_fn`. Some args.
40+
/// ```compile_fail
41+
#[doc = include_str!("../violations_coverage/unsafe_fn/fn_unused_unsafe/some_args.rs")]
42+
/// ```
43+
/// test cfg test:
44+
/// ```test_harness
45+
/// // test_harness -as per https://github.com/rust-lang/rust/issues/148942#issuecomment-3565011334
46+
/// #[cfg(not(test))]
47+
/// compile_error!("NOT DOCTEST!");
48+
/// ```
49+
/// Use the result of `unsafe_fn!` immediately as an array/slice:
50+
/// ```test_harness
51+
/// //TODO? failing??
52+
/// use prudent::*;
53+
/// const unsafe fn return_array() -> [bool; 1] { [true] }
54+
///
55+
/// const _: bool = unsafe_fn!( return_array)[0];
56+
/// ```
57+
/// Use the result of `unsafe_fn!` immediately as a mutable array/slice (assign/modify its slot(s)):
58+
/// ```
59+
/// // @TODO MOVE OUT TO coverage_positive/
60+
/// use prudent::*;
61+
/// fn _test_unsafe_fn_returning_mut_ref() {
62+
/// // NOT running under MIRI, because of an intentional leak.
63+
/// if !cfg!(miri) {
64+
/// unsafe fn return_mut_ref_array() -> &'static mut [bool; 1] {
65+
/// let boxed = Box::new([true]);
66+
/// Box::leak(boxed)
67+
/// }
68+
///
69+
/// unsafe_fn!( return_mut_ref_array)[0] = true;
70+
/// }
71+
/// }
72+
/// fn main() {}
73+
/// ```
74+
/// The same, but the function takes an argument (and no leak):
75+
/// ```
76+
/// // @TODO MOVE OUT TO coverage_positive/
77+
/// use prudent::*;
78+
/// unsafe fn return_same_mut_ref<T>(mref: &mut T) -> &mut T {
79+
/// mref
80+
/// }
81+
///
82+
/// fn main() {
83+
/// let mut marray = [true];
84+
/// unsafe_fn!( return_same_mut_ref => &mut marray )[0] = true;
85+
/// }
86+
/// ```
2087
#[doc(hidden)]
2188
#[macro_export]
2289
macro_rules! unsafe_fn {
@@ -101,6 +168,49 @@ macro_rules! unsafe_fn {
101168
};
102169
}
103170

171+
// Same `compile_fail` tests as listed above for `unsafe_fn`, but here we validate the error
172+
// numbers.
173+
//
174+
// Error numbers are validated with `cargo +nightly test`, ([The Rustdoc book > Unstable features >
175+
// Error numbers for compile-fail
176+
// doctests](https://doc.rust-lang.org/rustdoc/unstable-features.html#error-numbers-for-compile-fail-doctests))
177+
// but NOT with
178+
// - `cargo +stable test` nor
179+
// - RUSTDOCFLAGS="..." cargo +nightly doc ...
180+
//
181+
// Even though the following constant is "pub", it will **not** be a part of the public API, neither
182+
// a part of the documentation - it's used for doctest only.
183+
/// ```compile_fail,E0133
184+
#[doc = include_str!("../violations_coverage/unsafe_fn/sneaked_unsafe/fn_expr_zero_args.rs")]
185+
/// ```
186+
#[cfg(doctest)]
187+
pub const _: () = {};
188+
189+
/// ```compile_fail,E0133
190+
#[doc = include_str!("../violations_coverage/unsafe_fn/sneaked_unsafe/fn_expr_some_args.rs")]
191+
/// ```
192+
#[cfg(doctest)]
193+
pub const _: () = {};
194+
195+
/// ```compile_fail,E0133
196+
#[doc = include_str!("../violations_coverage/unsafe_fn/sneaked_unsafe/arg.rs")]
197+
/// ```
198+
#[cfg(doctest)]
199+
pub const _: () = {};
200+
201+
/// ```compile_fail,E0308
202+
#[doc = include_str!("../violations_coverage/unsafe_fn/fn_unused_unsafe/zero_args.rs")]
203+
/// ```
204+
#[cfg(doctest)]
205+
pub const _: () = {};
206+
207+
/// ```compile_fail,E0308
208+
#[doc = include_str!("../violations_coverage/unsafe_fn/fn_unused_unsafe/some_args.rs")]
209+
/// ```
210+
#[cfg(doctest)]
211+
pub const _: () = {};
212+
//----------------------
213+
104214
/// INTERNAL. Do NOT use directly - subject to change.
105215
#[doc(hidden)]
106216
#[macro_export]
@@ -176,6 +286,28 @@ macro_rules! unsafe_fn_internal_access_tuple_tree_field {
176286
/// - This treats `self` as if it were evaluated **outside** the `unsafe {...}` block.
177287
/// - $fn can **NOT** be an expression or a qualified path (which doesn't work in standard methods
178288
/// calls anyways), but only an identifier.
289+
///
290+
/// ```compile_fail
291+
#[doc = include_str!("../violations_coverage/unsafe_method/sneaked_unsafe/arg.rs")]
292+
/// ```
293+
///
294+
/// ```compile_fail
295+
#[doc = include_str!("../violations_coverage/unsafe_method/sneaked_unsafe/self_zero_args.rs")]
296+
/// ```
297+
///
298+
/// ```compile_fail
299+
#[doc = include_str!("../violations_coverage/unsafe_method/sneaked_unsafe/self_some_args.rs")]
300+
/// ```
301+
// TODO refactor for new checks:
302+
// ```compile_fail
303+
//#[doc = include_str!("../violations_coverage/unsafe_method/fn_unused_unsafe/zero_args.rs")]
304+
// ```
305+
//
306+
//#[allow(clippy::useless_attribute)]
307+
//#[allow(clippy::needless_doctest_main)]
308+
// ```compile_fail
309+
//#[doc = include_str!("../violations_coverage/unsafe_method/fn_unused_unsafe/some_args.rs")]
310+
// ```
179311
#[macro_export]
180312
#[doc(hidden)]
181313
macro_rules! unsafe_method {
@@ -249,6 +381,25 @@ macro_rules! unsafe_method {
249381
}
250382
}
251383

384+
/// ```compile_fail,E0133
385+
#[doc = include_str!("../violations_coverage/unsafe_method/sneaked_unsafe/arg.rs")]
386+
/// ```
387+
#[cfg(doctest)]
388+
pub const _: () = {};
389+
390+
/// ```compile_fail,E0133
391+
#[doc = include_str!("../violations_coverage/unsafe_method/sneaked_unsafe/self_zero_args.rs")]
392+
/// ```
393+
#[cfg(doctest)]
394+
pub const _: () = {};
395+
396+
/// ```compile_fail,E0133
397+
#[doc = include_str!("../violations_coverage/unsafe_method/sneaked_unsafe/self_some_args.rs")]
398+
/// ```
399+
#[cfg(doctest)]
400+
pub const _: () = {};
401+
//----------------------
402+
252403
#[doc(hidden)]
253404
#[macro_export]
254405
macro_rules! unsafe_method_internal_check_args_etc {
@@ -331,6 +482,48 @@ macro_rules! unsafe_method_internal_build_accessors_check_args_call {
331482
/// in `unsafe{...}`. TODO reconsider.
332483
///
333484
/// NOT for `static` variables (or their fields/components) of `union` types.
485+
///
486+
/// ```
487+
/// // @TODO MOVE OUT TO coverage_positive/
488+
/// //use prudent::*;
489+
/// fn main() {
490+
/// {
491+
/// static mut S: (bool,) = (true,);
492+
///
493+
/// let mptr = &raw mut S;
494+
/// unsafe { *mptr = (false,); }
495+
///
496+
/// let _mref = unsafe {&mut *mptr};
497+
///
498+
/// // The following IS accepted:
499+
/// //
500+
/// //{unsafe {&mut *mptr}}.0 = true;
501+
/// //
502+
/// // BUT, because the outer curly brackets {...} are **refused** just left of
503+
/// // [index_here] when indexing arrays (see below), we use oval parenthesis (...)
504+
/// // which work for both: the tuple access .usize_literal and for array access
505+
/// // [usize_expression].
506+
/// }
507+
/// {
508+
/// static mut ARR: [bool; 1] = [true];
509+
/// let mptr = &raw mut ARR;
510+
/// unsafe { *mptr = [false]; }
511+
///
512+
/// let _mref = unsafe {&mut *mptr};
513+
/// *_mref = [false];
514+
/// _mref[ 0 ] = true;
515+
///
516+
/// // Read access OK:
517+
/// let _b: bool = { unsafe {&mut *mptr} }[ 0 ];
518+
/// // Mut access - bad: The following refused:
519+
/// //
520+
/// //{ unsafe {&mut *mptr} }[ 0 ] = true;
521+
/// //
522+
/// // Have to use oval parenthesis:
523+
/// ( unsafe {&mut *mptr} )[ 0 ] = true;
524+
/// }
525+
/// }
526+
/// ```
334527
#[macro_export]
335528
#[doc(hidden)]
336529
macro_rules! unsafe_static_set {

0 commit comments

Comments
 (0)