@@ -3,7 +3,7 @@ use crate::hir::{self, Body, FunctionRetTy, Expr, ExprKind, HirId, Local, Pat};
33use crate :: hir:: intravisit:: { self , Visitor , NestedVisitorMap } ;
44use crate :: infer:: InferCtxt ;
55use crate :: infer:: type_variable:: TypeVariableOriginKind ;
6- use crate :: ty:: { self , Ty , Infer , TyVar } ;
6+ use crate :: ty:: { self , Ty , Infer , TyVar , DefIdTree } ;
77use crate :: ty:: print:: Print ;
88use syntax:: source_map:: DesugaringKind ;
99use syntax:: symbol:: kw;
@@ -117,6 +117,8 @@ fn closure_return_type_suggestion(
117117 descr : & str ,
118118 name : & str ,
119119 ret : & str ,
120+ parent_name : Option < String > ,
121+ parent_descr : Option < & str > ,
120122) {
121123 let ( arrow, post) = match output {
122124 FunctionRetTy :: DefaultReturn ( _) => ( "-> " , " " ) ,
@@ -138,7 +140,12 @@ fn closure_return_type_suggestion(
138140 suggestion,
139141 Applicability :: HasPlaceholders ,
140142 ) ;
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+ ) ) ;
142149}
143150
144151/// 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> {
177184 & self ,
178185 ty : Ty < ' tcx > ,
179186 highlight : Option < ty:: print:: RegionHighlightMode > ,
180- ) -> ( String , Option < Span > , Cow < ' static , str > ) {
187+ ) -> ( String , Option < Span > , Cow < ' static , str > , Option < String > , Option < & ' static str > ) {
181188 if let ty:: Infer ( ty:: TyVar ( ty_vid) ) = ty. kind {
182189 let ty_vars = self . type_variables . borrow ( ) ;
183190 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+
185205 if name != kw:: SelfUpper {
186206 return (
187207 name. to_string ( ) ,
188208 Some ( var_origin. span ) ,
189209 "type parameter" . into ( ) ,
210+ parent_name,
211+ parent_desc,
190212 ) ;
191213 }
192214 }
@@ -198,7 +220,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
198220 printer. region_highlight_mode = highlight;
199221 }
200222 let _ = ty. print ( printer) ;
201- ( s, None , ty. prefix_string ( ) )
223+ ( s, None , ty. prefix_string ( ) , None , None )
202224 }
203225
204226 pub fn need_type_info_err (
@@ -209,7 +231,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
209231 error_code : TypeAnnotationNeeded ,
210232 ) -> DiagnosticBuilder < ' tcx > {
211233 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+
213236
214237 let mut local_visitor = FindLocalByTypeVisitor :: new ( & self , ty, & self . tcx . hir ( ) ) ;
215238 let ty_to_string = |ty : Ty < ' tcx > | -> String {
@@ -218,7 +241,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
218241 let ty_vars = self . type_variables . borrow ( ) ;
219242 let getter = move |ty_vid| {
220243 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 {
222245 return Some ( name. to_string ( ) ) ;
223246 }
224247 None
@@ -317,6 +340,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
317340 & descr,
318341 & name,
319342 & ret,
343+ parent_name,
344+ parent_descr,
320345 ) ;
321346 // We don't want to give the other suggestions when the problem is the
322347 // closure return type.
@@ -433,8 +458,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
433458 if !err. span . span_labels ( ) . iter ( ) . any ( |span_label| {
434459 span_label. label . is_some ( ) && span_label. span == span
435460 } ) && 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+ ) ;
438467 }
439468
440469 err
@@ -496,19 +525,42 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
496525 ty : Ty < ' tcx > ,
497526 ) -> DiagnosticBuilder < ' tcx > {
498527 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+
500530 let mut err = struct_span_err ! (
501531 self . tcx. sess, span, E0698 , "type inside {} must be known in this context" , kind,
502532 ) ;
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+ ) ) ;
504539 err
505540 }
506541
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 > {
508548 if type_name == "_" {
509549 "cannot infer type" . into ( )
510550 } 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 ( )
512564 }
513565 }
514566}
0 commit comments