Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/closure/analysis.rs')
-rw-r--r--crates/hir-ty/src/infer/closure/analysis.rs104
1 files changed, 78 insertions, 26 deletions
diff --git a/crates/hir-ty/src/infer/closure/analysis.rs b/crates/hir-ty/src/infer/closure/analysis.rs
index 5a3eba1a71..ce0ccfe82f 100644
--- a/crates/hir-ty/src/infer/closure/analysis.rs
+++ b/crates/hir-ty/src/infer/closure/analysis.rs
@@ -4,14 +4,15 @@ use std::{cmp, mem};
use base_db::Crate;
use hir_def::{
- DefWithBodyId, FieldId, HasModule, VariantId,
- expr_store::path::Path,
+ ExpressionStoreOwnerId, FieldId, HasModule, VariantId,
+ expr_store::{Body, ExpressionStore, path::Path},
hir::{
Array, AsmOperand, BinaryOp, BindingId, CaptureBy, Expr, ExprId, ExprOrPatId, Pat, PatId,
RecordSpread, Statement, UnaryOp,
},
item_tree::FieldsShape,
resolver::ValueNs,
+ signatures::VariantFields,
};
use rustc_ast_ir::Mutability;
use rustc_hash::{FxHashMap, FxHashSet};
@@ -179,9 +180,26 @@ impl CapturedItem {
}
/// Converts the place to a name that can be inserted into source code.
- pub fn place_to_name(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String {
- let body = db.body(owner);
- let mut result = body[self.place.local].name.as_str().to_owned();
+ pub fn place_to_name(&self, owner: ExpressionStoreOwnerId, db: &dyn HirDatabase) -> String {
+ let krate = owner.krate(db);
+ let edition = krate.data(db).edition;
+ let mut result = match owner {
+ ExpressionStoreOwnerId::Signature(generic_def_id) => {
+ ExpressionStore::of(db, generic_def_id.into())[self.place.local]
+ .name
+ .display(db, edition)
+ .to_string()
+ }
+ ExpressionStoreOwnerId::Body(def_with_body_id) => Body::of(db, def_with_body_id)
+ [self.place.local]
+ .name
+ .display(db, edition)
+ .to_string(),
+ ExpressionStoreOwnerId::VariantFields(variant_id) => {
+ let fields = VariantFields::of(db, variant_id);
+ fields.store[self.place.local].name.display(db, edition).to_string()
+ }
+ };
for proj in &self.place.projections {
match proj {
HirPlaceProjection::Deref => {}
@@ -213,11 +231,30 @@ impl CapturedItem {
result
}
- pub fn display_place_source_code(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String {
- let body = db.body(owner);
+ pub fn display_place_source_code(
+ &self,
+ owner: ExpressionStoreOwnerId,
+ db: &dyn HirDatabase,
+ ) -> String {
let krate = owner.krate(db);
let edition = krate.data(db).edition;
- let mut result = body[self.place.local].name.display(db, edition).to_string();
+ let mut result = match owner {
+ ExpressionStoreOwnerId::Signature(generic_def_id) => {
+ ExpressionStore::of(db, generic_def_id.into())[self.place.local]
+ .name
+ .display(db, edition)
+ .to_string()
+ }
+ ExpressionStoreOwnerId::Body(def_with_body_id) => Body::of(db, def_with_body_id)
+ [self.place.local]
+ .name
+ .display(db, edition)
+ .to_string(),
+ ExpressionStoreOwnerId::VariantFields(variant_id) => {
+ let fields = VariantFields::of(db, variant_id);
+ fields.store[self.place.local].name.display(db, edition).to_string()
+ }
+ };
for proj in &self.place.projections {
match proj {
// In source code autoderef kicks in.
@@ -258,11 +295,26 @@ impl CapturedItem {
result
}
- pub fn display_place(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String {
- let body = db.body(owner);
+ pub fn display_place(&self, owner: ExpressionStoreOwnerId, db: &dyn HirDatabase) -> String {
let krate = owner.krate(db);
let edition = krate.data(db).edition;
- let mut result = body[self.place.local].name.display(db, edition).to_string();
+ let mut result = match owner {
+ ExpressionStoreOwnerId::Signature(generic_def_id) => {
+ ExpressionStore::of(db, generic_def_id.into())[self.place.local]
+ .name
+ .display(db, edition)
+ .to_string()
+ }
+ ExpressionStoreOwnerId::Body(def_with_body_id) => Body::of(db, def_with_body_id)
+ [self.place.local]
+ .name
+ .display(db, edition)
+ .to_string(),
+ ExpressionStoreOwnerId::VariantFields(variant_id) => {
+ let fields = VariantFields::of(db, variant_id);
+ fields.store[self.place.local].name.display(db, edition).to_string()
+ }
+ };
let mut field_need_paren = false;
for proj in &self.place.projections {
match proj {
@@ -346,7 +398,7 @@ impl<'db> InferenceContext<'_, 'db> {
if path.type_anchor().is_some() {
return None;
}
- let hygiene = self.body.expr_or_pat_path_hygiene(id);
+ let hygiene = self.store.expr_or_pat_path_hygiene(id);
self.resolver.resolve_path_in_value_ns_fully(self.db, path, hygiene).and_then(|result| {
match result {
ValueNs::LocalBinding(binding) => {
@@ -365,7 +417,7 @@ impl<'db> InferenceContext<'_, 'db> {
/// Changes `current_capture_span_stack` to contain the stack of spans for this expr.
fn place_of_expr_without_adjust(&mut self, tgt_expr: ExprId) -> Option<HirPlace> {
self.current_capture_span_stack.clear();
- match &self.body[tgt_expr] {
+ match &self.store[tgt_expr] {
Expr::Path(p) => {
let resolver_guard =
self.resolver.update_to_inner_scope(self.db, self.owner, tgt_expr);
@@ -416,7 +468,7 @@ impl<'db> InferenceContext<'_, 'db> {
let mut actual_truncate_to = 0;
for &span in &*span_stack {
actual_truncate_to += 1;
- if !span.is_ref_span(self.body) {
+ if !span.is_ref_span(self.store) {
remained -= 1;
if remained == 0 {
break;
@@ -424,7 +476,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
}
if actual_truncate_to < span_stack.len()
- && span_stack[actual_truncate_to].is_ref_span(self.body)
+ && span_stack[actual_truncate_to].is_ref_span(self.store)
{
// Include the ref operator if there is one, we will fix it later (in `strip_captures_ref_span()`) if it's incorrect.
actual_truncate_to += 1;
@@ -533,7 +585,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
fn walk_expr_without_adjust(&mut self, tgt_expr: ExprId) {
- match &self.body[tgt_expr] {
+ match &self.store[tgt_expr] {
Expr::OffsetOf(_) => (),
Expr::InlineAsm(e) => e.operands.iter().for_each(|(_, op)| match op {
AsmOperand::In { expr, .. }
@@ -733,7 +785,7 @@ impl<'db> InferenceContext<'_, 'db> {
self.consume_with_pat(rhs_place, target);
self.inside_assignment = false;
}
- None => self.body.walk_pats(target, &mut |pat| match &self.body[pat] {
+ None => self.store.walk_pats(target, &mut |pat| match &self.store[pat] {
Pat::Path(path) => self.mutate_path_pat(path, pat),
&Pat::Expr(expr) => {
let place = self.place_of_expr(expr);
@@ -775,7 +827,7 @@ impl<'db> InferenceContext<'_, 'db> {
update_result: &mut impl FnMut(CaptureKind),
mut for_mut: BorrowKind,
) {
- match &self.body[p] {
+ match &self.store[p] {
Pat::Ref { .. }
| Pat::Box { .. }
| Pat::Missing
@@ -819,13 +871,13 @@ impl<'db> InferenceContext<'_, 'db> {
if self.result.pat_adjustments.get(&p).is_some_and(|it| !it.is_empty()) {
for_mut = BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture };
}
- self.body.walk_pats_shallow(p, |p| self.walk_pat_inner(p, update_result, for_mut));
+ self.store.walk_pats_shallow(p, |p| self.walk_pat_inner(p, update_result, for_mut));
}
fn is_upvar(&self, place: &HirPlace) -> bool {
if let Some(c) = self.current_closure {
let InternedClosure(_, root) = self.db.lookup_intern_closure(c);
- return self.body.is_binding_upvar(place.local, root);
+ return self.store.is_binding_upvar(place.local, root);
}
false
}
@@ -858,7 +910,7 @@ impl<'db> InferenceContext<'_, 'db> {
if ty.is_raw_ptr() || ty.is_union() {
capture.kind = CaptureKind::ByRef(BorrowKind::Shared);
self.truncate_capture_spans(capture, 0);
- capture.place.projections.truncate(0);
+ capture.place.projections.clear();
continue;
}
for (i, p) in capture.place.projections.iter().enumerate() {
@@ -866,7 +918,7 @@ impl<'db> InferenceContext<'_, 'db> {
&self.table.infer_ctxt,
self.table.param_env,
ty,
- self.owner.module(self.db).krate(self.db),
+ self.owner.krate(self.db),
);
if ty.is_raw_ptr() || ty.is_union() {
capture.kind = CaptureKind::ByRef(BorrowKind::Shared);
@@ -938,7 +990,7 @@ impl<'db> InferenceContext<'_, 'db> {
self.current_capture_span_stack
.extend((0..adjustments_count).map(|_| MirSpan::PatId(tgt_pat)));
'reset_span_stack: {
- match &self.body[tgt_pat] {
+ match &self.store[tgt_pat] {
Pat::Missing | Pat::Wild => (),
Pat::Tuple { args, ellipsis } => {
let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize));
@@ -1089,7 +1141,7 @@ impl<'db> InferenceContext<'_, 'db> {
fn analyze_closure(&mut self, closure: InternedClosureId) -> FnTrait {
let InternedClosure(_, root) = self.db.lookup_intern_closure(closure);
self.current_closure = Some(closure);
- let Expr::Closure { body, capture_by, .. } = &self.body[root] else {
+ let Expr::Closure { body, capture_by, .. } = &self.store[root] else {
unreachable!("Closure expression id is always closure");
};
self.consume_expr(*body);
@@ -1133,7 +1185,7 @@ impl<'db> InferenceContext<'_, 'db> {
for capture in &mut captures {
if matches!(capture.kind, CaptureKind::ByValue) {
for span_stack in &mut capture.span_stacks {
- if span_stack[span_stack.len() - 1].is_ref_span(self.body) {
+ if span_stack[span_stack.len() - 1].is_ref_span(self.store) {
span_stack.truncate(span_stack.len() - 1);
}
}
@@ -1149,7 +1201,7 @@ impl<'db> InferenceContext<'_, 'db> {
let kind = self.analyze_closure(closure);
for (derefed_callee, callee_ty, params, expr) in exprs {
- if let &Expr::Call { callee, .. } = &self.body[expr] {
+ if let &Expr::Call { callee, .. } = &self.store[expr] {
let mut adjustments =
self.result.expr_adjustments.remove(&callee).unwrap_or_default().into_vec();
self.write_fn_trait_method_resolution(