mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-04 14:07:36 +00:00
73 lines
2.4 KiB
Rust
73 lines
2.4 KiB
Rust
![]() |
use crate::lints::UnitBindingsDiag;
|
||
|
use crate::{LateLintPass, LintContext};
|
||
|
use rustc_hir as hir;
|
||
|
use rustc_middle::ty::Ty;
|
||
|
|
||
|
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::Local<'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 == Ty::new_unit(cx.tcx)
|
||
|
&& local_ty == Ty::new_unit(cx.tcx)
|
||
|
&& local.ty.is_none()
|
||
|
&& !matches!(init.kind, hir::ExprKind::Tup([]))
|
||
|
&& !matches!(local.pat.kind, hir::PatKind::Tuple([], ..))
|
||
|
{
|
||
|
cx.emit_spanned_lint(
|
||
|
UNIT_BINDINGS,
|
||
|
local.span,
|
||
|
UnitBindingsDiag { label: local.pat.span },
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|