| use rustc_hir as hir; | 
 | use rustc_session::{declare_lint, declare_lint_pass}; | 
 |  | 
 | use crate::lints::UnitBindingsDiag; | 
 | use crate::{LateLintPass, LintContext}; | 
 |  | 
 | declare_lint! { | 
 |     /// The `unit_bindings` lint detects cases where bindings are useless because they have | 
 |     /// the unit type `()` as their inferred type. The lint is suppressed if the user explicitly | 
 |     /// annotates the let binding with the unit type `()`, or if the let binding uses an underscore | 
 |     /// wildcard pattern, i.e. `let _ = expr`, or if the binding is produced from macro expansions. | 
 |     /// | 
 |     /// ### Example | 
 |     /// | 
 |     /// ```rust,compile_fail | 
 |     /// #![deny(unit_bindings)] | 
 |     /// | 
 |     /// fn foo() { | 
 |     ///     println!("do work"); | 
 |     /// } | 
 |     /// | 
 |     /// pub fn main() { | 
 |     ///     let x = foo(); // useless binding | 
 |     /// } | 
 |     /// ``` | 
 |     /// | 
 |     /// {{produces}} | 
 |     /// | 
 |     /// ### Explanation | 
 |     /// | 
 |     /// Creating a local binding with the unit type `()` does not do much and can be a sign of a | 
 |     /// user error, such as in this example: | 
 |     /// | 
 |     /// ```rust,no_run | 
 |     /// fn main() { | 
 |     ///     let mut x = [1, 2, 3]; | 
 |     ///     x[0] = 5; | 
 |     ///     let y = x.sort(); // useless binding as `sort` returns `()` and not the sorted array. | 
 |     ///     println!("{:?}", y); // prints "()" | 
 |     /// } | 
 |     /// ``` | 
 |     pub UNIT_BINDINGS, | 
 |     Allow, | 
 |     "binding is useless because it has the unit `()` type" | 
 | } | 
 |  | 
 | declare_lint_pass!(UnitBindings => [UNIT_BINDINGS]); | 
 |  | 
 | impl<'tcx> LateLintPass<'tcx> for UnitBindings { | 
 |     fn check_local(&mut self, cx: &crate::LateContext<'tcx>, local: &'tcx hir::LetStmt<'tcx>) { | 
 |         // Suppress warning if user: | 
 |         // - explicitly ascribes a type to the pattern | 
 |         // - explicitly wrote `let pat = ();` | 
 |         // - explicitly wrote `let () = init;`. | 
 |         if !local.span.from_expansion() | 
 |             && let Some(tyck_results) = cx.maybe_typeck_results() | 
 |             && let Some(init) = local.init | 
 |             && let init_ty = tyck_results.expr_ty(init) | 
 |             && let local_ty = tyck_results.node_type(local.hir_id) | 
 |             && init_ty == cx.tcx.types.unit | 
 |             && local_ty == cx.tcx.types.unit | 
 |             && local.ty.is_none() | 
 |             && !matches!(init.kind, hir::ExprKind::Tup([])) | 
 |             && !matches!(local.pat.kind, hir::PatKind::Tuple([], ..)) | 
 |         { | 
 |             cx.emit_span_lint( | 
 |                 UNIT_BINDINGS, | 
 |                 local.span, | 
 |                 UnitBindingsDiag { label: local.pat.span }, | 
 |             ); | 
 |         } | 
 |     } | 
 | } |