@@ -4,6 +4,7 @@ use std::{cmp, collections::HashMap, convert::Infallible, mem};
44
55use chalk_ir:: { cast:: Cast , AliasEq , AliasTy , FnSubst , Mutability , TyKind , WhereClause } ;
66use hir_def:: {
7+ data:: adt:: VariantData ,
78 hir:: {
89 Array , BinaryOp , BindingAnnotation , BindingId , CaptureBy , Expr , ExprId , Pat , PatId ,
910 Statement , UnaryOp ,
@@ -18,6 +19,7 @@ use smallvec::SmallVec;
1819use stdx:: never;
1920
2021use crate :: {
22+ db:: HirDatabase ,
2123 mir:: { BorrowKind , MirSpan , ProjectionElem } ,
2224 static_lifetime, to_chalk_trait_id,
2325 traits:: FnTrait ,
@@ -146,13 +148,81 @@ pub(crate) enum CaptureKind {
146148}
147149
148150#[ derive( Debug , Clone , PartialEq , Eq ) ]
149- pub ( crate ) struct CapturedItem {
151+ pub struct CapturedItem {
150152 pub ( crate ) place : HirPlace ,
151153 pub ( crate ) kind : CaptureKind ,
152154 pub ( crate ) span : MirSpan ,
153155 pub ( crate ) ty : Ty ,
154156}
155157
158+ impl CapturedItem {
159+ pub fn display_kind ( & self ) -> & ' static str {
160+ match self . kind {
161+ CaptureKind :: ByRef ( k) => match k {
162+ BorrowKind :: Shared => "immutable borrow" ,
163+ BorrowKind :: Shallow => {
164+ never ! ( "shallow borrow should not happen in closure captures" ) ;
165+ "shallow borrow"
166+ } ,
167+ BorrowKind :: Unique => "unique immutable borrow ([read more](https://doc.rust-lang.org/stable/reference/types/closure.html#unique-immutable-borrows-in-captures))" ,
168+ BorrowKind :: Mut { .. } => "mutable borrow" ,
169+ } ,
170+ CaptureKind :: ByValue => "move" ,
171+ }
172+ }
173+
174+ pub fn display_place ( & self , owner : ClosureId , db : & dyn HirDatabase ) -> String {
175+ let owner = db. lookup_intern_closure ( owner. into ( ) ) . 0 ;
176+ let body = db. body ( owner) ;
177+ let mut result = body[ self . place . local ] . name . to_string ( ) ;
178+ let mut field_need_paren = false ;
179+ for proj in & self . place . projections {
180+ match proj {
181+ ProjectionElem :: Deref => {
182+ result = format ! ( "*{result}" ) ;
183+ field_need_paren = true ;
184+ }
185+ ProjectionElem :: Field ( f) => {
186+ if field_need_paren {
187+ result = format ! ( "({result})" ) ;
188+ }
189+ let variant_data = f. parent . variant_data ( db. upcast ( ) ) ;
190+ let field = match & * variant_data {
191+ VariantData :: Record ( fields) => fields[ f. local_id ]
192+ . name
193+ . as_str ( )
194+ . unwrap_or ( "[missing field]" )
195+ . to_string ( ) ,
196+ VariantData :: Tuple ( fields) => fields
197+ . iter ( )
198+ . position ( |x| x. 0 == f. local_id )
199+ . unwrap_or_default ( )
200+ . to_string ( ) ,
201+ VariantData :: Unit => "[missing field]" . to_string ( ) ,
202+ } ;
203+ result = format ! ( "{result}.{field}" ) ;
204+ field_need_paren = false ;
205+ }
206+ & ProjectionElem :: TupleOrClosureField ( field) => {
207+ if field_need_paren {
208+ result = format ! ( "({result})" ) ;
209+ }
210+ result = format ! ( "{result}.{field}" ) ;
211+ field_need_paren = false ;
212+ }
213+ ProjectionElem :: Index ( _)
214+ | ProjectionElem :: ConstantIndex { .. }
215+ | ProjectionElem :: Subslice { .. }
216+ | ProjectionElem :: OpaqueCast ( _) => {
217+ never ! ( "Not happen in closure capture" ) ;
218+ continue ;
219+ }
220+ }
221+ }
222+ result
223+ }
224+ }
225+
156226#[ derive( Debug , Clone , PartialEq , Eq ) ]
157227pub ( crate ) struct CapturedItemWithoutTy {
158228 pub ( crate ) place : HirPlace ,
0 commit comments