@@ -7,6 +7,7 @@ use crate::hir::def_id::DefId;
7
7
use crate :: hir:: print;
8
8
use crate :: hir:: ptr:: P ;
9
9
use crate :: hir:: { self , ExprKind , GenericArg , GenericArgs , HirVec } ;
10
+ use crate :: hir:: intravisit:: { NestedVisitorMap , Visitor } ;
10
11
use crate :: lint;
11
12
use crate :: middle:: lang_items:: SizedTraitLangItem ;
12
13
use crate :: middle:: resolve_lifetime as rl;
@@ -66,6 +67,8 @@ pub trait AstConv<'tcx> {
66
67
/// Returns the type to use when a type is omitted.
67
68
fn ty_infer ( & self , param : Option < & ty:: GenericParamDef > , span : Span ) -> Ty < ' tcx > ;
68
69
70
+ fn allow_ty_infer ( & self ) -> bool ;
71
+
69
72
/// Returns the const to use when a const is omitted.
70
73
fn ct_infer (
71
74
& self ,
@@ -2593,7 +2596,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2593
2596
}
2594
2597
hir:: TyKind :: BareFn ( ref bf) => {
2595
2598
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 ) )
2597
2600
}
2598
2601
hir:: TyKind :: TraitObject ( ref bounds, ref lifetime) => {
2599
2602
self . conv_object_ty_poly_trait_ref ( ast_ty. span , bounds, lifetime)
@@ -2758,14 +2761,55 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2758
2761
unsafety : hir:: Unsafety ,
2759
2762
abi : abi:: Abi ,
2760
2763
decl : & hir:: FnDecl < ' _ > ,
2764
+ generic_params : & [ hir:: GenericParam < ' _ > ] ,
2765
+ ident_span : Option < Span > ,
2761
2766
) -> ty:: PolyFnSig < ' tcx > {
2762
2767
debug ! ( "ty_of_fn" ) ;
2763
2768
2764
2769
let tcx = self . tcx ( ) ;
2765
- let input_tys = decl. inputs . iter ( ) . map ( |a| self . ty_of_arg ( a, None ) ) ;
2766
2770
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
+ } ) ;
2767
2797
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
+ }
2769
2813
hir:: DefaultReturn ( ..) => tcx. mk_unit ( ) ,
2770
2814
} ;
2771
2815
@@ -2774,6 +2818,39 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2774
2818
let bare_fn_ty =
2775
2819
ty:: Binder :: bind ( tcx. mk_fn_sig ( input_tys, output_ty, decl. c_variadic , unsafety, abi) ) ;
2776
2820
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
+
2777
2854
// Find any late-bound regions declared in return type that do
2778
2855
// not appear in the arguments. These are not well-formed.
2779
2856
//
0 commit comments