Skip to main content

rustc_lint/
redundant_semicolon.rs

1use rustc_ast::{Block, StmtKind};
2use rustc_session::{declare_lint, declare_lint_pass};
3use rustc_span::Span;
4
5use crate::lints::{RedundantSemicolonsDiag, RedundantSemicolonsSuggestion};
6use crate::{EarlyContext, EarlyLintPass, LintContext};
7
8#[doc = r" The `redundant_semicolons` lint detects unnecessary trailing"]
#[doc = r" semicolons."]
#[doc = r""]
#[doc = r" ### Example"]
#[doc = r""]
#[doc = r" ```rust"]
#[doc = r" let _ = 123;;"]
#[doc = r" ```"]
#[doc = r""]
#[doc = r" {{produces}}"]
#[doc = r""]
#[doc = r" ### Explanation"]
#[doc = r""]
#[doc =
r" Extra semicolons are not needed, and may be removed to avoid confusion"]
#[doc = r" and visual clutter."]
pub static REDUNDANT_SEMICOLONS: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: "REDUNDANT_SEMICOLONS",
            default_level: ::rustc_lint_defs::Warn,
            desc: "detects unnecessary trailing semicolons",
            is_externally_loaded: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_lint! {
9    /// The `redundant_semicolons` lint detects unnecessary trailing
10    /// semicolons.
11    ///
12    /// ### Example
13    ///
14    /// ```rust
15    /// let _ = 123;;
16    /// ```
17    ///
18    /// {{produces}}
19    ///
20    /// ### Explanation
21    ///
22    /// Extra semicolons are not needed, and may be removed to avoid confusion
23    /// and visual clutter.
24    pub REDUNDANT_SEMICOLONS,
25    Warn,
26    "detects unnecessary trailing semicolons"
27}
28
29pub struct RedundantSemicolons;
#[automatically_derived]
impl ::core::marker::Copy for RedundantSemicolons { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for RedundantSemicolons { }
#[automatically_derived]
impl ::core::clone::Clone for RedundantSemicolons {
    #[inline]
    fn clone(&self) -> RedundantSemicolons { *self }
}
impl ::rustc_lint_defs::LintPass for RedundantSemicolons {
    fn name(&self) -> &'static str { "RedundantSemicolons" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([REDUNDANT_SEMICOLONS]))
    }
}
impl RedundantSemicolons {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([REDUNDANT_SEMICOLONS]))
    }
}declare_lint_pass!(RedundantSemicolons => [REDUNDANT_SEMICOLONS]);
30
31impl EarlyLintPass for RedundantSemicolons {
32    fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) {
33        let mut seq = None;
34        for stmt in block.stmts.iter() {
35            match (&stmt.kind, &mut seq) {
36                (StmtKind::Empty, None) => seq = Some((stmt.span, false)),
37                (StmtKind::Empty, Some(seq)) => *seq = (seq.0.to(stmt.span), true),
38                (_, seq) => maybe_lint_redundant_semis(cx, seq),
39            }
40        }
41        maybe_lint_redundant_semis(cx, &mut seq);
42    }
43}
44
45fn maybe_lint_redundant_semis(cx: &EarlyContext<'_>, seq: &mut Option<(Span, bool)>) {
46    if let Some((span, multiple)) = seq.take() {
47        if span == rustc_span::DUMMY_SP {
48            return;
49        }
50
51        // Ignore redundant semicolons inside macro expansion.(issue #142143)
52        let suggestion = if span.from_expansion() {
53            None
54        } else {
55            Some(RedundantSemicolonsSuggestion { multiple_semicolons: multiple, span })
56        };
57
58        cx.emit_span_lint(
59            REDUNDANT_SEMICOLONS,
60            span,
61            RedundantSemicolonsDiag { multiple, suggestion },
62        );
63    }
64}