@@ -600,7 +600,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
600600 // If there are multiple arms, make sure they all agree on
601601 // what the type of the binding `x` ought to be.
602602 if var_id != pat. hir_id {
603- self . check_binding_alt_eq_ty ( pat. span , var_id, local_ty, ti) ;
603+ self . check_binding_alt_eq_ty ( ba , pat. span , var_id, local_ty, ti) ;
604604 }
605605
606606 if let Some ( p) = sub {
@@ -610,7 +610,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
610610 local_ty
611611 }
612612
613- fn check_binding_alt_eq_ty ( & self , span : Span , var_id : HirId , ty : Ty < ' tcx > , ti : TopInfo < ' tcx > ) {
613+ fn check_binding_alt_eq_ty (
614+ & self ,
615+ ba : hir:: BindingAnnotation ,
616+ span : Span ,
617+ var_id : HirId ,
618+ ty : Ty < ' tcx > ,
619+ ti : TopInfo < ' tcx > ,
620+ ) {
614621 let var_ty = self . local_ty ( span, var_id) . decl_ty ;
615622 if let Some ( mut err) = self . demand_eqtype_pat_diag ( span, var_ty, ty, ti) {
616623 let hir = self . tcx . hir ( ) ;
@@ -628,12 +635,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
628635 } ) ;
629636 let pre = if in_match { "in the same arm, " } else { "" } ;
630637 err. note ( & format ! ( "{}a binding must have the same type in all alternatives" , pre) ) ;
631- // FIXME: check if `var_ty` and `ty` can be made the same type by adding or removing
632- // `ref` or `&` to the pattern.
638+ self . suggest_adding_missing_ref_or_removing_ref (
639+ & mut err,
640+ span,
641+ var_ty,
642+ self . resolve_vars_with_obligations ( ty) ,
643+ ba,
644+ ) ;
633645 err. emit ( ) ;
634646 }
635647 }
636648
649+ fn suggest_adding_missing_ref_or_removing_ref (
650+ & self ,
651+ err : & mut Diagnostic ,
652+ span : Span ,
653+ expected : Ty < ' tcx > ,
654+ actual : Ty < ' tcx > ,
655+ ba : hir:: BindingAnnotation ,
656+ ) {
657+ match ( expected. kind ( ) , actual. kind ( ) , ba) {
658+ ( ty:: Ref ( _, inner_ty, _) , _, hir:: BindingAnnotation :: Unannotated )
659+ if self . can_eq ( self . param_env , * inner_ty, actual) . is_ok ( ) =>
660+ {
661+ err. span_suggestion_verbose (
662+ span. shrink_to_lo ( ) ,
663+ "consider adding `ref`" ,
664+ "ref " ,
665+ Applicability :: MaybeIncorrect ,
666+ ) ;
667+ }
668+ ( _, ty:: Ref ( _, inner_ty, _) , hir:: BindingAnnotation :: Ref )
669+ if self . can_eq ( self . param_env , expected, * inner_ty) . is_ok ( ) =>
670+ {
671+ err. span_suggestion_verbose (
672+ span. with_hi ( span. lo ( ) + BytePos ( 4 ) ) ,
673+ "consider removing `ref`" ,
674+ "" ,
675+ Applicability :: MaybeIncorrect ,
676+ ) ;
677+ }
678+ _ => ( ) ,
679+ }
680+ }
681+
637682 // Precondition: pat is a Ref(_) pattern
638683 fn borrow_pat_suggestion ( & self , err : & mut Diagnostic , pat : & Pat < ' _ > ) {
639684 let tcx = self . tcx ;
0 commit comments