@@ -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 }
@@ -567,15 +561,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
567561 // Lower the named constant to a THIR pattern.
568562 let args = self . typeck_results . node_args ( id) ;
569563 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) ;
579565
580566 // If this is an associated constant with an explicit user-written
581567 // type, add an ascription node (e.g. `<Foo<'a> as MyTrait>::CONST`).
@@ -612,18 +598,37 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
612598 let ty = tcx. typeck ( def_id) . node_type ( block. hir_id ) ;
613599
614600 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) ;
617602 let args = ty:: InlineConstArgs :: new ( tcx, ty:: InlineConstArgsParts { parent_args, ty } ) . args ;
618603
619- debug_assert ! ( !args. has_free_regions( ) ) ;
620-
621604 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+ }
627632 }
628633
629634 /// Lowers the kinds of "expression" that can appear in a HIR pattern:
@@ -635,43 +640,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
635640 expr : & ' tcx hir:: PatExpr < ' tcx > ,
636641 pat_ty : Option < Ty < ' tcx > > ,
637642 ) -> 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 ,
642645 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 )
644647 }
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
669677 }
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+ }
676679 }
677680}
0 commit comments