@@ -18,7 +18,7 @@ use rustc_errors::{pluralize, struct_span_err};
18
18
use rustc_hir as hir;
19
19
use rustc_hir:: def_id:: DefId ;
20
20
use rustc_hir:: itemlikevisit:: ItemLikeVisitor ;
21
- use rustc_hir:: lang_items:: { extract, ITEM_REFS } ;
21
+ use rustc_hir:: lang_items:: { extract, GenericRequirement , ITEM_REFS } ;
22
22
use rustc_hir:: { HirId , LangItem , LanguageItems , Target } ;
23
23
use rustc_span:: Span ;
24
24
@@ -183,121 +183,69 @@ impl LanguageItemCollector<'tcx> {
183
183
}
184
184
185
185
// Like collect_item() above, but also checks whether the lang item is declared
186
- // with the right number of generic arguments if it is a trait .
186
+ // with the right number of generic arguments.
187
187
fn collect_item_extended ( & mut self , item_index : usize , hir_id : HirId , span : Span ) {
188
188
let item_def_id = self . tcx . hir ( ) . local_def_id ( hir_id) . to_def_id ( ) ;
189
189
let lang_item = LangItem :: from_u32 ( item_index as u32 ) . unwrap ( ) ;
190
190
let name = lang_item. name ( ) ;
191
191
192
- self . collect_item ( item_index, item_def_id) ;
193
-
194
192
// Now check whether the lang_item has the expected number of generic
195
- // arguments if it is a trait. Generally speaking, binary and indexing
196
- // operations have one (for the RHS/index), unary operations have none,
197
- // and the rest also have none except for the closure traits (one for
198
- // the argument list), generators (one for the resume argument),
199
- // ordering/equality relations (one for the RHS), and various conversion
200
- // traits.
201
-
202
- let expected_num = match lang_item {
203
- // Binary operations
204
- LangItem :: Add
205
- | LangItem :: Sub
206
- | LangItem :: Mul
207
- | LangItem :: Div
208
- | LangItem :: Rem
209
- | LangItem :: BitXor
210
- | LangItem :: BitAnd
211
- | LangItem :: BitOr
212
- | LangItem :: Shl
213
- | LangItem :: Shr
214
- | LangItem :: AddAssign
215
- | LangItem :: SubAssign
216
- | LangItem :: MulAssign
217
- | LangItem :: DivAssign
218
- | LangItem :: RemAssign
219
- | LangItem :: BitXorAssign
220
- | LangItem :: BitAndAssign
221
- | LangItem :: BitOrAssign
222
- | LangItem :: ShlAssign
223
- | LangItem :: ShrAssign
224
- | LangItem :: Index
225
- | LangItem :: IndexMut
226
-
227
- // Miscellaneous
228
- | LangItem :: Unsize
229
- | LangItem :: CoerceUnsized
230
- | LangItem :: DispatchFromDyn
231
- | LangItem :: Fn
232
- | LangItem :: FnMut
233
- | LangItem :: FnOnce
234
- | LangItem :: Generator
235
- | LangItem :: PartialEq
236
- | LangItem :: PartialOrd
237
- => Some ( 1 ) ,
238
-
239
- // Unary operations
240
- LangItem :: Neg
241
- | LangItem :: Not
242
-
243
- // Miscellaneous
244
- | LangItem :: Deref
245
- | LangItem :: DerefMut
246
- | LangItem :: Sized
247
- | LangItem :: StructuralPeq
248
- | LangItem :: StructuralTeq
249
- | LangItem :: Copy
250
- | LangItem :: Clone
251
- | LangItem :: Sync
252
- | LangItem :: DiscriminantKind
253
- | LangItem :: PointeeTrait
254
- | LangItem :: Freeze
255
- | LangItem :: Drop
256
- | LangItem :: Receiver
257
- | LangItem :: Future
258
- | LangItem :: Unpin
259
- | LangItem :: Termination
260
- | LangItem :: Try
261
- => Some ( 0 ) ,
193
+ // arguments. Generally speaking, binary and indexing operations have
194
+ // one (for the RHS/index), unary operations have none, the closure
195
+ // traits have one for the argument list, generators have one for the
196
+ // resume argument, and ordering/equality relations have one for the RHS
197
+ // Some other types like Box and various functions like drop_in_place
198
+ // have minimum requirements.
262
199
263
- // Not a trait
264
- _ => None ,
265
- } ;
200
+ if let hir:: Node :: Item ( hir:: Item { kind, span : item_span, .. } ) = self . tcx . hir ( ) . get ( hir_id)
201
+ {
202
+ let ( actual_num, generics_span) = match kind. generics ( ) {
203
+ Some ( generics) => ( generics. params . len ( ) , generics. span ) ,
204
+ None => ( 0 , * item_span) ,
205
+ } ;
266
206
267
- if let Some ( expected_num) = expected_num {
268
- let ( actual_num, generics_span) = match self . tcx . hir ( ) . get ( hir_id) {
269
- hir:: Node :: Item ( hir:: Item {
270
- kind : hir:: ItemKind :: Trait ( _, _, generics, ..) ,
271
- ..
272
- } ) => ( generics. params . len ( ) , generics. span ) ,
273
- _ => bug ! ( "op/index/deref lang item target is not a trait: {:?}" , lang_item) ,
207
+ let required = match lang_item. required_generics ( ) {
208
+ GenericRequirement :: Exact ( num) if num != actual_num => {
209
+ Some ( ( format ! ( "{}" , num) , pluralize ! ( num) ) )
210
+ }
211
+ GenericRequirement :: Minimum ( num) if actual_num < num => {
212
+ Some ( ( format ! ( "at least {}" , num) , pluralize ! ( num) ) )
213
+ }
214
+ // If the number matches, or there is no requirement, handle it normally
215
+ _ => None ,
274
216
} ;
275
217
276
- if expected_num != actual_num {
218
+ if let Some ( ( range_str , pluralized ) ) = required {
277
219
// We are issuing E0718 "incorrect target" here, because while the
278
220
// item kind of the target is correct, the target is still wrong
279
221
// because of the wrong number of generic arguments.
280
222
struct_span_err ! (
281
223
self . tcx. sess,
282
224
span,
283
225
E0718 ,
284
- "`{}` language item must be applied to a trait with {} generic argument{}" ,
226
+ "`{}` language item must be applied to a {} with {} generic argument{}" ,
285
227
name,
286
- expected_num,
287
- pluralize!( expected_num)
228
+ kind. descr( ) ,
229
+ range_str,
230
+ pluralized,
288
231
)
289
232
. span_label (
290
233
generics_span,
291
234
format ! (
292
- "this trait has {} generic argument{}, not {}" ,
235
+ "this {} has {} generic argument{}" ,
236
+ kind. descr( ) ,
293
237
actual_num,
294
238
pluralize!( actual_num) ,
295
- expected_num
296
239
) ,
297
240
)
298
241
. emit ( ) ;
242
+
243
+ // return early to not collect the lang item
244
+ return ;
299
245
}
300
246
}
247
+
248
+ self . collect_item ( item_index, item_def_id) ;
301
249
}
302
250
}
303
251
0 commit comments