@@ -155,42 +155,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
155
155
fn lower_pattern_range_endpoint (
156
156
& mut self ,
157
157
expr : Option < & ' tcx hir:: PatExpr < ' tcx > > ,
158
- ) -> Result <
159
- ( Option < PatRangeBoundary < ' tcx > > , Option < Ascription < ' tcx > > , Option < LocalDefId > ) ,
160
- ErrorGuaranteed ,
161
- > {
162
- match expr {
163
- None => Ok ( ( None , None , None ) ) ,
164
- Some ( expr) => {
165
- let ( kind, ascr, inline_const) = match self . lower_lit ( expr) {
166
- PatKind :: ExpandedConstant { subpattern, def_id, is_inline : true } => {
167
- ( subpattern. kind , None , def_id. as_local ( ) )
168
- }
169
- PatKind :: ExpandedConstant { subpattern, is_inline : false , .. } => {
170
- ( subpattern. kind , None , None )
171
- }
172
- PatKind :: AscribeUserType { ascription, subpattern : box Pat { kind, .. } } => {
173
- ( kind, Some ( ascription) , None )
174
- }
175
- kind => ( kind, None , None ) ,
176
- } ;
177
- let value = match kind {
178
- PatKind :: Constant { value } => value,
179
- PatKind :: ExpandedConstant { subpattern, .. }
180
- if let PatKind :: Constant { value } = subpattern. kind =>
181
- {
182
- value
183
- }
184
- _ => {
185
- let msg = format ! (
186
- "found bad range pattern endpoint `{expr:?}` outside of error recovery"
187
- ) ;
188
- return Err ( self . tcx . dcx ( ) . span_delayed_bug ( expr. span , msg) ) ;
158
+ // Out-parameters collecting extra data to be reapplied by the caller
159
+ ascriptions : & mut Vec < Ascription < ' tcx > > ,
160
+ inline_consts : & mut Vec < LocalDefId > ,
161
+ ) -> Result < Option < PatRangeBoundary < ' tcx > > , ErrorGuaranteed > {
162
+ let Some ( expr) = expr else { return Ok ( None ) } ;
163
+
164
+ // Lower the endpoint into a temporary `PatKind` that will then be
165
+ // deconstructed to obtain the constant value and other data.
166
+ let mut kind: PatKind < ' tcx > = self . lower_lit ( expr) ;
167
+
168
+ // Unpeel any ascription or inline-const wrapper nodes.
169
+ loop {
170
+ match kind {
171
+ PatKind :: AscribeUserType { ascription, subpattern } => {
172
+ ascriptions. push ( ascription) ;
173
+ kind = subpattern. kind ;
174
+ }
175
+ PatKind :: ExpandedConstant { is_inline, def_id, subpattern } => {
176
+ if is_inline {
177
+ inline_consts. extend ( def_id. as_local ( ) ) ;
189
178
}
190
- } ;
191
- Ok ( ( Some ( PatRangeBoundary :: Finite ( value) ) , ascr, inline_const) )
179
+ kind = subpattern. kind ;
180
+ }
181
+ _ => break ,
192
182
}
193
183
}
184
+
185
+ // The unpeeled kind should now be a constant, giving us the endpoint value.
186
+ let PatKind :: Constant { value } = kind else {
187
+ let msg =
188
+ format ! ( "found bad range pattern endpoint `{expr:?}` outside of error recovery" ) ;
189
+ return Err ( self . tcx . dcx ( ) . span_delayed_bug ( expr. span , msg) ) ;
190
+ } ;
191
+
192
+ Ok ( Some ( PatRangeBoundary :: Finite ( value) ) )
194
193
}
195
194
196
195
/// Overflowing literals are linted against in a late pass. This is mostly fine, except when we
@@ -253,11 +252,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
253
252
self . tcx . dcx ( ) . span_bug ( span, msg) ;
254
253
}
255
254
256
- let ( lo, lo_ascr, lo_inline) = self . lower_pattern_range_endpoint ( lo_expr) ?;
257
- let ( hi, hi_ascr, hi_inline) = self . lower_pattern_range_endpoint ( hi_expr) ?;
255
+ // Collect extra data while lowering the endpoints, to be reapplied later.
256
+ let mut ascriptions = vec ! [ ] ;
257
+ let mut inline_consts = vec ! [ ] ;
258
+
259
+ let mut lower_endpoint =
260
+ |expr| self . lower_pattern_range_endpoint ( expr, & mut ascriptions, & mut inline_consts) ;
258
261
259
- let lo = lo . unwrap_or ( PatRangeBoundary :: NegInfinity ) ;
260
- let hi = hi . unwrap_or ( PatRangeBoundary :: PosInfinity ) ;
262
+ let lo = lower_endpoint ( lo_expr ) ? . unwrap_or ( PatRangeBoundary :: NegInfinity ) ;
263
+ let hi = lower_endpoint ( hi_expr ) ? . unwrap_or ( PatRangeBoundary :: PosInfinity ) ;
261
264
262
265
let cmp = lo. compare_with ( hi, ty, self . tcx , self . typing_env ) ;
263
266
let mut kind = PatKind :: Range ( Box :: new ( PatRange { lo, hi, end, ty } ) ) ;
@@ -298,13 +301,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
298
301
// If we are handling a range with associated constants (e.g.
299
302
// `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
300
303
// constants somewhere. Have them on the range pattern.
301
- for ascription in [ lo_ascr , hi_ascr ] . into_iter ( ) . flatten ( ) {
304
+ for ascription in ascriptions {
302
305
kind = PatKind :: AscribeUserType {
303
306
ascription,
304
307
subpattern : Box :: new ( Pat { span, ty, kind } ) ,
305
308
} ;
306
309
}
307
- for def in [ lo_inline , hi_inline ] . into_iter ( ) . flatten ( ) {
310
+ for def in inline_consts {
308
311
kind = PatKind :: ExpandedConstant {
309
312
def_id : def. to_def_id ( ) ,
310
313
is_inline : true ,
0 commit comments