From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- .../clippy/tests/ui/auxiliary/doc_unsafe_macros.rs | 8 ++ .../tests/ui/auxiliary/implicit_hasher_macros.rs | 6 + src/tools/clippy/tests/ui/auxiliary/macro_rules.rs | 142 +++++++++++++++++++++ .../clippy/tests/ui/auxiliary/macro_use_helper.rs | 60 +++++++++ .../tests/ui/auxiliary/non-exhaustive-enum.rs | 8 ++ .../clippy/tests/ui/auxiliary/option_helpers.rs | 64 ++++++++++ .../clippy/tests/ui/auxiliary/proc_macro_attr.rs | 101 +++++++++++++++ .../clippy/tests/ui/auxiliary/proc_macro_derive.rs | 88 +++++++++++++ .../proc_macro_suspicious_else_formatting.rs | 74 +++++++++++ .../clippy/tests/ui/auxiliary/proc_macro_unsafe.rs | 18 +++ .../tests/ui/auxiliary/proc_macro_with_span.rs | 32 +++++ src/tools/clippy/tests/ui/auxiliary/test_macro.rs | 11 ++ .../clippy/tests/ui/auxiliary/use_self_macro.rs | 15 +++ .../tests/ui/auxiliary/wildcard_imports_helper.rs | 27 ++++ 14 files changed, 654 insertions(+) create mode 100644 src/tools/clippy/tests/ui/auxiliary/doc_unsafe_macros.rs create mode 100644 src/tools/clippy/tests/ui/auxiliary/implicit_hasher_macros.rs create mode 100644 src/tools/clippy/tests/ui/auxiliary/macro_rules.rs create mode 100644 src/tools/clippy/tests/ui/auxiliary/macro_use_helper.rs create mode 100644 src/tools/clippy/tests/ui/auxiliary/non-exhaustive-enum.rs create mode 100644 src/tools/clippy/tests/ui/auxiliary/option_helpers.rs create mode 100644 src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs create mode 100644 src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs create mode 100644 src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs create mode 100644 src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs create mode 100644 src/tools/clippy/tests/ui/auxiliary/proc_macro_with_span.rs create mode 100644 src/tools/clippy/tests/ui/auxiliary/test_macro.rs create mode 100644 src/tools/clippy/tests/ui/auxiliary/use_self_macro.rs create mode 100644 src/tools/clippy/tests/ui/auxiliary/wildcard_imports_helper.rs (limited to 'src/tools/clippy/tests/ui/auxiliary') diff --git a/src/tools/clippy/tests/ui/auxiliary/doc_unsafe_macros.rs b/src/tools/clippy/tests/ui/auxiliary/doc_unsafe_macros.rs new file mode 100644 index 000000000..869672d1e --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/doc_unsafe_macros.rs @@ -0,0 +1,8 @@ +#[macro_export] +macro_rules! undocd_unsafe { + () => { + pub unsafe fn oy_vey() { + unimplemented!(); + } + }; +} diff --git a/src/tools/clippy/tests/ui/auxiliary/implicit_hasher_macros.rs b/src/tools/clippy/tests/ui/auxiliary/implicit_hasher_macros.rs new file mode 100644 index 000000000..1eb77c531 --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/implicit_hasher_macros.rs @@ -0,0 +1,6 @@ +#[macro_export] +macro_rules! implicit_hasher_fn { + () => { + pub fn f(input: &HashMap) {} + }; +} diff --git a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs new file mode 100644 index 000000000..83a0af6b8 --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs @@ -0,0 +1,142 @@ +#![allow(dead_code)] + +//! 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 { + () => { + pub fn try_err_fn() -> Result { + let err: i32 = 1; + // To avoid warnings during rustfix + if true { Err(err)? } else { Ok(2) } + } + }; +} + +#[macro_export] +macro_rules! string_add { + () => { + let y = "".to_owned(); + let z = y + "..."; + }; +} + +#[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 {} }}; +} diff --git a/src/tools/clippy/tests/ui/auxiliary/macro_use_helper.rs b/src/tools/clippy/tests/ui/auxiliary/macro_use_helper.rs new file mode 100644 index 000000000..ecb55d8cb --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/macro_use_helper.rs @@ -0,0 +1,60 @@ +extern crate macro_rules; + +// STMT +#[macro_export] +macro_rules! pub_macro { + () => { + let _ = "hello Mr. Vonnegut"; + }; +} + +pub mod inner { + pub use super::*; + + // RE-EXPORT + // this will stick in `inner` module + pub use macro_rules::foofoo; + pub use macro_rules::try_err; + + pub mod nested { + pub use macro_rules::string_add; + } + + // ITEM + #[macro_export] + macro_rules! inner_mod_macro { + () => { + #[allow(dead_code)] + pub struct Tardis; + }; + } +} + +// EXPR +#[macro_export] +macro_rules! function_macro { + () => { + if true { + } else { + } + }; +} + +// TYPE +#[macro_export] +macro_rules! ty_macro { + () => { + Vec + }; +} + +mod extern_exports { + pub(super) mod private_inner { + #[macro_export] + macro_rules! pub_in_private_macro { + ($name:ident) => { + let $name = String::from("secrets and lies"); + }; + } + } +} diff --git a/src/tools/clippy/tests/ui/auxiliary/non-exhaustive-enum.rs b/src/tools/clippy/tests/ui/auxiliary/non-exhaustive-enum.rs new file mode 100644 index 000000000..420232f9f --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/non-exhaustive-enum.rs @@ -0,0 +1,8 @@ +// Stripped down version of the ErrorKind enum of std +#[non_exhaustive] +pub enum ErrorKind { + NotFound, + PermissionDenied, + #[doc(hidden)] + Uncategorized, +} diff --git a/src/tools/clippy/tests/ui/auxiliary/option_helpers.rs b/src/tools/clippy/tests/ui/auxiliary/option_helpers.rs new file mode 100644 index 000000000..f9bc9436b --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/option_helpers.rs @@ -0,0 +1,64 @@ +#![allow(dead_code, unused_variables, clippy::return_self_not_must_use)] + +/// Utility macro to test linting behavior in `option_methods()` +/// The lints included in `option_methods()` should not lint if the call to map is partially +/// within a macro +#[macro_export] +macro_rules! opt_map { + ($opt:expr, $map:expr) => { + ($opt).map($map) + }; +} + +/// Struct to generate false positive for Iterator-based lints +#[derive(Copy, Clone)] +pub struct IteratorFalsePositives { + pub foo: u32, +} + +impl IteratorFalsePositives { + pub fn filter(self) -> IteratorFalsePositives { + self + } + + pub fn next(self) -> IteratorFalsePositives { + self + } + + pub fn find(self) -> Option { + Some(self.foo) + } + + pub fn position(self) -> Option { + Some(self.foo) + } + + pub fn rposition(self) -> Option { + Some(self.foo) + } + + pub fn nth(self, n: usize) -> Option { + Some(self.foo) + } + + pub fn skip(self, _: usize) -> IteratorFalsePositives { + self + } + + pub fn skip_while(self) -> IteratorFalsePositives { + self + } + + pub fn count(self) -> usize { + self.foo as usize + } +} + +#[derive(Copy, Clone)] +pub struct IteratorMethodFalsePositives; + +impl IteratorMethodFalsePositives { + pub fn filter(&self, _s: i32) -> std::vec::IntoIter { + unimplemented!(); + } +} diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs new file mode 100644 index 000000000..ae2cc2492 --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs @@ -0,0 +1,101 @@ +// compile-flags: --emit=link +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(repr128, proc_macro_hygiene, proc_macro_quote, box_patterns)] +#![allow(incomplete_features)] +#![allow(clippy::useless_conversion)] + +extern crate proc_macro; +extern crate quote; +extern crate syn; + +use proc_macro::TokenStream; +use quote::{quote, quote_spanned}; +use syn::parse_macro_input; +use syn::spanned::Spanned; +use syn::token::Star; +use syn::{ + parse_quote, FnArg, ImplItem, ItemImpl, ItemTrait, Lifetime, Pat, PatIdent, PatType, Signature, TraitItem, Type, +}; + +#[proc_macro_attribute] +pub fn dummy(_args: TokenStream, input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_attribute] +pub fn fake_async_trait(_args: TokenStream, input: TokenStream) -> TokenStream { + let mut item = parse_macro_input!(input as ItemTrait); + for inner in &mut item.items { + if let TraitItem::Method(method) = inner { + let sig = &method.sig; + let block = &mut method.default; + if let Some(block) = block { + let brace = block.brace_token; + + let my_block = quote_spanned!( brace.span => { + // Should not trigger `empty_line_after_outer_attr` + #[crate_type = "lib"] + #sig #block + Vec::new() + }); + *block = parse_quote!(#my_block); + } + } + } + TokenStream::from(quote!(#item)) +} + +#[proc_macro_attribute] +pub fn rename_my_lifetimes(_args: TokenStream, input: TokenStream) -> TokenStream { + fn make_name(count: usize) -> String { + format!("'life{}", count) + } + + fn mut_receiver_of(sig: &mut Signature) -> Option<&mut FnArg> { + let arg = sig.inputs.first_mut()?; + if let FnArg::Typed(PatType { pat, .. }) = arg { + if let Pat::Ident(PatIdent { ident, .. }) = &**pat { + if ident == "self" { + return Some(arg); + } + } + } + None + } + + let mut elided = 0; + let mut item = parse_macro_input!(input as ItemImpl); + + // Look for methods having arbitrary self type taken by &mut ref + for inner in &mut item.items { + if let ImplItem::Method(method) = inner { + if let Some(FnArg::Typed(pat_type)) = mut_receiver_of(&mut method.sig) { + if let box Type::Reference(reference) = &mut pat_type.ty { + // Target only unnamed lifetimes + let name = match &reference.lifetime { + Some(lt) if lt.ident == "_" => make_name(elided), + None => make_name(elided), + _ => continue, + }; + elided += 1; + + // HACK: Syn uses `Span` from the proc_macro2 crate, and does not seem to reexport it. + // In order to avoid adding the dependency, get a default span from a non-existent token. + // A default span is needed to mark the code as coming from expansion. + let span = Star::default().span(); + + // Replace old lifetime with the named one + let lifetime = Lifetime::new(&name, span); + reference.lifetime = Some(parse_quote!(#lifetime)); + + // Add lifetime to the generics of the method + method.sig.generics.params.push(parse_quote!(#lifetime)); + } + } + } + } + + TokenStream::from(quote!(#item)) +} diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs new file mode 100644 index 000000000..a89a06308 --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs @@ -0,0 +1,88 @@ +// compile-flags: --emit=link +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(repr128, proc_macro_quote)] +#![allow(incomplete_features)] +#![allow(clippy::field_reassign_with_default)] +#![allow(clippy::eq_op)] + +extern crate proc_macro; + +use proc_macro::{quote, TokenStream}; + +#[proc_macro_derive(DeriveSomething)] +pub fn derive(_: TokenStream) -> TokenStream { + // Should not trigger `used_underscore_binding` + let _inside_derive = 1; + assert_eq!(_inside_derive, _inside_derive); + + let output = quote! { + // Should not trigger `useless_attribute` + #[allow(dead_code)] + extern crate rustc_middle; + }; + output +} + +#[proc_macro_derive(FieldReassignWithDefault)] +pub fn derive_foo(_input: TokenStream) -> TokenStream { + quote! { + #[derive(Default)] + struct A { + pub i: i32, + pub j: i64, + } + #[automatically_derived] + fn lint() { + let mut a: A = Default::default(); + a.i = 42; + a; + } + } +} + +#[proc_macro_derive(StructAUseSelf)] +pub fn derive_use_self(_input: TokenStream) -> proc_macro::TokenStream { + quote! { + struct A; + impl A { + fn new() -> A { + A + } + } + } +} + +#[proc_macro_derive(ClippyMiniMacroTest)] +pub fn mini_macro(_: TokenStream) -> TokenStream { + quote!( + #[allow(unused)] + fn needless_take_by_value(s: String) { + println!("{}", s.len()); + } + #[allow(unused)] + fn needless_loop(items: &[u8]) { + for i in 0..items.len() { + println!("{}", items[i]); + } + } + fn line_wrapper() { + println!("{}", line!()); + } + ) +} + +#[proc_macro_derive(ExtraLifetimeDerive)] +#[allow(unused)] +pub fn extra_lifetime(_input: TokenStream) -> TokenStream { + quote!( + pub struct ExtraLifetime; + + impl<'b> ExtraLifetime { + pub fn something<'c>() -> Self { + Self + } + } + ) +} diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs new file mode 100644 index 000000000..a2ef0fe82 --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs @@ -0,0 +1,74 @@ +// compile-flags: --emit=link +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::{token_stream, Delimiter, Group, Ident, Span, TokenStream, TokenTree}; + +fn read_ident(iter: &mut token_stream::IntoIter) -> Ident { + match iter.next() { + Some(TokenTree::Ident(i)) => i, + _ => panic!("expected ident"), + } +} + +#[proc_macro_derive(DeriveBadSpan)] +pub fn derive_bad_span(input: TokenStream) -> TokenStream { + let mut input = input.into_iter(); + assert_eq!(read_ident(&mut input).to_string(), "struct"); + let ident = read_ident(&mut input); + let mut tys = match input.next() { + Some(TokenTree::Group(g)) if g.delimiter() == Delimiter::Parenthesis => g.stream().into_iter(), + _ => panic!(), + }; + let field1 = read_ident(&mut tys); + tys.next(); + let field2 = read_ident(&mut tys); + + >::from_iter( + [ + Ident::new("impl", Span::call_site()).into(), + ident.into(), + Group::new( + Delimiter::Brace, + >::from_iter( + [ + Ident::new("fn", Span::call_site()).into(), + Ident::new("_foo", Span::call_site()).into(), + Group::new(Delimiter::Parenthesis, TokenStream::new()).into(), + Group::new( + Delimiter::Brace, + >::from_iter( + [ + Ident::new("if", field1.span()).into(), + Ident::new("true", field1.span()).into(), + { + let mut group = Group::new(Delimiter::Brace, TokenStream::new()); + group.set_span(field1.span()); + group.into() + }, + Ident::new("if", field2.span()).into(), + Ident::new("true", field2.span()).into(), + { + let mut group = Group::new(Delimiter::Brace, TokenStream::new()); + group.set_span(field2.span()); + group.into() + }, + ] + .iter() + .cloned(), + ), + ) + .into(), + ] + .iter() + .cloned(), + ), + ) + .into(), + ] + .iter() + .cloned(), + ) +} diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs new file mode 100644 index 000000000..3c40f7746 --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs @@ -0,0 +1,18 @@ +// compile-flags: --emit=link +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Delimiter, Group, Ident, TokenStream, TokenTree}; + +#[proc_macro] +pub fn unsafe_block(input: TokenStream) -> TokenStream { + let span = input.into_iter().next().unwrap().span(); + TokenStream::from_iter([TokenTree::Ident(Ident::new("unsafe", span)), { + let mut group = Group::new(Delimiter::Brace, TokenStream::new()); + group.set_span(span); + TokenTree::Group(group) + }]) +} diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_with_span.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_with_span.rs new file mode 100644 index 000000000..8ea631f2b --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_with_span.rs @@ -0,0 +1,32 @@ +// 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]); + } + } +} diff --git a/src/tools/clippy/tests/ui/auxiliary/test_macro.rs b/src/tools/clippy/tests/ui/auxiliary/test_macro.rs new file mode 100644 index 000000000..624ca892a --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/test_macro.rs @@ -0,0 +1,11 @@ +pub trait A {} + +macro_rules! __implicit_hasher_test_macro { + (impl< $($impl_arg:tt),* > for $kind:ty where $($bounds:tt)*) => { + __implicit_hasher_test_macro!( ($($impl_arg),*) ($kind) ($($bounds)*) ); + }; + + (($($impl_arg:tt)*) ($($kind_arg:tt)*) ($($bounds:tt)*)) => { + impl< $($impl_arg)* > test_macro::A for $($kind_arg)* where $($bounds)* { } + }; +} diff --git a/src/tools/clippy/tests/ui/auxiliary/use_self_macro.rs b/src/tools/clippy/tests/ui/auxiliary/use_self_macro.rs new file mode 100644 index 000000000..a8a85b4ba --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/use_self_macro.rs @@ -0,0 +1,15 @@ +macro_rules! use_self { + ( + impl $ty:ident { + fn func(&$this:ident) { + [fields($($field:ident)*)] + } + } + ) => ( + impl $ty { + fn func(&$this) { + let $ty { $($field),* } = $this; + } + } + ) +} diff --git a/src/tools/clippy/tests/ui/auxiliary/wildcard_imports_helper.rs b/src/tools/clippy/tests/ui/auxiliary/wildcard_imports_helper.rs new file mode 100644 index 000000000..d75cdd625 --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/wildcard_imports_helper.rs @@ -0,0 +1,27 @@ +pub use crate::extern_exports::*; + +pub fn extern_foo() {} +pub fn extern_bar() {} + +pub struct ExternA; + +pub mod inner { + pub mod inner_for_self_import { + pub fn inner_extern_foo() {} + pub fn inner_extern_bar() {} + } +} + +mod extern_exports { + pub fn extern_exported() {} + pub struct ExternExportedStruct; + pub enum ExternExportedEnum { + A, + } +} + +pub mod prelude { + pub mod v1 { + pub struct PreludeModAnywhere; + } +} -- cgit v1.2.3