forge_lint/sol/analysis/
types.rs1use solar::sema::{
4 Gcx, Ty,
5 hir::{self, ContractId, Expr, TypeKind, VariableId},
6 ty::TyKind,
7};
8
9pub fn is_address_type(hir: &hir::Hir<'_>, vid: VariableId) -> bool {
11 matches!(hir.variable(vid).ty.kind, TypeKind::Elementary(hir::ElementaryType::Address(_)))
12}
13
14pub fn is_elementary(hir: &hir::Hir<'_>, id: VariableId, abi: &str) -> bool {
16 matches!(&hir.variable(id).ty.kind, TypeKind::Elementary(ty) if ty.to_abi_str() == abi)
17}
18
19pub fn ty_is_address(ty: Ty<'_>) -> bool {
21 ty.peel_refs().is_address()
22}
23
24pub fn ty_contract_id(ty: Ty<'_>) -> Option<ContractId> {
26 match ty.peel_refs().kind {
27 TyKind::Contract(id) => Some(id),
28 TyKind::Type(ty) => ty_contract_id(ty),
29 _ => None,
30 }
31}
32
33pub fn expr_is_address<'gcx>(gcx: Gcx<'gcx>, expr: &Expr<'gcx>) -> bool {
35 gcx.type_of_expr(expr.peel_parens().id).is_some_and(ty_is_address)
36}
37
38pub fn receiver_contract_id<'gcx>(gcx: Gcx<'gcx>, recv: &Expr<'gcx>) -> Option<ContractId> {
40 gcx.type_of_expr(recv.peel_parens().id).and_then(ty_contract_id)
41}
42
43pub fn unique<T>(mut iter: impl Iterator<Item = T>) -> Option<T> {
45 let first = iter.next()?;
46 iter.next().is_none().then_some(first)
47}