@@ -256,7 +256,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
256256 }
257257 _ => None ,
258258 } ;
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) ) ;
260260 let ( expected, binding_mode, max_ref_mutbl) =
261261 self . calc_default_binding_mode ( pat, expected, binding_mode, adjust_mode, max_ref_mutbl) ;
262262 let pat_info = PatInfo {
@@ -271,7 +271,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
271271 PatKind :: Wild | PatKind :: Err ( _) => expected,
272272 // We allow any type here; we ensure that the type is uninhabited during match checking.
273273 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+ }
275277 PatKind :: Range ( lhs, rhs, _) => self . check_pat_range ( pat. span , lhs, rhs, expected, ti) ,
276278 PatKind :: Binding ( ba, var_id, ident, sub) => {
277279 self . check_pat_ident ( pat, ba, var_id, ident, sub, expected, pat_info)
@@ -376,13 +378,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
376378 /// How should the binding mode and expected type be adjusted?
377379 ///
378380 /// 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 > > ) {
380388 // When we perform destructuring assignment, we disable default match bindings, which are
381389 // unintuitive in this context.
382390 if !pat. default_binding_modes {
383- return AdjustMode :: Reset ;
391+ return ( AdjustMode :: Reset , None ) ;
384392 }
385- match & pat. kind {
393+ let adjust = match & pat. kind {
386394 // Type checking these product-like types successfully always require
387395 // that the expected type be of those types and not reference types.
388396 PatKind :: Struct ( ..)
@@ -399,9 +407,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
399407 // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
400408 //
401409 // 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) )
405417 } ,
406418 PatKind :: Path ( _) => match opt_path_res. unwrap ( ) {
407419 // These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
@@ -431,7 +443,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
431443 | PatKind :: Or ( _)
432444 // Like or-patterns, guard patterns just propogate to their subpatterns.
433445 | PatKind :: Guard ( ..) => AdjustMode :: Pass ,
434- }
446+ } ;
447+ ( adjust, None )
435448 }
436449
437450 /// Peel off as many immediately nested `& mut?` from the expected type as possible
@@ -494,8 +507,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
494507 ( expected, def_br, max_ref_mutbl)
495508 }
496509
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 {
499517 rustc_hir:: PatExprKind :: Lit { lit, .. } => {
500518 self . check_expr_lit ( lit, Expectation :: NoExpectation )
501519 }
@@ -504,42 +522,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
504522 }
505523 rustc_hir:: PatExprKind :: Path ( qpath) => {
506524 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
509527 }
510- } ;
511- self . write_ty ( lt. hir_id , ty) ;
512- ty
528+ }
513529 }
514530
515531 fn check_pat_lit (
516532 & self ,
533+ hir_id : HirId ,
517534 span : Span ,
518- lt : & hir:: PatExpr < ' tcx > ,
535+ lt : & hir:: PatExprKind < ' tcx > ,
519536 expected : Ty < ' tcx > ,
520537 ti : & TopInfo < ' tcx > ,
538+ mut pat_ty : Ty < ' tcx > ,
521539 ) -> 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-
526540 // Byte string patterns behave the same way as array patterns
527541 // They can denote both statically and dynamically-sized byte arrays.
528- let mut pat_ty = ty;
529542 if let hir:: PatExprKind :: Lit {
530543 lit : Spanned { node : ast:: LitKind :: ByteStr ( ..) , .. } , ..
531- } = lt. kind
544+ } = lt
532545 {
533546 let expected = self . structurally_resolve_type ( span, expected) ;
534547 if let ty:: Ref ( _, inner_ty, _) = * expected. kind ( )
535548 && self . try_structurally_resolve_type ( span, inner_ty) . is_slice ( )
536549 {
537550 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 ) ;
543553 pat_ty =
544554 Ty :: new_imm_ref ( tcx, tcx. lifetimes . re_static , Ty :: new_slice ( tcx, tcx. types . u8 ) ) ;
545555 }
@@ -548,10 +558,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
548558 if self . tcx . features ( ) . string_deref_patterns ( )
549559 && let hir:: PatExprKind :: Lit {
550560 lit : Spanned { node : ast:: LitKind :: Str ( ..) , .. } , ..
551- } = lt. kind
561+ } = lt
552562 {
553563 let tcx = self . tcx ;
554564 let expected = self . resolve_vars_if_possible ( expected) ;
565+ self . typeck_results . borrow_mut ( ) . lit_pat_type_adjusted . insert ( hir_id. local_id ) ;
555566 pat_ty = match expected. kind ( ) {
556567 ty:: Adt ( def, _) if tcx. is_lang_item ( def. did ( ) , LangItem :: String ) => expected,
557568 ty:: Str => Ty :: new_static_str ( tcx) ,
@@ -597,7 +608,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
597608 let calc_side = |opt_expr : Option < & ' tcx hir:: PatExpr < ' tcx > > | match opt_expr {
598609 None => None ,
599610 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) ;
601614 // Check that the end-point is possibly of numeric or char type.
602615 // The early check here is not for correctness, but rather better
603616 // diagnostics (e.g. when `&str` is being matched, `expected` will
0 commit comments