@@ -16,21 +16,26 @@ use hir_def::{
1616 path:: { Path , PathKind } ,
1717 type_ref:: { TraitBoundModifier , TypeBound , TypeRef } ,
1818 visibility:: Visibility ,
19- HasModule , ItemContainerId , LocalFieldId , Lookup , ModuleDefId , ModuleId , TraitId ,
19+ EnumVariantId , HasModule , ItemContainerId , LocalFieldId , Lookup , ModuleDefId , ModuleId ,
20+ TraitId ,
2021} ;
2122use hir_expand:: { hygiene:: Hygiene , name:: Name } ;
2223use intern:: { Internable , Interned } ;
2324use itertools:: Itertools ;
25+ use la_arena:: ArenaMap ;
2426use smallvec:: SmallVec ;
2527use stdx:: never;
2628
2729use crate :: {
30+ consteval:: try_const_usize,
2831 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,
3035 mapping:: from_chalk,
3136 mir:: pad16,
3237 primitive, to_assoc_type_id,
33- utils:: { self , generics, ClosureSubst } ,
38+ utils:: { self , detect_variant_from_bytes , generics, ClosureSubst } ,
3439 AdtId , AliasEq , AliasTy , Binders , CallableDefId , CallableSig , Const , ConstScalar , ConstValue ,
3540 DomainGoal , GenericArg , ImplTraitId , Interner , Lifetime , LifetimeData , LifetimeOutlives ,
3641 MemoryMap , Mutability , OpaqueTy , ProjectionTy , ProjectionTyExt , QuantifiedWhereClause , Scalar ,
@@ -469,7 +474,7 @@ fn render_const_scalar(
469474 // infrastructure and have it here as a field on `f`.
470475 let krate = * f. db . crate_graph ( ) . crates_in_topological_order ( ) . last ( ) . unwrap ( ) ;
471476 match ty. kind ( Interner ) {
472- chalk_ir :: TyKind :: Scalar ( s) => match s {
477+ TyKind :: Scalar ( s) => match s {
473478 Scalar :: Bool => write ! ( f, "{}" , if b[ 0 ] == 0 { false } else { true } ) ,
474479 Scalar :: Char => {
475480 let x = u128:: from_le_bytes ( pad16 ( b, false ) ) as u32 ;
@@ -497,17 +502,54 @@ fn render_const_scalar(
497502 }
498503 } ,
499504 } ,
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 => {
502507 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>" ) ;
505513 write ! ( f, "{s:?}" )
506514 }
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+ }
508550 } ,
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 {
511553 return f. write_str ( "<layout-error>" ) ;
512554 } ;
513555 f. write_str ( "(" ) ?;
@@ -529,69 +571,144 @@ fn render_const_scalar(
529571 }
530572 f. write_str ( ")" )
531573 }
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+ )
581616 }
582617 }
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 ( _, _) => {
590621 let x = u128:: from_le_bytes ( pad16 ( b, false ) ) ;
591622 write ! ( f, "{:#X} as " , x) ?;
592623 ty. hir_fmt ( f)
593624 }
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 ( ( ) ) ,
595712 }
596713}
597714
0 commit comments