@@ -13,14 +13,15 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
1313use rustc_hir:: pat_util:: EnumerateAndAdjustIterator ;
1414use rustc_hir:: { self as hir, LangItem , RangeEnd } ;
1515use rustc_index:: Idx ;
16+ use rustc_infer:: infer:: TyCtxtInferExt ;
1617use rustc_middle:: mir:: interpret:: LitToConstInput ;
1718use rustc_middle:: thir:: {
1819 Ascription , FieldPat , LocalVarId , Pat , PatKind , PatRange , PatRangeBoundary ,
1920} ;
2021use 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 } ;
2223use rustc_middle:: { bug, span_bug} ;
23- use rustc_span:: def_id:: LocalDefId ;
24+ use rustc_span:: def_id:: DefId ;
2425use rustc_span:: { ErrorGuaranteed , Span } ;
2526use tracing:: { debug, instrument} ;
2627
@@ -124,7 +125,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
124125 expr : Option < & ' tcx hir:: PatExpr < ' tcx > > ,
125126 // Out-parameters collecting extra data to be reapplied by the caller
126127 ascriptions : & mut Vec < Ascription < ' tcx > > ,
127- inline_consts : & mut Vec < LocalDefId > ,
128+ expanded_consts : & mut Vec < DefId > ,
128129 ) -> Result < Option < PatRangeBoundary < ' tcx > > , ErrorGuaranteed > {
129130 let Some ( expr) = expr else { return Ok ( None ) } ;
130131
@@ -139,10 +140,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
139140 ascriptions. push ( ascription) ;
140141 kind = subpattern. kind ;
141142 }
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) ;
146145 kind = subpattern. kind ;
147146 }
148147 _ => break ,
@@ -221,10 +220,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
221220
222221 // Collect extra data while lowering the endpoints, to be reapplied later.
223222 let mut ascriptions = vec ! [ ] ;
224- let mut inline_consts = vec ! [ ] ;
223+ let mut expanded_consts = vec ! [ ] ;
225224
226225 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 ) ;
228227
229228 let lo = lower_endpoint ( lo_expr) ?. unwrap_or ( PatRangeBoundary :: NegInfinity ) ;
230229 let hi = lower_endpoint ( hi_expr) ?. unwrap_or ( PatRangeBoundary :: PosInfinity ) ;
@@ -269,17 +268,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
269268 // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
270269 // constants somewhere. Have them on the range pattern.
271270 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 } ;
276273 }
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 } ;
283277 }
284278 Ok ( kind)
285279 }
@@ -569,15 +563,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
569563 // Lower the named constant to a THIR pattern.
570564 let args = self . typeck_results . node_args ( id) ;
571565 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) ;
581567
582568 // If this is an associated constant with an explicit user-written
583569 // type, add an ascription node (e.g. `<Foo<'a> as MyTrait>::CONST`).
@@ -614,18 +600,37 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
614600 let ty = tcx. typeck ( def_id) . node_type ( block. hir_id ) ;
615601
616602 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) ;
619604 let args = ty:: InlineConstArgs :: new ( tcx, ty:: InlineConstArgsParts { parent_args, ty } ) . args ;
620605
621- debug_assert ! ( !args. has_free_regions( ) ) ;
622-
623606 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+ }
629634 }
630635
631636 /// Lowers the kinds of "expression" that can appear in a HIR pattern:
@@ -637,43 +642,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
637642 expr : & ' tcx hir:: PatExpr < ' tcx > ,
638643 pat_ty : Option < Ty < ' tcx > > ,
639644 ) -> 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 ,
644647 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 )
646649 }
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
671679 }
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+ }
678681 }
679682}
0 commit comments