diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 068f1372c0ecd..f902f3b92a08e 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -455,6 +455,12 @@ lint_path_statement_drop = path statement drops value lint_path_statement_no_effect = path statement with no effect +lint_precedence_unary = unary operator `{$op}` has lower precedence than method call + .suggestion = consider adding parentheses to clarify your intent + +lint_precedence_unwary = operator precedence can trip the unwary + .suggestion = consider adding parentheses to clarify your intent + lint_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value .label = expression has type `{$orig_ty}` diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 606e18866165c..79cdd17b00677 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -80,6 +80,7 @@ mod noop_method_call; mod opaque_hidden_inferred_bound; mod pass_by_value; mod passes; +mod precedence; mod ptr_nulls; mod redundant_semicolon; mod reference_casting; @@ -118,6 +119,7 @@ use nonstandard_style::*; use noop_method_call::*; use opaque_hidden_inferred_bound::*; use pass_by_value::*; +use precedence::*; use ptr_nulls::*; use redundant_semicolon::*; use reference_casting::*; @@ -180,6 +182,7 @@ early_lint_methods!( RedundantSemicolons: RedundantSemicolons, UnusedDocComment: UnusedDocComment, UnexpectedCfgs: UnexpectedCfgs, + Precedence: Precedence, ] ] ); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 756899e50a8cd..802cec2c01ab5 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -617,6 +617,53 @@ pub struct ExpectationNote { pub rationale: Symbol, } +// precedence.rs +#[derive(LintDiagnostic)] +pub enum PrecedenceDiag { + #[diag(lint_precedence_unary)] + Unary { + op: &'static str, + #[subdiagnostic] + suggestion: PrecedenceUnarySuggestion, + }, + #[diag(lint_precedence_unwary)] + Unwary { + #[subdiagnostic] + suggestion: PrecedenceUnwarySuggestion, + }, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +pub struct PrecedenceUnarySuggestion { + #[suggestion_part(code = "(")] + pub start_span: Span, + #[suggestion_part(code = ")")] + pub end_span: Span, +} + +#[derive(Subdiagnostic)] +pub enum PrecedenceUnwarySuggestion { + #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] + OneExpr { + #[suggestion_part(code = "(")] + start_span: Span, + #[suggestion_part(code = ")")] + end_span: Span, + }, + #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] + TwoExpr { + #[suggestion_part(code = "(")] + start_span: Span, + #[suggestion_part(code = ")")] + end_span: Span, + #[suggestion_part(code = "(")] + start2_span: Span, + #[suggestion_part(code = ")")] + end2_span: Span, + }, +} + // ptr_nulls.rs #[derive(LintDiagnostic)] pub enum PtrNullChecksDiag<'a> { diff --git a/compiler/rustc_lint/src/precedence.rs b/compiler/rustc_lint/src/precedence.rs new file mode 100644 index 0000000000000..45b10a511d810 --- /dev/null +++ b/compiler/rustc_lint/src/precedence.rs @@ -0,0 +1,116 @@ +use rustc_ast::token::LitKind; +use rustc_ast::{BinOpKind, Expr, ExprKind, MethodCall, UnOp}; +use rustc_span::source_map::Spanned; + +use crate::lints::{PrecedenceDiag, PrecedenceUnarySuggestion, PrecedenceUnwarySuggestion}; +use crate::{EarlyContext, EarlyLintPass, LintContext}; + +declare_lint! { + /// The `ambiguous_precedence` lint checks for operations where + /// precedence may be unclear and suggests adding parentheses. + /// + /// ### Example + /// + /// ```rust + /// # #![allow(unused)] + /// 1 << 2 + 3; // equals 32, while `(1 << 2) + 3` equals 7 + /// -1i32.abs(); // equals -1, while `(-1i32).abs()` equals 1 + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Unary operations take precedence on binary operations and method + /// calls take precedence over unary precedence. Setting the precedence + /// explicitly makes the code clearer and avoid potential bugs. + pub AMBIGUOUS_PRECEDENCE, + Warn, + "operations where precedence may be unclear" +} + +declare_lint_pass!(Precedence => [AMBIGUOUS_PRECEDENCE]); + +impl EarlyLintPass for Precedence { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + if expr.span.from_expansion() { + return; + } + + if let ExprKind::Binary(Spanned { node: op, .. }, ref left, ref right) = expr.kind { + if !is_bit_op(op) { + return; + } + + let suggestion = match (is_arith_expr(left), is_arith_expr(right)) { + (true, true) => PrecedenceUnwarySuggestion::TwoExpr { + start_span: left.span.shrink_to_lo(), + end_span: left.span.shrink_to_hi(), + start2_span: right.span.shrink_to_lo(), + end2_span: right.span.shrink_to_hi(), + }, + (true, false) => PrecedenceUnwarySuggestion::OneExpr { + start_span: left.span.shrink_to_lo(), + end_span: left.span.shrink_to_hi(), + }, + (false, true) => PrecedenceUnwarySuggestion::OneExpr { + start_span: right.span.shrink_to_lo(), + end_span: right.span.shrink_to_hi(), + }, + (false, false) => return, + }; + + cx.emit_spanned_lint( + AMBIGUOUS_PRECEDENCE, + expr.span, + PrecedenceDiag::Unwary { suggestion }, + ); + } + + if let ExprKind::Unary(unop, operand) = &expr.kind + && matches!(unop, UnOp::Neg) + && let ExprKind::MethodCall(..) = operand.kind + { + let mut arg = operand; + while let ExprKind::MethodCall(box MethodCall { receiver, .. }) = &arg.kind { + arg = receiver; + } + + if let ExprKind::Lit(lit) = &arg.kind + && let LitKind::Integer | LitKind::Float = &lit.kind + && !arg.span.from_expansion() + { + cx.emit_spanned_lint( + AMBIGUOUS_PRECEDENCE, + expr.span, + PrecedenceDiag::Unary { + op: UnOp::to_string(*unop), + suggestion: PrecedenceUnarySuggestion { + start_span: operand.span.shrink_to_lo(), + end_span: operand.span.shrink_to_hi(), + }, + }, + ); + } + } + } +} + +fn is_arith_expr(expr: &Expr) -> bool { + match expr.kind { + ExprKind::Binary(Spanned { node: op, .. }, _, _) => is_arith_op(op), + _ => false, + } +} + +#[must_use] +fn is_bit_op(op: BinOpKind) -> bool { + use rustc_ast::ast::BinOpKind::{BitAnd, BitOr, BitXor, Shl, Shr}; + matches!(op, BitXor | BitAnd | BitOr | Shl | Shr) +} + +#[must_use] +fn is_arith_op(op: BinOpKind) -> bool { + use rustc_ast::ast::BinOpKind::{Add, Div, Mul, Rem, Sub}; + matches!(op, Add | Sub | Mul | Div | Rem) +} diff --git a/library/core/tests/num/i32.rs b/library/core/tests/num/i32.rs index efd5b1596a80d..833d654b3f814 100644 --- a/library/core/tests/num/i32.rs +++ b/library/core/tests/num/i32.rs @@ -15,7 +15,7 @@ fn test_arith_operation() { assert_eq!(i32_a * i32_a * i32_a, 1000); assert_eq!(i32_a * i32_a * i32_a * i32_a, 10000); assert_eq!(i32_a * i32_a / i32_a * i32_a, 100); - assert_eq!(i32_a * (i32_a - 1) << (2 + i32_a as usize), 368640); + assert_eq!((i32_a * (i32_a - 1)) << (2 + i32_a as usize), 368640); let i32_b: isize = 0x10101010; assert_eq!(i32_b + 1 - 1, i32_b); assert_eq!(i32_b << 1, i32_b << 1); diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 85854a0dfb762..5bf03489776d8 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -561,7 +561,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF_INFO, crate::pattern_type_mismatch::PATTERN_TYPE_MISMATCH_INFO, crate::permissions_set_readonly_false::PERMISSIONS_SET_READONLY_FALSE_INFO, - crate::precedence::PRECEDENCE_INFO, crate::ptr::CMP_NULL_INFO, crate::ptr::INVALID_NULL_PTR_USAGE_INFO, crate::ptr::MUT_FROM_REF_INFO, diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index c462c93308250..e29d4d9b42172 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -264,7 +264,6 @@ mod partialeq_to_none; mod pass_by_ref_or_value; mod pattern_type_mismatch; mod permissions_set_readonly_false; -mod precedence; mod ptr; mod ptr_offset_with_cast; mod pub_use; @@ -809,7 +808,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(returns::Return)); store.register_early_pass(|| Box::new(collapsible_if::CollapsibleIf)); store.register_late_pass(|_| Box::new(items_after_statements::ItemsAfterStatements)); - store.register_early_pass(|| Box::new(precedence::Precedence)); store.register_late_pass(|_| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals)); store.register_early_pass(|| Box::new(needless_continue::NeedlessContinue)); store.register_early_pass(|| Box::new(redundant_else::RedundantElse)); diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs index 613f1ecc6fbee..414ad285f2e40 100644 --- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs +++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs @@ -52,6 +52,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[ ("clippy::invalid_utf8_in_unchecked", "invalid_from_utf8_unchecked"), ("clippy::let_underscore_drop", "let_underscore_drop"), ("clippy::mem_discriminant_non_enum", "enum_intrinsics_non_enums"), + ("clippy::precedence", "ambiguous_precedence"), ("clippy::panic_params", "non_fmt_panics"), ("clippy::positional_named_format_parameters", "named_arguments_used_positionally"), ("clippy::temporary_cstring_as_ptr", "temporary_cstring_as_ptr"), diff --git a/src/tools/clippy/tests/ui/neg_multiply.fixed b/src/tools/clippy/tests/ui/neg_multiply.fixed index 52edea73afbb7..94532ef6222dc 100644 --- a/src/tools/clippy/tests/ui/neg_multiply.fixed +++ b/src/tools/clippy/tests/ui/neg_multiply.fixed @@ -1,6 +1,6 @@ #![warn(clippy::neg_multiply)] -#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::precedence)] -#![allow(unused)] +#![allow(clippy::no_effect, clippy::unnecessary_operation)] +#![allow(unused, ambiguous_precedence)] use std::ops::Mul; diff --git a/src/tools/clippy/tests/ui/neg_multiply.rs b/src/tools/clippy/tests/ui/neg_multiply.rs index 23092a35e6064..bdfa0cf03b15a 100644 --- a/src/tools/clippy/tests/ui/neg_multiply.rs +++ b/src/tools/clippy/tests/ui/neg_multiply.rs @@ -1,6 +1,6 @@ #![warn(clippy::neg_multiply)] -#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::precedence)] -#![allow(unused)] +#![allow(clippy::no_effect, clippy::unnecessary_operation)] +#![allow(unused, ambiguous_precedence)] use std::ops::Mul; diff --git a/src/tools/clippy/tests/ui/precedence.fixed b/src/tools/clippy/tests/ui/precedence.fixed deleted file mode 100644 index cc87de0d90f18..0000000000000 --- a/src/tools/clippy/tests/ui/precedence.fixed +++ /dev/null @@ -1,60 +0,0 @@ -#![warn(clippy::precedence)] -#![allow(unused_must_use, clippy::no_effect, clippy::unnecessary_operation)] -#![allow(clippy::identity_op)] -#![allow(clippy::eq_op)] - -macro_rules! trip { - ($a:expr) => { - match $a & 0b1111_1111u8 { - 0 => println!("a is zero ({})", $a), - _ => println!("a is {}", $a), - } - }; -} - -fn main() { - 1 << (2 + 3); - (1 + 2) << 3; - 4 >> (1 + 1); - (1 + 3) >> 2; - 1 ^ (1 - 1); - 3 | (2 - 1); - 3 & (5 - 2); - -(1i32.abs()); - -(1f32.abs()); - - // These should not trigger an error - let _ = (-1i32).abs(); - let _ = (-1f32).abs(); - let _ = -(1i32).abs(); - let _ = -(1f32).abs(); - let _ = -(1i32.abs()); - let _ = -(1f32.abs()); - - // Odd functions should not trigger an error - let _ = -1f64.asin(); - let _ = -1f64.asinh(); - let _ = -1f64.atan(); - let _ = -1f64.atanh(); - let _ = -1f64.cbrt(); - let _ = -1f64.fract(); - let _ = -1f64.round(); - let _ = -1f64.signum(); - let _ = -1f64.sin(); - let _ = -1f64.sinh(); - let _ = -1f64.tan(); - let _ = -1f64.tanh(); - let _ = -1f64.to_degrees(); - let _ = -1f64.to_radians(); - - // Chains containing any non-odd function should trigger (issue #5924) - let _ = -(1.0_f64.cos().cos()); - let _ = -(1.0_f64.cos().sin()); - let _ = -(1.0_f64.sin().cos()); - - // Chains of odd functions shouldn't trigger - let _ = -1f64.sin().sin(); - - let b = 3; - trip!(b * 8); -} diff --git a/src/tools/clippy/tests/ui/precedence.rs b/src/tools/clippy/tests/ui/precedence.rs deleted file mode 100644 index 00c18d92b5fb6..0000000000000 --- a/src/tools/clippy/tests/ui/precedence.rs +++ /dev/null @@ -1,60 +0,0 @@ -#![warn(clippy::precedence)] -#![allow(unused_must_use, clippy::no_effect, clippy::unnecessary_operation)] -#![allow(clippy::identity_op)] -#![allow(clippy::eq_op)] - -macro_rules! trip { - ($a:expr) => { - match $a & 0b1111_1111u8 { - 0 => println!("a is zero ({})", $a), - _ => println!("a is {}", $a), - } - }; -} - -fn main() { - 1 << 2 + 3; - 1 + 2 << 3; - 4 >> 1 + 1; - 1 + 3 >> 2; - 1 ^ 1 - 1; - 3 | 2 - 1; - 3 & 5 - 2; - -1i32.abs(); - -1f32.abs(); - - // These should not trigger an error - let _ = (-1i32).abs(); - let _ = (-1f32).abs(); - let _ = -(1i32).abs(); - let _ = -(1f32).abs(); - let _ = -(1i32.abs()); - let _ = -(1f32.abs()); - - // Odd functions should not trigger an error - let _ = -1f64.asin(); - let _ = -1f64.asinh(); - let _ = -1f64.atan(); - let _ = -1f64.atanh(); - let _ = -1f64.cbrt(); - let _ = -1f64.fract(); - let _ = -1f64.round(); - let _ = -1f64.signum(); - let _ = -1f64.sin(); - let _ = -1f64.sinh(); - let _ = -1f64.tan(); - let _ = -1f64.tanh(); - let _ = -1f64.to_degrees(); - let _ = -1f64.to_radians(); - - // Chains containing any non-odd function should trigger (issue #5924) - let _ = -1.0_f64.cos().cos(); - let _ = -1.0_f64.cos().sin(); - let _ = -1.0_f64.sin().cos(); - - // Chains of odd functions shouldn't trigger - let _ = -1f64.sin().sin(); - - let b = 3; - trip!(b * 8); -} diff --git a/src/tools/clippy/tests/ui/precedence.stderr b/src/tools/clippy/tests/ui/precedence.stderr deleted file mode 100644 index bd0cbccc787c8..0000000000000 --- a/src/tools/clippy/tests/ui/precedence.stderr +++ /dev/null @@ -1,77 +0,0 @@ -error: operator precedence can trip the unwary - --> $DIR/precedence.rs:16:5 - | -LL | 1 << 2 + 3; - | ^^^^^^^^^^ help: consider parenthesizing your expression: `1 << (2 + 3)` - | - = note: `-D clippy::precedence` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::precedence)]` - -error: operator precedence can trip the unwary - --> $DIR/precedence.rs:17:5 - | -LL | 1 + 2 << 3; - | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 2) << 3` - -error: operator precedence can trip the unwary - --> $DIR/precedence.rs:18:5 - | -LL | 4 >> 1 + 1; - | ^^^^^^^^^^ help: consider parenthesizing your expression: `4 >> (1 + 1)` - -error: operator precedence can trip the unwary - --> $DIR/precedence.rs:19:5 - | -LL | 1 + 3 >> 2; - | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 3) >> 2` - -error: operator precedence can trip the unwary - --> $DIR/precedence.rs:20:5 - | -LL | 1 ^ 1 - 1; - | ^^^^^^^^^ help: consider parenthesizing your expression: `1 ^ (1 - 1)` - -error: operator precedence can trip the unwary - --> $DIR/precedence.rs:21:5 - | -LL | 3 | 2 - 1; - | ^^^^^^^^^ help: consider parenthesizing your expression: `3 | (2 - 1)` - -error: operator precedence can trip the unwary - --> $DIR/precedence.rs:22:5 - | -LL | 3 & 5 - 2; - | ^^^^^^^^^ help: consider parenthesizing your expression: `3 & (5 - 2)` - -error: unary minus has lower precedence than method call - --> $DIR/precedence.rs:23:5 - | -LL | -1i32.abs(); - | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1i32.abs())` - -error: unary minus has lower precedence than method call - --> $DIR/precedence.rs:24:5 - | -LL | -1f32.abs(); - | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1f32.abs())` - -error: unary minus has lower precedence than method call - --> $DIR/precedence.rs:51:13 - | -LL | let _ = -1.0_f64.cos().cos(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1.0_f64.cos().cos())` - -error: unary minus has lower precedence than method call - --> $DIR/precedence.rs:52:13 - | -LL | let _ = -1.0_f64.cos().sin(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1.0_f64.cos().sin())` - -error: unary minus has lower precedence than method call - --> $DIR/precedence.rs:53:13 - | -LL | let _ = -1.0_f64.sin().cos(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1.0_f64.sin().cos())` - -error: aborting due to 12 previous errors - diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed index 4df9be2c21d9a..0fec4f46abb47 100644 --- a/src/tools/clippy/tests/ui/rename.fixed +++ b/src/tools/clippy/tests/ui/rename.fixed @@ -32,6 +32,7 @@ #![allow(invalid_reference_casting)] #![allow(suspicious_double_ref_op)] #![allow(invalid_nan_comparisons)] +#![allow(ambiguous_precedence)] #![allow(drop_bounds)] #![allow(dropping_copy_types)] #![allow(dropping_references)] @@ -103,6 +104,7 @@ #![warn(enum_intrinsics_non_enums)] #![warn(non_fmt_panics)] #![warn(named_arguments_used_positionally)] +#![warn(ambiguous_precedence)] #![warn(temporary_cstring_as_ptr)] #![warn(undropped_manually_drops)] #![warn(unknown_lints)] diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs index 940e60068e7b9..b0b26ff11001d 100644 --- a/src/tools/clippy/tests/ui/rename.rs +++ b/src/tools/clippy/tests/ui/rename.rs @@ -32,6 +32,7 @@ #![allow(invalid_reference_casting)] #![allow(suspicious_double_ref_op)] #![allow(invalid_nan_comparisons)] +#![allow(ambiguous_precedence)] #![allow(drop_bounds)] #![allow(dropping_copy_types)] #![allow(dropping_references)] @@ -103,6 +104,7 @@ #![warn(clippy::mem_discriminant_non_enum)] #![warn(clippy::panic_params)] #![warn(clippy::positional_named_format_parameters)] +#![warn(clippy::precedence)] #![warn(clippy::temporary_cstring_as_ptr)] #![warn(clippy::undropped_manually_drops)] #![warn(clippy::unknown_clippy_lints)] diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr index 30824e154b8bf..30b1181401b64 100644 --- a/src/tools/clippy/tests/ui/rename.stderr +++ b/src/tools/clippy/tests/ui/rename.stderr @@ -1,5 +1,5 @@ error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range` - --> $DIR/rename.rs:54:9 + --> $DIR/rename.rs:55:9 | LL | #![warn(clippy::almost_complete_letter_range)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` @@ -8,334 +8,340 @@ LL | #![warn(clippy::almost_complete_letter_range)] = help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]` error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names` - --> $DIR/rename.rs:55:9 + --> $DIR/rename.rs:56:9 | LL | #![warn(clippy::blacklisted_name)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names` error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:56:9 + --> $DIR/rename.rs:57:9 | LL | #![warn(clippy::block_in_if_condition_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:57:9 + --> $DIR/rename.rs:58:9 | LL | #![warn(clippy::block_in_if_condition_stmt)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::box_vec` has been renamed to `clippy::box_collection` - --> $DIR/rename.rs:58:9 + --> $DIR/rename.rs:59:9 | LL | #![warn(clippy::box_vec)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection` error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` - --> $DIR/rename.rs:59:9 + --> $DIR/rename.rs:60:9 | LL | #![warn(clippy::const_static_lifetime)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes` error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity` - --> $DIR/rename.rs:60:9 + --> $DIR/rename.rs:61:9 | LL | #![warn(clippy::cyclomatic_complexity)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity` error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq` - --> $DIR/rename.rs:61:9 + --> $DIR/rename.rs:62:9 | LL | #![warn(clippy::derive_hash_xor_eq)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq` error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods` - --> $DIR/rename.rs:62:9 + --> $DIR/rename.rs:63:9 | LL | #![warn(clippy::disallowed_method)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods` error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types` - --> $DIR/rename.rs:63:9 + --> $DIR/rename.rs:64:9 | LL | #![warn(clippy::disallowed_type)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types` error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression` - --> $DIR/rename.rs:64:9 + --> $DIR/rename.rs:65:9 | LL | #![warn(clippy::eval_order_dependence)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression` error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion` - --> $DIR/rename.rs:65:9 + --> $DIR/rename.rs:66:9 | LL | #![warn(clippy::identity_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion` error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok` - --> $DIR/rename.rs:66:9 + --> $DIR/rename.rs:67:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl` - --> $DIR/rename.rs:67:9 + --> $DIR/rename.rs:68:9 | LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl` error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl` - --> $DIR/rename.rs:68:9 + --> $DIR/rename.rs:69:9 | LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl` error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects` - --> $DIR/rename.rs:69:9 + --> $DIR/rename.rs:70:9 | LL | #![warn(clippy::integer_arithmetic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects` error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` - --> $DIR/rename.rs:70:9 + --> $DIR/rename.rs:71:9 | LL | #![warn(clippy::logic_bug)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr` error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` - --> $DIR/rename.rs:71:9 + --> $DIR/rename.rs:72:9 | LL | #![warn(clippy::new_without_default_derive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map` - --> $DIR/rename.rs:72:9 + --> $DIR/rename.rs:73:9 | LL | #![warn(clippy::option_and_then_some)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map` error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used` - --> $DIR/rename.rs:73:9 + --> $DIR/rename.rs:74:9 | LL | #![warn(clippy::option_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:74:9 + --> $DIR/rename.rs:75:9 | LL | #![warn(clippy::option_map_unwrap_or)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:75:9 + --> $DIR/rename.rs:76:9 | LL | #![warn(clippy::option_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used` - --> $DIR/rename.rs:76:9 + --> $DIR/rename.rs:77:9 | LL | #![warn(clippy::option_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow` - --> $DIR/rename.rs:77:9 + --> $DIR/rename.rs:78:9 | LL | #![warn(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow` error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used` - --> $DIR/rename.rs:78:9 + --> $DIR/rename.rs:79:9 | LL | #![warn(clippy::result_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:79:9 + --> $DIR/rename.rs:80:9 | LL | #![warn(clippy::result_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used` - --> $DIR/rename.rs:80:9 + --> $DIR/rename.rs:81:9 | LL | #![warn(clippy::result_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str` - --> $DIR/rename.rs:81:9 + --> $DIR/rename.rs:82:9 | LL | #![warn(clippy::single_char_push_str)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str` error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` - --> $DIR/rename.rs:82:9 + --> $DIR/rename.rs:83:9 | LL | #![warn(clippy::stutter)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl` - --> $DIR/rename.rs:83:9 + --> $DIR/rename.rs:84:9 | LL | #![warn(clippy::to_string_in_display)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl` error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default` - --> $DIR/rename.rs:84:9 + --> $DIR/rename.rs:85:9 | LL | #![warn(clippy::unwrap_or_else_default)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default` error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters` - --> $DIR/rename.rs:85:9 + --> $DIR/rename.rs:86:9 | LL | #![warn(clippy::zero_width_space)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting` - --> $DIR/rename.rs:86:9 + --> $DIR/rename.rs:87:9 | LL | #![warn(clippy::cast_ref_to_mut)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting` error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` - --> $DIR/rename.rs:87:9 + --> $DIR/rename.rs:88:9 | LL | #![warn(clippy::clone_double_ref)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op` error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons` - --> $DIR/rename.rs:88:9 + --> $DIR/rename.rs:89:9 | LL | #![warn(clippy::cmp_nan)] | ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons` error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` - --> $DIR/rename.rs:89:9 + --> $DIR/rename.rs:90:9 | LL | #![warn(clippy::drop_bounds)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types` - --> $DIR/rename.rs:90:9 + --> $DIR/rename.rs:91:9 | LL | #![warn(clippy::drop_copy)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types` error: lint `clippy::drop_ref` has been renamed to `dropping_references` - --> $DIR/rename.rs:91:9 + --> $DIR/rename.rs:92:9 | LL | #![warn(clippy::drop_ref)] | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references` error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks` - --> $DIR/rename.rs:92:9 + --> $DIR/rename.rs:93:9 | LL | #![warn(clippy::fn_null_check)] | ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:93:9 + --> $DIR/rename.rs:94:9 | LL | #![warn(clippy::for_loop_over_option)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:94:9 + --> $DIR/rename.rs:95:9 | LL | #![warn(clippy::for_loop_over_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:95:9 + --> $DIR/rename.rs:96:9 | LL | #![warn(clippy::for_loops_over_fallibles)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types` - --> $DIR/rename.rs:96:9 + --> $DIR/rename.rs:97:9 | LL | #![warn(clippy::forget_copy)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types` error: lint `clippy::forget_ref` has been renamed to `forgetting_references` - --> $DIR/rename.rs:97:9 + --> $DIR/rename.rs:98:9 | LL | #![warn(clippy::forget_ref)] | ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references` error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> $DIR/rename.rs:98:9 + --> $DIR/rename.rs:99:9 | LL | #![warn(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering` - --> $DIR/rename.rs:99:9 + --> $DIR/rename.rs:100:9 | LL | #![warn(clippy::invalid_atomic_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering` error: lint `clippy::invalid_ref` has been renamed to `invalid_value` - --> $DIR/rename.rs:100:9 + --> $DIR/rename.rs:101:9 | LL | #![warn(clippy::invalid_ref)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked` - --> $DIR/rename.rs:101:9 + --> $DIR/rename.rs:102:9 | LL | #![warn(clippy::invalid_utf8_in_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked` error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` - --> $DIR/rename.rs:102:9 + --> $DIR/rename.rs:103:9 | LL | #![warn(clippy::let_underscore_drop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop` error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` - --> $DIR/rename.rs:103:9 + --> $DIR/rename.rs:104:9 | LL | #![warn(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` - --> $DIR/rename.rs:104:9 + --> $DIR/rename.rs:105:9 | LL | #![warn(clippy::panic_params)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally` - --> $DIR/rename.rs:105:9 + --> $DIR/rename.rs:106:9 | LL | #![warn(clippy::positional_named_format_parameters)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally` +error: lint `clippy::precedence` has been renamed to `ambiguous_precedence` + --> $DIR/rename.rs:107:9 + | +LL | #![warn(clippy::precedence)] + | ^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_precedence` + error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr` - --> $DIR/rename.rs:106:9 + --> $DIR/rename.rs:108:9 | LL | #![warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr` error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops` - --> $DIR/rename.rs:107:9 + --> $DIR/rename.rs:109:9 | LL | #![warn(clippy::undropped_manually_drops)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> $DIR/rename.rs:108:9 + --> $DIR/rename.rs:110:9 | LL | #![warn(clippy::unknown_clippy_lints)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` error: lint `clippy::unused_label` has been renamed to `unused_labels` - --> $DIR/rename.rs:109:9 + --> $DIR/rename.rs:111:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` -error: aborting due to 56 previous errors +error: aborting due to 57 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.fixed b/src/tools/clippy/tests/ui/unnecessary_cast.fixed index 18dd53bf2b42c..b4f90214f944a 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_cast.fixed @@ -205,7 +205,7 @@ mod fixable { fn issue_9563() { let _: f64 = (-8.0_f64).exp(); - #[allow(clippy::precedence)] + #[allow(ambiguous_precedence)] let _: f64 = -8.0_f64.exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior } diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.rs b/src/tools/clippy/tests/ui/unnecessary_cast.rs index fcdd4c60ccd01..5fbba6e38fd8d 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast.rs +++ b/src/tools/clippy/tests/ui/unnecessary_cast.rs @@ -205,7 +205,7 @@ mod fixable { fn issue_9563() { let _: f64 = (-8.0 as f64).exp(); - #[allow(clippy::precedence)] + #[allow(ambiguous_precedence)] let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior } diff --git a/tests/rustdoc/const-generics/const-generics-docs.rs b/tests/rustdoc/const-generics/const-generics-docs.rs index 70a9518f05b40..3b0cc1f016af1 100644 --- a/tests/rustdoc/const-generics/const-generics-docs.rs +++ b/tests/rustdoc/const-generics/const-generics-docs.rs @@ -74,7 +74,7 @@ pub async fn b_sink(_: impl Trait) {} // @has foo/fn.concrete.html '//pre[@class="rust item-decl"]' \ // 'pub fn concrete() -> [u8; 22]' -pub fn concrete() -> [u8; 3 + std::mem::size_of::() << 1] { +pub fn concrete() -> [u8; (3 + std::mem::size_of::()) << 1] { Default::default() } diff --git a/tests/ui/consts/const-err-rpass.rs b/tests/ui/consts/const-err-rpass.rs index e7fa10a2a11a3..e597ca3fd7f23 100644 --- a/tests/ui/consts/const-err-rpass.rs +++ b/tests/ui/consts/const-err-rpass.rs @@ -9,7 +9,7 @@ const W: bool = Z <= 'B'; fn main() { - let _ = ((-1 as i8) << 8 - 1) as f32; + let _ = ((-1 as i8) << (8 - 1)) as f32; let _ = 0u8 as char; let _ = true > false; let _ = true >= false; diff --git a/tests/ui/lint/precedence.fixed b/tests/ui/lint/precedence.fixed new file mode 100644 index 0000000000000..face61f123e93 --- /dev/null +++ b/tests/ui/lint/precedence.fixed @@ -0,0 +1,49 @@ +// run-rustfix +// check-pass + +fn main() { + let _ = 1 << (2 + 3); + //~^ WARN operator precedence can trip the unwary + let _ = (1 + 2) << 3; + //~^ WARN operator precedence can trip the unwary + let _ = 4 >> (1 + 1); + //~^ WARN operator precedence can trip the unwary + let _ = (1 + 3) >> 2; + //~^ WARN operator precedence can trip the unwary + let _ = 1 ^ (1 - 1); + //~^ WARN operator precedence can trip the unwary + let _ = 3 | (2 - 1); + //~^ WARN operator precedence can trip the unwary + let _ = 3 & (5 - 2); + //~^ WARN operator precedence can trip the unwary + let _ = (1 + 2) << (3 + 1); + //~^ WARN operator precedence can trip the unwary + let _ = -(1i32.abs()); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -(1f32.abs()); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -(1f64.asin()); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -(1f64.asinh()); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -(1f64.tan()); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -(1f64.tanh()); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -(1.0_f64.cos().cos()); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -(1.0_f64.cos().sin()); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -(1.0_f64.sin().cos()); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -(1f64.sin().sin()); + //~^ WARN unary operator `-` has lower precedence than method call + + // These should not trigger an error + let _ = (-1i32).abs(); + let _ = (-1f32).abs(); + let _ = -(1i32).abs(); + let _ = -(1f32).abs(); + let _ = -(1i32.abs()); + let _ = -(1f32.abs()); +} diff --git a/tests/ui/lint/precedence.rs b/tests/ui/lint/precedence.rs new file mode 100644 index 0000000000000..c78a5db8d6e0a --- /dev/null +++ b/tests/ui/lint/precedence.rs @@ -0,0 +1,49 @@ +// run-rustfix +// check-pass + +fn main() { + let _ = 1 << 2 + 3; + //~^ WARN operator precedence can trip the unwary + let _ = 1 + 2 << 3; + //~^ WARN operator precedence can trip the unwary + let _ = 4 >> 1 + 1; + //~^ WARN operator precedence can trip the unwary + let _ = 1 + 3 >> 2; + //~^ WARN operator precedence can trip the unwary + let _ = 1 ^ 1 - 1; + //~^ WARN operator precedence can trip the unwary + let _ = 3 | 2 - 1; + //~^ WARN operator precedence can trip the unwary + let _ = 3 & 5 - 2; + //~^ WARN operator precedence can trip the unwary + let _ = 1 + 2 << 3 + 1; + //~^ WARN operator precedence can trip the unwary + let _ = -1i32.abs(); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -1f32.abs(); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -1f64.asin(); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -1f64.asinh(); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -1f64.tan(); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -1f64.tanh(); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -1.0_f64.cos().cos(); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -1.0_f64.cos().sin(); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -1.0_f64.sin().cos(); + //~^ WARN unary operator `-` has lower precedence than method call + let _ = -1f64.sin().sin(); + //~^ WARN unary operator `-` has lower precedence than method call + + // These should not trigger an error + let _ = (-1i32).abs(); + let _ = (-1f32).abs(); + let _ = -(1i32).abs(); + let _ = -(1f32).abs(); + let _ = -(1i32.abs()); + let _ = -(1f32.abs()); +} diff --git a/tests/ui/lint/precedence.stderr b/tests/ui/lint/precedence.stderr new file mode 100644 index 0000000000000..b2439d7e8951b --- /dev/null +++ b/tests/ui/lint/precedence.stderr @@ -0,0 +1,201 @@ +warning: operator precedence can trip the unwary + --> $DIR/precedence.rs:5:13 + | +LL | let _ = 1 << 2 + 3; + | ^^^^^^^^^^ + | + = note: `#[warn(ambiguous_precedence)]` on by default +help: consider adding parentheses to clarify your intent + | +LL | let _ = 1 << (2 + 3); + | + + + +warning: operator precedence can trip the unwary + --> $DIR/precedence.rs:7:13 + | +LL | let _ = 1 + 2 << 3; + | ^^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = (1 + 2) << 3; + | + + + +warning: operator precedence can trip the unwary + --> $DIR/precedence.rs:9:13 + | +LL | let _ = 4 >> 1 + 1; + | ^^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = 4 >> (1 + 1); + | + + + +warning: operator precedence can trip the unwary + --> $DIR/precedence.rs:11:13 + | +LL | let _ = 1 + 3 >> 2; + | ^^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = (1 + 3) >> 2; + | + + + +warning: operator precedence can trip the unwary + --> $DIR/precedence.rs:13:13 + | +LL | let _ = 1 ^ 1 - 1; + | ^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = 1 ^ (1 - 1); + | + + + +warning: operator precedence can trip the unwary + --> $DIR/precedence.rs:15:13 + | +LL | let _ = 3 | 2 - 1; + | ^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = 3 | (2 - 1); + | + + + +warning: operator precedence can trip the unwary + --> $DIR/precedence.rs:17:13 + | +LL | let _ = 3 & 5 - 2; + | ^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = 3 & (5 - 2); + | + + + +warning: operator precedence can trip the unwary + --> $DIR/precedence.rs:19:13 + | +LL | let _ = 1 + 2 << 3 + 1; + | ^^^^^^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = (1 + 2) << (3 + 1); + | + + + + + +warning: unary operator `-` has lower precedence than method call + --> $DIR/precedence.rs:21:13 + | +LL | let _ = -1i32.abs(); + | ^^^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = -(1i32.abs()); + | + + + +warning: unary operator `-` has lower precedence than method call + --> $DIR/precedence.rs:23:13 + | +LL | let _ = -1f32.abs(); + | ^^^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = -(1f32.abs()); + | + + + +warning: unary operator `-` has lower precedence than method call + --> $DIR/precedence.rs:25:13 + | +LL | let _ = -1f64.asin(); + | ^^^^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = -(1f64.asin()); + | + + + +warning: unary operator `-` has lower precedence than method call + --> $DIR/precedence.rs:27:13 + | +LL | let _ = -1f64.asinh(); + | ^^^^^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = -(1f64.asinh()); + | + + + +warning: unary operator `-` has lower precedence than method call + --> $DIR/precedence.rs:29:13 + | +LL | let _ = -1f64.tan(); + | ^^^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = -(1f64.tan()); + | + + + +warning: unary operator `-` has lower precedence than method call + --> $DIR/precedence.rs:31:13 + | +LL | let _ = -1f64.tanh(); + | ^^^^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = -(1f64.tanh()); + | + + + +warning: unary operator `-` has lower precedence than method call + --> $DIR/precedence.rs:33:13 + | +LL | let _ = -1.0_f64.cos().cos(); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = -(1.0_f64.cos().cos()); + | + + + +warning: unary operator `-` has lower precedence than method call + --> $DIR/precedence.rs:35:13 + | +LL | let _ = -1.0_f64.cos().sin(); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = -(1.0_f64.cos().sin()); + | + + + +warning: unary operator `-` has lower precedence than method call + --> $DIR/precedence.rs:37:13 + | +LL | let _ = -1.0_f64.sin().cos(); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = -(1.0_f64.sin().cos()); + | + + + +warning: unary operator `-` has lower precedence than method call + --> $DIR/precedence.rs:39:13 + | +LL | let _ = -1f64.sin().sin(); + | ^^^^^^^^^^^^^^^^^ + | +help: consider adding parentheses to clarify your intent + | +LL | let _ = -(1f64.sin().sin()); + | + + + +warning: 18 warnings emitted +