1
1
use crate :: mir:: pretty:: { function_body, pretty_statement} ;
2
- use crate :: ty:: { AdtDef , ClosureDef , Const , CoroutineDef , GenericArgs , Movability , Region , Ty } ;
3
- use crate :: Opaque ;
4
- use crate :: Span ;
2
+ use crate :: ty:: {
3
+ AdtDef , ClosureDef , Const , CoroutineDef , GenericArgs , Movability , Region , RigidTy , Ty , TyKind ,
4
+ } ;
5
+ use crate :: { Error , Opaque , Span } ;
5
6
use std:: io;
7
+
6
8
/// The SMIR representation of a single function.
7
9
#[ derive( Clone , Debug ) ]
8
10
pub struct Body {
@@ -561,7 +563,7 @@ pub struct SwitchTarget {
561
563
pub target : usize ,
562
564
}
563
565
564
- #[ derive( Clone , Debug , Eq , PartialEq ) ]
566
+ #[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
565
567
pub enum BorrowKind {
566
568
/// Data must be immutable and is aliasable.
567
569
Shared ,
@@ -579,14 +581,14 @@ pub enum BorrowKind {
579
581
} ,
580
582
}
581
583
582
- #[ derive( Clone , Debug , Eq , PartialEq ) ]
584
+ #[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
583
585
pub enum MutBorrowKind {
584
586
Default ,
585
587
TwoPhaseBorrow ,
586
588
ClosureCapture ,
587
589
}
588
590
589
- #[ derive( Clone , Debug , PartialEq , Eq ) ]
591
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
590
592
pub enum Mutability {
591
593
Not ,
592
594
Mut ,
@@ -651,10 +653,16 @@ pub enum NullOp {
651
653
}
652
654
653
655
impl Operand {
654
- pub fn ty ( & self , locals : & [ LocalDecl ] ) -> Ty {
656
+ /// Get the type of an operand relative to the local declaration.
657
+ ///
658
+ /// In order to retrieve the correct type, the `locals` argument must match the list of all
659
+ /// locals from the function body where this operand originates from.
660
+ ///
661
+ /// Errors indicate a malformed operand or incompatible locals list.
662
+ pub fn ty ( & self , locals : & [ LocalDecl ] ) -> Result < Ty , Error > {
655
663
match self {
656
664
Operand :: Copy ( place) | Operand :: Move ( place) => place. ty ( locals) ,
657
- Operand :: Constant ( c) => c. ty ( ) ,
665
+ Operand :: Constant ( c) => Ok ( c. ty ( ) ) ,
658
666
}
659
667
}
660
668
}
@@ -666,12 +674,57 @@ impl Constant {
666
674
}
667
675
668
676
impl Place {
669
- // FIXME(klinvill): This function is expected to resolve down the chain of projections to get
670
- // the type referenced at the end of it. E.g. calling `ty()` on `*(_1.f)` should end up
671
- // returning the type referenced by `f`. The information needed to do this may not currently be
672
- // present in Stable MIR since at least an implementation for AdtDef is probably needed.
673
- pub fn ty ( & self , locals : & [ LocalDecl ] ) -> Ty {
674
- let _start_ty = locals[ self . local ] . ty ;
675
- todo ! ( "Implement projection" )
677
+ /// Resolve down the chain of projections to get the type referenced at the end of it.
678
+ /// E.g.:
679
+ /// Calling `ty()` on `var.field` should return the type of `field`.
680
+ ///
681
+ /// In order to retrieve the correct type, the `locals` argument must match the list of all
682
+ /// locals from the function body where this place originates from.
683
+ pub fn ty ( & self , locals : & [ LocalDecl ] ) -> Result < Ty , Error > {
684
+ let start_ty = locals[ self . local ] . ty ;
685
+ self . projection . iter ( ) . fold ( Ok ( start_ty) , |place_ty, elem| {
686
+ let ty = place_ty?;
687
+ match elem {
688
+ ProjectionElem :: Deref => Self :: deref_ty ( ty) ,
689
+ ProjectionElem :: Field ( _idx, fty) => Ok ( * fty) ,
690
+ ProjectionElem :: Index ( _) | ProjectionElem :: ConstantIndex { .. } => {
691
+ Self :: index_ty ( ty)
692
+ }
693
+ ProjectionElem :: Subslice { from, to, from_end } => {
694
+ Self :: subslice_ty ( ty, from, to, from_end)
695
+ }
696
+ ProjectionElem :: Downcast ( _) => Ok ( ty) ,
697
+ ProjectionElem :: OpaqueCast ( ty) | ProjectionElem :: Subtype ( ty) => Ok ( * ty) ,
698
+ }
699
+ } )
700
+ }
701
+
702
+ fn index_ty ( ty : Ty ) -> Result < Ty , Error > {
703
+ ty. kind ( ) . builtin_index ( ) . ok_or_else ( || error ! ( "Cannot index non-array type: {ty:?}" ) )
704
+ }
705
+
706
+ fn subslice_ty ( ty : Ty , from : & u64 , to : & u64 , from_end : & bool ) -> Result < Ty , Error > {
707
+ let ty_kind = ty. kind ( ) ;
708
+ match ty_kind {
709
+ TyKind :: RigidTy ( RigidTy :: Slice ( ..) ) => Ok ( ty) ,
710
+ TyKind :: RigidTy ( RigidTy :: Array ( inner, _) ) if !from_end => Ty :: try_new_array (
711
+ inner,
712
+ to. checked_sub ( * from) . ok_or_else ( || error ! ( "Subslice overflow: {from}..{to}" ) ) ?,
713
+ ) ,
714
+ TyKind :: RigidTy ( RigidTy :: Array ( inner, size) ) => {
715
+ let size = size. eval_target_usize ( ) ?;
716
+ let len = size - from - to;
717
+ Ty :: try_new_array ( inner, len)
718
+ }
719
+ _ => Err ( Error ( format ! ( "Cannot subslice non-array type: `{ty_kind:?}`" ) ) ) ,
720
+ }
721
+ }
722
+
723
+ fn deref_ty ( ty : Ty ) -> Result < Ty , Error > {
724
+ let deref_ty = ty
725
+ . kind ( )
726
+ . builtin_deref ( true )
727
+ . ok_or_else ( || error ! ( "Cannot dereference type: {ty:?}" ) ) ?;
728
+ Ok ( deref_ty. ty )
676
729
}
677
730
}
0 commit comments