@@ -299,11 +299,10 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
299299 impl_m_span,
300300 impl_m_body_id,
301301 & impl_sig) ;
302- let impl_args = impl_sig. inputs . clone ( ) ;
303302 let impl_fty = tcx. mk_fn_ptr ( tcx. mk_bare_fn ( ty:: BareFnTy {
304303 unsafety : impl_m. fty . unsafety ,
305304 abi : impl_m. fty . abi ,
306- sig : ty:: Binder ( impl_sig)
305+ sig : ty:: Binder ( impl_sig. clone ( ) )
307306 } ) ) ;
308307 debug ! ( "compare_impl_method: impl_fty={:?}" , impl_fty) ;
309308
@@ -318,11 +317,10 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
318317 impl_m_span,
319318 impl_m_body_id,
320319 & trait_sig) ;
321- let trait_args = trait_sig. inputs . clone ( ) ;
322320 let trait_fty = tcx. mk_fn_ptr ( tcx. mk_bare_fn ( ty:: BareFnTy {
323321 unsafety : trait_m. fty . unsafety ,
324322 abi : trait_m. fty . abi ,
325- sig : ty:: Binder ( trait_sig)
323+ sig : ty:: Binder ( trait_sig. clone ( ) )
326324 } ) ) ;
327325
328326 debug ! ( "compare_impl_method: trait_fty={:?}" , trait_fty) ;
@@ -332,65 +330,9 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
332330 impl_fty,
333331 trait_fty) ;
334332
335- let impl_m_iter = match tcx. map . expect_impl_item ( impl_m_node_id) . node {
336- ImplItemKind :: Method ( ref impl_m_sig, _) => impl_m_sig. decl . inputs . iter ( ) ,
337- _ => bug ! ( "{:?} is not a method" , impl_m)
338- } ;
339-
340- let ( impl_err_span, trait_err_span) = match terr {
341- TypeError :: Mutability => {
342- if let Some ( trait_m_node_id) = tcx. map . as_local_node_id ( trait_m. def_id ) {
343- let trait_m_iter = match tcx. map . expect_trait_item ( trait_m_node_id) . node {
344- TraitItem_ :: MethodTraitItem ( ref trait_m_sig, _) =>
345- trait_m_sig. decl . inputs . iter ( ) ,
346- _ => bug ! ( "{:?} is not a MethodTraitItem" , trait_m)
347- } ;
348-
349- impl_m_iter. zip ( trait_m_iter) . find ( |& ( ref impl_arg, ref trait_arg) | {
350- match ( & impl_arg. ty . node , & trait_arg. ty . node ) {
351- ( & Ty_ :: TyRptr ( _, ref impl_mt) , & Ty_ :: TyRptr ( _, ref trait_mt) ) |
352- ( & Ty_ :: TyPtr ( ref impl_mt) , & Ty_ :: TyPtr ( ref trait_mt) ) =>
353- impl_mt. mutbl != trait_mt. mutbl ,
354- _ => false
355- }
356- } ) . map ( |( ref impl_arg, ref trait_arg) | {
357- match ( impl_arg. to_self ( ) , trait_arg. to_self ( ) ) {
358- ( Some ( impl_self) , Some ( trait_self) ) =>
359- ( impl_self. span , Some ( trait_self. span ) ) ,
360- ( None , None ) => ( impl_arg. ty . span , Some ( trait_arg. ty . span ) ) ,
361- _ => bug ! ( "impl and trait fns have different first args, \
362- impl: {:?}, trait: {:?}", impl_arg, trait_arg)
363- }
364- } ) . unwrap_or ( ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) ) )
365- } else {
366- ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) )
367- }
368- }
369- TypeError :: Sorts ( ExpectedFound { expected, found } ) => {
370- if let Some ( trait_m_node_id) = tcx. map . as_local_node_id ( trait_m. def_id ) {
371- let trait_m_iter = match tcx. map . expect_trait_item ( trait_m_node_id) . node {
372- TraitItem_ :: MethodTraitItem ( ref trait_m_sig, _) =>
373- trait_m_sig. decl . inputs . iter ( ) ,
374- _ => bug ! ( "{:?} is not a MethodTraitItem" , trait_m)
375- } ;
376- let impl_iter = impl_args. iter ( ) ;
377- let trait_iter = trait_args. iter ( ) ;
378- let arg_idx = impl_iter. zip ( trait_iter)
379- . position ( |( impl_arg_ty, trait_arg_ty) | {
380- * impl_arg_ty == found && * trait_arg_ty == expected
381- } ) . unwrap ( ) ;
382- impl_m_iter. zip ( trait_m_iter)
383- . nth ( arg_idx)
384- . map ( |( impl_arg, trait_arg) |
385- ( impl_arg. ty . span , Some ( trait_arg. ty . span ) ) )
386- . unwrap_or (
387- ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) ) )
388- } else {
389- ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) )
390- }
391- }
392- _ => ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) )
393- } ;
333+ let ( impl_err_span, trait_err_span) =
334+ extract_spans_for_error_reporting ( & infcx, & terr, origin, impl_m,
335+ impl_sig, trait_m, trait_sig) ;
394336
395337 let origin = TypeOrigin :: MethodCompatCheck ( impl_err_span) ;
396338
@@ -478,6 +420,86 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
478420
479421 return true ;
480422 }
423+
424+ fn extract_spans_for_error_reporting < ' a , ' gcx , ' tcx > ( infcx : & infer:: InferCtxt < ' a , ' gcx , ' tcx > ,
425+ terr : & TypeError ,
426+ origin : TypeOrigin ,
427+ impl_m : & ty:: Method ,
428+ impl_sig : ty:: FnSig < ' tcx > ,
429+ trait_m : & ty:: Method ,
430+ trait_sig : ty:: FnSig < ' tcx > )
431+ -> ( Span , Option < Span > ) {
432+ let tcx = infcx. tcx ;
433+ let impl_m_node_id = tcx. map . as_local_node_id ( impl_m. def_id ) . unwrap ( ) ;
434+ let ( impl_m_output, impl_m_iter) = match tcx. map . expect_impl_item ( impl_m_node_id) . node {
435+ ImplItemKind :: Method ( ref impl_m_sig, _) =>
436+ ( & impl_m_sig. decl . output , impl_m_sig. decl . inputs . iter ( ) ) ,
437+ _ => bug ! ( "{:?} is not a method" , impl_m)
438+ } ;
439+
440+ match * terr {
441+ TypeError :: Mutability => {
442+ if let Some ( trait_m_node_id) = tcx. map . as_local_node_id ( trait_m. def_id ) {
443+ let trait_m_iter = match tcx. map . expect_trait_item ( trait_m_node_id) . node {
444+ TraitItem_ :: MethodTraitItem ( ref trait_m_sig, _) =>
445+ trait_m_sig. decl . inputs . iter ( ) ,
446+ _ => bug ! ( "{:?} is not a MethodTraitItem" , trait_m)
447+ } ;
448+
449+ impl_m_iter. zip ( trait_m_iter) . find ( |& ( ref impl_arg, ref trait_arg) | {
450+ match ( & impl_arg. ty . node , & trait_arg. ty . node ) {
451+ ( & Ty_ :: TyRptr ( _, ref impl_mt) , & Ty_ :: TyRptr ( _, ref trait_mt) ) |
452+ ( & Ty_ :: TyPtr ( ref impl_mt) , & Ty_ :: TyPtr ( ref trait_mt) ) =>
453+ impl_mt. mutbl != trait_mt. mutbl ,
454+ _ => false
455+ }
456+ } ) . map ( |( ref impl_arg, ref trait_arg) | {
457+ match ( impl_arg. to_self ( ) , trait_arg. to_self ( ) ) {
458+ ( Some ( impl_self) , Some ( trait_self) ) =>
459+ ( impl_self. span , Some ( trait_self. span ) ) ,
460+ ( None , None ) => ( impl_arg. ty . span , Some ( trait_arg. ty . span ) ) ,
461+ _ => bug ! ( "impl and trait fns have different first args, \
462+ impl: {:?}, trait: {:?}", impl_arg, trait_arg)
463+ }
464+ } ) . unwrap_or ( ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) ) )
465+ } else {
466+ ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) )
467+ }
468+ }
469+ TypeError :: Sorts ( ExpectedFound { .. } ) => {
470+ if let Some ( trait_m_node_id) = tcx. map . as_local_node_id ( trait_m. def_id ) {
471+ let ( trait_m_output, trait_m_iter) =
472+ match tcx. map . expect_trait_item ( trait_m_node_id) . node {
473+ TraitItem_ :: MethodTraitItem ( ref trait_m_sig, _) =>
474+ ( & trait_m_sig. decl . output , trait_m_sig. decl . inputs . iter ( ) ) ,
475+ _ => bug ! ( "{:?} is not a MethodTraitItem" , trait_m)
476+ } ;
477+
478+ let impl_iter = impl_sig. inputs . iter ( ) ;
479+ let trait_iter = trait_sig. inputs . iter ( ) ;
480+ impl_iter. zip ( trait_iter) . zip ( impl_m_iter) . zip ( trait_m_iter)
481+ . filter_map ( |( ( ( impl_arg_ty, trait_arg_ty) , impl_arg) , trait_arg) | {
482+ match infcx. sub_types ( true , origin, trait_arg_ty, impl_arg_ty) {
483+ Ok ( _) => None ,
484+ Err ( _) => Some ( ( impl_arg. ty . span , Some ( trait_arg. ty . span ) ) )
485+ }
486+ } )
487+ . next ( )
488+ . unwrap_or_else ( || {
489+ if infcx. sub_types ( false , origin, impl_sig. output ,
490+ trait_sig. output ) . is_err ( ) {
491+ ( impl_m_output. span ( ) , Some ( trait_m_output. span ( ) ) )
492+ } else {
493+ ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) )
494+ }
495+ } )
496+ } else {
497+ ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) )
498+ }
499+ }
500+ _ => ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) )
501+ }
502+ }
481503}
482504
483505pub fn compare_const_impl < ' a , ' tcx > ( ccx : & CrateCtxt < ' a , ' tcx > ,
0 commit comments