@@ -102,17 +102,96 @@ pub struct ItemCtxt<'tcx> {
102
102
103
103
///////////////////////////////////////////////////////////////////////////
104
104
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
+
105
125
struct CollectItemTypesVisitor < ' tcx > {
106
126
tcx : TyCtxt < ' tcx > ,
107
127
}
108
128
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
+
109
187
impl Visitor < ' tcx > for CollectItemTypesVisitor < ' tcx > {
110
188
fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
111
189
NestedVisitorMap :: OnlyBodies ( & self . tcx . hir ( ) )
112
190
}
113
191
114
192
fn visit_item ( & mut self , item : & ' tcx hir:: Item < ' tcx > ) {
115
193
convert_item ( self . tcx , item. hir_id ) ;
194
+ reject_placeholder_type_signatures_in_item ( self . tcx , item) ;
116
195
intravisit:: walk_item ( self , item) ;
117
196
}
118
197
@@ -200,8 +279,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
200
279
}
201
280
202
281
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" ) ;
205
283
self . tcx ( ) . types . err
206
284
}
207
285
@@ -1189,6 +1267,10 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
1189
1267
. and_then ( |body_id| {
1190
1268
if let hir:: TyKind :: Infer = ty. kind {
1191
1269
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 )
1192
1274
} else {
1193
1275
None
1194
1276
}
@@ -1208,6 +1290,10 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
1208
1290
ImplItemKind :: Const ( ref ty, body_id) => {
1209
1291
if let hir:: TyKind :: Infer = ty. kind {
1210
1292
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
1211
1297
} else {
1212
1298
icx. to_ty ( ty)
1213
1299
}
@@ -1233,6 +1319,10 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
1233
1319
ItemKind :: Static ( ref ty, .., body_id) | ItemKind :: Const ( ref ty, body_id) => {
1234
1320
if let hir:: TyKind :: Infer = ty. kind {
1235
1321
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
1236
1326
} else {
1237
1327
icx. to_ty ( ty)
1238
1328
}
@@ -1703,7 +1793,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
1703
1793
}
1704
1794
}
1705
1795
1706
- fn is_infer_ty ( ty : & hir:: Ty < ' _ > ) -> bool {
1796
+ crate fn is_infer_ty ( ty : & hir:: Ty < ' _ > ) -> bool {
1707
1797
match & ty. kind {
1708
1798
hir:: TyKind :: Infer => true ,
1709
1799
hir:: TyKind :: Slice ( ty) | hir:: TyKind :: Array ( ty, _) => is_infer_ty ( ty) ,
0 commit comments