@@ -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
}
@@ -389,16 +399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
389
399
| PatKind :: Slice ( ..) => AdjustMode :: Peel ,
390
400
// A never pattern behaves somewhat like a literal or unit variant.
391
401
PatKind :: Never => AdjustMode :: Peel ,
392
- // String and byte-string literals result in types `&str` and `&[u8]` respectively.
393
- // All other literals result in non-reference types.
394
- // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
395
- //
396
- // Call `resolve_vars_if_possible` here for inline const blocks.
397
- PatKind :: Expr ( lt) => match self . resolve_vars_if_possible ( self . check_pat_expr_unadjusted ( lt) ) . kind ( ) {
398
- ty:: Ref ( ..) => AdjustMode :: Pass ,
399
- _ => AdjustMode :: Peel ,
400
- } ,
401
- PatKind :: Path ( _) => match opt_path_res. unwrap ( ) {
402
+ PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( _) , .. } ) => match opt_path_res. unwrap ( ) {
402
403
// These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
403
404
// Peeling the reference types too early will cause type checking failures.
404
405
// Although it would be possible to *also* peel the types of the constants too.
@@ -409,6 +410,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
409
410
// a reference type wherefore peeling doesn't give up any expressiveness.
410
411
_ => AdjustMode :: Peel ,
411
412
} ,
413
+ // String and byte-string literals result in types `&str` and `&[u8]` respectively.
414
+ // All other literals result in non-reference types.
415
+ // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
416
+ //
417
+ // Call `resolve_vars_if_possible` here for inline const blocks.
418
+ PatKind :: Expr ( lt) => match self . resolve_vars_if_possible ( self . check_pat_expr_unadjusted ( lt) ) . kind ( ) {
419
+ ty:: Ref ( ..) => AdjustMode :: Pass ,
420
+ _ => AdjustMode :: Peel ,
421
+ } ,
412
422
// Ref patterns are complicated, we handle them in `check_pat_ref`.
413
423
PatKind :: Ref ( ..) => AdjustMode :: Pass ,
414
424
// A `_` pattern works with any expected type, so there's no need to do anything.
@@ -931,7 +941,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
931
941
PatKind :: Wild
932
942
| PatKind :: Never
933
943
| PatKind :: Binding ( ..)
934
- | PatKind :: Path ( ..)
935
944
| PatKind :: Box ( ..)
936
945
| PatKind :: Deref ( _)
937
946
| PatKind :: Ref ( ..)
@@ -1070,6 +1079,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1070
1079
fn check_pat_path (
1071
1080
& self ,
1072
1081
hir_id : HirId ,
1082
+ pat_id : HirId ,
1073
1083
span : Span ,
1074
1084
qpath : & hir:: QPath < ' _ > ,
1075
1085
path_resolution : ( Res , Option < LoweredTy < ' tcx > > , & ' tcx [ hir:: PathSegment < ' tcx > ] ) ,
@@ -1127,7 +1137,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1127
1137
if let Err ( err) =
1128
1138
self . demand_suptype_with_origin ( & self . pattern_cause ( ti, span) , expected, pat_ty)
1129
1139
{
1130
- self . emit_bad_pat_path ( err, hir_id , span, res, pat_res, pat_ty, segments) ;
1140
+ self . emit_bad_pat_path ( err, pat_id , span, res, pat_res, pat_ty, segments) ;
1131
1141
}
1132
1142
pat_ty
1133
1143
}
@@ -1170,7 +1180,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1170
1180
fn emit_bad_pat_path (
1171
1181
& self ,
1172
1182
mut e : Diag < ' _ > ,
1173
- hir_id : HirId ,
1183
+ pat_id : HirId ,
1174
1184
pat_span : Span ,
1175
1185
res : Res ,
1176
1186
pat_res : Res ,
@@ -1189,7 +1199,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1189
1199
res. descr( ) ,
1190
1200
) ,
1191
1201
) ;
1192
- match self . tcx . parent_hir_node ( hir_id ) {
1202
+ match self . tcx . parent_hir_node ( pat_id ) {
1193
1203
hir:: Node :: PatField ( ..) => {
1194
1204
e. span_suggestion_verbose (
1195
1205
ident. span . shrink_to_hi ( ) ,
0 commit comments