@@ -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
@@ -167,18 +172,7 @@ pub enum PatternKind<'tcx> {
167
172
} ,
168
173
}
169
174
170
- impl < ' tcx > PatternKind < ' tcx > {
171
- /// If this is a `PatternKind::AscribeUserType` then return the subpattern kind, otherwise
172
- /// return this pattern kind.
173
- fn with_user_type_ascription_subpattern ( self ) -> Self {
174
- match self {
175
- PatternKind :: AscribeUserType { subpattern : Pattern { box kind, .. } , .. } => kind,
176
- kind => kind,
177
- }
178
- }
179
- }
180
-
181
- #[ derive( Clone , Copy , Debug , PartialEq ) ]
175
+ #[ derive( Copy , Clone , Debug , PartialEq ) ]
182
176
pub struct PatternRange < ' tcx > {
183
177
pub lo : ty:: Const < ' tcx > ,
184
178
pub hi : ty:: Const < ' tcx > ,
@@ -405,6 +399,19 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
405
399
)
406
400
}
407
401
402
+ fn lower_range_expr (
403
+ & mut self ,
404
+ expr : & ' tcx hir:: Expr ,
405
+ ) -> ( PatternKind < ' tcx > , Option < Ascription < ' tcx > > ) {
406
+ match self . lower_lit ( expr) {
407
+ PatternKind :: AscribeUserType {
408
+ ascription : lo_ascription,
409
+ subpattern : Pattern { kind : box kind, .. } ,
410
+ } => ( kind, Some ( lo_ascription) ) ,
411
+ kind => ( kind, None ) ,
412
+ }
413
+ }
414
+
408
415
fn lower_pattern_unadjusted ( & mut self , pat : & ' tcx hir:: Pat ) -> Pattern < ' tcx > {
409
416
let mut ty = self . tables . node_id_to_type ( pat. hir_id ) ;
410
417
@@ -414,14 +421,10 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
414
421
PatKind :: Lit ( ref value) => self . lower_lit ( value) ,
415
422
416
423
PatKind :: Range ( ref lo_expr, ref hi_expr, end) => {
417
- match (
418
- // Look for `PatternKind::Constant` patterns inside of any
419
- // `PatternKind::AscribeUserType` patterns. Type ascriptions can be safely
420
- // ignored for the purposes of lowering a range correctly - these are checked
421
- // elsewhere for well-formedness.
422
- self . lower_lit ( lo_expr) . with_user_type_ascription_subpattern ( ) ,
423
- self . lower_lit ( hi_expr) . with_user_type_ascription_subpattern ( ) ,
424
- ) {
424
+ let ( lo, lo_ascription) = self . lower_range_expr ( lo_expr) ;
425
+ let ( hi, hi_ascription) = self . lower_range_expr ( hi_expr) ;
426
+
427
+ let mut kind = match ( lo, hi) {
425
428
( PatternKind :: Constant { value : lo } , PatternKind :: Constant { value : hi } ) => {
426
429
use std:: cmp:: Ordering ;
427
430
let cmp = compare_const_vals (
@@ -470,17 +473,33 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
470
473
PatternKind :: Wild
471
474
}
472
475
}
473
- }
476
+ } ,
474
477
ref pats => {
475
478
self . tcx . sess . delay_span_bug (
476
479
pat. span ,
477
- & format ! ( "found bad range pattern `{:?}` outside of error recovery" ,
478
- pats) ,
480
+ & format ! (
481
+ "found bad range pattern `{:?}` outside of error recovery" ,
482
+ pats,
483
+ ) ,
479
484
) ;
480
485
481
486
PatternKind :: Wild
487
+ } ,
488
+ } ;
489
+
490
+ // If we are handling a range with associated constants (e.g.
491
+ // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
492
+ // constants somewhere. Have them on the range pattern.
493
+ for ascription in & [ lo_ascription, hi_ascription] {
494
+ if let Some ( ascription) = ascription {
495
+ kind = PatternKind :: AscribeUserType {
496
+ ascription : * ascription,
497
+ subpattern : Pattern { span : pat. span , ty, kind : Box :: new ( kind) , } ,
498
+ } ;
482
499
}
483
500
}
501
+
502
+ kind
484
503
}
485
504
486
505
PatKind :: Path ( ref qpath) => {
@@ -756,9 +775,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
756
775
ty,
757
776
kind : Box :: new ( kind) ,
758
777
} ,
759
- user_ty : PatternTypeProjection :: from_user_type ( user_ty) ,
760
- user_ty_span : span,
761
- variance : ty:: Variance :: Covariant ,
778
+ ascription : Ascription {
779
+ user_ty : PatternTypeProjection :: from_user_type ( user_ty) ,
780
+ user_ty_span : span,
781
+ variance : ty:: Variance :: Covariant ,
782
+ } ,
762
783
} ;
763
784
}
764
785
@@ -808,11 +829,13 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
808
829
kind : Box :: new (
809
830
PatternKind :: AscribeUserType {
810
831
subpattern : pattern,
811
- /// Note that use `Contravariant` here. See the
812
- /// `variance` field documentation for details.
813
- variance : ty:: Variance :: Contravariant ,
814
- user_ty,
815
- user_ty_span : span,
832
+ ascription : Ascription {
833
+ /// Note that use `Contravariant` here. See the
834
+ /// `variance` field documentation for details.
835
+ variance : ty:: Variance :: Contravariant ,
836
+ user_ty,
837
+ user_ty_span : span,
838
+ } ,
816
839
}
817
840
) ,
818
841
ty : value. ty ,
@@ -1105,14 +1128,18 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
1105
1128
PatternKind :: Wild => PatternKind :: Wild ,
1106
1129
PatternKind :: AscribeUserType {
1107
1130
ref subpattern,
1108
- variance,
1109
- ref user_ty,
1110
- user_ty_span,
1131
+ ascription : Ascription {
1132
+ variance,
1133
+ ref user_ty,
1134
+ user_ty_span,
1135
+ } ,
1111
1136
} => PatternKind :: AscribeUserType {
1112
1137
subpattern : subpattern. fold_with ( folder) ,
1113
- user_ty : user_ty. fold_with ( folder) ,
1114
- variance,
1115
- user_ty_span,
1138
+ ascription : Ascription {
1139
+ user_ty : user_ty. fold_with ( folder) ,
1140
+ variance,
1141
+ user_ty_span,
1142
+ } ,
1116
1143
} ,
1117
1144
PatternKind :: Binding {
1118
1145
mutability,
0 commit comments