@@ -11,8 +11,8 @@ use rustc_errors::{
11
11
use rustc_hir:: def:: { CtorKind , DefKind , Res } ;
12
12
use rustc_hir:: pat_util:: EnumerateAndAdjustIterator ;
13
13
use rustc_hir:: {
14
- self as hir, BindingMode , ByRef , ExprKind , HirId , LangItem , Mutability , Pat , PatKind ,
15
- expr_needs_parens,
14
+ self as hir, BindingMode , ByRef , ExprKind , HirId , LangItem , Mutability , Pat , PatExpr ,
15
+ PatExprKind , PatKind , expr_needs_parens,
16
16
} ;
17
17
use rustc_infer:: infer;
18
18
use rustc_middle:: traits:: PatternOriginExpr ;
@@ -312,9 +312,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
312
312
fn check_pat ( & self , pat : & ' tcx Pat < ' tcx > , expected : Ty < ' tcx > , pat_info : PatInfo < ' _ , ' tcx > ) {
313
313
let PatInfo { binding_mode, max_ref_mutbl, top_info : ti, current_depth, .. } = pat_info;
314
314
315
- let path_res = match & pat. kind {
316
- PatKind :: Path ( qpath) => {
317
- Some ( self . resolve_ty_and_res_fully_qualified_call ( qpath, pat . hir_id , pat . span ) )
315
+ let path_res = match pat. kind {
316
+ PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( ref qpath) , hir_id , span } ) => {
317
+ Some ( self . resolve_ty_and_res_fully_qualified_call ( qpath, * hir_id, * span) )
318
318
}
319
319
_ => None ,
320
320
} ;
@@ -333,6 +333,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
333
333
PatKind :: Wild | PatKind :: Err ( _) => expected,
334
334
// We allow any type here; we ensure that the type is uninhabited during match checking.
335
335
PatKind :: Never => expected,
336
+ PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( ref qpath) , hir_id, span } ) => {
337
+ let ty =
338
+ self . check_pat_path ( * hir_id, * span, qpath, path_res. unwrap ( ) , expected, ti) ;
339
+ self . write_ty ( * hir_id, ty) ;
340
+ ty
341
+ }
336
342
PatKind :: Expr ( lt) => self . check_pat_lit ( pat. span , lt, expected, ti) ,
337
343
PatKind :: Range ( lhs, rhs, _) => self . check_pat_range ( pat. span , lhs, rhs, expected, ti) ,
338
344
PatKind :: Binding ( ba, var_id, ident, sub) => {
@@ -341,9 +347,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
341
347
PatKind :: TupleStruct ( ref qpath, subpats, ddpos) => {
342
348
self . check_pat_tuple_struct ( pat, qpath, subpats, ddpos, expected, pat_info)
343
349
}
344
- PatKind :: Path ( ref qpath) => {
345
- self . check_pat_path ( pat. hir_id , pat. span , qpath, path_res. unwrap ( ) , expected, ti)
346
- }
347
350
PatKind :: Struct ( ref qpath, fields, has_rest_pat) => {
348
351
self . check_pat_struct ( pat, qpath, fields, has_rest_pat, expected, pat_info)
349
352
}
@@ -456,16 +459,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
456
459
| PatKind :: Slice ( ..) => AdjustMode :: Peel ,
457
460
// A never pattern behaves somewhat like a literal or unit variant.
458
461
PatKind :: Never => AdjustMode :: Peel ,
459
- // String and byte-string literals result in types `&str` and `&[u8]` respectively.
460
- // All other literals result in non-reference types.
461
- // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
462
- //
463
- // Call `resolve_vars_if_possible` here for inline const blocks.
464
- PatKind :: Expr ( lt) => match self . resolve_vars_if_possible ( self . check_pat_expr_unadjusted ( lt) ) . kind ( ) {
465
- ty:: Ref ( ..) => AdjustMode :: Pass ,
466
- _ => AdjustMode :: Peel ,
467
- } ,
468
- PatKind :: Path ( _) => match opt_path_res. unwrap ( ) {
462
+ PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( _) , .. } ) => match opt_path_res. unwrap ( ) {
469
463
// These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
470
464
// Peeling the reference types too early will cause type checking failures.
471
465
// Although it would be possible to *also* peel the types of the constants too.
@@ -476,6 +470,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
476
470
// a reference type wherefore peeling doesn't give up any expressiveness.
477
471
_ => AdjustMode :: Peel ,
478
472
} ,
473
+
474
+ // String and byte-string literals result in types `&str` and `&[u8]` respectively.
475
+ // All other literals result in non-reference types.
476
+ // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
477
+ //
478
+ // Call `resolve_vars_if_possible` here for inline const blocks.
479
+ PatKind :: Expr ( lt) => match self . resolve_vars_if_possible ( self . check_pat_expr_unadjusted ( lt) ) . kind ( ) {
480
+ ty:: Ref ( ..) => AdjustMode :: Pass ,
481
+ _ => AdjustMode :: Peel ,
482
+ } ,
483
+
479
484
// Ref patterns are complicated, we handle them in `check_pat_ref`.
480
485
PatKind :: Ref ( ..) => AdjustMode :: Pass ,
481
486
// A `_` pattern works with any expected type, so there's no need to do anything.
@@ -1001,7 +1006,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1001
1006
PatKind :: Wild
1002
1007
| PatKind :: Never
1003
1008
| PatKind :: Binding ( ..)
1004
- | PatKind :: Path ( ..)
1005
1009
| PatKind :: Box ( ..)
1006
1010
| PatKind :: Deref ( _)
1007
1011
| PatKind :: Ref ( ..)
0 commit comments