@@ -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
}
@@ -567,15 +561,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
567
561
// Lower the named constant to a THIR pattern.
568
562
let args = self . typeck_results . node_args ( id) ;
569
563
let c = ty:: Const :: new_unevaluated ( self . tcx , ty:: UnevaluatedConst { def : def_id, args } ) ;
570
- let subpattern = self . const_to_pat ( c, ty, id, span) ;
571
-
572
- // Wrap the pattern in a marker node to indicate that it is the result
573
- // of lowering a named constant. This marker is used for improved
574
- // diagnostics in some situations, but has no effect at runtime.
575
- let mut pattern = {
576
- let kind = PatKind :: ExpandedConstant { subpattern, def_id, is_inline : false } ;
577
- Box :: new ( Pat { span, ty, kind } )
578
- } ;
564
+ let mut pattern = self . const_to_pat ( c, ty, id, span) ;
579
565
580
566
// If this is an associated constant with an explicit user-written
581
567
// type, add an ascription node (e.g. `<Foo<'a> as MyTrait>::CONST`).
@@ -612,18 +598,37 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
612
598
let ty = tcx. typeck ( def_id) . node_type ( block. hir_id ) ;
613
599
614
600
let typeck_root_def_id = tcx. typeck_root_def_id ( def_id. to_def_id ( ) ) ;
615
- let parent_args =
616
- tcx. erase_regions ( ty:: GenericArgs :: identity_for_item ( tcx, typeck_root_def_id) ) ;
601
+ let parent_args = ty:: GenericArgs :: identity_for_item ( tcx, typeck_root_def_id) ;
617
602
let args = ty:: InlineConstArgs :: new ( tcx, ty:: InlineConstArgsParts { parent_args, ty } ) . args ;
618
603
619
- debug_assert ! ( !args. has_free_regions( ) ) ;
620
-
621
604
let ct = ty:: UnevaluatedConst { def : def_id. to_def_id ( ) , args } ;
622
- let subpattern = self . const_to_pat ( ty:: Const :: new_unevaluated ( self . tcx , ct) , ty, id, span) ;
623
-
624
- // Wrap the pattern in a marker node to indicate that it is the result
625
- // of lowering an inline const block.
626
- PatKind :: ExpandedConstant { subpattern, def_id : def_id. to_def_id ( ) , is_inline : true }
605
+ let c = ty:: Const :: new_unevaluated ( self . tcx , ct) ;
606
+ let pattern = self . const_to_pat ( c, ty, id, span) ;
607
+
608
+ // Apply a type ascription for the inline constant.
609
+ let annotation = {
610
+ let infcx = tcx. infer_ctxt ( ) . build ( TypingMode :: non_body_analysis ( ) ) ;
611
+ let args = ty:: InlineConstArgs :: new (
612
+ tcx,
613
+ ty:: InlineConstArgsParts { parent_args, ty : infcx. next_ty_var ( span) } ,
614
+ )
615
+ . args ;
616
+ infcx. canonicalize_user_type_annotation ( ty:: UserType :: new ( ty:: UserTypeKind :: TypeOf (
617
+ def_id. to_def_id ( ) ,
618
+ ty:: UserArgs { args, user_self_ty : None } ,
619
+ ) ) )
620
+ } ;
621
+ let annotation =
622
+ CanonicalUserTypeAnnotation { user_ty : Box :: new ( annotation) , span, inferred_ty : ty } ;
623
+ PatKind :: AscribeUserType {
624
+ subpattern : pattern,
625
+ ascription : Ascription {
626
+ annotation,
627
+ // Note that we use `Contravariant` here. See the `variance` field documentation
628
+ // for details.
629
+ variance : ty:: Contravariant ,
630
+ } ,
631
+ }
627
632
}
628
633
629
634
/// Lowers the kinds of "expression" that can appear in a HIR pattern:
@@ -635,43 +640,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
635
640
expr : & ' tcx hir:: PatExpr < ' tcx > ,
636
641
pat_ty : Option < Ty < ' tcx > > ,
637
642
) -> PatKind < ' tcx > {
638
- let ( lit, neg) = match & expr. kind {
639
- hir:: PatExprKind :: Path ( qpath) => {
640
- return self . lower_path ( qpath, expr. hir_id , expr. span ) . kind ;
641
- }
643
+ match & expr. kind {
644
+ hir:: PatExprKind :: Path ( qpath) => self . lower_path ( qpath, expr. hir_id , expr. span ) . kind ,
642
645
hir:: PatExprKind :: ConstBlock ( anon_const) => {
643
- return self . lower_inline_const ( anon_const, expr. hir_id , expr. span ) ;
646
+ self . lower_inline_const ( anon_const, expr. hir_id , expr. span )
644
647
}
645
- hir:: PatExprKind :: Lit { lit, negated } => ( lit, * negated) ,
646
- } ;
647
-
648
- // We handle byte string literal patterns by using the pattern's type instead of the
649
- // literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
650
- // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
651
- // pattern's type means we'll properly translate it to a slice reference pattern. This works
652
- // because slices and arrays have the same valtree representation.
653
- // HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if
654
- // `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR.
655
- // FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is
656
- // superseded by a more general implementation of deref patterns.
657
- let ct_ty = match pat_ty {
658
- Some ( pat_ty)
659
- if let ty:: Adt ( def, _) = * pat_ty. kind ( )
660
- && self . tcx . is_lang_item ( def. did ( ) , LangItem :: String ) =>
661
- {
662
- if !self . tcx . features ( ) . string_deref_patterns ( ) {
663
- span_bug ! (
664
- expr. span,
665
- "matching on `String` went through without enabling string_deref_patterns"
666
- ) ;
667
- }
668
- self . typeck_results . node_type ( expr. hir_id )
648
+ hir:: PatExprKind :: Lit { lit, negated } => {
649
+ // We handle byte string literal patterns by using the pattern's type instead of the
650
+ // literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
651
+ // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
652
+ // pattern's type means we'll properly translate it to a slice reference pattern. This works
653
+ // because slices and arrays have the same valtree representation.
654
+ // HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if
655
+ // `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR.
656
+ // FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is
657
+ // superseded by a more general implementation of deref patterns.
658
+ let ct_ty = match pat_ty {
659
+ Some ( pat_ty)
660
+ if let ty:: Adt ( def, _) = * pat_ty. kind ( )
661
+ && self . tcx . is_lang_item ( def. did ( ) , LangItem :: String ) =>
662
+ {
663
+ if !self . tcx . features ( ) . string_deref_patterns ( ) {
664
+ span_bug ! (
665
+ expr. span,
666
+ "matching on `String` went through without enabling string_deref_patterns"
667
+ ) ;
668
+ }
669
+ self . typeck_results . node_type ( expr. hir_id )
670
+ }
671
+ Some ( pat_ty) => pat_ty,
672
+ None => self . typeck_results . node_type ( expr. hir_id ) ,
673
+ } ;
674
+ let lit_input = LitToConstInput { lit : & lit. node , ty : ct_ty, neg : * negated } ;
675
+ let constant = self . tcx . at ( expr. span ) . lit_to_const ( lit_input) ;
676
+ self . const_to_pat ( constant, ct_ty, expr. hir_id , lit. span ) . kind
669
677
}
670
- Some ( pat_ty) => pat_ty,
671
- None => self . typeck_results . node_type ( expr. hir_id ) ,
672
- } ;
673
- let lit_input = LitToConstInput { lit : & lit. node , ty : ct_ty, neg } ;
674
- let constant = self . tcx . at ( expr. span ) . lit_to_const ( lit_input) ;
675
- self . const_to_pat ( constant, ct_ty, expr. hir_id , lit. span ) . kind
678
+ }
676
679
}
677
680
}
0 commit comments