Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/expr_store/body.rs18
-rw-r--r--crates/hir-def/src/expr_store/lower.rs24
-rw-r--r--crates/hir-def/src/expr_store/pretty.rs2
-rw-r--r--crates/hir-def/src/expr_store/scope.rs2
-rw-r--r--crates/hir-ty/src/infer.rs2
-rw-r--r--crates/hir-ty/src/mir/lower.rs2
-rw-r--r--crates/hir-ty/src/tests.rs2
-rw-r--r--crates/hir-ty/src/tests/closure_captures.rs12
-rw-r--r--crates/hir/src/display.rs2
-rw-r--r--crates/hir/src/lib.rs12
-rw-r--r--crates/hir/src/semantics/source_to_def.rs2
-rw-r--r--crates/hir/src/source_analyzer.rs2
12 files changed, 50 insertions, 32 deletions
diff --git a/crates/hir-def/src/expr_store/body.rs b/crates/hir-def/src/expr_store/body.rs
index 3c7452507e..2fb47e59c5 100644
--- a/crates/hir-def/src/expr_store/body.rs
+++ b/crates/hir-def/src/expr_store/body.rs
@@ -2,6 +2,7 @@
//! consts.
use std::ops;
+use arrayvec::ArrayVec;
use hir_expand::{InFile, Lookup};
use span::Edition;
use syntax::ast;
@@ -28,7 +29,12 @@ pub struct Body {
/// If this `Body` is for the body of a constant, this will just be
/// empty.
pub params: Box<[PatId]>,
- pub self_param: Option<BindingId>,
+ /// 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>,
}
impl ops::Deref for Body {
@@ -122,6 +128,16 @@ 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()
+ }
+
pub fn pretty_print(
&self,
db: &dyn DefDatabase,
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs
index e683f06840..6060a5a234 100644
--- a/crates/hir-def/src/expr_store/lower.rs
+++ b/crates/hir-def/src/expr_store/lower.rs
@@ -8,6 +8,7 @@ mod path;
use std::{cell::OnceCell, mem};
+use arrayvec::ArrayVec;
use base_db::FxIndexSet;
use cfg::CfgOptions;
use either::Either;
@@ -81,7 +82,7 @@ pub(super) fn lower_body(
// even though they should be the same. Also, when the body comes from multiple expansions, their
// hygiene is different.
- let mut self_param = None;
+ let mut self_params = ArrayVec::new();
let mut source_map_self_param = None;
let mut params = vec![];
let mut collector = ExprCollector::new(db, module, current_file_id);
@@ -114,7 +115,7 @@ pub(super) fn lower_body(
BindingAnnotation::new(is_mutable, false),
hygiene,
);
- self_param = Some(binding_id);
+ self_params.push(binding_id);
source_map_self_param =
Some(collector.expander.in_file(AstPtr::new(&self_param_syn)));
}
@@ -124,7 +125,7 @@ pub(super) fn lower_body(
collector.with_expr_root(|collector| collector.missing_expr());
let (store, source_map) = collector.store.finish();
return (
- Body { store, params: params.into_boxed_slice(), self_param },
+ Body { store, params: params.into_boxed_slice(), self_params },
BodySourceMap { self_param: source_map_self_param, store: source_map },
);
}
@@ -142,7 +143,7 @@ pub(super) fn lower_body(
BindingAnnotation::new(is_mutable, false),
hygiene,
);
- self_param = Some(binding_id);
+ self_params.push(binding_id);
source_map_self_param = Some(collector.expander.in_file(AstPtr::new(&self_param_syn)));
}
@@ -166,7 +167,7 @@ pub(super) fn lower_body(
collector.with_expr_root(|collector| {
collector.collect(
- self_param,
+ &mut self_params,
&mut params,
body,
if is_async_fn {
@@ -186,7 +187,7 @@ pub(super) fn lower_body(
let (store, source_map) = collector.store.finish();
(
- Body { store, params: params.into_boxed_slice(), self_param },
+ Body { store, params: params.into_boxed_slice(), self_params },
BodySourceMap { self_param: source_map_self_param, store: source_map },
)
}
@@ -946,7 +947,7 @@ impl<'db> ExprCollector<'db> {
/// drop order are stable.
fn lower_coroutine_body_with_moved_arguments(
&mut self,
- self_param: Option<BindingId>,
+ self_params: &mut ArrayVec<BindingId, 2>,
params: &mut [PatId],
body: ExprId,
kind: CoroutineKind,
@@ -980,7 +981,7 @@ impl<'db> ExprCollector<'db> {
let mut statements = Vec::new();
- if let Some(self_param) = self_param {
+ if let Some(&self_param) = self_params.first() {
let Binding { ref name, mode, hygiene, .. } = self.store.bindings[self_param];
let name = name.clone();
let child_binding_id = self.alloc_binding(name.clone(), mode, hygiene);
@@ -997,6 +998,7 @@ impl<'db> ExprCollector<'db> {
initializer: Some(expr),
else_branch: None,
});
+ self_params.push(child_binding_id);
}
for param in params {
@@ -1098,7 +1100,7 @@ impl<'db> ExprCollector<'db> {
fn collect(
&mut self,
- self_param: Option<BindingId>,
+ self_params: &mut ArrayVec<BindingId, 2>,
params: &mut [PatId],
expr: Option<ast::Expr>,
awaitable: Awaitable,
@@ -1116,7 +1118,7 @@ impl<'db> ExprCollector<'db> {
(false, false) => unreachable!(),
};
this.lower_coroutine_body_with_moved_arguments(
- self_param,
+ self_params,
params,
body,
kind,
@@ -1593,7 +1595,7 @@ impl<'db> ExprCollector<'db> {
// It's important that this expr is allocated immediately before the closure.
// We rely on it for `coroutine_for_closure()`.
body = this.lower_coroutine_body_with_moved_arguments(
- None,
+ &mut ArrayVec::new(),
&mut args,
body,
kind,
diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs
index 5afd7f38a7..34cedbd728 100644
--- a/crates/hir-def/src/expr_store/pretty.rs
+++ b/crates/hir-def/src/expr_store/pretty.rs
@@ -92,7 +92,7 @@ pub fn print_body_hir(
};
if let DefWithBodyId::FunctionId(_) = owner {
p.buf.push('(');
- if let Some(self_param) = body.self_param {
+ if let Some(self_param) = body.self_param() {
p.print_binding(self_param);
p.buf.push_str(", ");
}
diff --git a/crates/hir-def/src/expr_store/scope.rs b/crates/hir-def/src/expr_store/scope.rs
index 5663b8155c..ddb8285137 100644
--- a/crates/hir-def/src/expr_store/scope.rs
+++ b/crates/hir-def/src/expr_store/scope.rs
@@ -147,7 +147,7 @@ impl ExprScopes {
),
};
let mut root = scopes.root_scope();
- if let Some(self_param) = body.self_param {
+ if let Some(self_param) = body.self_param() {
scopes.add_bindings(body, root, self_param, body.binding_hygiene(self_param));
}
scopes.add_params_bindings(body, root, &body.params);
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index b399a7e0ed..3ae3525baa 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -140,7 +140,7 @@ pub fn infer_query_with_inspect<'db>(
}
match def {
- DefWithBodyId::FunctionId(f) => ctx.collect_fn(f, body.self_param, &body.params),
+ DefWithBodyId::FunctionId(f) => ctx.collect_fn(f, body.self_param(), &body.params),
DefWithBodyId::ConstId(c) => ctx.collect_const(c, ConstSignature::of(db, c)),
DefWithBodyId::StaticId(s) => ctx.collect_static(s, StaticSignature::of(db, s)),
DefWithBodyId::VariantId(v) => {
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 763d52398b..3852db909e 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -2320,7 +2320,7 @@ pub fn mir_body_query<'db>(db: &'db dyn HirDatabase, def: InferBodyId) -> Result
let (store, root_expr, self_param, params) = match def {
InferBodyId::DefWithBodyId(def) => {
let body = Body::of(db, def);
- (&**body, body.root_expr(), body.self_param, &*body.params)
+ (&**body, body.root_expr(), body.self_param(), &*body.params)
}
InferBodyId::AnonConstId(def) => {
let loc = def.loc(db);
diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs
index 9e70f69bad..d259ce7963 100644
--- a/crates/hir-ty/src/tests.rs
+++ b/crates/hir-ty/src/tests.rs
@@ -514,7 +514,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
for (def, krate) in defs {
let (body, source_map) = Body::with_source_map(&db, def);
let infer = InferenceResult::of(&db, def);
- let self_param = body.self_param.map(|id| (id, source_map.self_param_syntax()));
+ let self_param = body.self_param().map(|id| (id, source_map.self_param_syntax()));
infer_def(infer, body, source_map, self_param, krate);
}
diff --git a/crates/hir-ty/src/tests/closure_captures.rs b/crates/hir-ty/src/tests/closure_captures.rs
index b01f44acbc..0a38635930 100644
--- a/crates/hir-ty/src/tests/closure_captures.rs
+++ b/crates/hir-ty/src/tests/closure_captures.rs
@@ -102,19 +102,19 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec
// FIXME: Deduplicate this with hir::Local::sources().
let captured_local = capture.captured_local();
- let local_text_range = match body.self_param.zip(source_map.self_param_syntax())
+ let local_text_range = if body.self_params.contains(&captured_local)
+ && let Some(source) = source_map.self_param_syntax()
{
- Some((param, source)) if param == captured_local => {
- format!("{:?}", text_range(db, source))
- }
- _ => source_map
+ format!("{:?}", text_range(db, source))
+ } else {
+ source_map
.patterns_for_binding(captured_local)
.iter()
.map(|&definition| {
text_range(db, source_map.pat_syntax(definition).unwrap())
})
.map(|it| format!("{it:?}"))
- .join(", "),
+ .join(", ")
};
let place = display_place(db, body, &capture.place, captured_local);
let capture_ty = capture
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index c87a175cee..a71851ea8c 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -204,7 +204,7 @@ fn write_function<'db>(f: &mut HirFormatter<'_, 'db>, func_id: FunctionId) -> Re
first = false;
}
- let pat_id = body.params[param.idx - body.self_param.is_some() as usize];
+ let pat_id = body.params[param.idx - body.self_param().is_some() as usize];
let pat_str = body.pretty_print_pat(db, func_id.into(), pat_id, true, f.edition());
f.write_str(&pat_str)?;
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 3f83d068bb..0423a8fc4f 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -3000,14 +3000,14 @@ impl<'db> Param<'db> {
Callee::Def(CallableDefId::FunctionId(it)) => {
let parent = DefWithBodyId::FunctionId(it);
let body = Body::of(db, parent);
- if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
+ if let Some(self_param) = body.self_param().filter(|_| self.idx == 0) {
Some(Local {
parent: parent.into(),
parent_infer: parent.into(),
binding_id: self_param,
})
} else if let Pat::Bind { id, .. } =
- &body[body.params[self.idx - body.self_param.is_some() as usize]]
+ &body[body.params[self.idx - body.self_param().is_some() as usize]]
{
Some(Local {
parent: parent.into(),
@@ -4466,8 +4466,8 @@ impl Local {
}
ExpressionStoreOwnerId::Body(def_with_body_id) => {
b = Body::with_source_map(db, def_with_body_id);
- if let Some((param, source)) = b.0.self_param.zip(b.1.self_param_syntax())
- && param == self.binding_id
+ if b.0.self_params.contains(&self.binding_id)
+ && let Some(source) = b.1.self_param_syntax()
{
let root = source.file_syntax(db);
return vec![LocalSource {
@@ -4507,8 +4507,8 @@ impl Local {
}
ExpressionStoreOwnerId::Body(def_with_body_id) => {
b = Body::with_source_map(db, def_with_body_id);
- if let Some((param, source)) = b.0.self_param.zip(b.1.self_param_syntax())
- && param == self.binding_id
+ if b.0.self_params.contains(&self.binding_id)
+ && let Some(source) = b.1.self_param_syntax()
{
let root = source.file_syntax(db);
return LocalSource {
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index 1d1acd7f8e..583b3e4bda 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -371,7 +371,7 @@ impl SourceToDefCtx<'_, '_> {
.as_expression_store_owner()?
.as_def_with_body()?;
let body = Body::of(self.db, container);
- Some((container, body.self_param?))
+ Some((container, body.self_param()?))
}
pub(super) fn label_to_def(
&mut self,
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 4029b004a7..cb3516ffdc 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -472,7 +472,7 @@ impl<'db> SourceAnalyzer<'db> {
) -> Option<Type<'db>> {
let binding = match self.body_or_sig.as_ref()? {
BodyOrSig::Sig { .. } | BodyOrSig::VariantFields { .. } => return None,
- BodyOrSig::Body { body, .. } => body.self_param?,
+ BodyOrSig::Body { body, .. } => body.self_param()?,
};
let ty = self.infer()?.binding_ty(binding);
Some(Type::new_with_resolver(db, &self.resolver, ty))