@@ -7,6 +7,7 @@ use crate::hir::def_id::DefId;
77use crate :: hir:: print;
88use crate :: hir:: ptr:: P ;
99use crate :: hir:: { self , ExprKind , GenericArg , GenericArgs , HirVec } ;
10+ use crate :: hir:: intravisit:: { NestedVisitorMap , Visitor } ;
1011use crate :: lint;
1112use crate :: middle:: lang_items:: SizedTraitLangItem ;
1213use crate :: middle:: resolve_lifetime as rl;
@@ -66,6 +67,8 @@ pub trait AstConv<'tcx> {
6667 /// Returns the type to use when a type is omitted.
6768 fn ty_infer ( & self , param : Option < & ty:: GenericParamDef > , span : Span ) -> Ty < ' tcx > ;
6869
70+ fn allow_ty_infer ( & self ) -> bool ;
71+
6972 /// Returns the const to use when a const is omitted.
7073 fn ct_infer (
7174 & self ,
@@ -2593,7 +2596,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
25932596 }
25942597 hir:: TyKind :: BareFn ( ref bf) => {
25952598 require_c_abi_if_c_variadic ( tcx, & bf. decl , bf. abi , ast_ty. span ) ;
2596- tcx. mk_fn_ptr ( self . ty_of_fn ( bf. unsafety , bf. abi , & bf. decl ) )
2599+ tcx. mk_fn_ptr ( self . ty_of_fn ( bf. unsafety , bf. abi , & bf. decl , & [ ] , None ) )
25972600 }
25982601 hir:: TyKind :: TraitObject ( ref bounds, ref lifetime) => {
25992602 self . conv_object_ty_poly_trait_ref ( ast_ty. span , bounds, lifetime)
@@ -2758,14 +2761,55 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
27582761 unsafety : hir:: Unsafety ,
27592762 abi : abi:: Abi ,
27602763 decl : & hir:: FnDecl < ' _ > ,
2764+ generic_params : & [ hir:: GenericParam < ' _ > ] ,
2765+ ident_span : Option < Span > ,
27612766 ) -> ty:: PolyFnSig < ' tcx > {
27622767 debug ! ( "ty_of_fn" ) ;
27632768
27642769 let tcx = self . tcx ( ) ;
2765- let input_tys = decl. inputs . iter ( ) . map ( |a| self . ty_of_arg ( a, None ) ) ;
27662770
2771+ // We proactively collect all the infered type params to emit a single error per fn def.
2772+ struct PlaceholderHirTyCollector ( Vec < Span > ) ;
2773+ impl < ' v > Visitor < ' v > for PlaceholderHirTyCollector {
2774+ fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' v > {
2775+ NestedVisitorMap :: None
2776+ }
2777+ fn visit_ty ( & mut self , t : & ' v hir:: Ty < ' v > ) {
2778+ if let hir:: TyKind :: Infer = t. kind {
2779+ self . 0 . push ( t. span ) ;
2780+ }
2781+ hir:: intravisit:: walk_ty ( self , t)
2782+ }
2783+ }
2784+ let mut placeholder_types = vec ! [ ] ;
2785+ let mut output_placeholder_types = vec ! [ ] ;
2786+
2787+ let input_tys = decl. inputs . iter ( ) . map ( |a| {
2788+ let mut visitor = PlaceholderHirTyCollector ( vec ! [ ] ) ;
2789+ visitor. visit_ty ( & a) ;
2790+ if visitor. 0 . is_empty ( ) || self . allow_ty_infer ( ) {
2791+ self . ty_of_arg ( a, None )
2792+ } else {
2793+ placeholder_types. extend ( visitor. 0 ) ;
2794+ tcx. types . err
2795+ }
2796+ } ) ;
27672797 let output_ty = match decl. output {
2768- hir:: Return ( ref output) => self . ast_ty_to_ty ( output) ,
2798+ hir:: Return ( ref output) => {
2799+ let mut visitor = PlaceholderHirTyCollector ( vec ! [ ] ) ;
2800+ visitor. visit_ty ( output) ;
2801+ let is_infer = if let hir:: TyKind :: Infer = output. kind {
2802+ true
2803+ } else {
2804+ false
2805+ } ;
2806+ if ( is_infer || !visitor. 0 . is_empty ( ) ) && !self . allow_ty_infer ( ) {
2807+ output_placeholder_types. extend ( visitor. 0 ) ;
2808+ tcx. types . err
2809+ } else {
2810+ self . ast_ty_to_ty ( output)
2811+ }
2812+ }
27692813 hir:: DefaultReturn ( ..) => tcx. mk_unit ( ) ,
27702814 } ;
27712815
@@ -2774,6 +2818,39 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
27742818 let bare_fn_ty =
27752819 ty:: Binder :: bind ( tcx. mk_fn_sig ( input_tys, output_ty, decl. c_variadic , unsafety, abi) ) ;
27762820
2821+ placeholder_types. extend ( output_placeholder_types) ;
2822+
2823+ if !placeholder_types. is_empty ( ) {
2824+ let mut sugg = placeholder_types. iter ( ) . cloned ( )
2825+ . map ( |sp| ( sp, "T" . to_owned ( ) ) )
2826+ . collect :: < Vec < _ > > ( ) ;
2827+ if let Some ( span) = ident_span {
2828+ if generic_params. is_empty ( ) {
2829+ sugg. push ( ( span. shrink_to_hi ( ) , "<T>" . to_string ( ) ) ) ;
2830+ } else {
2831+ sugg. push ( (
2832+ generic_params. iter ( ) . last ( ) . unwrap ( ) . span . shrink_to_hi ( ) ,
2833+ ", T" . to_string ( ) ,
2834+ ) ) ;
2835+ }
2836+ }
2837+ let mut err = struct_span_err ! (
2838+ tcx. sess,
2839+ placeholder_types,
2840+ E0121 ,
2841+ "the type placeholder `_` is not allowed within types on item signatures" ,
2842+ ) ;
2843+ if ident_span. is_some ( ) {
2844+ err. multipart_suggestion (
2845+ "use type parameters instead" ,
2846+ sugg,
2847+ Applicability :: HasPlaceholders ,
2848+ ) ;
2849+ }
2850+ err. emit ( ) ;
2851+ }
2852+
2853+
27772854 // Find any late-bound regions declared in return type that do
27782855 // not appear in the arguments. These are not well-formed.
27792856 //
0 commit comments