1use syn::visit::Visit;
6use syn::{Block, FnArg, ReturnType, Signature, Type};
7
8use crate::io_call_finder::IoCallFinder;
9use crate::unsafe_finder::UnsafeFinder;
10
11pub struct FunctionPurity;
12
13impl FunctionPurity {
14 pub fn has_mut_param(sig: &Signature) -> bool {
15 sig.inputs.iter().any(|arg| match arg {
16 FnArg::Receiver(recv) => recv.reference.is_some() && recv.mutability.is_some(),
17 FnArg::Typed(pat_type) => Self::has_mut_in_type(&pat_type.ty),
18 })
19 }
20
21 #[allow(clippy::only_used_in_recursion)]
22 fn has_mut_in_type(ty: &Type) -> bool {
23 match ty {
24 Type::Reference(reference) => reference.mutability.is_some(),
25 Type::Paren(inner) => Self::has_mut_in_type(&inner.elem),
26 _ => false,
27 }
28 }
29
30 pub fn is_unit_return(sig: &Signature) -> bool {
31 match &sig.output {
32 ReturnType::Default => true,
33 ReturnType::Type(_, ty) => {
34 if let Type::Tuple(tuple) = ty.as_ref() {
35 tuple.elems.is_empty()
36 } else {
37 false
38 }
39 }
40 }
41 }
42
43 pub fn has_unsafe_block(block: &Block) -> bool {
44 let mut finder = UnsafeFinder::new();
45 finder.visit_block(block);
46 finder.found
47 }
48
49 pub fn has_io_call(block: &Block) -> bool {
50 let mut finder = IoCallFinder::new();
51 finder.visit_block(block);
52 finder.found
53 }
54}