@@ -710,7 +710,7 @@ pub struct LocalDecl<'tcx> {
710710 /// e.g. via `let x: T`, then we carry that type here. The MIR
711711 /// borrow checker needs this information since it can affect
712712 /// region inference.
713- pub user_ty : Option < ( UserTypeAnnotation < ' tcx > , Span ) > ,
713+ pub user_ty : UserTypeProjections < ' tcx > ,
714714
715715 /// Name of the local, used in debuginfo and pretty-printing.
716716 ///
@@ -882,7 +882,7 @@ impl<'tcx> LocalDecl<'tcx> {
882882 LocalDecl {
883883 mutability,
884884 ty,
885- user_ty : None ,
885+ user_ty : UserTypeProjections :: none ( ) ,
886886 name : None ,
887887 source_info : SourceInfo {
888888 span,
@@ -903,7 +903,7 @@ impl<'tcx> LocalDecl<'tcx> {
903903 LocalDecl {
904904 mutability : Mutability :: Mut ,
905905 ty : return_ty,
906- user_ty : None ,
906+ user_ty : UserTypeProjections :: none ( ) ,
907907 source_info : SourceInfo {
908908 span,
909909 scope : OUTERMOST_SOURCE_SCOPE ,
@@ -1674,6 +1674,10 @@ impl<'tcx> Statement<'tcx> {
16741674 /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
16751675 /// invalidating statement indices in `Location`s.
16761676 pub fn make_nop ( & mut self ) {
1677+ // `Statement` contributes significantly to peak memory usage. Make
1678+ // sure it doesn't get bigger.
1679+ static_assert ! ( STATEMENT_IS_AT_MOST_56_BYTES : mem:: size_of:: <Statement <' _>>( ) <= 56 ) ;
1680+
16771681 self . kind = StatementKind :: Nop
16781682 }
16791683
@@ -1737,7 +1741,7 @@ pub enum StatementKind<'tcx> {
17371741 /// - `Contravariant` -- requires that `T_y :> T`
17381742 /// - `Invariant` -- requires that `T_y == T`
17391743 /// - `Bivariant` -- no effect
1740- AscribeUserType ( Place < ' tcx > , ty:: Variance , UserTypeAnnotation < ' tcx > ) ,
1744+ AscribeUserType ( Place < ' tcx > , ty:: Variance , Box < UserTypeProjection < ' tcx > > ) ,
17411745
17421746 /// No-op. Useful for deleting instructions without affecting statement indices.
17431747 Nop ,
@@ -1940,6 +1944,10 @@ pub type PlaceProjection<'tcx> = Projection<'tcx, Place<'tcx>, Local, Ty<'tcx>>;
19401944/// and the index is a local.
19411945pub type PlaceElem < ' tcx > = ProjectionElem < ' tcx , Local , Ty < ' tcx > > ;
19421946
1947+ /// Alias for projections as they appear in `UserTypeProjection`, where we
1948+ /// need neither the `V` parameter for `Index` nor the `T` for `Field`.
1949+ pub type ProjectionKind < ' tcx > = ProjectionElem < ' tcx , ( ) , ( ) > ;
1950+
19431951newtype_index ! {
19441952 pub struct Field {
19451953 DEBUG_FORMAT = "field[{}]"
@@ -2445,6 +2453,117 @@ EnumLiftImpl! {
24452453 }
24462454}
24472455
2456+ /// A collection of projections into user types.
2457+ ///
2458+ /// They are projections because a binding can occur a part of a
2459+ /// parent pattern that has been ascribed a type.
2460+ ///
2461+ /// Its a collection because there can be multiple type ascriptions on
2462+ /// the path from the root of the pattern down to the binding itself.
2463+ ///
2464+ /// An example:
2465+ ///
2466+ /// ```rust
2467+ /// struct S<'a>((i32, &'a str), String);
2468+ /// let S((_, w): (i32, &'static str), _): S = ...;
2469+ /// // ------ ^^^^^^^^^^^^^^^^^^^ (1)
2470+ /// // --------------------------------- ^ (2)
2471+ /// ```
2472+ ///
2473+ /// The highlights labelled `(1)` show the subpattern `(_, w)` being
2474+ /// ascribed the type `(i32, &'static str)`.
2475+ ///
2476+ /// The highlights labelled `(2)` show the whole pattern being
2477+ /// ascribed the type `S`.
2478+ ///
2479+ /// In this example, when we descend to `w`, we will have built up the
2480+ /// following two projected types:
2481+ ///
2482+ /// * base: `S`, projection: `(base.0).1`
2483+ /// * base: `(i32, &'static str)`, projection: `base.1`
2484+ ///
2485+ /// The first will lead to the constraint `w: &'1 str` (for some
2486+ /// inferred region `'1`). The second will lead to the constraint `w:
2487+ /// &'static str`.
2488+ #[ derive( Clone , Debug , PartialEq , Eq , Hash , RustcEncodable , RustcDecodable ) ]
2489+ pub struct UserTypeProjections < ' tcx > {
2490+ pub ( crate ) contents : Vec < ( UserTypeProjection < ' tcx > , Span ) > ,
2491+ }
2492+
2493+ BraceStructTypeFoldableImpl ! {
2494+ impl <' tcx> TypeFoldable <' tcx> for UserTypeProjections <' tcx> {
2495+ contents
2496+ }
2497+ }
2498+
2499+ impl < ' tcx > UserTypeProjections < ' tcx > {
2500+ pub fn none ( ) -> Self {
2501+ UserTypeProjections { contents : vec ! [ ] }
2502+ }
2503+
2504+ pub fn from_projections ( projs : impl Iterator < Item =( UserTypeProjection < ' tcx > , Span ) > ) -> Self {
2505+ UserTypeProjections { contents : projs. collect ( ) }
2506+ }
2507+
2508+ pub fn projections_and_spans ( & self ) -> impl Iterator < Item =& ( UserTypeProjection < ' tcx > , Span ) > {
2509+ self . contents . iter ( )
2510+ }
2511+
2512+ pub fn projections ( & self ) -> impl Iterator < Item =& UserTypeProjection < ' tcx > > {
2513+ self . contents . iter ( ) . map ( |& ( ref user_type, _span) | user_type)
2514+ }
2515+ }
2516+
2517+ /// Encodes the effect of a user-supplied type annotation on the
2518+ /// subcomponents of a pattern. The effect is determined by applying the
2519+ /// given list of proejctions to some underlying base type. Often,
2520+ /// the projection element list `projs` is empty, in which case this
2521+ /// directly encodes a type in `base`. But in the case of complex patterns with
2522+ /// subpatterns and bindings, we want to apply only a *part* of the type to a variable,
2523+ /// in which case the `projs` vector is used.
2524+ ///
2525+ /// Examples:
2526+ ///
2527+ /// * `let x: T = ...` -- here, the `projs` vector is empty.
2528+ ///
2529+ /// * `let (x, _): T = ...` -- here, the `projs` vector would contain
2530+ /// `field[0]` (aka `.0`), indicating that the type of `s` is
2531+ /// determined by finding the type of the `.0` field from `T`.
2532+ #[ derive( Clone , Debug , PartialEq , Eq , Hash , RustcEncodable , RustcDecodable ) ]
2533+ pub struct UserTypeProjection < ' tcx > {
2534+ pub base : UserTypeAnnotation < ' tcx > ,
2535+ pub projs : Vec < ProjectionElem < ' tcx , ( ) , ( ) > > ,
2536+ }
2537+
2538+ impl < ' tcx > Copy for ProjectionKind < ' tcx > { }
2539+
2540+ CloneTypeFoldableAndLiftImpls ! { ProjectionKind <' tcx>, }
2541+
2542+ impl < ' tcx > TypeFoldable < ' tcx > for UserTypeProjection < ' tcx > {
2543+ fn super_fold_with < ' gcx : ' tcx , F : TypeFolder < ' gcx , ' tcx > > ( & self , folder : & mut F ) -> Self {
2544+ use mir:: ProjectionElem :: * ;
2545+
2546+ let base = self . base . fold_with ( folder) ;
2547+ let projs: Vec < _ > = self . projs
2548+ . iter ( )
2549+ . map ( |elem| {
2550+ match elem {
2551+ Deref => Deref ,
2552+ Field ( f, ( ) ) => Field ( f. clone ( ) , ( ) ) ,
2553+ Index ( ( ) ) => Index ( ( ) ) ,
2554+ elem => elem. clone ( ) ,
2555+ } } )
2556+ . collect ( ) ;
2557+
2558+ UserTypeProjection { base, projs }
2559+ }
2560+
2561+ fn super_visit_with < Vs : TypeVisitor < ' tcx > > ( & self , visitor : & mut Vs ) -> bool {
2562+ self . base . visit_with ( visitor)
2563+ // Note: there's nothing in `self.proj` to visit.
2564+ }
2565+ }
2566+
24482567newtype_index ! {
24492568 pub struct Promoted {
24502569 DEBUG_FORMAT = "promoted[{}]"
0 commit comments