@@ -710,7 +710,7 @@ pub struct LocalDecl<'tcx> {
710
710
/// e.g. via `let x: T`, then we carry that type here. The MIR
711
711
/// borrow checker needs this information since it can affect
712
712
/// region inference.
713
- pub user_ty : Option < ( UserTypeAnnotation < ' tcx > , Span ) > ,
713
+ pub user_ty : UserTypeProjections < ' tcx > ,
714
714
715
715
/// Name of the local, used in debuginfo and pretty-printing.
716
716
///
@@ -882,7 +882,7 @@ impl<'tcx> LocalDecl<'tcx> {
882
882
LocalDecl {
883
883
mutability,
884
884
ty,
885
- user_ty : None ,
885
+ user_ty : UserTypeProjections :: none ( ) ,
886
886
name : None ,
887
887
source_info : SourceInfo {
888
888
span,
@@ -903,7 +903,7 @@ impl<'tcx> LocalDecl<'tcx> {
903
903
LocalDecl {
904
904
mutability : Mutability :: Mut ,
905
905
ty : return_ty,
906
- user_ty : None ,
906
+ user_ty : UserTypeProjections :: none ( ) ,
907
907
source_info : SourceInfo {
908
908
span,
909
909
scope : OUTERMOST_SOURCE_SCOPE ,
@@ -1674,6 +1674,10 @@ impl<'tcx> Statement<'tcx> {
1674
1674
/// Changes a statement to a nop. This is both faster than deleting instructions and avoids
1675
1675
/// invalidating statement indices in `Location`s.
1676
1676
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
+
1677
1681
self . kind = StatementKind :: Nop
1678
1682
}
1679
1683
@@ -1737,7 +1741,7 @@ pub enum StatementKind<'tcx> {
1737
1741
/// - `Contravariant` -- requires that `T_y :> T`
1738
1742
/// - `Invariant` -- requires that `T_y == T`
1739
1743
/// - `Bivariant` -- no effect
1740
- AscribeUserType ( Place < ' tcx > , ty:: Variance , UserTypeAnnotation < ' tcx > ) ,
1744
+ AscribeUserType ( Place < ' tcx > , ty:: Variance , Box < UserTypeProjection < ' tcx > > ) ,
1741
1745
1742
1746
/// No-op. Useful for deleting instructions without affecting statement indices.
1743
1747
Nop ,
@@ -1940,6 +1944,10 @@ pub type PlaceProjection<'tcx> = Projection<'tcx, Place<'tcx>, Local, Ty<'tcx>>;
1940
1944
/// and the index is a local.
1941
1945
pub type PlaceElem < ' tcx > = ProjectionElem < ' tcx , Local , Ty < ' tcx > > ;
1942
1946
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
+
1943
1951
newtype_index ! {
1944
1952
pub struct Field {
1945
1953
DEBUG_FORMAT = "field[{}]"
@@ -2445,6 +2453,117 @@ EnumLiftImpl! {
2445
2453
}
2446
2454
}
2447
2455
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
+
2448
2567
newtype_index ! {
2449
2568
pub struct Promoted {
2450
2569
DEBUG_FORMAT = "promoted[{}]"
0 commit comments