selene_lib/lints/
must_use.rs1use crate::standard_library::{Field, FieldKind};
2
3use super::*;
4use std::convert::Infallible;
5
6pub struct MustUseLint;
7
8impl Lint for MustUseLint {
9 type Config = ();
10 type Error = Infallible;
11
12 const SEVERITY: Severity = Severity::Warning;
13 const LINT_TYPE: LintType = LintType::Correctness;
14
15 fn new(_: Self::Config) -> Result<Self, Self::Error> {
16 Ok(MustUseLint)
17 }
18
19 fn pass(
20 &self,
21 _: &Ast,
22 Context {
23 standard_library, ..
24 }: &Context,
25 AstContext { scope_manager, .. }: &AstContext,
26 ) -> Vec<Diagnostic> {
27 let mut diagnostics = Vec::new();
28
29 for (_, function_call_stmt) in scope_manager.function_calls.iter() {
30 let function_behavior =
31 match standard_library.find_global(&function_call_stmt.call_name_path) {
32 Some(Field {
33 field_kind: FieldKind::Function(function_behavior),
34 ..
35 }) => function_behavior,
36 _ => continue,
37 };
38
39 if !function_behavior.must_use {
40 continue;
41 }
42
43 diagnostics.push(Diagnostic::new(
44 "must_use",
45 format!(
46 "unused return value of `{}` must be used",
47 function_call_stmt.call_name_path.join(".")
49 ),
50 Label::new(function_call_stmt.call_prefix_range),
51 ));
52 }
53
54 diagnostics
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::{super::test_util::test_lint, *};
61
62 #[test]
63 fn test_must_use() {
64 test_lint(MustUseLint::new(()).unwrap(), "must_use", "must_use");
65 }
66}