@@ -189,7 +189,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
189
189
190
190
// Lower the endpoint into a temporary `PatKind` that will then be
191
191
// 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) ;
193
193
194
194
// Unpeel any ascription or inline-const wrapper nodes.
195
195
loop {
@@ -353,7 +353,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
353
353
354
354
hir:: PatKind :: Never => PatKind :: Never ,
355
355
356
- hir:: PatKind :: Expr ( value) => self . lower_lit ( value) ,
356
+ hir:: PatKind :: Expr ( value) => self . lower_pat_expr ( value) ,
357
357
358
358
hir:: PatKind :: Range ( ref lo_expr, ref hi_expr, end) => {
359
359
let ( lo_expr, hi_expr) = ( lo_expr. as_deref ( ) , hi_expr. as_deref ( ) ) ;
@@ -638,54 +638,57 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
638
638
let ty = self . typeck_results . node_type ( id) ;
639
639
let res = self . typeck_results . qpath_res ( qpath, id) ;
640
640
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
+ }
646
646
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
+ }
648
653
} ;
649
654
655
+ // Lower the named constant to a THIR pattern.
650
656
let args = self . typeck_results . node_args ( id) ;
651
657
let c = ty:: Const :: new_unevaluated ( self . tcx , ty:: UnevaluatedConst { def : def_id, args } ) ;
652
658
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
- } ) ;
658
659
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
+ } ;
662
667
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 {
665
671
let annotation = CanonicalUserTypeAnnotation {
666
672
user_ty : Box :: new ( user_ty) ,
667
673
span,
668
674
inferred_ty : self . typeck_results . node_type ( id) ,
669
675
} ;
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 ,
680
683
} ,
681
- ty,
682
- } )
683
- } else {
684
- pattern
684
+ } ;
685
+ pattern = Box :: new ( Pat { span, kind, ty } ) ;
685
686
}
687
+
688
+ pattern
686
689
}
687
690
688
- /// Converts inline const patterns .
691
+ /// Lowers an inline const block (e.g. `const { 1 + 1 }`) to a pattern .
689
692
fn lower_inline_const (
690
693
& mut self ,
691
694
block : & ' tcx hir:: ConstBlock ,
@@ -705,14 +708,17 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
705
708
706
709
let ct = ty:: UnevaluatedConst { def : def_id. to_def_id ( ) , args } ;
707
710
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.
708
714
PatKind :: ExpandedConstant { subpattern, def_id : def_id. to_def_id ( ) , is_inline : true }
709
715
}
710
716
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 > {
716
722
let ( lit, neg) = match & expr. kind {
717
723
hir:: PatExprKind :: Path ( qpath) => {
718
724
return self . lower_path ( qpath, expr. hir_id , expr. span ) . kind ;
0 commit comments