@@ -10,11 +10,19 @@ mod pat_util;
1010pub ( crate ) mod deconstruct_pat;
1111pub ( crate ) mod usefulness;
1212
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 } ;
1419use stdx:: { always, never} ;
1520
1621use 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 ,
1826} ;
1927
2028use self :: pat_util:: EnumerateAndAdjustIterator ;
@@ -49,6 +57,7 @@ pub(crate) enum PatKind {
4957
5058 /// `x`, `ref x`, `x @ P`, etc.
5159 Binding {
60+ name : Name ,
5261 subpattern : Option < Pat > ,
5362 } ,
5463
@@ -148,7 +157,7 @@ impl<'a> PatCtxt<'a> {
148157 }
149158 _ => ( ) ,
150159 }
151- PatKind :: Binding { subpattern : self . lower_opt_pattern ( subpat) }
160+ PatKind :: Binding { name : name . clone ( ) , subpattern : self . lower_opt_pattern ( subpat) }
152161 }
153162
154163 hir_def:: expr:: Pat :: TupleStruct { ref args, ellipsis, .. } if variant. is_some ( ) => {
@@ -282,6 +291,127 @@ impl<'a> PatCtxt<'a> {
282291 }
283292}
284293
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+
285415pub ( crate ) trait PatternFoldable : Sized {
286416 fn fold_with < F : PatternFolder > ( & self , folder : & mut F ) -> Self {
287417 self . super_fold_with ( folder)
@@ -357,8 +487,8 @@ impl PatternFoldable for PatKind {
357487 fn super_fold_with < F : PatternFolder > ( & self , folder : & mut F ) -> Self {
358488 match self {
359489 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) }
362492 }
363493 PatKind :: Variant { substs, enum_variant, subpatterns } => PatKind :: Variant {
364494 substs : substs. fold_with ( folder) ,
0 commit comments