1 //! This module provides a simplified abstraction for working with
2 //! code blocks identified by their integer `NodeId`. In particular,
3 //! it captures a common set of attributes that all "function-like
4 //! things" (represented by `FnLike` instances) share. For example,
5 //! all `FnLike` instances have a type signature (be it explicit or
6 //! inferred). And all `FnLike` instances have a body, i.e., the code
7 //! that is run when the function-like thing it represents is invoked.
9 //! With the above abstraction in place, one can treat the program
10 //! text as a collection of blocks of code (and most such blocks are
11 //! nested within a uniquely determined `FnLike`), and users can ask
12 //! for the `Code` associated with a particular NodeId.
15 use rustc_hir::intravisit::FnKind;
18 /// An FnLikeNode is a Node that is like a fn, in that it has a decl
19 /// and a body (as well as a NodeId, a span, etc).
21 /// More specifically, it is one of either:
23 /// - A function item,
24 /// - A closure expr (i.e., an ExprKind::Closure), or
25 /// - The default implementation for a trait method.
27 /// To construct one, use the `Code::from_node` function.
28 #[derive(Copy, Clone, Debug)]
29 pub struct FnLikeNode<'a> {
33 impl<'a> FnLikeNode<'a> {
34 /// Attempts to construct a FnLikeNode from presumed FnLike node input.
35 pub fn from_node(node: Node<'_>) -> Option<FnLikeNode<'_>> {
36 let fn_like = match node {
37 Node::Item(item) => matches!(item.kind, hir::ItemKind::Fn(..)),
38 Node::TraitItem(tm) => {
39 matches!(tm.kind, hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)))
41 Node::ImplItem(it) => matches!(it.kind, hir::ImplItemKind::Fn(..)),
42 Node::Expr(e) => matches!(e.kind, hir::ExprKind::Closure(..)),
45 fn_like.then_some(FnLikeNode { node })
48 pub fn constness(self) -> hir::Constness {
49 self.kind().header().map_or(hir::Constness::NotConst, |header| header.constness)
52 pub fn asyncness(self) -> hir::IsAsync {
53 self.kind().header().map_or(hir::IsAsync::NotAsync, |header| header.asyncness)
56 pub fn kind(self) -> FnKind<'a> {
58 Node::Item(i) => match i.kind {
59 hir::ItemKind::Fn(ref sig, ref generics, _) => {
60 FnKind::ItemFn(i.ident, generics, sig.header, &i.vis)
62 _ => bug!("item FnLikeNode that is not fn-like"),
64 Node::TraitItem(ti) => match ti.kind {
65 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(_)) => {
66 FnKind::Method(ti.ident, sig, None)
68 _ => bug!("trait method FnLikeNode that is not fn-like"),
70 Node::ImplItem(ii) => match ii.kind {
71 hir::ImplItemKind::Fn(ref sig, _) => FnKind::Method(ii.ident, sig, Some(&ii.vis)),
72 _ => bug!("impl method FnLikeNode that is not fn-like"),
74 Node::Expr(e) => match e.kind {
75 hir::ExprKind::Closure(..) => FnKind::Closure,
76 _ => bug!("expr FnLikeNode that is not fn-like"),
78 _ => bug!("other FnLikeNode that is not fn-like"),