@@ -18,13 +18,15 @@ use rustc_middle::infer::unify_key::{
1818} ;
1919use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AutoBorrow } ;
2020use rustc_middle:: ty:: print:: { FmtPrinter , PrettyPrinter , Print , Printer } ;
21- use rustc_middle:: ty:: { self , InferConst } ;
22- use rustc_middle:: ty:: { GenericArg , GenericArgKind , GenericArgsRef } ;
23- use rustc_middle:: ty:: { IsSuggestable , Ty , TyCtxt , TypeckResults } ;
21+ use rustc_middle:: ty:: {
22+ self , GenericArg , GenericArgKind , GenericArgsRef , InferConst , IsSuggestable , Ty , TyCtxt ,
23+ TypeFoldable , TypeFolder , TypeSuperFoldable , TypeckResults ,
24+ } ;
2425use rustc_span:: symbol:: { kw, sym, Ident } ;
25- use rustc_span:: { BytePos , Span } ;
26+ use rustc_span:: { BytePos , Span , DUMMY_SP } ;
2627use std:: borrow:: Cow ;
2728use std:: iter;
29+ use std:: path:: PathBuf ;
2830
2931pub enum TypeAnnotationNeeded {
3032 /// ```compile_fail,E0282
@@ -153,6 +155,29 @@ impl UnderspecifiedArgKind {
153155 }
154156}
155157
158+ struct ClosureEraser < ' tcx > {
159+ tcx : TyCtxt < ' tcx > ,
160+ }
161+
162+ impl < ' tcx > TypeFolder < TyCtxt < ' tcx > > for ClosureEraser < ' tcx > {
163+ fn interner ( & self ) -> TyCtxt < ' tcx > {
164+ self . tcx
165+ }
166+
167+ fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
168+ match ty. kind ( ) {
169+ ty:: Closure ( _, args) => {
170+ let closure_sig = args. as_closure ( ) . sig ( ) ;
171+ Ty :: new_fn_ptr (
172+ self . tcx ,
173+ self . tcx . signature_unclosure ( closure_sig, hir:: Unsafety :: Normal ) ,
174+ )
175+ }
176+ _ => ty. super_fold_with ( self ) ,
177+ }
178+ }
179+ }
180+
156181fn fmt_printer < ' a , ' tcx > ( infcx : & ' a InferCtxt < ' tcx > , ns : Namespace ) -> FmtPrinter < ' a , ' tcx > {
157182 let mut printer = FmtPrinter :: new ( infcx. tcx , ns) ;
158183 let ty_getter = move |ty_vid| {
@@ -209,6 +234,10 @@ fn ty_to_string<'tcx>(
209234) -> String {
210235 let mut printer = fmt_printer ( infcx, Namespace :: TypeNS ) ;
211236 let ty = infcx. resolve_vars_if_possible ( ty) ;
237+ // We use `fn` ptr syntax for closures, but this only works when the closure
238+ // does not capture anything.
239+ let ty = ty. fold_with ( & mut ClosureEraser { tcx : infcx. tcx } ) ;
240+
212241 match ( ty. kind ( ) , called_method_def_id) {
213242 // We don't want the regular output for `fn`s because it includes its path in
214243 // invalid pseudo-syntax, we want the `fn`-pointer output instead.
@@ -223,11 +252,6 @@ fn ty_to_string<'tcx>(
223252 "Vec<_>" . to_string ( )
224253 }
225254 _ if ty. is_ty_or_numeric_infer ( ) => "/* Type */" . to_string ( ) ,
226- // FIXME: The same thing for closures, but this only works when the closure
227- // does not capture anything.
228- //
229- // We do have to hide the `extern "rust-call"` ABI in that case though,
230- // which is too much of a bother for now.
231255 _ => {
232256 ty. print ( & mut printer) . unwrap ( ) ;
233257 printer. into_buffer ( )
@@ -387,6 +411,8 @@ impl<'tcx> InferCtxt<'tcx> {
387411 infer_subdiags,
388412 multi_suggestions,
389413 bad_label,
414+ was_written : None ,
415+ path : Default :: default ( ) ,
390416 } ) ,
391417 TypeAnnotationNeeded :: E0283 => self . dcx ( ) . create_err ( AmbiguousImpl {
392418 span,
@@ -396,6 +422,8 @@ impl<'tcx> InferCtxt<'tcx> {
396422 infer_subdiags,
397423 multi_suggestions,
398424 bad_label,
425+ was_written : None ,
426+ path : Default :: default ( ) ,
399427 } ) ,
400428 TypeAnnotationNeeded :: E0284 => self . dcx ( ) . create_err ( AmbiguousReturn {
401429 span,
@@ -405,6 +433,8 @@ impl<'tcx> InferCtxt<'tcx> {
405433 infer_subdiags,
406434 multi_suggestions,
407435 bad_label,
436+ was_written : None ,
437+ path : Default :: default ( ) ,
408438 } ) ,
409439 }
410440 }
@@ -442,7 +472,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
442472 return self . bad_inference_failure_err ( failure_span, arg_data, error_code) ;
443473 } ;
444474
445- let ( source_kind, name) = kind. ty_localized_msg ( self ) ;
475+ let ( source_kind, name, path ) = kind. ty_localized_msg ( self ) ;
446476 let failure_span = if should_label_span && !failure_span. overlaps ( span) {
447477 Some ( failure_span)
448478 } else {
@@ -518,15 +548,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
518548 GenericArgKind :: Lifetime ( _) => bug ! ( "unexpected lifetime" ) ,
519549 GenericArgKind :: Type ( _) => self
520550 . next_ty_var ( TypeVariableOrigin {
521- span : rustc_span :: DUMMY_SP ,
551+ span : DUMMY_SP ,
522552 kind : TypeVariableOriginKind :: MiscVariable ,
523553 } )
524554 . into ( ) ,
525555 GenericArgKind :: Const ( arg) => self
526556 . next_const_var (
527557 arg. ty ( ) ,
528558 ConstVariableOrigin {
529- span : rustc_span :: DUMMY_SP ,
559+ span : DUMMY_SP ,
530560 kind : ConstVariableOriginKind :: MiscVariable ,
531561 } ,
532562 )
@@ -547,7 +577,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
547577 }
548578 InferSourceKind :: FullyQualifiedMethodCall { receiver, successor, args, def_id } => {
549579 let placeholder = Some ( self . next_ty_var ( TypeVariableOrigin {
550- span : rustc_span :: DUMMY_SP ,
580+ span : DUMMY_SP ,
551581 kind : TypeVariableOriginKind :: MiscVariable ,
552582 } ) ) ;
553583 if let Some ( args) = args. make_suggestable ( self . infcx . tcx , true , placeholder) {
@@ -584,7 +614,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
584614 }
585615 InferSourceKind :: ClosureReturn { ty, data, should_wrap_expr } => {
586616 let placeholder = Some ( self . next_ty_var ( TypeVariableOrigin {
587- span : rustc_span :: DUMMY_SP ,
617+ span : DUMMY_SP ,
588618 kind : TypeVariableOriginKind :: MiscVariable ,
589619 } ) ) ;
590620 if let Some ( ty) = ty. make_suggestable ( self . infcx . tcx , true , placeholder) {
@@ -606,6 +636,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
606636 infer_subdiags,
607637 multi_suggestions,
608638 bad_label : None ,
639+ was_written : path. as_ref ( ) . map ( |_| ( ) ) ,
640+ path : path. unwrap_or_default ( ) ,
609641 } ) ,
610642 TypeAnnotationNeeded :: E0283 => self . dcx ( ) . create_err ( AmbiguousImpl {
611643 span,
@@ -615,6 +647,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
615647 infer_subdiags,
616648 multi_suggestions,
617649 bad_label : None ,
650+ was_written : path. as_ref ( ) . map ( |_| ( ) ) ,
651+ path : path. unwrap_or_default ( ) ,
618652 } ) ,
619653 TypeAnnotationNeeded :: E0284 => self . dcx ( ) . create_err ( AmbiguousReturn {
620654 span,
@@ -624,6 +658,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
624658 infer_subdiags,
625659 multi_suggestions,
626660 bad_label : None ,
661+ was_written : path. as_ref ( ) . map ( |_| ( ) ) ,
662+ path : path. unwrap_or_default ( ) ,
627663 } ) ,
628664 }
629665 }
@@ -688,22 +724,23 @@ impl<'tcx> InferSource<'tcx> {
688724}
689725
690726impl < ' tcx > InferSourceKind < ' tcx > {
691- fn ty_localized_msg ( & self , infcx : & InferCtxt < ' tcx > ) -> ( & ' static str , String ) {
727+ fn ty_localized_msg ( & self , infcx : & InferCtxt < ' tcx > ) -> ( & ' static str , String , Option < PathBuf > ) {
728+ let mut path = None ;
692729 match * self {
693730 InferSourceKind :: LetBinding { ty, .. }
694731 | InferSourceKind :: ClosureArg { ty, .. }
695732 | InferSourceKind :: ClosureReturn { ty, .. } => {
696733 if ty. is_closure ( ) {
697- ( "closure" , closure_as_fn_str ( infcx, ty) )
734+ ( "closure" , closure_as_fn_str ( infcx, ty) , path )
698735 } else if !ty. is_ty_or_numeric_infer ( ) {
699- ( "normal" , ty_to_string ( infcx, ty, None ) )
736+ ( "normal" , infcx. tcx . short_ty_string ( ty, & mut path ) , path )
700737 } else {
701- ( "other" , String :: new ( ) )
738+ ( "other" , String :: new ( ) , path )
702739 }
703740 }
704741 // FIXME: We should be able to add some additional info here.
705742 InferSourceKind :: GenericArg { .. }
706- | InferSourceKind :: FullyQualifiedMethodCall { .. } => ( "other" , String :: new ( ) ) ,
743+ | InferSourceKind :: FullyQualifiedMethodCall { .. } => ( "other" , String :: new ( ) , path ) ,
707744 }
708745 }
709746}
0 commit comments