mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-26 14:43:24 +00:00
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
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#![feature(lang_items)]
|
||||
|
||||
#[lang = "owned_box"]
|
||||
struct Foo; //~ ERROR E0152
|
||||
struct Foo<T>(T); //~ ERROR E0152
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0152]: found duplicate lang item `owned_box`
|
||||
--> $DIR/E0152.rs:5:1
|
||||
|
|
||||
LL | struct Foo;
|
||||
| ^^^^^^^^^^^
|
||||
LL | struct Foo<T>(T);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the lang item is first defined in crate `alloc` (which `std` depends on)
|
||||
= note: first definition in `alloc` loaded from SYSROOT/liballoc-*.rlib
|
||||
|
28
src/test/ui/lang-items/lang-item-correct-generics.rs
Normal file
28
src/test/ui/lang-items/lang-item-correct-generics.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// build-pass
|
||||
|
||||
#![feature(lang_items,no_core)]
|
||||
#![no_core]
|
||||
#![crate_type="lib"]
|
||||
|
||||
#[lang = "sized"]
|
||||
trait MySized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait MyCopy {}
|
||||
|
||||
#[lang = "drop"]
|
||||
trait MyDrop<T> {}
|
||||
|
||||
struct S;
|
||||
|
||||
impl<T> MyDrop<T> for S {}
|
||||
|
||||
#[lang = "i32"]
|
||||
impl<'a> i32 {
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
i32::foo();
|
||||
S;
|
||||
}
|
44
src/test/ui/lang-items/lang-item-generic-requirements.rs
Normal file
44
src/test/ui/lang-items/lang-item-generic-requirements.rs
Normal file
@ -0,0 +1,44 @@
|
||||
// Checks whether declaring a lang item with the wrong number
|
||||
// of generic arguments crashes the compiler (issue #83893, #87573, and part of #9307).
|
||||
|
||||
#![feature(lang_items, no_core)]
|
||||
#![no_core]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
#[lang = "sized"]
|
||||
trait MySized {}
|
||||
|
||||
#[lang = "add"]
|
||||
trait MyAdd<'a, T> {}
|
||||
//~^^ ERROR: `add` language item must be applied to a trait with 1 generic argument [E0718]
|
||||
|
||||
#[lang = "drop_in_place"]
|
||||
//~^ ERROR `drop_in_place` language item must be applied to a function with at least 1 generic
|
||||
fn my_ptr_drop() {}
|
||||
|
||||
#[lang = "index"]
|
||||
trait MyIndex<'a, T> {}
|
||||
//~^^ ERROR: `index` language item must be applied to a trait with 1 generic argument [E0718]
|
||||
|
||||
#[lang = "phantom_data"]
|
||||
//~^ ERROR `phantom_data` language item must be applied to a struct with 1 generic argument
|
||||
struct MyPhantomData<T, U>;
|
||||
//~^ ERROR parameter `T` is never used
|
||||
//~| ERROR parameter `U` is never used
|
||||
|
||||
fn ice() {
|
||||
// Use add
|
||||
let r = 5;
|
||||
let a = 6;
|
||||
r + a;
|
||||
|
||||
// Use drop in place
|
||||
my_ptr_drop();
|
||||
|
||||
// Use index
|
||||
let arr = [0; 5];
|
||||
let _ = arr[2];
|
||||
|
||||
// Use phantomdata
|
||||
let _ = MyPhantomData::<(), i32>;
|
||||
}
|
56
src/test/ui/lang-items/lang-item-generic-requirements.stderr
Normal file
56
src/test/ui/lang-items/lang-item-generic-requirements.stderr
Normal file
@ -0,0 +1,56 @@
|
||||
error[E0718]: `add` language item must be applied to a trait with 1 generic argument
|
||||
--> $DIR/lang-item-generic-requirements.rs:11:1
|
||||
|
|
||||
LL | #[lang = "add"]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
LL | trait MyAdd<'a, T> {}
|
||||
| ------- this trait has 2 generic arguments
|
||||
|
||||
error[E0718]: `drop_in_place` language item must be applied to a function with at least 1 generic argument
|
||||
--> $DIR/lang-item-generic-requirements.rs:15:1
|
||||
|
|
||||
LL | #[lang = "drop_in_place"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL |
|
||||
LL | fn my_ptr_drop() {}
|
||||
| - this function has 0 generic arguments
|
||||
|
||||
error[E0718]: `index` language item must be applied to a trait with 1 generic argument
|
||||
--> $DIR/lang-item-generic-requirements.rs:19:1
|
||||
|
|
||||
LL | #[lang = "index"]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
LL | trait MyIndex<'a, T> {}
|
||||
| ------- this trait has 2 generic arguments
|
||||
|
||||
error[E0718]: `phantom_data` language item must be applied to a struct with 1 generic argument
|
||||
--> $DIR/lang-item-generic-requirements.rs:23:1
|
||||
|
|
||||
LL | #[lang = "phantom_data"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL |
|
||||
LL | struct MyPhantomData<T, U>;
|
||||
| ------ this struct has 2 generic arguments
|
||||
|
||||
error[E0392]: parameter `T` is never used
|
||||
--> $DIR/lang-item-generic-requirements.rs:25:22
|
||||
|
|
||||
LL | struct MyPhantomData<T, U>;
|
||||
| ^ unused parameter
|
||||
|
|
||||
= help: consider removing `T` or referring to it in a field
|
||||
= help: if you intended `T` to be a const parameter, use `const T: usize` instead
|
||||
|
||||
error[E0392]: parameter `U` is never used
|
||||
--> $DIR/lang-item-generic-requirements.rs:25:25
|
||||
|
|
||||
LL | struct MyPhantomData<T, U>;
|
||||
| ^ unused parameter
|
||||
|
|
||||
= help: consider removing `U` or referring to it in a field
|
||||
= help: if you intended `U` to be a const parameter, use `const U: usize` instead
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0392, E0718.
|
||||
For more information about an error, try `rustc --explain E0392`.
|
@ -1,20 +0,0 @@
|
||||
// Checks whether declaring a lang item with the wrong number
|
||||
// of generic arguments crashes the compiler (issue #83893).
|
||||
|
||||
#![feature(lang_items,no_core)]
|
||||
#![no_core]
|
||||
#![crate_type="lib"]
|
||||
|
||||
#[lang = "sized"]
|
||||
trait MySized {}
|
||||
|
||||
#[lang = "add"]
|
||||
trait MyAdd<'a, T> {}
|
||||
//~^^ ERROR: `add` language item must be applied to a trait with 1 generic argument [E0718]
|
||||
|
||||
fn ice() {
|
||||
let r = 5;
|
||||
let a = 6;
|
||||
r + a
|
||||
//~^ ERROR: cannot add `{integer}` to `{integer}` [E0369]
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
error[E0718]: `add` language item must be applied to a trait with 1 generic argument
|
||||
--> $DIR/wrong-number-generic-args-add.rs:11:1
|
||||
|
|
||||
LL | #[lang = "add"]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
LL | trait MyAdd<'a, T> {}
|
||||
| ------- this trait has 2 generic arguments, not 1
|
||||
|
||||
error[E0369]: cannot add `{integer}` to `{integer}`
|
||||
--> $DIR/wrong-number-generic-args-add.rs:18:7
|
||||
|
|
||||
LL | r + a
|
||||
| - ^ - {integer}
|
||||
| |
|
||||
| {integer}
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0369, E0718.
|
||||
For more information about an error, try `rustc --explain E0369`.
|
@ -1,19 +0,0 @@
|
||||
// Checks whether declaring a lang item with the wrong number
|
||||
// of generic arguments crashes the compiler (issue #83893).
|
||||
|
||||
#![feature(lang_items,no_core)]
|
||||
#![no_core]
|
||||
#![crate_type="lib"]
|
||||
|
||||
#[lang = "sized"]
|
||||
trait MySized {}
|
||||
|
||||
#[lang = "index"]
|
||||
trait MyIndex<'a, T> {}
|
||||
//~^^ ERROR: `index` language item must be applied to a trait with 1 generic argument [E0718]
|
||||
|
||||
fn ice() {
|
||||
let arr = [0; 5];
|
||||
let _ = arr[2];
|
||||
//~^ ERROR: cannot index into a value of type `[{integer}; 5]` [E0608]
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
error[E0718]: `index` language item must be applied to a trait with 1 generic argument
|
||||
--> $DIR/wrong-number-generic-args-index.rs:11:1
|
||||
|
|
||||
LL | #[lang = "index"]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
LL | trait MyIndex<'a, T> {}
|
||||
| ------- this trait has 2 generic arguments, not 1
|
||||
|
||||
error[E0608]: cannot index into a value of type `[{integer}; 5]`
|
||||
--> $DIR/wrong-number-generic-args-index.rs:17:13
|
||||
|
|
||||
LL | let _ = arr[2];
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0608, E0718.
|
||||
For more information about an error, try `rustc --explain E0608`.
|
Loading…
Reference in New Issue
Block a user