mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-04 19:12:50 +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)]
|
#![feature(lang_items)]
|
||||||
|
|
||||||
#[lang = "owned_box"]
|
#[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
|
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.
|
// So you probably just want to nip down to the end.
|
||||||
macro_rules! language_item_table {
|
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! {
|
enum_from_u32! {
|
||||||
@ -72,6 +72,12 @@ macro_rules! language_item_table {
|
|||||||
$( LangItem::$variant => expand_group!($($group)*), )*
|
$( LangItem::$variant => expand_group!($($group)*), )*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn required_generics(&self) -> GenericRequirement {
|
||||||
|
match self {
|
||||||
|
$( LangItem::$variant => $generics, )*
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All of the language items, defined or not.
|
/// All of the language items, defined or not.
|
||||||
@ -165,108 +171,108 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
language_item_table! {
|
language_item_table! {
|
||||||
// Variant name, Name, Method name, Target;
|
// Variant name, Name, Method name, Target Generic requirements;
|
||||||
Bool, sym::bool, bool_impl, Target::Impl;
|
Bool, sym::bool, bool_impl, Target::Impl, GenericRequirement::None;
|
||||||
Char, sym::char, char_impl, Target::Impl;
|
Char, sym::char, char_impl, Target::Impl, GenericRequirement::None;
|
||||||
Str, sym::str, str_impl, Target::Impl;
|
Str, sym::str, str_impl, Target::Impl, GenericRequirement::None;
|
||||||
Array, sym::array, array_impl, Target::Impl;
|
Array, sym::array, array_impl, Target::Impl, GenericRequirement::None;
|
||||||
Slice, sym::slice, slice_impl, Target::Impl;
|
Slice, sym::slice, slice_impl, Target::Impl, GenericRequirement::None;
|
||||||
SliceU8, sym::slice_u8, slice_u8_impl, Target::Impl;
|
SliceU8, sym::slice_u8, slice_u8_impl, Target::Impl, GenericRequirement::None;
|
||||||
StrAlloc, sym::str_alloc, str_alloc_impl, Target::Impl;
|
StrAlloc, sym::str_alloc, str_alloc_impl, Target::Impl, GenericRequirement::None;
|
||||||
SliceAlloc, sym::slice_alloc, slice_alloc_impl, Target::Impl;
|
SliceAlloc, sym::slice_alloc, slice_alloc_impl, Target::Impl, GenericRequirement::None;
|
||||||
SliceU8Alloc, sym::slice_u8_alloc, slice_u8_alloc_impl, Target::Impl;
|
SliceU8Alloc, sym::slice_u8_alloc, slice_u8_alloc_impl, Target::Impl, GenericRequirement::None;
|
||||||
ConstPtr, sym::const_ptr, const_ptr_impl, Target::Impl;
|
ConstPtr, sym::const_ptr, const_ptr_impl, Target::Impl, GenericRequirement::None;
|
||||||
MutPtr, sym::mut_ptr, mut_ptr_impl, Target::Impl;
|
MutPtr, sym::mut_ptr, mut_ptr_impl, Target::Impl, GenericRequirement::None;
|
||||||
ConstSlicePtr, sym::const_slice_ptr, const_slice_ptr_impl, Target::Impl;
|
ConstSlicePtr, sym::const_slice_ptr, const_slice_ptr_impl, Target::Impl, GenericRequirement::None;
|
||||||
MutSlicePtr, sym::mut_slice_ptr, mut_slice_ptr_impl, Target::Impl;
|
MutSlicePtr, sym::mut_slice_ptr, mut_slice_ptr_impl, Target::Impl, GenericRequirement::None;
|
||||||
I8, sym::i8, i8_impl, Target::Impl;
|
I8, sym::i8, i8_impl, Target::Impl, GenericRequirement::None;
|
||||||
I16, sym::i16, i16_impl, Target::Impl;
|
I16, sym::i16, i16_impl, Target::Impl, GenericRequirement::None;
|
||||||
I32, sym::i32, i32_impl, Target::Impl;
|
I32, sym::i32, i32_impl, Target::Impl, GenericRequirement::None;
|
||||||
I64, sym::i64, i64_impl, Target::Impl;
|
I64, sym::i64, i64_impl, Target::Impl, GenericRequirement::None;
|
||||||
I128, sym::i128, i128_impl, Target::Impl;
|
I128, sym::i128, i128_impl, Target::Impl, GenericRequirement::None;
|
||||||
Isize, sym::isize, isize_impl, Target::Impl;
|
Isize, sym::isize, isize_impl, Target::Impl, GenericRequirement::None;
|
||||||
U8, sym::u8, u8_impl, Target::Impl;
|
U8, sym::u8, u8_impl, Target::Impl, GenericRequirement::None;
|
||||||
U16, sym::u16, u16_impl, Target::Impl;
|
U16, sym::u16, u16_impl, Target::Impl, GenericRequirement::None;
|
||||||
U32, sym::u32, u32_impl, Target::Impl;
|
U32, sym::u32, u32_impl, Target::Impl, GenericRequirement::None;
|
||||||
U64, sym::u64, u64_impl, Target::Impl;
|
U64, sym::u64, u64_impl, Target::Impl, GenericRequirement::None;
|
||||||
U128, sym::u128, u128_impl, Target::Impl;
|
U128, sym::u128, u128_impl, Target::Impl, GenericRequirement::None;
|
||||||
Usize, sym::usize, usize_impl, Target::Impl;
|
Usize, sym::usize, usize_impl, Target::Impl, GenericRequirement::None;
|
||||||
F32, sym::f32, f32_impl, Target::Impl;
|
F32, sym::f32, f32_impl, Target::Impl, GenericRequirement::None;
|
||||||
F64, sym::f64, f64_impl, Target::Impl;
|
F64, sym::f64, f64_impl, Target::Impl, GenericRequirement::None;
|
||||||
F32Runtime, sym::f32_runtime, f32_runtime_impl, Target::Impl;
|
F32Runtime, sym::f32_runtime, f32_runtime_impl, Target::Impl, GenericRequirement::None;
|
||||||
F64Runtime, sym::f64_runtime, f64_runtime_impl, Target::Impl;
|
F64Runtime, sym::f64_runtime, f64_runtime_impl, Target::Impl, GenericRequirement::None;
|
||||||
|
|
||||||
Sized, sym::sized, sized_trait, Target::Trait;
|
Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
Unsize, sym::unsize, unsize_trait, Target::Trait;
|
Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
|
||||||
/// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
|
/// 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).
|
/// Trait injected by `#[derive(Eq)]`, (i.e. "Total EQ"; no, I will not apologize).
|
||||||
StructuralTeq, sym::structural_teq, structural_teq_trait, Target::Trait;
|
StructuralTeq, sym::structural_teq, structural_teq_trait, Target::Trait, GenericRequirement::None;
|
||||||
Copy, sym::copy, copy_trait, Target::Trait;
|
Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
Clone, sym::clone, clone_trait, Target::Trait;
|
Clone, sym::clone, clone_trait, Target::Trait, GenericRequirement::None;
|
||||||
Sync, sym::sync, sync_trait, Target::Trait;
|
Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait;
|
DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None;
|
||||||
/// The associated item of the [`DiscriminantKind`] trait.
|
/// 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;
|
PointeeTrait, sym::pointee_trait, pointee_trait, Target::Trait, GenericRequirement::None;
|
||||||
Metadata, sym::metadata_type, metadata_type, Target::AssocTy;
|
Metadata, sym::metadata_type, metadata_type, Target::AssocTy, GenericRequirement::None;
|
||||||
DynMetadata, sym::dyn_metadata, dyn_metadata, Target::Struct;
|
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;
|
CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait, GenericRequirement::Minimum(1);
|
||||||
DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait;
|
DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait, GenericRequirement::Minimum(1);
|
||||||
|
|
||||||
Add(Op), sym::add, add_trait, Target::Trait;
|
Add(Op), sym::add, add_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Sub(Op), sym::sub, sub_trait, Target::Trait;
|
Sub(Op), sym::sub, sub_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Mul(Op), sym::mul, mul_trait, Target::Trait;
|
Mul(Op), sym::mul, mul_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Div(Op), sym::div, div_trait, Target::Trait;
|
Div(Op), sym::div, div_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Rem(Op), sym::rem, rem_trait, Target::Trait;
|
Rem(Op), sym::rem, rem_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Neg(Op), sym::neg, neg_trait, Target::Trait;
|
Neg(Op), sym::neg, neg_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
Not(Op), sym::not, not_trait, Target::Trait;
|
Not(Op), sym::not, not_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
BitXor(Op), sym::bitxor, bitxor_trait, Target::Trait;
|
BitXor(Op), sym::bitxor, bitxor_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
BitAnd(Op), sym::bitand, bitand_trait, Target::Trait;
|
BitAnd(Op), sym::bitand, bitand_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
BitOr(Op), sym::bitor, bitor_trait, Target::Trait;
|
BitOr(Op), sym::bitor, bitor_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Shl(Op), sym::shl, shl_trait, Target::Trait;
|
Shl(Op), sym::shl, shl_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Shr(Op), sym::shr, shr_trait, Target::Trait;
|
Shr(Op), sym::shr, shr_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
AddAssign(Op), sym::add_assign, add_assign_trait, Target::Trait;
|
AddAssign(Op), sym::add_assign, add_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
SubAssign(Op), sym::sub_assign, sub_assign_trait, Target::Trait;
|
SubAssign(Op), sym::sub_assign, sub_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
MulAssign(Op), sym::mul_assign, mul_assign_trait, Target::Trait;
|
MulAssign(Op), sym::mul_assign, mul_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
DivAssign(Op), sym::div_assign, div_assign_trait, Target::Trait;
|
DivAssign(Op), sym::div_assign, div_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
RemAssign(Op), sym::rem_assign, rem_assign_trait, Target::Trait;
|
RemAssign(Op), sym::rem_assign, rem_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
BitXorAssign(Op), sym::bitxor_assign, bitxor_assign_trait, Target::Trait;
|
BitXorAssign(Op), sym::bitxor_assign, bitxor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
BitAndAssign(Op), sym::bitand_assign, bitand_assign_trait, Target::Trait;
|
BitAndAssign(Op), sym::bitand_assign, bitand_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
BitOrAssign(Op), sym::bitor_assign, bitor_assign_trait, Target::Trait;
|
BitOrAssign(Op), sym::bitor_assign, bitor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
ShlAssign(Op), sym::shl_assign, shl_assign_trait, Target::Trait;
|
ShlAssign(Op), sym::shl_assign, shl_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
ShrAssign(Op), sym::shr_assign, shr_assign_trait, Target::Trait;
|
ShrAssign(Op), sym::shr_assign, shr_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Index(Op), sym::index, index_trait, Target::Trait;
|
Index(Op), sym::index, index_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
IndexMut(Op), sym::index_mut, index_mut_trait, Target::Trait;
|
IndexMut(Op), sym::index_mut, index_mut_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
|
|
||||||
UnsafeCell, sym::unsafe_cell, unsafe_cell_type, Target::Struct;
|
UnsafeCell, sym::unsafe_cell, unsafe_cell_type, Target::Struct, GenericRequirement::None;
|
||||||
VaList, sym::va_list, va_list, Target::Struct;
|
VaList, sym::va_list, va_list, Target::Struct, GenericRequirement::None;
|
||||||
|
|
||||||
Deref, sym::deref, deref_trait, Target::Trait;
|
Deref, sym::deref, deref_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait;
|
DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
DerefTarget, sym::deref_target, deref_target, Target::AssocTy;
|
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
|
||||||
Receiver, sym::receiver, receiver_trait, Target::Trait;
|
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
|
||||||
|
|
||||||
Fn, kw::Fn, fn_trait, Target::Trait;
|
Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
FnMut, sym::fn_mut, fn_mut_trait, Target::Trait;
|
FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
FnOnce, sym::fn_once, fn_once_trait, Target::Trait;
|
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;
|
Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
GeneratorState, sym::generator_state, gen_state, Target::Enum;
|
GeneratorState, sym::generator_state, gen_state, Target::Enum, GenericRequirement::None;
|
||||||
Generator, sym::generator, gen_trait, Target::Trait;
|
Generator, sym::generator, gen_trait, Target::Trait, GenericRequirement::Minimum(1);
|
||||||
Unpin, sym::unpin, unpin_trait, Target::Trait;
|
Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
|
||||||
Pin, sym::pin, pin_type, Target::Struct;
|
Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None;
|
||||||
|
|
||||||
PartialEq, sym::eq, eq_trait, Target::Trait;
|
PartialEq, sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait;
|
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
|
// 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.
|
// 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
|
// 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
|
// is required to define it somewhere. Additionally, there are restrictions on crates that use
|
||||||
// a weak lang item, but do not have it defined.
|
// a weak lang item, but do not have it defined.
|
||||||
Panic, sym::panic, panic_fn, Target::Fn;
|
Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::None;
|
||||||
PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn;
|
PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None;
|
||||||
PanicStr, sym::panic_str, panic_str, Target::Fn;
|
PanicStr, sym::panic_str, panic_str, Target::Fn, GenericRequirement::None;
|
||||||
ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn;
|
ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None;
|
||||||
PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn;
|
PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::None;
|
||||||
PanicInfo, sym::panic_info, panic_info, Target::Struct;
|
PanicInfo, sym::panic_info, panic_info, Target::Struct, GenericRequirement::None;
|
||||||
PanicLocation, sym::panic_location, panic_location, Target::Struct;
|
PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None;
|
||||||
PanicImpl, sym::panic_impl, panic_impl, Target::Fn;
|
PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None;
|
||||||
/// libstd panic entry point. Necessary for const eval to be able to catch it
|
/// libstd panic entry point. Necessary for const eval to be able to catch it
|
||||||
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn;
|
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None;
|
||||||
BeginPanicFmt, sym::begin_panic_fmt, begin_panic_fmt, Target::Fn;
|
BeginPanicFmt, sym::begin_panic_fmt, begin_panic_fmt, Target::Fn, GenericRequirement::None;
|
||||||
|
|
||||||
ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn;
|
ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
|
||||||
BoxFree, sym::box_free, box_free_fn, Target::Fn;
|
BoxFree, sym::box_free, box_free_fn, Target::Fn, GenericRequirement::Minimum(1);
|
||||||
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn;
|
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
|
||||||
Oom, sym::oom, oom, Target::Fn;
|
Oom, sym::oom, oom, Target::Fn, GenericRequirement::None;
|
||||||
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct;
|
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;
|
EhPersonality, sym::eh_personality, eh_personality, Target::Fn, GenericRequirement::None;
|
||||||
EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static;
|
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.
|
/// 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
|
// Language items from AST lowering
|
||||||
TryTraitFromResidual, sym::from_residual, from_residual_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 });
|
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 });
|
TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||||
|
|
||||||
PollReady, sym::Ready, poll_ready_variant, Target::Variant;
|
PollReady, sym::Ready, poll_ready_variant, Target::Variant, GenericRequirement::None;
|
||||||
PollPending, sym::Pending, poll_pending_variant, Target::Variant;
|
PollPending, sym::Pending, poll_pending_variant, Target::Variant, GenericRequirement::None;
|
||||||
|
|
||||||
FromGenerator, sym::from_generator, from_generator_fn, Target::Fn;
|
FromGenerator, sym::from_generator, from_generator_fn, Target::Fn, GenericRequirement::None;
|
||||||
GetContext, sym::get_context, get_context_fn, Target::Fn;
|
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;
|
OptionSome, sym::Some, option_some_variant, Target::Variant, GenericRequirement::None;
|
||||||
OptionNone, sym::None, option_none_variant, Target::Variant;
|
OptionNone, sym::None, option_none_variant, Target::Variant, GenericRequirement::None;
|
||||||
|
|
||||||
ResultOk, sym::Ok, result_ok_variant, Target::Variant;
|
ResultOk, sym::Ok, result_ok_variant, Target::Variant, GenericRequirement::None;
|
||||||
ResultErr, sym::Err, result_err_variant, Target::Variant;
|
ResultErr, sym::Err, result_err_variant, Target::Variant, GenericRequirement::None;
|
||||||
|
|
||||||
ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant;
|
ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant, GenericRequirement::None;
|
||||||
ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant;
|
ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant, GenericRequirement::None;
|
||||||
|
|
||||||
IntoIterIntoIter, sym::into_iter, into_iter_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});
|
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;
|
RangeFrom, sym::RangeFrom, range_from_struct, Target::Struct, GenericRequirement::None;
|
||||||
RangeFull, sym::RangeFull, range_full_struct, Target::Struct;
|
RangeFull, sym::RangeFull, range_full_struct, Target::Struct, GenericRequirement::None;
|
||||||
RangeInclusiveStruct, sym::RangeInclusive, range_inclusive_struct, Target::Struct;
|
RangeInclusiveStruct, sym::RangeInclusive, range_inclusive_struct, Target::Struct, GenericRequirement::None;
|
||||||
RangeInclusiveNew, sym::range_inclusive_new, range_inclusive_new_method, Target::Method(MethodKind::Inherent);
|
RangeInclusiveNew, sym::range_inclusive_new, range_inclusive_new_method, Target::Method(MethodKind::Inherent), GenericRequirement::None;
|
||||||
Range, sym::Range, range_struct, Target::Struct;
|
Range, sym::Range, range_struct, Target::Struct, GenericRequirement::None;
|
||||||
RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct;
|
RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct, GenericRequirement::None;
|
||||||
RangeTo, sym::RangeTo, range_to_struct, Target::Struct;
|
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 as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
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_hir::{HirId, LangItem, LanguageItems, Target};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
@ -183,97 +183,39 @@ impl LanguageItemCollector<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Like collect_item() above, but also checks whether the lang item is declared
|
// 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) {
|
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 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 lang_item = LangItem::from_u32(item_index as u32).unwrap();
|
||||||
let name = lang_item.name();
|
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
|
// Now check whether the lang_item has the expected number of generic
|
||||||
// arguments if it is a trait. Generally speaking, binary and indexing
|
// arguments. Generally speaking, binary and indexing operations have
|
||||||
// operations have one (for the RHS/index), unary operations have none,
|
// one (for the RHS/index), unary operations have none, the closure
|
||||||
// and the rest also have none except for the closure traits (one for
|
// traits have one for the argument list, generators have one for the
|
||||||
// the argument list), generators (one for the resume argument),
|
// resume argument, and ordering/equality relations have one for the RHS
|
||||||
// ordering/equality relations (one for the RHS), and various conversion
|
// Some other types like Box and various functions like drop_in_place
|
||||||
// traits.
|
// have minimum requirements.
|
||||||
|
|
||||||
let expected_num = match lang_item {
|
if let hir::Node::Item(hir::Item { kind, span: item_span, .. }) = self.tcx.hir().get(hir_id)
|
||||||
// Binary operations
|
{
|
||||||
LangItem::Add
|
let (actual_num, generics_span) = match kind.generics() {
|
||||||
| LangItem::Sub
|
Some(generics) => (generics.params.len(), generics.span),
|
||||||
| LangItem::Mul
|
None => (0, *item_span),
|
||||||
| 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 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
|
// We are issuing E0718 "incorrect target" here, because while the
|
||||||
// item kind of the target is correct, the target is still wrong
|
// item kind of the target is correct, the target is still wrong
|
||||||
// because of the wrong number of generic arguments.
|
// because of the wrong number of generic arguments.
|
||||||
@ -281,23 +223,29 @@ impl LanguageItemCollector<'tcx> {
|
|||||||
self.tcx.sess,
|
self.tcx.sess,
|
||||||
span,
|
span,
|
||||||
E0718,
|
E0718,
|
||||||
"`{}` language item must be applied to a trait with {} generic argument{}",
|
"`{}` language item must be applied to a {} with {} generic argument{}",
|
||||||
name,
|
name,
|
||||||
expected_num,
|
kind.descr(),
|
||||||
pluralize!(expected_num)
|
range_str,
|
||||||
|
pluralized,
|
||||||
)
|
)
|
||||||
.span_label(
|
.span_label(
|
||||||
generics_span,
|
generics_span,
|
||||||
format!(
|
format!(
|
||||||
"this trait has {} generic argument{}, not {}",
|
"this {} has {} generic argument{}",
|
||||||
|
kind.descr(),
|
||||||
actual_num,
|
actual_num,
|
||||||
pluralize!(actual_num),
|
pluralize!(actual_num),
|
||||||
expected_num
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.emit();
|
.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)]
|
#![feature(lang_items)]
|
||||||
|
|
||||||
#[lang = "owned_box"]
|
#[lang = "owned_box"]
|
||||||
struct Foo; //~ ERROR E0152
|
struct Foo<T>(T); //~ ERROR E0152
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error[E0152]: found duplicate lang item `owned_box`
|
error[E0152]: found duplicate lang item `owned_box`
|
||||||
--> $DIR/E0152.rs:5:1
|
--> $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: the lang item is first defined in crate `alloc` (which `std` depends on)
|
||||||
= note: first definition in `alloc` loaded from SYSROOT/liballoc-*.rlib
|
= 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