@@ -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.
@@ -169,18 +174,7 @@ pub enum PatternKind<'tcx> {
169174 } ,
170175}
171176
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 ) ]
184178pub struct PatternRange < ' tcx > {
185179 pub lo : ty:: Const < ' tcx > ,
186180 pub hi : ty:: Const < ' tcx > ,
@@ -407,6 +401,19 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
407401 )
408402 }
409403
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+
410417 fn lower_pattern_unadjusted ( & mut self , pat : & ' tcx hir:: Pat ) -> Pattern < ' tcx > {
411418 let mut ty = self . tables . node_type ( pat. hir_id ) ;
412419
@@ -416,14 +423,10 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
416423 PatKind :: Lit ( ref value) => self . lower_lit ( value) ,
417424
418425 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) {
427430 ( PatternKind :: Constant { value : lo } , PatternKind :: Constant { value : hi } ) => {
428431 use std:: cmp:: Ordering ;
429432 let cmp = compare_const_vals (
@@ -472,17 +475,33 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
472475 PatternKind :: Wild
473476 }
474477 }
475- }
478+ } ,
476479 ref pats => {
477480 self . tcx . sess . delay_span_bug (
478481 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+ ) ,
481486 ) ;
482487
483488 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+ } ;
484501 }
485502 }
503+
504+ kind
486505 }
487506
488507 PatKind :: Path ( ref qpath) => {
@@ -758,9 +777,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
758777 ty,
759778 kind : Box :: new ( kind) ,
760779 } ,
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+ } ,
764785 } ;
765786 }
766787
@@ -810,11 +831,13 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
810831 kind : Box :: new (
811832 PatternKind :: AscribeUserType {
812833 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+ } ,
818841 }
819842 ) ,
820843 ty : value. ty ,
@@ -1107,14 +1130,18 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
11071130 PatternKind :: Wild => PatternKind :: Wild ,
11081131 PatternKind :: AscribeUserType {
11091132 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+ } ,
11131138 } => PatternKind :: AscribeUserType {
11141139 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+ } ,
11181145 } ,
11191146 PatternKind :: Binding {
11201147 mutability,
0 commit comments