@@ -16,7 +16,7 @@ use std::fmt::{self, Write};
16
16
impl NiceRegionError < ' me , ' tcx > {
17
17
/// When given a `ConcreteFailure` for a function with arguments containing a named region and
18
18
/// an anonymous region, emit a descriptive diagnostic error.
19
- pub ( super ) fn try_report_placeholder_conflict ( & self ) -> Option < DiagnosticBuilder < ' me > > {
19
+ pub ( super ) fn try_report_placeholder_conflict ( & self ) -> Option < DiagnosticBuilder < ' tcx > > {
20
20
match & self . error {
21
21
///////////////////////////////////////////////////////////////////////////
22
22
// NB. The ordering of cases in this match is very
@@ -30,157 +30,153 @@ impl NiceRegionError<'me, 'tcx> {
30
30
Some ( RegionResolutionError :: SubSupConflict (
31
31
vid,
32
32
_,
33
- SubregionOrigin :: Subtype ( box TypeTrace {
34
- cause,
35
- values : ValuePairs :: TraitRefs ( ExpectedFound { expected, found } ) ,
36
- } ) ,
33
+ SubregionOrigin :: Subtype ( box TypeTrace { cause, values } ) ,
37
34
sub_placeholder @ ty:: RePlaceholder ( _) ,
38
35
_,
39
36
sup_placeholder @ ty:: RePlaceholder ( _) ,
40
- ) ) if expected . def_id == found . def_id => Some ( self . try_report_placeholders_trait (
37
+ ) ) => self . try_report_trait_placeholder_mismatch (
41
38
Some ( self . tcx ( ) . mk_region ( ty:: ReVar ( * vid) ) ) ,
42
39
cause,
43
40
Some ( sub_placeholder) ,
44
41
Some ( sup_placeholder) ,
45
- expected. def_id ,
46
- expected. substs ,
47
- found. substs ,
48
- ) ) ,
42
+ values,
43
+ ) ,
49
44
50
45
Some ( RegionResolutionError :: SubSupConflict (
51
46
vid,
52
47
_,
53
- SubregionOrigin :: Subtype ( box TypeTrace {
54
- cause,
55
- values : ValuePairs :: TraitRefs ( ExpectedFound { expected, found } ) ,
56
- } ) ,
48
+ SubregionOrigin :: Subtype ( box TypeTrace { cause, values } ) ,
57
49
sub_placeholder @ ty:: RePlaceholder ( _) ,
58
50
_,
59
51
_,
60
- ) ) if expected . def_id == found . def_id => Some ( self . try_report_placeholders_trait (
52
+ ) ) => self . try_report_trait_placeholder_mismatch (
61
53
Some ( self . tcx ( ) . mk_region ( ty:: ReVar ( * vid) ) ) ,
62
54
cause,
63
55
Some ( sub_placeholder) ,
64
56
None ,
65
- expected. def_id ,
66
- expected. substs ,
67
- found. substs ,
68
- ) ) ,
57
+ values,
58
+ ) ,
69
59
70
60
Some ( RegionResolutionError :: SubSupConflict (
71
61
vid,
72
62
_,
73
- SubregionOrigin :: Subtype ( box TypeTrace {
74
- cause,
75
- values : ValuePairs :: TraitRefs ( ExpectedFound { expected, found } ) ,
76
- } ) ,
63
+ SubregionOrigin :: Subtype ( box TypeTrace { cause, values } ) ,
77
64
_,
78
65
_,
79
66
sup_placeholder @ ty:: RePlaceholder ( _) ,
80
- ) ) if expected . def_id == found . def_id => Some ( self . try_report_placeholders_trait (
67
+ ) ) => self . try_report_trait_placeholder_mismatch (
81
68
Some ( self . tcx ( ) . mk_region ( ty:: ReVar ( * vid) ) ) ,
82
69
cause,
83
70
None ,
84
71
Some ( * sup_placeholder) ,
85
- expected. def_id ,
86
- expected. substs ,
87
- found. substs ,
88
- ) ) ,
72
+ values,
73
+ ) ,
89
74
90
75
Some ( RegionResolutionError :: SubSupConflict (
91
76
vid,
92
77
_,
93
78
_,
94
79
_,
95
- SubregionOrigin :: Subtype ( box TypeTrace {
96
- cause,
97
- values : ValuePairs :: TraitRefs ( ExpectedFound { expected, found } ) ,
98
- } ) ,
80
+ SubregionOrigin :: Subtype ( box TypeTrace { cause, values } ) ,
99
81
sup_placeholder @ ty:: RePlaceholder ( _) ,
100
- ) ) if expected . def_id == found . def_id => Some ( self . try_report_placeholders_trait (
82
+ ) ) => self . try_report_trait_placeholder_mismatch (
101
83
Some ( self . tcx ( ) . mk_region ( ty:: ReVar ( * vid) ) ) ,
102
84
cause,
103
85
None ,
104
86
Some ( * sup_placeholder) ,
105
- expected. def_id ,
106
- expected. substs ,
107
- found. substs ,
108
- ) ) ,
87
+ values,
88
+ ) ,
109
89
110
90
Some ( RegionResolutionError :: UpperBoundUniverseConflict (
111
91
vid,
112
92
_,
113
93
_,
114
- SubregionOrigin :: Subtype ( box TypeTrace {
115
- cause,
116
- values : ValuePairs :: TraitRefs ( ExpectedFound { expected, found } ) ,
117
- } ) ,
94
+ SubregionOrigin :: Subtype ( box TypeTrace { cause, values } ) ,
118
95
sup_placeholder @ ty:: RePlaceholder ( _) ,
119
- ) ) if expected . def_id == found . def_id => Some ( self . try_report_placeholders_trait (
96
+ ) ) => self . try_report_trait_placeholder_mismatch (
120
97
Some ( self . tcx ( ) . mk_region ( ty:: ReVar ( * vid) ) ) ,
121
98
cause,
122
99
None ,
123
100
Some ( * sup_placeholder) ,
124
- expected. def_id ,
125
- expected. substs ,
126
- found. substs ,
127
- ) ) ,
101
+ values,
102
+ ) ,
128
103
129
104
Some ( RegionResolutionError :: ConcreteFailure (
130
- SubregionOrigin :: Subtype ( box TypeTrace {
131
- cause,
132
- values : ValuePairs :: TraitRefs ( ExpectedFound { expected, found } ) ,
133
- } ) ,
105
+ SubregionOrigin :: Subtype ( box TypeTrace { cause, values } ) ,
134
106
sub_region @ ty:: RePlaceholder ( _) ,
135
107
sup_region @ ty:: RePlaceholder ( _) ,
136
- ) ) if expected . def_id == found . def_id => Some ( self . try_report_placeholders_trait (
108
+ ) ) => self . try_report_trait_placeholder_mismatch (
137
109
None ,
138
110
cause,
139
111
Some ( * sub_region) ,
140
112
Some ( * sup_region) ,
141
- expected. def_id ,
142
- expected. substs ,
143
- found. substs ,
144
- ) ) ,
113
+ values,
114
+ ) ,
145
115
146
116
Some ( RegionResolutionError :: ConcreteFailure (
147
- SubregionOrigin :: Subtype ( box TypeTrace {
148
- cause,
149
- values : ValuePairs :: TraitRefs ( ExpectedFound { expected, found } ) ,
150
- } ) ,
117
+ SubregionOrigin :: Subtype ( box TypeTrace { cause, values } ) ,
151
118
sub_region @ ty:: RePlaceholder ( _) ,
152
119
sup_region,
153
- ) ) if expected . def_id == found . def_id => Some ( self . try_report_placeholders_trait (
154
- Some ( sup_region) ,
120
+ ) ) => self . try_report_trait_placeholder_mismatch (
121
+ ( !sup_region . has_name ( ) ) . then_some ( sup_region) ,
155
122
cause,
156
- Some ( * sub_region) ,
123
+ Some ( sub_region) ,
157
124
None ,
158
- expected. def_id ,
159
- expected. substs ,
160
- found. substs ,
161
- ) ) ,
125
+ values,
126
+ ) ,
162
127
163
128
Some ( RegionResolutionError :: ConcreteFailure (
164
- SubregionOrigin :: Subtype ( box TypeTrace {
165
- cause,
166
- values : ValuePairs :: TraitRefs ( ExpectedFound { expected, found } ) ,
167
- } ) ,
129
+ SubregionOrigin :: Subtype ( box TypeTrace { cause, values } ) ,
168
130
sub_region,
169
131
sup_region @ ty:: RePlaceholder ( _) ,
170
- ) ) if expected . def_id == found . def_id => Some ( self . try_report_placeholders_trait (
171
- Some ( sub_region) ,
132
+ ) ) => self . try_report_trait_placeholder_mismatch (
133
+ ( !sub_region . has_name ( ) ) . then_some ( sub_region) ,
172
134
cause,
173
135
None ,
174
- Some ( * sup_region) ,
175
- expected. def_id ,
176
- expected. substs ,
177
- found. substs ,
178
- ) ) ,
136
+ Some ( sup_region) ,
137
+ values,
138
+ ) ,
179
139
180
140
_ => None ,
181
141
}
182
142
}
183
143
144
+ fn try_report_trait_placeholder_mismatch (
145
+ & self ,
146
+ vid : Option < ty:: Region < ' tcx > > ,
147
+ cause : & ObligationCause < ' tcx > ,
148
+ sub_placeholder : Option < ty:: Region < ' tcx > > ,
149
+ sup_placeholder : Option < ty:: Region < ' tcx > > ,
150
+ value_pairs : & ValuePairs < ' tcx > ,
151
+ ) -> Option < DiagnosticBuilder < ' tcx > > {
152
+ let ( expected_substs, found_substs, trait_def_id) = match value_pairs {
153
+ ValuePairs :: TraitRefs ( ExpectedFound { expected, found } )
154
+ if expected. def_id == found. def_id =>
155
+ {
156
+ ( expected. substs , found. substs , expected. def_id )
157
+ }
158
+ ValuePairs :: PolyTraitRefs ( ExpectedFound { expected, found } )
159
+ if expected. def_id ( ) == found. def_id ( ) =>
160
+ {
161
+ // It's possible that the placeholders come from a binder
162
+ // outside of this value pair. Use `no_bound_vars` as a
163
+ // simple heuristic for that.
164
+ ( expected. no_bound_vars ( ) ?. substs , found. no_bound_vars ( ) ?. substs , expected. def_id ( ) )
165
+ }
166
+ _ => return None ,
167
+ } ;
168
+
169
+ Some ( self . report_trait_placeholder_mismatch (
170
+ vid,
171
+ cause,
172
+ sub_placeholder,
173
+ sup_placeholder,
174
+ trait_def_id,
175
+ expected_substs,
176
+ found_substs,
177
+ ) )
178
+ }
179
+
184
180
// error[E0308]: implementation of `Foo` does not apply to enough lifetimes
185
181
// --> /home/nmatsakis/tmp/foo.rs:12:5
186
182
// |
@@ -190,7 +186,8 @@ impl NiceRegionError<'me, 'tcx> {
190
186
// = note: Due to a where-clause on the function `all`,
191
187
// = note: `T` must implement `...` for any two lifetimes `'1` and `'2`.
192
188
// = note: However, the type `T` only implements `...` for some specific lifetime `'2`.
193
- fn try_report_placeholders_trait (
189
+ #[ instrument( level = "debug" , skip( self ) ) ]
190
+ fn report_trait_placeholder_mismatch (
194
191
& self ,
195
192
vid : Option < ty:: Region < ' tcx > > ,
196
193
cause : & ObligationCause < ' tcx > ,
@@ -199,28 +196,13 @@ impl NiceRegionError<'me, 'tcx> {
199
196
trait_def_id : DefId ,
200
197
expected_substs : SubstsRef < ' tcx > ,
201
198
actual_substs : SubstsRef < ' tcx > ,
202
- ) -> DiagnosticBuilder < ' me > {
203
- debug ! (
204
- "try_report_placeholders_trait(\
205
- vid={:?}, \
206
- sub_placeholder={:?}, \
207
- sup_placeholder={:?}, \
208
- trait_def_id={:?}, \
209
- expected_substs={:?}, \
210
- actual_substs={:?})",
211
- vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs
212
- ) ;
213
-
199
+ ) -> DiagnosticBuilder < ' tcx > {
214
200
let span = cause. span ( self . tcx ( ) ) ;
215
201
let msg = format ! (
216
202
"implementation of `{}` is not general enough" ,
217
203
self . tcx( ) . def_path_str( trait_def_id) ,
218
204
) ;
219
205
let mut err = self . tcx ( ) . sess . struct_span_err ( span, & msg) ;
220
- err. span_label (
221
- self . tcx ( ) . def_span ( trait_def_id) ,
222
- format ! ( "trait `{}` defined here" , self . tcx( ) . def_path_str( trait_def_id) ) ,
223
- ) ;
224
206
225
207
let leading_ellipsis = if let ObligationCauseCode :: ItemObligation ( def_id) = cause. code {
226
208
err. span_label ( span, "doesn't satisfy where-clause" ) ;
@@ -285,17 +267,13 @@ impl NiceRegionError<'me, 'tcx> {
285
267
286
268
let any_self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid;
287
269
288
- debug ! ( "try_report_placeholders_trait: actual_has_vid={:?}" , actual_has_vid) ;
289
- debug ! ( "try_report_placeholders_trait: expected_has_vid={:?}" , expected_has_vid) ;
290
- debug ! ( "try_report_placeholders_trait: has_sub={:?}" , has_sub) ;
291
- debug ! ( "try_report_placeholders_trait: has_sup={:?}" , has_sup) ;
292
270
debug ! (
293
- "try_report_placeholders_trait: actual_self_ty_has_vid={:?}" ,
294
- actual_self_ty_has_vid
295
- ) ;
296
- debug ! (
297
- "try_report_placeholders_trait: expected_self_ty_has_vid={:?}" ,
298
- expected_self_ty_has_vid
271
+ ?actual_has_vid ,
272
+ ?expected_has_vid ,
273
+ ?has_sub ,
274
+ ?has_sup ,
275
+ ?actual_self_ty_has_vid ,
276
+ ? expected_self_ty_has_vid,
299
277
) ;
300
278
301
279
self . explain_actual_impl_that_was_found (
@@ -388,6 +366,8 @@ impl NiceRegionError<'me, 'tcx> {
388
366
value : trait_ref,
389
367
} ;
390
368
369
+ let same_self_type = actual_trait_ref. self_ty ( ) == expected_trait_ref. self_ty ( ) ;
370
+
391
371
let mut expected_trait_ref = highlight_trait_ref ( expected_trait_ref) ;
392
372
expected_trait_ref. highlight . maybe_highlighting_region ( sub_placeholder, has_sub) ;
393
373
expected_trait_ref. highlight . maybe_highlighting_region ( sup_placeholder, has_sup) ;
@@ -403,7 +383,42 @@ impl NiceRegionError<'me, 'tcx> {
403
383
}
404
384
} ;
405
385
406
- let mut note = if passive_voice {
386
+ let mut note = if same_self_type {
387
+ let mut self_ty = expected_trait_ref. map ( |tr| tr. self_ty ( ) ) ;
388
+ self_ty. highlight . maybe_highlighting_region ( vid, actual_has_vid) ;
389
+
390
+ if self_ty. value . is_closure ( )
391
+ && self
392
+ . tcx ( )
393
+ . fn_trait_kind_from_lang_item ( expected_trait_ref. value . def_id )
394
+ . is_some ( )
395
+ {
396
+ let closure_sig = self_ty. map ( |closure| {
397
+ if let ty:: Closure ( _, substs) = closure. kind ( ) {
398
+ self . tcx ( ) . signature_unclosure (
399
+ substs. as_closure ( ) . sig ( ) ,
400
+ rustc_hir:: Unsafety :: Normal ,
401
+ )
402
+ } else {
403
+ bug ! ( "type is not longer closure" ) ;
404
+ }
405
+ } ) ;
406
+
407
+ format ! (
408
+ "{}closure with signature `{}` must implement `{}`" ,
409
+ if leading_ellipsis { "..." } else { "" } ,
410
+ closure_sig,
411
+ expected_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
412
+ )
413
+ } else {
414
+ format ! (
415
+ "{}`{}` must implement `{}`" ,
416
+ if leading_ellipsis { "..." } else { "" } ,
417
+ self_ty,
418
+ expected_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
419
+ )
420
+ }
421
+ } else if passive_voice {
407
422
format ! (
408
423
"{}`{}` would have to be implemented for the type `{}`" ,
409
424
if leading_ellipsis { "..." } else { "" } ,
@@ -449,7 +464,12 @@ impl NiceRegionError<'me, 'tcx> {
449
464
None => true ,
450
465
} ;
451
466
452
- let mut note = if passive_voice {
467
+ let mut note = if same_self_type {
468
+ format ! (
469
+ "...but it actually implements `{}`" ,
470
+ actual_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
471
+ )
472
+ } else if passive_voice {
453
473
format ! (
454
474
"...but `{}` is actually implemented for the type `{}`" ,
455
475
actual_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
0 commit comments