https://gcc.gnu.org/g:b9ea11257cd54f33df81776d418dd569542526c5

commit r17-4089-gb9ea11257cd54f33df81776d418dd569542526c5
Author: Lucas Ly Ba <[email protected]>
Date:   Sat Jun 27 23:45:25 2026 +0200

    gccrs: add double negations lint
    
    Warn on a double arithmetic negation such as `- -x`, which is likely a
    mistake (Rust has no `--` operator).
    
    gcc/rust/ChangeLog:
    
            * checks/lints/unused/rust-unused-checker.cc (UnusedChecker::visit):
            New.
            * checks/lints/unused/rust-unused-checker.h (UnusedChecker::visit):
            New.
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/double-negations_0.rs: New test.
    
    Signed-off-by: Lucas Ly Ba <[email protected]>

Diff:
---
 .../checks/lints/unused/rust-unused-checker.cc     | 31 ++++++++++++++++++++++
 gcc/rust/checks/lints/unused/rust-unused-checker.h |  1 +
 gcc/testsuite/rust/compile/double-negations_0.rs   | 17 ++++++++++++
 3 files changed, 49 insertions(+)

diff --git a/gcc/rust/checks/lints/unused/rust-unused-checker.cc 
b/gcc/rust/checks/lints/unused/rust-unused-checker.cc
index 553a2f71ed80..1c128f5197b4 100644
--- a/gcc/rust/checks/lints/unused/rust-unused-checker.cc
+++ b/gcc/rust/checks/lints/unused/rust-unused-checker.cc
@@ -378,5 +378,36 @@ UnusedChecker::visit (HIR::BorrowExpr &expr)
   walk (expr);
 }
 
+namespace {
+// Probe whether an expression is itself an arithmetic negation, without
+// recursing (so it only inspects the node it is dispatched on). Used to detect
+// `- -x` for the double_negations lint, since gccrs builds with -fno-rtti and
+// HIR has no down-cast helper.
+class NegationProbe : public HIR::HIRFullVisitorBase
+{
+public:
+  bool is_negation = false;
+  using HIR::HIRFullVisitorBase::visit;
+  void visit (HIR::NegationExpr &expr) override
+  {
+    is_negation = expr.get_expr_type () == HIR::NegationExpr::ExprType::NEGATE;
+  }
+};
+} // namespace
+
+void
+UnusedChecker::visit (HIR::NegationExpr &expr)
+{
+  if (expr.get_expr_type () == HIR::NegationExpr::ExprType::NEGATE)
+    {
+      NegationProbe probe;
+      expr.get_expr ().accept_vis (probe);
+      if (probe.is_negation)
+       rust_warning_at (expr.get_locus (), OPT_Wunused,
+                        "use of a double negation");
+    }
+  walk (expr);
+}
+
 } // namespace Analysis
 } // namespace Rust
diff --git a/gcc/rust/checks/lints/unused/rust-unused-checker.h 
b/gcc/rust/checks/lints/unused/rust-unused-checker.h
index 161f59b8a662..659087a5776a 100644
--- a/gcc/rust/checks/lints/unused/rust-unused-checker.h
+++ b/gcc/rust/checks/lints/unused/rust-unused-checker.h
@@ -53,6 +53,7 @@ private:
   virtual void visit (HIR::ExternBlock &block) override;
   virtual void visit (HIR::LetStmt &stmt) override;
   virtual void visit (HIR::BorrowExpr &expr) override;
+  virtual void visit (HIR::NegationExpr &expr) override;
   virtual void visit_loop_label (HIR::LoopLabel &label) override;
 };
 } // namespace Analysis
diff --git a/gcc/testsuite/rust/compile/double-negations_0.rs 
b/gcc/testsuite/rust/compile/double-negations_0.rs
new file mode 100644
index 000000000000..47854e963545
--- /dev/null
+++ b/gcc/testsuite/rust/compile/double-negations_0.rs
@@ -0,0 +1,17 @@
+// { dg-additional-options "-frust-unused-check-2.0" }
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "neg"]
+pub trait Neg {
+    type Output;
+    fn neg(self) -> Self::Output;
+}
+
+pub fn f(x: i32) -> i32 {
+    - -x
+// { dg-warning "double negation" "" { target *-*-* } .-1 }
+}

Reply via email to