@@ -299,11 +299,10 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
299
299
impl_m_span,
300
300
impl_m_body_id,
301
301
& impl_sig) ;
302
- let impl_args = impl_sig. inputs . clone ( ) ;
303
302
let impl_fty = tcx. mk_fn_ptr ( tcx. mk_bare_fn ( ty:: BareFnTy {
304
303
unsafety : impl_m. fty . unsafety ,
305
304
abi : impl_m. fty . abi ,
306
- sig : ty:: Binder ( impl_sig)
305
+ sig : ty:: Binder ( impl_sig. clone ( ) )
307
306
} ) ) ;
308
307
debug ! ( "compare_impl_method: impl_fty={:?}" , impl_fty) ;
309
308
@@ -318,11 +317,10 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
318
317
impl_m_span,
319
318
impl_m_body_id,
320
319
& trait_sig) ;
321
- let trait_args = trait_sig. inputs . clone ( ) ;
322
320
let trait_fty = tcx. mk_fn_ptr ( tcx. mk_bare_fn ( ty:: BareFnTy {
323
321
unsafety : trait_m. fty . unsafety ,
324
322
abi : trait_m. fty . abi ,
325
- sig : ty:: Binder ( trait_sig)
323
+ sig : ty:: Binder ( trait_sig. clone ( ) )
326
324
} ) ) ;
327
325
328
326
debug ! ( "compare_impl_method: trait_fty={:?}" , trait_fty) ;
@@ -332,65 +330,9 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
332
330
impl_fty,
333
331
trait_fty) ;
334
332
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) ;
394
336
395
337
let origin = TypeOrigin :: MethodCompatCheck ( impl_err_span) ;
396
338
@@ -478,6 +420,86 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
478
420
479
421
return true ;
480
422
}
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
+ }
481
503
}
482
504
483
505
pub fn compare_const_impl < ' a , ' tcx > ( ccx : & CrateCtxt < ' a , ' tcx > ,
0 commit comments