@@ -17,21 +17,26 @@ use hir_def::{
1717 path:: { Path , PathKind } ,
1818 type_ref:: { TraitBoundModifier , TypeBound , TypeRef } ,
1919 visibility:: Visibility ,
20- HasModule , ItemContainerId , LocalFieldId , Lookup , ModuleDefId , ModuleId , TraitId ,
20+ EnumVariantId , HasModule , ItemContainerId , LocalFieldId , Lookup , ModuleDefId , ModuleId ,
21+ TraitId ,
2122} ;
2223use hir_expand:: { hygiene:: Hygiene , name:: Name } ;
2324use intern:: { Internable , Interned } ;
2425use itertools:: Itertools ;
26+ use la_arena:: ArenaMap ;
2527use smallvec:: SmallVec ;
2628use stdx:: never;
2729
2830use crate :: {
31+ consteval:: try_const_usize,
2932 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,
3136 mapping:: from_chalk,
3237 mir:: pad16,
3338 primitive, to_assoc_type_id,
34- utils:: { self , generics, ClosureSubst } ,
39+ utils:: { self , detect_variant_from_bytes , generics, ClosureSubst } ,
3540 AdtId , AliasEq , AliasTy , Binders , CallableDefId , CallableSig , Const , ConstScalar , ConstValue ,
3641 DomainGoal , GenericArg , ImplTraitId , Interner , Lifetime , LifetimeData , LifetimeOutlives ,
3742 MemoryMap , Mutability , OpaqueTy , ProjectionTy , ProjectionTyExt , QuantifiedWhereClause , Scalar ,
@@ -470,7 +475,7 @@ fn render_const_scalar(
470475 // infrastructure and have it here as a field on `f`.
471476 let krate = * f. db . crate_graph ( ) . crates_in_topological_order ( ) . last ( ) . unwrap ( ) ;
472477 match ty. kind ( Interner ) {
473- chalk_ir :: TyKind :: Scalar ( s) => match s {
478+ TyKind :: Scalar ( s) => match s {
474479 Scalar :: Bool => write ! ( f, "{}" , if b[ 0 ] == 0 { false } else { true } ) ,
475480 Scalar :: Char => {
476481 let x = u128:: from_le_bytes ( pad16 ( b, false ) ) as u32 ;
@@ -498,17 +503,54 @@ fn render_const_scalar(
498503 }
499504 } ,
500505 } ,
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 => {
503508 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>" ) ;
506514 write ! ( f, "{s:?}" )
507515 }
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+ }
509551 } ,
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 {
512554 return f. write_str ( "<layout-error>" ) ;
513555 } ;
514556 f. write_str ( "(" ) ?;
@@ -530,69 +572,144 @@ fn render_const_scalar(
530572 }
531573 f. write_str ( ")" )
532574 }
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+ )
582617 }
583618 }
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 ( _, _) => {
591622 let x = u128:: from_le_bytes ( pad16 ( b, false ) ) ;
592623 write ! ( f, "{:#X} as " , x) ?;
593624 ty. hir_fmt ( f)
594625 }
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 ( ( ) ) ,
596713 }
597714}
598715
0 commit comments