@@ -58,7 +58,7 @@ pub struct Pattern<'tcx> {
5858}
5959
6060
61- #[ derive( Clone , Debug ) ]
61+ #[ derive( Copy , Clone , Debug , PartialEq ) ]
6262pub struct PatternTypeProjection < ' tcx > {
6363 pub user_ty : CanonicalUserType < ' tcx > ,
6464}
@@ -87,33 +87,38 @@ impl<'tcx> PatternTypeProjection<'tcx> {
8787 }
8888}
8989
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+
90115#[ derive( Clone , Debug ) ]
91116pub enum PatternKind < ' tcx > {
92117 Wild ,
93118
94119 AscribeUserType {
95- user_ty : PatternTypeProjection < ' tcx > ,
120+ ascription : Ascription < ' tcx > ,
96121 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 ,
117122 } ,
118123
119124 /// x, ref x, x @ P, etc
@@ -167,18 +172,7 @@ pub enum PatternKind<'tcx> {
167172 } ,
168173}
169174
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 ) ]
182176pub struct PatternRange < ' tcx > {
183177 pub lo : ty:: Const < ' tcx > ,
184178 pub hi : ty:: Const < ' tcx > ,
@@ -405,6 +399,19 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
405399 )
406400 }
407401
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+
408415 fn lower_pattern_unadjusted ( & mut self , pat : & ' tcx hir:: Pat ) -> Pattern < ' tcx > {
409416 let mut ty = self . tables . node_id_to_type ( pat. hir_id ) ;
410417
@@ -414,14 +421,10 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
414421 PatKind :: Lit ( ref value) => self . lower_lit ( value) ,
415422
416423 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) {
425428 ( PatternKind :: Constant { value : lo } , PatternKind :: Constant { value : hi } ) => {
426429 use std:: cmp:: Ordering ;
427430 let cmp = compare_const_vals (
@@ -470,17 +473,33 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
470473 PatternKind :: Wild
471474 }
472475 }
473- }
476+ } ,
474477 ref pats => {
475478 self . tcx . sess . delay_span_bug (
476479 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+ ) ,
479484 ) ;
480485
481486 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+ } ;
482499 }
483500 }
501+
502+ kind
484503 }
485504
486505 PatKind :: Path ( ref qpath) => {
@@ -756,9 +775,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
756775 ty,
757776 kind : Box :: new ( kind) ,
758777 } ,
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+ } ,
762783 } ;
763784 }
764785
@@ -808,11 +829,13 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
808829 kind : Box :: new (
809830 PatternKind :: AscribeUserType {
810831 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+ } ,
816839 }
817840 ) ,
818841 ty : value. ty ,
@@ -1105,14 +1128,18 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
11051128 PatternKind :: Wild => PatternKind :: Wild ,
11061129 PatternKind :: AscribeUserType {
11071130 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+ } ,
11111136 } => PatternKind :: AscribeUserType {
11121137 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+ } ,
11161143 } ,
11171144 PatternKind :: Binding {
11181145 mutability,
0 commit comments