@@ -58,7 +58,7 @@ pub struct Pattern<'tcx> {
58
58
}
59
59
60
60
61
- #[ derive( Clone , Debug ) ]
61
+ #[ derive( Copy , Clone , Debug , PartialEq ) ]
62
62
pub struct PatternTypeProjection < ' tcx > {
63
63
pub user_ty : CanonicalUserType < ' tcx > ,
64
64
}
@@ -87,33 +87,38 @@ impl<'tcx> PatternTypeProjection<'tcx> {
87
87
}
88
88
}
89
89
90
+ #[ derive( Copy , Clone , Debug , PartialEq ) ]
91
+ pub struct Ascription < ' tcx > {
92
+ pub user_ty : PatternTypeProjection < ' tcx > ,
93
+ /// Variance to use when relating the type `user_ty` to the **type of the value being
94
+ /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
95
+ /// have a type that is some subtype of the ascribed type.
96
+ ///
97
+ /// Note that this variance does not apply for any bindings within subpatterns. The type
98
+ /// assigned to those bindings must be exactly equal to the `user_ty` given here.
99
+ ///
100
+ /// The only place where this field is not `Covariant` is when matching constants, where
101
+ /// we currently use `Contravariant` -- this is because the constant type just needs to
102
+ /// be "comparable" to the type of the input value. So, for example:
103
+ ///
104
+ /// ```text
105
+ /// match x { "foo" => .. }
106
+ /// ```
107
+ ///
108
+ /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
109
+ /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
110
+ /// of the old type-check for now. See #57280 for details.
111
+ pub variance : ty:: Variance ,
112
+ pub user_ty_span : Span ,
113
+ }
114
+
90
115
#[ derive( Clone , Debug ) ]
91
116
pub enum PatternKind < ' tcx > {
92
117
Wild ,
93
118
94
119
AscribeUserType {
95
- user_ty : PatternTypeProjection < ' tcx > ,
120
+ ascription : Ascription < ' tcx > ,
96
121
subpattern : Pattern < ' tcx > ,
97
- /// Variance to use when relating the type `user_ty` to the **type of the value being
98
- /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
99
- /// have a type that is some subtype of the ascribed type.
100
- ///
101
- /// Note that this variance does not apply for any bindings within subpatterns. The type
102
- /// assigned to those bindings must be exactly equal to the `user_ty` given here.
103
- ///
104
- /// The only place where this field is not `Covariant` is when matching constants, where
105
- /// we currently use `Contravariant` -- this is because the constant type just needs to
106
- /// be "comparable" to the type of the input value. So, for example:
107
- ///
108
- /// ```text
109
- /// match x { "foo" => .. }
110
- /// ```
111
- ///
112
- /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
113
- /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
114
- /// of the old type-check for now. See #57280 for details.
115
- variance : ty:: Variance ,
116
- user_ty_span : Span ,
117
122
} ,
118
123
119
124
/// `x`, `ref x`, `x @ P`, etc.
@@ -169,18 +174,7 @@ pub enum PatternKind<'tcx> {
169
174
} ,
170
175
}
171
176
172
- impl < ' tcx > PatternKind < ' tcx > {
173
- /// If this is a `PatternKind::AscribeUserType` then return the subpattern kind, otherwise
174
- /// return this pattern kind.
175
- fn with_user_type_ascription_subpattern ( self ) -> Self {
176
- match self {
177
- PatternKind :: AscribeUserType { subpattern : Pattern { box kind, .. } , .. } => kind,
178
- kind => kind,
179
- }
180
- }
181
- }
182
-
183
- #[ derive( Clone , Copy , Debug , PartialEq ) ]
177
+ #[ derive( Copy , Clone , Debug , PartialEq ) ]
184
178
pub struct PatternRange < ' tcx > {
185
179
pub lo : ty:: Const < ' tcx > ,
186
180
pub hi : ty:: Const < ' tcx > ,
@@ -407,6 +401,19 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
407
401
)
408
402
}
409
403
404
+ fn lower_range_expr (
405
+ & mut self ,
406
+ expr : & ' tcx hir:: Expr ,
407
+ ) -> ( PatternKind < ' tcx > , Option < Ascription < ' tcx > > ) {
408
+ match self . lower_lit ( expr) {
409
+ PatternKind :: AscribeUserType {
410
+ ascription : lo_ascription,
411
+ subpattern : Pattern { kind : box kind, .. } ,
412
+ } => ( kind, Some ( lo_ascription) ) ,
413
+ kind => ( kind, None ) ,
414
+ }
415
+ }
416
+
410
417
fn lower_pattern_unadjusted ( & mut self , pat : & ' tcx hir:: Pat ) -> Pattern < ' tcx > {
411
418
let mut ty = self . tables . node_type ( pat. hir_id ) ;
412
419
@@ -416,14 +423,10 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
416
423
PatKind :: Lit ( ref value) => self . lower_lit ( value) ,
417
424
418
425
PatKind :: Range ( ref lo_expr, ref hi_expr, end) => {
419
- match (
420
- // Look for `PatternKind::Constant` patterns inside of any
421
- // `PatternKind::AscribeUserType` patterns. Type ascriptions can be safely
422
- // ignored for the purposes of lowering a range correctly - these are checked
423
- // elsewhere for well-formedness.
424
- self . lower_lit ( lo_expr) . with_user_type_ascription_subpattern ( ) ,
425
- self . lower_lit ( hi_expr) . with_user_type_ascription_subpattern ( ) ,
426
- ) {
426
+ let ( lo, lo_ascription) = self . lower_range_expr ( lo_expr) ;
427
+ let ( hi, hi_ascription) = self . lower_range_expr ( hi_expr) ;
428
+
429
+ let mut kind = match ( lo, hi) {
427
430
( PatternKind :: Constant { value : lo } , PatternKind :: Constant { value : hi } ) => {
428
431
use std:: cmp:: Ordering ;
429
432
let cmp = compare_const_vals (
@@ -472,17 +475,33 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
472
475
PatternKind :: Wild
473
476
}
474
477
}
475
- }
478
+ } ,
476
479
ref pats => {
477
480
self . tcx . sess . delay_span_bug (
478
481
pat. span ,
479
- & format ! ( "found bad range pattern `{:?}` outside of error recovery" ,
480
- pats) ,
482
+ & format ! (
483
+ "found bad range pattern `{:?}` outside of error recovery" ,
484
+ pats,
485
+ ) ,
481
486
) ;
482
487
483
488
PatternKind :: Wild
489
+ } ,
490
+ } ;
491
+
492
+ // If we are handling a range with associated constants (e.g.
493
+ // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
494
+ // constants somewhere. Have them on the range pattern.
495
+ for ascription in & [ lo_ascription, hi_ascription] {
496
+ if let Some ( ascription) = ascription {
497
+ kind = PatternKind :: AscribeUserType {
498
+ ascription : * ascription,
499
+ subpattern : Pattern { span : pat. span , ty, kind : Box :: new ( kind) , } ,
500
+ } ;
484
501
}
485
502
}
503
+
504
+ kind
486
505
}
487
506
488
507
PatKind :: Path ( ref qpath) => {
@@ -758,9 +777,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
758
777
ty,
759
778
kind : Box :: new ( kind) ,
760
779
} ,
761
- user_ty : PatternTypeProjection :: from_user_type ( user_ty) ,
762
- user_ty_span : span,
763
- variance : ty:: Variance :: Covariant ,
780
+ ascription : Ascription {
781
+ user_ty : PatternTypeProjection :: from_user_type ( user_ty) ,
782
+ user_ty_span : span,
783
+ variance : ty:: Variance :: Covariant ,
784
+ } ,
764
785
} ;
765
786
}
766
787
@@ -810,11 +831,13 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
810
831
kind : Box :: new (
811
832
PatternKind :: AscribeUserType {
812
833
subpattern : pattern,
813
- /// Note that use `Contravariant` here. See the
814
- /// `variance` field documentation for details.
815
- variance : ty:: Variance :: Contravariant ,
816
- user_ty,
817
- user_ty_span : span,
834
+ ascription : Ascription {
835
+ /// Note that use `Contravariant` here. See the
836
+ /// `variance` field documentation for details.
837
+ variance : ty:: Variance :: Contravariant ,
838
+ user_ty,
839
+ user_ty_span : span,
840
+ } ,
818
841
}
819
842
) ,
820
843
ty : value. ty ,
@@ -1107,14 +1130,18 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
1107
1130
PatternKind :: Wild => PatternKind :: Wild ,
1108
1131
PatternKind :: AscribeUserType {
1109
1132
ref subpattern,
1110
- variance,
1111
- ref user_ty,
1112
- user_ty_span,
1133
+ ascription : Ascription {
1134
+ variance,
1135
+ ref user_ty,
1136
+ user_ty_span,
1137
+ } ,
1113
1138
} => PatternKind :: AscribeUserType {
1114
1139
subpattern : subpattern. fold_with ( folder) ,
1115
- user_ty : user_ty. fold_with ( folder) ,
1116
- variance,
1117
- user_ty_span,
1140
+ ascription : Ascription {
1141
+ user_ty : user_ty. fold_with ( folder) ,
1142
+ variance,
1143
+ user_ty_span,
1144
+ } ,
1118
1145
} ,
1119
1146
PatternKind :: Binding {
1120
1147
mutability,
0 commit comments