@@ -256,7 +256,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
256
256
}
257
257
_ => None ,
258
258
} ;
259
- let adjust_mode = self . calc_adjust_mode ( pat, path_res. map ( |( res, ..) | res) ) ;
259
+ let ( adjust_mode, opt_expr_ty ) = self . calc_adjust_mode ( pat, path_res. map ( |( res, ..) | res) ) ;
260
260
let ( expected, binding_mode, max_ref_mutbl) =
261
261
self . calc_default_binding_mode ( pat, expected, binding_mode, adjust_mode, max_ref_mutbl) ;
262
262
let pat_info = PatInfo {
@@ -271,7 +271,9 @@ 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 ( lt) => self . check_pat_lit ( pat. span , lt, expected, ti) ,
274
+ PatKind :: Expr ( ref lt) => {
275
+ self . check_pat_lit ( pat. hir_id , pat. span , lt, expected, ti, opt_expr_ty. unwrap ( ) )
276
+ }
275
277
PatKind :: Range ( lhs, rhs, _) => self . check_pat_range ( pat. span , lhs, rhs, expected, ti) ,
276
278
PatKind :: Binding ( ba, var_id, ident, sub) => {
277
279
self . check_pat_ident ( pat, ba, var_id, ident, sub, expected, pat_info)
@@ -376,13 +378,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
376
378
/// How should the binding mode and expected type be adjusted?
377
379
///
378
380
/// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`.
379
- fn calc_adjust_mode ( & self , pat : & ' tcx Pat < ' tcx > , opt_path_res : Option < Res > ) -> AdjustMode {
381
+ ///
382
+ /// Returns the unadjusted type for expr patterns.
383
+ fn calc_adjust_mode (
384
+ & self ,
385
+ pat : & ' tcx Pat < ' tcx > ,
386
+ opt_path_res : Option < Res > ,
387
+ ) -> ( AdjustMode , Option < Ty < ' tcx > > ) {
380
388
// When we perform destructuring assignment, we disable default match bindings, which are
381
389
// unintuitive in this context.
382
390
if !pat. default_binding_modes {
383
- return AdjustMode :: Reset ;
391
+ return ( AdjustMode :: Reset , None ) ;
384
392
}
385
- match & pat. kind {
393
+ let adjust = match & pat. kind {
386
394
// Type checking these product-like types successfully always require
387
395
// that the expected type be of those types and not reference types.
388
396
PatKind :: Struct ( ..)
@@ -399,9 +407,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
399
407
// As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
400
408
//
401
409
// 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 ,
410
+ PatKind :: Expr ( lt) => {
411
+ let ty = self . resolve_vars_if_possible ( self . check_pat_expr_unadjusted ( lt, pat. hir_id , pat. span ) ) ;
412
+ let adjust = match ty. kind ( ) {
413
+ ty:: Ref ( ..) => AdjustMode :: Pass ,
414
+ _ => AdjustMode :: Peel ,
415
+ } ;
416
+ return ( adjust, Some ( ty) )
405
417
} ,
406
418
PatKind :: Path ( _) => match opt_path_res. unwrap ( ) {
407
419
// These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
@@ -431,7 +443,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
431
443
| PatKind :: Or ( _)
432
444
// Like or-patterns, guard patterns just propogate to their subpatterns.
433
445
| PatKind :: Guard ( ..) => AdjustMode :: Pass ,
434
- }
446
+ } ;
447
+ ( adjust, None )
435
448
}
436
449
437
450
/// Peel off as many immediately nested `& mut?` from the expected type as possible
@@ -494,8 +507,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
494
507
( expected, def_br, max_ref_mutbl)
495
508
}
496
509
497
- fn check_pat_expr_unadjusted ( & self , lt : & ' tcx hir:: PatExpr < ' tcx > ) -> Ty < ' tcx > {
498
- let ty = match & lt. kind {
510
+ fn check_pat_expr_unadjusted (
511
+ & self ,
512
+ kind : & ' tcx hir:: PatExprKind < ' tcx > ,
513
+ hir_id : HirId ,
514
+ span : Span ,
515
+ ) -> Ty < ' tcx > {
516
+ match kind {
499
517
rustc_hir:: PatExprKind :: Lit { lit, .. } => {
500
518
self . check_expr_lit ( lit, Expectation :: NoExpectation )
501
519
}
@@ -504,42 +522,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
504
522
}
505
523
rustc_hir:: PatExprKind :: Path ( qpath) => {
506
524
let ( res, opt_ty, segments) =
507
- self . resolve_ty_and_res_fully_qualified_call ( qpath, lt . hir_id , lt . span ) ;
508
- self . instantiate_value_path ( segments, opt_ty, res, lt . span , lt . span , lt . hir_id ) . 0
525
+ self . resolve_ty_and_res_fully_qualified_call ( qpath, hir_id, span) ;
526
+ self . instantiate_value_path ( segments, opt_ty, res, span, span, hir_id) . 0
509
527
}
510
- } ;
511
- self . write_ty ( lt. hir_id , ty) ;
512
- ty
528
+ }
513
529
}
514
530
515
531
fn check_pat_lit (
516
532
& self ,
533
+ hir_id : HirId ,
517
534
span : Span ,
518
- lt : & hir:: PatExpr < ' tcx > ,
535
+ lt : & hir:: PatExprKind < ' tcx > ,
519
536
expected : Ty < ' tcx > ,
520
537
ti : & TopInfo < ' tcx > ,
538
+ mut pat_ty : Ty < ' tcx > ,
521
539
) -> Ty < ' tcx > {
522
- // We've already computed the type above (when checking for a non-ref pat),
523
- // so avoid computing it again.
524
- let ty = self . node_ty ( lt. hir_id ) ;
525
-
526
540
// Byte string patterns behave the same way as array patterns
527
541
// They can denote both statically and dynamically-sized byte arrays.
528
- let mut pat_ty = ty;
529
542
if let hir:: PatExprKind :: Lit {
530
543
lit : Spanned { node : ast:: LitKind :: ByteStr ( ..) , .. } , ..
531
- } = lt. kind
544
+ } = lt
532
545
{
533
546
let expected = self . structurally_resolve_type ( span, expected) ;
534
547
if let ty:: Ref ( _, inner_ty, _) = * expected. kind ( )
535
548
&& self . try_structurally_resolve_type ( span, inner_ty) . is_slice ( )
536
549
{
537
550
let tcx = self . tcx ;
538
- trace ! ( ?lt. hir_id. local_id, "polymorphic byte string lit" ) ;
539
- self . typeck_results
540
- . borrow_mut ( )
541
- . treat_byte_string_as_slice
542
- . insert ( lt. hir_id . local_id ) ;
551
+ trace ! ( ?hir_id. local_id, "polymorphic byte string lit" ) ;
552
+ self . typeck_results . borrow_mut ( ) . lit_pat_type_adjusted . insert ( hir_id. local_id ) ;
543
553
pat_ty =
544
554
Ty :: new_imm_ref ( tcx, tcx. lifetimes . re_static , Ty :: new_slice ( tcx, tcx. types . u8 ) ) ;
545
555
}
@@ -548,10 +558,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
548
558
if self . tcx . features ( ) . string_deref_patterns ( )
549
559
&& let hir:: PatExprKind :: Lit {
550
560
lit : Spanned { node : ast:: LitKind :: Str ( ..) , .. } , ..
551
- } = lt. kind
561
+ } = lt
552
562
{
553
563
let tcx = self . tcx ;
554
564
let expected = self . resolve_vars_if_possible ( expected) ;
565
+ self . typeck_results . borrow_mut ( ) . lit_pat_type_adjusted . insert ( hir_id. local_id ) ;
555
566
pat_ty = match expected. kind ( ) {
556
567
ty:: Adt ( def, _) if tcx. is_lang_item ( def. did ( ) , LangItem :: String ) => expected,
557
568
ty:: Str => Ty :: new_static_str ( tcx) ,
@@ -597,7 +608,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
597
608
let calc_side = |opt_expr : Option < & ' tcx hir:: PatExpr < ' tcx > > | match opt_expr {
598
609
None => None ,
599
610
Some ( expr) => {
600
- let ty = self . check_pat_expr_unadjusted ( expr) ;
611
+ let ty = self . check_pat_expr_unadjusted ( & expr. kind , expr. hir_id , expr. span ) ;
612
+
613
+ self . write_ty ( expr. hir_id , ty) ;
601
614
// Check that the end-point is possibly of numeric or char type.
602
615
// The early check here is not for correctness, but rather better
603
616
// diagnostics (e.g. when `&str` is being matched, `expected` will
0 commit comments