@@ -37,7 +37,7 @@ use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
3737use std:: fmt;
3838use syntax:: ast;
3939use ty:: { self , AdtKind , ToPredicate , ToPolyTraitRef , Ty , TyCtxt , TypeFoldable } ;
40- use ty:: error:: { ExpectedFound , TypeError } ;
40+ use ty:: error:: ExpectedFound ;
4141use ty:: fast_reject;
4242use ty:: fold:: TypeFolder ;
4343use ty:: subst:: Subst ;
@@ -711,7 +711,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
711711 }
712712 }
713713
714- OutputTypeParameterMismatch ( ref expected_trait_ref, ref actual_trait_ref, ref e ) => {
714+ OutputTypeParameterMismatch ( ref expected_trait_ref, ref actual_trait_ref, _ ) => {
715715 let expected_trait_ref = self . resolve_type_vars_if_possible ( & * expected_trait_ref) ;
716716 let actual_trait_ref = self . resolve_type_vars_if_possible ( & * actual_trait_ref) ;
717717 if actual_trait_ref. self_ty ( ) . references_error ( ) {
@@ -722,48 +722,31 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
722722 self . tcx . hir . span_if_local ( did)
723723 } ) ;
724724
725- if let & TypeError :: TupleSize ( ref expected_found) = e {
726- // Expected `|x| { }`, found `|x, y| { }`
727- self . report_arg_count_mismatch ( span,
728- found_span,
729- expected_found. expected ,
730- expected_found. found ,
731- expected_trait_ty. is_closure ( ) )
732- } else if let & TypeError :: Sorts ( ref expected_found) = e {
733- let expected = if let ty:: TyTuple ( tys, _) = expected_found. expected . sty {
734- tys. len ( )
735- } else {
736- 1
725+ let self_ty_count =
726+ match expected_trait_ref. skip_binder ( ) . substs . type_at ( 1 ) . sty {
727+ ty:: TyTuple ( ref tys, _) => tys. len ( ) ,
728+ _ => 1 ,
737729 } ;
738- let found = if let ty :: TyTuple ( tys , _ ) = expected_found . found . sty {
739- tys . len ( )
740- } else {
741- 1
730+ let arg_ty_count =
731+ match actual_trait_ref . skip_binder ( ) . substs . type_at ( 1 ) . sty {
732+ ty :: TyTuple ( ref tys , _ ) => tys . len ( ) ,
733+ _ => 1 ,
742734 } ;
743-
744- if expected != found {
745- // Expected `|| { }`, found `|x, y| { }`
746- // Expected `fn(x) -> ()`, found `|| { }`
747- self . report_arg_count_mismatch ( span,
748- found_span,
749- expected,
750- found,
751- expected_trait_ty. is_closure ( ) )
752- } else {
753- self . report_type_argument_mismatch ( span,
754- found_span,
755- expected_trait_ty,
756- expected_trait_ref,
757- actual_trait_ref,
758- e)
759- }
735+ if self_ty_count == arg_ty_count {
736+ self . report_closure_arg_mismatch ( span,
737+ found_span,
738+ expected_trait_ref,
739+ actual_trait_ref)
760740 } else {
761- self . report_type_argument_mismatch ( span,
762- found_span,
763- expected_trait_ty,
764- expected_trait_ref,
765- actual_trait_ref,
766- e)
741+ // Expected `|| { }`, found `|x, y| { }`
742+ // Expected `fn(x) -> ()`, found `|| { }`
743+ self . report_arg_count_mismatch (
744+ span,
745+ found_span,
746+ arg_ty_count,
747+ self_ty_count,
748+ expected_trait_ty. is_closure ( )
749+ )
767750 }
768751 }
769752
@@ -784,31 +767,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
784767 err. emit ( ) ;
785768 }
786769
787- fn report_type_argument_mismatch ( & self ,
788- span : Span ,
789- found_span : Option < Span > ,
790- expected_ty : Ty < ' tcx > ,
791- expected_ref : ty:: PolyTraitRef < ' tcx > ,
792- found_ref : ty:: PolyTraitRef < ' tcx > ,
793- type_error : & TypeError < ' tcx > )
794- -> DiagnosticBuilder < ' tcx >
795- {
796- let mut err = struct_span_err ! ( self . tcx. sess, span, E0281 ,
797- "type mismatch: `{}` implements the trait `{}`, but the trait `{}` is required" ,
798- expected_ty,
799- expected_ref,
800- found_ref) ;
801-
802- err. span_label ( span, format ! ( "{}" , type_error) ) ;
803-
804- if let Some ( sp) = found_span {
805- err. span_label ( span, format ! ( "requires `{}`" , found_ref) ) ;
806- err. span_label ( sp, format ! ( "implements `{}`" , expected_ref) ) ;
807- }
808-
809- err
810- }
811-
812770 fn report_arg_count_mismatch ( & self ,
813771 span : Span ,
814772 found_span : Option < Span > ,
@@ -837,6 +795,57 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
837795 }
838796 err
839797 }
798+
799+ fn report_closure_arg_mismatch ( & self ,
800+ span : Span ,
801+ found_span : Option < Span > ,
802+ expected_ref : ty:: PolyTraitRef < ' tcx > ,
803+ found : ty:: PolyTraitRef < ' tcx > )
804+ -> DiagnosticBuilder < ' tcx >
805+ {
806+ fn build_fn_sig_string < ' a , ' gcx , ' tcx > ( tcx : ty:: TyCtxt < ' a , ' gcx , ' tcx > ,
807+ trait_ref : & ty:: TraitRef < ' tcx > ) -> String {
808+ let inputs = trait_ref. substs . type_at ( 1 ) ;
809+ let sig = if let ty:: TyTuple ( inputs, _) = inputs. sty {
810+ tcx. mk_fn_sig (
811+ inputs. iter ( ) . map ( |& x| x) ,
812+ tcx. mk_infer ( ty:: TyVar ( ty:: TyVid { index : 0 } ) ) ,
813+ false ,
814+ hir:: Unsafety :: Normal ,
815+ :: syntax:: abi:: Abi :: Rust
816+ )
817+ } else {
818+ tcx. mk_fn_sig (
819+ :: std:: iter:: once ( inputs) ,
820+ tcx. mk_infer ( ty:: TyVar ( ty:: TyVid { index : 0 } ) ) ,
821+ false ,
822+ hir:: Unsafety :: Normal ,
823+ :: syntax:: abi:: Abi :: Rust
824+ )
825+ } ;
826+ format ! ( "{}" , ty:: Binder ( sig) )
827+ }
828+
829+ let argument_is_closure = expected_ref. skip_binder ( ) . substs . type_at ( 0 ) . is_closure ( ) ;
830+ let mut err = struct_span_err ! ( self . tcx. sess, span, E0631 ,
831+ "type mismatch in {} arguments" ,
832+ if argument_is_closure { "closure" } else { "function" } ) ;
833+
834+ let found_str = format ! (
835+ "expected signature of `{}`" ,
836+ build_fn_sig_string( self . tcx, found. skip_binder( ) )
837+ ) ;
838+ err. span_label ( span, found_str) ;
839+
840+ let found_span = found_span. unwrap_or ( span) ;
841+ let expected_str = format ! (
842+ "found signature of `{}`" ,
843+ build_fn_sig_string( self . tcx, expected_ref. skip_binder( ) )
844+ ) ;
845+ err. span_label ( found_span, expected_str) ;
846+
847+ err
848+ }
840849}
841850
842851impl < ' a , ' gcx , ' tcx > TyCtxt < ' a , ' gcx , ' tcx > {
0 commit comments