@@ -3,7 +3,7 @@ use crate::hir::{self, Body, FunctionRetTy, Expr, ExprKind, HirId, Local, Pat};
3
3
use crate :: hir:: intravisit:: { self , Visitor , NestedVisitorMap } ;
4
4
use crate :: infer:: InferCtxt ;
5
5
use crate :: infer:: type_variable:: TypeVariableOriginKind ;
6
- use crate :: ty:: { self , Ty , Infer , TyVar } ;
6
+ use crate :: ty:: { self , Ty , Infer , TyVar , DefIdTree } ;
7
7
use crate :: ty:: print:: Print ;
8
8
use syntax:: source_map:: DesugaringKind ;
9
9
use syntax:: symbol:: kw;
@@ -117,6 +117,8 @@ fn closure_return_type_suggestion(
117
117
descr : & str ,
118
118
name : & str ,
119
119
ret : & str ,
120
+ parent_name : Option < String > ,
121
+ parent_descr : Option < & str > ,
120
122
) {
121
123
let ( arrow, post) = match output {
122
124
FunctionRetTy :: DefaultReturn ( _) => ( "-> " , " " ) ,
@@ -138,7 +140,12 @@ fn closure_return_type_suggestion(
138
140
suggestion,
139
141
Applicability :: HasPlaceholders ,
140
142
) ;
141
- err. span_label ( span, InferCtxt :: missing_type_msg ( & name, & descr) ) ;
143
+ err. span_label ( span, InferCtxt :: missing_type_msg (
144
+ & name,
145
+ & descr,
146
+ parent_name,
147
+ parent_descr
148
+ ) ) ;
142
149
}
143
150
144
151
/// Given a closure signature, return a `String` containing a list of all its argument types.
@@ -177,16 +184,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
177
184
& self ,
178
185
ty : Ty < ' tcx > ,
179
186
highlight : Option < ty:: print:: RegionHighlightMode > ,
180
- ) -> ( String , Option < Span > , Cow < ' static , str > ) {
187
+ ) -> ( String , Option < Span > , Cow < ' static , str > , Option < String > , Option < & ' static str > ) {
181
188
if let ty:: Infer ( ty:: TyVar ( ty_vid) ) = ty. kind {
182
189
let ty_vars = self . type_variables . borrow ( ) ;
183
190
let var_origin = ty_vars. var_origin ( ty_vid) ;
184
- if let TypeVariableOriginKind :: TypeParameterDefinition ( name) = var_origin. kind {
191
+ if let TypeVariableOriginKind :: TypeParameterDefinition ( name, def_id) = var_origin. kind {
192
+ let parent_def_id = def_id. and_then ( |def_id| self . tcx . parent ( def_id) ) ;
193
+ let ( parent_name, parent_desc) = if let Some ( parent_def_id) = parent_def_id {
194
+ let parent_name = self . tcx . def_key ( parent_def_id) . disambiguated_data . data
195
+ . get_opt_name ( ) . map ( |parent_symbol| parent_symbol. to_string ( ) ) ;
196
+
197
+ let type_parent_desc = self . tcx . def_kind ( parent_def_id)
198
+ . map ( |parent_def_kind| parent_def_kind. descr ( parent_def_id) ) ;
199
+
200
+ ( parent_name, type_parent_desc)
201
+ } else {
202
+ ( None , None )
203
+ } ;
204
+
185
205
if name != kw:: SelfUpper {
186
206
return (
187
207
name. to_string ( ) ,
188
208
Some ( var_origin. span ) ,
189
209
"type parameter" . into ( ) ,
210
+ parent_name,
211
+ parent_desc,
190
212
) ;
191
213
}
192
214
}
@@ -198,7 +220,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
198
220
printer. region_highlight_mode = highlight;
199
221
}
200
222
let _ = ty. print ( printer) ;
201
- ( s, None , ty. prefix_string ( ) )
223
+ ( s, None , ty. prefix_string ( ) , None , None )
202
224
}
203
225
204
226
pub fn need_type_info_err (
@@ -209,7 +231,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
209
231
error_code : TypeAnnotationNeeded ,
210
232
) -> DiagnosticBuilder < ' tcx > {
211
233
let ty = self . resolve_vars_if_possible ( & ty) ;
212
- let ( name, name_sp, descr) = self . extract_type_name ( & ty, None ) ;
234
+ let ( name, name_sp, descr, parent_name, parent_descr) = self . extract_type_name ( & ty, None ) ;
235
+
213
236
214
237
let mut local_visitor = FindLocalByTypeVisitor :: new ( & self , ty, & self . tcx . hir ( ) ) ;
215
238
let ty_to_string = |ty : Ty < ' tcx > | -> String {
@@ -218,7 +241,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
218
241
let ty_vars = self . type_variables . borrow ( ) ;
219
242
let getter = move |ty_vid| {
220
243
let var_origin = ty_vars. var_origin ( ty_vid) ;
221
- if let TypeVariableOriginKind :: TypeParameterDefinition ( name) = var_origin. kind {
244
+ if let TypeVariableOriginKind :: TypeParameterDefinition ( name, _ ) = var_origin. kind {
222
245
return Some ( name. to_string ( ) ) ;
223
246
}
224
247
None
@@ -317,6 +340,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
317
340
& descr,
318
341
& name,
319
342
& ret,
343
+ parent_name,
344
+ parent_descr,
320
345
) ;
321
346
// We don't want to give the other suggestions when the problem is the
322
347
// closure return type.
@@ -433,8 +458,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
433
458
if !err. span . span_labels ( ) . iter ( ) . any ( |span_label| {
434
459
span_label. label . is_some ( ) && span_label. span == span
435
460
} ) && local_visitor. found_arg_pattern . is_none ( )
436
- { // Avoid multiple labels pointing at `span`.
437
- err. span_label ( span, InferCtxt :: missing_type_msg ( & name, & descr) ) ;
461
+ {
462
+ // Avoid multiple labels pointing at `span`.
463
+ err. span_label (
464
+ span,
465
+ InferCtxt :: missing_type_msg ( & name, & descr, parent_name, parent_descr)
466
+ ) ;
438
467
}
439
468
440
469
err
@@ -496,19 +525,42 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
496
525
ty : Ty < ' tcx > ,
497
526
) -> DiagnosticBuilder < ' tcx > {
498
527
let ty = self . resolve_vars_if_possible ( & ty) ;
499
- let ( name, _, descr) = self . extract_type_name ( & ty, None ) ;
528
+ let ( name, _, descr, parent_name, parent_descr) = self . extract_type_name ( & ty, None ) ;
529
+
500
530
let mut err = struct_span_err ! (
501
531
self . tcx. sess, span, E0698 , "type inside {} must be known in this context" , kind,
502
532
) ;
503
- err. span_label ( span, InferCtxt :: missing_type_msg ( & name, & descr) ) ;
533
+ err. span_label ( span, InferCtxt :: missing_type_msg (
534
+ & name,
535
+ & descr,
536
+ parent_name,
537
+ parent_descr
538
+ ) ) ;
504
539
err
505
540
}
506
541
507
- fn missing_type_msg ( type_name : & str , descr : & str ) -> Cow < ' static , str > {
542
+ fn missing_type_msg (
543
+ type_name : & str ,
544
+ descr : & str ,
545
+ parent_name : Option < String > ,
546
+ parent_descr : Option < & str > ,
547
+ ) -> Cow < ' static , str > {
508
548
if type_name == "_" {
509
549
"cannot infer type" . into ( )
510
550
} else {
511
- format ! ( "cannot infer type for {} `{}`" , descr, type_name) . into ( )
551
+ let parent_desc = if let Some ( parent_name) = parent_name {
552
+ let parent_type_descr = if let Some ( parent_descr) = parent_descr {
553
+ format ! ( " the {}" , parent_descr)
554
+ } else {
555
+ "" . into ( )
556
+ } ;
557
+
558
+ format ! ( " declared on{} `{}`" , parent_type_descr, parent_name)
559
+ } else {
560
+ "" . to_string ( )
561
+ } ;
562
+
563
+ format ! ( "cannot infer type for {} `{}`{}" , descr, type_name, parent_desc) . into ( )
512
564
}
513
565
}
514
566
}
0 commit comments