@@ -17,21 +17,26 @@ use hir_def::{
17
17
path:: { Path , PathKind } ,
18
18
type_ref:: { TraitBoundModifier , TypeBound , TypeRef } ,
19
19
visibility:: Visibility ,
20
- HasModule , ItemContainerId , LocalFieldId , Lookup , ModuleDefId , ModuleId , TraitId ,
20
+ EnumVariantId , HasModule , ItemContainerId , LocalFieldId , Lookup , ModuleDefId , ModuleId ,
21
+ TraitId ,
21
22
} ;
22
23
use hir_expand:: { hygiene:: Hygiene , name:: Name } ;
23
24
use intern:: { Internable , Interned } ;
24
25
use itertools:: Itertools ;
26
+ use la_arena:: ArenaMap ;
25
27
use smallvec:: SmallVec ;
26
28
use stdx:: never;
27
29
28
30
use crate :: {
31
+ consteval:: try_const_usize,
29
32
db:: HirDatabase ,
30
- from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, lt_from_placeholder_idx,
33
+ from_assoc_type_id, from_foreign_def_id, from_placeholder_idx,
34
+ layout:: Layout ,
35
+ lt_from_placeholder_idx,
31
36
mapping:: from_chalk,
32
37
mir:: pad16,
33
38
primitive, to_assoc_type_id,
34
- utils:: { self , generics, ClosureSubst } ,
39
+ utils:: { self , detect_variant_from_bytes , generics, ClosureSubst } ,
35
40
AdtId , AliasEq , AliasTy , Binders , CallableDefId , CallableSig , Const , ConstScalar , ConstValue ,
36
41
DomainGoal , GenericArg , ImplTraitId , Interner , Lifetime , LifetimeData , LifetimeOutlives ,
37
42
MemoryMap , Mutability , OpaqueTy , ProjectionTy , ProjectionTyExt , QuantifiedWhereClause , Scalar ,
@@ -470,7 +475,7 @@ fn render_const_scalar(
470
475
// infrastructure and have it here as a field on `f`.
471
476
let krate = * f. db . crate_graph ( ) . crates_in_topological_order ( ) . last ( ) . unwrap ( ) ;
472
477
match ty. kind ( Interner ) {
473
- chalk_ir :: TyKind :: Scalar ( s) => match s {
478
+ TyKind :: Scalar ( s) => match s {
474
479
Scalar :: Bool => write ! ( f, "{}" , if b[ 0 ] == 0 { false } else { true } ) ,
475
480
Scalar :: Char => {
476
481
let x = u128:: from_le_bytes ( pad16 ( b, false ) ) as u32 ;
@@ -498,17 +503,54 @@ fn render_const_scalar(
498
503
}
499
504
} ,
500
505
} ,
501
- chalk_ir :: TyKind :: Ref ( _, _, t) => match t. kind ( Interner ) {
502
- chalk_ir :: TyKind :: Str => {
506
+ TyKind :: Ref ( _, _, t) => match t. kind ( Interner ) {
507
+ TyKind :: Str => {
503
508
let addr = usize:: from_le_bytes ( b[ 0 ..b. len ( ) / 2 ] . try_into ( ) . unwrap ( ) ) ;
504
- let bytes = memory_map. memory . get ( & addr) . map ( |x| & * * x) . unwrap_or ( & [ ] ) ;
505
- let s = std:: str:: from_utf8 ( bytes) . unwrap_or ( "<utf8-error>" ) ;
509
+ let size = usize:: from_le_bytes ( b[ b. len ( ) / 2 ..] . try_into ( ) . unwrap ( ) ) ;
510
+ let Some ( bytes) = memory_map. get ( addr, size) else {
511
+ return f. write_str ( "<ref-data-not-available>" ) ;
512
+ } ;
513
+ let s = std:: str:: from_utf8 ( & bytes) . unwrap_or ( "<utf8-error>" ) ;
506
514
write ! ( f, "{s:?}" )
507
515
}
508
- _ => f. write_str ( "<ref-not-supported>" ) ,
516
+ TyKind :: Slice ( ty) => {
517
+ let addr = usize:: from_le_bytes ( b[ 0 ..b. len ( ) / 2 ] . try_into ( ) . unwrap ( ) ) ;
518
+ let count = usize:: from_le_bytes ( b[ b. len ( ) / 2 ..] . try_into ( ) . unwrap ( ) ) ;
519
+ let Ok ( layout) = f. db . layout_of_ty ( ty. clone ( ) , krate) else {
520
+ return f. write_str ( "<layout-error>" ) ;
521
+ } ;
522
+ let size_one = layout. size . bytes_usize ( ) ;
523
+ let Some ( bytes) = memory_map. get ( addr, size_one * count) else {
524
+ return f. write_str ( "<ref-data-not-available>" ) ;
525
+ } ;
526
+ f. write_str ( "&[" ) ?;
527
+ let mut first = true ;
528
+ for i in 0 ..count {
529
+ if first {
530
+ first = false ;
531
+ } else {
532
+ f. write_str ( ", " ) ?;
533
+ }
534
+ let offset = size_one * i;
535
+ render_const_scalar ( f, & bytes[ offset..offset + size_one] , memory_map, & ty) ?;
536
+ }
537
+ f. write_str ( "]" )
538
+ }
539
+ _ => {
540
+ let addr = usize:: from_le_bytes ( b. try_into ( ) . unwrap ( ) ) ;
541
+ let Ok ( layout) = f. db . layout_of_ty ( t. clone ( ) , krate) else {
542
+ return f. write_str ( "<layout-error>" ) ;
543
+ } ;
544
+ let size = layout. size . bytes_usize ( ) ;
545
+ let Some ( bytes) = memory_map. get ( addr, size) else {
546
+ return f. write_str ( "<ref-data-not-available>" ) ;
547
+ } ;
548
+ f. write_str ( "&" ) ?;
549
+ render_const_scalar ( f, bytes, memory_map, t)
550
+ }
509
551
} ,
510
- chalk_ir :: TyKind :: Tuple ( _, subst) => {
511
- let Ok ( layout) = f. db . layout_of_ty ( ty. clone ( ) , krate) else {
552
+ TyKind :: Tuple ( _, subst) => {
553
+ let Ok ( layout) = f. db . layout_of_ty ( ty. clone ( ) , krate) else {
512
554
return f. write_str ( "<layout-error>" ) ;
513
555
} ;
514
556
f. write_str ( "(" ) ?;
@@ -530,69 +572,144 @@ fn render_const_scalar(
530
572
}
531
573
f. write_str ( ")" )
532
574
}
533
- chalk_ir:: TyKind :: Adt ( adt, subst) => match adt. 0 {
534
- hir_def:: AdtId :: StructId ( s) => {
535
- let data = f. db . struct_data ( s) ;
536
- let Ok ( layout) = f. db . layout_of_adt ( adt. 0 , subst. clone ( ) , krate) else {
537
- return f. write_str ( "<layout-error>" ) ;
538
- } ;
539
- match data. variant_data . as_ref ( ) {
540
- VariantData :: Record ( fields) | VariantData :: Tuple ( fields) => {
541
- let field_types = f. db . field_types ( s. into ( ) ) ;
542
- let krate = adt. 0 . module ( f. db . upcast ( ) ) . krate ( ) ;
543
- let render_field = |f : & mut HirFormatter < ' _ > , id : LocalFieldId | {
544
- let offset = layout
545
- . fields
546
- . offset ( u32:: from ( id. into_raw ( ) ) as usize )
547
- . bytes_usize ( ) ;
548
- let ty = field_types[ id] . clone ( ) . substitute ( Interner , subst) ;
549
- let Ok ( layout) = f. db . layout_of_ty ( ty. clone ( ) , krate) else {
550
- return f. write_str ( "<layout-error>" ) ;
551
- } ;
552
- let size = layout. size . bytes_usize ( ) ;
553
- render_const_scalar ( f, & b[ offset..offset + size] , memory_map, & ty)
554
- } ;
555
- let mut it = fields. iter ( ) ;
556
- if matches ! ( data. variant_data. as_ref( ) , VariantData :: Record ( _) ) {
557
- write ! ( f, "{} {{" , data. name. display( f. db. upcast( ) ) ) ?;
558
- if let Some ( ( id, data) ) = it. next ( ) {
559
- write ! ( f, " {}: " , data. name. display( f. db. upcast( ) ) ) ?;
560
- render_field ( f, id) ?;
561
- }
562
- for ( id, data) in it {
563
- write ! ( f, ", {}: " , data. name. display( f. db. upcast( ) ) ) ?;
564
- render_field ( f, id) ?;
565
- }
566
- write ! ( f, " }}" ) ?;
567
- } else {
568
- let mut it = it. map ( |x| x. 0 ) ;
569
- write ! ( f, "{}(" , data. name. display( f. db. upcast( ) ) ) ?;
570
- if let Some ( id) = it. next ( ) {
571
- render_field ( f, id) ?;
572
- }
573
- for id in it {
574
- write ! ( f, ", " ) ?;
575
- render_field ( f, id) ?;
576
- }
577
- write ! ( f, ")" ) ?;
578
- }
579
- return Ok ( ( ) ) ;
580
- }
581
- VariantData :: Unit => write ! ( f, "{}" , data. name. display( f. db. upcast( ) ) ) ,
575
+ TyKind :: Adt ( adt, subst) => {
576
+ let Ok ( layout) = f. db . layout_of_adt ( adt. 0 , subst. clone ( ) , krate) else {
577
+ return f. write_str ( "<layout-error>" ) ;
578
+ } ;
579
+ match adt. 0 {
580
+ hir_def:: AdtId :: StructId ( s) => {
581
+ let data = f. db . struct_data ( s) ;
582
+ write ! ( f, "{}" , data. name. display( f. db. upcast( ) ) ) ?;
583
+ let field_types = f. db . field_types ( s. into ( ) ) ;
584
+ render_variant_after_name (
585
+ & data. variant_data ,
586
+ f,
587
+ & field_types,
588
+ adt. 0 . module ( f. db . upcast ( ) ) . krate ( ) ,
589
+ & layout,
590
+ subst,
591
+ b,
592
+ memory_map,
593
+ )
594
+ }
595
+ hir_def:: AdtId :: UnionId ( u) => {
596
+ write ! ( f, "{}" , f. db. union_data( u) . name. display( f. db. upcast( ) ) )
597
+ }
598
+ hir_def:: AdtId :: EnumId ( e) => {
599
+ let Some ( ( var_id, var_layout) ) =
600
+ detect_variant_from_bytes ( & layout, f. db , krate, b, e) else {
601
+ return f. write_str ( "<failed-to-detect-variant>" ) ;
602
+ } ;
603
+ let data = & f. db . enum_data ( e) . variants [ var_id] ;
604
+ write ! ( f, "{}" , data. name. display( f. db. upcast( ) ) ) ?;
605
+ let field_types =
606
+ f. db . field_types ( EnumVariantId { parent : e, local_id : var_id } . into ( ) ) ;
607
+ render_variant_after_name (
608
+ & data. variant_data ,
609
+ f,
610
+ & field_types,
611
+ adt. 0 . module ( f. db . upcast ( ) ) . krate ( ) ,
612
+ & var_layout,
613
+ subst,
614
+ b,
615
+ memory_map,
616
+ )
582
617
}
583
618
}
584
- hir_def:: AdtId :: UnionId ( u) => {
585
- write ! ( f, "{}" , f. db. union_data( u) . name. display( f. db. upcast( ) ) )
586
- }
587
- hir_def:: AdtId :: EnumId ( _) => f. write_str ( "<enum-not-supported>" ) ,
588
- } ,
589
- chalk_ir:: TyKind :: FnDef ( ..) => ty. hir_fmt ( f) ,
590
- chalk_ir:: TyKind :: Raw ( _, _) => {
619
+ }
620
+ TyKind :: FnDef ( ..) => ty. hir_fmt ( f) ,
621
+ TyKind :: Function ( _) | TyKind :: Raw ( _, _) => {
591
622
let x = u128:: from_le_bytes ( pad16 ( b, false ) ) ;
592
623
write ! ( f, "{:#X} as " , x) ?;
593
624
ty. hir_fmt ( f)
594
625
}
595
- _ => f. write_str ( "<not-supported>" ) ,
626
+ TyKind :: Array ( ty, len) => {
627
+ let Some ( len) = try_const_usize ( f. db , len) else {
628
+ return f. write_str ( "<unknown-array-len>" ) ;
629
+ } ;
630
+ let Ok ( layout) = f. db . layout_of_ty ( ty. clone ( ) , krate) else {
631
+ return f. write_str ( "<layout-error>" ) ;
632
+ } ;
633
+ let size_one = layout. size . bytes_usize ( ) ;
634
+ f. write_str ( "[" ) ?;
635
+ let mut first = true ;
636
+ for i in 0 ..len as usize {
637
+ if first {
638
+ first = false ;
639
+ } else {
640
+ f. write_str ( ", " ) ?;
641
+ }
642
+ let offset = size_one * i;
643
+ render_const_scalar ( f, & b[ offset..offset + size_one] , memory_map, & ty) ?;
644
+ }
645
+ f. write_str ( "]" )
646
+ }
647
+ TyKind :: Never => f. write_str ( "!" ) ,
648
+ TyKind :: Closure ( _, _) => f. write_str ( "<closure>" ) ,
649
+ TyKind :: Generator ( _, _) => f. write_str ( "<generator>" ) ,
650
+ TyKind :: GeneratorWitness ( _, _) => f. write_str ( "<generator-witness>" ) ,
651
+ // The below arms are unreachable, since const eval will bail out before here.
652
+ TyKind :: Foreign ( _) => f. write_str ( "<extern-type>" ) ,
653
+ TyKind :: Error
654
+ | TyKind :: Placeholder ( _)
655
+ | TyKind :: Alias ( _)
656
+ | TyKind :: AssociatedType ( _, _)
657
+ | TyKind :: OpaqueType ( _, _)
658
+ | TyKind :: BoundVar ( _)
659
+ | TyKind :: InferenceVar ( _, _) => f. write_str ( "<placeholder-or-unknown-type>" ) ,
660
+ // The below arms are unreachable, since we handled them in ref case.
661
+ TyKind :: Slice ( _) | TyKind :: Str | TyKind :: Dyn ( _) => f. write_str ( "<unsized-value>" ) ,
662
+ }
663
+ }
664
+
665
+ fn render_variant_after_name (
666
+ data : & VariantData ,
667
+ f : & mut HirFormatter < ' _ > ,
668
+ field_types : & ArenaMap < LocalFieldId , Binders < Ty > > ,
669
+ krate : CrateId ,
670
+ layout : & Layout ,
671
+ subst : & Substitution ,
672
+ b : & [ u8 ] ,
673
+ memory_map : & MemoryMap ,
674
+ ) -> Result < ( ) , HirDisplayError > {
675
+ match data {
676
+ VariantData :: Record ( fields) | VariantData :: Tuple ( fields) => {
677
+ let render_field = |f : & mut HirFormatter < ' _ > , id : LocalFieldId | {
678
+ let offset = layout. fields . offset ( u32:: from ( id. into_raw ( ) ) as usize ) . bytes_usize ( ) ;
679
+ let ty = field_types[ id] . clone ( ) . substitute ( Interner , subst) ;
680
+ let Ok ( layout) = f. db . layout_of_ty ( ty. clone ( ) , krate) else {
681
+ return f. write_str ( "<layout-error>" ) ;
682
+ } ;
683
+ let size = layout. size . bytes_usize ( ) ;
684
+ render_const_scalar ( f, & b[ offset..offset + size] , memory_map, & ty)
685
+ } ;
686
+ let mut it = fields. iter ( ) ;
687
+ if matches ! ( data, VariantData :: Record ( _) ) {
688
+ write ! ( f, " {{" ) ?;
689
+ if let Some ( ( id, data) ) = it. next ( ) {
690
+ write ! ( f, " {}: " , data. name. display( f. db. upcast( ) ) ) ?;
691
+ render_field ( f, id) ?;
692
+ }
693
+ for ( id, data) in it {
694
+ write ! ( f, ", {}: " , data. name. display( f. db. upcast( ) ) ) ?;
695
+ render_field ( f, id) ?;
696
+ }
697
+ write ! ( f, " }}" ) ?;
698
+ } else {
699
+ let mut it = it. map ( |x| x. 0 ) ;
700
+ write ! ( f, "(" ) ?;
701
+ if let Some ( id) = it. next ( ) {
702
+ render_field ( f, id) ?;
703
+ }
704
+ for id in it {
705
+ write ! ( f, ", " ) ?;
706
+ render_field ( f, id) ?;
707
+ }
708
+ write ! ( f, ")" ) ?;
709
+ }
710
+ return Ok ( ( ) ) ;
711
+ }
712
+ VariantData :: Unit => Ok ( ( ) ) ,
596
713
}
597
714
}
598
715
0 commit comments