@@ -4,6 +4,7 @@ use std::{cmp, collections::HashMap, convert::Infallible, mem};
4
4
5
5
use chalk_ir:: { cast:: Cast , AliasEq , AliasTy , FnSubst , Mutability , TyKind , WhereClause } ;
6
6
use hir_def:: {
7
+ data:: adt:: VariantData ,
7
8
hir:: {
8
9
Array , BinaryOp , BindingAnnotation , BindingId , CaptureBy , Expr , ExprId , Pat , PatId ,
9
10
Statement , UnaryOp ,
@@ -18,6 +19,7 @@ use smallvec::SmallVec;
18
19
use stdx:: never;
19
20
20
21
use crate :: {
22
+ db:: HirDatabase ,
21
23
mir:: { BorrowKind , MirSpan , ProjectionElem } ,
22
24
static_lifetime, to_chalk_trait_id,
23
25
traits:: FnTrait ,
@@ -146,13 +148,81 @@ pub(crate) enum CaptureKind {
146
148
}
147
149
148
150
#[ derive( Debug , Clone , PartialEq , Eq ) ]
149
- pub ( crate ) struct CapturedItem {
151
+ pub struct CapturedItem {
150
152
pub ( crate ) place : HirPlace ,
151
153
pub ( crate ) kind : CaptureKind ,
152
154
pub ( crate ) span : MirSpan ,
153
155
pub ( crate ) ty : Ty ,
154
156
}
155
157
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
+
156
226
#[ derive( Debug , Clone , PartialEq , Eq ) ]
157
227
pub ( crate ) struct CapturedItemWithoutTy {
158
228
pub ( crate ) place : HirPlace ,
0 commit comments