@@ -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 ;
@@ -250,9 +250,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
250
250
fn check_pat ( & self , pat : & ' tcx Pat < ' tcx > , expected : Ty < ' tcx > , pat_info : PatInfo < ' _ , ' tcx > ) {
251
251
let PatInfo { binding_mode, max_ref_mutbl, top_info : ti, current_depth, .. } = pat_info;
252
252
253
- let path_res = match & pat. kind {
254
- PatKind :: Path ( qpath) => {
255
- Some ( self . resolve_ty_and_res_fully_qualified_call ( qpath, pat . hir_id , pat . span ) )
253
+ let path_res = match pat. kind {
254
+ PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( ref qpath) , hir_id , span } ) => {
255
+ Some ( self . resolve_ty_and_res_fully_qualified_call ( qpath, * hir_id, * span) )
256
256
}
257
257
_ => None ,
258
258
} ;
@@ -271,6 +271,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
271
271
PatKind :: Wild | PatKind :: Err ( _) => expected,
272
272
// We allow any type here; we ensure that the type is uninhabited during match checking.
273
273
PatKind :: Never => expected,
274
+ PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( ref qpath) , hir_id, span } ) => {
275
+ let ty =
276
+ self . check_pat_path ( * hir_id, * span, qpath, path_res. unwrap ( ) , expected, ti) ;
277
+ self . write_ty ( * hir_id, ty) ;
278
+ ty
279
+ }
274
280
PatKind :: Expr ( lt) => self . check_pat_lit ( pat. span , lt, expected, ti) ,
275
281
PatKind :: Range ( lhs, rhs, _) => self . check_pat_range ( pat. span , lhs, rhs, expected, ti) ,
276
282
PatKind :: Binding ( ba, var_id, ident, sub) => {
@@ -279,9 +285,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
279
285
PatKind :: TupleStruct ( ref qpath, subpats, ddpos) => {
280
286
self . check_pat_tuple_struct ( pat, qpath, subpats, ddpos, expected, pat_info)
281
287
}
282
- PatKind :: Path ( ref qpath) => {
283
- self . check_pat_path ( pat. hir_id , pat. span , qpath, path_res. unwrap ( ) , expected, ti)
284
- }
285
288
PatKind :: Struct ( ref qpath, fields, has_rest_pat) => {
286
289
self . check_pat_struct ( pat, qpath, fields, has_rest_pat, expected, pat_info)
287
290
}
@@ -394,16 +397,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
394
397
| PatKind :: Slice ( ..) => AdjustMode :: Peel ,
395
398
// A never pattern behaves somewhat like a literal or unit variant.
396
399
PatKind :: Never => AdjustMode :: Peel ,
397
- // String and byte-string literals result in types `&str` and `&[u8]` respectively.
398
- // All other literals result in non-reference types.
399
- // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
400
- //
401
- // Call `resolve_vars_if_possible` here for inline const blocks.
402
- PatKind :: Expr ( lt) => match self . resolve_vars_if_possible ( self . check_pat_expr_unadjusted ( lt) ) . kind ( ) {
403
- ty:: Ref ( ..) => AdjustMode :: Pass ,
404
- _ => AdjustMode :: Peel ,
405
- } ,
406
- PatKind :: Path ( _) => match opt_path_res. unwrap ( ) {
400
+ PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( _) , .. } ) => match opt_path_res. unwrap ( ) {
407
401
// These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
408
402
// Peeling the reference types too early will cause type checking failures.
409
403
// Although it would be possible to *also* peel the types of the constants too.
@@ -414,6 +408,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
414
408
// a reference type wherefore peeling doesn't give up any expressiveness.
415
409
_ => AdjustMode :: Peel ,
416
410
} ,
411
+
412
+ // String and byte-string literals result in types `&str` and `&[u8]` respectively.
413
+ // All other literals result in non-reference types.
414
+ // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
415
+ //
416
+ // Call `resolve_vars_if_possible` here for inline const blocks.
417
+ PatKind :: Expr ( lt) => match self . resolve_vars_if_possible ( self . check_pat_expr_unadjusted ( lt) ) . kind ( ) {
418
+ ty:: Ref ( ..) => AdjustMode :: Pass ,
419
+ _ => AdjustMode :: Peel ,
420
+ } ,
421
+
417
422
// Ref patterns are complicated, we handle them in `check_pat_ref`.
418
423
PatKind :: Ref ( ..) => AdjustMode :: Pass ,
419
424
// A `_` pattern works with any expected type, so there's no need to do anything.
@@ -939,7 +944,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
939
944
PatKind :: Wild
940
945
| PatKind :: Never
941
946
| PatKind :: Binding ( ..)
942
- | PatKind :: Path ( ..)
943
947
| PatKind :: Box ( ..)
944
948
| PatKind :: Deref ( _)
945
949
| PatKind :: Ref ( ..)
0 commit comments