@@ -2564,6 +2564,8 @@ pub enum TyKind {
25642564 /// Usually not written directly in user code but indirectly via the macro
25652565 /// `core::field::field_of!(...)`.
25662566 FieldOf ( Box < Ty > , Option < Ident > , Ident ) ,
2567+ /// A view of a type. `T.{ field_1, field_2 }`.
2568+ View ( Box < Ty > , #[ visitable( ignore) ] ThinVec < Ident > ) ,
25672569 /// Sometimes we need a dummy value when no error has occurred.
25682570 Dummy ,
25692571 /// Placeholder for a kind that has failed to be defined.
@@ -2575,6 +2577,17 @@ impl TyKind {
25752577 matches ! ( self , TyKind :: ImplicitSelf )
25762578 }
25772579
2580+ pub fn as_implicit_self_maybe_wrapped_in_view ( & self ) -> Option < ViewKind > {
2581+ match self {
2582+ TyKind :: ImplicitSelf => Some ( ViewKind :: Full ) ,
2583+ TyKind :: View ( ty, fields) if ty. kind . is_implicit_self ( ) => {
2584+ let fields = fields. clone ( ) ;
2585+ Some ( ViewKind :: Partial { fields } )
2586+ }
2587+ _ => None ,
2588+ }
2589+ }
2590+
25782591 pub fn is_unit ( & self ) -> bool {
25792592 matches ! ( self , TyKind :: Tup ( tys) if tys. is_empty( ) )
25802593 }
@@ -2928,6 +2941,12 @@ pub struct Param {
29282941/// Alternative representation for `Arg`s describing `self` parameter of methods.
29292942///
29302943/// E.g., `&mut self` as in `fn foo(&mut self)`.
2944+ #[ derive( Clone , Encodable , Decodable , Debug ) ]
2945+ pub struct SelfParam {
2946+ pub kind : SelfKind ,
2947+ pub view : ViewKind ,
2948+ }
2949+
29312950#[ derive( Clone , Encodable , Decodable , Debug ) ]
29322951pub enum SelfKind {
29332952 /// `self`, `mut self`
@@ -2954,28 +2973,46 @@ impl SelfKind {
29542973 }
29552974}
29562975
2957- pub type ExplicitSelf = Spanned < SelfKind > ;
2976+ /// Represents how a type is viewed.
2977+ #[ derive( Clone , Encodable , Decodable , Debug , Walkable ) ]
2978+ pub enum ViewKind {
2979+ /// `T`. All the fields can be observed.
2980+ Full ,
2981+ /// `T.{ foo, bar }`. Only `foo` and `bar` can be observed.
2982+ // FIXME(scrabsha): in the future, we may want to express more complex situations, such as
2983+ // mutably observing some fields while immutably observing others. Something like
2984+ // `T.{ foo, mut bar }`.
2985+ Partial {
2986+ #[ visitable( ignore) ]
2987+ fields : ThinVec < Ident > ,
2988+ } ,
2989+ }
2990+
2991+ pub type ExplicitSelf = Spanned < SelfParam > ;
29582992
29592993impl Param {
29602994 /// Attempts to cast parameter to `ExplicitSelf`.
29612995 pub fn to_self ( & self ) -> Option < ExplicitSelf > {
29622996 if let PatKind :: Ident ( BindingMode ( ByRef :: No , mutbl) , ident, _) = self . pat . kind {
29632997 if ident. name == kw:: SelfLower {
2964- return match self . ty . kind {
2965- TyKind :: ImplicitSelf => Some ( respan ( self . pat . span , SelfKind :: Value ( mutbl) ) ) ,
2966- TyKind :: Ref ( lt, MutTy { ref ty, mutbl } ) if ty. kind . is_implicit_self ( ) => {
2967- Some ( respan ( self . pat . span , SelfKind :: Region ( lt, mutbl) ) )
2998+ let ( kind, view, span) = match self . ty . kind {
2999+ ref kind if let Some ( view) = kind. as_implicit_self_maybe_wrapped_in_view ( ) => {
3000+ ( SelfKind :: Value ( mutbl) , view, self . pat . span )
3001+ }
3002+ TyKind :: Ref ( lt, MutTy { ref ty, mutbl } )
3003+ if let Some ( view) = ty. kind . as_implicit_self_maybe_wrapped_in_view ( ) =>
3004+ {
3005+ ( SelfKind :: Region ( lt, mutbl) , view, self . pat . span )
29683006 }
29693007 TyKind :: PinnedRef ( lt, MutTy { ref ty, mutbl } )
2970- if ty. kind . is_implicit_self ( ) =>
3008+ if let Some ( view ) = ty. kind . as_implicit_self_maybe_wrapped_in_view ( ) =>
29713009 {
2972- Some ( respan ( self . pat . span , SelfKind :: Pinned ( lt, mutbl) ) )
3010+ ( SelfKind :: Pinned ( lt, mutbl) , view , self . pat . span )
29733011 }
2974- _ => Some ( respan (
2975- self . pat . span . to ( self . ty . span ) ,
2976- SelfKind :: Explicit ( self . ty . clone ( ) , mutbl) ,
2977- ) ) ,
3012+ _ => ( SelfKind :: Explicit ( self . ty . clone ( ) , mutbl) , ViewKind :: Full , self . ty . span ) ,
29783013 } ;
3014+ let param = respan ( span, SelfParam { view, kind } ) ;
3015+ return Some ( param) ;
29793016 }
29803017 }
29813018 None
@@ -2993,13 +3030,21 @@ impl Param {
29933030 /// Builds a `Param` object from `ExplicitSelf`.
29943031 pub fn from_self ( attrs : AttrVec , eself : ExplicitSelf , eself_ident : Ident ) -> Param {
29953032 let span = eself. span . to ( eself_ident. span ) ;
2996- let infer_ty = Box :: new ( Ty {
3033+ let mut infer_ty = Box :: new ( Ty {
29973034 id : DUMMY_NODE_ID ,
29983035 kind : TyKind :: ImplicitSelf ,
29993036 span : eself_ident. span ,
30003037 tokens : None ,
30013038 } ) ;
3002- let ( mutbl, ty) = match eself. node {
3039+ if let ViewKind :: Partial { fields } = eself. node . view {
3040+ infer_ty = Box :: new ( Ty {
3041+ id : DUMMY_NODE_ID ,
3042+ kind : TyKind :: View ( infer_ty, fields) ,
3043+ span : eself_ident. span ,
3044+ tokens : None ,
3045+ } ) ;
3046+ }
3047+ let ( mutbl, ty) = match eself. node . kind {
30033048 SelfKind :: Explicit ( ty, mutbl) => ( mutbl, ty) ,
30043049 SelfKind :: Value ( mutbl) => ( mutbl, infer_ty) ,
30053050 SelfKind :: Region ( lt, mutbl) => (
@@ -3872,7 +3917,7 @@ impl Fn {
38723917 . inputs
38733918 . first ( )
38743919 . and_then ( |param| param. to_self ( ) )
3875- . is_some_and ( |eself| matches ! ( eself. node, SelfKind :: Pinned ( None , Mutability :: Mut ) ) )
3920+ . is_some_and ( |eself| matches ! ( eself. node. kind , SelfKind :: Pinned ( None , Mutability :: Mut ) ) )
38763921 }
38773922}
38783923
0 commit comments