@@ -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,19 @@ 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 = self . check_pat_path (
276
+ hir_id,
277
+ pat. hir_id ,
278
+ span,
279
+ qpath,
280
+ path_res. unwrap ( ) ,
281
+ expected,
282
+ ti,
283
+ ) ;
284
+ self . write_ty ( hir_id, ty) ;
285
+ ty
286
+ }
274
287
PatKind :: Expr ( lt) => self . check_pat_lit ( pat. span , lt, expected, ti) ,
275
288
PatKind :: Range ( lhs, rhs, _) => self . check_pat_range ( pat. span , lhs, rhs, expected, ti) ,
276
289
PatKind :: Binding ( ba, var_id, ident, sub) => {
@@ -279,9 +292,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
279
292
PatKind :: TupleStruct ( ref qpath, subpats, ddpos) => {
280
293
self . check_pat_tuple_struct ( pat, qpath, subpats, ddpos, expected, pat_info)
281
294
}
282
- PatKind :: Path ( ref qpath) => {
283
- self . check_pat_path ( pat. hir_id , pat. span , qpath, path_res. unwrap ( ) , expected, ti)
284
- }
285
295
PatKind :: Struct ( ref qpath, fields, has_rest_pat) => {
286
296
self . check_pat_struct ( pat, qpath, fields, has_rest_pat, expected, pat_info)
287
297
}
@@ -394,16 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
394
404
| PatKind :: Slice ( ..) => AdjustMode :: Peel ,
395
405
// A never pattern behaves somewhat like a literal or unit variant.
396
406
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 ( ) {
407
+ PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( _) , .. } ) => match opt_path_res. unwrap ( ) {
407
408
// These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
408
409
// Peeling the reference types too early will cause type checking failures.
409
410
// Although it would be possible to *also* peel the types of the constants too.
@@ -414,6 +415,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
414
415
// a reference type wherefore peeling doesn't give up any expressiveness.
415
416
_ => AdjustMode :: Peel ,
416
417
} ,
418
+ // String and byte-string literals result in types `&str` and `&[u8]` respectively.
419
+ // All other literals result in non-reference types.
420
+ // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
421
+ //
422
+ // Call `resolve_vars_if_possible` here for inline const blocks.
423
+ PatKind :: Expr ( lt) => match self . resolve_vars_if_possible ( self . check_pat_expr_unadjusted ( lt) ) . kind ( ) {
424
+ ty:: Ref ( ..) => AdjustMode :: Pass ,
425
+ _ => AdjustMode :: Peel ,
426
+ } ,
417
427
// Ref patterns are complicated, we handle them in `check_pat_ref`.
418
428
PatKind :: Ref ( ..) => AdjustMode :: Pass ,
419
429
// A `_` pattern works with any expected type, so there's no need to do anything.
@@ -939,7 +949,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
939
949
PatKind :: Wild
940
950
| PatKind :: Never
941
951
| PatKind :: Binding ( ..)
942
- | PatKind :: Path ( ..)
943
952
| PatKind :: Box ( ..)
944
953
| PatKind :: Deref ( _)
945
954
| PatKind :: Ref ( ..)
@@ -1078,6 +1087,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1078
1087
fn check_pat_path (
1079
1088
& self ,
1080
1089
hir_id : HirId ,
1090
+ pat_id : HirId ,
1081
1091
span : Span ,
1082
1092
qpath : & hir:: QPath < ' _ > ,
1083
1093
path_resolution : ( Res , Option < LoweredTy < ' tcx > > , & ' tcx [ hir:: PathSegment < ' tcx > ] ) ,
@@ -1135,7 +1145,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1135
1145
if let Err ( err) =
1136
1146
self . demand_suptype_with_origin ( & self . pattern_cause ( ti, span) , expected, pat_ty)
1137
1147
{
1138
- self . emit_bad_pat_path ( err, hir_id , span, res, pat_res, pat_ty, segments) ;
1148
+ self . emit_bad_pat_path ( err, pat_id , span, res, pat_res, pat_ty, segments) ;
1139
1149
}
1140
1150
pat_ty
1141
1151
}
@@ -1178,7 +1188,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1178
1188
fn emit_bad_pat_path (
1179
1189
& self ,
1180
1190
mut e : Diag < ' _ > ,
1181
- hir_id : HirId ,
1191
+ pat_id : HirId ,
1182
1192
pat_span : Span ,
1183
1193
res : Res ,
1184
1194
pat_res : Res ,
@@ -1197,7 +1207,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1197
1207
res. descr( ) ,
1198
1208
) ,
1199
1209
) ;
1200
- match self . tcx . parent_hir_node ( hir_id ) {
1210
+ match self . tcx . parent_hir_node ( pat_id ) {
1201
1211
hir:: Node :: PatField ( ..) => {
1202
1212
e. span_suggestion_verbose (
1203
1213
ident. span . shrink_to_hi ( ) ,
0 commit comments