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.rs42
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(