@@ -18,7 +18,7 @@ use rustc_errors::{pluralize, struct_span_err};
1818use rustc_hir as hir;
1919use rustc_hir:: def_id:: DefId ;
2020use rustc_hir:: itemlikevisit:: ItemLikeVisitor ;
21- use rustc_hir:: lang_items:: { extract, ITEM_REFS } ;
21+ use rustc_hir:: lang_items:: { extract, GenericRequirement , ITEM_REFS } ;
2222use rustc_hir:: { HirId , LangItem , LanguageItems , Target } ;
2323use rustc_span:: Span ;
2424
@@ -183,121 +183,69 @@ impl LanguageItemCollector<'tcx> {
183183 }
184184
185185 // 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.
187187 fn collect_item_extended ( & mut self , item_index : usize , hir_id : HirId , span : Span ) {
188188 let item_def_id = self . tcx . hir ( ) . local_def_id ( hir_id) . to_def_id ( ) ;
189189 let lang_item = LangItem :: from_u32 ( item_index as u32 ) . unwrap ( ) ;
190190 let name = lang_item. name ( ) ;
191191
192- self . collect_item ( item_index, item_def_id) ;
193-
194192 // 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.
262199
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+ } ;
266206
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 ,
274216 } ;
275217
276- if expected_num != actual_num {
218+ if let Some ( ( range_str , pluralized ) ) = required {
277219 // We are issuing E0718 "incorrect target" here, because while the
278220 // item kind of the target is correct, the target is still wrong
279221 // because of the wrong number of generic arguments.
280222 struct_span_err ! (
281223 self . tcx. sess,
282224 span,
283225 E0718 ,
284- "`{}` language item must be applied to a trait with {} generic argument{}" ,
226+ "`{}` language item must be applied to a {} with {} generic argument{}" ,
285227 name,
286- expected_num,
287- pluralize!( expected_num)
228+ kind. descr( ) ,
229+ range_str,
230+ pluralized,
288231 )
289232 . span_label (
290233 generics_span,
291234 format ! (
292- "this trait has {} generic argument{}, not {}" ,
235+ "this {} has {} generic argument{}" ,
236+ kind. descr( ) ,
293237 actual_num,
294238 pluralize!( actual_num) ,
295- expected_num
296239 ) ,
297240 )
298241 . emit ( ) ;
242+
243+ // return early to not collect the lang item
244+ return ;
299245 }
300246 }
247+
248+ self . collect_item ( item_index, item_def_id) ;
301249 }
302250}
303251
0 commit comments