@@ -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,11 @@ 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 ( hir_id, span, qpath, path_res. unwrap ( ) , expected, ti) ;
253
+ self . write_ty ( hir_id, ty) ;
254
+ ty
255
+ }
249
256
PatKind :: Lit ( lt) => self . check_pat_lit ( pat. span , lt, expected, ti) ,
250
257
PatKind :: Range ( lhs, rhs, _) => self . check_pat_range ( pat. span , lhs, rhs, expected, ti) ,
251
258
PatKind :: Binding ( ba, var_id, ident, sub) => {
@@ -254,9 +261,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
254
261
PatKind :: TupleStruct ( ref qpath, subpats, ddpos) => {
255
262
self . check_pat_tuple_struct ( pat, qpath, subpats, ddpos, expected, pat_info)
256
263
}
257
- PatKind :: Path ( ref qpath) => {
258
- self . check_pat_path ( pat. hir_id , pat. span , qpath, path_res. unwrap ( ) , expected, ti)
259
- }
260
264
PatKind :: Struct ( ref qpath, fields, has_rest_pat) => {
261
265
self . check_pat_struct ( pat, qpath, fields, has_rest_pat, expected, pat_info)
262
266
}
@@ -364,16 +368,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
364
368
| PatKind :: Slice ( ..) => AdjustMode :: Peel ,
365
369
// A never pattern behaves somewhat like a literal or unit variant.
366
370
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 ( ) {
371
+ PatKind :: Lit ( PatLit { kind : PatLitKind :: Path ( _) , .. } ) => match opt_path_res. unwrap ( ) {
377
372
// These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
378
373
// Peeling the reference types too early will cause type checking failures.
379
374
// Although it would be possible to *also* peel the types of the constants too.
@@ -384,6 +379,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
384
379
// a reference type wherefore peeling doesn't give up any expressiveness.
385
380
_ => AdjustMode :: Peel ,
386
381
} ,
382
+ // String and byte-string literals result in types `&str` and `&[u8]` respectively.
383
+ // All other literals result in non-reference types.
384
+ // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
385
+ //
386
+ // Call `resolve_vars_if_possible` here for inline const blocks.
387
+ PatKind :: Lit ( lt) => match self . resolve_vars_if_possible ( self . check_pat_lit_unadjusted ( lt) ) . kind ( ) {
388
+ ty:: Ref ( ..) => AdjustMode :: Pass ,
389
+ _ => AdjustMode :: Peel ,
390
+ } ,
387
391
// Ref patterns are complicated, we handle them in `check_pat_ref`.
388
392
PatKind :: Ref ( ..) => AdjustMode :: Pass ,
389
393
// A `_` pattern works with any expected type, so there's no need to do anything.
@@ -905,7 +909,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
905
909
PatKind :: Wild
906
910
| PatKind :: Never
907
911
| PatKind :: Binding ( ..)
908
- | PatKind :: Path ( ..)
909
912
| PatKind :: Box ( ..)
910
913
| PatKind :: Deref ( _)
911
914
| PatKind :: Ref ( ..)
0 commit comments