@@ -21,15 +21,18 @@ use rustc_hir::def_id::DefId;
2121use  rustc_hir:: { ExprKind ,  Node ,  QPath } ; 
2222use  rustc_index:: vec:: IndexVec ; 
2323use  rustc_infer:: infer:: error_reporting:: { FailureCode ,  ObligationCauseExt } ; 
24+ use  rustc_infer:: infer:: type_variable:: { TypeVariableOrigin ,  TypeVariableOriginKind } ; 
2425use  rustc_infer:: infer:: InferOk ; 
2526use  rustc_infer:: infer:: TypeTrace ; 
2627use  rustc_middle:: ty:: adjustment:: AllowTwoPhase ; 
2728use  rustc_middle:: ty:: visit:: TypeVisitable ; 
28- use  rustc_middle:: ty:: { self ,  IsSuggestable ,   Ty ,   TyCtxt } ; 
29+ use  rustc_middle:: ty:: { self ,  DefIdTree ,   IsSuggestable ,   Ty } ; 
2930use  rustc_session:: Session ; 
3031use  rustc_span:: symbol:: Ident ; 
3132use  rustc_span:: { self ,  Span } ; 
32- use  rustc_trait_selection:: traits:: { self ,  ObligationCauseCode ,  StatementAsExpression } ; 
33+ use  rustc_trait_selection:: traits:: { 
34+     self ,  ObligationCauseCode ,  SelectionContext ,  StatementAsExpression , 
35+ } ; 
3336
3437use  std:: iter; 
3538use  std:: slice; 
@@ -89,7 +92,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8992                args_no_rcvr, 
9093                false , 
9194                tuple_arguments, 
92-                 None , 
95+                 method . ok ( ) . map ( |method| method . def_id ) , 
9396            ) ; 
9497            return  self . tcx . ty_error ( ) ; 
9598        } 
@@ -393,41 +396,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
393396        } 
394397
395398        if  !call_appears_satisfied { 
396-             // Next, let's construct the error 
397-             let  ( error_span,  full_call_span,  ctor_of)  = match  & call_expr. kind  { 
398-                 hir:: ExprKind :: Call ( 
399-                     hir:: Expr  { 
400-                         span, 
401-                         kind : 
402-                             hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( 
403-                                 _, 
404-                                 hir:: Path  {  res :  Res :: Def ( DefKind :: Ctor ( of,  _) ,  _) ,  .. } , 
405-                             ) ) , 
406-                         ..
407-                     } , 
408-                     _, 
409-                 )  => ( call_span,  * span,  Some ( of) ) , 
410-                 hir:: ExprKind :: Call ( hir:: Expr  {  span,  .. } ,  _)  => ( call_span,  * span,  None ) , 
411-                 hir:: ExprKind :: MethodCall ( path_segment,  _,  span)  => { 
412-                     let  ident_span = path_segment. ident . span ; 
413-                     let  ident_span = if  let  Some ( args)  = path_segment. args  { 
414-                         ident_span. with_hi ( args. span_ext . hi ( ) ) 
415-                     }  else  { 
416-                         ident_span
417-                     } ; 
418-                     ( 
419-                         * span,  ident_span,  None ,  // methods are never ctors 
420-                     ) 
421-                 } 
422-                 k => span_bug ! ( call_span,  "checking argument types on a non-call: `{:?}`" ,  k) , 
423-             } ; 
424-             let  args_span = error_span. trim_start ( full_call_span) . unwrap_or ( error_span) ; 
425-             let  call_name = match  ctor_of { 
426-                 Some ( CtorOf :: Struct )  => "struct" , 
427-                 Some ( CtorOf :: Variant )  => "enum variant" , 
428-                 None  => "function" , 
429-             } ; 
430- 
431399            let  compatibility_diagonal = IndexVec :: from_raw ( compatibility_diagonal) ; 
432400            let  provided_args = IndexVec :: from_iter ( provided_args. iter ( ) . take ( if  c_variadic { 
433401                minimum_input_count
@@ -451,13 +419,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
451419                compatibility_diagonal, 
452420                formal_and_expected_inputs, 
453421                provided_args, 
454-                 full_call_span, 
455-                 error_span, 
456-                 args_span, 
457-                 call_name, 
458422                c_variadic, 
459423                err_code, 
460424                fn_def_id, 
425+                 call_span, 
426+                 call_expr, 
461427            ) ; 
462428        } 
463429    } 
@@ -467,14 +433,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
467433        compatibility_diagonal :  IndexVec < ProvidedIdx ,  Compatibility < ' tcx > > , 
468434        formal_and_expected_inputs :  IndexVec < ExpectedIdx ,  ( Ty < ' tcx > ,  Ty < ' tcx > ) > , 
469435        provided_args :  IndexVec < ProvidedIdx ,  & ' tcx  hir:: Expr < ' tcx > > , 
470-         full_call_span :  Span , 
471-         error_span :  Span , 
472-         args_span :  Span , 
473-         call_name :  & str , 
474436        c_variadic :  bool , 
475437        err_code :  & str , 
476438        fn_def_id :  Option < DefId > , 
439+         call_span :  Span , 
440+         call_expr :  & hir:: Expr < ' tcx > , 
477441    )  { 
442+         // Next, let's construct the error 
443+         let  ( error_span,  full_call_span,  ctor_of)  = match  & call_expr. kind  { 
444+             hir:: ExprKind :: Call ( 
445+                 hir:: Expr  { 
446+                     span, 
447+                     kind : 
448+                         hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( 
449+                             _, 
450+                             hir:: Path  {  res :  Res :: Def ( DefKind :: Ctor ( of,  _) ,  _) ,  .. } , 
451+                         ) ) , 
452+                     ..
453+                 } , 
454+                 _, 
455+             )  => ( call_span,  * span,  Some ( of) ) , 
456+             hir:: ExprKind :: Call ( hir:: Expr  {  span,  .. } ,  _)  => ( call_span,  * span,  None ) , 
457+             hir:: ExprKind :: MethodCall ( path_segment,  _,  span)  => { 
458+                 let  ident_span = path_segment. ident . span ; 
459+                 let  ident_span = if  let  Some ( args)  = path_segment. args  { 
460+                     ident_span. with_hi ( args. span_ext . hi ( ) ) 
461+                 }  else  { 
462+                     ident_span
463+                 } ; 
464+                 ( 
465+                     * span,  ident_span,  None ,  // methods are never ctors 
466+                 ) 
467+             } 
468+             k => span_bug ! ( call_span,  "checking argument types on a non-call: `{:?}`" ,  k) , 
469+         } ; 
470+         let  args_span = error_span. trim_start ( full_call_span) . unwrap_or ( error_span) ; 
471+         let  call_name = match  ctor_of { 
472+             Some ( CtorOf :: Struct )  => "struct" , 
473+             Some ( CtorOf :: Variant )  => "enum variant" , 
474+             None  => "function" , 
475+         } ; 
476+ 
478477        // Don't print if it has error types or is just plain `_` 
479478        fn  has_error_or_infer < ' tcx > ( tys :  impl  IntoIterator < Item  = Ty < ' tcx > > )  -> bool  { 
480479            tys. into_iter ( ) . any ( |ty| ty. references_error ( )  || ty. is_ty_var ( ) ) 
@@ -495,6 +494,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
495494                ( self . resolve_vars_if_possible ( ty) ,  expr. span ) 
496495            } ) 
497496            . collect ( ) ; 
497+         let  callee_expr = match  & call_expr. peel_blocks ( ) . kind  { 
498+             hir:: ExprKind :: Call ( callee,  _)  => Some ( * callee) , 
499+             hir:: ExprKind :: MethodCall ( _,  callee,  _)  => { 
500+                 if  let  Some ( ( DefKind :: AssocFn ,  def_id) )  =
501+                     self . typeck_results . borrow ( ) . type_dependent_def ( call_expr. hir_id ) 
502+                     && let  Some ( assoc)  = tcx. opt_associated_item ( def_id) 
503+                     && assoc. fn_has_self_parameter 
504+                 { 
505+                     Some ( & callee[ 0 ] ) 
506+                 }  else  { 
507+                     None 
508+                 } 
509+             } 
510+             _ => None , 
511+         } ; 
512+         let  callee_ty = callee_expr
513+             . and_then ( |callee_expr| self . typeck_results . borrow ( ) . expr_ty_adjusted_opt ( callee_expr) ) ; 
498514
499515        // A "softer" version of the `demand_compatible`, which checks types without persisting them, 
500516        // and treats error types differently 
@@ -631,7 +647,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
631647                            Applicability :: MachineApplicable , 
632648                        ) ; 
633649                    } ; 
634-                     label_fn_like ( tcx ,   & mut  err,  fn_def_id) ; 
650+                     self . label_fn_like ( & mut  err,  fn_def_id,  callee_ty ) ; 
635651                    err. emit ( ) ; 
636652                    return ; 
637653                } 
@@ -721,7 +737,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
721737                format ! ( "arguments to this {} are incorrect" ,  call_name) , 
722738            ) ; 
723739            // Call out where the function is defined 
724-             label_fn_like ( tcx ,   & mut  err,  fn_def_id) ; 
740+             self . label_fn_like ( & mut  err,  fn_def_id,  callee_ty ) ; 
725741            err. emit ( ) ; 
726742            return ; 
727743        } 
@@ -1003,7 +1019,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10031019        } 
10041020
10051021        // Call out where the function is defined 
1006-         label_fn_like ( tcx ,   & mut  err,  fn_def_id) ; 
1022+         self . label_fn_like ( & mut  err,  fn_def_id,  callee_ty ) ; 
10071023
10081024        // And add a suggestion block for all of the parameters 
10091025        let  suggestion_text = match  suggestion_text { 
@@ -1795,47 +1811,126 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17951811            } 
17961812        } 
17971813    } 
1798- } 
17991814
1800- fn  label_fn_like < ' tcx > ( 
1801-     tcx :  TyCtxt < ' tcx > , 
1802-     err :  & mut  rustc_errors:: DiagnosticBuilder < ' tcx ,  rustc_errors:: ErrorGuaranteed > , 
1803-     def_id :  Option < DefId > , 
1804- )  { 
1805-     let  Some ( def_id)  = def_id else  { 
1806-         return ; 
1807-     } ; 
1808- 
1809-     if  let  Some ( def_span)  = tcx. def_ident_span ( def_id)  { 
1810-         let  mut  spans:  MultiSpan  = def_span. into ( ) ; 
1811- 
1812-         let  params = tcx
1813-             . hir ( ) 
1814-             . get_if_local ( def_id) 
1815-             . and_then ( |node| node. body_id ( ) ) 
1816-             . into_iter ( ) 
1817-             . flat_map ( |id| tcx. hir ( ) . body ( id) . params ) ; 
1818- 
1819-         for  param in  params { 
1820-             spans. push_span_label ( param. span ,  "" ) ; 
1815+     fn  label_fn_like ( 
1816+         & self , 
1817+         err :  & mut  rustc_errors:: DiagnosticBuilder < ' tcx ,  rustc_errors:: ErrorGuaranteed > , 
1818+         callable_def_id :  Option < DefId > , 
1819+         callee_ty :  Option < Ty < ' tcx > > , 
1820+     )  { 
1821+         let  Some ( mut  def_id)  = callable_def_id else  { 
1822+             return ; 
1823+         } ; 
1824+ 
1825+         if  let  Some ( assoc_item)  = self . tcx . opt_associated_item ( def_id) 
1826+             // Possibly points at either impl or trait item, so try to get it 
1827+             // to point to trait item, then get the parent. 
1828+             // This parent might be an impl in the case of an inherent function, 
1829+             // but the next check will fail. 
1830+             && let  maybe_trait_item_def_id = assoc_item. trait_item_def_id . unwrap_or ( def_id) 
1831+             && let  maybe_trait_def_id = self . tcx . parent ( maybe_trait_item_def_id) 
1832+             // Just an easy way to check "trait_def_id == Fn/FnMut/FnOnce" 
1833+             && let  Some ( call_kind)  = ty:: ClosureKind :: from_def_id ( self . tcx ,  maybe_trait_def_id) 
1834+             && let  Some ( callee_ty)  = callee_ty
1835+         { 
1836+             let  callee_ty = callee_ty. peel_refs ( ) ; 
1837+             match  * callee_ty. kind ( )  { 
1838+                 ty:: Param ( param)  => { 
1839+                     let  param =
1840+                         self . tcx . generics_of ( self . body_id . owner ) . type_param ( & param,  self . tcx ) ; 
1841+                     if  param. kind . is_synthetic ( )  { 
1842+                         // if it's `impl Fn() -> ..` then just fall down to the def-id based logic 
1843+                         def_id = param. def_id ; 
1844+                     }  else  { 
1845+                         // Otherwise, find the predicate that makes this generic callable, 
1846+                         // and point at that. 
1847+                         let  instantiated = self 
1848+                             . tcx 
1849+                             . explicit_predicates_of ( self . body_id . owner ) 
1850+                             . instantiate_identity ( self . tcx ) ; 
1851+                         // FIXME(compiler-errors): This could be problematic if something has two 
1852+                         // fn-like predicates with different args, but callable types really never 
1853+                         // do that, so it's OK. 
1854+                         for  ( predicate,  span)  in 
1855+                             std:: iter:: zip ( instantiated. predicates ,  instantiated. spans ) 
1856+                         { 
1857+                             if  let  ty:: PredicateKind :: Trait ( pred)  = predicate. kind ( ) . skip_binder ( ) 
1858+                                 && pred. self_ty ( ) . peel_refs ( )  == callee_ty
1859+                                 && ty:: ClosureKind :: from_def_id ( self . tcx ,  pred. def_id ( ) ) . is_some ( ) 
1860+                             { 
1861+                                 err. span_note ( span,  "callable defined here" ) ; 
1862+                                 return ; 
1863+                             } 
1864+                         } 
1865+                     } 
1866+                 } 
1867+                 ty:: Opaque ( new_def_id,  _) 
1868+                 | ty:: Closure ( new_def_id,  _) 
1869+                 | ty:: FnDef ( new_def_id,  _)  => { 
1870+                     def_id = new_def_id; 
1871+                 } 
1872+                 _ => { 
1873+                     // Look for a user-provided impl of a `Fn` trait, and point to it. 
1874+                     let  new_def_id = self . probe ( |_| { 
1875+                         let  trait_ref = ty:: TraitRef :: new ( 
1876+                             call_kind. to_def_id ( self . tcx ) , 
1877+                             self . tcx . mk_substs ( [ 
1878+                                 ty:: GenericArg :: from ( callee_ty) , 
1879+                                 self . next_ty_var ( TypeVariableOrigin  { 
1880+                                     kind :  TypeVariableOriginKind :: MiscVariable , 
1881+                                     span :  rustc_span:: DUMMY_SP , 
1882+                                 } ) 
1883+                                 . into ( ) , 
1884+                             ] . into_iter ( ) ) , 
1885+                         ) ; 
1886+                         let  obligation = traits:: Obligation :: new ( 
1887+                             traits:: ObligationCause :: dummy ( ) , 
1888+                             self . param_env , 
1889+                             ty:: Binder :: dummy ( ty:: TraitPredicate  { 
1890+                                 trait_ref, 
1891+                                 constness :  ty:: BoundConstness :: NotConst , 
1892+                                 polarity :  ty:: ImplPolarity :: Positive , 
1893+                             } ) , 
1894+                         ) ; 
1895+                         match  SelectionContext :: new ( & self ) . select ( & obligation)  { 
1896+                             Ok ( Some ( traits:: ImplSource :: UserDefined ( impl_source) ) )  => { 
1897+                                 Some ( impl_source. impl_def_id ) 
1898+                             } 
1899+                             _ => None 
1900+                         } 
1901+                     } ) ; 
1902+                     if  let  Some ( new_def_id)  = new_def_id { 
1903+                         def_id = new_def_id; 
1904+                     }  else  { 
1905+                         return ; 
1906+                     } 
1907+                 } 
1908+             } 
18211909        } 
18221910
1823-         let  def_kind = tcx. def_kind ( def_id) ; 
1824-         err. span_note ( spans,  & format ! ( "{} defined here" ,  def_kind. descr( def_id) ) ) ; 
1825-     }  else  { 
1826-         match  tcx. hir ( ) . get_if_local ( def_id)  { 
1827-             Some ( hir:: Node :: Expr ( hir:: Expr  { 
1828-                 kind :  hir:: ExprKind :: Closure ( hir:: Closure  {  fn_decl_span,  .. } ) , 
1829-                 ..
1830-             } ) )  => { 
1831-                 let  spans:  MultiSpan  = ( * fn_decl_span) . into ( ) ; 
1911+         if  let  Some ( def_span)  = self . tcx . def_ident_span ( def_id)  && !def_span. is_dummy ( )  { 
1912+             let  mut  spans:  MultiSpan  = def_span. into ( ) ; 
18321913
1833-                 // Note: We don't point to param spans here because they overlap 
1834-                 // with the closure span itself 
1914+             let  params = self 
1915+                 . tcx 
1916+                 . hir ( ) 
1917+                 . get_if_local ( def_id) 
1918+                 . and_then ( |node| node. body_id ( ) ) 
1919+                 . into_iter ( ) 
1920+                 . flat_map ( |id| self . tcx . hir ( ) . body ( id) . params ) ; 
18351921
1836-                 err. span_note ( spans,  "closure defined here" ) ; 
1922+             for  param in  params { 
1923+                 spans. push_span_label ( param. span ,  "" ) ; 
18371924            } 
1838-             _ => { } 
1925+ 
1926+             let  def_kind = self . tcx . def_kind ( def_id) ; 
1927+             err. span_note ( spans,  & format ! ( "{} defined here" ,  def_kind. descr( def_id) ) ) ; 
1928+         }  else  { 
1929+             let  def_kind = self . tcx . def_kind ( def_id) ; 
1930+             err. span_note ( 
1931+                 self . tcx . def_span ( def_id) , 
1932+                 & format ! ( "{} defined here" ,  def_kind. descr( def_id) ) , 
1933+             ) ; 
18391934        } 
18401935    } 
18411936} 
0 commit comments