Auto merge of #87875 - asquared31415:generic-lang-items, r=cjgillot
Improve detection of generics on lang items Adds detection for the required generics for all lang items. Many lang items require an exact or minimum amount of generic arguments and if they don't exist, the compiler will ICE. This does not add any additional validation about bounds on generics or any other lang item restrictions. Fixes one of the ICEs in #87573 cc `@FabianWolff`
This commit is contained in:
commit
9863bf51a5
12 changed files with 319 additions and 308 deletions
|
@ -6,7 +6,7 @@ Erroneous code example:
|
|||
#![feature(lang_items)]
|
||||
|
||||
#[lang = "owned_box"]
|
||||
struct Foo; // error: duplicate lang item found: `owned_box`
|
||||
struct Foo<T>(T); // error: duplicate lang item found: `owned_box`
|
||||
```
|
||||
|
||||
Lang items are already implemented in the standard library. Unless you are
|
||||
|
|
|
@ -38,7 +38,7 @@ macro_rules! expand_group {
|
|||
// So you probably just want to nip down to the end.
|
||||
macro_rules! language_item_table {
|
||||
(
|
||||
$( $(#[$attr:meta])* $variant:ident $($group:expr)?, $module:ident :: $name:ident, $method:ident, $target:expr; )*
|
||||
$( $(#[$attr:meta])* $variant:ident $($group:expr)?, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )*
|
||||
) => {
|
||||
|
||||
enum_from_u32! {
|
||||
|
@ -72,6 +72,12 @@ macro_rules! language_item_table {
|
|||
$( LangItem::$variant => expand_group!($($group)*), )*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn required_generics(&self) -> GenericRequirement {
|
||||
match self {
|
||||
$( LangItem::$variant => $generics, )*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// All of the language items, defined or not.
|
||||
|
@ -165,108 +171,108 @@ where
|
|||
}
|
||||
|
||||
language_item_table! {
|
||||
// Variant name, Name, Method name, Target;
|
||||
Bool, sym::bool, bool_impl, Target::Impl;
|
||||
Char, sym::char, char_impl, Target::Impl;
|
||||
Str, sym::str, str_impl, Target::Impl;
|
||||
Array, sym::array, array_impl, Target::Impl;
|
||||
Slice, sym::slice, slice_impl, Target::Impl;
|
||||
SliceU8, sym::slice_u8, slice_u8_impl, Target::Impl;
|
||||
StrAlloc, sym::str_alloc, str_alloc_impl, Target::Impl;
|
||||
SliceAlloc, sym::slice_alloc, slice_alloc_impl, Target::Impl;
|
||||
SliceU8Alloc, sym::slice_u8_alloc, slice_u8_alloc_impl, Target::Impl;
|
||||
ConstPtr, sym::const_ptr, const_ptr_impl, Target::Impl;
|
||||
MutPtr, sym::mut_ptr, mut_ptr_impl, Target::Impl;
|
||||
ConstSlicePtr, sym::const_slice_ptr, const_slice_ptr_impl, Target::Impl;
|
||||
MutSlicePtr, sym::mut_slice_ptr, mut_slice_ptr_impl, Target::Impl;
|
||||
I8, sym::i8, i8_impl, Target::Impl;
|
||||
I16, sym::i16, i16_impl, Target::Impl;
|
||||
I32, sym::i32, i32_impl, Target::Impl;
|
||||
I64, sym::i64, i64_impl, Target::Impl;
|
||||
I128, sym::i128, i128_impl, Target::Impl;
|
||||
Isize, sym::isize, isize_impl, Target::Impl;
|
||||
U8, sym::u8, u8_impl, Target::Impl;
|
||||
U16, sym::u16, u16_impl, Target::Impl;
|
||||
U32, sym::u32, u32_impl, Target::Impl;
|
||||
U64, sym::u64, u64_impl, Target::Impl;
|
||||
U128, sym::u128, u128_impl, Target::Impl;
|
||||
Usize, sym::usize, usize_impl, Target::Impl;
|
||||
F32, sym::f32, f32_impl, Target::Impl;
|
||||
F64, sym::f64, f64_impl, Target::Impl;
|
||||
F32Runtime, sym::f32_runtime, f32_runtime_impl, Target::Impl;
|
||||
F64Runtime, sym::f64_runtime, f64_runtime_impl, Target::Impl;
|
||||
// Variant name, Name, Method name, Target Generic requirements;
|
||||
Bool, sym::bool, bool_impl, Target::Impl, GenericRequirement::None;
|
||||
Char, sym::char, char_impl, Target::Impl, GenericRequirement::None;
|
||||
Str, sym::str, str_impl, Target::Impl, GenericRequirement::None;
|
||||
Array, sym::array, array_impl, Target::Impl, GenericRequirement::None;
|
||||
Slice, sym::slice, slice_impl, Target::Impl, GenericRequirement::None;
|
||||
SliceU8, sym::slice_u8, slice_u8_impl, Target::Impl, GenericRequirement::None;
|
||||
StrAlloc, sym::str_alloc, str_alloc_impl, Target::Impl, GenericRequirement::None;
|
||||
SliceAlloc, sym::slice_alloc, slice_alloc_impl, Target::Impl, GenericRequirement::None;
|
||||
SliceU8Alloc, sym::slice_u8_alloc, slice_u8_alloc_impl, Target::Impl, GenericRequirement::None;
|
||||
ConstPtr, sym::const_ptr, const_ptr_impl, Target::Impl, GenericRequirement::None;
|
||||
MutPtr, sym::mut_ptr, mut_ptr_impl, Target::Impl, GenericRequirement::None;
|
||||
ConstSlicePtr, sym::const_slice_ptr, const_slice_ptr_impl, Target::Impl, GenericRequirement::None;
|
||||
MutSlicePtr, sym::mut_slice_ptr, mut_slice_ptr_impl, Target::Impl, GenericRequirement::None;
|
||||
I8, sym::i8, i8_impl, Target::Impl, GenericRequirement::None;
|
||||
I16, sym::i16, i16_impl, Target::Impl, GenericRequirement::None;
|
||||
I32, sym::i32, i32_impl, Target::Impl, GenericRequirement::None;
|
||||
I64, sym::i64, i64_impl, Target::Impl, GenericRequirement::None;
|
||||
I128, sym::i128, i128_impl, Target::Impl, GenericRequirement::None;
|
||||
Isize, sym::isize, isize_impl, Target::Impl, GenericRequirement::None;
|
||||
U8, sym::u8, u8_impl, Target::Impl, GenericRequirement::None;
|
||||
U16, sym::u16, u16_impl, Target::Impl, GenericRequirement::None;
|
||||
U32, sym::u32, u32_impl, Target::Impl, GenericRequirement::None;
|
||||
U64, sym::u64, u64_impl, Target::Impl, GenericRequirement::None;
|
||||
U128, sym::u128, u128_impl, Target::Impl, GenericRequirement::None;
|
||||
Usize, sym::usize, usize_impl, Target::Impl, GenericRequirement::None;
|
||||
F32, sym::f32, f32_impl, Target::Impl, GenericRequirement::None;
|
||||
F64, sym::f64, f64_impl, Target::Impl, GenericRequirement::None;
|
||||
F32Runtime, sym::f32_runtime, f32_runtime_impl, Target::Impl, GenericRequirement::None;
|
||||
F64Runtime, sym::f64_runtime, f64_runtime_impl, Target::Impl, GenericRequirement::None;
|
||||
|
||||
Sized, sym::sized, sized_trait, Target::Trait;
|
||||
Unsize, sym::unsize, unsize_trait, Target::Trait;
|
||||
Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
|
||||
/// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
|
||||
StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait;
|
||||
StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None;
|
||||
/// Trait injected by `#[derive(Eq)]`, (i.e. "Total EQ"; no, I will not apologize).
|
||||
StructuralTeq, sym::structural_teq, structural_teq_trait, Target::Trait;
|
||||
Copy, sym::copy, copy_trait, Target::Trait;
|
||||
Clone, sym::clone, clone_trait, Target::Trait;
|
||||
Sync, sym::sync, sync_trait, Target::Trait;
|
||||
DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait;
|
||||
StructuralTeq, sym::structural_teq, structural_teq_trait, Target::Trait, GenericRequirement::None;
|
||||
Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
Clone, sym::clone, clone_trait, Target::Trait, GenericRequirement::None;
|
||||
Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None;
|
||||
/// The associated item of the [`DiscriminantKind`] trait.
|
||||
Discriminant, sym::discriminant_type, discriminant_type, Target::AssocTy;
|
||||
Discriminant, sym::discriminant_type, discriminant_type, Target::AssocTy, GenericRequirement::None;
|
||||
|
||||
PointeeTrait, sym::pointee_trait, pointee_trait, Target::Trait;
|
||||
Metadata, sym::metadata_type, metadata_type, Target::AssocTy;
|
||||
DynMetadata, sym::dyn_metadata, dyn_metadata, Target::Struct;
|
||||
PointeeTrait, sym::pointee_trait, pointee_trait, Target::Trait, GenericRequirement::None;
|
||||
Metadata, sym::metadata_type, metadata_type, Target::AssocTy, GenericRequirement::None;
|
||||
DynMetadata, sym::dyn_metadata, dyn_metadata, Target::Struct, GenericRequirement::None;
|
||||
|
||||
Freeze, sym::freeze, freeze_trait, Target::Trait;
|
||||
Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
|
||||
Drop, sym::drop, drop_trait, Target::Trait;
|
||||
Drop, sym::drop, drop_trait, Target::Trait, GenericRequirement::None;
|
||||
|
||||
CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait;
|
||||
DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait;
|
||||
CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait, GenericRequirement::Minimum(1);
|
||||
DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait, GenericRequirement::Minimum(1);
|
||||
|
||||
Add(Op), sym::add, add_trait, Target::Trait;
|
||||
Sub(Op), sym::sub, sub_trait, Target::Trait;
|
||||
Mul(Op), sym::mul, mul_trait, Target::Trait;
|
||||
Div(Op), sym::div, div_trait, Target::Trait;
|
||||
Rem(Op), sym::rem, rem_trait, Target::Trait;
|
||||
Neg(Op), sym::neg, neg_trait, Target::Trait;
|
||||
Not(Op), sym::not, not_trait, Target::Trait;
|
||||
BitXor(Op), sym::bitxor, bitxor_trait, Target::Trait;
|
||||
BitAnd(Op), sym::bitand, bitand_trait, Target::Trait;
|
||||
BitOr(Op), sym::bitor, bitor_trait, Target::Trait;
|
||||
Shl(Op), sym::shl, shl_trait, Target::Trait;
|
||||
Shr(Op), sym::shr, shr_trait, Target::Trait;
|
||||
AddAssign(Op), sym::add_assign, add_assign_trait, Target::Trait;
|
||||
SubAssign(Op), sym::sub_assign, sub_assign_trait, Target::Trait;
|
||||
MulAssign(Op), sym::mul_assign, mul_assign_trait, Target::Trait;
|
||||
DivAssign(Op), sym::div_assign, div_assign_trait, Target::Trait;
|
||||
RemAssign(Op), sym::rem_assign, rem_assign_trait, Target::Trait;
|
||||
BitXorAssign(Op), sym::bitxor_assign, bitxor_assign_trait, Target::Trait;
|
||||
BitAndAssign(Op), sym::bitand_assign, bitand_assign_trait, Target::Trait;
|
||||
BitOrAssign(Op), sym::bitor_assign, bitor_assign_trait, Target::Trait;
|
||||
ShlAssign(Op), sym::shl_assign, shl_assign_trait, Target::Trait;
|
||||
ShrAssign(Op), sym::shr_assign, shr_assign_trait, Target::Trait;
|
||||
Index(Op), sym::index, index_trait, Target::Trait;
|
||||
IndexMut(Op), sym::index_mut, index_mut_trait, Target::Trait;
|
||||
Add(Op), sym::add, add_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
Sub(Op), sym::sub, sub_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
Mul(Op), sym::mul, mul_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
Div(Op), sym::div, div_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
Rem(Op), sym::rem, rem_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
Neg(Op), sym::neg, neg_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
Not(Op), sym::not, not_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
BitXor(Op), sym::bitxor, bitxor_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
BitAnd(Op), sym::bitand, bitand_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
BitOr(Op), sym::bitor, bitor_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
Shl(Op), sym::shl, shl_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
Shr(Op), sym::shr, shr_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
AddAssign(Op), sym::add_assign, add_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
SubAssign(Op), sym::sub_assign, sub_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
MulAssign(Op), sym::mul_assign, mul_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
DivAssign(Op), sym::div_assign, div_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
RemAssign(Op), sym::rem_assign, rem_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
BitXorAssign(Op), sym::bitxor_assign, bitxor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
BitAndAssign(Op), sym::bitand_assign, bitand_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
BitOrAssign(Op), sym::bitor_assign, bitor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
ShlAssign(Op), sym::shl_assign, shl_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
ShrAssign(Op), sym::shr_assign, shr_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
Index(Op), sym::index, index_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
IndexMut(Op), sym::index_mut, index_mut_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
|
||||
UnsafeCell, sym::unsafe_cell, unsafe_cell_type, Target::Struct;
|
||||
VaList, sym::va_list, va_list, Target::Struct;
|
||||
UnsafeCell, sym::unsafe_cell, unsafe_cell_type, Target::Struct, GenericRequirement::None;
|
||||
VaList, sym::va_list, va_list, Target::Struct, GenericRequirement::None;
|
||||
|
||||
Deref, sym::deref, deref_trait, Target::Trait;
|
||||
DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait;
|
||||
DerefTarget, sym::deref_target, deref_target, Target::AssocTy;
|
||||
Receiver, sym::receiver, receiver_trait, Target::Trait;
|
||||
Deref, sym::deref, deref_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
|
||||
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
|
||||
|
||||
Fn, kw::Fn, fn_trait, Target::Trait;
|
||||
FnMut, sym::fn_mut, fn_mut_trait, Target::Trait;
|
||||
FnOnce, sym::fn_once, fn_once_trait, Target::Trait;
|
||||
Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
FnOnce, sym::fn_once, fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
|
||||
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy;
|
||||
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
|
||||
|
||||
Future, sym::future_trait, future_trait, Target::Trait;
|
||||
GeneratorState, sym::generator_state, gen_state, Target::Enum;
|
||||
Generator, sym::generator, gen_trait, Target::Trait;
|
||||
Unpin, sym::unpin, unpin_trait, Target::Trait;
|
||||
Pin, sym::pin, pin_type, Target::Struct;
|
||||
Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
GeneratorState, sym::generator_state, gen_state, Target::Enum, GenericRequirement::None;
|
||||
Generator, sym::generator, gen_trait, Target::Trait, GenericRequirement::Minimum(1);
|
||||
Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
|
||||
Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None;
|
||||
|
||||
PartialEq, sym::eq, eq_trait, Target::Trait;
|
||||
PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait;
|
||||
PartialEq, sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
|
||||
// A number of panic-related lang items. The `panic` item corresponds to divide-by-zero and
|
||||
// various panic cases with `match`. The `panic_bounds_check` item is for indexing arrays.
|
||||
|
@ -275,80 +281,86 @@ language_item_table! {
|
|||
// in the sense that a crate is not required to have it defined to use it, but a final product
|
||||
// is required to define it somewhere. Additionally, there are restrictions on crates that use
|
||||
// a weak lang item, but do not have it defined.
|
||||
Panic, sym::panic, panic_fn, Target::Fn;
|
||||
PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn;
|
||||
PanicStr, sym::panic_str, panic_str, Target::Fn;
|
||||
ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn;
|
||||
PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn;
|
||||
PanicInfo, sym::panic_info, panic_info, Target::Struct;
|
||||
PanicLocation, sym::panic_location, panic_location, Target::Struct;
|
||||
PanicImpl, sym::panic_impl, panic_impl, Target::Fn;
|
||||
Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::None;
|
||||
PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None;
|
||||
PanicStr, sym::panic_str, panic_str, Target::Fn, GenericRequirement::None;
|
||||
ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None;
|
||||
PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::None;
|
||||
PanicInfo, sym::panic_info, panic_info, Target::Struct, GenericRequirement::None;
|
||||
PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None;
|
||||
PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None;
|
||||
/// libstd panic entry point. Necessary for const eval to be able to catch it
|
||||
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn;
|
||||
BeginPanicFmt, sym::begin_panic_fmt, begin_panic_fmt, Target::Fn;
|
||||
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None;
|
||||
BeginPanicFmt, sym::begin_panic_fmt, begin_panic_fmt, Target::Fn, GenericRequirement::None;
|
||||
|
||||
ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn;
|
||||
BoxFree, sym::box_free, box_free_fn, Target::Fn;
|
||||
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn;
|
||||
Oom, sym::oom, oom, Target::Fn;
|
||||
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct;
|
||||
ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
|
||||
BoxFree, sym::box_free, box_free_fn, Target::Fn, GenericRequirement::Minimum(1);
|
||||
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
|
||||
Oom, sym::oom, oom, Target::Fn, GenericRequirement::None;
|
||||
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;
|
||||
|
||||
Start, sym::start, start_fn, Target::Fn;
|
||||
Start, sym::start, start_fn, Target::Fn, GenericRequirement::None;
|
||||
|
||||
EhPersonality, sym::eh_personality, eh_personality, Target::Fn;
|
||||
EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static;
|
||||
EhPersonality, sym::eh_personality, eh_personality, Target::Fn, GenericRequirement::None;
|
||||
EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static, GenericRequirement::None;
|
||||
|
||||
OwnedBox, sym::owned_box, owned_box, Target::Struct;
|
||||
OwnedBox, sym::owned_box, owned_box, Target::Struct, GenericRequirement::Minimum(1);
|
||||
|
||||
PhantomData, sym::phantom_data, phantom_data, Target::Struct;
|
||||
PhantomData, sym::phantom_data, phantom_data, Target::Struct, GenericRequirement::Exact(1);
|
||||
|
||||
ManuallyDrop, sym::manually_drop, manually_drop, Target::Struct;
|
||||
ManuallyDrop, sym::manually_drop, manually_drop, Target::Struct, GenericRequirement::None;
|
||||
|
||||
MaybeUninit, sym::maybe_uninit, maybe_uninit, Target::Union;
|
||||
MaybeUninit, sym::maybe_uninit, maybe_uninit, Target::Union, GenericRequirement::None;
|
||||
|
||||
/// Align offset for stride != 1; must not panic.
|
||||
AlignOffset, sym::align_offset, align_offset_fn, Target::Fn;
|
||||
AlignOffset, sym::align_offset, align_offset_fn, Target::Fn, GenericRequirement::None;
|
||||
|
||||
Termination, sym::termination, termination, Target::Trait;
|
||||
Termination, sym::termination, termination, Target::Trait, GenericRequirement::None;
|
||||
|
||||
Try, sym::Try, try_trait, Target::Trait;
|
||||
Try, sym::Try, try_trait, Target::Trait, GenericRequirement::None;
|
||||
|
||||
SliceLen, sym::slice_len_fn, slice_len_fn, Target::Method(MethodKind::Inherent);
|
||||
SliceLen, sym::slice_len_fn, slice_len_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
|
||||
|
||||
// Language items from AST lowering
|
||||
TryTraitFromResidual, sym::from_residual, from_residual_fn, Target::Method(MethodKind::Trait { body: false });
|
||||
TryTraitFromOutput, sym::from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false });
|
||||
TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false });
|
||||
TryTraitFromResidual, sym::from_residual, from_residual_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
TryTraitFromOutput, sym::from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
|
||||
PollReady, sym::Ready, poll_ready_variant, Target::Variant;
|
||||
PollPending, sym::Pending, poll_pending_variant, Target::Variant;
|
||||
PollReady, sym::Ready, poll_ready_variant, Target::Variant, GenericRequirement::None;
|
||||
PollPending, sym::Pending, poll_pending_variant, Target::Variant, GenericRequirement::None;
|
||||
|
||||
FromGenerator, sym::from_generator, from_generator_fn, Target::Fn;
|
||||
GetContext, sym::get_context, get_context_fn, Target::Fn;
|
||||
FromGenerator, sym::from_generator, from_generator_fn, Target::Fn, GenericRequirement::None;
|
||||
GetContext, sym::get_context, get_context_fn, Target::Fn, GenericRequirement::None;
|
||||
|
||||
FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false });
|
||||
FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
|
||||
FromFrom, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false });
|
||||
FromFrom, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
|
||||
OptionSome, sym::Some, option_some_variant, Target::Variant;
|
||||
OptionNone, sym::None, option_none_variant, Target::Variant;
|
||||
OptionSome, sym::Some, option_some_variant, Target::Variant, GenericRequirement::None;
|
||||
OptionNone, sym::None, option_none_variant, Target::Variant, GenericRequirement::None;
|
||||
|
||||
ResultOk, sym::Ok, result_ok_variant, Target::Variant;
|
||||
ResultErr, sym::Err, result_err_variant, Target::Variant;
|
||||
ResultOk, sym::Ok, result_ok_variant, Target::Variant, GenericRequirement::None;
|
||||
ResultErr, sym::Err, result_err_variant, Target::Variant, GenericRequirement::None;
|
||||
|
||||
ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant;
|
||||
ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant;
|
||||
ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant, GenericRequirement::None;
|
||||
ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant, GenericRequirement::None;
|
||||
|
||||
IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false });
|
||||
IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false});
|
||||
IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None;
|
||||
|
||||
PinNewUnchecked, sym::new_unchecked, new_unchecked_fn, Target::Method(MethodKind::Inherent);
|
||||
PinNewUnchecked, sym::new_unchecked, new_unchecked_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
|
||||
|
||||
RangeFrom, sym::RangeFrom, range_from_struct, Target::Struct;
|
||||
RangeFull, sym::RangeFull, range_full_struct, Target::Struct;
|
||||
RangeInclusiveStruct, sym::RangeInclusive, range_inclusive_struct, Target::Struct;
|
||||
RangeInclusiveNew, sym::range_inclusive_new, range_inclusive_new_method, Target::Method(MethodKind::Inherent);
|
||||
Range, sym::Range, range_struct, Target::Struct;
|
||||
RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct;
|
||||
RangeTo, sym::RangeTo, range_to_struct, Target::Struct;
|
||||
RangeFrom, sym::RangeFrom, range_from_struct, Target::Struct, GenericRequirement::None;
|
||||
RangeFull, sym::RangeFull, range_full_struct, Target::Struct, GenericRequirement::None;
|
||||
RangeInclusiveStruct, sym::RangeInclusive, range_inclusive_struct, Target::Struct, GenericRequirement::None;
|
||||
RangeInclusiveNew, sym::range_inclusive_new, range_inclusive_new_method, Target::Method(MethodKind::Inherent), GenericRequirement::None;
|
||||
Range, sym::Range, range_struct, Target::Struct, GenericRequirement::None;
|
||||
RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct, GenericRequirement::None;
|
||||
RangeTo, sym::RangeTo, range_to_struct, Target::Struct, GenericRequirement::None;
|
||||
}
|
||||
|
||||
pub enum GenericRequirement {
|
||||
None,
|
||||
Minimum(usize),
|
||||
Exact(usize),
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ use rustc_errors::{pluralize, struct_span_err};
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc_hir::lang_items::{extract, ITEM_REFS};
|
||||
use rustc_hir::lang_items::{extract, GenericRequirement, ITEM_REFS};
|
||||
use rustc_hir::{HirId, LangItem, LanguageItems, Target};
|
||||
use rustc_span::Span;
|
||||
|
||||
|
@ -183,97 +183,39 @@ impl LanguageItemCollector<'tcx> {
|
|||
}
|
||||
|
||||
// Like collect_item() above, but also checks whether the lang item is declared
|
||||
// with the right number of generic arguments if it is a trait.
|
||||
// with the right number of generic arguments.
|
||||
fn collect_item_extended(&mut self, item_index: usize, hir_id: HirId, span: Span) {
|
||||
let item_def_id = self.tcx.hir().local_def_id(hir_id).to_def_id();
|
||||
let lang_item = LangItem::from_u32(item_index as u32).unwrap();
|
||||
let name = lang_item.name();
|
||||
|
||||
self.collect_item(item_index, item_def_id);
|
||||
|
||||
// Now check whether the lang_item has the expected number of generic
|
||||
// arguments if it is a trait. Generally speaking, binary and indexing
|
||||
// operations have one (for the RHS/index), unary operations have none,
|
||||
// and the rest also have none except for the closure traits (one for
|
||||
// the argument list), generators (one for the resume argument),
|
||||
// ordering/equality relations (one for the RHS), and various conversion
|
||||
// traits.
|
||||
// arguments. Generally speaking, binary and indexing operations have
|
||||
// one (for the RHS/index), unary operations have none, the closure
|
||||
// traits have one for the argument list, generators have one for the
|
||||
// resume argument, and ordering/equality relations have one for the RHS
|
||||
// Some other types like Box and various functions like drop_in_place
|
||||
// have minimum requirements.
|
||||
|
||||
let expected_num = match lang_item {
|
||||
// Binary operations
|
||||
LangItem::Add
|
||||
| LangItem::Sub
|
||||
| LangItem::Mul
|
||||
| LangItem::Div
|
||||
| LangItem::Rem
|
||||
| LangItem::BitXor
|
||||
| LangItem::BitAnd
|
||||
| LangItem::BitOr
|
||||
| LangItem::Shl
|
||||
| LangItem::Shr
|
||||
| LangItem::AddAssign
|
||||
| LangItem::SubAssign
|
||||
| LangItem::MulAssign
|
||||
| LangItem::DivAssign
|
||||
| LangItem::RemAssign
|
||||
| LangItem::BitXorAssign
|
||||
| LangItem::BitAndAssign
|
||||
| LangItem::BitOrAssign
|
||||
| LangItem::ShlAssign
|
||||
| LangItem::ShrAssign
|
||||
| LangItem::Index
|
||||
| LangItem::IndexMut
|
||||
|
||||
// Miscellaneous
|
||||
| LangItem::Unsize
|
||||
| LangItem::CoerceUnsized
|
||||
| LangItem::DispatchFromDyn
|
||||
| LangItem::Fn
|
||||
| LangItem::FnMut
|
||||
| LangItem::FnOnce
|
||||
| LangItem::Generator
|
||||
| LangItem::PartialEq
|
||||
| LangItem::PartialOrd
|
||||
=> Some(1),
|
||||
|
||||
// Unary operations
|
||||
LangItem::Neg
|
||||
| LangItem::Not
|
||||
|
||||
// Miscellaneous
|
||||
| LangItem::Deref
|
||||
| LangItem::DerefMut
|
||||
| LangItem::Sized
|
||||
| LangItem::StructuralPeq
|
||||
| LangItem::StructuralTeq
|
||||
| LangItem::Copy
|
||||
| LangItem::Clone
|
||||
| LangItem::Sync
|
||||
| LangItem::DiscriminantKind
|
||||
| LangItem::PointeeTrait
|
||||
| LangItem::Freeze
|
||||
| LangItem::Drop
|
||||
| LangItem::Receiver
|
||||
| LangItem::Future
|
||||
| LangItem::Unpin
|
||||
| LangItem::Termination
|
||||
| LangItem::Try
|
||||
=> Some(0),
|
||||
|
||||
// Not a trait
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(expected_num) = expected_num {
|
||||
let (actual_num, generics_span) = match self.tcx.hir().get(hir_id) {
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Trait(_, _, generics, ..),
|
||||
..
|
||||
}) => (generics.params.len(), generics.span),
|
||||
_ => bug!("op/index/deref lang item target is not a trait: {:?}", lang_item),
|
||||
if let hir::Node::Item(hir::Item { kind, span: item_span, .. }) = self.tcx.hir().get(hir_id)
|
||||
{
|
||||
let (actual_num, generics_span) = match kind.generics() {
|
||||
Some(generics) => (generics.params.len(), generics.span),
|
||||
None => (0, *item_span),
|
||||
};
|
||||
|
||||
if expected_num != actual_num {
|
||||
let required = match lang_item.required_generics() {
|
||||
GenericRequirement::Exact(num) if num != actual_num => {
|
||||
Some((format!("{}", num), pluralize!(num)))
|
||||
}
|
||||
GenericRequirement::Minimum(num) if actual_num < num => {
|
||||
Some((format!("at least {}", num), pluralize!(num)))
|
||||
}
|
||||
// If the number matches, or there is no requirement, handle it normally
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some((range_str, pluralized)) = required {
|
||||
// We are issuing E0718 "incorrect target" here, because while the
|
||||
// item kind of the target is correct, the target is still wrong
|
||||
// because of the wrong number of generic arguments.
|
||||
|
@ -281,23 +223,29 @@ impl LanguageItemCollector<'tcx> {
|
|||
self.tcx.sess,
|
||||
span,
|
||||
E0718,
|
||||
"`{}` language item must be applied to a trait with {} generic argument{}",
|
||||
"`{}` language item must be applied to a {} with {} generic argument{}",
|
||||
name,
|
||||
expected_num,
|
||||
pluralize!(expected_num)
|
||||
kind.descr(),
|
||||
range_str,
|
||||
pluralized,
|
||||
)
|
||||
.span_label(
|
||||
generics_span,
|
||||
format!(
|
||||
"this trait has {} generic argument{}, not {}",
|
||||
"this {} has {} generic argument{}",
|
||||
kind.descr(),
|
||||
actual_num,
|
||||
pluralize!(actual_num),
|
||||
expected_num
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
|
||||
// return early to not collect the lang item
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.collect_item(item_index, item_def_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue