@@ -12,10 +12,9 @@ use middle::free_region::FreeRegionMap;
12
12
use rustc:: infer:: { self , InferOk , TypeOrigin } ;
13
13
use rustc:: ty;
14
14
use rustc:: traits:: { self , Reveal } ;
15
- use rustc:: ty:: error:: ExpectedFound ;
15
+ use rustc:: ty:: error:: { ExpectedFound , TypeError } ;
16
16
use rustc:: ty:: subst:: { Subst , Substs } ;
17
- use rustc:: hir:: map:: Node ;
18
- use rustc:: hir:: { ImplItemKind , TraitItem_ } ;
17
+ use rustc:: hir:: { ImplItemKind , TraitItem_ , Ty_ } ;
19
18
20
19
use syntax:: ast;
21
20
use syntax_pos:: Span ;
@@ -300,6 +299,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
300
299
impl_m_span,
301
300
impl_m_body_id,
302
301
& impl_sig) ;
302
+ let impl_args = impl_sig. inputs . clone ( ) ;
303
303
let impl_fty = tcx. mk_fn_ptr ( tcx. mk_bare_fn ( ty:: BareFnTy {
304
304
unsafety : impl_m. fty . unsafety ,
305
305
abi : impl_m. fty . abi ,
@@ -318,6 +318,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
318
318
impl_m_span,
319
319
impl_m_body_id,
320
320
& trait_sig) ;
321
+ let trait_args = trait_sig. inputs . clone ( ) ;
321
322
let trait_fty = tcx. mk_fn_ptr ( tcx. mk_bare_fn ( ty:: BareFnTy {
322
323
unsafety : trait_m. fty . unsafety ,
323
324
abi : trait_m. fty . abi ,
@@ -331,16 +332,54 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
331
332
impl_fty,
332
333
trait_fty) ;
333
334
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 :: Sorts ( ExpectedFound { expected, found } ) => {
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
+ let impl_iter = impl_args. iter ( ) ;
349
+ let trait_iter = trait_args. iter ( ) ;
350
+ let arg_idx = impl_iter. zip ( trait_iter)
351
+ . position ( |( impl_arg_ty, trait_arg_ty) | {
352
+ * impl_arg_ty == found && * trait_arg_ty == expected
353
+ } ) . unwrap ( ) ;
354
+ impl_m_iter. zip ( trait_m_iter)
355
+ . nth ( arg_idx)
356
+ . map ( |( impl_arg, trait_arg) |
357
+ ( impl_arg. ty . span , Some ( trait_arg. ty . span ) ) )
358
+ . unwrap_or (
359
+ ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) ) )
360
+ } else {
361
+ ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) )
362
+ }
363
+ }
364
+ _ => ( origin. span ( ) , tcx. map . span_if_local ( trait_m. def_id ) )
365
+ } ;
366
+
367
+ let origin = TypeOrigin :: MethodCompatCheck ( impl_err_span) ;
368
+
334
369
let mut diag = struct_span_err ! (
335
370
tcx. sess, origin. span( ) , E0053 ,
336
371
"method `{}` has an incompatible type for trait" , trait_m. name
337
372
) ;
373
+
338
374
infcx. note_type_err (
339
- & mut diag, origin,
375
+ & mut diag,
376
+ origin,
377
+ trait_err_span. map ( |sp| ( sp, format ! ( "original trait requirement" ) ) ) ,
340
378
Some ( infer:: ValuePairs :: Types ( ExpectedFound {
341
- expected : trait_fty,
342
- found : impl_fty
343
- } ) ) , & terr
379
+ expected : trait_fty,
380
+ found : impl_fty
381
+ } ) ) ,
382
+ & terr
344
383
) ;
345
384
diag. emit ( ) ;
346
385
return
@@ -487,12 +526,9 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
487
526
trait_ty) ;
488
527
489
528
// Locate the Span containing just the type of the offending impl
490
- if let Some ( impl_trait_node) = tcx. map . get_if_local ( impl_c. def_id ) {
491
- if let Node :: NodeImplItem ( impl_trait_item) = impl_trait_node {
492
- if let ImplItemKind :: Const ( ref ty, _) = impl_trait_item. node {
493
- origin = TypeOrigin :: Misc ( ty. span ) ;
494
- }
495
- }
529
+ match tcx. map . expect_impl_item ( impl_c_node_id) . node {
530
+ ImplItemKind :: Const ( ref ty, _) => origin = TypeOrigin :: Misc ( ty. span ) ,
531
+ _ => bug ! ( "{:?} is not a impl const" , impl_c)
496
532
}
497
533
498
534
let mut diag = struct_span_err ! (
@@ -502,16 +538,16 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
502
538
) ;
503
539
504
540
// Add a label to the Span containing just the type of the item
505
- if let Some ( orig_trait_node) = tcx. map . get_if_local ( trait_c. def_id ) {
506
- if let Node :: NodeTraitItem ( orig_trait_item) = orig_trait_node {
507
- if let TraitItem_ :: ConstTraitItem ( ref ty, _) = orig_trait_item. node {
508
- diag. span_label ( ty. span , & format ! ( "original trait requirement" ) ) ;
509
- }
510
- }
511
- }
541
+ let trait_c_node_id = tcx. map . as_local_node_id ( trait_c. def_id ) . unwrap ( ) ;
542
+ let trait_c_span = match tcx. map . expect_trait_item ( trait_c_node_id) . node {
543
+ TraitItem_ :: ConstTraitItem ( ref ty, _) => ty. span ,
544
+ _ => bug ! ( "{:?} is not a trait const" , trait_c)
545
+ } ;
512
546
513
547
infcx. note_type_err (
514
- & mut diag, origin,
548
+ & mut diag,
549
+ origin,
550
+ Some ( ( trait_c_span, format ! ( "original trait requirement" ) ) ) ,
515
551
Some ( infer:: ValuePairs :: Types ( ExpectedFound {
516
552
expected : trait_ty,
517
553
found : impl_ty
0 commit comments