@@ -9,9 +9,9 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator;
99use rustc_hir:: { HirId , Pat , PatKind } ;
1010use rustc_infer:: infer;
1111use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
12- use rustc_infer:: traits:: Pattern ;
12+ use rustc_infer:: traits:: { ObligationCause , Pattern } ;
1313use rustc_span:: hygiene:: DesugaringKind ;
14- use rustc_span:: Span ;
14+ use rustc_span:: source_map :: { Span , Spanned } ;
1515use syntax:: ast;
1616use syntax:: util:: lev_distance:: find_best_match_for_name;
1717
@@ -66,16 +66,19 @@ struct TopInfo<'tcx> {
6666}
6767
6868impl < ' tcx > FnCtxt < ' _ , ' tcx > {
69+ fn pattern_cause ( & self , ti : TopInfo < ' tcx > , cause_span : Span ) -> ObligationCause < ' tcx > {
70+ let code = Pattern { span : ti. span , root_ty : ti. expected , origin_expr : ti. origin_expr } ;
71+ self . cause ( cause_span, code)
72+ }
73+
6974 fn demand_eqtype_pat_diag (
7075 & self ,
7176 cause_span : Span ,
7277 expected : Ty < ' tcx > ,
7378 actual : Ty < ' tcx > ,
7479 ti : TopInfo < ' tcx > ,
7580 ) -> Option < DiagnosticBuilder < ' tcx > > {
76- let code = Pattern { span : ti. span , root_ty : ti. expected , origin_expr : ti. origin_expr } ;
77- let cause = self . cause ( cause_span, code) ;
78- self . demand_eqtype_with_origin ( & cause, expected, actual)
81+ self . demand_eqtype_with_origin ( & self . pattern_cause ( ti, cause_span) , expected, actual)
7982 }
8083
8184 fn demand_eqtype_pat (
@@ -152,7 +155,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
152155 self . check_pat_tuple_struct ( pat, qpath, subpats, ddpos, expected, def_bm, ti)
153156 }
154157 PatKind :: Path ( ref qpath) => {
155- self . check_pat_path ( pat, path_res. unwrap ( ) , qpath, expected)
158+ self . check_pat_path ( pat, path_res. unwrap ( ) , qpath, expected, ti )
156159 }
157160 PatKind :: Struct ( ref qpath, fields, etc) => {
158161 self . check_pat_struct ( pat, qpath, fields, etc, expected, def_bm, ti)
@@ -361,16 +364,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
361364 // Byte string patterns behave the same way as array patterns
362365 // They can denote both statically and dynamically-sized byte arrays.
363366 let mut pat_ty = ty;
364- if let hir:: ExprKind :: Lit ( ref lt) = lt. kind {
365- if let ast:: LitKind :: ByteStr ( _) = lt. node {
366- let expected_ty = self . structurally_resolved_type ( span, expected) ;
367- if let ty:: Ref ( _, r_ty, _) = expected_ty. kind {
368- if let ty:: Slice ( _) = r_ty. kind {
369- let tcx = self . tcx ;
370- pat_ty =
371- tcx. mk_imm_ref ( tcx. lifetimes . re_static , tcx. mk_slice ( tcx. types . u8 ) ) ;
372- }
373- }
367+ if let hir:: ExprKind :: Lit ( Spanned { node : ast:: LitKind :: ByteStr ( _) , .. } ) = lt. kind {
368+ let expected = self . structurally_resolved_type ( span, expected) ;
369+ if let ty:: Ref ( _, ty:: TyS { kind : ty:: Slice ( _) , .. } , _) = expected. kind {
370+ let tcx = self . tcx ;
371+ pat_ty = tcx. mk_imm_ref ( tcx. lifetimes . re_static , tcx. mk_slice ( tcx. types . u8 ) ) ;
374372 }
375373 }
376374
@@ -384,7 +382,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
384382 // &'static str <: expected
385383 //
386384 // then that's equivalent to there existing a LUB.
387- if let Some ( mut err) = self . demand_suptype_diag ( span, expected, pat_ty) {
385+ let cause = self . pattern_cause ( ti, span) ;
386+ if let Some ( mut err) = self . demand_suptype_with_origin ( & cause, expected, pat_ty) {
388387 err. emit_unless (
389388 ti. span
390389 . filter ( |& s| {
@@ -543,8 +542,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
543542 // If there are multiple arms, make sure they all agree on
544543 // what the type of the binding `x` ought to be.
545544 if var_id != pat. hir_id {
546- let vt = self . local_ty ( pat. span , var_id) . decl_ty ;
547- self . demand_eqtype_pat ( pat. span , vt, local_ty, ti) ;
545+ self . check_binding_alt_eq_ty ( pat. span , var_id, local_ty, ti) ;
548546 }
549547
550548 if let Some ( p) = sub {
@@ -554,6 +552,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
554552 local_ty
555553 }
556554
555+ fn check_binding_alt_eq_ty ( & self , span : Span , var_id : HirId , ty : Ty < ' tcx > , ti : TopInfo < ' tcx > ) {
556+ let var_ty = self . local_ty ( span, var_id) . decl_ty ;
557+ if let Some ( mut err) = self . demand_eqtype_pat_diag ( span, var_ty, ty, ti) {
558+ let hir = self . tcx . hir ( ) ;
559+ let var_ty = self . resolve_vars_with_obligations ( var_ty) ;
560+ let msg = format ! ( "first introduced with type `{}` here" , var_ty) ;
561+ err. span_label ( hir. span ( var_id) , msg) ;
562+ let in_arm = hir. parent_iter ( var_id) . any ( |( _, n) | matches ! ( n, hir:: Node :: Arm ( ..) ) ) ;
563+ let pre = if in_arm { "in the same arm, " } else { "" } ;
564+ err. note ( & format ! ( "{}a binding must have the same type in all alternatives" , pre) ) ;
565+ err. emit ( ) ;
566+ }
567+ }
568+
557569 fn borrow_pat_suggestion (
558570 & self ,
559571 err : & mut DiagnosticBuilder < ' _ > ,
@@ -659,6 +671,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
659671 path_resolution : ( Res , Option < Ty < ' tcx > > , & ' b [ hir:: PathSegment < ' b > ] ) ,
660672 qpath : & hir:: QPath < ' _ > ,
661673 expected : Ty < ' tcx > ,
674+ ti : TopInfo < ' tcx > ,
662675 ) -> Ty < ' tcx > {
663676 let tcx = self . tcx ;
664677
@@ -684,7 +697,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
684697
685698 // Type-check the path.
686699 let pat_ty = self . instantiate_value_path ( segments, opt_ty, res, pat. span , pat. hir_id ) . 0 ;
687- self . demand_suptype ( pat. span , expected, pat_ty) ;
700+ if let Some ( mut err) =
701+ self . demand_suptype_with_origin ( & self . pattern_cause ( ti, pat. span ) , expected, pat_ty)
702+ {
703+ err. emit ( ) ;
704+ }
688705 pat_ty
689706 }
690707
@@ -901,7 +918,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
901918 } ) ;
902919 let element_tys = tcx. mk_substs ( element_tys_iter) ;
903920 let pat_ty = tcx. mk_ty ( ty:: Tuple ( element_tys) ) ;
904- if let Some ( mut err) = self . demand_eqtype_diag ( span, expected, pat_ty) {
921+ if let Some ( mut err) = self . demand_eqtype_pat_diag ( span, expected, pat_ty, ti ) {
905922 err. emit ( ) ;
906923 // Walk subpatterns with an expected type of `err` in this case to silence
907924 // further errors being emitted when using the bindings. #50333
@@ -1205,7 +1222,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12051222 } ) ;
12061223 let rptr_ty = self . new_ref_ty ( pat. span , mutbl, inner_ty) ;
12071224 debug ! ( "check_pat_ref: demanding {:?} = {:?}" , expected, rptr_ty) ;
1208- let err = self . demand_eqtype_diag ( pat. span , expected, rptr_ty) ;
1225+ let err = self . demand_eqtype_pat_diag ( pat. span , expected, rptr_ty, ti ) ;
12091226
12101227 // Look for a case like `fn foo(&foo: u32)` and suggest
12111228 // `fn foo(foo: &u32)`
0 commit comments