@@ -63,78 +63,56 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
63
63
err. span_label ( trait_sp, & format ! ( "expected {:?}" , expected) ) ;
64
64
let trait_fn_sig = tcx. fn_sig ( trait_def_id) ;
65
65
66
+ // Check the `trait`'s method's output to look for type parameters that might have
67
+ // unconstrained lifetimes. If the method returns a type parameter and the `impl` has a
68
+ // borrow as the type parameter being implemented, the lifetimes will not match because
69
+ // a new lifetime is being introduced in the `impl` that is not present in the `trait`.
70
+ // Because this is confusing as hell the first time you see it, we give a short message
71
+ // explaining the situation and proposing constraining the type param with a named lifetime
72
+ // so that the `impl` will have one to tie them together.
66
73
struct AssocTypeFinder ( FxHashSet < ty:: ParamTy > ) ;
67
74
impl < ' tcx > ty:: fold:: TypeVisitor < ' tcx > for AssocTypeFinder {
68
75
fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> bool {
69
76
debug ! ( "assoc type finder ty {:?} {:?}" , ty, ty. kind) ;
70
- match ty. kind {
71
- ty:: Param ( param) => {
72
- self . 0 . insert ( param) ;
73
- }
74
- _ => { }
77
+ if let ty:: Param ( param) = ty. kind {
78
+ self . 0 . insert ( param) ;
75
79
}
76
80
ty. super_visit_with ( self )
77
81
}
78
82
}
79
83
let mut visitor = AssocTypeFinder ( FxHashSet :: default ( ) ) ;
80
84
trait_fn_sig. output ( ) . visit_with ( & mut visitor) ;
81
-
82
85
if let Some ( id) = tcx. hir ( ) . as_local_hir_id ( trait_def_id) {
83
86
let parent_id = tcx. hir ( ) . get_parent_item ( id) ;
84
87
let trait_item = tcx. hir ( ) . expect_item ( parent_id) ;
85
88
if let hir:: ItemKind :: Trait ( _, _, generics, _, _) = & trait_item. kind {
86
89
for param_ty in visitor. 0 {
87
90
if let Some ( generic) = generics. get_named ( param_ty. name ) {
88
91
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`",
92
+ "for `impl` items to implement the method, this type parameter might \
93
+ need a lifetime restriction like `{}: 'a`",
91
94
param_ty. name,
92
95
) ) ;
93
96
}
94
97
}
95
98
}
96
99
}
97
100
98
- struct EarlyBoundRegionHighlighter ( FxHashSet < DefId > ) ;
99
- impl < ' tcx > ty:: fold:: TypeVisitor < ' tcx > for EarlyBoundRegionHighlighter {
100
- fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> bool {
101
- match * r {
102
- ty:: ReFree ( free) => {
103
- self . 0 . insert ( free. scope ) ;
104
- }
105
- ty:: ReEarlyBound ( bound) => {
106
- self . 0 . insert ( bound. def_id ) ;
107
- }
108
- _ => { }
109
- }
110
- r. super_visit_with ( self )
111
- }
112
- }
113
-
114
- let mut visitor = EarlyBoundRegionHighlighter ( FxHashSet :: default ( ) ) ;
115
- expected. visit_with ( & mut visitor) ;
116
-
117
- let note = !visitor. 0 . is_empty ( ) ;
118
-
119
- if let Some ( ( expected, found) ) = self
120
- . tcx ( )
101
+ if let Some ( ( expected, found) ) = tcx
121
102
. infer_ctxt ( )
122
103
. enter ( |infcx| infcx. expected_found_str_ty ( & ExpectedFound { expected, found } ) )
123
104
{
105
+ // Highlighted the differences when showing the "expected/found" note.
124
106
err. note_expected_found ( & "" , expected, & "" , found) ;
125
107
} else {
126
108
// This fallback shouldn't be necessary, but let's keep it in just in case.
127
109
err. note ( & format ! ( "expected `{:?}`\n found `{:?}`" , expected, found) ) ;
128
110
}
129
- if note {
130
- err. note (
131
- "the lifetime requirements from the `trait` could not be fulfilled by the `impl`" ,
132
- ) ;
133
- err. help (
134
- "verify the lifetime relationships in the `trait` and `impl` between the \
135
- `self` argument, the other inputs and its output",
136
- ) ;
137
- }
111
+ err. note ( "the lifetime requirements from the `trait` could not be satisfied by the `impl`" ) ;
112
+ err. help (
113
+ "verify the lifetime relationships in the `trait` and `impl` between the `self` \
114
+ argument, the other inputs and its output",
115
+ ) ;
138
116
err. emit ( ) ;
139
117
}
140
118
}
0 commit comments