@@ -27,7 +27,7 @@ use rustc_middle::ty::CanonicalUserTypeAnnotation;
27
27
use rustc_middle:: ty:: TypeVisitableExt ;
28
28
use rustc_middle:: ty:: { self , AdtDef , Region , Ty , TyCtxt , UserType } ;
29
29
use rustc_middle:: ty:: { GenericArg , GenericArgsRef } ;
30
- use rustc_span:: { Span , Symbol } ;
30
+ use rustc_span:: { ErrorGuaranteed , Span , Symbol } ;
31
31
use rustc_target:: abi:: FieldIdx ;
32
32
33
33
use std:: cmp:: Ordering ;
@@ -85,127 +85,126 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
85
85
)
86
86
}
87
87
88
- fn lower_range_expr (
88
+ fn lower_pattern_range_endpoint (
89
89
& mut self ,
90
- expr : & ' tcx hir:: Expr < ' tcx > ,
91
- ) -> ( PatKind < ' tcx > , Option < Ascription < ' tcx > > ) {
92
- match self . lower_lit ( expr) {
93
- PatKind :: AscribeUserType { ascription, subpattern : box Pat { kind, .. } } => {
94
- ( kind, Some ( ascription) )
90
+ expr : Option < & ' tcx hir:: Expr < ' tcx > > ,
91
+ ) -> Result < ( Option < mir:: Const < ' tcx > > , Option < Ascription < ' tcx > > ) , ErrorGuaranteed > {
92
+ match expr {
93
+ None => Ok ( ( None , None ) ) ,
94
+ Some ( expr) => {
95
+ let ( kind, ascr) = match self . lower_lit ( expr) {
96
+ PatKind :: AscribeUserType { ascription, subpattern : box Pat { kind, .. } } => {
97
+ ( kind, Some ( ascription) )
98
+ }
99
+ kind => ( kind, None ) ,
100
+ } ;
101
+ let value = if let PatKind :: Constant { value } = kind {
102
+ value
103
+ } else {
104
+ let msg = format ! (
105
+ "found bad range pattern endpoint `{expr:?}` outside of error recovery"
106
+ ) ;
107
+ return Err ( self . tcx . sess . delay_span_bug ( expr. span , msg) ) ;
108
+ } ;
109
+ Ok ( ( Some ( value) , ascr) )
95
110
}
96
- kind => ( kind, None ) ,
97
111
}
98
112
}
99
113
100
114
fn lower_pattern_range (
101
115
& mut self ,
102
- ty : Ty < ' tcx > ,
103
- lo : mir:: Const < ' tcx > ,
104
- hi : mir:: Const < ' tcx > ,
116
+ lo_expr : Option < & ' tcx hir:: Expr < ' tcx > > ,
117
+ hi_expr : Option < & ' tcx hir:: Expr < ' tcx > > ,
105
118
end : RangeEnd ,
119
+ ty : Ty < ' tcx > ,
106
120
span : Span ,
107
- lo_expr : Option < & hir:: Expr < ' tcx > > ,
108
- hi_expr : Option < & hir:: Expr < ' tcx > > ,
109
- ) -> PatKind < ' tcx > {
121
+ ) -> Result < PatKind < ' tcx > , ErrorGuaranteed > {
122
+ if lo_expr. is_none ( ) && hi_expr. is_none ( ) {
123
+ let msg = format ! ( "found twice-open range pattern (`..`) outside of error recovery" ) ;
124
+ return Err ( self . tcx . sess . delay_span_bug ( span, msg) ) ;
125
+ }
126
+
127
+ let ( lo, lo_ascr) = self . lower_pattern_range_endpoint ( lo_expr) ?;
128
+ let ( hi, hi_ascr) = self . lower_pattern_range_endpoint ( hi_expr) ?;
129
+
130
+ let lo = lo. unwrap_or_else ( || {
131
+ // Unwrap is ok because the type is known to be numeric.
132
+ let lo = ty. numeric_min_val ( self . tcx ) . unwrap ( ) ;
133
+ mir:: Const :: from_ty_const ( lo, self . tcx )
134
+ } ) ;
135
+ let hi = hi. unwrap_or_else ( || {
136
+ // Unwrap is ok because the type is known to be numeric.
137
+ let hi = ty. numeric_max_val ( self . tcx ) . unwrap ( ) ;
138
+ mir:: Const :: from_ty_const ( hi, self . tcx )
139
+ } ) ;
110
140
assert_eq ! ( lo. ty( ) , ty) ;
111
141
assert_eq ! ( hi. ty( ) , ty) ;
142
+
112
143
let cmp = compare_const_vals ( self . tcx , lo, hi, self . param_env ) ;
113
- let max = || {
114
- self . tcx
115
- . layout_of ( self . param_env . with_reveal_all_normalized ( self . tcx ) . and ( ty) )
116
- . ok ( )
117
- . unwrap ( )
118
- . size
119
- . unsigned_int_max ( )
120
- } ;
121
- match ( end, cmp) {
144
+ let mut kind = match ( end, cmp) {
122
145
// `x..y` where `x < y`.
123
146
// Non-empty because the range includes at least `x`.
124
147
( RangeEnd :: Excluded , Some ( Ordering :: Less ) ) => {
125
148
PatKind :: Range ( Box :: new ( PatRange { lo, hi, end } ) )
126
149
}
127
- // `x..y` where `x >= y`. The range is empty => error.
128
- ( RangeEnd :: Excluded , _) => {
129
- let mut lower_overflow = false ;
130
- let mut higher_overflow = false ;
131
- if let Some ( hir:: Expr { kind : hir:: ExprKind :: Lit ( lit) , .. } ) = lo_expr
132
- && let rustc_ast:: ast:: LitKind :: Int ( val, _) = lit. node
133
- {
134
- if lo. eval_bits ( self . tcx , self . param_env ) != val {
135
- lower_overflow = true ;
136
- self . tcx . sess . emit_err ( LiteralOutOfRange { span : lit. span , ty, max : max ( ) } ) ;
137
- }
138
- }
139
- if let Some ( hir:: Expr { kind : hir:: ExprKind :: Lit ( lit) , .. } ) = hi_expr
140
- && let rustc_ast:: ast:: LitKind :: Int ( val, _) = lit. node
141
- {
142
- if hi. eval_bits ( self . tcx , self . param_env ) != val {
143
- higher_overflow = true ;
144
- self . tcx . sess . emit_err ( LiteralOutOfRange { span : lit. span , ty, max : max ( ) } ) ;
145
- }
146
- }
147
- if !lower_overflow && !higher_overflow {
148
- self . tcx . sess . emit_err ( LowerRangeBoundMustBeLessThanUpper { span } ) ;
149
- }
150
- PatKind :: Wild
151
- }
152
150
// `x..=y` where `x == y`.
153
151
( RangeEnd :: Included , Some ( Ordering :: Equal ) ) => PatKind :: Constant { value : lo } ,
154
152
// `x..=y` where `x < y`.
155
153
( RangeEnd :: Included , Some ( Ordering :: Less ) ) => {
156
154
PatKind :: Range ( Box :: new ( PatRange { lo, hi, end } ) )
157
155
}
158
- // `x..=y` where `x > y` hence the range is empty => error.
159
- ( RangeEnd :: Included , _) => {
160
- let mut lower_overflow = false ;
161
- let mut higher_overflow = false ;
156
+ // `x..y` where `x >= y`, or `x..=y` where `x > y`. The range is empty => error.
157
+ _ => {
158
+ let max = || {
159
+ self . tcx
160
+ . layout_of ( self . param_env . with_reveal_all_normalized ( self . tcx ) . and ( ty) )
161
+ . ok ( )
162
+ . unwrap ( )
163
+ . size
164
+ . unsigned_int_max ( )
165
+ } ;
166
+ // Emit a different message if there was overflow.
162
167
if let Some ( hir:: Expr { kind : hir:: ExprKind :: Lit ( lit) , .. } ) = lo_expr
163
168
&& let rustc_ast:: ast:: LitKind :: Int ( val, _) = lit. node
164
169
{
165
170
if lo. eval_bits ( self . tcx , self . param_env ) != val {
166
- lower_overflow = true ;
167
- self . tcx . sess . emit_err ( LiteralOutOfRange { span : lit. span , ty, max : max ( ) } ) ;
171
+ return Err ( self . tcx . sess . emit_err ( LiteralOutOfRange { span : lit. span , ty, max : max ( ) } ) ) ;
168
172
}
169
173
}
170
174
if let Some ( hir:: Expr { kind : hir:: ExprKind :: Lit ( lit) , .. } ) = hi_expr
171
175
&& let rustc_ast:: ast:: LitKind :: Int ( val, _) = lit. node
172
176
{
173
177
if hi. eval_bits ( self . tcx , self . param_env ) != val {
174
- higher_overflow = true ;
175
- self . tcx . sess . emit_err ( LiteralOutOfRange { span : lit. span , ty, max : max ( ) } ) ;
178
+ return Err ( self . tcx . sess . emit_err ( LiteralOutOfRange { span : lit. span , ty, max : max ( ) } ) ) ;
176
179
}
177
180
}
178
- if !lower_overflow && !higher_overflow {
179
- self . tcx . sess . emit_err ( LowerRangeBoundMustBeLessThanOrEqualToUpper {
180
- span,
181
- teach : self . tcx . sess . teach ( & error_code ! ( E0030 ) ) . then_some ( ( ) ) ,
182
- } ) ;
183
- }
184
- PatKind :: Wild
181
+ let e = match end {
182
+ RangeEnd :: Included => {
183
+ self . tcx . sess . emit_err ( LowerRangeBoundMustBeLessThanOrEqualToUpper {
184
+ span,
185
+ teach : self . tcx . sess . teach ( & error_code ! ( E0030 ) ) . then_some ( ( ) ) ,
186
+ } )
187
+ }
188
+ RangeEnd :: Excluded => {
189
+ self . tcx . sess . emit_err ( LowerRangeBoundMustBeLessThanUpper { span } )
190
+ }
191
+ } ;
192
+ return Err ( e) ;
185
193
}
186
- }
187
- }
194
+ } ;
188
195
189
- fn normalize_range_pattern_ends (
190
- & self ,
191
- ty : Ty < ' tcx > ,
192
- lo : Option < & PatKind < ' tcx > > ,
193
- hi : Option < & PatKind < ' tcx > > ,
194
- ) -> Option < ( mir:: Const < ' tcx > , mir:: Const < ' tcx > ) > {
195
- match ( lo, hi) {
196
- ( Some ( PatKind :: Constant { value : lo } ) , Some ( PatKind :: Constant { value : hi } ) ) => {
197
- Some ( ( * lo, * hi) )
198
- }
199
- ( Some ( PatKind :: Constant { value : lo } ) , None ) => {
200
- let hi = ty. numeric_max_val ( self . tcx ) ?;
201
- Some ( ( * lo, mir:: Const :: from_ty_const ( hi, self . tcx ) ) )
202
- }
203
- ( None , Some ( PatKind :: Constant { value : hi } ) ) => {
204
- let lo = ty. numeric_min_val ( self . tcx ) ?;
205
- Some ( ( mir:: Const :: from_ty_const ( lo, self . tcx ) , * hi) )
196
+ // If we are handling a range with associated constants (e.g.
197
+ // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
198
+ // constants somewhere. Have them on the range pattern.
199
+ for ascr in [ lo_ascr, hi_ascr] {
200
+ if let Some ( ascription) = ascr {
201
+ kind = PatKind :: AscribeUserType {
202
+ ascription,
203
+ subpattern : Box :: new ( Pat { span, ty, kind } ) ,
204
+ } ;
206
205
}
207
- _ => None ,
208
206
}
207
+ Ok ( kind)
209
208
}
210
209
211
210
#[ instrument( skip( self ) , level = "debug" ) ]
@@ -220,37 +219,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
220
219
221
220
hir:: PatKind :: Range ( ref lo_expr, ref hi_expr, end) => {
222
221
let ( lo_expr, hi_expr) = ( lo_expr. as_deref ( ) , hi_expr. as_deref ( ) ) ;
223
- let lo_span = lo_expr. map_or ( pat. span , |e| e. span ) ;
224
- let lo = lo_expr. map ( |e| self . lower_range_expr ( e) ) ;
225
- let hi = hi_expr. map ( |e| self . lower_range_expr ( e) ) ;
226
-
227
- let ( lp, hp) = ( lo. as_ref ( ) . map ( |( x, _) | x) , hi. as_ref ( ) . map ( |( x, _) | x) ) ;
228
- let mut kind = match self . normalize_range_pattern_ends ( ty, lp, hp) {
229
- Some ( ( lc, hc) ) => {
230
- self . lower_pattern_range ( ty, lc, hc, end, lo_span, lo_expr, hi_expr)
231
- }
232
- None => {
233
- let msg = format ! (
234
- "found bad range pattern `{:?}` outside of error recovery" ,
235
- ( & lo, & hi) ,
236
- ) ;
237
- self . tcx . sess . delay_span_bug ( pat. span , msg) ;
238
- PatKind :: Wild
239
- }
240
- } ;
241
-
242
- // If we are handling a range with associated constants (e.g.
243
- // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
244
- // constants somewhere. Have them on the range pattern.
245
- for end in & [ lo, hi] {
246
- if let Some ( ( _, Some ( ascription) ) ) = end {
247
- let subpattern = Box :: new ( Pat { span : pat. span , ty, kind } ) ;
248
- kind =
249
- PatKind :: AscribeUserType { ascription : ascription. clone ( ) , subpattern } ;
250
- }
251
- }
252
-
253
- kind
222
+ let span = lo_expr. map_or ( span, |e| e. span ) ;
223
+ // FIXME?: returning `_` can cause inaccurate "unreachable" warnings. This can be
224
+ // fixed by returning `PatKind::Const(ConstKind::Error(...))` if #115937 gets
225
+ // merged.
226
+ self . lower_pattern_range ( lo_expr, hi_expr, end, ty, span) . unwrap_or ( PatKind :: Wild )
254
227
}
255
228
256
229
hir:: PatKind :: Path ( ref qpath) => {
0 commit comments