Auto merge of #10453 - Jarcho:test_utils, r=dswij

Add utility macros to help with writing tests.

Adds two utility macros to help with testing:
* `external` expands to it's argument tokens, but makes them appear to come from an external macro. Helps make tests for `in_external_macro` much more readable.
* `inline_macros` is an attribute macro which allows the use of a pseudo `inline!` macro which expands to it's argument tokens, but makes them appear to be from a crate-local macro expansion. This removes the need to write `macro_rules` boilerplate when testing how lints interact with macros.

---

`external`'s usage is simple. `external!(struct Foo { x: u32});` will make the struct appear as though it came from an external macro. Individual tokens can be escaped if needed. `external!($x + 0 / 10)` will make everything except `x` appear as though it came from an external macro. Can also use `$literal` and `$(tokens...)` as well.

---

`inline_macros` is more complicated due to compiler constraints. Given:
```rust
#[inline_macros]
fn foo() {
    inline!(5 + 5 / 10);
}
```
`inline!(5 + 5 / 10)` will be replace with a call to a generated macro which expands to the contained tokens.

Tokens can be escaped by prefixing them with `$`:
```rust
#[inline_macros]
fn foo() {
    let x = 5;
    inline!($x + 5 / $10);
}
```
This will pass `x` as an `ident` argument and `10` as a `literal` argument.

Token sequences can also be passed with `$(...)`:
```rust
#[inline_macros]
fn foo() {
    let mut x = 5;
    inline!(if $(x >= 5) {
        $x = 5;
    });
}
```
This will pass `x >= 5` as `tt` arguments, and `x` as an `ident` argument.

---

Not 100% sure `inline_macros` is actually worth having. It does make the tests a little easier to read once you're used to it and it becomes more useful once there are multiple macro tests. The verbosity of declaring single use macros starts to hurt at that point.

changelog: None
This commit is contained in:
bors 2023-03-12 21:36:47 +00:00
commit e65ad6f5d0
86 changed files with 1179 additions and 1098 deletions

View File

@ -1,6 +1,6 @@
// run-rustfix
// edition:2018
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![feature(exclusive_range_pattern)]
#![feature(stmt_expr_attributes)]
@ -9,33 +9,10 @@
#![allow(clippy::needless_parens_on_range_literals)]
#![allow(clippy::double_parens)]
#[macro_use]
extern crate macro_rules;
macro_rules! a {
() => {
'a'
};
}
macro_rules! A {
() => {
'A'
};
}
macro_rules! zero {
() => {
'0'
};
}
macro_rules! b {
() => {
let _ = 'a'..='z';
let _ = 'A'..='Z';
let _ = '0'..='9';
};
}
extern crate proc_macros;
use proc_macros::{external, inline_macros};
#[inline_macros]
fn main() {
#[rustfmt::skip]
{
@ -56,9 +33,9 @@ fn main() {
let _ = b'B'..b'Z';
let _ = b'1'..b'9';
let _ = a!()..='z';
let _ = A!()..='Z';
let _ = zero!()..='9';
let _ = inline!('a')..='z';
let _ = inline!('A')..='Z';
let _ = inline!('0')..='9';
let _ = match 0u8 {
b'a'..=b'z' if true => 1,
@ -80,8 +57,16 @@ fn main() {
_ => 7,
};
almost_complete_range!();
b!();
external!(
let _ = 'a'..'z';
let _ = 'A'..'Z';
let _ = '0'..'9';
);
inline!(
let _ = 'a'..='z';
let _ = 'A'..='Z';
let _ = '0'..='9';
);
}
#[clippy::msrv = "1.25"]

View File

@ -1,6 +1,6 @@
// run-rustfix
// edition:2018
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![feature(exclusive_range_pattern)]
#![feature(stmt_expr_attributes)]
@ -9,33 +9,10 @@
#![allow(clippy::needless_parens_on_range_literals)]
#![allow(clippy::double_parens)]
#[macro_use]
extern crate macro_rules;
macro_rules! a {
() => {
'a'
};
}
macro_rules! A {
() => {
'A'
};
}
macro_rules! zero {
() => {
'0'
};
}
macro_rules! b {
() => {
let _ = 'a'..'z';
let _ = 'A'..'Z';
let _ = '0'..'9';
};
}
extern crate proc_macros;
use proc_macros::{external, inline_macros};
#[inline_macros]
fn main() {
#[rustfmt::skip]
{
@ -56,9 +33,9 @@ fn main() {
let _ = b'B'..b'Z';
let _ = b'1'..b'9';
let _ = a!()..'z';
let _ = A!()..'Z';
let _ = zero!()..'9';
let _ = inline!('a')..'z';
let _ = inline!('A')..'Z';
let _ = inline!('0')..'9';
let _ = match 0u8 {
b'a'..b'z' if true => 1,
@ -80,8 +57,16 @@ fn main() {
_ => 7,
};
almost_complete_range!();
b!();
external!(
let _ = 'a'..'z';
let _ = 'A'..'Z';
let _ = '0'..'9';
);
inline!(
let _ = 'a'..'z';
let _ = 'A'..'Z';
let _ = '0'..'9';
);
}
#[clippy::msrv = "1.25"]

View File

@ -1,5 +1,5 @@
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:42:17
--> $DIR/almost_complete_range.rs:19:17
|
LL | let _ = ('a') ..'z';
| ^^^^^^--^^^
@ -9,7 +9,7 @@ LL | let _ = ('a') ..'z';
= note: `-D clippy::almost-complete-range` implied by `-D warnings`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:43:17
--> $DIR/almost_complete_range.rs:20:17
|
LL | let _ = 'A' .. ('Z');
| ^^^^--^^^^^^
@ -17,7 +17,7 @@ LL | let _ = 'A' .. ('Z');
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:44:17
--> $DIR/almost_complete_range.rs:21:17
|
LL | let _ = ((('0'))) .. ('9');
| ^^^^^^^^^^--^^^^^^
@ -25,7 +25,7 @@ LL | let _ = ((('0'))) .. ('9');
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:51:13
--> $DIR/almost_complete_range.rs:28:13
|
LL | let _ = (b'a')..(b'z');
| ^^^^^^--^^^^^^
@ -33,7 +33,7 @@ LL | let _ = (b'a')..(b'z');
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:52:13
--> $DIR/almost_complete_range.rs:29:13
|
LL | let _ = b'A'..b'Z';
| ^^^^--^^^^
@ -41,7 +41,7 @@ LL | let _ = b'A'..b'Z';
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:53:13
--> $DIR/almost_complete_range.rs:30:13
|
LL | let _ = b'0'..b'9';
| ^^^^--^^^^
@ -49,31 +49,31 @@ LL | let _ = b'0'..b'9';
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:59:13
--> $DIR/almost_complete_range.rs:36:13
|
LL | let _ = a!()..'z';
| ^^^^--^^^
| |
| help: use an inclusive range: `..=`
LL | let _ = inline!('a')..'z';
| ^^^^^^^^^^^^--^^^
| |
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:60:13
--> $DIR/almost_complete_range.rs:37:13
|
LL | let _ = A!()..'Z';
| ^^^^--^^^
| |
| help: use an inclusive range: `..=`
LL | let _ = inline!('A')..'Z';
| ^^^^^^^^^^^^--^^^
| |
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:61:13
--> $DIR/almost_complete_range.rs:38:13
|
LL | let _ = zero!()..'9';
| ^^^^^^^--^^^
| |
| help: use an inclusive range: `..=`
LL | let _ = inline!('0')..'9';
| ^^^^^^^^^^^^--^^^
| |
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:64:9
--> $DIR/almost_complete_range.rs:41:9
|
LL | b'a'..b'z' if true => 1,
| ^^^^--^^^^
@ -81,7 +81,7 @@ LL | b'a'..b'z' if true => 1,
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:65:9
--> $DIR/almost_complete_range.rs:42:9
|
LL | b'A'..b'Z' if true => 2,
| ^^^^--^^^^
@ -89,7 +89,7 @@ LL | b'A'..b'Z' if true => 2,
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:66:9
--> $DIR/almost_complete_range.rs:43:9
|
LL | b'0'..b'9' if true => 3,
| ^^^^--^^^^
@ -97,7 +97,7 @@ LL | b'0'..b'9' if true => 3,
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:74:9
--> $DIR/almost_complete_range.rs:51:9
|
LL | 'a'..'z' if true => 1,
| ^^^--^^^
@ -105,7 +105,7 @@ LL | 'a'..'z' if true => 1,
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:75:9
--> $DIR/almost_complete_range.rs:52:9
|
LL | 'A'..'Z' if true => 2,
| ^^^--^^^
@ -113,7 +113,7 @@ LL | 'A'..'Z' if true => 2,
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:76:9
--> $DIR/almost_complete_range.rs:53:9
|
LL | '0'..'9' if true => 3,
| ^^^--^^^
@ -121,46 +121,37 @@ LL | '0'..'9' if true => 3,
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:33:17
--> $DIR/almost_complete_range.rs:66:17
|
LL | let _ = 'a'..'z';
| ^^^--^^^
| |
| help: use an inclusive range: `..=`
...
LL | b!();
| ---- in this macro invocation
|
= note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:34:17
--> $DIR/almost_complete_range.rs:67:17
|
LL | let _ = 'A'..'Z';
| ^^^--^^^
| |
| help: use an inclusive range: `..=`
...
LL | b!();
| ---- in this macro invocation
|
= note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:35:17
--> $DIR/almost_complete_range.rs:68:17
|
LL | let _ = '0'..'9';
| ^^^--^^^
| |
| help: use an inclusive range: `..=`
...
LL | b!();
| ---- in this macro invocation
|
= note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:90:9
--> $DIR/almost_complete_range.rs:75:9
|
LL | 'a'..'z' => 1,
| ^^^--^^^
@ -168,7 +159,7 @@ LL | 'a'..'z' => 1,
| help: use an inclusive range: `...`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:91:9
--> $DIR/almost_complete_range.rs:76:9
|
LL | 'A'..'Z' => 2,
| ^^^--^^^
@ -176,7 +167,7 @@ LL | 'A'..'Z' => 2,
| help: use an inclusive range: `...`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:92:9
--> $DIR/almost_complete_range.rs:77:9
|
LL | '0'..'9' => 3,
| ^^^--^^^
@ -184,7 +175,7 @@ LL | '0'..'9' => 3,
| help: use an inclusive range: `...`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:99:13
--> $DIR/almost_complete_range.rs:84:13
|
LL | let _ = 'a'..'z';
| ^^^--^^^
@ -192,7 +183,7 @@ LL | let _ = 'a'..'z';
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:100:13
--> $DIR/almost_complete_range.rs:85:13
|
LL | let _ = 'A'..'Z';
| ^^^--^^^
@ -200,7 +191,7 @@ LL | let _ = 'A'..'Z';
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:101:13
--> $DIR/almost_complete_range.rs:86:13
|
LL | let _ = '0'..'9';
| ^^^--^^^
@ -208,7 +199,7 @@ LL | let _ = '0'..'9';
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:103:9
--> $DIR/almost_complete_range.rs:88:9
|
LL | 'a'..'z' => 1,
| ^^^--^^^
@ -216,7 +207,7 @@ LL | 'a'..'z' => 1,
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:104:9
--> $DIR/almost_complete_range.rs:89:9
|
LL | 'A'..'Z' => 1,
| ^^^--^^^
@ -224,7 +215,7 @@ LL | 'A'..'Z' => 1,
| help: use an inclusive range: `..=`
error: almost complete ascii range
--> $DIR/almost_complete_range.rs:105:9
--> $DIR/almost_complete_range.rs:90:9
|
LL | '0'..'9' => 3,
| ^^^--^^^

View File

@ -1,20 +1,15 @@
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::as_conversions)]
#![allow(clippy::borrow_as_ptr)]
#[macro_use]
extern crate macro_rules;
fn with_external_macro() {
as_conv_with_arg!(0u32 as u64);
as_conv!();
}
extern crate proc_macros;
use proc_macros::external;
fn main() {
let i = 0u32 as u64;
let j = &i as *const u64 as *mut u64;
with_external_macro();
external!(0u32 as u64);
}

View File

@ -1,5 +1,5 @@
error: using a potentially dangerous silent `as` conversion
--> $DIR/as_conversions.rs:15:13
--> $DIR/as_conversions.rs:10:13
|
LL | let i = 0u32 as u64;
| ^^^^^^^^^^^
@ -8,7 +8,7 @@ LL | let i = 0u32 as u64;
= note: `-D clippy::as-conversions` implied by `-D warnings`
error: using a potentially dangerous silent `as` conversion
--> $DIR/as_conversions.rs:17:13
--> $DIR/as_conversions.rs:12:13
|
LL | let j = &i as *const u64 as *mut u64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -16,7 +16,7 @@ LL | let j = &i as *const u64 as *mut u64;
= help: consider using a safe wrapper for this conversion
error: using a potentially dangerous silent `as` conversion
--> $DIR/as_conversions.rs:17:13
--> $DIR/as_conversions.rs:12:13
|
LL | let j = &i as *const u64 as *mut u64;
| ^^^^^^^^^^^^^^^^

View File

@ -1,16 +0,0 @@
#[macro_export]
macro_rules! undocd_unsafe {
() => {
pub unsafe fn oy_vey() {
unimplemented!();
}
};
}
#[macro_export]
macro_rules! undocd_safe {
() => {
pub fn vey_oy() {
unimplemented!();
}
};
}

View File

@ -1,6 +0,0 @@
#[macro_export]
macro_rules! implicit_hasher_fn {
() => {
pub fn f(input: &HashMap<u32, u32>) {}
};
}

View File

@ -2,21 +2,6 @@
//! Used to test that certain lints don't trigger in imported external macros
#[macro_export]
macro_rules! foofoo {
() => {
loop {}
};
}
#[macro_export]
macro_rules! must_use_unit {
() => {
#[must_use]
fn foo() {}
};
}
#[macro_export]
macro_rules! try_err {
() => {
@ -36,135 +21,9 @@ macro_rules! string_add {
};
}
#[macro_export]
macro_rules! take_external {
($s:expr) => {
std::mem::replace($s, Default::default())
};
}
#[macro_export]
macro_rules! option_env_unwrap_external {
($env: expr) => {
option_env!($env).unwrap()
};
($env: expr, $message: expr) => {
option_env!($env).expect($message)
};
}
#[macro_export]
macro_rules! ref_arg_binding {
() => {
let ref _y = 42;
};
}
#[macro_export]
macro_rules! ref_arg_function {
() => {
fn fun_example(ref _x: usize) {}
};
}
#[macro_export]
macro_rules! as_conv_with_arg {
(0u32 as u64) => {
()
};
}
#[macro_export]
macro_rules! as_conv {
() => {
0u32 as u64
};
}
#[macro_export]
macro_rules! large_enum_variant {
() => {
enum LargeEnumInMacro {
A(i32),
B([i32; 8000]),
}
};
}
#[macro_export]
macro_rules! field_reassign_with_default {
() => {
#[derive(Default)]
struct A {
pub i: i32,
pub j: i64,
}
fn lint() {
let mut a: A = Default::default();
a.i = 42;
a;
}
};
}
#[macro_export]
macro_rules! default_numeric_fallback {
() => {
let x = 22;
};
}
#[macro_export]
macro_rules! mut_mut {
() => {
let mut_mut_ty: &mut &mut u32 = &mut &mut 1u32;
};
}
#[macro_export]
macro_rules! ptr_as_ptr_cast {
($ptr: ident) => {
$ptr as *const i32
};
}
#[macro_export]
macro_rules! manual_rem_euclid {
() => {
let value: i32 = 5;
let _: i32 = ((value % 4) + 4) % 4;
};
}
#[macro_export]
macro_rules! equatable_if_let {
($a:ident) => {{ if let 2 = $a {} }};
}
#[macro_export]
macro_rules! almost_complete_range {
() => {
let _ = 'a'..'z';
let _ = 'A'..'Z';
let _ = '0'..'9';
};
}
#[macro_export]
macro_rules! unsafe_macro {
() => {
unsafe {
*core::ptr::null::<()>();
*core::ptr::null::<()>();
}
};
}
#[macro_export]
macro_rules! needless_lifetime {
() => {
fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 {
unimplemented!()
}
};
}

View File

@ -13,7 +13,7 @@ pub mod inner {
// RE-EXPORT
// this will stick in `inner` module
pub use macro_rules::foofoo;
pub use macro_rules::mut_mut;
pub use macro_rules::try_err;
pub mod nested {

View File

@ -1,32 +0,0 @@
// compile-flags: --emit=link
// no-prefer-dynamic
#![crate_type = "proc-macro"]
extern crate proc_macro;
use proc_macro::{token_stream::IntoIter, Group, Span, TokenStream, TokenTree};
#[proc_macro]
pub fn with_span(input: TokenStream) -> TokenStream {
let mut iter = input.into_iter();
let span = iter.next().unwrap().span();
let mut res = TokenStream::new();
write_with_span(span, iter, &mut res);
res
}
fn write_with_span(s: Span, input: IntoIter, out: &mut TokenStream) {
for mut tt in input {
if let TokenTree::Group(g) = tt {
let mut stream = TokenStream::new();
write_with_span(s, g.stream().into_iter(), &mut stream);
let mut group = Group::new(g.delimiter(), stream);
group.set_span(s);
out.extend([TokenTree::Group(group)]);
} else {
tt.set_span(s);
out.extend([tt]);
}
}
}

View File

@ -0,0 +1,474 @@
// compile-flags: --emit=link
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(let_chains)]
#![feature(proc_macro_span)]
#![allow(dead_code)]
extern crate proc_macro;
use core::mem;
use proc_macro::{
token_stream::IntoIter,
Delimiter::{self, Brace, Parenthesis},
Group, Ident, Literal, Punct,
Spacing::{self, Alone, Joint},
Span, TokenStream, TokenTree as TT,
};
type Result<T> = core::result::Result<T, TokenStream>;
/// Make a `compile_error!` pointing to the given span.
fn make_error(msg: &str, span: Span) -> TokenStream {
TokenStream::from_iter([
TT::Ident(Ident::new("compile_error", span)),
TT::Punct(punct_with_span('!', Alone, span)),
TT::Group({
let mut msg = Literal::string(msg);
msg.set_span(span);
group_with_span(Parenthesis, TokenStream::from_iter([TT::Literal(msg)]), span)
}),
])
}
fn expect_tt<T>(tt: Option<TT>, f: impl FnOnce(TT) -> Option<T>, expected: &str, span: Span) -> Result<T> {
match tt {
None => Err(make_error(
&format!("unexpected end of input, expected {expected}"),
span,
)),
Some(tt) => {
let span = tt.span();
match f(tt) {
Some(x) => Ok(x),
None => Err(make_error(&format!("unexpected token, expected {expected}"), span)),
}
},
}
}
fn punct_with_span(c: char, spacing: Spacing, span: Span) -> Punct {
let mut p = Punct::new(c, spacing);
p.set_span(span);
p
}
fn group_with_span(delimiter: Delimiter, stream: TokenStream, span: Span) -> Group {
let mut g = Group::new(delimiter, stream);
g.set_span(span);
g
}
/// Token used to escape the following token from the macro's span rules.
const ESCAPE_CHAR: char = '$';
/// Takes a single token followed by a sequence tokens. Returns the sequence of tokens with their
/// span set to that of the first token. Tokens may be escaped with either `#ident` or `#(tokens)`.
#[proc_macro]
pub fn with_span(input: TokenStream) -> TokenStream {
let mut iter = input.into_iter();
let span = iter.next().unwrap().span();
let mut res = TokenStream::new();
if let Err(e) = write_with_span(span, iter, &mut res) {
e
} else {
res
}
}
/// Takes a sequence of tokens and return the tokens with the span set such that they appear to be
/// from an external macro. Tokens may be escaped with either `#ident` or `#(tokens)`.
#[proc_macro]
pub fn external(input: TokenStream) -> TokenStream {
let mut res = TokenStream::new();
if let Err(e) = write_with_span(Span::mixed_site(), input.into_iter(), &mut res) {
e
} else {
res
}
}
/// Copies all the tokens, replacing all their spans with the given span. Tokens can be escaped
/// either by `#ident` or `#(tokens)`.
fn write_with_span(s: Span, mut input: IntoIter, out: &mut TokenStream) -> Result<()> {
while let Some(tt) = input.next() {
match tt {
TT::Punct(p) if p.as_char() == ESCAPE_CHAR => {
expect_tt(
input.next(),
|tt| match tt {
tt @ (TT::Ident(_) | TT::Literal(_)) => {
out.extend([tt]);
Some(())
},
TT::Punct(mut p) if p.as_char() == ESCAPE_CHAR => {
p.set_span(s);
out.extend([TT::Punct(p)]);
Some(())
},
TT::Group(g) if g.delimiter() == Parenthesis => {
out.extend([TT::Group(group_with_span(Delimiter::None, g.stream(), g.span()))]);
Some(())
},
_ => None,
},
"an ident, a literal, or parenthesized tokens",
p.span(),
)?;
},
TT::Group(g) => {
let mut stream = TokenStream::new();
write_with_span(s, g.stream().into_iter(), &mut stream)?;
out.extend([TT::Group(group_with_span(g.delimiter(), stream, s))]);
},
mut tt => {
tt.set_span(s);
out.extend([tt]);
},
}
}
Ok(())
}
/// Within the item this attribute is attached to, an `inline!` macro is available which expands the
/// contained tokens as though they came from a macro expansion.
///
/// Within the `inline!` macro, any token preceded by `$` is passed as though it were an argument
/// with an automatically chosen fragment specifier. `$ident` will be passed as `ident`, `$1` or
/// `$"literal"` will be passed as `literal`, `$'lt` will be passed as `lifetime`, and `$(...)` will
/// pass the contained tokens as a `tt` sequence (the wrapping parenthesis are removed). If another
/// specifier is required it can be specified within parenthesis like `$(@expr ...)`. This will
/// expand the remaining tokens as a single argument.
///
/// Multiple `inline!` macros may be nested within each other. This will expand as nested macro
/// calls. However, any arguments will be passed as though they came from the outermost context.
#[proc_macro_attribute]
pub fn inline_macros(args: TokenStream, input: TokenStream) -> TokenStream {
let mut args = args.into_iter();
let mac_name = match args.next() {
Some(TT::Ident(name)) => Some(name),
Some(tt) => {
return make_error(
"unexpected argument, expected either an ident or no arguments",
tt.span(),
);
},
None => None,
};
if let Some(tt) = args.next() {
return make_error(
"unexpected argument, expected either an ident or no arguments",
tt.span(),
);
};
let mac_name = if let Some(mac_name) = mac_name {
Ident::new(&format!("__inline_mac_{mac_name}"), Span::call_site())
} else {
let mut input = match LookaheadIter::new(input.clone().into_iter()) {
Some(x) => x,
None => return input,
};
loop {
match input.next() {
None => break Ident::new("__inline_mac", Span::call_site()),
Some(TT::Ident(kind)) => match &*kind.to_string() {
"impl" => break Ident::new("__inline_mac_impl", Span::call_site()),
kind @ ("struct" | "enum" | "union" | "fn" | "mod" | "trait" | "type" | "const" | "static") => {
if let TT::Ident(name) = &input.tt {
break Ident::new(&format!("__inline_mac_{kind}_{name}"), Span::call_site());
} else {
break Ident::new(&format!("__inline_mac_{kind}"), Span::call_site());
}
},
_ => {},
},
_ => {},
}
}
};
let mut expander = Expander::default();
let mut mac = MacWriter::new(mac_name);
if let Err(e) = expander.expand(input.into_iter(), &mut mac) {
return e;
}
let mut out = TokenStream::new();
mac.finish(&mut out);
out.extend(expander.expn);
out
}
/// Wraps a `TokenStream` iterator with a single token lookahead.
struct LookaheadIter {
tt: TT,
iter: IntoIter,
}
impl LookaheadIter {
fn new(mut iter: IntoIter) -> Option<Self> {
iter.next().map(|tt| Self { tt, iter })
}
/// Get's the lookahead token, replacing it with the next token in the stream.
/// Note: If there isn't a next token, this will not return the lookahead token.
fn next(&mut self) -> Option<TT> {
self.iter.next().map(|tt| mem::replace(&mut self.tt, tt))
}
}
/// Builds the macro used to implement all the `inline!` macro calls.
struct MacWriter {
name: Ident,
macros: TokenStream,
next_idx: usize,
}
impl MacWriter {
fn new(name: Ident) -> Self {
Self {
name,
macros: TokenStream::new(),
next_idx: 0,
}
}
/// Inserts a new `inline!` call.
fn insert(&mut self, name_span: Span, bang_span: Span, body: Group, expander: &mut Expander) -> Result<()> {
let idx = self.next_idx;
self.next_idx += 1;
let mut inner = Expander::for_arm(idx);
inner.expand(body.stream().into_iter(), self)?;
let new_arm = inner.arm.unwrap();
self.macros.extend([
TT::Group(Group::new(Parenthesis, new_arm.args_def)),
TT::Punct(Punct::new('=', Joint)),
TT::Punct(Punct::new('>', Alone)),
TT::Group(Group::new(Parenthesis, inner.expn)),
TT::Punct(Punct::new(';', Alone)),
]);
expander.expn.extend([
TT::Ident({
let mut name = self.name.clone();
name.set_span(name_span);
name
}),
TT::Punct(punct_with_span('!', Alone, bang_span)),
]);
let mut call_body = TokenStream::from_iter([TT::Literal(Literal::usize_unsuffixed(idx))]);
if let Some(arm) = expander.arm.as_mut() {
if !new_arm.args.is_empty() {
arm.add_sub_args(new_arm.args, &mut call_body);
}
} else {
call_body.extend(new_arm.args);
}
let mut g = Group::new(body.delimiter(), call_body);
g.set_span(body.span());
expander.expn.extend([TT::Group(g)]);
Ok(())
}
/// Creates the macro definition.
fn finish(self, out: &mut TokenStream) {
if self.next_idx != 0 {
out.extend([
TT::Ident(Ident::new("macro_rules", Span::call_site())),
TT::Punct(Punct::new('!', Alone)),
TT::Ident(self.name),
TT::Group(Group::new(Brace, self.macros)),
])
}
}
}
struct MacroArm {
args_def: TokenStream,
args: Vec<TT>,
}
impl MacroArm {
fn add_single_arg_def(&mut self, kind: &str, dollar_span: Span, arg_span: Span, out: &mut TokenStream) {
let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site());
self.args_def.extend([
TT::Punct(Punct::new('$', Alone)),
TT::Ident(name.clone()),
TT::Punct(Punct::new(':', Alone)),
TT::Ident(Ident::new(kind, Span::call_site())),
]);
name.set_span(arg_span);
out.extend([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]);
}
fn add_parenthesized_arg_def(&mut self, kind: Ident, dollar_span: Span, arg_span: Span, out: &mut TokenStream) {
let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site());
self.args_def.extend([TT::Group(Group::new(
Parenthesis,
TokenStream::from_iter([
TT::Punct(Punct::new('$', Alone)),
TT::Ident(name.clone()),
TT::Punct(Punct::new(':', Alone)),
TT::Ident(kind),
]),
))]);
name.set_span(arg_span);
out.extend([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]);
}
fn add_multi_arg_def(&mut self, dollar_span: Span, arg_span: Span, out: &mut TokenStream) {
let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site());
self.args_def.extend([TT::Group(Group::new(
Parenthesis,
TokenStream::from_iter([
TT::Punct(Punct::new('$', Alone)),
TT::Group(Group::new(
Parenthesis,
TokenStream::from_iter([
TT::Punct(Punct::new('$', Alone)),
TT::Ident(name.clone()),
TT::Punct(Punct::new(':', Alone)),
TT::Ident(Ident::new("tt", Span::call_site())),
]),
)),
TT::Punct(Punct::new('*', Alone)),
]),
))]);
name.set_span(arg_span);
out.extend([
TT::Punct(punct_with_span('$', Alone, dollar_span)),
TT::Group(group_with_span(
Parenthesis,
TokenStream::from_iter([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]),
dollar_span,
)),
TT::Punct(punct_with_span('*', Alone, dollar_span)),
]);
}
fn add_arg(&mut self, dollar_span: Span, tt: TT, input: &mut IntoIter, out: &mut TokenStream) -> Result<()> {
match tt {
TT::Punct(p) if p.as_char() == ESCAPE_CHAR => out.extend([TT::Punct(p)]),
TT::Punct(p) if p.as_char() == '\'' && p.spacing() == Joint => {
let lt_name = expect_tt(
input.next(),
|tt| match tt {
TT::Ident(x) => Some(x),
_ => None,
},
"lifetime name",
p.span(),
)?;
let arg_span = p.span().join(lt_name.span()).unwrap_or(p.span());
self.add_single_arg_def("lifetime", dollar_span, arg_span, out);
self.args.extend([TT::Punct(p), TT::Ident(lt_name)]);
},
TT::Ident(x) => {
self.add_single_arg_def("ident", dollar_span, x.span(), out);
self.args.push(TT::Ident(x));
},
TT::Literal(x) => {
self.add_single_arg_def("literal", dollar_span, x.span(), out);
self.args.push(TT::Literal(x));
},
TT::Group(g) if g.delimiter() == Parenthesis => {
let mut inner = g.stream().into_iter();
if let Some(TT::Punct(p)) = inner.next()
&& p.as_char() == '@'
{
let kind = expect_tt(
inner.next(),
|tt| match tt {
TT::Ident(kind) => Some(kind),
_ => None,
},
"a macro fragment specifier",
p.span(),
)?;
self.add_parenthesized_arg_def(kind, dollar_span, g.span(), out);
self.args.push(TT::Group(group_with_span(Parenthesis, inner.collect(), g.span())))
} else {
self.add_multi_arg_def(dollar_span, g.span(), out);
self.args.push(TT::Group(g));
}
},
tt => return Err(make_error("unsupported escape", tt.span())),
};
Ok(())
}
fn add_sub_args(&mut self, args: Vec<TT>, out: &mut TokenStream) {
self.add_multi_arg_def(Span::call_site(), Span::call_site(), out);
self.args
.extend([TT::Group(Group::new(Parenthesis, TokenStream::from_iter(args)))]);
}
}
#[derive(Default)]
struct Expander {
arm: Option<MacroArm>,
expn: TokenStream,
}
impl Expander {
fn for_arm(idx: usize) -> Self {
Self {
arm: Some(MacroArm {
args_def: TokenStream::from_iter([TT::Literal(Literal::usize_unsuffixed(idx))]),
args: Vec::new(),
}),
expn: TokenStream::new(),
}
}
fn write_tt(&mut self, tt: TT, mac: &mut MacWriter) -> Result<()> {
match tt {
TT::Group(g) => {
let outer = mem::take(&mut self.expn);
self.expand(g.stream().into_iter(), mac)?;
let inner = mem::replace(&mut self.expn, outer);
self.expn
.extend([TT::Group(group_with_span(g.delimiter(), inner, g.span()))]);
},
tt => self.expn.extend([tt]),
}
Ok(())
}
fn expand(&mut self, input: IntoIter, mac: &mut MacWriter) -> Result<()> {
let Some(mut input) = LookaheadIter::new(input) else {
return Ok(());
};
while let Some(tt) = input.next() {
if let TT::Punct(p) = &tt
&& p.as_char() == ESCAPE_CHAR
&& let Some(arm) = self.arm.as_mut()
{
arm.add_arg(p.span(), mem::replace(&mut input.tt, tt), &mut input.iter, &mut self.expn)?;
if input.next().is_none() {
return Ok(());
}
} else if let TT::Punct(p) = &input.tt
&& p.as_char() == '!'
&& let TT::Ident(name) = &tt
&& name.to_string() == "inline"
{
let g = expect_tt(
input.iter.next(),
|tt| match tt {
TT::Group(g) => Some(g),
_ => None,
},
"macro arguments",
p.span(),
)?;
mac.insert(name.span(), p.span(), g, self)?;
if input.next().is_none() {
return Ok(());
}
} else {
self.write_tt(tt, mac)?;
}
}
self.write_tt(input.tt, mac)
}
}

View File

@ -1,5 +1,5 @@
// this file solely exists to test constants defined in foreign crates.
// As the most common case is the `http` crate, it replicates `http::HeadewrName`'s structure.
// As the most common case is the `http` crate, it replicates `http::HeaderName`'s structure.
#![allow(clippy::declare_interior_mutable_const)]
#![allow(unused_tuple_struct_fields)]

View File

@ -1,8 +1,8 @@
// aux-build:../../auxiliary/proc_macro_with_span.rs
// aux-build:../../auxiliary/proc_macros.rs
extern crate proc_macro_with_span;
extern crate proc_macros;
use proc_macro_with_span::with_span;
use proc_macros::with_span;
fn main() {
println!(with_span!(""something ""));

View File

@ -1,5 +1,5 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::default_numeric_fallback)]
#![allow(
@ -13,8 +13,8 @@
clippy::let_with_type_underscore
)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::{external, inline_macros};
mod basic_expr {
fn test() {
@ -167,20 +167,17 @@ mod method_calls {
}
mod in_macro {
macro_rules! internal_macro {
() => {
let x = 22.0_f64;
};
}
use super::*;
// Should lint in internal macro.
#[inline_macros]
fn internal() {
internal_macro!();
inline!(let x = 22.0_f64;);
}
// Should NOT lint in external macro.
fn external() {
default_numeric_fallback!();
external!(let x = 22.;);
}
}

View File

@ -1,5 +1,5 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::default_numeric_fallback)]
#![allow(
@ -13,8 +13,8 @@
clippy::let_with_type_underscore
)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::{external, inline_macros};
mod basic_expr {
fn test() {
@ -167,20 +167,17 @@ mod method_calls {
}
mod in_macro {
macro_rules! internal_macro {
() => {
let x = 22.;
};
}
use super::*;
// Should lint in internal macro.
#[inline_macros]
fn internal() {
internal_macro!();
inline!(let x = 22.;);
}
// Should NOT lint in external macro.
fn external() {
default_numeric_fallback!();
external!(let x = 22.;);
}
}

View File

@ -139,15 +139,12 @@ LL | s.generic_arg(1.);
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
--> $DIR/default_numeric_fallback_f64.rs:172:21
--> $DIR/default_numeric_fallback_f64.rs:175:25
|
LL | let x = 22.;
| ^^^ help: consider adding suffix: `22.0_f64`
...
LL | internal_macro!();
| ----------------- in this macro invocation
LL | inline!(let x = 22.;);
| ^^^ help: consider adding suffix: `22.0_f64`
|
= note: this error originates in the macro `internal_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_fn_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 24 previous errors

View File

@ -1,5 +1,5 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![feature(lint_reasons)]
#![warn(clippy::default_numeric_fallback)]
@ -13,8 +13,8 @@
clippy::let_with_type_underscore
)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::{external, inline_macros};
mod basic_expr {
fn test() {
@ -168,20 +168,17 @@ mod method_calls {
}
mod in_macro {
macro_rules! internal_macro {
() => {
let x = 22_i32;
};
}
use super::*;
// Should lint in internal macro.
#[inline_macros]
fn internal() {
internal_macro!();
inline!(let x = 22_i32;);
}
// Should NOT lint in external macro.
fn external() {
default_numeric_fallback!();
external!(let x = 22;);
}
}

View File

@ -1,5 +1,5 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![feature(lint_reasons)]
#![warn(clippy::default_numeric_fallback)]
@ -13,8 +13,8 @@
clippy::let_with_type_underscore
)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::{external, inline_macros};
mod basic_expr {
fn test() {
@ -168,20 +168,17 @@ mod method_calls {
}
mod in_macro {
macro_rules! internal_macro {
() => {
let x = 22;
};
}
use super::*;
// Should lint in internal macro.
#[inline_macros]
fn internal() {
internal_macro!();
inline!(let x = 22;);
}
// Should NOT lint in external macro.
fn external() {
default_numeric_fallback!();
external!(let x = 22;);
}
}

View File

@ -151,15 +151,12 @@ LL | s.generic_arg(1);
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
--> $DIR/default_numeric_fallback_i32.rs:173:21
--> $DIR/default_numeric_fallback_i32.rs:176:25
|
LL | let x = 22;
| ^^ help: consider adding suffix: `22_i32`
...
LL | internal_macro!();
| ----------------- in this macro invocation
LL | inline!(let x = 22;);
| ^^ help: consider adding suffix: `22_i32`
|
= note: this error originates in the macro `internal_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_fn_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 26 previous errors

View File

@ -1,12 +1,12 @@
// run-rustfix
// aux-build: proc_macro_with_span.rs
// aux-build: proc_macros.rs
#![deny(clippy::default_trait_access)]
#![allow(dead_code, unused_imports)]
#![allow(clippy::uninlined_format_args)]
extern crate proc_macro_with_span;
extern crate proc_macros;
use proc_macro_with_span::with_span;
use proc_macros::with_span;
use std::default;
use std::default::Default as D2;
use std::string;

View File

@ -1,12 +1,12 @@
// run-rustfix
// aux-build: proc_macro_with_span.rs
// aux-build: proc_macros.rs
#![deny(clippy::default_trait_access)]
#![allow(dead_code, unused_imports)]
#![allow(clippy::uninlined_format_args)]
extern crate proc_macro_with_span;
extern crate proc_macros;
use proc_macro_with_span::with_span;
use proc_macros::with_span;
use std::default;
use std::default::Default as D2;
use std::string;

View File

@ -1,7 +1,12 @@
// run-rustfix
// aux-build:proc_macros.rs
#![allow(clippy::return_self_not_must_use)]
#![warn(clippy::deref_addrof)]
extern crate proc_macros;
use proc_macros::inline_macros;
fn get_number() -> usize {
10
}
@ -41,28 +46,15 @@ fn main() {
let _ = unsafe { *core::ptr::addr_of!(a) };
}
#[rustfmt::skip]
macro_rules! m {
($visitor: expr) => {
$visitor
};
}
#[rustfmt::skip]
macro_rules! m_mut {
($visitor: expr) => {
$visitor
};
}
#[derive(Copy, Clone)]
pub struct S;
#[inline_macros]
impl S {
pub fn f(&self) -> &Self {
m!(self)
inline!($(@expr self))
}
#[allow(unused_mut)] // mut will be unused, once the macro is fixed
pub fn f_mut(mut self) -> Self {
m_mut!(self)
inline!($(@expr self))
}
}

View File

@ -1,7 +1,12 @@
// run-rustfix
// aux-build:proc_macros.rs
#![allow(clippy::return_self_not_must_use)]
#![warn(clippy::deref_addrof)]
extern crate proc_macros;
use proc_macros::inline_macros;
fn get_number() -> usize {
10
}
@ -41,28 +46,15 @@ fn main() {
let _ = unsafe { *core::ptr::addr_of!(a) };
}
#[rustfmt::skip]
macro_rules! m {
($visitor: expr) => {
*& $visitor
};
}
#[rustfmt::skip]
macro_rules! m_mut {
($visitor: expr) => {
*& mut $visitor
};
}
#[derive(Copy, Clone)]
pub struct S;
#[inline_macros]
impl S {
pub fn f(&self) -> &Self {
m!(self)
inline!(*& $(@expr self))
}
#[allow(unused_mut)] // mut will be unused, once the macro is fixed
pub fn f_mut(mut self) -> Self {
m_mut!(self)
inline!(*&mut $(@expr self))
}
}

View File

@ -1,5 +1,5 @@
error: immediately dereferencing a reference
--> $DIR/deref_addrof.rs:19:13
--> $DIR/deref_addrof.rs:24:13
|
LL | let b = *&a;
| ^^^ help: try this: `a`
@ -7,68 +7,62 @@ LL | let b = *&a;
= note: `-D clippy::deref-addrof` implied by `-D warnings`
error: immediately dereferencing a reference
--> $DIR/deref_addrof.rs:21:13
--> $DIR/deref_addrof.rs:26:13
|
LL | let b = *&get_number();
| ^^^^^^^^^^^^^^ help: try this: `get_number()`
error: immediately dereferencing a reference
--> $DIR/deref_addrof.rs:26:13
--> $DIR/deref_addrof.rs:31:13
|
LL | let b = *&bytes[1..2][0];
| ^^^^^^^^^^^^^^^^ help: try this: `bytes[1..2][0]`
error: immediately dereferencing a reference
--> $DIR/deref_addrof.rs:30:13
--> $DIR/deref_addrof.rs:35:13
|
LL | let b = *&(a);
| ^^^^^ help: try this: `(a)`
error: immediately dereferencing a reference
--> $DIR/deref_addrof.rs:32:13
--> $DIR/deref_addrof.rs:37:13
|
LL | let b = *(&a);
| ^^^^^ help: try this: `a`
error: immediately dereferencing a reference
--> $DIR/deref_addrof.rs:35:13
--> $DIR/deref_addrof.rs:40:13
|
LL | let b = *((&a));
| ^^^^^^^ help: try this: `a`
error: immediately dereferencing a reference
--> $DIR/deref_addrof.rs:37:13
--> $DIR/deref_addrof.rs:42:13
|
LL | let b = *&&a;
| ^^^^ help: try this: `&a`
error: immediately dereferencing a reference
--> $DIR/deref_addrof.rs:39:14
--> $DIR/deref_addrof.rs:44:14
|
LL | let b = **&aref;
| ^^^^^^ help: try this: `aref`
error: immediately dereferencing a reference
--> $DIR/deref_addrof.rs:47:9
--> $DIR/deref_addrof.rs:54:17
|
LL | *& $visitor
| ^^^^^^^^^^^ help: try this: `$visitor`
...
LL | m!(self)
| -------- in this macro invocation
LL | inline!(*& $(@expr self))
| ^^^^^^^^^^^^^^^^ help: try this: `$(@expr self)`
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: immediately dereferencing a reference
--> $DIR/deref_addrof.rs:54:9
--> $DIR/deref_addrof.rs:58:17
|
LL | *& mut $visitor
| ^^^^^^^^^^^^^^^ help: try this: `$visitor`
...
LL | m_mut!(self)
| ------------ in this macro invocation
LL | inline!(*&mut $(@expr self))
| ^^^^^^^^^^^^^^^^^^^ help: try this: `$(@expr self)`
|
= note: this error originates in the macro `m_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 10 previous errors

View File

@ -1,10 +1,13 @@
macro_rules! m {
($($x:tt),*) => { &[$(($x, stringify!(x)),)*] };
}
// aux-build:proc_macros.rs
#[warn(clippy::deref_addrof)]
fn f() -> [(i32, &'static str); 3] {
*m![1, 2, 3] // should be fine
#![warn(clippy::deref_addrof)]
extern crate proc_macros;
#[proc_macros::inline_macros]
fn f() -> i32 {
// should be fine
*inline!(&$1)
}
fn main() {}

View File

@ -1,9 +1,9 @@
// aux-build:doc_unsafe_macros.rs
// aux-build:proc_macros.rs
#![allow(clippy::let_unit_value)]
#[macro_use]
extern crate doc_unsafe_macros;
extern crate proc_macros;
use proc_macros::external;
/// This is not sufficiently documented
pub unsafe fn destroy_the_planet() {
@ -105,7 +105,11 @@ macro_rules! very_unsafe {
very_unsafe!();
// we don't lint code from external macros
undocd_unsafe!();
external! {
pub unsafe fn oy_vey() {
unimplemented!();
}
}
fn main() {
unsafe {

View File

@ -1,9 +1,9 @@
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::empty_loop)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::{external, inline_macros};
fn should_trigger() {
loop {}
@ -16,6 +16,7 @@ fn should_trigger() {
}
}
#[inline_macros]
fn should_not_trigger() {
loop {
panic!("This is fine")
@ -38,14 +39,10 @@ fn should_not_trigger() {
loop {}
// We don't lint loops inside macros
macro_rules! foo {
() => {
loop {}
};
}
inline!(loop {});
// We don't lint external macros
foofoo!()
external!(loop {});
}
fn main() {}

View File

@ -1,11 +1,11 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)]
#![warn(clippy::equatable_if_let)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::{external, inline_macros};
use std::cmp::Ordering;
@ -44,6 +44,7 @@ impl PartialEq for NotStructuralEq {
}
}
#[inline_macros]
fn main() {
let a = 2;
let b = 3;
@ -78,14 +79,9 @@ fn main() {
if Some(g) == Some(NotStructuralEq::A) {}
if matches!(h, NoPartialEqStruct { a: 2, b: false }) {}
macro_rules! m1 {
(x) => {
"abc"
};
}
if "abc" == m1!(x) {
if "abc" == inline!("abc") {
println!("OK");
}
equatable_if_let!(a);
external!({ if let 2 = $a {} });
}

View File

@ -1,11 +1,11 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)]
#![warn(clippy::equatable_if_let)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::{external, inline_macros};
use std::cmp::Ordering;
@ -44,6 +44,7 @@ impl PartialEq for NotStructuralEq {
}
}
#[inline_macros]
fn main() {
let a = 2;
let b = 3;
@ -78,14 +79,9 @@ fn main() {
if let Some(NotStructuralEq::A) = Some(g) {}
if let NoPartialEqStruct { a: 2, b: false } = h {}
macro_rules! m1 {
(x) => {
"abc"
};
}
if let m1!(x) = "abc" {
if let inline!("abc") = "abc" {
println!("OK");
}
equatable_if_let!(a);
external!({ if let 2 = $a {} });
}

View File

@ -1,5 +1,5 @@
error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:59:8
--> $DIR/equatable_if_let.rs:60:8
|
LL | if let 2 = a {}
| ^^^^^^^^^ help: try: `a == 2`
@ -7,82 +7,82 @@ LL | if let 2 = a {}
= note: `-D clippy::equatable-if-let` implied by `-D warnings`
error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:60:8
--> $DIR/equatable_if_let.rs:61:8
|
LL | if let Ordering::Greater = a.cmp(&b) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.cmp(&b) == Ordering::Greater`
error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:61:8
--> $DIR/equatable_if_let.rs:62:8
|
LL | if let Some(2) = c {}
| ^^^^^^^^^^^^^^^ help: try: `c == Some(2)`
error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:62:8
--> $DIR/equatable_if_let.rs:63:8
|
LL | if let Struct { a: 2, b: false } = d {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `d == (Struct { a: 2, b: false })`
error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:63:8
--> $DIR/equatable_if_let.rs:64:8
|
LL | if let Enum::TupleVariant(32, 64) = e {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::TupleVariant(32, 64)`
error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:64:8
--> $DIR/equatable_if_let.rs:65:8
|
LL | if let Enum::RecordVariant { a: 64, b: 32 } = e {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == (Enum::RecordVariant { a: 64, b: 32 })`
error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:65:8
--> $DIR/equatable_if_let.rs:66:8
|
LL | if let Enum::UnitVariant = e {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::UnitVariant`
error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:66:8
--> $DIR/equatable_if_let.rs:67:8
|
LL | if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false })`
error: this pattern matching can be expressed using `matches!`
--> $DIR/equatable_if_let.rs:75:8
--> $DIR/equatable_if_let.rs:76:8
|
LL | if let NotPartialEq::A = f {}
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(f, NotPartialEq::A)`
error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:76:8
--> $DIR/equatable_if_let.rs:77:8
|
LL | if let NotStructuralEq::A = g {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `g == NotStructuralEq::A`
error: this pattern matching can be expressed using `matches!`
--> $DIR/equatable_if_let.rs:77:8
--> $DIR/equatable_if_let.rs:78:8
|
LL | if let Some(NotPartialEq::A) = Some(f) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(f), Some(NotPartialEq::A))`
error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:78:8
--> $DIR/equatable_if_let.rs:79:8
|
LL | if let Some(NotStructuralEq::A) = Some(g) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)`
error: this pattern matching can be expressed using `matches!`
--> $DIR/equatable_if_let.rs:79:8
--> $DIR/equatable_if_let.rs:80:8
|
LL | if let NoPartialEqStruct { a: 2, b: false } = h {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(h, NoPartialEqStruct { a: 2, b: false })`
error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:86:8
--> $DIR/equatable_if_let.rs:82:8
|
LL | if let m1!(x) = "abc" {
| ^^^^^^^^^^^^^^^^^^ help: try: `"abc" == m1!(x)`
LL | if let inline!("abc") = "abc" {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"abc" == inline!("abc")`
error: aborting due to 14 previous errors

View File

@ -1,12 +1,12 @@
// aux-build:proc_macro_derive.rs
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::field_reassign_with_default)]
#[macro_use]
extern crate proc_macro_derive;
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::{external, inline_macros};
// Don't lint on derives that derive `Default`
// See https://github.com/rust-lang/rust-clippy/issues/6545
@ -36,14 +36,6 @@ struct D {
b: Option<i32>,
}
macro_rules! m {
($key:ident: $value:tt) => {{
let mut data = $crate::D::default();
data.$key = Some($value);
data
}};
}
/// Implements .next() that returns a different number each time.
struct SideEffect(i32);
@ -57,6 +49,7 @@ impl SideEffect {
}
}
#[inline_macros]
fn main() {
// wrong, produces first error in stderr
let mut a: A = Default::default();
@ -150,7 +143,18 @@ fn main() {
a.i = vec![1];
// Don't lint in external macros
field_reassign_with_default!();
external! {
#[derive(Default)]
struct A {
pub i: i32,
pub j: i64,
}
fn lint() {
let mut a: A = Default::default();
a.i = 42;
a;
}
}
// be sure suggestion is correct with generics
let mut a: Wrapper<bool> = Default::default();
@ -160,9 +164,11 @@ fn main() {
a.i = 42;
// Don't lint in macros
m! {
a: 42
};
inline!(
let mut data = $crate::D::default();
data.$a = Some($42);
data
);
}
mod m {

View File

@ -1,132 +1,132 @@
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:63:5
--> $DIR/field_reassign_with_default.rs:56:5
|
LL | a.i = 42;
| ^^^^^^^^^
|
note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:62:5
--> $DIR/field_reassign_with_default.rs:55:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: `-D clippy::field-reassign-with-default` implied by `-D warnings`
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:103:5
--> $DIR/field_reassign_with_default.rs:96:5
|
LL | a.j = 43;
| ^^^^^^^^^
|
note: consider initializing the variable with `main::A { j: 43, i: 42 }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:102:5
--> $DIR/field_reassign_with_default.rs:95:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:108:5
--> $DIR/field_reassign_with_default.rs:101:5
|
LL | a.i = 42;
| ^^^^^^^^^
|
note: consider initializing the variable with `main::A { i: 42, j: 44 }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:107:5
--> $DIR/field_reassign_with_default.rs:100:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:114:5
--> $DIR/field_reassign_with_default.rs:107:5
|
LL | a.i = 42;
| ^^^^^^^^^
|
note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:113:5
--> $DIR/field_reassign_with_default.rs:106:5
|
LL | let mut a = A::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:124:5
--> $DIR/field_reassign_with_default.rs:117:5
|
LL | a.i = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: consider initializing the variable with `main::A { i: Default::default(), ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:123:5
--> $DIR/field_reassign_with_default.rs:116:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:128:5
--> $DIR/field_reassign_with_default.rs:121:5
|
LL | a.i = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: consider initializing the variable with `main::A { i: Default::default(), j: 45 }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:127:5
--> $DIR/field_reassign_with_default.rs:120:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:150:5
--> $DIR/field_reassign_with_default.rs:143:5
|
LL | a.i = vec![1];
| ^^^^^^^^^^^^^^
|
note: consider initializing the variable with `C { i: vec![1], ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:149:5
--> $DIR/field_reassign_with_default.rs:142:5
|
LL | let mut a: C = C::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:157:5
--> $DIR/field_reassign_with_default.rs:161:5
|
LL | a.i = true;
| ^^^^^^^^^^^
|
note: consider initializing the variable with `Wrapper::<bool> { i: true }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:156:5
--> $DIR/field_reassign_with_default.rs:160:5
|
LL | let mut a: Wrapper<bool> = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:160:5
--> $DIR/field_reassign_with_default.rs:164:5
|
LL | a.i = 42;
| ^^^^^^^^^
|
note: consider initializing the variable with `WrapperMulti::<i32, i64> { i: 42, ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:159:5
--> $DIR/field_reassign_with_default.rs:163:5
|
LL | let mut a: WrapperMulti<i32, i64> = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:229:13
--> $DIR/field_reassign_with_default.rs:235:13
|
LL | f.name = name.len();
| ^^^^^^^^^^^^^^^^^^^^
|
note: consider initializing the variable with `issue6312::ImplDropAllCopy { name: name.len(), ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:228:13
--> $DIR/field_reassign_with_default.rs:234:13
|
LL | let mut f = ImplDropAllCopy::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:245:13
--> $DIR/field_reassign_with_default.rs:251:13
|
LL | f.name = name.len();
| ^^^^^^^^^^^^^^^^^^^^
|
note: consider initializing the variable with `issue6312::NoDropAllCopy { name: name.len(), ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:244:13
--> $DIR/field_reassign_with_default.rs:250:13
|
LL | let mut f = NoDropAllCopy::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,9 +1,11 @@
// aux-build:implicit_hasher_macros.rs
// aux-build:proc_macros.rs
#![deny(clippy::implicit_hasher)]
#![allow(unused)]
#[macro_use]
extern crate implicit_hasher_macros;
extern crate proc_macros;
use proc_macros::external;
use std::cmp::Eq;
use std::collections::{HashMap, HashSet};
@ -68,22 +70,19 @@ impl<S: BuildHasher + Default> Foo<i64> for HashSet<String, S> {
pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
macro_rules! gen {
(impl) => {
#[proc_macros::inline_macros]
pub mod gen {
use super::*;
inline! {
impl<K: Hash + Eq, V> Foo<u8> for HashMap<K, V> {
fn make() -> (Self, Self) {
(HashMap::new(), HashMap::with_capacity(10))
}
}
};
(fn $name:ident) => {
pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
};
pub fn bar(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
}
}
#[rustfmt::skip]
gen!(impl);
gen!(fn bar);
// When the macro is in a different file, the suggestion spans can't be combined properly
// and should not cause an ICE
@ -94,7 +93,9 @@ pub mod test_macro;
__implicit_hasher_test_macro!(impl<K, V> for HashMap<K, V> where V: test_macro::A);
// #4260
implicit_hasher_fn!();
external! {
pub fn f(input: &HashMap<u32, u32>) {}
}
// #7712
pub async fn election_vote(_data: HashMap<i32, i32>) {}

View File

@ -1,11 +1,11 @@
error: impl for `HashMap` should be generalized over different hashers
--> $DIR/implicit_hasher.rs:16:35
--> $DIR/implicit_hasher.rs:18:35
|
LL | impl<K: Hash + Eq, V> Foo<i8> for HashMap<K, V> {
| ^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/implicit_hasher.rs:2:9
--> $DIR/implicit_hasher.rs:3:9
|
LL | #![deny(clippy::implicit_hasher)]
| ^^^^^^^^^^^^^^^^^^^^^^^
@ -19,7 +19,7 @@ LL | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default:
| ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: impl for `HashMap` should be generalized over different hashers
--> $DIR/implicit_hasher.rs:25:36
--> $DIR/implicit_hasher.rs:27:36
|
LL | impl<K: Hash + Eq, V> Foo<i8> for (HashMap<K, V>,) {
| ^^^^^^^^^^^^^
@ -34,7 +34,7 @@ LL | ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Defa
| ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: impl for `HashMap` should be generalized over different hashers
--> $DIR/implicit_hasher.rs:30:19
--> $DIR/implicit_hasher.rs:32:19
|
LL | impl Foo<i16> for HashMap<String, String> {
| ^^^^^^^^^^^^^^^^^^^^^^^
@ -49,7 +49,7 @@ LL | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default:
| ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: impl for `HashSet` should be generalized over different hashers
--> $DIR/implicit_hasher.rs:47:32
--> $DIR/implicit_hasher.rs:49:32
|
LL | impl<T: Hash + Eq> Foo<i8> for HashSet<T> {
| ^^^^^^^^^^
@ -64,7 +64,7 @@ LL | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default:
| ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: impl for `HashSet` should be generalized over different hashers
--> $DIR/implicit_hasher.rs:52:19
--> $DIR/implicit_hasher.rs:54:19
|
LL | impl Foo<i16> for HashSet<String> {
| ^^^^^^^^^^^^^^^
@ -79,7 +79,7 @@ LL | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default:
| ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: parameter of type `HashMap` should be generalized over different hashers
--> $DIR/implicit_hasher.rs:69:23
--> $DIR/implicit_hasher.rs:71:23
|
LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
| ^^^^^^^^^^^^^^^^^
@ -90,7 +90,7 @@ LL | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32, S>, _s
| +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~~~~~
error: parameter of type `HashSet` should be generalized over different hashers
--> $DIR/implicit_hasher.rs:69:53
--> $DIR/implicit_hasher.rs:71:53
|
LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
| ^^^^^^^^^^^^
@ -101,15 +101,12 @@ LL | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32>, _set:
| +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~
error: impl for `HashMap` should be generalized over different hashers
--> $DIR/implicit_hasher.rs:73:43
--> $DIR/implicit_hasher.rs:77:43
|
LL | impl<K: Hash + Eq, V> Foo<u8> for HashMap<K, V> {
| ^^^^^^^^^^^^^
...
LL | gen!(impl);
| ---------- in this macro invocation
|
= note: this error originates in the macro `gen` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_mod_gen` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider adding a type parameter
|
LL | impl<K: Hash + Eq, V, S: ::std::hash::BuildHasher + Default> Foo<u8> for HashMap<K, V, S> {
@ -120,37 +117,31 @@ LL | (HashMap::default(), HashMap::with_capacity_and_hasher(10,
| ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: parameter of type `HashMap` should be generalized over different hashers
--> $DIR/implicit_hasher.rs:81:33
--> $DIR/implicit_hasher.rs:83:31
|
LL | pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
| ^^^^^^^^^^^^^^^^^
...
LL | gen!(fn bar);
| ------------ in this macro invocation
LL | pub fn bar(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
| ^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `gen` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_mod_gen` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider adding a type parameter
|
LL | pub fn $name<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32, S>, _set: &mut HashSet<i32>) {}
| +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~~~~~
LL | pub fn bar<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32, S>, _set: &mut HashSet<i32>) {}
| +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~~~~~
error: parameter of type `HashSet` should be generalized over different hashers
--> $DIR/implicit_hasher.rs:81:63
--> $DIR/implicit_hasher.rs:83:61
|
LL | pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
| ^^^^^^^^^^^^
...
LL | gen!(fn bar);
| ------------ in this macro invocation
LL | pub fn bar(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
| ^^^^^^^^^^^^
|
= note: this error originates in the macro `gen` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_mod_gen` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider adding a type parameter
|
LL | pub fn $name<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32, S>) {}
| +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~
LL | pub fn bar<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32, S>) {}
| +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~
error: parameter of type `HashMap` should be generalized over different hashers
--> $DIR/implicit_hasher.rs:100:35
--> $DIR/implicit_hasher.rs:101:35
|
LL | pub async fn election_vote(_data: HashMap<i32, i32>) {}
| ^^^^^^^^^^^^^^^^^

View File

@ -1,10 +1,14 @@
// run-rustfix
// aux-build:proc_macros.rs
#![warn(clippy::inconsistent_struct_constructor)]
#![allow(clippy::redundant_field_names)]
#![allow(clippy::unnecessary_operation)]
#![allow(clippy::no_effect)]
#![allow(dead_code)]
extern crate proc_macros;
#[derive(Default)]
struct Foo {
x: i32,
@ -12,18 +16,10 @@ struct Foo {
z: i32,
}
macro_rules! new_foo {
() => {
let x = 1;
let y = 1;
let z = 1;
Foo { y, x, z }
};
}
mod without_base {
use super::Foo;
#[proc_macros::inline_macros]
fn test() {
let x = 1;
let y = 1;
@ -34,7 +30,12 @@ mod without_base {
// Should NOT lint.
// issue #7069.
new_foo!();
inline!({
let x = 1;
let y = 1;
let z = 1;
Foo { y, x, z }
});
// Should NOT lint because the order is the same as in the definition.
Foo { x, y, z };

View File

@ -1,10 +1,14 @@
// run-rustfix
// aux-build:proc_macros.rs
#![warn(clippy::inconsistent_struct_constructor)]
#![allow(clippy::redundant_field_names)]
#![allow(clippy::unnecessary_operation)]
#![allow(clippy::no_effect)]
#![allow(dead_code)]
extern crate proc_macros;
#[derive(Default)]
struct Foo {
x: i32,
@ -12,18 +16,10 @@ struct Foo {
z: i32,
}
macro_rules! new_foo {
() => {
let x = 1;
let y = 1;
let z = 1;
Foo { y, x, z }
};
}
mod without_base {
use super::Foo;
#[proc_macros::inline_macros]
fn test() {
let x = 1;
let y = 1;
@ -34,7 +30,12 @@ mod without_base {
// Should NOT lint.
// issue #7069.
new_foo!();
inline!({
let x = 1;
let y = 1;
let z = 1;
Foo { y, x, z }
});
// Should NOT lint because the order is the same as in the definition.
Foo { x, y, z };

View File

@ -1,5 +1,5 @@
error: struct constructor field order is inconsistent with struct definition field order
--> $DIR/inconsistent_struct_constructor.rs:33:9
--> $DIR/inconsistent_struct_constructor.rs:29:9
|
LL | Foo { y, x, z };
| ^^^^^^^^^^^^^^^ help: try: `Foo { x, y, z }`
@ -7,7 +7,7 @@ LL | Foo { y, x, z };
= note: `-D clippy::inconsistent-struct-constructor` implied by `-D warnings`
error: struct constructor field order is inconsistent with struct definition field order
--> $DIR/inconsistent_struct_constructor.rs:55:9
--> $DIR/inconsistent_struct_constructor.rs:56:9
|
LL | / Foo {
LL | | z,

View File

@ -1,11 +1,11 @@
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![allow(dead_code)]
#![allow(unused_variables)]
#![warn(clippy::large_enum_variant)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::external;
enum LargeEnum {
A(i32),
@ -155,5 +155,10 @@ enum LargeEnumOfConst {
}
fn main() {
large_enum_variant!();
external!(
enum LargeEnumInMacro {
A(i32),
B([i32; 8000]),
}
);
}

View File

@ -20,7 +20,7 @@ mod a {
use mac;
use mini_mac::ClippyMiniMacroTest;
use mini_mac;
use mac::{inner::foofoo, inner::try_err};
use mac::{inner::mut_mut, inner::try_err};
use mac::inner;
use mac::inner::nested::string_add;
use mac::inner::nested;
@ -36,7 +36,7 @@ mod a {
let v: ty_macro!() = Vec::default();
inner::try_err!();
inner::foofoo!();
inner::mut_mut!();
nested::string_add!();
}
}

View File

@ -36,7 +36,7 @@ mod a {
let v: ty_macro!() = Vec::default();
inner::try_err!();
inner::foofoo!();
inner::mut_mut!();
nested::string_add!();
}
}

View File

@ -16,7 +16,7 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition
--> $DIR/macro_use_imports.rs:23:5
|
LL | #[macro_use]
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};`
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::mut_mut, inner::try_err};`
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
--> $DIR/macro_use_imports.rs:19:5

View File

@ -39,7 +39,7 @@ mod a {
let v: ty_macro!() = Vec::default();
inner::try_err!();
inner::foofoo!();
inner::mut_mut!();
nested::string_add!();
}
}

View File

@ -1,19 +1,13 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::manual_rem_euclid)]
#![allow(clippy::let_with_type_underscore)]
#[macro_use]
extern crate macro_rules;
macro_rules! internal_rem_euclid {
() => {
let value: i32 = 5;
let _: i32 = value.rem_euclid(4);
};
}
extern crate proc_macros;
use proc_macros::{external, inline_macros};
#[inline_macros]
fn main() {
let value: i32 = 5;
@ -39,10 +33,16 @@ fn main() {
let _: i32 = ((4 % value) + 4) % 4;
// Lint in internal macros
internal_rem_euclid!();
inline!(
let value: i32 = 5;
let _: i32 = value.rem_euclid(4);
);
// Do not lint in external macros
manual_rem_euclid!();
external!(
let value: i32 = 5;
let _: i32 = ((value % 4) + 4) % 4;
);
}
// Should lint for params too

View File

@ -1,19 +1,13 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::manual_rem_euclid)]
#![allow(clippy::let_with_type_underscore)]
#[macro_use]
extern crate macro_rules;
macro_rules! internal_rem_euclid {
() => {
let value: i32 = 5;
let _: i32 = ((value % 4) + 4) % 4;
};
}
extern crate proc_macros;
use proc_macros::{external, inline_macros};
#[inline_macros]
fn main() {
let value: i32 = 5;
@ -39,10 +33,16 @@ fn main() {
let _: i32 = ((4 % value) + 4) % 4;
// Lint in internal macros
internal_rem_euclid!();
inline!(
let value: i32 = 5;
let _: i32 = ((value % 4) + 4) % 4;
);
// Do not lint in external macros
manual_rem_euclid!();
external!(
let value: i32 = 5;
let _: i32 = ((value % 4) + 4) % 4;
);
}
// Should lint for params too

View File

@ -1,5 +1,5 @@
error: manual `rem_euclid` implementation
--> $DIR/manual_rem_euclid.rs:20:18
--> $DIR/manual_rem_euclid.rs:14:18
|
LL | let _: i32 = ((value % 4) + 4) % 4;
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
@ -7,39 +7,36 @@ LL | let _: i32 = ((value % 4) + 4) % 4;
= note: `-D clippy::manual-rem-euclid` implied by `-D warnings`
error: manual `rem_euclid` implementation
--> $DIR/manual_rem_euclid.rs:21:18
--> $DIR/manual_rem_euclid.rs:15:18
|
LL | let _: i32 = (4 + (value % 4)) % 4;
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
error: manual `rem_euclid` implementation
--> $DIR/manual_rem_euclid.rs:22:18
--> $DIR/manual_rem_euclid.rs:16:18
|
LL | let _: i32 = (value % 4 + 4) % 4;
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
error: manual `rem_euclid` implementation
--> $DIR/manual_rem_euclid.rs:23:18
--> $DIR/manual_rem_euclid.rs:17:18
|
LL | let _: i32 = (4 + value % 4) % 4;
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
error: manual `rem_euclid` implementation
--> $DIR/manual_rem_euclid.rs:24:22
--> $DIR/manual_rem_euclid.rs:18:22
|
LL | let _: i32 = 1 + (4 + value % 4) % 4;
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
error: manual `rem_euclid` implementation
--> $DIR/manual_rem_euclid.rs:13:22
--> $DIR/manual_rem_euclid.rs:38:22
|
LL | let _: i32 = ((value % 4) + 4) % 4;
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
...
LL | internal_rem_euclid!();
| ---------------------- in this macro invocation
|
= note: this error originates in the macro `internal_rem_euclid` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
error: manual `rem_euclid` implementation
--> $DIR/manual_rem_euclid.rs:50:5

View File

@ -1,21 +1,12 @@
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::mem_replace_with_default)]
#[macro_use]
extern crate macro_rules;
macro_rules! take {
($s:expr) => {
std::mem::replace($s, Default::default())
};
}
fn replace_with_default() {
let s = &mut String::from("foo");
take!(s);
take_external!(s);
}
extern crate proc_macros;
use proc_macros::{external, inline_macros};
#[inline_macros]
fn main() {
replace_with_default();
let s = &mut String::from("foo");
inline!(std::mem::replace($s, Default::default()));
external!(std::mem::replace($s, Default::default()));
}

View File

@ -1,14 +1,11 @@
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> $DIR/mem_replace_macro.rs:9:9
--> $DIR/mem_replace_macro.rs:10:13
|
LL | std::mem::replace($s, Default::default())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | take!(s);
| -------- in this macro invocation
LL | inline!(std::mem::replace($s, Default::default()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::mem-replace-with-default` implied by `-D warnings`
= note: this error originates in the macro `take` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -3,15 +3,15 @@
//! The .stderr output of this test should be empty. Otherwise it's a bug somewhere.
// aux-build:helper.rs
// aux-build:../../auxiliary/proc_macro_with_span.rs
// aux-build:../../auxiliary/proc_macros.rs
#![warn(clippy::missing_const_for_fn)]
#![feature(start)]
extern crate helper;
extern crate proc_macro_with_span;
extern crate proc_macros;
use proc_macro_with_span::with_span;
use proc_macros::with_span;
struct Game;

View File

@ -1,5 +1,5 @@
// needs-asm-support
// aux-build: proc_macro_with_span.rs
// aux-build: proc_macros.rs
#![warn(clippy::missing_docs_in_private_items)]
// When denying at the crate level, be sure to not get random warnings from the
@ -8,9 +8,9 @@
//! Some garbage docs for the crate here
#![doc = "More garbage"]
extern crate proc_macro_with_span;
extern crate proc_macros;
use proc_macro_with_span::with_span;
use proc_macros::with_span;
use std::arch::global_asm;
type Typedef = String;

View File

@ -1,4 +1,4 @@
// aux-build: proc_macro_with_span.rs
// aux-build: proc_macros.rs
#![warn(clippy::missing_docs_in_private_items)]
#![allow(dead_code)]
@ -7,8 +7,8 @@
//! Some garbage docs for the crate here
#![doc = "More garbage"]
extern crate proc_macro_with_span;
use proc_macro_with_span::with_span;
extern crate proc_macros;
use proc_macros::with_span;
struct Foo {
a: isize,

View File

@ -1,5 +1,5 @@
// run-rustfix
// aux-build: proc_macro_with_span.rs
// aux-build: proc_macros.rs
#![allow(
dead_code,
@ -10,8 +10,8 @@
clippy::unusual_byte_groupings
)]
extern crate proc_macro_with_span;
use proc_macro_with_span::with_span;
extern crate proc_macros;
use proc_macros::with_span;
fn main() {
let fail14 = 2_i32;

View File

@ -1,5 +1,5 @@
// run-rustfix
// aux-build: proc_macro_with_span.rs
// aux-build: proc_macros.rs
#![allow(
dead_code,
@ -10,8 +10,8 @@
clippy::unusual_byte_groupings
)]
extern crate proc_macro_with_span;
use proc_macro_with_span::with_span;
extern crate proc_macros;
use proc_macros::with_span;
fn main() {
let fail14 = 2_32;

View File

@ -1,12 +1,12 @@
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![allow(unused)]
#![allow(deref_nullptr)]
#![allow(clippy::unnecessary_operation)]
#![allow(clippy::drop_copy)]
#![warn(clippy::multiple_unsafe_ops_per_block)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::external;
use core::arch::asm;
@ -113,7 +113,10 @@ unsafe fn read_char_good(ptr: *const u8) -> char {
// no lint
fn issue10259() {
unsafe_macro!();
external!(unsafe {
*core::ptr::null::<()>();
*core::ptr::null::<()>();
});
}
fn _fn_ptr(x: unsafe fn()) {

View File

@ -126,7 +126,7 @@ LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
| ^^^^^^^^^^^^^^^^^^
error: this `unsafe` block contains 2 unsafe operations, expected only one
--> $DIR/multiple_unsafe_ops_per_block.rs:120:5
--> $DIR/multiple_unsafe_ops_per_block.rs:123:5
|
LL | / unsafe {
LL | | x();
@ -135,18 +135,18 @@ LL | | }
| |_____^
|
note: unsafe function call occurs here
--> $DIR/multiple_unsafe_ops_per_block.rs:121:9
--> $DIR/multiple_unsafe_ops_per_block.rs:124:9
|
LL | x();
| ^^^
note: unsafe function call occurs here
--> $DIR/multiple_unsafe_ops_per_block.rs:122:9
--> $DIR/multiple_unsafe_ops_per_block.rs:125:9
|
LL | x();
| ^^^
error: this `unsafe` block contains 2 unsafe operations, expected only one
--> $DIR/multiple_unsafe_ops_per_block.rs:131:9
--> $DIR/multiple_unsafe_ops_per_block.rs:134:9
|
LL | / unsafe {
LL | | T::X();
@ -155,18 +155,18 @@ LL | | }
| |_________^
|
note: unsafe function call occurs here
--> $DIR/multiple_unsafe_ops_per_block.rs:132:13
--> $DIR/multiple_unsafe_ops_per_block.rs:135:13
|
LL | T::X();
| ^^^^^^
note: unsafe function call occurs here
--> $DIR/multiple_unsafe_ops_per_block.rs:133:13
--> $DIR/multiple_unsafe_ops_per_block.rs:136:13
|
LL | T::X();
| ^^^^^^
error: this `unsafe` block contains 2 unsafe operations, expected only one
--> $DIR/multiple_unsafe_ops_per_block.rs:141:5
--> $DIR/multiple_unsafe_ops_per_block.rs:144:5
|
LL | / unsafe {
LL | | x.0();
@ -175,12 +175,12 @@ LL | | }
| |_____^
|
note: unsafe function call occurs here
--> $DIR/multiple_unsafe_ops_per_block.rs:142:9
--> $DIR/multiple_unsafe_ops_per_block.rs:145:9
|
LL | x.0();
| ^^^^^
note: unsafe function call occurs here
--> $DIR/multiple_unsafe_ops_per_block.rs:143:9
--> $DIR/multiple_unsafe_ops_per_block.rs:146:9
|
LL | x.0();
| ^^^^^

View File

@ -1,11 +1,11 @@
//run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::must_use_unit)]
#![allow(clippy::unused_unit)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::external;
pub fn must_use_default() {}
@ -22,5 +22,8 @@ fn main() {
must_use_with_note();
// We should not lint in external macros
must_use_unit!();
external!(
#[must_use]
fn foo() {}
);
}

View File

@ -1,11 +1,11 @@
//run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::must_use_unit)]
#![allow(clippy::unused_unit)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::external;
#[must_use]
pub fn must_use_default() {}
@ -22,5 +22,8 @@ fn main() {
must_use_with_note();
// We should not lint in external macros
must_use_unit!();
external!(
#[must_use]
fn foo() {}
);
}

View File

@ -1,10 +1,10 @@
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::mut_mut)]
#![allow(unused)]
#![allow(clippy::no_effect, clippy::uninlined_format_args, clippy::unnecessary_operation)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::{external, inline_macros};
fn fun(x: &mut &mut u32) -> bool {
**x > 0
@ -21,6 +21,7 @@ macro_rules! mut_ptr {
}
#[allow(unused_mut, unused_variables)]
#[inline_macros]
fn main() {
let mut x = &mut &mut 1u32;
{
@ -37,7 +38,7 @@ fn main() {
***y + **x;
}
let mut z = mut_ptr!(&mut 3u32);
let mut z = inline!(&mut $(&mut 3u32));
}
fn issue939() {
@ -55,7 +56,7 @@ fn issue939() {
fn issue6922() {
// do not lint from an external macro
mut_mut!();
external!(let mut_mut_ty: &mut &mut u32 = &mut &mut 1u32;);
}
mod issue9035 {

View File

@ -7,54 +7,51 @@ LL | fn fun(x: &mut &mut u32) -> bool {
= note: `-D clippy::mut-mut` implied by `-D warnings`
error: generally you want to avoid `&mut &mut _` if possible
--> $DIR/mut_mut.rs:25:17
--> $DIR/mut_mut.rs:26:17
|
LL | let mut x = &mut &mut 1u32;
| ^^^^^^^^^^^^^^
error: generally you want to avoid `&mut &mut _` if possible
--> $DIR/mut_mut.rs:19:9
--> $DIR/mut_mut.rs:41:25
|
LL | &mut $p
| ^^^^^^^
...
LL | let mut z = mut_ptr!(&mut 3u32);
| ------------------- in this macro invocation
LL | let mut z = inline!(&mut $(&mut 3u32));
| ^
|
= note: this error originates in the macro `mut_ptr` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
error: this expression mutably borrows a mutable reference. Consider reborrowing
--> $DIR/mut_mut.rs:27:21
--> $DIR/mut_mut.rs:28:21
|
LL | let mut y = &mut x;
| ^^^^^^
error: generally you want to avoid `&mut &mut _` if possible
--> $DIR/mut_mut.rs:31:32
--> $DIR/mut_mut.rs:32:32
|
LL | let y: &mut &mut u32 = &mut &mut 2;
| ^^^^^^^^^^^
error: generally you want to avoid `&mut &mut _` if possible
--> $DIR/mut_mut.rs:31:16
--> $DIR/mut_mut.rs:32:16
|
LL | let y: &mut &mut u32 = &mut &mut 2;
| ^^^^^^^^^^^^^
error: generally you want to avoid `&mut &mut _` if possible
--> $DIR/mut_mut.rs:36:37
--> $DIR/mut_mut.rs:37:37
|
LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2;
| ^^^^^^^^^^^^^^^^
error: generally you want to avoid `&mut &mut _` if possible
--> $DIR/mut_mut.rs:36:16
--> $DIR/mut_mut.rs:37:16
|
LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2;
| ^^^^^^^^^^^^^^^^^^
error: generally you want to avoid `&mut &mut _` if possible
--> $DIR/mut_mut.rs:36:21
--> $DIR/mut_mut.rs:37:21
|
LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2;
| ^^^^^^^^^^^^^

View File

@ -1,4 +1,5 @@
// run-rustfix
// aux-build:proc_macros.rs
#![feature(let_chains)]
#![allow(unused)]
#![allow(
@ -10,6 +11,8 @@
clippy::uninlined_format_args
)]
extern crate proc_macros;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::rc::Rc;
@ -138,6 +141,7 @@ const fn in_const() -> &'static str {
a
}
#[proc_macros::inline_macros]
fn does_not_lint() {
let z;
if false {
@ -195,35 +199,27 @@ fn does_not_lint() {
}
y = 3;
macro_rules! assign {
($i:ident) => {
$i = 1;
};
}
let x;
assign!(x);
inline!($x = 1;);
let x;
if true {
assign!(x);
inline!($x = 1;);
} else {
x = 2;
}
macro_rules! in_macro {
() => {
let x;
x = 1;
inline!({
let x;
x = 1;
let x;
if true {
x = 1;
} else {
x = 2;
}
};
}
in_macro!();
let x;
if true {
x = 1;
} else {
x = 2;
}
});
// ignore if-lets - https://github.com/rust-lang/rust-clippy/issues/8613
let x;

View File

@ -1,4 +1,5 @@
// run-rustfix
// aux-build:proc_macros.rs
#![feature(let_chains)]
#![allow(unused)]
#![allow(
@ -10,6 +11,8 @@
clippy::uninlined_format_args
)]
extern crate proc_macros;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::rc::Rc;
@ -138,6 +141,7 @@ const fn in_const() -> &'static str {
a
}
#[proc_macros::inline_macros]
fn does_not_lint() {
let z;
if false {
@ -195,35 +199,27 @@ fn does_not_lint() {
}
y = 3;
macro_rules! assign {
($i:ident) => {
$i = 1;
};
}
let x;
assign!(x);
inline!($x = 1;);
let x;
if true {
assign!(x);
inline!($x = 1;);
} else {
x = 2;
}
macro_rules! in_macro {
() => {
let x;
x = 1;
inline!({
let x;
x = 1;
let x;
if true {
x = 1;
} else {
x = 2;
}
};
}
in_macro!();
let x;
if true {
x = 1;
} else {
x = 2;
}
});
// ignore if-lets - https://github.com/rust-lang/rust-clippy/issues/8613
let x;

View File

@ -1,5 +1,5 @@
error: unneeded late initialization
--> $DIR/needless_late_init.rs:24:5
--> $DIR/needless_late_init.rs:27:5
|
LL | let a;
| ^^^^^^ created here
@ -13,7 +13,7 @@ LL | let a = "zero";
| ~~~~~
error: unneeded late initialization
--> $DIR/needless_late_init.rs:27:5
--> $DIR/needless_late_init.rs:30:5
|
LL | let b;
| ^^^^^^ created here
@ -27,7 +27,7 @@ LL | let b = 1;
| ~~~~~
error: unneeded late initialization
--> $DIR/needless_late_init.rs:28:5
--> $DIR/needless_late_init.rs:31:5
|
LL | let c;
| ^^^^^^ created here
@ -41,7 +41,7 @@ LL | let c = 2;
| ~~~~~
error: unneeded late initialization
--> $DIR/needless_late_init.rs:32:5
--> $DIR/needless_late_init.rs:35:5
|
LL | let d: usize;
| ^^^^^^^^^^^^^ created here
@ -54,7 +54,7 @@ LL | let d: usize = 1;
| ~~~~~~~~~~~~
error: unneeded late initialization
--> $DIR/needless_late_init.rs:35:5
--> $DIR/needless_late_init.rs:38:5
|
LL | let e;
| ^^^^^^ created here
@ -67,7 +67,7 @@ LL | let e = format!("{}", d);
| ~~~~~
error: unneeded late initialization
--> $DIR/needless_late_init.rs:40:5
--> $DIR/needless_late_init.rs:43:5
|
LL | let a;
| ^^^^^^
@ -88,7 +88,7 @@ LL | };
| +
error: unneeded late initialization
--> $DIR/needless_late_init.rs:49:5
--> $DIR/needless_late_init.rs:52:5
|
LL | let b;
| ^^^^^^
@ -109,7 +109,7 @@ LL | };
| +
error: unneeded late initialization
--> $DIR/needless_late_init.rs:56:5
--> $DIR/needless_late_init.rs:59:5
|
LL | let d;
| ^^^^^^
@ -130,7 +130,7 @@ LL | };
| +
error: unneeded late initialization
--> $DIR/needless_late_init.rs:64:5
--> $DIR/needless_late_init.rs:67:5
|
LL | let e;
| ^^^^^^
@ -151,7 +151,7 @@ LL | };
| +
error: unneeded late initialization
--> $DIR/needless_late_init.rs:71:5
--> $DIR/needless_late_init.rs:74:5
|
LL | let f;
| ^^^^^^
@ -167,7 +167,7 @@ LL + 1 => "three",
|
error: unneeded late initialization
--> $DIR/needless_late_init.rs:77:5
--> $DIR/needless_late_init.rs:80:5
|
LL | let g: usize;
| ^^^^^^^^^^^^^
@ -187,7 +187,7 @@ LL | };
| +
error: unneeded late initialization
--> $DIR/needless_late_init.rs:85:5
--> $DIR/needless_late_init.rs:88:5
|
LL | let x;
| ^^^^^^ created here
@ -201,7 +201,7 @@ LL | let x = 1;
| ~~~~~
error: unneeded late initialization
--> $DIR/needless_late_init.rs:89:5
--> $DIR/needless_late_init.rs:92:5
|
LL | let x;
| ^^^^^^ created here
@ -215,7 +215,7 @@ LL | let x = SignificantDrop;
| ~~~~~
error: unneeded late initialization
--> $DIR/needless_late_init.rs:93:5
--> $DIR/needless_late_init.rs:96:5
|
LL | let x;
| ^^^^^^ created here
@ -229,7 +229,7 @@ LL | let x = SignificantDrop;
| ~~~~~
error: unneeded late initialization
--> $DIR/needless_late_init.rs:112:5
--> $DIR/needless_late_init.rs:115:5
|
LL | let a;
| ^^^^^^
@ -250,7 +250,7 @@ LL | };
| +
error: unneeded late initialization
--> $DIR/needless_late_init.rs:129:5
--> $DIR/needless_late_init.rs:132:5
|
LL | let a;
| ^^^^^^

View File

@ -1,5 +1,5 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::needless_lifetimes)]
#![allow(
@ -12,8 +12,8 @@
clippy::get_first
)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::inline_macros;
fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {}
@ -502,30 +502,29 @@ mod pr_9743_output_lifetime_checks {
}
}
#[inline_macros]
mod in_macro {
macro_rules! local_one_input_macro {
() => {
fn one_input(x: &u8) -> &u8 {
unimplemented!()
}
};
}
use proc_macros::external;
// lint local macro expands to function with needless lifetimes
local_one_input_macro!();
// no lint on external macro
macro_rules::needless_lifetime!();
macro_rules! expanded_lifetime {
($l:lifetime) => {
fn f<$l>(arg: &$l str) -> &$l str {
arg
}
inline! {
fn one_input(x: &u8) -> &u8 {
unimplemented!()
}
}
expanded_lifetime!('a);
// no lint on external macro
external! {
fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 {
unimplemented!()
}
}
inline! {
fn f<$'a>(arg: &$'a str) -> &$'a str {
arg
}
}
}
mod issue5787 {

View File

@ -1,5 +1,5 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::needless_lifetimes)]
#![allow(
@ -12,8 +12,8 @@
clippy::get_first
)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::inline_macros;
fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
@ -502,30 +502,29 @@ mod pr_9743_output_lifetime_checks {
}
}
#[inline_macros]
mod in_macro {
macro_rules! local_one_input_macro {
() => {
fn one_input<'a>(x: &'a u8) -> &'a u8 {
unimplemented!()
}
};
}
use proc_macros::external;
// lint local macro expands to function with needless lifetimes
local_one_input_macro!();
// no lint on external macro
macro_rules::needless_lifetime!();
macro_rules! expanded_lifetime {
($l:lifetime) => {
fn f<$l>(arg: &$l str) -> &$l str {
arg
}
inline! {
fn one_input<'a>(x: &'a u8) -> &'a u8 {
unimplemented!()
}
}
expanded_lifetime!('a);
// no lint on external macro
external! {
fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 {
unimplemented!()
}
}
inline! {
fn f<$'a>(arg: &$'a str) -> &$'a str {
arg
}
}
}
mod issue5787 {

View File

@ -540,19 +540,16 @@ LL + fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8)
|
error: the following explicit lifetimes could be elided: 'a
--> $DIR/needless_lifetimes.rs:508:13
--> $DIR/needless_lifetimes.rs:511:9
|
LL | fn one_input<'a>(x: &'a u8) -> &'a u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | local_one_input_macro!();
| ------------------------ in this macro invocation
LL | fn one_input<'a>(x: &'a u8) -> &'a u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `local_one_input_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_mod_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
help: elide the lifetimes
|
LL - fn one_input<'a>(x: &'a u8) -> &'a u8 {
LL + fn one_input(x: &u8) -> &u8 {
LL - fn one_input<'a>(x: &'a u8) -> &'a u8 {
LL + fn one_input(x: &u8) -> &u8 {
|
error: aborting due to 46 previous errors

View File

@ -1,24 +1,16 @@
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::option_env_unwrap)]
#![allow(clippy::map_flatten)]
#[macro_use]
extern crate macro_rules;
macro_rules! option_env_unwrap {
($env: expr) => {
option_env!($env).unwrap()
};
($env: expr, $message: expr) => {
option_env!($env).expect($message)
};
}
extern crate proc_macros;
use proc_macros::{external, inline_macros};
#[inline_macros]
fn main() {
let _ = option_env!("PATH").unwrap();
let _ = option_env!("PATH").expect("environment variable PATH isn't set");
let _ = option_env_unwrap!("PATH");
let _ = option_env_unwrap!("PATH", "environment variable PATH isn't set");
let _ = option_env_unwrap_external!("PATH");
let _ = option_env_unwrap_external!("PATH", "environment variable PATH isn't set");
let _ = inline!(option_env!($"PATH").unwrap());
let _ = inline!(option_env!($"PATH").expect($"environment variable PATH isn't set"));
let _ = external!(option_env!($"PATH").unwrap());
let _ = external!(option_env!($"PATH").expect($"environment variable PATH isn't set"));
}

View File

@ -1,5 +1,5 @@
error: this will panic at run-time if the environment variable doesn't exist at compile-time
--> $DIR/option_env_unwrap.rs:18:13
--> $DIR/option_env_unwrap.rs:10:13
|
LL | let _ = option_env!("PATH").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -8,7 +8,7 @@ LL | let _ = option_env!("PATH").unwrap();
= note: `-D clippy::option-env-unwrap` implied by `-D warnings`
error: this will panic at run-time if the environment variable doesn't exist at compile-time
--> $DIR/option_env_unwrap.rs:19:13
--> $DIR/option_env_unwrap.rs:11:13
|
LL | let _ = option_env!("PATH").expect("environment variable PATH isn't set");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -16,46 +16,40 @@ LL | let _ = option_env!("PATH").expect("environment variable PATH isn't set
= help: consider using the `env!` macro instead
error: this will panic at run-time if the environment variable doesn't exist at compile-time
--> $DIR/option_env_unwrap.rs:10:9
--> $DIR/option_env_unwrap.rs:12:21
|
LL | option_env!($env).unwrap()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | let _ = option_env_unwrap!("PATH");
| -------------------------- in this macro invocation
LL | let _ = inline!(option_env!($"PATH").unwrap());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider using the `env!` macro instead
= note: this error originates in the macro `option_env_unwrap` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
error: this will panic at run-time if the environment variable doesn't exist at compile-time
--> $DIR/option_env_unwrap.rs:13:9
--> $DIR/option_env_unwrap.rs:13:21
|
LL | option_env!($env).expect($message)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | let _ = option_env_unwrap!("PATH", "environment variable PATH isn't set");
| ----------------------------------------------------------------- in this macro invocation
LL | let _ = inline!(option_env!($"PATH").expect($"environment variable PATH isn't set"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider using the `env!` macro instead
= note: this error originates in the macro `option_env_unwrap` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
error: this will panic at run-time if the environment variable doesn't exist at compile-time
--> $DIR/option_env_unwrap.rs:22:13
--> $DIR/option_env_unwrap.rs:14:13
|
LL | let _ = option_env_unwrap_external!("PATH");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | let _ = external!(option_env!($"PATH").unwrap());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider using the `env!` macro instead
= note: this error originates in the macro `option_env_unwrap_external` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `external` (in Nightly builds, run with -Z macro-backtrace for more info)
error: this will panic at run-time if the environment variable doesn't exist at compile-time
--> $DIR/option_env_unwrap.rs:23:13
--> $DIR/option_env_unwrap.rs:15:13
|
LL | let _ = option_env_unwrap_external!("PATH", "environment variable PATH isn't set");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | let _ = external!(option_env!($"PATH").expect($"environment variable PATH isn't set"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider using the `env!` macro instead
= note: this error originates in the macro `option_env_unwrap_external` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `external` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 6 previous errors

View File

@ -1,16 +1,12 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::ptr_as_ptr)]
extern crate macro_rules;
macro_rules! cast_it {
($ptr: ident) => {
$ptr.cast::<i32>()
};
}
extern crate proc_macros;
use proc_macros::{external, inline_macros};
#[inline_macros]
fn main() {
let ptr: *const u32 = &42_u32;
let mut_ptr: *mut u32 = &mut 42_u32;
@ -38,10 +34,10 @@ fn main() {
let _: *mut i32 = mut_ptr.cast();
// Make sure the lint is triggered inside a macro
let _ = cast_it!(ptr);
let _ = inline!($ptr.cast::<i32>());
// Do not lint inside macros from external crates
let _ = macro_rules::ptr_as_ptr_cast!(ptr);
let _ = external!($ptr as *const i32);
}
#[clippy::msrv = "1.37"]

View File

@ -1,16 +1,12 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::ptr_as_ptr)]
extern crate macro_rules;
macro_rules! cast_it {
($ptr: ident) => {
$ptr as *const i32
};
}
extern crate proc_macros;
use proc_macros::{external, inline_macros};
#[inline_macros]
fn main() {
let ptr: *const u32 = &42_u32;
let mut_ptr: *mut u32 = &mut 42_u32;
@ -38,10 +34,10 @@ fn main() {
let _: *mut i32 = mut_ptr as _;
// Make sure the lint is triggered inside a macro
let _ = cast_it!(ptr);
let _ = inline!($ptr as *const i32);
// Do not lint inside macros from external crates
let _ = macro_rules::ptr_as_ptr_cast!(ptr);
let _ = external!($ptr as *const i32);
}
#[clippy::msrv = "1.37"]

View File

@ -1,5 +1,5 @@
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:18:13
--> $DIR/ptr_as_ptr.rs:14:13
|
LL | let _ = ptr as *const i32;
| ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
@ -7,48 +7,45 @@ LL | let _ = ptr as *const i32;
= note: `-D clippy::ptr-as-ptr` implied by `-D warnings`
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:19:13
--> $DIR/ptr_as_ptr.rs:15:13
|
LL | let _ = mut_ptr as *mut i32;
| ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:24:17
--> $DIR/ptr_as_ptr.rs:20:17
|
LL | let _ = *ptr_ptr as *const i32;
| ^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `(*ptr_ptr).cast::<i32>()`
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:37:25
--> $DIR/ptr_as_ptr.rs:33:25
|
LL | let _: *const i32 = ptr as *const _;
| ^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast()`
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:38:23
--> $DIR/ptr_as_ptr.rs:34:23
|
LL | let _: *mut i32 = mut_ptr as _;
| ^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast()`
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:10:9
--> $DIR/ptr_as_ptr.rs:37:21
|
LL | $ptr as *const i32
| ^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `$ptr.cast::<i32>()`
...
LL | let _ = cast_it!(ptr);
| ------------- in this macro invocation
LL | let _ = inline!($ptr as *const i32);
| ^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `$ptr.cast::<i32>()`
|
= note: this error originates in the macro `cast_it` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:62:13
--> $DIR/ptr_as_ptr.rs:58:13
|
LL | let _ = ptr as *const i32;
| ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:63:13
--> $DIR/ptr_as_ptr.rs:59:13
|
LL | let _ = mut_ptr as *mut i32;
| ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`

View File

@ -1,9 +1,9 @@
// aux-build: proc_macro_with_span.rs
// aux-build: proc_macros.rs
#![warn(clippy::single_match_else)]
#![allow(clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
extern crate proc_macro_with_span;
use proc_macro_with_span::with_span;
extern crate proc_macros;
use proc_macros::with_span;
enum ExprNode {
ExprAddrOf,

View File

@ -1,7 +1,7 @@
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::external;
#[warn(clippy::string_add)]
#[allow(clippy::string_add_assign, unused)]
@ -22,5 +22,8 @@ fn main() {
x = x + 1;
assert_eq!(2, x);
string_add!();
external!({
let y = "".to_owned();
let z = y + "...";
});
}

View File

@ -1,17 +1,12 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::toplevel_ref_arg)]
#![allow(clippy::uninlined_format_args)]
#![allow(clippy::uninlined_format_args, unused)]
#[macro_use]
extern crate macro_rules;
macro_rules! gen_binding {
() => {
let _y = &42;
};
}
extern crate proc_macros;
use proc_macros::{external, inline_macros};
#[inline_macros]
fn main() {
// Closures should not warn
let y = |ref x| println!("{:?}", x);
@ -38,13 +33,8 @@ fn main() {
for ref _x in 0..10 {}
// lint in macro
#[allow(unused)]
{
gen_binding!();
}
inline!(let _y = &42;);
// do not lint in external macro
{
ref_arg_binding!();
}
external!(let ref _y = 42;);
}

View File

@ -1,17 +1,12 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::toplevel_ref_arg)]
#![allow(clippy::uninlined_format_args)]
#![allow(clippy::uninlined_format_args, unused)]
#[macro_use]
extern crate macro_rules;
macro_rules! gen_binding {
() => {
let ref _y = 42;
};
}
extern crate proc_macros;
use proc_macros::{external, inline_macros};
#[inline_macros]
fn main() {
// Closures should not warn
let y = |ref x| println!("{:?}", x);
@ -38,13 +33,8 @@ fn main() {
for ref _x in 0..10 {}
// lint in macro
#[allow(unused)]
{
gen_binding!();
}
inline!(let ref _y = 42;);
// do not lint in external macro
{
ref_arg_binding!();
}
external!(let ref _y = 42;);
}

View File

@ -1,5 +1,5 @@
error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
--> $DIR/toplevel_ref_arg.rs:20:9
--> $DIR/toplevel_ref_arg.rs:15:9
|
LL | let ref _x = 1;
| ----^^^^^^----- help: try: `let _x = &1;`
@ -7,39 +7,36 @@ LL | let ref _x = 1;
= note: `-D clippy::toplevel-ref-arg` implied by `-D warnings`
error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
--> $DIR/toplevel_ref_arg.rs:22:9
--> $DIR/toplevel_ref_arg.rs:17:9
|
LL | let ref _y: (&_, u8) = (&1, 2);
| ----^^^^^^--------------------- help: try: `let _y: &(&_, u8) = &(&1, 2);`
error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
--> $DIR/toplevel_ref_arg.rs:24:9
--> $DIR/toplevel_ref_arg.rs:19:9
|
LL | let ref _z = 1 + 2;
| ----^^^^^^--------- help: try: `let _z = &(1 + 2);`
error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
--> $DIR/toplevel_ref_arg.rs:26:9
--> $DIR/toplevel_ref_arg.rs:21:9
|
LL | let ref mut _z = 1 + 2;
| ----^^^^^^^^^^--------- help: try: `let _z = &mut (1 + 2);`
error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
--> $DIR/toplevel_ref_arg.rs:31:9
--> $DIR/toplevel_ref_arg.rs:26:9
|
LL | let ref _x = vec![1, 2, 3];
| ----^^^^^^----------------- help: try: `let _x = &vec![1, 2, 3];`
error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
--> $DIR/toplevel_ref_arg.rs:11:13
--> $DIR/toplevel_ref_arg.rs:36:17
|
LL | let ref _y = 42;
| ----^^^^^^------ help: try: `let _y = &42;`
...
LL | gen_binding!();
| -------------- in this macro invocation
LL | inline!(let ref _y = 42;);
| ----^^^^^^------ help: try: `let _y = &42;`
|
= note: this error originates in the macro `gen_binding` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 6 previous errors

View File

@ -1,33 +1,27 @@
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![warn(clippy::toplevel_ref_arg)]
#![allow(unused)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::{external, inline_macros};
fn the_answer(ref mut x: u8) {
*x = 42;
}
macro_rules! gen_function {
() => {
fn fun_example(ref _x: usize) {}
};
}
#[inline_macros]
fn main() {
let mut x = 0;
the_answer(x);
// lint in macro
#[allow(unused)]
{
gen_function!();
inline! {
fn fun_example(ref _x: usize) {}
}
// do not lint in external macro
{
ref_arg_function!();
external! {
fn fun_example2(ref _x: usize) {}
}
}

View File

@ -7,15 +7,12 @@ LL | fn the_answer(ref mut x: u8) {
= note: `-D clippy::toplevel-ref-arg` implied by `-D warnings`
error: `ref` directly on a function argument is ignored. Consider using a reference type instead
--> $DIR/toplevel_ref_arg_non_rustfix.rs:15:24
--> $DIR/toplevel_ref_arg_non_rustfix.rs:20:24
|
LL | fn fun_example(ref _x: usize) {}
| ^^^^^^
...
LL | gen_function!();
| --------------- in this macro invocation
|
= note: this error originates in the macro `gen_function` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors

View File

@ -1,11 +1,11 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![deny(clippy::try_err)]
#![allow(clippy::unnecessary_wraps, clippy::needless_question_mark)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::{external, inline_macros};
use std::io;
use std::task::Poll;
@ -79,36 +79,22 @@ fn nested_error() -> Result<i32, i32> {
Ok(1)
}
// Bad suggestion when in macro (see #6242)
macro_rules! try_validation {
($e: expr) => {{
match $e {
#[inline_macros]
fn calling_macro() -> Result<i32, i32> {
// macro
inline!(
match $(Ok::<_, i32>(5)) {
Ok(_) => 0,
Err(_) => return Err(1),
}
}};
}
macro_rules! ret_one {
() => {
1
};
}
macro_rules! try_validation_in_macro {
($e: expr) => {{
match $e {
Ok(_) => 0,
Err(_) => return Err(ret_one!()),
}
}};
}
fn calling_macro() -> Result<i32, i32> {
// macro
try_validation!(Ok::<_, i32>(5));
);
// `Err` arg is another macro
try_validation_in_macro!(Ok::<_, i32>(5));
inline!(
match $(Ok::<_, i32>(5)) {
Ok(_) => 0,
Err(_) => return Err(inline!(1)),
}
);
Ok(5)
}
@ -121,24 +107,19 @@ fn main() {
calling_macro().unwrap();
// We don't want to lint in external macros
try_err!();
}
macro_rules! bar {
() => {
String::from("aasdfasdfasdfa")
};
}
macro_rules! foo {
() => {
bar!()
};
external! {
pub fn try_err_fn() -> Result<i32, i32> {
let err: i32 = 1;
// To avoid warnings during rustfix
if true { Err(err)? } else { Ok(2) }
}
}
}
#[inline_macros]
pub fn macro_inside(fail: bool) -> Result<i32, String> {
if fail {
return Err(foo!());
return Err(inline!(inline!(String::from("aasdfasdfasdfa"))));
}
Ok(0)
}

View File

@ -1,11 +1,11 @@
// run-rustfix
// aux-build:macro_rules.rs
// aux-build:proc_macros.rs
#![deny(clippy::try_err)]
#![allow(clippy::unnecessary_wraps, clippy::needless_question_mark)]
#[macro_use]
extern crate macro_rules;
extern crate proc_macros;
use proc_macros::{external, inline_macros};
use std::io;
use std::task::Poll;
@ -79,36 +79,22 @@ fn nested_error() -> Result<i32, i32> {
Ok(1)
}
// Bad suggestion when in macro (see #6242)
macro_rules! try_validation {
($e: expr) => {{
match $e {
#[inline_macros]
fn calling_macro() -> Result<i32, i32> {
// macro
inline!(
match $(Ok::<_, i32>(5)) {
Ok(_) => 0,
Err(_) => Err(1)?,
}
}};
}
macro_rules! ret_one {
() => {
1
};
}
macro_rules! try_validation_in_macro {
($e: expr) => {{
match $e {
Ok(_) => 0,
Err(_) => Err(ret_one!())?,
}
}};
}
fn calling_macro() -> Result<i32, i32> {
// macro
try_validation!(Ok::<_, i32>(5));
);
// `Err` arg is another macro
try_validation_in_macro!(Ok::<_, i32>(5));
inline!(
match $(Ok::<_, i32>(5)) {
Ok(_) => 0,
Err(_) => Err(inline!(1))?,
}
);
Ok(5)
}
@ -121,24 +107,19 @@ fn main() {
calling_macro().unwrap();
// We don't want to lint in external macros
try_err!();
}
macro_rules! bar {
() => {
String::from("aasdfasdfasdfa")
};
}
macro_rules! foo {
() => {
bar!()
};
external! {
pub fn try_err_fn() -> Result<i32, i32> {
let err: i32 = 1;
// To avoid warnings during rustfix
if true { Err(err)? } else { Ok(2) }
}
}
}
#[inline_macros]
pub fn macro_inside(fail: bool) -> Result<i32, String> {
if fail {
Err(foo!())?;
Err(inline!(inline!(String::from("aasdfasdfasdfa"))))?;
}
Ok(0)
}

View File

@ -29,53 +29,47 @@ LL | Err(err)?;
| ^^^^^^^^^ help: try this: `return Err(err.into())`
error: returning an `Err(_)` with the `?` operator
--> $DIR/try_err.rs:87:23
--> $DIR/try_err.rs:88:23
|
LL | Err(_) => Err(1)?,
| ^^^^^^^ help: try this: `return Err(1)`
...
LL | try_validation!(Ok::<_, i32>(5));
| -------------------------------- in this macro invocation
|
= note: this error originates in the macro `try_validation` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_fn_calling_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
error: returning an `Err(_)` with the `?` operator
--> $DIR/try_err.rs:102:23
--> $DIR/try_err.rs:95:23
|
LL | Err(_) => Err(ret_one!())?,
| ^^^^^^^^^^^^^^^^ help: try this: `return Err(ret_one!())`
...
LL | try_validation_in_macro!(Ok::<_, i32>(5));
| ----------------------------------------- in this macro invocation
LL | Err(_) => Err(inline!(1))?,
| ^^^^^^^^^^^^^^^^ help: try this: `return Err(inline!(1))`
|
= note: this error originates in the macro `try_validation_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `__inline_mac_fn_calling_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
error: returning an `Err(_)` with the `?` operator
--> $DIR/try_err.rs:141:9
--> $DIR/try_err.rs:122:9
|
LL | Err(foo!())?;
| ^^^^^^^^^^^^ help: try this: `return Err(foo!())`
LL | Err(inline!(inline!(String::from("aasdfasdfasdfa"))))?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Err(inline!(inline!(String::from("aasdfasdfasdfa"))))`
error: returning an `Err(_)` with the `?` operator
--> $DIR/try_err.rs:148:9
--> $DIR/try_err.rs:129:9
|
LL | Err(io::ErrorKind::WriteZero)?
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Err(io::ErrorKind::WriteZero.into()))`
error: returning an `Err(_)` with the `?` operator
--> $DIR/try_err.rs:150:9
--> $DIR/try_err.rs:131:9
|
LL | Err(io::Error::new(io::ErrorKind::InvalidInput, "error"))?
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "error")))`
error: returning an `Err(_)` with the `?` operator
--> $DIR/try_err.rs:158:9
--> $DIR/try_err.rs:139:9
|
LL | Err(io::ErrorKind::NotFound)?
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Some(Err(io::ErrorKind::NotFound.into())))`
error: returning an `Err(_)` with the `?` operator
--> $DIR/try_err.rs:167:16
--> $DIR/try_err.rs:148:16
|
LL | return Err(42)?;
| ^^^^^^^^ help: try this: `Err(42)`

View File

@ -1,11 +1,11 @@
// aux-build:proc_macro_with_span.rs
// aux-build:proc_macros.rs
// run-rustfix
#![warn(clippy::uninlined_format_args)]
#![allow(named_arguments_used_positionally, unused_imports, unused_macros, unused_variables)]
#![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)]
extern crate proc_macro_with_span;
use proc_macro_with_span::with_span;
extern crate proc_macros;
use proc_macros::with_span;
macro_rules! no_param_str {
() => {

View File

@ -1,11 +1,11 @@
// aux-build:proc_macro_with_span.rs
// aux-build:proc_macros.rs
// run-rustfix
#![warn(clippy::uninlined_format_args)]
#![allow(named_arguments_used_positionally, unused_imports, unused_macros, unused_variables)]
#![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)]
extern crate proc_macro_with_span;
use proc_macro_with_span::with_span;
extern crate proc_macros;
use proc_macros::with_span;
macro_rules! no_param_str {
() => {

View File

@ -1,4 +1,4 @@
// aux-build: proc_macro_with_span.rs
// aux-build: proc_macros.rs
#![warn(clippy::unit_arg)]
#![allow(unused_must_use, unused_variables)]
#![allow(
@ -13,9 +13,9 @@
clippy::unused_unit
)]
extern crate proc_macro_with_span;
extern crate proc_macros;
use proc_macro_with_span::with_span;
use proc_macros::with_span;
use std::fmt::Debug;
fn foo<T: Debug>(t: T) {

View File

@ -1,12 +1,12 @@
// run-rustfix
// aux-build: proc_macro_with_span.rs
// aux-build: proc_macros.rs
#![warn(clippy::unnecessary_lazy_evaluations)]
#![allow(clippy::redundant_closure)]
#![allow(clippy::bind_instead_of_map)]
#![allow(clippy::map_identity)]
extern crate proc_macro_with_span;
use proc_macro_with_span::with_span;
extern crate proc_macros;
use proc_macros::with_span;
struct Deep(Option<usize>);

View File

@ -1,12 +1,12 @@
// run-rustfix
// aux-build: proc_macro_with_span.rs
// aux-build: proc_macros.rs
#![warn(clippy::unnecessary_lazy_evaluations)]
#![allow(clippy::redundant_closure)]
#![allow(clippy::bind_instead_of_map)]
#![allow(clippy::map_identity)]
extern crate proc_macro_with_span;
use proc_macro_with_span::with_span;
extern crate proc_macros;
use proc_macros::with_span;
struct Deep(Option<usize>);

View File

@ -1,10 +1,10 @@
// aux-build:doc_unsafe_macros.rs
// aux-build:proc_macros.rs
#![allow(clippy::let_unit_value)]
#![warn(clippy::unnecessary_safety_doc)]
#[macro_use]
extern crate doc_unsafe_macros;
extern crate proc_macros;
use proc_macros::external;
/// This is has no safety section, and does not need one either
pub fn destroy_the_planet() {
@ -129,7 +129,11 @@ macro_rules! very_safe {
very_safe!();
// we don't lint code from external macros
undocd_safe!();
external!(
pub fn vey_oy() {
unimplemented!();
}
);
fn main() {}

View File

@ -42,7 +42,7 @@ LL | very_safe!();
= note: this error originates in the macro `very_safe` (in Nightly builds, run with -Z macro-backtrace for more info)
error: docs for safe trait have unnecessary `# Safety` section
--> $DIR/unnecessary_unsafety_doc.rs:147:1
--> $DIR/unnecessary_unsafety_doc.rs:151:1
|
LL | pub trait DocumentedSafeTraitWithImplementationHeader {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^