@@ -10,11 +10,19 @@ mod pat_util;
10
10
pub ( crate ) mod deconstruct_pat;
11
11
pub ( crate ) mod usefulness;
12
12
13
- use hir_def:: { body:: Body , expr:: PatId , EnumVariantId , LocalFieldId , VariantId } ;
13
+ use chalk_ir:: Mutability ;
14
+ use hir_def:: {
15
+ adt:: VariantData , body:: Body , expr:: PatId , AdtId , EnumVariantId , HasModule , LocalFieldId ,
16
+ VariantId ,
17
+ } ;
18
+ use hir_expand:: name:: { name, Name } ;
14
19
use stdx:: { always, never} ;
15
20
16
21
use crate :: {
17
- db:: HirDatabase , infer:: BindingMode , InferenceResult , Interner , Substitution , Ty , TyKind ,
22
+ db:: HirDatabase ,
23
+ display:: { HirDisplay , HirDisplayError , HirFormatter } ,
24
+ infer:: BindingMode ,
25
+ InferenceResult , Interner , Substitution , Ty , TyExt , TyKind ,
18
26
} ;
19
27
20
28
use self :: pat_util:: EnumerateAndAdjustIterator ;
@@ -49,6 +57,7 @@ pub(crate) enum PatKind {
49
57
50
58
/// `x`, `ref x`, `x @ P`, etc.
51
59
Binding {
60
+ name : Name ,
52
61
subpattern : Option < Pat > ,
53
62
} ,
54
63
@@ -148,7 +157,7 @@ impl<'a> PatCtxt<'a> {
148
157
}
149
158
_ => ( ) ,
150
159
}
151
- PatKind :: Binding { subpattern : self . lower_opt_pattern ( subpat) }
160
+ PatKind :: Binding { name : name . clone ( ) , subpattern : self . lower_opt_pattern ( subpat) }
152
161
}
153
162
154
163
hir_def:: expr:: Pat :: TupleStruct { ref args, ellipsis, .. } if variant. is_some ( ) => {
@@ -282,6 +291,127 @@ impl<'a> PatCtxt<'a> {
282
291
}
283
292
}
284
293
294
+ impl HirDisplay for Pat {
295
+ fn hir_fmt ( & self , f : & mut HirFormatter ) -> Result < ( ) , HirDisplayError > {
296
+ match & * self . kind {
297
+ PatKind :: Wild => write ! ( f, "_" ) ,
298
+ PatKind :: Binding { name, subpattern } => {
299
+ write ! ( f, "{name}" ) ?;
300
+ if let Some ( subpattern) = subpattern {
301
+ write ! ( f, " @ " ) ?;
302
+ subpattern. hir_fmt ( f) ?;
303
+ }
304
+ Ok ( ( ) )
305
+ }
306
+ PatKind :: Variant { subpatterns, .. } | PatKind :: Leaf { subpatterns } => {
307
+ let variant = match * self . kind {
308
+ PatKind :: Variant { enum_variant, .. } => Some ( VariantId :: from ( enum_variant) ) ,
309
+ _ => self . ty . as_adt ( ) . and_then ( |( adt, _) | match adt {
310
+ AdtId :: StructId ( s) => Some ( s. into ( ) ) ,
311
+ AdtId :: UnionId ( u) => Some ( u. into ( ) ) ,
312
+ AdtId :: EnumId ( _) => None ,
313
+ } ) ,
314
+ } ;
315
+
316
+ if let Some ( variant) = variant {
317
+ match variant {
318
+ VariantId :: EnumVariantId ( v) => {
319
+ let data = f. db . enum_data ( v. parent ) ;
320
+ write ! ( f, "{}" , data. variants[ v. local_id] . name) ?;
321
+ }
322
+ VariantId :: StructId ( s) => write ! ( f, "{}" , f. db. struct_data( s) . name) ?,
323
+ VariantId :: UnionId ( u) => write ! ( f, "{}" , f. db. union_data( u) . name) ?,
324
+ } ;
325
+
326
+ let variant_data = variant. variant_data ( f. db . upcast ( ) ) ;
327
+ if let VariantData :: Record ( rec_fields) = & * variant_data {
328
+ write ! ( f, " {{ " ) ?;
329
+
330
+ let mut printed = 0 ;
331
+ let subpats = subpatterns
332
+ . iter ( )
333
+ . filter ( |p| !matches ! ( * p. pattern. kind, PatKind :: Wild ) )
334
+ . map ( |p| {
335
+ printed += 1 ;
336
+ WriteWith ( move |f| {
337
+ write ! ( f, "{}: " , rec_fields[ p. field] . name) ?;
338
+ p. pattern . hir_fmt ( f)
339
+ } )
340
+ } ) ;
341
+ f. write_joined ( subpats, ", " ) ?;
342
+
343
+ if printed < rec_fields. len ( ) {
344
+ write ! ( f, "{}.." , if printed > 0 { ", " } else { "" } ) ?;
345
+ }
346
+
347
+ return write ! ( f, " }}" ) ;
348
+ }
349
+ }
350
+
351
+ let num_fields = variant
352
+ . map_or ( subpatterns. len ( ) , |v| v. variant_data ( f. db . upcast ( ) ) . fields ( ) . len ( ) ) ;
353
+ if num_fields != 0 || variant. is_none ( ) {
354
+ write ! ( f, "(" ) ?;
355
+ let subpats = ( 0 ..num_fields) . map ( |i| {
356
+ WriteWith ( move |f| {
357
+ let fid = LocalFieldId :: from_raw ( ( i as u32 ) . into ( ) ) ;
358
+ if let Some ( p) = subpatterns. get ( i) {
359
+ if p. field == fid {
360
+ return p. pattern . hir_fmt ( f) ;
361
+ }
362
+ }
363
+ if let Some ( p) = subpatterns. iter ( ) . find ( |p| p. field == fid) {
364
+ p. pattern . hir_fmt ( f)
365
+ } else {
366
+ write ! ( f, "_" )
367
+ }
368
+ } )
369
+ } ) ;
370
+ f. write_joined ( subpats, ", " ) ?;
371
+ if let ( TyKind :: Tuple ( ..) , 1 ) = ( self . ty . kind ( Interner ) , num_fields) {
372
+ write ! ( f, "," ) ?;
373
+ }
374
+ write ! ( f, ")" ) ?;
375
+ }
376
+
377
+ Ok ( ( ) )
378
+ }
379
+ PatKind :: Deref { subpattern } => {
380
+ match self . ty . kind ( Interner ) {
381
+ TyKind :: Adt ( adt, _) if is_box ( adt. 0 , f. db ) => write ! ( f, "box " ) ?,
382
+ & TyKind :: Ref ( mutbl, ..) => {
383
+ write ! ( f, "&{}" , if mutbl == Mutability :: Mut { "mut " } else { "" } ) ?
384
+ }
385
+ _ => never ! ( "{:?} is a bad Deref pattern type" , self . ty) ,
386
+ }
387
+ subpattern. hir_fmt ( f)
388
+ }
389
+ PatKind :: LiteralBool { value } => write ! ( f, "{}" , value) ,
390
+ PatKind :: Or { pats } => f. write_joined ( pats. iter ( ) , " | " ) ,
391
+ }
392
+ }
393
+ }
394
+
395
+ struct WriteWith < F > ( F )
396
+ where
397
+ F : Fn ( & mut HirFormatter ) -> Result < ( ) , HirDisplayError > ;
398
+
399
+ impl < F > HirDisplay for WriteWith < F >
400
+ where
401
+ F : Fn ( & mut HirFormatter ) -> Result < ( ) , HirDisplayError > ,
402
+ {
403
+ fn hir_fmt ( & self , f : & mut HirFormatter < ' _ > ) -> Result < ( ) , HirDisplayError > {
404
+ ( self . 0 ) ( f)
405
+ }
406
+ }
407
+
408
+ fn is_box ( adt : AdtId , db : & dyn HirDatabase ) -> bool {
409
+ let owned_box = name ! [ owned_box] . to_smol_str ( ) ;
410
+ let krate = adt. module ( db. upcast ( ) ) . krate ( ) ;
411
+ let box_adt = db. lang_item ( krate, owned_box) . and_then ( |it| it. as_struct ( ) ) . map ( AdtId :: from) ;
412
+ Some ( adt) == box_adt
413
+ }
414
+
285
415
pub ( crate ) trait PatternFoldable : Sized {
286
416
fn fold_with < F : PatternFolder > ( & self , folder : & mut F ) -> Self {
287
417
self . super_fold_with ( folder)
@@ -357,8 +487,8 @@ impl PatternFoldable for PatKind {
357
487
fn super_fold_with < F : PatternFolder > ( & self , folder : & mut F ) -> Self {
358
488
match self {
359
489
PatKind :: Wild => PatKind :: Wild ,
360
- PatKind :: Binding { subpattern } => {
361
- PatKind :: Binding { subpattern : subpattern. fold_with ( folder) }
490
+ PatKind :: Binding { name , subpattern } => {
491
+ PatKind :: Binding { name : name . clone ( ) , subpattern : subpattern. fold_with ( folder) }
362
492
}
363
493
PatKind :: Variant { substs, enum_variant, subpatterns } => PatKind :: Variant {
364
494
substs : substs. fold_with ( folder) ,
0 commit comments