@@ -20,21 +20,33 @@ use std::cmp;
2020use  super :: report_unexpected_variant_def; 
2121
2222impl < ' a ,  ' gcx ,  ' tcx >  FnCtxt < ' a ,  ' gcx ,  ' tcx >  { 
23-     /// The `is_arg` argument indicates whether this pattern is the 
24- /// *outermost* pattern in an argument (e.g., in `fn foo(&x: 
25- /// &u32)`, it is true for the `&x` pattern but not `x`). This is 
26- /// used to tailor error reporting. 
23+     /// `match_discrim_span` argument having a `Span` indicates that this pattern is part of 
24+ /// a match expression arm guard, and it points to the match discriminant to add context 
25+ /// in type errors. In the folloowing example, `match_discrim_span` corresponds to the 
26+ /// `a + b` expression: 
27+ /// 
28+ /// ```text 
29+ /// error[E0308]: mismatched types 
30+ ///  --> src/main.rs:5:9 
31+ ///   | 
32+ /// 4 |    let temp: usize = match a + b { 
33+ ///   |                            ----- this expression has type `usize` 
34+ /// 5 |         Ok(num) => num, 
35+ ///   |         ^^^^^^^ expected usize, found enum `std::result::Result` 
36+ ///   | 
37+ ///   = note: expected type `usize` 
38+ ///              found type `std::result::Result<_, _>` 
39+ /// ``` 
2740pub  fn  check_pat_walk ( 
2841        & self , 
2942        pat :  & ' gcx  hir:: Pat , 
3043        mut  expected :  Ty < ' tcx > , 
3144        mut  def_bm :  ty:: BindingMode , 
32-         is_arg :   bool ) 
33-     { 
45+         match_discrim_span :   Option < Span > , 
46+     )   { 
3447        let  tcx = self . tcx ; 
3548
36-         debug ! ( "check_pat_walk(pat={:?},expected={:?},def_bm={:?},is_arg={})" , 
37-             pat,  expected,  def_bm,  is_arg) ; 
49+         debug ! ( "check_pat_walk(pat={:?},expected={:?},def_bm={:?})" ,  pat,  expected,  def_bm) ; 
3850
3951        let  is_non_ref_pat = match  pat. node  { 
4052            PatKind :: Struct ( ..)  |
@@ -210,8 +222,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
210222                let  common_type = self . resolve_type_vars_if_possible ( & lhs_ty) ; 
211223
212224                // subtyping doesn't matter here, as the value is some kind of scalar 
213-                 self . demand_eqtype ( pat. span ,  expected,  lhs_ty) ; 
214-                 self . demand_eqtype ( pat. span ,  expected,  rhs_ty) ; 
225+                 self . demand_eqtype_pat ( pat. span ,  expected,  lhs_ty,  match_discrim_span ) ; 
226+                 self . demand_eqtype_pat ( pat. span ,  expected,  rhs_ty,  match_discrim_span ) ; 
215227                common_type
216228            } 
217229            PatKind :: Binding ( ba,  var_id,  _,  ref  sub)  => { 
@@ -240,37 +252,45 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
240252                        // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is 
241253                        // required. However, we use equality, which is stronger. See (*) for 
242254                        // an explanation. 
243-                         self . demand_eqtype ( pat. span ,  region_ty,  local_ty) ; 
255+                         self . demand_eqtype_pat ( pat. span ,  region_ty,  local_ty,  match_discrim_span ) ; 
244256                    } 
245257                    // otherwise the type of x is the expected type T 
246258                    ty:: BindByValue ( _)  => { 
247259                        // As above, `T <: typeof(x)` is required but we 
248260                        // use equality, see (*) below. 
249-                         self . demand_eqtype ( pat. span ,  expected,  local_ty) ; 
261+                         self . demand_eqtype_pat ( pat. span ,  expected,  local_ty,  match_discrim_span ) ; 
250262                    } 
251263                } 
252264
253265                // if there are multiple arms, make sure they all agree on 
254266                // what the type of the binding `x` ought to be 
255267                if  var_id != pat. id  { 
256268                    let  vt = self . local_ty ( pat. span ,  var_id) . decl_ty ; 
257-                     self . demand_eqtype ( pat. span ,  vt,  local_ty) ; 
269+                     self . demand_eqtype_pat ( pat. span ,  vt,  local_ty,  match_discrim_span ) ; 
258270                } 
259271
260272                if  let  Some ( ref  p)  = * sub { 
261-                     self . check_pat_walk ( & p,  expected,  def_bm,  true ) ; 
273+                     self . check_pat_walk ( & p,  expected,  def_bm,  match_discrim_span ) ; 
262274                } 
263275
264276                local_ty
265277            } 
266278            PatKind :: TupleStruct ( ref  qpath,  ref  subpats,  ddpos)  => { 
267-                 self . check_pat_tuple_struct ( pat,  qpath,  & subpats,  ddpos,  expected,  def_bm) 
279+                 self . check_pat_tuple_struct ( 
280+                     pat, 
281+                     qpath, 
282+                     & subpats, 
283+                     ddpos, 
284+                     expected, 
285+                     def_bm, 
286+                     match_discrim_span, 
287+                 ) 
268288            } 
269289            PatKind :: Path ( ref  qpath)  => { 
270290                self . check_pat_path ( pat,  qpath,  expected) 
271291            } 
272292            PatKind :: Struct ( ref  qpath,  ref  fields,  etc)  => { 
273-                 self . check_pat_struct ( pat,  qpath,  fields,  etc,  expected,  def_bm) 
293+                 self . check_pat_struct ( pat,  qpath,  fields,  etc,  expected,  def_bm,  match_discrim_span ) 
274294            } 
275295            PatKind :: Tuple ( ref  elements,  ddpos)  => { 
276296                let  mut  expected_len = elements. len ( ) ; 
@@ -295,12 +315,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
295315                    // further errors being emitted when using the bindings. #50333 
296316                    let  element_tys_iter = ( 0 ..max_len) . map ( |_| tcx. types . err ) ; 
297317                    for  ( _,  elem)  in  elements. iter ( ) . enumerate_and_adjust ( max_len,  ddpos)  { 
298-                         self . check_pat_walk ( elem,  & tcx. types . err ,  def_bm,  true ) ; 
318+                         self . check_pat_walk ( elem,  & tcx. types . err ,  def_bm,  match_discrim_span ) ; 
299319                    } 
300320                    tcx. mk_tup ( element_tys_iter) 
301321                }  else  { 
302322                    for  ( i,  elem)  in  elements. iter ( ) . enumerate_and_adjust ( max_len,  ddpos)  { 
303-                         self . check_pat_walk ( elem,  & element_tys[ i] ,  def_bm,  true ) ; 
323+                         self . check_pat_walk ( elem,  & element_tys[ i] ,  def_bm,  match_discrim_span ) ; 
304324                    } 
305325                    pat_ty
306326                } 
@@ -313,11 +333,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
313333                    // Here, `demand::subtype` is good enough, but I don't 
314334                    // think any errors can be introduced by using 
315335                    // `demand::eqtype`. 
316-                     self . demand_eqtype ( pat. span ,  expected,  uniq_ty) ; 
317-                     self . check_pat_walk ( & inner,  inner_ty,  def_bm,  true ) ; 
336+                     self . demand_eqtype_pat ( pat. span ,  expected,  uniq_ty,  match_discrim_span ) ; 
337+                     self . check_pat_walk ( & inner,  inner_ty,  def_bm,  match_discrim_span ) ; 
318338                    uniq_ty
319339                }  else  { 
320-                     self . check_pat_walk ( & inner,  tcx. types . err ,  def_bm,  true ) ; 
340+                     self . check_pat_walk ( & inner,  tcx. types . err ,  def_bm,  match_discrim_span ) ; 
321341                    tcx. types . err 
322342                } 
323343            } 
@@ -349,15 +369,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
349369                            // Look for a case like `fn foo(&foo: u32)` and suggest 
350370                            // `fn foo(foo: &u32)` 
351371                            if  let  Some ( mut  err)  = err { 
352-                                 if  is_arg { 
353-                                     if  let  PatKind :: Binding ( ..)  = inner. node  { 
354-                                         if  let  Ok ( snippet)  = tcx. sess . source_map ( ) 
355-                                                                      . span_to_snippet ( pat. span ) 
356-                                         { 
357-                                             err. help ( & format ! ( "did you mean `{}: &{}`?" , 
358-                                                               & snippet[ 1 ..] , 
359-                                                               expected) ) ; 
360-                                         } 
372+                                 if  let  PatKind :: Binding ( ..)  = inner. node  { 
373+                                     if  let  Ok ( snippet)  = tcx. sess . source_map ( ) 
374+                                                                     . span_to_snippet ( pat. span ) 
375+                                     { 
376+                                         err. help ( & format ! ( "did you mean `{}: &{}`?" , 
377+                                                             & snippet[ 1 ..] , 
378+                                                             expected) ) ; 
361379                                    } 
362380                                } 
363381                                err. emit ( ) ; 
@@ -366,10 +384,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
366384                        } 
367385                    } ; 
368386
369-                     self . check_pat_walk ( & inner,  inner_ty,  def_bm,  true ) ; 
387+                     self . check_pat_walk ( & inner,  inner_ty,  def_bm,  match_discrim_span ) ; 
370388                    rptr_ty
371389                }  else  { 
372-                     self . check_pat_walk ( & inner,  tcx. types . err ,  def_bm,  true ) ; 
390+                     self . check_pat_walk ( & inner,  tcx. types . err ,  def_bm,  match_discrim_span ) ; 
373391                    tcx. types . err 
374392                } 
375393            } 
@@ -427,13 +445,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
427445                } ; 
428446
429447                for  elt in  before { 
430-                     self . check_pat_walk ( & elt,  inner_ty,  def_bm,  true ) ; 
448+                     self . check_pat_walk ( & elt,  inner_ty,  def_bm,  match_discrim_span ) ; 
431449                } 
432450                if  let  Some ( ref  slice)  = * slice { 
433-                     self . check_pat_walk ( & slice,  slice_ty,  def_bm,  true ) ; 
451+                     self . check_pat_walk ( & slice,  slice_ty,  def_bm,  match_discrim_span ) ; 
434452                } 
435453                for  elt in  after { 
436-                     self . check_pat_walk ( & elt,  inner_ty,  def_bm,  true ) ; 
454+                     self . check_pat_walk ( & elt,  inner_ty,  def_bm,  match_discrim_span ) ; 
437455                } 
438456                expected_ty
439457            } 
@@ -524,12 +542,14 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
524542        true 
525543    } 
526544
527-     pub  fn  check_match ( & self , 
528-                        expr :  & ' gcx  hir:: Expr , 
529-                        discrim :  & ' gcx  hir:: Expr , 
530-                        arms :  & ' gcx  [ hir:: Arm ] , 
531-                        expected :  Expectation < ' tcx > , 
532-                        match_src :  hir:: MatchSource )  -> Ty < ' tcx >  { 
545+     pub  fn  check_match ( 
546+         & self , 
547+         expr :  & ' gcx  hir:: Expr , 
548+         discrim :  & ' gcx  hir:: Expr , 
549+         arms :  & ' gcx  [ hir:: Arm ] , 
550+         expected :  Expectation < ' tcx > , 
551+         match_src :  hir:: MatchSource , 
552+     )  -> Ty < ' tcx >  { 
533553        let  tcx = self . tcx ; 
534554
535555        // Not entirely obvious: if matches may create ref bindings, we want to 
@@ -624,8 +644,12 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
624644            let  mut  all_pats_diverge = Diverges :: WarnedAlways ; 
625645            for  p in  & arm. pats  { 
626646                self . diverges . set ( Diverges :: Maybe ) ; 
627-                 self . check_pat_walk ( & p,  discrim_ty, 
628-                     ty:: BindingMode :: BindByValue ( hir:: Mutability :: MutImmutable ) ,  true ) ; 
647+                 self . check_pat_walk ( 
648+                     & p, 
649+                     discrim_ty, 
650+                     ty:: BindingMode :: BindByValue ( hir:: Mutability :: MutImmutable ) , 
651+                     Some ( discrim. span ) , 
652+                 ) ; 
629653                all_pats_diverge &= self . diverges . get ( ) ; 
630654            } 
631655
@@ -703,26 +727,34 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
703727        coercion. complete ( self ) 
704728    } 
705729
706-     fn  check_pat_struct ( & self , 
707-                         pat :  & ' gcx  hir:: Pat , 
708-                         qpath :  & hir:: QPath , 
709-                         fields :  & ' gcx  [ Spanned < hir:: FieldPat > ] , 
710-                         etc :  bool , 
711-                         expected :  Ty < ' tcx > , 
712-                         def_bm :  ty:: BindingMode )  -> Ty < ' tcx > 
730+     fn  check_pat_struct ( 
731+         & self , 
732+         pat :  & ' gcx  hir:: Pat , 
733+         qpath :  & hir:: QPath , 
734+         fields :  & ' gcx  [ Spanned < hir:: FieldPat > ] , 
735+         etc :  bool , 
736+         expected :  Ty < ' tcx > , 
737+         def_bm :  ty:: BindingMode , 
738+         match_discrim_span :  Option < Span > , 
739+     )  -> Ty < ' tcx > 
713740    { 
714741        // Resolve the path and check the definition for errors. 
715742        let  ( variant,  pat_ty)  = if  let  Some ( variant_ty)  = self . check_struct_path ( qpath,  pat. id )  { 
716743            variant_ty
717744        }  else  { 
718745            for  field in  fields { 
719-                 self . check_pat_walk ( & field. node . pat ,  self . tcx . types . err ,  def_bm,  true ) ; 
746+                 self . check_pat_walk ( 
747+                     & field. node . pat , 
748+                     self . tcx . types . err , 
749+                     def_bm, 
750+                     match_discrim_span, 
751+                 ) ; 
720752            } 
721753            return  self . tcx . types . err ; 
722754        } ; 
723755
724756        // Type-check the path. 
725-         self . demand_eqtype ( pat. span ,  expected,  pat_ty) ; 
757+         self . demand_eqtype_pat ( pat. span ,  expected,  pat_ty,  match_discrim_span ) ; 
726758
727759        // Type-check subpatterns. 
728760        if  self . check_struct_pat_fields ( pat_ty,  pat. id ,  pat. span ,  variant,  fields,  etc,  def_bm)  { 
@@ -732,11 +764,12 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
732764        } 
733765    } 
734766
735-     fn  check_pat_path ( & self , 
736-                       pat :  & hir:: Pat , 
737-                       qpath :  & hir:: QPath , 
738-                       expected :  Ty < ' tcx > )  -> Ty < ' tcx > 
739-     { 
767+     fn  check_pat_path ( 
768+         & self , 
769+         pat :  & hir:: Pat , 
770+         qpath :  & hir:: QPath , 
771+         expected :  Ty < ' tcx > , 
772+     )  -> Ty < ' tcx >  { 
740773        let  tcx = self . tcx ; 
741774
742775        // Resolve the path and check the definition for errors. 
@@ -767,18 +800,20 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
767800        pat_ty
768801    } 
769802
770-     fn  check_pat_tuple_struct ( & self , 
771-                               pat :  & hir:: Pat , 
772-                               qpath :  & hir:: QPath , 
773-                               subpats :  & ' gcx  [ P < hir:: Pat > ] , 
774-                               ddpos :  Option < usize > , 
775-                               expected :  Ty < ' tcx > , 
776-                               def_bm :  ty:: BindingMode )  -> Ty < ' tcx > 
777-     { 
803+     fn  check_pat_tuple_struct ( 
804+         & self , 
805+         pat :  & hir:: Pat , 
806+         qpath :  & hir:: QPath , 
807+         subpats :  & ' gcx  [ P < hir:: Pat > ] , 
808+         ddpos :  Option < usize > , 
809+         expected :  Ty < ' tcx > , 
810+         def_bm :  ty:: BindingMode , 
811+         match_arm_pat_span :  Option < Span > , 
812+     )  -> Ty < ' tcx >  { 
778813        let  tcx = self . tcx ; 
779814        let  on_error = || { 
780815            for  pat in  subpats { 
781-                 self . check_pat_walk ( & pat,  tcx. types . err ,  def_bm,  true ) ; 
816+                 self . check_pat_walk ( & pat,  tcx. types . err ,  def_bm,  match_arm_pat_span ) ; 
782817            } 
783818        } ; 
784819        let  report_unexpected_def = |def :  Def | { 
@@ -826,7 +861,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
826861        let  pat_ty = pat_ty. fn_sig ( tcx) . output ( ) ; 
827862        let  pat_ty = pat_ty. no_bound_vars ( ) . expect ( "expected fn type" ) ; 
828863
829-         self . demand_eqtype ( pat. span ,  expected,  pat_ty) ; 
864+         self . demand_eqtype_pat ( pat. span ,  expected,  pat_ty,  match_arm_pat_span ) ; 
830865
831866        // Type-check subpatterns. 
832867        if  subpats. len ( )  == variant. fields . len ( )  ||
@@ -837,7 +872,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
837872            } ; 
838873            for  ( i,  subpat)  in  subpats. iter ( ) . enumerate_and_adjust ( variant. fields . len ( ) ,  ddpos)  { 
839874                let  field_ty = self . field_ty ( subpat. span ,  & variant. fields [ i] ,  substs) ; 
840-                 self . check_pat_walk ( & subpat,  field_ty,  def_bm,  true ) ; 
875+                 self . check_pat_walk ( & subpat,  field_ty,  def_bm,  match_arm_pat_span ) ; 
841876
842877                self . tcx . check_stability ( variant. fields [ i] . did ,  Some ( pat. id ) ,  subpat. span ) ; 
843878            } 
@@ -917,7 +952,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
917952                } 
918953            } ; 
919954
920-             self . check_pat_walk ( & field. pat ,  field_ty,  def_bm,  true ) ; 
955+             self . check_pat_walk ( & field. pat ,  field_ty,  def_bm,  None ) ; 
921956        } 
922957        let  mut  unmentioned_fields = variant. fields 
923958                . iter ( ) 
0 commit comments