@@ -155,42 +155,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
155155 fn lower_pattern_range_endpoint (
156156 & mut self ,
157157 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 ( ) ) ;
189178 }
190- } ;
191- Ok ( ( Some ( PatRangeBoundary :: Finite ( value) ) , ascr, inline_const) )
179+ kind = subpattern. kind ;
180+ }
181+ _ => break ,
192182 }
193183 }
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) ) )
194193 }
195194
196195 /// 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> {
253252 self . tcx . dcx ( ) . span_bug ( span, msg) ;
254253 }
255254
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) ;
258261
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 ) ;
261264
262265 let cmp = lo. compare_with ( hi, ty, self . tcx , self . typing_env ) ;
263266 let mut kind = PatKind :: Range ( Box :: new ( PatRange { lo, hi, end, ty } ) ) ;
@@ -298,13 +301,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
298301 // If we are handling a range with associated constants (e.g.
299302 // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
300303 // constants somewhere. Have them on the range pattern.
301- for ascription in [ lo_ascr , hi_ascr ] . into_iter ( ) . flatten ( ) {
304+ for ascription in ascriptions {
302305 kind = PatKind :: AscribeUserType {
303306 ascription,
304307 subpattern : Box :: new ( Pat { span, ty, kind } ) ,
305308 } ;
306309 }
307- for def in [ lo_inline , hi_inline ] . into_iter ( ) . flatten ( ) {
310+ for def in inline_consts {
308311 kind = PatKind :: ExpandedConstant {
309312 def_id : def. to_def_id ( ) ,
310313 is_inline : true ,
0 commit comments