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