@@ -10,7 +10,9 @@ use rustc_errors::{
10
10
} ;
11
11
use rustc_hir:: def:: { CtorKind , DefKind , Res } ;
12
12
use rustc_hir:: pat_util:: EnumerateAndAdjustIterator ;
13
- use rustc_hir:: { self as hir, BindingMode , ByRef , HirId , LangItem , Mutability , Pat , PatKind } ;
13
+ use rustc_hir:: {
14
+ self as hir, BindingMode , ByRef , HirId , LangItem , Mutability , Pat , PatKind , PatLit , PatLitKind ,
15
+ } ;
14
16
use rustc_infer:: infer;
15
17
use rustc_middle:: ty:: { self , Ty , TypeVisitableExt } ;
16
18
use rustc_middle:: { bug, span_bug} ;
@@ -225,9 +227,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
225
227
fn check_pat ( & self , pat : & ' tcx Pat < ' tcx > , expected : Ty < ' tcx > , pat_info : PatInfo < ' _ , ' tcx > ) {
226
228
let PatInfo { binding_mode, max_ref_mutbl, top_info : ti, current_depth, .. } = pat_info;
227
229
228
- let path_res = match & pat. kind {
229
- PatKind :: Path ( qpath) => {
230
- Some ( self . resolve_ty_and_res_fully_qualified_call ( qpath, pat . hir_id , pat . span ) )
230
+ let path_res = match pat. kind {
231
+ PatKind :: Lit ( & PatLit { kind : PatLitKind :: Path ( ref qpath) , hir_id , span } ) => {
232
+ Some ( self . resolve_ty_and_res_fully_qualified_call ( qpath, hir_id, span) )
231
233
}
232
234
_ => None ,
233
235
} ;
@@ -246,6 +248,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
246
248
PatKind :: Wild | PatKind :: Err ( _) => expected,
247
249
// We allow any type here; we ensure that the type is uninhabited during match checking.
248
250
PatKind :: Never => expected,
251
+ PatKind :: Lit ( & PatLit { kind : PatLitKind :: Path ( ref qpath) , hir_id, span } ) => {
252
+ let ty = self . check_pat_path (
253
+ hir_id,
254
+ pat. hir_id ,
255
+ span,
256
+ qpath,
257
+ path_res. unwrap ( ) ,
258
+ expected,
259
+ ti,
260
+ ) ;
261
+ self . write_ty ( hir_id, ty) ;
262
+ ty
263
+ }
249
264
PatKind :: Lit ( lt) => self . check_pat_lit ( pat. span , lt, expected, ti) ,
250
265
PatKind :: Range ( lhs, rhs, _) => self . check_pat_range ( pat. span , lhs, rhs, expected, ti) ,
251
266
PatKind :: Binding ( ba, var_id, ident, sub) => {
@@ -254,9 +269,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
254
269
PatKind :: TupleStruct ( ref qpath, subpats, ddpos) => {
255
270
self . check_pat_tuple_struct ( pat, qpath, subpats, ddpos, expected, pat_info)
256
271
}
257
- PatKind :: Path ( ref qpath) => {
258
- self . check_pat_path ( pat. hir_id , pat. span , qpath, path_res. unwrap ( ) , expected, ti)
259
- }
260
272
PatKind :: Struct ( ref qpath, fields, has_rest_pat) => {
261
273
self . check_pat_struct ( pat, qpath, fields, has_rest_pat, expected, pat_info)
262
274
}
@@ -364,16 +376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
364
376
| PatKind :: Slice ( ..) => AdjustMode :: Peel ,
365
377
// A never pattern behaves somewhat like a literal or unit variant.
366
378
PatKind :: Never => AdjustMode :: Peel ,
367
- // String and byte-string literals result in types `&str` and `&[u8]` respectively.
368
- // All other literals result in non-reference types.
369
- // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
370
- //
371
- // Call `resolve_vars_if_possible` here for inline const blocks.
372
- PatKind :: Lit ( lt) => match self . resolve_vars_if_possible ( self . check_pat_lit_unadjusted ( lt) ) . kind ( ) {
373
- ty:: Ref ( ..) => AdjustMode :: Pass ,
374
- _ => AdjustMode :: Peel ,
375
- } ,
376
- PatKind :: Path ( _) => match opt_path_res. unwrap ( ) {
379
+ PatKind :: Lit ( PatLit { kind : PatLitKind :: Path ( _) , .. } ) => match opt_path_res. unwrap ( ) {
377
380
// These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
378
381
// Peeling the reference types too early will cause type checking failures.
379
382
// Although it would be possible to *also* peel the types of the constants too.
@@ -384,6 +387,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
384
387
// a reference type wherefore peeling doesn't give up any expressiveness.
385
388
_ => AdjustMode :: Peel ,
386
389
} ,
390
+ // String and byte-string literals result in types `&str` and `&[u8]` respectively.
391
+ // All other literals result in non-reference types.
392
+ // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
393
+ //
394
+ // Call `resolve_vars_if_possible` here for inline const blocks.
395
+ PatKind :: Lit ( lt) => match self . resolve_vars_if_possible ( self . check_pat_lit_unadjusted ( lt) ) . kind ( ) {
396
+ ty:: Ref ( ..) => AdjustMode :: Pass ,
397
+ _ => AdjustMode :: Peel ,
398
+ } ,
387
399
// Ref patterns are complicated, we handle them in `check_pat_ref`.
388
400
PatKind :: Ref ( ..) => AdjustMode :: Pass ,
389
401
// A `_` pattern works with any expected type, so there's no need to do anything.
@@ -905,7 +917,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
905
917
PatKind :: Wild
906
918
| PatKind :: Never
907
919
| PatKind :: Binding ( ..)
908
- | PatKind :: Path ( ..)
909
920
| PatKind :: Box ( ..)
910
921
| PatKind :: Deref ( _)
911
922
| PatKind :: Ref ( ..)
@@ -1044,6 +1055,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1044
1055
fn check_pat_path (
1045
1056
& self ,
1046
1057
hir_id : HirId ,
1058
+ pat_id : HirId ,
1047
1059
span : Span ,
1048
1060
qpath : & hir:: QPath < ' _ > ,
1049
1061
path_resolution : ( Res , Option < LoweredTy < ' tcx > > , & ' tcx [ hir:: PathSegment < ' tcx > ] ) ,
@@ -1101,7 +1113,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1101
1113
if let Err ( err) =
1102
1114
self . demand_suptype_with_origin ( & self . pattern_cause ( ti, span) , expected, pat_ty)
1103
1115
{
1104
- self . emit_bad_pat_path ( err, hir_id , span, res, pat_res, pat_ty, segments) ;
1116
+ self . emit_bad_pat_path ( err, pat_id , span, res, pat_res, pat_ty, segments) ;
1105
1117
}
1106
1118
pat_ty
1107
1119
}
@@ -1144,7 +1156,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1144
1156
fn emit_bad_pat_path (
1145
1157
& self ,
1146
1158
mut e : Diag < ' _ > ,
1147
- hir_id : HirId ,
1159
+ pat_id : HirId ,
1148
1160
pat_span : Span ,
1149
1161
res : Res ,
1150
1162
pat_res : Res ,
@@ -1163,7 +1175,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1163
1175
res. descr( ) ,
1164
1176
) ,
1165
1177
) ;
1166
- match self . tcx . parent_hir_node ( hir_id ) {
1178
+ match self . tcx . parent_hir_node ( pat_id ) {
1167
1179
hir:: Node :: PatField ( ..) => {
1168
1180
e. span_suggestion_verbose (
1169
1181
ident. span . shrink_to_hi ( ) ,
0 commit comments