mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-31 04:57:19 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			74 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			74 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| 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 },
 | |
|             );
 | |
|         }
 | |
|     }
 | |
| }
 | 
