@@ -13,14 +13,15 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
13
13
use rustc_hir:: pat_util:: EnumerateAndAdjustIterator ;
14
14
use rustc_hir:: { self as hir, LangItem , RangeEnd } ;
15
15
use rustc_index:: Idx ;
16
+ use rustc_infer:: infer:: TyCtxtInferExt ;
16
17
use rustc_middle:: mir:: interpret:: LitToConstInput ;
17
18
use rustc_middle:: thir:: {
18
19
Ascription , FieldPat , LocalVarId , Pat , PatKind , PatRange , PatRangeBoundary ,
19
20
} ;
20
21
use rustc_middle:: ty:: layout:: IntegerExt ;
21
- use rustc_middle:: ty:: { self , CanonicalUserTypeAnnotation , Ty , TyCtxt , TypeVisitableExt } ;
22
+ use rustc_middle:: ty:: { self , CanonicalUserTypeAnnotation , Ty , TyCtxt , TypingMode } ;
22
23
use rustc_middle:: { bug, span_bug} ;
23
- use rustc_span:: def_id:: LocalDefId ;
24
+ use rustc_span:: def_id:: DefId ;
24
25
use rustc_span:: { ErrorGuaranteed , Span } ;
25
26
use tracing:: { debug, instrument} ;
26
27
@@ -124,7 +125,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
124
125
expr : Option < & ' tcx hir:: PatExpr < ' tcx > > ,
125
126
// Out-parameters collecting extra data to be reapplied by the caller
126
127
ascriptions : & mut Vec < Ascription < ' tcx > > ,
127
- inline_consts : & mut Vec < LocalDefId > ,
128
+ expanded_consts : & mut Vec < DefId > ,
128
129
) -> Result < Option < PatRangeBoundary < ' tcx > > , ErrorGuaranteed > {
129
130
let Some ( expr) = expr else { return Ok ( None ) } ;
130
131
@@ -139,10 +140,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
139
140
ascriptions. push ( ascription) ;
140
141
kind = subpattern. kind ;
141
142
}
142
- PatKind :: ExpandedConstant { is_inline, def_id, subpattern } => {
143
- if is_inline {
144
- inline_consts. extend ( def_id. as_local ( ) ) ;
145
- }
143
+ PatKind :: ExpandedConstant { def_id, subpattern } => {
144
+ expanded_consts. push ( def_id) ;
146
145
kind = subpattern. kind ;
147
146
}
148
147
_ => break ,
@@ -221,10 +220,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
221
220
222
221
// Collect extra data while lowering the endpoints, to be reapplied later.
223
222
let mut ascriptions = vec ! [ ] ;
224
- let mut inline_consts = vec ! [ ] ;
223
+ let mut expanded_consts = vec ! [ ] ;
225
224
226
225
let mut lower_endpoint =
227
- |expr| self . lower_pattern_range_endpoint ( expr, & mut ascriptions, & mut inline_consts ) ;
226
+ |expr| self . lower_pattern_range_endpoint ( expr, & mut ascriptions, & mut expanded_consts ) ;
228
227
229
228
let lo = lower_endpoint ( lo_expr) ?. unwrap_or ( PatRangeBoundary :: NegInfinity ) ;
230
229
let hi = lower_endpoint ( hi_expr) ?. unwrap_or ( PatRangeBoundary :: PosInfinity ) ;
@@ -269,17 +268,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
269
268
// `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
270
269
// constants somewhere. Have them on the range pattern.
271
270
for ascription in ascriptions {
272
- kind = PatKind :: AscribeUserType {
273
- ascription,
274
- subpattern : Box :: new ( Pat { span, ty, kind } ) ,
275
- } ;
271
+ let subpattern = Box :: new ( Pat { span, ty, kind } ) ;
272
+ kind = PatKind :: AscribeUserType { ascription, subpattern } ;
276
273
}
277
- for def in inline_consts {
278
- kind = PatKind :: ExpandedConstant {
279
- def_id : def. to_def_id ( ) ,
280
- is_inline : true ,
281
- subpattern : Box :: new ( Pat { span, ty, kind } ) ,
282
- } ;
274
+ for def_id in expanded_consts {
275
+ let subpattern = Box :: new ( Pat { span, ty, kind } ) ;
276
+ kind = PatKind :: ExpandedConstant { def_id, subpattern } ;
283
277
}
284
278
Ok ( kind)
285
279
}
@@ -569,15 +563,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
569
563
// Lower the named constant to a THIR pattern.
570
564
let args = self . typeck_results . node_args ( id) ;
571
565
let c = ty:: Const :: new_unevaluated ( self . tcx , ty:: UnevaluatedConst { def : def_id, args } ) ;
572
- let subpattern = self . const_to_pat ( c, ty, id, span) ;
573
-
574
- // Wrap the pattern in a marker node to indicate that it is the result
575
- // of lowering a named constant. This marker is used for improved
576
- // diagnostics in some situations, but has no effect at runtime.
577
- let mut pattern = {
578
- let kind = PatKind :: ExpandedConstant { subpattern, def_id, is_inline : false } ;
579
- Box :: new ( Pat { span, ty, kind } )
580
- } ;
566
+ let mut pattern = self . const_to_pat ( c, ty, id, span) ;
581
567
582
568
// If this is an associated constant with an explicit user-written
583
569
// type, add an ascription node (e.g. `<Foo<'a> as MyTrait>::CONST`).
@@ -614,18 +600,37 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
614
600
let ty = tcx. typeck ( def_id) . node_type ( block. hir_id ) ;
615
601
616
602
let typeck_root_def_id = tcx. typeck_root_def_id ( def_id. to_def_id ( ) ) ;
617
- let parent_args =
618
- tcx. erase_regions ( ty:: GenericArgs :: identity_for_item ( tcx, typeck_root_def_id) ) ;
603
+ let parent_args = ty:: GenericArgs :: identity_for_item ( tcx, typeck_root_def_id) ;
619
604
let args = ty:: InlineConstArgs :: new ( tcx, ty:: InlineConstArgsParts { parent_args, ty } ) . args ;
620
605
621
- debug_assert ! ( !args. has_free_regions( ) ) ;
622
-
623
606
let ct = ty:: UnevaluatedConst { def : def_id. to_def_id ( ) , args } ;
624
- let subpattern = self . const_to_pat ( ty:: Const :: new_unevaluated ( self . tcx , ct) , ty, id, span) ;
625
-
626
- // Wrap the pattern in a marker node to indicate that it is the result
627
- // of lowering an inline const block.
628
- PatKind :: ExpandedConstant { subpattern, def_id : def_id. to_def_id ( ) , is_inline : true }
607
+ let c = ty:: Const :: new_unevaluated ( self . tcx , ct) ;
608
+ let pattern = self . const_to_pat ( c, ty, id, span) ;
609
+
610
+ // Apply a type ascription for the inline constant.
611
+ let annotation = {
612
+ let infcx = tcx. infer_ctxt ( ) . build ( TypingMode :: non_body_analysis ( ) ) ;
613
+ let args = ty:: InlineConstArgs :: new (
614
+ tcx,
615
+ ty:: InlineConstArgsParts { parent_args, ty : infcx. next_ty_var ( span) } ,
616
+ )
617
+ . args ;
618
+ infcx. canonicalize_user_type_annotation ( ty:: UserType :: new ( ty:: UserTypeKind :: TypeOf (
619
+ def_id. to_def_id ( ) ,
620
+ ty:: UserArgs { args, user_self_ty : None } ,
621
+ ) ) )
622
+ } ;
623
+ let annotation =
624
+ CanonicalUserTypeAnnotation { user_ty : Box :: new ( annotation) , span, inferred_ty : ty } ;
625
+ PatKind :: AscribeUserType {
626
+ subpattern : pattern,
627
+ ascription : Ascription {
628
+ annotation,
629
+ // Note that we use `Contravariant` here. See the `variance` field documentation
630
+ // for details.
631
+ variance : ty:: Contravariant ,
632
+ } ,
633
+ }
629
634
}
630
635
631
636
/// Lowers the kinds of "expression" that can appear in a HIR pattern:
@@ -637,43 +642,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
637
642
expr : & ' tcx hir:: PatExpr < ' tcx > ,
638
643
pat_ty : Option < Ty < ' tcx > > ,
639
644
) -> PatKind < ' tcx > {
640
- let ( lit, neg) = match & expr. kind {
641
- hir:: PatExprKind :: Path ( qpath) => {
642
- return self . lower_path ( qpath, expr. hir_id , expr. span ) . kind ;
643
- }
645
+ match & expr. kind {
646
+ hir:: PatExprKind :: Path ( qpath) => self . lower_path ( qpath, expr. hir_id , expr. span ) . kind ,
644
647
hir:: PatExprKind :: ConstBlock ( anon_const) => {
645
- return self . lower_inline_const ( anon_const, expr. hir_id , expr. span ) ;
648
+ self . lower_inline_const ( anon_const, expr. hir_id , expr. span )
646
649
}
647
- hir:: PatExprKind :: Lit { lit, negated } => ( lit, * negated) ,
648
- } ;
649
-
650
- // We handle byte string literal patterns by using the pattern's type instead of the
651
- // literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
652
- // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
653
- // pattern's type means we'll properly translate it to a slice reference pattern. This works
654
- // because slices and arrays have the same valtree representation.
655
- // HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if
656
- // `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR.
657
- // FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is
658
- // superseded by a more general implementation of deref patterns.
659
- let ct_ty = match pat_ty {
660
- Some ( pat_ty)
661
- if let ty:: Adt ( def, _) = * pat_ty. kind ( )
662
- && self . tcx . is_lang_item ( def. did ( ) , LangItem :: String ) =>
663
- {
664
- if !self . tcx . features ( ) . string_deref_patterns ( ) {
665
- span_bug ! (
666
- expr. span,
667
- "matching on `String` went through without enabling string_deref_patterns"
668
- ) ;
669
- }
670
- self . typeck_results . node_type ( expr. hir_id )
650
+ hir:: PatExprKind :: Lit { lit, negated } => {
651
+ // We handle byte string literal patterns by using the pattern's type instead of the
652
+ // literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
653
+ // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
654
+ // pattern's type means we'll properly translate it to a slice reference pattern. This works
655
+ // because slices and arrays have the same valtree representation.
656
+ // HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if
657
+ // `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR.
658
+ // FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is
659
+ // superseded by a more general implementation of deref patterns.
660
+ let ct_ty = match pat_ty {
661
+ Some ( pat_ty)
662
+ if let ty:: Adt ( def, _) = * pat_ty. kind ( )
663
+ && self . tcx . is_lang_item ( def. did ( ) , LangItem :: String ) =>
664
+ {
665
+ if !self . tcx . features ( ) . string_deref_patterns ( ) {
666
+ span_bug ! (
667
+ expr. span,
668
+ "matching on `String` went through without enabling string_deref_patterns"
669
+ ) ;
670
+ }
671
+ self . typeck_results . node_type ( expr. hir_id )
672
+ }
673
+ Some ( pat_ty) => pat_ty,
674
+ None => self . typeck_results . node_type ( expr. hir_id ) ,
675
+ } ;
676
+ let lit_input = LitToConstInput { lit : & lit. node , ty : ct_ty, neg : * negated } ;
677
+ let constant = self . tcx . at ( expr. span ) . lit_to_const ( lit_input) ;
678
+ self . const_to_pat ( constant, ct_ty, expr. hir_id , lit. span ) . kind
671
679
}
672
- Some ( pat_ty) => pat_ty,
673
- None => self . typeck_results . node_type ( expr. hir_id ) ,
674
- } ;
675
- let lit_input = LitToConstInput { lit : & lit. node , ty : ct_ty, neg } ;
676
- let constant = self . tcx . at ( expr. span ) . lit_to_const ( lit_input) ;
677
- self . const_to_pat ( constant, ct_ty, expr. hir_id , lit. span ) . kind
680
+ }
678
681
}
679
682
}
0 commit comments