@@ -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
@@ -479,6 +421,86 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
479
421
480
422
return true ;
481
423
}
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
+ }
482
504
}
483
505
484
506
pub fn compare_const_impl < ' a , ' tcx > ( ccx : & CrateCtxt < ' a , ' tcx > ,
0 commit comments