Skip to content

Commit c6f3c6b

Browse files
tests
1 parent 3f8b366 commit c6f3c6b

15 files changed

+77
-290
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,8 @@ Please contribute, or at least subscribe, and give thumbs up, to:
598598

599599
## Related issues
600600
Sorted by importance (for `prudent`):
601+
- [rust-lang/rust#88531](https://github.com/rust-lang/rust/issues/88531) No way to get compile-time info from the type of local
602+
- [rust-lang/rust#63063](https://github.com/rust-lang/rust/issues/63063) Tracking issue for RFC 2515, "Permit impl Trait in type aliases"
601603
- [rust-lang/rust#110613](https://github.com/rust-lang/rust/issues/110613) Forbidding lints doesn't
602604
really work in macros
603605
- [rust-lang/rust#148942](https://github.com/rust-lang/rust/issues/148942) cfg(test) is not set

coverage_positive/md-shared_ref.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
use crate::prudent::unsafe_method;
22
// Works for Copy types
3-
const _: u8 = unsafe_method!( 1u8 =>@ unchecked_add => 0);
4-
const _: u8 = unsafe_method!(~allow_unsafe 1u8 =>@ unchecked_add => 0);
5-
const _: u8 = unsafe_method!(~allow_unsafe unsafe { 1u8.unchecked_add(2) } =>@ unchecked_add => 0);
6-
const _: u8 = unsafe_method!(~expect_unsafe unsafe { 1u8.unchecked_add(2) } =>@ unchecked_add => 0);
3+
const _: u8 = unsafe_method!( 1u8 =>@ unchecked_add => 0 );
74

85
fn main() {}
96

src/backend.rs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -291,28 +291,6 @@ macro_rules! expecting_unsafe_fn_path {
291291
};
292292
}
293293

294-
/// NOT a part of public API. Ensure that maximum one of `~allow_unsafe` or `~expect_unsafe` is
295-
/// passed to [unsafe_method].
296-
#[doc(hidden)]
297-
#[macro_export]
298-
macro_rules! max_one_active_of_allow_unsafe_expect_unsafe {
299-
(
300-
~allow_unsafe $( { $_allow_unsafe_empty_indicator:tt } )?
301-
~expect_unsafe $( { $_expect_unsafe_empty_indicator:tt } )?
302-
) => {
303-
compile_error!(
304-
"Do not use *both* ~allow_unsafe and ~expect_unsafe with unsafe_method macro."
305-
);
306-
};
307-
(
308-
~allow_unsafe $( { $_allow_unsafe_empty_indicator:tt } )?
309-
) => {};
310-
(
311-
~expect_unsafe $( { $_expect_unsafe_empty_indicator:tt } )?
312-
) => {};
313-
() => {};
314-
}
315-
316294
/// NOT a part of public API. Pretend to get a mutable reference from a shared reference. For
317295
/// internal/generated **compile-time** checks only.
318296
#[doc(hidden)]

src/frontend_linted.rs

Lines changed: 38 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,14 @@ macro_rules! internal_prudent_unsafe_fn {
5353
// 1. the result can be used as a value in an outer expression, and
5454
// 2. local variables don't conflict with the outer scope
5555
{
56-
// Ensure that $fn (the expression itself, one that yields a function to call) and
57-
// any arguments (expressions that yield values passed to the function to call)
56+
// Ensure that
57+
// - $fn (the expression itself, one that yields the function to call) and
58+
// - any arguments (expressions that yield values passed to the function to call)
59+
//
5860
// don't include any unnecessary `unsafe{...}` block(s):
61+
//
62+
// @TODO remove this #[deny(unused_unsafe)] ??? $fn or any of $arg could be a rexult
63+
// of unsafe_method!(...) that itself MAY have "unused_unsafe" in $self!!!
5964
#[deny(unused_unsafe)]
6065
// Ensure that $fn (the expression itself) and any arguments (expressions) don't
6166
// include any unsafe code/calls/casts on their own without their own `unsafe{...}`
@@ -108,6 +113,8 @@ macro_rules! internal_prudent_unsafe_fn {
108113
({
109114
// Ensure that $fn (the expression itself, one that yields a function to call) doesn't
110115
// include an unnecessary `unsafe{...}` block:
116+
//
117+
// @TODO remove this #[deny(unused_unsafe)]
111118
#[deny(unused_unsafe)]
112119
// Ensure that $fn (the expression itself) doesn't include any unsafe code/calls/casts
113120
// on its own without its own `unsafe{...}` block(s):
@@ -122,11 +129,6 @@ macro_rules! internal_prudent_unsafe_fn {
122129
};
123130
::core::unreachable!()
124131
}
125-
// `#[deny(unused_unsafe)]` does NOT work here. Why? Because when we assigned `let fun =
126-
// $fn` above, that then happily coerces/infers to an unsafe function, even though it's
127-
// safe. That's why we have `expecting_unsafe_fn` module.
128-
#[deny(unused_unsafe)]
129-
#[allow(unsafe_code)]
130132
let result = unsafe {
131133
fun()
132134
};
@@ -182,6 +184,7 @@ macro_rules! internal_prudent_unsafe_fn_internal_build_accessors_and_call {
182184
),*
183185
) => {
184186
#[allow(unsafe_code)]
187+
// @TODO remove this #[deny(unused_unsafe)]
185188
#[deny(unused_unsafe)]
186189
unsafe {
187190
$fn( $(
@@ -215,91 +218,52 @@ pub use internal_prudent_unsafe_fn_internal_access_tuple_tree_field;
215218
/// - This treats `self` as if it were evaluated **outside** the `unsafe {...}` block.
216219
/// - $fn can **NOT** be an expression or a qualified path (which doesn't work in standard methods
217220
/// calls anyways), but only an identifier.
218-
///
219-
/// Do NOT use parameters/input parts matched by
220-
/// - `$expect_unsafe_empty_indicator` or
221-
/// - `$allow_unsafe_empty_indicator`
222-
///
223-
/// as they are internal.
224221
#[macro_export]
225222
#[doc(hidden)]
226223
macro_rules! internal_prudent_unsafe_method {
227224
(
228-
$( ~allow_unsafe $( { $allow_unsafe_empty_indicator:tt } )? )?
229-
$( ~expect_unsafe $( { $expect_unsafe_empty_indicator:tt } )? )?
230225
$self:expr =>@ $method:ident
231226
) => {
232227
internal_prudent_unsafe_method!(
233-
$( ~allow_unsafe $( { $allow_unsafe_empty_indicator } )? )?
234-
$( ~expect_unsafe $( { $expect_unsafe_empty_indicator } )? )?
235228
$self =>@ $method =>
236229
)
237230
};
238231
(
239-
$( ~allow_unsafe $( { $allow_unsafe_empty_indicator:tt } )? )?
240-
$( ~expect_unsafe $( { $expect_unsafe_empty_indicator:tt } )? )?
241232
$self:expr =>@ $method:ident => $( $arg:expr ),*
242233
) => {
243234
// See unsafe_fn for why here we enclose in (...) and not in {...}.
244235
(
245236
if false {
246-
// no module needed in the following macro path, since allow_unsafe_expect_unsafe_is_correct has #[macro_export]
247-
::prudent::max_one_active_of_allow_unsafe_expect_unsafe!{
248-
$( ~allow_unsafe $( { $allow_unsafe_empty_indicator } )? )?
249-
$( ~expect_unsafe $( { $expect_unsafe_empty_indicator } )? )?
250-
}
251-
if false {
252-
// This block "makes" an owned_receiver, an instance/owned value of the same
253-
// type as $self. (Of course, the instance is invalid - this is for compile-time
254-
// checks only, hence `if false {...}`.)
255-
//
256-
// Then we simulate invocation of the given method inside `unsafe {...}``, BUT
257-
// without evaluating the given $self expression inside that same `unsafe
258-
// {...}`` block, so that we isolate/catch any `unsafe`` code in $self.
259-
//
260-
// We **cannot** just move/take/assign $self by value, in case it's a non-Copy
261-
// **static** variable. See also comments in
262-
// unsafe_method_internal_build_accessors_check_args_call.
263-
let mref = {
264-
#[rustfmt::skip]
265-
#[deny(unused_unsafe)]
266-
// @TODO simplify once https://github.com/rust-lang/rust/issues/15701
267-
// (attributes on expressions)
268-
#[deny(unsafe_code)]
269-
#[deny(unfulfilled_lint_expectations)]
270-
$(
271-
$( { $allow_unsafe_empty_indicator } )?
272-
#[allow(unsafe_code)]
273-
)?
274-
$(
275-
$( { $expect_unsafe_empty_indicator } )?
276-
#[expect(unsafe_code)]
277-
)?
278-
let rref = &( $self );
279-
::prudent::backend::shared_to_mut( rref )
280-
};
281-
#[allow(unused_mut)]
282-
#[allow(invalid_value)] // for &str and other types where zeroed() issues invalid_value warning.
283-
let mut owned_receiver = ::core::mem::replace(mref, unsafe{ ::core::mem::zeroed() });
284-
// Detect code where unsafe_method! is not needed at all. Maybe the method used
285-
// to be `unsafe`, but not anymore.
286-
#[deny(unused_unsafe)]
287-
let _ = unsafe { owned_receiver. $method( $( $arg ),* ) };
288-
//@TODO here call the method with tuple tree-stored evaluated args.
289-
//
290-
//THEN simplify internal_prudent_unsafe_method_internal_check_args_etc -> internal_prudent_unsafe_method_internal_build_accessors_check_args_call
291-
} else {
292-
// @TODO eliminate
293-
$(
294-
#[deny(unused_unsafe)]
295-
let _ = $arg;
296-
)*
297-
}
237+
// "Make" an owned_receiver, an instance/owned value of the same
238+
// type as $self. (Of course, the instance is invalid - this is for compile-time
239+
// checks only, hence `if false {...}`.)
240+
//
241+
// Then we simulate invocation of the given method inside `unsafe {...}``, BUT
242+
// without evaluating the given $self expression inside that same `unsafe
243+
// {...}`` block, so that we isolate/catch any `unsafe`` code in $self.
244+
//
245+
// We **cannot** just move/take/assign $self by value, in case it's a non-Copy
246+
// **static** variable. See also comments in
247+
// unsafe_method_internal_build_accessors_check_args_call.
248+
let mref = {
249+
let rref = &( $self );
250+
::prudent::backend::shared_to_mut( rref )
251+
};
252+
#[allow(unused_mut)]
253+
#[allow(invalid_value)] // for &str and other types where zeroed() issues invalid_value warning.
254+
let mut owned_receiver = ::core::mem::replace(mref, unsafe{ ::core::mem::zeroed() });
255+
// Detect code where `unsafe_method!` is not needed at all. Maybe the method used
256+
// to be `unsafe`, but not anymore.
257+
//
258+
// @TODO This is the only place where we "need" #[deny(unused_unsafe)]
259+
#[deny(unused_unsafe)]
260+
let _ = unsafe { owned_receiver. $method( $( $arg ),* ) };
261+
//@TODO here call the method with tuple tree-stored evaluated args.
262+
//
263+
//THEN simplify internal_prudent_unsafe_method_internal_check_args_etc -> internal_prudent_unsafe_method_internal_build_accessors_check_args_call
298264
::core::unreachable!()
299265
} else {
300266
internal_prudent_unsafe_method_internal_check_args_etc!(
301-
$( ~allow_unsafe $( { $allow_unsafe_empty_indicator } )? )?
302-
$( ~expect_unsafe $( { $expect_unsafe_empty_indicator } )? )?
303267
$self, $method $(, $arg )*
304268
)
305269
}
@@ -312,17 +276,12 @@ pub use internal_prudent_unsafe_method;
312276
#[macro_export]
313277
macro_rules! internal_prudent_unsafe_method_internal_check_args_etc {
314278
(
315-
$( ~expect_unsafe $( { $expect_unsafe_empty_indicator:tt } )? )?
316-
$( ~allow_unsafe $( { $allow_unsafe_empty_indicator:tt } )? )?
317279
$self:expr, $fn:ident $(, $arg:expr )+
318280
) => {({
319-
#[deny(unused_unsafe)]
320281
let tuple_tree =
321282
internal_prudent_unsafe_fn_internal_build_tuple_tree!{ $($arg),+ };
322283

323284
internal_prudent_unsafe_method_internal_build_accessors_check_args_call! {
324-
$( ~allow_unsafe $( { $allow_unsafe_empty_indicator } )? )?
325-
$( ~expect_unsafe $( { $expect_unsafe_empty_indicator } )? )?
326285
$self,
327286
$fn,
328287
tuple_tree,
@@ -331,22 +290,9 @@ macro_rules! internal_prudent_unsafe_method_internal_check_args_etc {
331290
}
332291
})};
333292
(
334-
$( ~expect_unsafe $( { $expect_unsafe_empty_indicator:tt } )? )?
335-
$( ~allow_unsafe $( { $allow_unsafe_empty_indicator:tt } )? )?
336293
$self:expr, $fn:ident
337294
) => {({
338295
#[allow(unsafe_code)]
339-
// Notify if $self includes `unsafe {...}`, but no ~allow_unsafe or ~expect_unsafe:
340-
#[deny(unused_unsafe)]
341-
$(
342-
$( { $allow_unsafe_empty_indicator } )?
343-
#[allow(unused_unsafe)]
344-
)?
345-
$(
346-
$( { $expect_unsafe_empty_indicator } )?
347-
#[expect(unused_unsafe)]
348-
)?
349-
//#[deny(unused_unsafe)]
350296
let result = unsafe { $self. $fn () };
351297
result
352298
})};
@@ -358,17 +304,13 @@ pub use internal_prudent_unsafe_method_internal_check_args_etc;
358304
macro_rules! internal_prudent_unsafe_method_internal_build_accessors_check_args_call {
359305
// Access tuple_tree parts and get ready to call the method:
360306
(
361-
$( ~expect_unsafe $( { $expect_unsafe_empty_indicator:tt } )? )?
362-
$( ~allow_unsafe $( { $allow_unsafe_empty_indicator:tt } )? )?
363307
$self:expr, $fn:ident, $tuple_tree:ident,
364308
( $_first_arg:expr, $($other_arg:expr),+ ),
365309
$( ( $($accessor_part:tt),+
366310
)
367311
),*
368312
) => {
369313
internal_prudent_unsafe_method_internal_build_accessors_check_args_call!{
370-
$( ~allow_unsafe $( { $allow_unsafe_empty_indicator } )? )?
371-
$( ~expect_unsafe $( { $expect_unsafe_empty_indicator } )? )?
372314
$self, $fn, $tuple_tree, ( $($other_arg),+ ),
373315
// Insert a new accessor to the front (left): 0.
374316
(0),
@@ -379,30 +321,20 @@ macro_rules! internal_prudent_unsafe_method_internal_build_accessors_check_args_
379321
};
380322
// All accessors are ready. Call the function:
381323
(
382-
$( ~expect_unsafe $( { $expect_unsafe_empty_indicator:tt } )? )?
383-
$( ~allow_unsafe $( { $allow_unsafe_empty_indicator:tt } )? )?
384324
$self:expr, $fn:ident, $tuple_tree:ident,
385325
( $_last_or_only_arg:expr ),
386326
$( ( $($accessor_part:tt),+
387327
)
388328
),*
389329
) => {({
390330
#[allow(unsafe_code)]
391-
#[deny(unused_unsafe)]
392-
$(
393-
$( { $allow_unsafe_empty_indicator } )?
394-
#[allow(unused_unsafe)]
395-
)?
396-
$(
397-
$( { $expect_unsafe_empty_indicator } )?
398-
#[expect(unused_unsafe)]
399-
)?
400331
let result = unsafe {
401332
// Unlike arguments, we can NOT store result of $self expression in a variable, because
402333
// - it would be moved, but a method with receiver by reference `&self` or `&mut self`
403334
// does NOT move the instance it's called on. Also,
404335
// - if Self were `Copy`, then `&self` or `&mut self` reference would not point to the
405336
// original instance! (Plus extra stack used, plus lifetimes issues.)
337+
// - it could be a non-Copy **static** variable, which cannot be moved.
406338
$self. $fn( $(
407339
internal_prudent_unsafe_fn_internal_access_tuple_tree_field!{ $tuple_tree, $($accessor_part),+ }
408340
),*

src/frontend_unlinted.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,6 @@ macro_rules! internal_prudent_unsafe_method {
239239
// See unsafe_fn for why here we enclose in (...) and not in {...}.
240240
(
241241
if false {
242-
::prudent::max_one_active_of_allow_unsafe_expect_unsafe!{
243-
$( ~allow_unsafe $( { $allow_unsafe_empty_indicator } )? )?
244-
$( ~expect_unsafe $( { $expect_unsafe_empty_indicator } )? )?
245-
}
246242
if false {
247243
// This block "makes" owned_receiver, an instance/owned value of the same type
248244
// as $self. (Of course, the instance is invalid - this is for compile-time

src/frontend_with_compile_fail_tests.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -181,14 +181,6 @@ pub use crate::frontend_untested::internal_prudent_unsafe_fn_internal_access_tup
181181
/// ```compile_fail
182182
#[doc = include_str!("../violations_coverage/unsafe_method/fn_unused_unsafe/some_args.rs")]
183183
/// ```
184-
///
185-
/// ```compile_fail
186-
#[doc = include_str!("../violations_coverage/unsafe_method/unused_expect_unsafe/zero_args.rs")]
187-
/// ```
188-
///
189-
/// ```compile_fail
190-
#[doc = include_str!("../violations_coverage/unsafe_method/unused_expect_unsafe/some_args.rs")]
191-
/// ```
192184
#[doc(inline)]
193185
pub use crate::frontend_untested::internal_prudent_unsafe_method;
194186

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
1+
warning: unexpected `cfg` condition value: `internal_use_frontend_linted`
2+
--> violations/frontend_linted.rs
3+
|
4+
| #[cfg(not(feature = "internal_use_frontend_linted"))]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the condition
6+
|
7+
= note: no expected values for `feature`
8+
= help: consider adding `internal_use_frontend_linted` as a feature in `Cargo.toml`
9+
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
10+
= note: `#[warn(unexpected_cfgs)]` on by default
11+
112
error: unnecessary `unsafe` block
213
--> violations/frontend_linted.rs
314
|
4-
| let _ = unsafe { owned_receiver. $fn( $( $arg ),* ) };
5-
| ^^^^^^ unnecessary `unsafe` block
15+
| let _ = unsafe { owned_receiver. $method( $( $arg ),* ) };
16+
| ^^^^^^ unnecessary `unsafe` block
617
|
718
::: violations/unsafe_method-fn_unused_unsafe-some_args.rs:11:5
819
|
@@ -12,16 +23,16 @@ error: unnecessary `unsafe` block
1223
note: the lint level is defined here
1324
--> violations/frontend_linted.rs
1425
|
15-
| #[deny(unused_unsafe)]
16-
| ^^^^^^^^^^^^^
26+
| #[deny(unused_unsafe)]
27+
| ^^^^^^^^^^^^^
1728
|
1829
::: violations/unsafe_method-fn_unused_unsafe-some_args.rs:11:5
1930
|
2031
11 | unsafe_method!(s =>@ use_it => true);
2132
| ------------------------------------ in this macro invocation
2233
= note: this error originates in the macro `unsafe_method` (in Nightly builds, run with -Z macro-backtrace for more info)
2334

24-
error: unnecessary `unsafe` block
35+
warning: unnecessary `unsafe` block
2536
--> violations/frontend_linted.rs
2637
|
2738
| let result = unsafe {
@@ -32,14 +43,5 @@ error: unnecessary `unsafe` block
3243
11 | unsafe_method!(s =>@ use_it => true);
3344
| ------------------------------------ in this macro invocation
3445
|
35-
note: the lint level is defined here
36-
--> violations/frontend_linted.rs
37-
|
38-
| #[deny(unused_unsafe)]
39-
| ^^^^^^^^^^^^^
40-
|
41-
::: violations/unsafe_method-fn_unused_unsafe-some_args.rs:11:5
42-
|
43-
11 | unsafe_method!(s =>@ use_it => true);
44-
| ------------------------------------ in this macro invocation
45-
= note: this error originates in the macro `internal_prudent_unsafe_method_internal_build_accessors_check_args_call` which comes from the expansion of the macro `unsafe_method` (in Nightly builds, run with -Z macro-backtrace for more info)
46+
= note: `#[warn(unused_unsafe)]` (part of `#[warn(unused)]`) on by default
47+
= note: this warning originates in the macro `internal_prudent_unsafe_method_internal_build_accessors_check_args_call` which comes from the expansion of the macro `unsafe_method` (in Nightly builds, run with -Z macro-backtrace for more info)

0 commit comments

Comments
 (0)