@@ -189,7 +189,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
189189
190190 // Lower the endpoint into a temporary `PatKind` that will then be
191191 // deconstructed to obtain the constant value and other data.
192- let mut kind: PatKind < ' tcx > = self . lower_lit ( expr) ;
192+ let mut kind: PatKind < ' tcx > = self . lower_pat_expr ( expr) ;
193193
194194 // Unpeel any ascription or inline-const wrapper nodes.
195195 loop {
@@ -353,7 +353,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
353353
354354 hir:: PatKind :: Never => PatKind :: Never ,
355355
356- hir:: PatKind :: Expr ( value) => self . lower_lit ( value) ,
356+ hir:: PatKind :: Expr ( value) => self . lower_pat_expr ( value) ,
357357
358358 hir:: PatKind :: Range ( ref lo_expr, ref hi_expr, end) => {
359359 let ( lo_expr, hi_expr) = ( lo_expr. as_deref ( ) , hi_expr. as_deref ( ) ) ;
@@ -638,54 +638,57 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
638638 let ty = self . typeck_results . node_type ( id) ;
639639 let res = self . typeck_results . qpath_res ( qpath, id) ;
640640
641- let pat_from_kind = |kind| Box :: new ( Pat { span , ty , kind } ) ;
642-
643- let ( def_id , is_associated_const ) = match res {
644- Res :: Def ( DefKind :: Const , def_id ) => ( def_id, false ) ,
645- Res :: Def ( DefKind :: AssocConst , def_id ) => ( def_id , true ) ,
641+ let ( def_id , user_ty ) = match res {
642+ Res :: Def ( DefKind :: Const , def_id ) => ( def_id , None ) ,
643+ Res :: Def ( DefKind :: AssocConst , def_id ) => {
644+ ( def_id, self . typeck_results . user_provided_types ( ) . get ( id ) )
645+ }
646646
647- _ => return pat_from_kind ( self . lower_variant_or_leaf ( res, id, span, ty, vec ! [ ] ) ) ,
647+ _ => {
648+ // The path isn't the name of a constant, so it must actually
649+ // be a unit struct or unit variant (e.g. `Option::None`).
650+ let kind = self . lower_variant_or_leaf ( res, id, span, ty, vec ! [ ] ) ;
651+ return Box :: new ( Pat { span, ty, kind } ) ;
652+ }
648653 } ;
649654
655+ // Lower the named constant to a THIR pattern.
650656 let args = self . typeck_results . node_args ( id) ;
651657 let c = ty:: Const :: new_unevaluated ( self . tcx , ty:: UnevaluatedConst { def : def_id, args } ) ;
652658 let subpattern = self . const_to_pat ( c, ty, id, span) ;
653- let pattern = Box :: new ( Pat {
654- span,
655- ty,
656- kind : PatKind :: ExpandedConstant { subpattern, def_id, is_inline : false } ,
657- } ) ;
658659
659- if !is_associated_const {
660- return pattern;
661- }
660+ // Wrap the pattern in a marker node to indicate that it is the result
661+ // of lowering a named constant. This marker is used for improved
662+ // diagnostics in some situations, but has no effect at runtime.
663+ let mut pattern = {
664+ let kind = PatKind :: ExpandedConstant { subpattern, def_id, is_inline : false } ;
665+ Box :: new ( Pat { span, ty, kind } )
666+ } ;
662667
663- let user_provided_types = self . typeck_results . user_provided_types ( ) ;
664- if let Some ( & user_ty) = user_provided_types. get ( id) {
668+ // If this is an associated constant with an explicit user-written
669+ // type, add an ascription node (e.g. `<Foo<'a> as MyTrait>::CONST`).
670+ if let Some ( & user_ty) = user_ty {
665671 let annotation = CanonicalUserTypeAnnotation {
666672 user_ty : Box :: new ( user_ty) ,
667673 span,
668674 inferred_ty : self . typeck_results . node_type ( id) ,
669675 } ;
670- Box :: new ( Pat {
671- span,
672- kind : PatKind :: AscribeUserType {
673- subpattern : pattern,
674- ascription : Ascription {
675- annotation,
676- // Note that use `Contravariant` here. See the
677- // `variance` field documentation for details.
678- variance : ty:: Contravariant ,
679- } ,
676+ let kind = PatKind :: AscribeUserType {
677+ subpattern : pattern,
678+ ascription : Ascription {
679+ annotation,
680+ // Note that we use `Contravariant` here. See the
681+ // `variance` field documentation for details.
682+ variance : ty:: Contravariant ,
680683 } ,
681- ty,
682- } )
683- } else {
684- pattern
684+ } ;
685+ pattern = Box :: new ( Pat { span, kind, ty } ) ;
685686 }
687+
688+ pattern
686689 }
687690
688- /// Converts inline const patterns .
691+ /// Lowers an inline const block (e.g. `const { 1 + 1 }`) to a pattern .
689692 fn lower_inline_const (
690693 & mut self ,
691694 block : & ' tcx hir:: ConstBlock ,
@@ -705,14 +708,17 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
705708
706709 let ct = ty:: UnevaluatedConst { def : def_id. to_def_id ( ) , args } ;
707710 let subpattern = self . const_to_pat ( ty:: Const :: new_unevaluated ( self . tcx , ct) , ty, id, span) ;
711+
712+ // Wrap the pattern in a marker node to indicate that it is the result
713+ // of lowering an inline const block.
708714 PatKind :: ExpandedConstant { subpattern, def_id : def_id. to_def_id ( ) , is_inline : true }
709715 }
710716
711- /// Converts literals, paths and negation of literals to patterns.
712- /// The special case for negation exists to allow things like `-128_i8`
713- /// which would overflow if we tried to evaluate `128_i8` and then negate
714- /// afterwards.
715- fn lower_lit ( & mut self , expr : & ' tcx hir:: PatExpr < ' tcx > ) -> PatKind < ' tcx > {
717+ /// Lowers the kinds of "expression" that can appear in a HIR pattern:
718+ /// - Paths (e.g. `FOO`, `foo::BAR`, `Option::None`)
719+ /// - Inline const blocks (e.g. `const { 1 + 1 }`)
720+ /// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
721+ fn lower_pat_expr ( & mut self , expr : & ' tcx hir:: PatExpr < ' tcx > ) -> PatKind < ' tcx > {
716722 let ( lit, neg) = match & expr. kind {
717723 hir:: PatExprKind :: Path ( qpath) => {
718724 return self . lower_path ( qpath, expr. hir_id , expr. span ) . kind ;
0 commit comments