Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/expr_store/body.rs')
| -rw-r--r-- | crates/hir-def/src/expr_store/body.rs | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/crates/hir-def/src/expr_store/body.rs b/crates/hir-def/src/expr_store/body.rs index 01423d5109..5b254c5711 100644 --- a/crates/hir-def/src/expr_store/body.rs +++ b/crates/hir-def/src/expr_store/body.rs @@ -2,7 +2,6 @@ //! consts. use std::ops; -use arrayvec::ArrayVec; use hir_expand::{InFile, Lookup}; use span::Edition; use syntax::ast; @@ -18,6 +17,24 @@ use crate::{ src::HasSource, }; +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Param<Id> { + /// The id of the formal parameter. In analysis, you want to use this: it has a special status as a parameter, + /// while [`user_written`][Self::user_written] is just a local variable. + pub formal: Id, + /// The id that corresponds to the pattern the user wrote. In IDE, you usually want to use this. + /// + /// It will be different than [`formal`][Self::formal] for coroutine fns (async fn etc.), because we apply + /// a desugaring for those that copies the parameter into a local variable. + pub user_written: Id, +} + +impl<Id: Copy> Param<Id> { + pub(crate) fn new(id: Id) -> Self { + Self { formal: id, user_written: id } + } +} + /// The body of an item (function, const etc.). #[derive(Debug, Eq, PartialEq)] pub struct Body { @@ -28,13 +45,8 @@ pub struct Body { /// /// If this `Body` is for the body of a constant, this will just be /// empty. - pub params: Box<[PatId]>, - /// The first element, if it exists, is the real `self` binding. - /// - /// The second element is used for `async fn` (or `gen fn` etc.). These functions - /// have to put a `let self = self` inside the returned coroutine, and the second element - /// points at it. - pub self_params: ArrayVec<BindingId, 2>, + pub params: Box<[Param<PatId>]>, + pub self_param: Option<Param<BindingId>>, } impl ops::Deref for Body { @@ -128,14 +140,12 @@ impl Body { self.store.expr_roots().next_back().unwrap() } - pub fn self_param(&self) -> Option<BindingId> { - self.self_params.first().copied() - } - - /// `async fn` (or `gen fn` etc.), have to put a `let self = self` inside the returned coroutine. - /// This function returns it. - pub fn coroutine_self_binding(&self) -> Option<BindingId> { - self.self_params.get(1).copied() + /// Returns `true` if this is the formal or user-written self param. + #[inline] + pub fn is_any_self_param(&self, binding: BindingId) -> bool { + self.self_param.is_some_and(|self_param| { + self_param.formal == binding || self_param.user_written == binding + }) } pub fn pretty_print( |