|
1 | | -// For docs see frontend_with_compile_fail_tests.rs |
2 | | -#![allow(missing_docs)] |
3 | | - |
4 | 1 | /// Invoke an `unsafe` function, but isolate `unsafe {...}` only for the function invocation itself. |
5 | 2 | /// - If `$fn` (the function itself) is NOT given as an identifier/qualified path, but it's given as |
6 | 3 | /// an expression, then this expression is treated as if evaluated **outside** `unsafe {...}`. |
|
17 | 14 | /// `unsafe.` |
18 | 15 | /// - Some arguments. The given expression (which evaluates to the function to be called) is |
19 | 16 | /// `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 | +/// ``` |
20 | 87 | #[doc(hidden)] |
21 | 88 | #[macro_export] |
22 | 89 | macro_rules! unsafe_fn { |
@@ -101,6 +168,49 @@ macro_rules! unsafe_fn { |
101 | 168 | }; |
102 | 169 | } |
103 | 170 |
|
| 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 | + |
104 | 214 | /// INTERNAL. Do NOT use directly - subject to change. |
105 | 215 | #[doc(hidden)] |
106 | 216 | #[macro_export] |
@@ -176,6 +286,28 @@ macro_rules! unsafe_fn_internal_access_tuple_tree_field { |
176 | 286 | /// - This treats `self` as if it were evaluated **outside** the `unsafe {...}` block. |
177 | 287 | /// - $fn can **NOT** be an expression or a qualified path (which doesn't work in standard methods |
178 | 288 | /// 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 | +// ``` |
179 | 311 | #[macro_export] |
180 | 312 | #[doc(hidden)] |
181 | 313 | macro_rules! unsafe_method { |
@@ -249,6 +381,25 @@ macro_rules! unsafe_method { |
249 | 381 | } |
250 | 382 | } |
251 | 383 |
|
| 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 | + |
252 | 403 | #[doc(hidden)] |
253 | 404 | #[macro_export] |
254 | 405 | macro_rules! unsafe_method_internal_check_args_etc { |
@@ -331,6 +482,48 @@ macro_rules! unsafe_method_internal_build_accessors_check_args_call { |
331 | 482 | /// in `unsafe{...}`. TODO reconsider. |
332 | 483 | /// |
333 | 484 | /// 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 | +/// ``` |
334 | 527 | #[macro_export] |
335 | 528 | #[doc(hidden)] |
336 | 529 | macro_rules! unsafe_static_set { |
|
0 commit comments