11//! Error Reporting for `impl` items that do not match the obligations from their `trait`.
22
3+ use crate :: hir;
34use crate :: hir:: def_id:: DefId ;
45use crate :: infer:: error_reporting:: nice_region_error:: NiceRegionError ;
56use crate :: infer:: lexical_region_resolve:: RegionResolutionError ;
@@ -40,7 +41,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
4041 var_origin. span ( ) ,
4142 sub_expected_found. expected ,
4243 sub_expected_found. found ,
43- self . tcx ( ) . def_span ( * trait_item_def_id) ,
44+ * trait_item_def_id,
4445 ) ;
4546 return Some ( ErrorReported ) ;
4647 }
@@ -51,23 +52,56 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
5152 None
5253 }
5354
54- fn emit_err ( & self , sp : Span , expected : Ty < ' tcx > , found : Ty < ' tcx > , impl_sp : Span ) {
55+ fn emit_err ( & self , sp : Span , expected : Ty < ' tcx > , found : Ty < ' tcx > , trait_def_id : DefId ) {
56+ let tcx = self . tcx ( ) ;
57+ let trait_sp = self . tcx ( ) . def_span ( trait_def_id) ;
5558 let mut err = self
5659 . tcx ( )
5760 . sess
5861 . struct_span_err ( sp, "`impl` item signature doesn't match `trait` item signature" ) ;
5962 err. span_label ( sp, & format ! ( "found {:?}" , found) ) ;
60- err. span_label ( impl_sp, & format ! ( "expected {:?}" , expected) ) ;
63+ err. span_label ( trait_sp, & format ! ( "expected {:?}" , expected) ) ;
64+ let trait_fn_sig = tcx. fn_sig ( trait_def_id) ;
65+
66+ struct AssocTypeFinder ( FxHashSet < ty:: ParamTy > ) ;
67+ impl < ' tcx > ty:: fold:: TypeVisitor < ' tcx > for AssocTypeFinder {
68+ fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> bool {
69+ debug ! ( "assoc type finder ty {:?} {:?}" , ty, ty. kind) ;
70+ match ty. kind {
71+ ty:: Param ( param) => {
72+ self . 0 . insert ( param) ;
73+ }
74+ _ => { }
75+ }
76+ ty. super_visit_with ( self )
77+ }
78+ }
79+ let mut visitor = AssocTypeFinder ( FxHashSet :: default ( ) ) ;
80+ trait_fn_sig. output ( ) . visit_with ( & mut visitor) ;
81+
82+ if let Some ( id) = tcx. hir ( ) . as_local_hir_id ( trait_def_id) {
83+ let parent_id = tcx. hir ( ) . get_parent_item ( id) ;
84+ let trait_item = tcx. hir ( ) . expect_item ( parent_id) ;
85+ if let hir:: ItemKind :: Trait ( _, _, generics, _, _) = & trait_item. kind {
86+ for param_ty in visitor. 0 {
87+ if let Some ( generic) = generics. get_named ( param_ty. name ) {
88+ err. span_label ( generic. span , & format ! (
89+ "in order for `impl` items to be able to implement the method, this \
90+ type parameter might need a lifetime restriction like `{}: 'a`",
91+ param_ty. name,
92+ ) ) ;
93+ }
94+ }
95+ }
96+ }
6197
6298 struct EarlyBoundRegionHighlighter ( FxHashSet < DefId > ) ;
6399 impl < ' tcx > ty:: fold:: TypeVisitor < ' tcx > for EarlyBoundRegionHighlighter {
64100 fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> bool {
65- debug ! ( "LateBoundRegionNameCollector visit_region {:?}" , r) ;
66101 match * r {
67102 ty:: ReFree ( free) => {
68103 self . 0 . insert ( free. scope ) ;
69104 }
70-
71105 ty:: ReEarlyBound ( bound) => {
72106 self . 0 . insert ( bound. def_id ) ;
73107 }
@@ -94,12 +128,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
94128 }
95129 if note {
96130 err. note (
97- "the lifetime requirements from the `trait` could not be fulfilled by the \
98- `impl`",
131+ "the lifetime requirements from the `trait` could not be fulfilled by the `impl`" ,
99132 ) ;
100133 err. help (
101- "consider adding a named lifetime to the `trait` that constrains the item's \
102- `self` argument, its inputs and its output with it ",
134+ "verify the lifetime relationships in the `trait` and `impl` between the \
135+ `self` argument, the other inputs and its output",
103136 ) ;
104137 }
105138 err. emit ( ) ;
0 commit comments