@@ -102,17 +102,96 @@ pub struct ItemCtxt<'tcx> {
102102
103103///////////////////////////////////////////////////////////////////////////
104104
105+ crate struct PlaceholderHirTyCollector ( crate Vec < Span > ) ;
106+
107+ impl < ' v > Visitor < ' v > for PlaceholderHirTyCollector {
108+ fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' v > {
109+ NestedVisitorMap :: None
110+ }
111+ fn visit_ty ( & mut self , t : & ' v hir:: Ty < ' v > ) {
112+ if let hir:: TyKind :: Infer = t. kind {
113+ self . 0 . push ( t. span ) ;
114+ }
115+ hir:: intravisit:: walk_ty ( self , t)
116+ }
117+ }
118+
119+ impl PlaceholderHirTyCollector {
120+ pub fn new ( ) -> PlaceholderHirTyCollector {
121+ PlaceholderHirTyCollector ( vec ! [ ] )
122+ }
123+ }
124+
105125struct CollectItemTypesVisitor < ' tcx > {
106126 tcx : TyCtxt < ' tcx > ,
107127}
108128
129+ crate fn placeholder_type_error (
130+ tcx : TyCtxt < ' tcx > ,
131+ ident_span : Span ,
132+ generics : & [ hir:: GenericParam < ' _ > ] ,
133+ placeholder_types : Vec < Span > ,
134+ suggest : bool ,
135+ ) {
136+ if !placeholder_types. is_empty ( ) {
137+ let mut sugg: Vec < _ > = placeholder_types. iter ( ) . map ( |sp| ( * sp, "T" . to_string ( ) ) ) . collect ( ) ;
138+ if generics. is_empty ( ) {
139+ sugg. push ( ( ident_span. shrink_to_hi ( ) , "<T>" . to_string ( ) ) ) ;
140+ } else {
141+ sugg. push ( ( generics. iter ( ) . last ( ) . unwrap ( ) . span . shrink_to_hi ( ) , ", T" . to_string ( ) ) ) ;
142+ }
143+ let mut err = struct_span_err ! (
144+ tcx. sess,
145+ placeholder_types. clone( ) ,
146+ E0121 ,
147+ "the type placeholder `_` is not allowed within types on item signatures" ,
148+ ) ;
149+ for span in & placeholder_types {
150+ err. span_label ( * span, "not allowed in type signatures" ) ;
151+ }
152+ if suggest {
153+ err. multipart_suggestion (
154+ "use type parameters instead" ,
155+ sugg,
156+ Applicability :: HasPlaceholders ,
157+ ) ;
158+ }
159+ err. emit ( ) ;
160+ }
161+ }
162+
163+ fn reject_placeholder_type_signatures_in_item ( tcx : TyCtxt < ' tcx > , item : & ' tcx hir:: Item < ' tcx > ) {
164+ let ( generics, suggest) = match & item. kind {
165+ hir:: ItemKind :: Union ( _, generics)
166+ | hir:: ItemKind :: Enum ( _, generics)
167+ | hir:: ItemKind :: Struct ( _, generics) => ( & generics. params [ ..] , true ) ,
168+ hir:: ItemKind :: Static ( ty, ..) => {
169+ if let hir:: TyKind :: Infer = ty. kind {
170+ return ; // We handle it elsewhere to attempt to suggest an appropriate type.
171+ } else {
172+ ( & [ ] [ ..] , false )
173+ }
174+ }
175+ hir:: ItemKind :: TyAlias ( _, generics) => ( & generics. params [ ..] , false ) ,
176+ // hir::ItemKind::Fn(..) |
177+ // hir::ItemKind::Const(..) => {} // We handle these elsewhere to suggest appropriate type.
178+ _ => return ,
179+ } ;
180+
181+ let mut visitor = PlaceholderHirTyCollector :: new ( ) ;
182+ visitor. visit_item ( item) ;
183+
184+ placeholder_type_error ( tcx, item. ident . span , generics, visitor. 0 , suggest) ;
185+ }
186+
109187impl Visitor < ' tcx > for CollectItemTypesVisitor < ' tcx > {
110188 fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
111189 NestedVisitorMap :: OnlyBodies ( & self . tcx . hir ( ) )
112190 }
113191
114192 fn visit_item ( & mut self , item : & ' tcx hir:: Item < ' tcx > ) {
115193 convert_item ( self . tcx , item. hir_id ) ;
194+ reject_placeholder_type_signatures_in_item ( self . tcx , item) ;
116195 intravisit:: walk_item ( self , item) ;
117196 }
118197
@@ -200,8 +279,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
200279 }
201280
202281 fn ty_infer ( & self , _: Option < & ty:: GenericParamDef > , span : Span ) -> Ty < ' tcx > {
203- bad_placeholder_type ( self . tcx ( ) , span) . emit ( ) ;
204-
282+ self . tcx ( ) . sess . delay_span_bug ( span, "bad placeholder type, but no error was emitted" ) ;
205283 self . tcx ( ) . types . err
206284 }
207285
@@ -1189,6 +1267,10 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
11891267 . and_then ( |body_id| {
11901268 if let hir:: TyKind :: Infer = ty. kind {
11911269 Some ( infer_placeholder_type ( tcx, def_id, body_id, ty. span , item. ident ) )
1270+ } else if is_infer_ty ( ty) {
1271+ // Infering this would cause a cycle error.
1272+ tcx. sess . delay_span_bug ( ty. span , "`_` placeholder but no error emitted" ) ;
1273+ Some ( tcx. types . err )
11921274 } else {
11931275 None
11941276 }
@@ -1208,6 +1290,10 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
12081290 ImplItemKind :: Const ( ref ty, body_id) => {
12091291 if let hir:: TyKind :: Infer = ty. kind {
12101292 infer_placeholder_type ( tcx, def_id, body_id, ty. span , item. ident )
1293+ } else if is_infer_ty ( ty) {
1294+ // Infering this would cause a cycle error.
1295+ tcx. sess . delay_span_bug ( ty. span , "`_` placeholder but no error emitted" ) ;
1296+ tcx. types . err
12111297 } else {
12121298 icx. to_ty ( ty)
12131299 }
@@ -1233,6 +1319,10 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
12331319 ItemKind :: Static ( ref ty, .., body_id) | ItemKind :: Const ( ref ty, body_id) => {
12341320 if let hir:: TyKind :: Infer = ty. kind {
12351321 infer_placeholder_type ( tcx, def_id, body_id, ty. span , item. ident )
1322+ } else if is_infer_ty ( ty) {
1323+ // Infering this would cause a cycle error.
1324+ tcx. sess . delay_span_bug ( ty. span , "`_` placeholder but no error emitted" ) ;
1325+ tcx. types . err
12361326 } else {
12371327 icx. to_ty ( ty)
12381328 }
@@ -1703,7 +1793,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
17031793 }
17041794}
17051795
1706- fn is_infer_ty ( ty : & hir:: Ty < ' _ > ) -> bool {
1796+ crate fn is_infer_ty ( ty : & hir:: Ty < ' _ > ) -> bool {
17071797 match & ty. kind {
17081798 hir:: TyKind :: Infer => true ,
17091799 hir:: TyKind :: Slice ( ty) | hir:: TyKind :: Array ( ty, _) => is_infer_ty ( ty) ,
0 commit comments