@@ -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,19 @@ 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 = self . check_pat_path (
338
+ * hir_id,
339
+ pat. hir_id ,
340
+ * span,
341
+ qpath,
342
+ path_res. unwrap ( ) ,
343
+ expected,
344
+ ti,
345
+ ) ;
346
+ self . write_ty ( * hir_id, ty) ;
347
+ ty
348
+ }
336
349
PatKind :: Expr ( lt) => self . check_pat_lit ( pat. span , lt, expected, ti) ,
337
350
PatKind :: Range ( lhs, rhs, _) => self . check_pat_range ( pat. span , lhs, rhs, expected, ti) ,
338
351
PatKind :: Binding ( ba, var_id, ident, sub) => {
@@ -341,9 +354,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
341
354
PatKind :: TupleStruct ( ref qpath, subpats, ddpos) => {
342
355
self . check_pat_tuple_struct ( pat, qpath, subpats, ddpos, expected, pat_info)
343
356
}
344
- PatKind :: Path ( ref qpath) => {
345
- self . check_pat_path ( pat. hir_id , pat. span , qpath, path_res. unwrap ( ) , expected, ti)
346
- }
347
357
PatKind :: Struct ( ref qpath, fields, has_rest_pat) => {
348
358
self . check_pat_struct ( pat, qpath, fields, has_rest_pat, expected, pat_info)
349
359
}
@@ -456,16 +466,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
456
466
| PatKind :: Slice ( ..) => AdjustMode :: Peel ,
457
467
// A never pattern behaves somewhat like a literal or unit variant.
458
468
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 ( ) {
469
+ PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( _) , .. } ) => match opt_path_res. unwrap ( ) {
469
470
// These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
470
471
// Peeling the reference types too early will cause type checking failures.
471
472
// Although it would be possible to *also* peel the types of the constants too.
@@ -476,6 +477,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
476
477
// a reference type wherefore peeling doesn't give up any expressiveness.
477
478
_ => AdjustMode :: Peel ,
478
479
} ,
480
+
481
+ // String and byte-string literals result in types `&str` and `&[u8]` respectively.
482
+ // All other literals result in non-reference types.
483
+ // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
484
+ //
485
+ // Call `resolve_vars_if_possible` here for inline const blocks.
486
+ PatKind :: Expr ( lt) => match self . resolve_vars_if_possible ( self . check_pat_expr_unadjusted ( lt) ) . kind ( ) {
487
+ ty:: Ref ( ..) => AdjustMode :: Pass ,
488
+ _ => AdjustMode :: Peel ,
489
+ } ,
490
+
479
491
// Ref patterns are complicated, we handle them in `check_pat_ref`.
480
492
PatKind :: Ref ( ..) => AdjustMode :: Pass ,
481
493
// A `_` pattern works with any expected type, so there's no need to do anything.
@@ -1001,7 +1013,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1001
1013
PatKind :: Wild
1002
1014
| PatKind :: Never
1003
1015
| PatKind :: Binding ( ..)
1004
- | PatKind :: Path ( ..)
1005
1016
| PatKind :: Box ( ..)
1006
1017
| PatKind :: Deref ( _)
1007
1018
| PatKind :: Ref ( ..)
@@ -1139,7 +1150,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1139
1150
1140
1151
fn check_pat_path (
1141
1152
& self ,
1142
- hir_id : HirId ,
1153
+ path_id : HirId ,
1154
+ pat_id_for_diag : HirId ,
1143
1155
span : Span ,
1144
1156
qpath : & hir:: QPath < ' _ > ,
1145
1157
path_resolution : ( Res , Option < LoweredTy < ' tcx > > , & ' tcx [ hir:: PathSegment < ' tcx > ] ) ,
@@ -1193,11 +1205,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1193
1205
1194
1206
// Type-check the path.
1195
1207
let ( pat_ty, pat_res) =
1196
- self . instantiate_value_path ( segments, opt_ty, res, span, span, hir_id ) ;
1208
+ self . instantiate_value_path ( segments, opt_ty, res, span, span, path_id ) ;
1197
1209
if let Err ( err) =
1198
1210
self . demand_suptype_with_origin ( & self . pattern_cause ( ti, span) , expected, pat_ty)
1199
1211
{
1200
- self . emit_bad_pat_path ( err, hir_id , span, res, pat_res, pat_ty, segments) ;
1212
+ self . emit_bad_pat_path ( err, pat_id_for_diag , span, res, pat_res, pat_ty, segments) ;
1201
1213
}
1202
1214
pat_ty
1203
1215
}
0 commit comments