|  | #![warn(rust_2018_idioms, single_use_lifetimes)] | 
|  | #![warn(nonstandard_style, rust_2018_compatibility, unused)] | 
|  | // Note: This does not guarantee compatibility with `forbid(future_incompatible)` in the future. | 
|  | // If rustc adds a new lint, we may not be able to keep this. | 
|  | #![forbid(future_incompatible)] | 
|  | #![warn(clippy::all, clippy::pedantic, clippy::nursery)] | 
|  | #![allow(unknown_lints)] // for old compilers | 
|  | #![warn( | 
|  | absolute_paths_not_starting_with_crate, | 
|  | anonymous_parameters, | 
|  | box_pointers, | 
|  | deprecated_in_future, | 
|  | elided_lifetimes_in_paths, | 
|  | explicit_outlives_requirements, | 
|  | indirect_structural_match, | 
|  | keyword_idents, | 
|  | macro_use_extern_crate, | 
|  | meta_variable_misuse, | 
|  | missing_copy_implementations, | 
|  | missing_crate_level_docs, | 
|  | missing_debug_implementations, | 
|  | missing_docs, | 
|  | missing_doc_code_examples, | 
|  | non_ascii_idents, | 
|  | private_doc_tests, | 
|  | single_use_lifetimes, | 
|  | trivial_casts, | 
|  | trivial_numeric_casts, | 
|  | unaligned_references, | 
|  | unreachable_pub, | 
|  | unstable_features, | 
|  | unused_extern_crates, | 
|  | unused_import_braces, | 
|  | unused_lifetimes, | 
|  | unused_qualifications, | 
|  | unused_results, | 
|  | variant_size_differences | 
|  | )] | 
|  | // unused_crate_dependencies: unrelated | 
|  | // unsafe_code: checked in forbid_unsafe module | 
|  | // unsafe_block_in_unsafe_fn: unstable | 
|  |  | 
|  | // Check interoperability with rustc and clippy lints. | 
|  |  | 
|  | pub mod basic { | 
|  | include!("include/basic.rs"); | 
|  | } | 
|  |  | 
|  | pub mod forbid_unsafe { | 
|  | #![forbid(unsafe_code)] | 
|  |  | 
|  | include!("include/basic-safe-part.rs"); | 
|  | } | 
|  |  | 
|  | pub mod clippy { | 
|  | use pin_project::pin_project; | 
|  |  | 
|  | #[rustversion::attr(before(1.37), allow(single_use_lifetimes))] // https://github.com/rust-lang/rust/issues/53738 | 
|  | #[pin_project(project_replace)] | 
|  | #[derive(Debug)] | 
|  | pub struct MutMutStruct<'a, T, U> { | 
|  | #[pin] | 
|  | pub pinned: &'a mut T, | 
|  | pub unpinned: &'a mut U, | 
|  | } | 
|  |  | 
|  | #[rustversion::attr(before(1.37), allow(single_use_lifetimes))] // https://github.com/rust-lang/rust/issues/53738 | 
|  | #[pin_project(project_replace)] | 
|  | #[derive(Debug)] | 
|  | pub struct MutMutTupleStruct<'a, T, U>(#[pin] &'a mut T, &'a mut U); | 
|  |  | 
|  | #[rustversion::attr(before(1.37), allow(single_use_lifetimes))] // https://github.com/rust-lang/rust/issues/53738 | 
|  | #[pin_project(project_replace)] | 
|  | #[derive(Debug)] | 
|  | pub enum MutMutEnum<'a, T, U> { | 
|  | Struct { | 
|  | #[pin] | 
|  | pinned: &'a mut T, | 
|  | unpinned: &'a mut U, | 
|  | }, | 
|  | Tuple(#[pin] &'a mut T, &'a mut U), | 
|  | Unit, | 
|  | } | 
|  |  | 
|  | #[pin_project(project_replace)] | 
|  | #[derive(Debug)] | 
|  | pub struct TypeRepetitionInBoundsStruct<T, U> | 
|  | where | 
|  | Self: Sized, | 
|  | { | 
|  | #[pin] | 
|  | pub pinned: T, | 
|  | pub unpinned: U, | 
|  | } | 
|  |  | 
|  | #[pin_project(project_replace)] | 
|  | #[derive(Debug)] | 
|  | pub struct TypeRepetitionInBoundsTupleStruct<T, U>(#[pin] T, U) | 
|  | where | 
|  | Self: Sized; | 
|  |  | 
|  | #[pin_project(project_replace)] | 
|  | #[derive(Debug)] | 
|  | pub enum TypeRepetitionInBoundsEnum<T, U> | 
|  | where | 
|  | Self: Sized, | 
|  | { | 
|  | Struct { | 
|  | #[pin] | 
|  | pinned: T, | 
|  | unpinned: U, | 
|  | }, | 
|  | Tuple(#[pin] T, U), | 
|  | Unit, | 
|  | } | 
|  |  | 
|  | #[pin_project(project_replace)] | 
|  | #[derive(Debug)] | 
|  | pub struct UsedUnderscoreBindingStruct<T, U> { | 
|  | #[pin] | 
|  | pub _pinned: T, | 
|  | pub _unpinned: U, | 
|  | } | 
|  |  | 
|  | #[pin_project(project_replace)] | 
|  | #[derive(Debug)] | 
|  | pub enum UsedUnderscoreBindingEnum<T, U> { | 
|  | Struct { | 
|  | #[pin] | 
|  | _pinned: T, | 
|  | _unpinned: U, | 
|  | }, | 
|  | } | 
|  | } | 
|  |  | 
|  | #[allow(box_pointers)] | 
|  | #[rustversion::attr(not(nightly), ignore)] | 
|  | #[test] | 
|  | fn check_lint_list() { | 
|  | use std::{env, fs, path::PathBuf, process::Command, str}; | 
|  |  | 
|  | type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>; | 
|  |  | 
|  | fn assert_eq(expected_path: &str, actual: &str) -> Result<()> { | 
|  | let manifest_dir = env::var_os("CARGO_MANIFEST_DIR") | 
|  | .map(PathBuf::from) | 
|  | .expect("CARGO_MANIFEST_DIR not set"); | 
|  | let expected_path = manifest_dir.join(expected_path); | 
|  | let expected = fs::read_to_string(&expected_path)?; | 
|  | if expected != actual { | 
|  | if env::var_os("CI").map_or(false, |v| v == "true") { | 
|  | panic!( | 
|  | "assertion failed:\n\nEXPECTED:\n{0}\n{1}\n{0}\n\nACTUAL:\n{0}\n{2}\n{0}\n", | 
|  | "-".repeat(60), | 
|  | expected, | 
|  | actual, | 
|  | ); | 
|  | } else { | 
|  | fs::write(&expected_path, actual)?; | 
|  | } | 
|  | } | 
|  | Ok(()) | 
|  | } | 
|  |  | 
|  | (|| -> Result<()> { | 
|  | let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into()); | 
|  | let output = Command::new(rustc).args(&["-W", "help"]).output()?; | 
|  | let new = str::from_utf8(&output.stdout)?; | 
|  | assert_eq("tests/lint.txt", new) | 
|  | })() | 
|  | .unwrap_or_else(|e| panic!("{}", e)); | 
|  | } |