Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/closure.rs')
| -rw-r--r-- | crates/hir-ty/src/infer/closure.rs | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index e7eb967c04..346c7f6df6 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -4,6 +4,7 @@ use std::{cmp, collections::HashMap, convert::Infallible, mem}; use chalk_ir::{cast::Cast, AliasEq, AliasTy, FnSubst, Mutability, TyKind, WhereClause}; use hir_def::{ + data::adt::VariantData, hir::{ Array, BinaryOp, BindingAnnotation, BindingId, CaptureBy, Expr, ExprId, Pat, PatId, Statement, UnaryOp, @@ -18,6 +19,7 @@ use smallvec::SmallVec; use stdx::never; use crate::{ + db::HirDatabase, mir::{BorrowKind, MirSpan, ProjectionElem}, static_lifetime, to_chalk_trait_id, traits::FnTrait, @@ -146,13 +148,81 @@ pub(crate) enum CaptureKind { } #[derive(Debug, Clone, PartialEq, Eq)] -pub(crate) struct CapturedItem { +pub struct CapturedItem { pub(crate) place: HirPlace, pub(crate) kind: CaptureKind, pub(crate) span: MirSpan, pub(crate) ty: Ty, } +impl CapturedItem { + pub fn display_kind(&self) -> &'static str { + match self.kind { + CaptureKind::ByRef(k) => match k { + BorrowKind::Shared => "immutable borrow", + BorrowKind::Shallow => { + never!("shallow borrow should not happen in closure captures"); + "shallow borrow" + }, + BorrowKind::Unique => "unique immutable borrow ([read more](https://doc.rust-lang.org/stable/reference/types/closure.html#unique-immutable-borrows-in-captures))", + BorrowKind::Mut { .. } => "mutable borrow", + }, + CaptureKind::ByValue => "move", + } + } + + pub fn display_place(&self, owner: ClosureId, db: &dyn HirDatabase) -> String { + let owner = db.lookup_intern_closure(owner.into()).0; + let body = db.body(owner); + let mut result = body[self.place.local].name.to_string(); + let mut field_need_paren = false; + for proj in &self.place.projections { + match proj { + ProjectionElem::Deref => { + result = format!("*{result}"); + field_need_paren = true; + } + ProjectionElem::Field(f) => { + if field_need_paren { + result = format!("({result})"); + } + let variant_data = f.parent.variant_data(db.upcast()); + let field = match &*variant_data { + VariantData::Record(fields) => fields[f.local_id] + .name + .as_str() + .unwrap_or("[missing field]") + .to_string(), + VariantData::Tuple(fields) => fields + .iter() + .position(|x| x.0 == f.local_id) + .unwrap_or_default() + .to_string(), + VariantData::Unit => "[missing field]".to_string(), + }; + result = format!("{result}.{field}"); + field_need_paren = false; + } + &ProjectionElem::TupleOrClosureField(field) => { + if field_need_paren { + result = format!("({result})"); + } + result = format!("{result}.{field}"); + field_need_paren = false; + } + ProjectionElem::Index(_) + | ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } + | ProjectionElem::OpaqueCast(_) => { + never!("Not happen in closure capture"); + continue; + } + } + } + result + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) struct CapturedItemWithoutTy { pub(crate) place: HirPlace, |