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