@@ -17,7 +17,7 @@ use rustc_errors::{pluralize, struct_span_err};
1717use rustc_hir as hir;
1818use rustc_hir:: def_id:: DefId ;
1919use rustc_hir:: itemlikevisit:: ItemLikeVisitor ;
20- use rustc_hir:: lang_items:: { extract, ITEM_REFS } ;
20+ use rustc_hir:: lang_items:: { extract, GenericRequirement , ITEM_REFS } ;
2121use rustc_hir:: { HirId , LangItem , LanguageItems , Target } ;
2222use rustc_span:: Span ;
2323
@@ -182,121 +182,69 @@ impl LanguageItemCollector<'tcx> {
182182 }
183183
184184 // 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.
186186 fn collect_item_extended ( & mut self , item_index : usize , hir_id : HirId , span : Span ) {
187187 let item_def_id = self . tcx . hir ( ) . local_def_id ( hir_id) . to_def_id ( ) ;
188188 let lang_item = LangItem :: from_u32 ( item_index as u32 ) . unwrap ( ) ;
189189 let name = lang_item. name ( ) ;
190190
191- self . collect_item ( item_index, item_def_id) ;
192-
193191 // 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.
261198
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+ } ;
265205
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 ,
273215 } ;
274216
275- if expected_num != actual_num {
217+ if let Some ( ( range_str , pluralized ) ) = required {
276218 // We are issuing E0718 "incorrect target" here, because while the
277219 // item kind of the target is correct, the target is still wrong
278220 // because of the wrong number of generic arguments.
279221 struct_span_err ! (
280222 self . tcx. sess,
281223 span,
282224 E0718 ,
283- "`{}` language item must be applied to a trait with {} generic argument{}" ,
225+ "`{}` language item must be applied to a {} with {} generic argument{}" ,
284226 name,
285- expected_num,
286- pluralize!( expected_num)
227+ kind. descr( ) ,
228+ range_str,
229+ pluralized,
287230 )
288231 . span_label (
289232 generics_span,
290233 format ! (
291- "this trait has {} generic argument{}, not {}" ,
234+ "this {} has {} generic argument{}" ,
235+ kind. descr( ) ,
292236 actual_num,
293237 pluralize!( actual_num) ,
294- expected_num
295238 ) ,
296239 )
297240 . emit ( ) ;
241+
242+ // return early to not collect the lang item
243+ return ;
298244 }
299245 }
246+
247+ self . collect_item ( item_index, item_def_id) ;
300248 }
301249}
302250
0 commit comments