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.rs72
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,