2023-07-27 08:23:04 -05:00
|
|
|
//@aux-build:proc_macros.rs
|
2021-06-05 01:11:44 -05:00
|
|
|
|
2022-06-09 02:17:46 -05:00
|
|
|
#![feature(lint_reasons)]
|
2021-02-01 21:26:20 -06:00
|
|
|
#![warn(clippy::default_numeric_fallback)]
|
2022-03-17 18:53:28 -05:00
|
|
|
#![allow(
|
|
|
|
unused,
|
|
|
|
clippy::never_loop,
|
|
|
|
clippy::no_effect,
|
|
|
|
clippy::unnecessary_operation,
|
|
|
|
clippy::branches_sharing_code,
|
2023-03-08 10:31:00 -06:00
|
|
|
clippy::let_unit_value,
|
|
|
|
clippy::let_with_type_underscore
|
2022-03-17 18:53:28 -05:00
|
|
|
)]
|
2021-02-14 23:22:31 -06:00
|
|
|
|
2023-03-07 08:40:55 -06:00
|
|
|
extern crate proc_macros;
|
|
|
|
use proc_macros::{external, inline_macros};
|
2021-06-05 01:11:44 -05:00
|
|
|
|
2021-02-15 08:33:27 -06:00
|
|
|
mod basic_expr {
|
|
|
|
fn test() {
|
|
|
|
// Should lint unsuffixed literals typed `i32`.
|
|
|
|
let x = 22;
|
|
|
|
let x = [1, 2, 3];
|
|
|
|
let x = if true { (1, 2) } else { (3, 4) };
|
|
|
|
let x = match 1 {
|
|
|
|
1 => 1,
|
|
|
|
_ => 2,
|
|
|
|
};
|
2021-02-14 23:22:31 -06:00
|
|
|
|
2021-02-15 08:33:27 -06:00
|
|
|
// Should NOT lint suffixed literals.
|
|
|
|
let x = 22_i32;
|
|
|
|
|
|
|
|
// Should NOT lint literals in init expr if `Local` has a type annotation.
|
|
|
|
let x: [i32; 3] = [1, 2, 3];
|
|
|
|
let x: (i32, i32) = if true { (1, 2) } else { (3, 4) };
|
|
|
|
let x: _ = 1;
|
2022-10-12 05:04:41 -05:00
|
|
|
let x: u64 = 1;
|
|
|
|
const CONST_X: i8 = 1;
|
2021-02-15 08:33:27 -06:00
|
|
|
}
|
2021-02-14 23:22:31 -06:00
|
|
|
}
|
|
|
|
|
2021-02-15 08:33:27 -06:00
|
|
|
mod nested_local {
|
|
|
|
fn test() {
|
|
|
|
let x: _ = {
|
|
|
|
// Should lint this because this literal is not bound to any types.
|
|
|
|
let y = 1;
|
|
|
|
|
|
|
|
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
|
|
|
|
1
|
|
|
|
};
|
2021-02-15 20:20:51 -06:00
|
|
|
|
|
|
|
let x: _ = if true {
|
|
|
|
// Should lint this because this literal is not bound to any types.
|
|
|
|
let y = 1;
|
|
|
|
|
|
|
|
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
|
|
|
|
1
|
|
|
|
} else {
|
|
|
|
// Should lint this because this literal is not bound to any types.
|
|
|
|
let y = 1;
|
|
|
|
|
|
|
|
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
|
|
|
|
2
|
|
|
|
};
|
2022-10-12 05:04:41 -05:00
|
|
|
|
|
|
|
const CONST_X: i32 = {
|
|
|
|
// Should lint this because this literal is not bound to any types.
|
|
|
|
let y = 1;
|
|
|
|
|
|
|
|
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
|
|
|
|
1
|
|
|
|
};
|
2021-02-15 08:33:27 -06:00
|
|
|
}
|
2021-02-14 23:22:31 -06:00
|
|
|
}
|
|
|
|
|
2021-02-15 08:33:27 -06:00
|
|
|
mod function_def {
|
|
|
|
fn ret_i32() -> i32 {
|
2021-02-15 20:20:51 -06:00
|
|
|
1
|
2021-02-15 08:33:27 -06:00
|
|
|
}
|
2021-02-14 23:22:31 -06:00
|
|
|
|
2021-02-15 08:33:27 -06:00
|
|
|
fn test() {
|
|
|
|
// Should lint this because return type is inferred to `i32` and NOT bound to a concrete
|
|
|
|
// type.
|
|
|
|
let f = || -> _ { 1 };
|
|
|
|
|
|
|
|
// Even though the output type is specified,
|
|
|
|
// this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
|
|
|
|
let f = || -> i32 { 1 };
|
|
|
|
}
|
2021-02-14 23:22:31 -06:00
|
|
|
}
|
2021-02-01 21:26:20 -06:00
|
|
|
|
2021-02-15 08:33:27 -06:00
|
|
|
mod function_calls {
|
2021-07-09 00:51:16 -05:00
|
|
|
fn concrete_arg(x: i32) {}
|
2021-02-15 08:33:27 -06:00
|
|
|
|
|
|
|
fn generic_arg<T>(t: T) {}
|
2021-02-14 23:22:31 -06:00
|
|
|
|
2021-02-15 08:33:27 -06:00
|
|
|
fn test() {
|
|
|
|
// Should NOT lint this because the argument type is bound to a concrete type.
|
2021-07-09 00:51:16 -05:00
|
|
|
concrete_arg(1);
|
2021-02-14 23:22:31 -06:00
|
|
|
|
2021-02-15 08:33:27 -06:00
|
|
|
// Should lint this because the argument type is inferred to `i32` and NOT bound to a concrete type.
|
|
|
|
generic_arg(1);
|
2021-02-01 21:26:20 -06:00
|
|
|
|
2021-02-15 08:33:27 -06:00
|
|
|
// Should lint this because the argument type is inferred to `i32` and NOT bound to a concrete type.
|
|
|
|
let x: _ = generic_arg(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-15 20:20:51 -06:00
|
|
|
mod struct_ctor {
|
|
|
|
struct ConcreteStruct {
|
|
|
|
x: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct GenericStruct<T> {
|
|
|
|
x: T,
|
|
|
|
}
|
|
|
|
|
|
|
|
fn test() {
|
|
|
|
// Should NOT lint this because the field type is bound to a concrete type.
|
|
|
|
ConcreteStruct { x: 1 };
|
|
|
|
|
|
|
|
// Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type.
|
|
|
|
GenericStruct { x: 1 };
|
|
|
|
|
|
|
|
// Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type.
|
|
|
|
let _ = GenericStruct { x: 1 };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-07 21:37:12 -05:00
|
|
|
mod enum_ctor {
|
|
|
|
enum ConcreteEnum {
|
|
|
|
X(i32),
|
|
|
|
}
|
|
|
|
|
|
|
|
enum GenericEnum<T> {
|
|
|
|
X(T),
|
|
|
|
}
|
|
|
|
|
|
|
|
fn test() {
|
|
|
|
// Should NOT lint this because the field type is bound to a concrete type.
|
|
|
|
ConcreteEnum::X(1);
|
|
|
|
|
|
|
|
// Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type.
|
|
|
|
GenericEnum::X(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-15 08:33:27 -06:00
|
|
|
mod method_calls {
|
2022-03-27 07:41:09 -05:00
|
|
|
struct StructForMethodCallTest;
|
2021-02-14 23:22:31 -06:00
|
|
|
|
2021-02-15 08:33:27 -06:00
|
|
|
impl StructForMethodCallTest {
|
|
|
|
fn concrete_arg(&self, x: i32) {}
|
2021-02-14 23:22:31 -06:00
|
|
|
|
2021-02-15 08:33:27 -06:00
|
|
|
fn generic_arg<T>(&self, t: T) {}
|
|
|
|
}
|
2021-02-14 23:22:31 -06:00
|
|
|
|
2021-02-15 08:33:27 -06:00
|
|
|
fn test() {
|
|
|
|
let s = StructForMethodCallTest {};
|
2021-02-14 23:22:31 -06:00
|
|
|
|
2021-02-15 08:33:27 -06:00
|
|
|
// Should NOT lint this because the argument type is bound to a concrete type.
|
|
|
|
s.concrete_arg(1);
|
|
|
|
|
|
|
|
// Should lint this because the argument type is bound to a concrete type.
|
|
|
|
s.generic_arg(1);
|
|
|
|
}
|
2021-02-01 21:26:20 -06:00
|
|
|
}
|
2021-02-15 08:33:27 -06:00
|
|
|
|
2021-06-05 01:11:44 -05:00
|
|
|
mod in_macro {
|
2023-03-07 08:40:55 -06:00
|
|
|
use super::*;
|
2021-06-05 01:11:44 -05:00
|
|
|
|
|
|
|
// Should lint in internal macro.
|
2023-03-07 08:40:55 -06:00
|
|
|
#[inline_macros]
|
2021-06-05 01:11:44 -05:00
|
|
|
fn internal() {
|
2023-03-07 08:40:55 -06:00
|
|
|
inline!(let x = 22;);
|
2021-06-05 01:11:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Should NOT lint in external macro.
|
|
|
|
fn external() {
|
2023-03-07 08:40:55 -06:00
|
|
|
external!(let x = 22;);
|
2021-06-05 01:11:44 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-09 02:17:46 -05:00
|
|
|
fn check_expect_suppression() {
|
|
|
|
#[expect(clippy::default_numeric_fallback)]
|
|
|
|
let x = 21;
|
|
|
|
}
|
|
|
|
|
2024-01-02 18:21:51 -06:00
|
|
|
mod type_already_inferred {
|
2023-12-12 21:09:08 -06:00
|
|
|
// Should NOT lint if bound to return type
|
|
|
|
fn ret_i32() -> i32 {
|
|
|
|
1
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should NOT lint if bound to return type
|
|
|
|
fn ret_if_i32(b: bool) -> i32 {
|
|
|
|
if b { 100 } else { 0 }
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should NOT lint if bound to return type
|
|
|
|
fn ret_i32_tuple() -> (i32, i32) {
|
|
|
|
(0, 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should NOT lint if bound to return type
|
|
|
|
fn ret_stmt(b: bool) -> (i32, i32) {
|
|
|
|
if b {
|
|
|
|
return (0, 1);
|
|
|
|
}
|
|
|
|
(0, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(clippy::useless_vec)]
|
|
|
|
fn vec_macro() {
|
|
|
|
// Should NOT lint in `vec!` call if the type was already stated
|
|
|
|
let data_i32: Vec<i32> = vec![1, 2, 3];
|
|
|
|
let data_i32 = vec![1, 2, 3];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-15 08:33:27 -06:00
|
|
|
fn main() {}
|