1
1
//! Error Reporting for `impl` items that do not match the obligations from their `trait`.
2
2
3
+ use crate :: hir;
3
4
use crate :: hir:: def_id:: DefId ;
4
5
use crate :: infer:: error_reporting:: nice_region_error:: NiceRegionError ;
5
6
use crate :: infer:: lexical_region_resolve:: RegionResolutionError ;
@@ -40,7 +41,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
40
41
var_origin. span ( ) ,
41
42
sub_expected_found. expected ,
42
43
sub_expected_found. found ,
43
- self . tcx ( ) . def_span ( * trait_item_def_id) ,
44
+ * trait_item_def_id,
44
45
) ;
45
46
return Some ( ErrorReported ) ;
46
47
}
@@ -51,23 +52,56 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
51
52
None
52
53
}
53
54
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) ;
55
58
let mut err = self
56
59
. tcx ( )
57
60
. sess
58
61
. struct_span_err ( sp, "`impl` item signature doesn't match `trait` item signature" ) ;
59
62
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
+ }
61
97
62
98
struct EarlyBoundRegionHighlighter ( FxHashSet < DefId > ) ;
63
99
impl < ' tcx > ty:: fold:: TypeVisitor < ' tcx > for EarlyBoundRegionHighlighter {
64
100
fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> bool {
65
- debug ! ( "LateBoundRegionNameCollector visit_region {:?}" , r) ;
66
101
match * r {
67
102
ty:: ReFree ( free) => {
68
103
self . 0 . insert ( free. scope ) ;
69
104
}
70
-
71
105
ty:: ReEarlyBound ( bound) => {
72
106
self . 0 . insert ( bound. def_id ) ;
73
107
}
@@ -94,12 +128,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
94
128
}
95
129
if note {
96
130
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`" ,
99
132
) ;
100
133
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",
103
136
) ;
104
137
}
105
138
err. emit ( ) ;
0 commit comments