@@ -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
@@ -479,6 +421,86 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
479421
480422 return true ;
481423 }
424+
425+ fn extract_spans_for_error_reporting < ' a , ' gcx , ' tcx > ( infcx : & infer:: InferCtxt < ' a , ' gcx , ' tcx > ,
426+ terr : & TypeError ,
427+ origin : TypeOrigin ,
428+ impl_m : & ty:: Method ,
429+ impl_sig : ty:: FnSig < ' tcx > ,
430+ trait_m : & ty:: Method ,
431+ trait_sig : ty:: FnSig < ' tcx > )
432+ -> ( Span , Option < Span > ) {
433+ let tcx = infcx. tcx ;
434+ let impl_m_node_id = tcx. map . as_local_node_id ( impl_m. def_id ) . unwrap ( ) ;
435+ let ( impl_m_output, impl_m_iter) = match tcx. map . expect_impl_item ( impl_m_node_id) . node {
436+ ImplItemKind :: Method ( ref impl_m_sig, _) =>
437+ ( & impl_m_sig. decl . output , impl_m_sig. decl . inputs . iter ( ) ) ,
438+ _ => bug ! ( "{:?} is not a method" , impl_m)
439+ } ;
440+
441+ match * terr {
442+ TypeError :: Mutability => {
443+ if let Some ( trait_m_node_id) = tcx. map . as_local_node_id ( trait_m. def_id ) {
444+ let trait_m_iter = match tcx. map . expect_trait_item ( trait_m_node_id) . node {
445+ TraitItem_ :: MethodTraitItem ( ref trait_m_sig, _) =>
446+ trait_m_sig. decl . inputs . iter ( ) ,
447+ _ => bug ! ( "{:?} is not a MethodTraitItem" , trait_m)
448+ } ;
449+
450+ impl_m_iter. zip ( trait_m_iter) . find ( |& ( ref impl_arg, ref trait_arg) | {
451+ match ( & impl_arg. ty . node , & trait_arg. ty . node ) {
452+ ( & Ty_ :: TyRptr ( _, ref impl_mt) , & Ty_ :: TyRptr ( _, ref trait_mt) ) |
453+ ( & Ty_ :: TyPtr ( ref impl_mt) , & Ty_ :: TyPtr ( ref trait_mt) ) =>
454+ impl_mt. mutbl != trait_mt. mutbl ,
455+ _ => false
456+ }
457+ } ) . map ( |( ref impl_arg, ref trait_arg) | {
458+ match ( impl_arg. to_self ( ) , trait_arg. to_self ( ) ) {
459+ ( Some ( impl_self) , Some ( trait_self) ) =>
460+ ( impl_self. span , Some ( trait_self. span ) ) ,
461+ ( None , None ) => ( impl_arg. ty . span , Some ( trait_arg. ty . span ) ) ,
462+ _ => bug ! ( "impl and trait fns have different first args, \
463+ impl: {:?}, trait: {:?}", impl_arg, trait_arg)
464+ }
465+ } ) . unwrap_or ( ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) ) )
466+ } else {
467+ ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) )
468+ }
469+ }
470+ TypeError :: Sorts ( ExpectedFound { .. } ) => {
471+ if let Some ( trait_m_node_id) = tcx. map . as_local_node_id ( trait_m. def_id ) {
472+ let ( trait_m_output, trait_m_iter) =
473+ match tcx. map . expect_trait_item ( trait_m_node_id) . node {
474+ TraitItem_ :: MethodTraitItem ( ref trait_m_sig, _) =>
475+ ( & trait_m_sig. decl . output , trait_m_sig. decl . inputs . iter ( ) ) ,
476+ _ => bug ! ( "{:?} is not a MethodTraitItem" , trait_m)
477+ } ;
478+
479+ let impl_iter = impl_sig. inputs . iter ( ) ;
480+ let trait_iter = trait_sig. inputs . iter ( ) ;
481+ impl_iter. zip ( trait_iter) . zip ( impl_m_iter) . zip ( trait_m_iter)
482+ . filter_map ( |( ( ( impl_arg_ty, trait_arg_ty) , impl_arg) , trait_arg) | {
483+ match infcx. sub_types ( true , origin, trait_arg_ty, impl_arg_ty) {
484+ Ok ( _) => None ,
485+ Err ( _) => Some ( ( impl_arg. ty . span , Some ( trait_arg. ty . span ) ) )
486+ }
487+ } )
488+ . next ( )
489+ . unwrap_or_else ( || {
490+ if infcx. sub_types ( false , origin, impl_sig. output ,
491+ trait_sig. output ) . is_err ( ) {
492+ ( impl_m_output. span ( ) , Some ( trait_m_output. span ( ) ) )
493+ } else {
494+ ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) )
495+ }
496+ } )
497+ } else {
498+ ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) )
499+ }
500+ }
501+ _ => ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) )
502+ }
503+ }
482504}
483505
484506pub fn compare_const_impl < ' a , ' tcx > ( ccx : & CrateCtxt < ' a , ' tcx > ,
0 commit comments