mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Extend lang items to assert correct target.
This commit extends the existing lang items functionality to assert that the `#[lang_item]` attribute is only found on the appropriate item for any given lang item. That is, language items representing traits must only ever have their corresponding attribute placed on a trait, for example.
This commit is contained in:
parent
a534216fa6
commit
2ecce7ccc5
@ -637,8 +637,8 @@ Erroneous code example:
|
|||||||
```compile_fail,E0152
|
```compile_fail,E0152
|
||||||
#![feature(lang_items)]
|
#![feature(lang_items)]
|
||||||
|
|
||||||
#[lang = "panic_impl"]
|
#[lang = "arc"]
|
||||||
struct Foo; // error: duplicate lang item found: `panic_impl`
|
struct Foo; // error: duplicate lang item found: `arc`
|
||||||
```
|
```
|
||||||
|
|
||||||
Lang items are already implemented in the standard library. Unless you are
|
Lang items are already implemented in the standard library. Unless you are
|
||||||
@ -2116,6 +2116,20 @@ struct Foo;
|
|||||||
```
|
```
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
|
E0718: r##"
|
||||||
|
This error indicates that a `#[lang = ".."]` attribute was placed
|
||||||
|
on the wrong type of item.
|
||||||
|
|
||||||
|
Examples of erroneous code:
|
||||||
|
|
||||||
|
```compile_fail,E0718
|
||||||
|
#![feature(lang_items)]
|
||||||
|
|
||||||
|
#[lang = "arc"]
|
||||||
|
static X: u32 = 42;
|
||||||
|
```
|
||||||
|
"##,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,40 +14,80 @@
|
|||||||
//! conflicts between multiple such attributes attached to the same
|
//! conflicts between multiple such attributes attached to the same
|
||||||
//! item.
|
//! item.
|
||||||
|
|
||||||
use syntax_pos::Span;
|
|
||||||
use ty::TyCtxt;
|
|
||||||
|
|
||||||
use hir;
|
use hir;
|
||||||
use hir::intravisit::{self, Visitor, NestedVisitorMap};
|
use hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||||
|
use ty::TyCtxt;
|
||||||
|
use std::fmt::{self, Display};
|
||||||
|
use syntax_pos::Span;
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
enum Target {
|
pub(crate) enum Target {
|
||||||
|
ExternCrate,
|
||||||
|
Use,
|
||||||
|
Static,
|
||||||
|
Const,
|
||||||
Fn,
|
Fn,
|
||||||
|
Closure,
|
||||||
|
Mod,
|
||||||
|
ForeignMod,
|
||||||
|
GlobalAsm,
|
||||||
|
Ty,
|
||||||
|
Existential,
|
||||||
|
Enum,
|
||||||
Struct,
|
Struct,
|
||||||
Union,
|
Union,
|
||||||
Enum,
|
Trait,
|
||||||
Const,
|
TraitAlias,
|
||||||
ForeignMod,
|
Impl,
|
||||||
Expression,
|
Expression,
|
||||||
Statement,
|
Statement,
|
||||||
Closure,
|
}
|
||||||
Static,
|
|
||||||
Trait,
|
impl Display for Target {
|
||||||
Other,
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}", match *self {
|
||||||
|
Target::ExternCrate => "extern crate",
|
||||||
|
Target::Use => "use",
|
||||||
|
Target::Static => "static item",
|
||||||
|
Target::Const => "constant item",
|
||||||
|
Target::Fn => "function",
|
||||||
|
Target::Closure => "closure",
|
||||||
|
Target::Mod => "module",
|
||||||
|
Target::ForeignMod => "foreign module",
|
||||||
|
Target::GlobalAsm => "global asm",
|
||||||
|
Target::Ty => "type alias",
|
||||||
|
Target::Existential => "existential type",
|
||||||
|
Target::Enum => "enum",
|
||||||
|
Target::Struct => "struct",
|
||||||
|
Target::Union => "union",
|
||||||
|
Target::Trait => "trait",
|
||||||
|
Target::TraitAlias => "trait alias",
|
||||||
|
Target::Impl => "item",
|
||||||
|
Target::Expression => "expression",
|
||||||
|
Target::Statement => "statement",
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Target {
|
impl Target {
|
||||||
fn from_item(item: &hir::Item) -> Target {
|
pub(crate) fn from_item(item: &hir::Item) -> Target {
|
||||||
match item.node {
|
match item.node {
|
||||||
|
hir::ItemKind::ExternCrate(..) => Target::ExternCrate,
|
||||||
|
hir::ItemKind::Use(..) => Target::Use,
|
||||||
|
hir::ItemKind::Static(..) => Target::Static,
|
||||||
|
hir::ItemKind::Const(..) => Target::Const,
|
||||||
hir::ItemKind::Fn(..) => Target::Fn,
|
hir::ItemKind::Fn(..) => Target::Fn,
|
||||||
|
hir::ItemKind::Mod(..) => Target::Mod,
|
||||||
|
hir::ItemKind::ForeignMod(..) => Target::ForeignMod,
|
||||||
|
hir::ItemKind::GlobalAsm(..) => Target::GlobalAsm,
|
||||||
|
hir::ItemKind::Ty(..) => Target::Ty,
|
||||||
|
hir::ItemKind::Existential(..) => Target::Existential,
|
||||||
|
hir::ItemKind::Enum(..) => Target::Enum,
|
||||||
hir::ItemKind::Struct(..) => Target::Struct,
|
hir::ItemKind::Struct(..) => Target::Struct,
|
||||||
hir::ItemKind::Union(..) => Target::Union,
|
hir::ItemKind::Union(..) => Target::Union,
|
||||||
hir::ItemKind::Enum(..) => Target::Enum,
|
|
||||||
hir::ItemKind::Const(..) => Target::Const,
|
|
||||||
hir::ItemKind::ForeignMod(..) => Target::ForeignMod,
|
|
||||||
hir::ItemKind::Static(..) => Target::Static,
|
|
||||||
hir::ItemKind::Trait(..) => Target::Trait,
|
hir::ItemKind::Trait(..) => Target::Trait,
|
||||||
_ => Target::Other,
|
hir::ItemKind::TraitAlias(..) => Target::TraitAlias,
|
||||||
|
hir::ItemKind::Impl(..) => Target::Impl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
pub use self::LangItem::*;
|
pub use self::LangItem::*;
|
||||||
|
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
|
use hir::check_attr::Target;
|
||||||
use ty::{self, TyCtxt};
|
use ty::{self, TyCtxt};
|
||||||
use middle::weak_lang_items;
|
use middle::weak_lang_items;
|
||||||
use util::nodemap::FxHashMap;
|
use util::nodemap::FxHashMap;
|
||||||
@ -36,7 +37,7 @@ use hir;
|
|||||||
// 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 {
|
||||||
(
|
(
|
||||||
$( $variant:ident, $name:expr, $method:ident; )*
|
$( $variant:ident, $name:expr, $method:ident, $target:path; )*
|
||||||
) => {
|
) => {
|
||||||
|
|
||||||
enum_from_u32! {
|
enum_from_u32! {
|
||||||
@ -96,26 +97,49 @@ impl LanguageItems {
|
|||||||
|
|
||||||
struct LanguageItemCollector<'a, 'tcx: 'a> {
|
struct LanguageItemCollector<'a, 'tcx: 'a> {
|
||||||
items: LanguageItems,
|
items: LanguageItems,
|
||||||
|
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
item_refs: FxHashMap<&'static str, (usize, Target)>,
|
||||||
item_refs: FxHashMap<&'static str, usize>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> {
|
impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> {
|
||||||
fn visit_item(&mut self, item: &hir::Item) {
|
fn visit_item(&mut self, item: &hir::Item) {
|
||||||
if let Some((value, span)) = extract(&item.attrs) {
|
if let Some((value, span)) = extract(&item.attrs) {
|
||||||
let item_index = self.item_refs.get(&*value.as_str()).cloned();
|
let actual_target = Target::from_item(item);
|
||||||
|
match self.item_refs.get(&*value.as_str()).cloned() {
|
||||||
if let Some(item_index) = item_index {
|
// Known lang item with attribute on correct target.
|
||||||
let def_id = self.tcx.hir.local_def_id(item.id);
|
Some((item_index, expected_target)) if actual_target == expected_target => {
|
||||||
self.collect_item(item_index, def_id);
|
let def_id = self.tcx.hir.local_def_id(item.id);
|
||||||
} else {
|
self.collect_item(item_index, def_id);
|
||||||
let mut err = struct_span_err!(self.tcx.sess, span, E0522,
|
},
|
||||||
"definition of an unknown language item: `{}`",
|
// Known lang item with attribute on incorrect target.
|
||||||
value);
|
Some((_, expected_target)) => {
|
||||||
err.span_label(span, format!("definition of unknown language item `{}`", value));
|
let mut err = struct_span_err!(
|
||||||
err.emit();
|
self.tcx.sess, span, E0718,
|
||||||
|
"`{}` language item must be applied to a {}",
|
||||||
|
value, expected_target,
|
||||||
|
);
|
||||||
|
err.span_label(
|
||||||
|
span,
|
||||||
|
format!(
|
||||||
|
"attribute should be applied to a {}, not a {}",
|
||||||
|
expected_target, actual_target,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
err.emit();
|
||||||
|
},
|
||||||
|
// Unknown lang item.
|
||||||
|
_ => {
|
||||||
|
let mut err = struct_span_err!(
|
||||||
|
self.tcx.sess, span, E0522,
|
||||||
|
"definition of an unknown language item: `{}`",
|
||||||
|
value
|
||||||
|
);
|
||||||
|
err.span_label(
|
||||||
|
span,
|
||||||
|
format!("definition of unknown language item `{}`", value)
|
||||||
|
);
|
||||||
|
err.emit();
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,7 +157,7 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
|
|||||||
fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItemCollector<'a, 'tcx> {
|
fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItemCollector<'a, 'tcx> {
|
||||||
let mut item_refs = FxHashMap();
|
let mut item_refs = FxHashMap();
|
||||||
|
|
||||||
$( item_refs.insert($name, $variant as usize); )*
|
$( item_refs.insert($name, ($variant as usize, $target)); )*
|
||||||
|
|
||||||
LanguageItemCollector {
|
LanguageItemCollector {
|
||||||
tcx,
|
tcx,
|
||||||
@ -210,84 +234,84 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
|
|||||||
}
|
}
|
||||||
|
|
||||||
language_item_table! {
|
language_item_table! {
|
||||||
// Variant name, Name, Method name;
|
// Variant name, Name, Method name, Target;
|
||||||
CharImplItem, "char", char_impl;
|
CharImplItem, "char", char_impl, Target::Impl;
|
||||||
StrImplItem, "str", str_impl;
|
StrImplItem, "str", str_impl, Target::Impl;
|
||||||
SliceImplItem, "slice", slice_impl;
|
SliceImplItem, "slice", slice_impl, Target::Impl;
|
||||||
SliceU8ImplItem, "slice_u8", slice_u8_impl;
|
SliceU8ImplItem, "slice_u8", slice_u8_impl, Target::Impl;
|
||||||
StrAllocImplItem, "str_alloc", str_alloc_impl;
|
StrAllocImplItem, "str_alloc", str_alloc_impl, Target::Impl;
|
||||||
SliceAllocImplItem, "slice_alloc", slice_alloc_impl;
|
SliceAllocImplItem, "slice_alloc", slice_alloc_impl, Target::Impl;
|
||||||
SliceU8AllocImplItem, "slice_u8_alloc", slice_u8_alloc_impl;
|
SliceU8AllocImplItem, "slice_u8_alloc", slice_u8_alloc_impl, Target::Impl;
|
||||||
ConstPtrImplItem, "const_ptr", const_ptr_impl;
|
ConstPtrImplItem, "const_ptr", const_ptr_impl, Target::Impl;
|
||||||
MutPtrImplItem, "mut_ptr", mut_ptr_impl;
|
MutPtrImplItem, "mut_ptr", mut_ptr_impl, Target::Impl;
|
||||||
I8ImplItem, "i8", i8_impl;
|
I8ImplItem, "i8", i8_impl, Target::Impl;
|
||||||
I16ImplItem, "i16", i16_impl;
|
I16ImplItem, "i16", i16_impl, Target::Impl;
|
||||||
I32ImplItem, "i32", i32_impl;
|
I32ImplItem, "i32", i32_impl, Target::Impl;
|
||||||
I64ImplItem, "i64", i64_impl;
|
I64ImplItem, "i64", i64_impl, Target::Impl;
|
||||||
I128ImplItem, "i128", i128_impl;
|
I128ImplItem, "i128", i128_impl, Target::Impl;
|
||||||
IsizeImplItem, "isize", isize_impl;
|
IsizeImplItem, "isize", isize_impl, Target::Impl;
|
||||||
U8ImplItem, "u8", u8_impl;
|
U8ImplItem, "u8", u8_impl, Target::Impl;
|
||||||
U16ImplItem, "u16", u16_impl;
|
U16ImplItem, "u16", u16_impl, Target::Impl;
|
||||||
U32ImplItem, "u32", u32_impl;
|
U32ImplItem, "u32", u32_impl, Target::Impl;
|
||||||
U64ImplItem, "u64", u64_impl;
|
U64ImplItem, "u64", u64_impl, Target::Impl;
|
||||||
U128ImplItem, "u128", u128_impl;
|
U128ImplItem, "u128", u128_impl, Target::Impl;
|
||||||
UsizeImplItem, "usize", usize_impl;
|
UsizeImplItem, "usize", usize_impl, Target::Impl;
|
||||||
F32ImplItem, "f32", f32_impl;
|
F32ImplItem, "f32", f32_impl, Target::Impl;
|
||||||
F64ImplItem, "f64", f64_impl;
|
F64ImplItem, "f64", f64_impl, Target::Impl;
|
||||||
F32RuntimeImplItem, "f32_runtime", f32_runtime_impl;
|
F32RuntimeImplItem, "f32_runtime", f32_runtime_impl, Target::Impl;
|
||||||
F64RuntimeImplItem, "f64_runtime", f64_runtime_impl;
|
F64RuntimeImplItem, "f64_runtime", f64_runtime_impl, Target::Impl;
|
||||||
|
|
||||||
SizedTraitLangItem, "sized", sized_trait;
|
SizedTraitLangItem, "sized", sized_trait, Target::Trait;
|
||||||
UnsizeTraitLangItem, "unsize", unsize_trait;
|
UnsizeTraitLangItem, "unsize", unsize_trait, Target::Trait;
|
||||||
CopyTraitLangItem, "copy", copy_trait;
|
CopyTraitLangItem, "copy", copy_trait, Target::Trait;
|
||||||
CloneTraitLangItem, "clone", clone_trait;
|
CloneTraitLangItem, "clone", clone_trait, Target::Trait;
|
||||||
SyncTraitLangItem, "sync", sync_trait;
|
SyncTraitLangItem, "sync", sync_trait, Target::Trait;
|
||||||
FreezeTraitLangItem, "freeze", freeze_trait;
|
FreezeTraitLangItem, "freeze", freeze_trait, Target::Trait;
|
||||||
|
|
||||||
DropTraitLangItem, "drop", drop_trait;
|
DropTraitLangItem, "drop", drop_trait, Target::Trait;
|
||||||
|
|
||||||
CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait;
|
CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait, Target::Trait;
|
||||||
|
|
||||||
AddTraitLangItem, "add", add_trait;
|
AddTraitLangItem, "add", add_trait, Target::Trait;
|
||||||
SubTraitLangItem, "sub", sub_trait;
|
SubTraitLangItem, "sub", sub_trait, Target::Trait;
|
||||||
MulTraitLangItem, "mul", mul_trait;
|
MulTraitLangItem, "mul", mul_trait, Target::Trait;
|
||||||
DivTraitLangItem, "div", div_trait;
|
DivTraitLangItem, "div", div_trait, Target::Trait;
|
||||||
RemTraitLangItem, "rem", rem_trait;
|
RemTraitLangItem, "rem", rem_trait, Target::Trait;
|
||||||
NegTraitLangItem, "neg", neg_trait;
|
NegTraitLangItem, "neg", neg_trait, Target::Trait;
|
||||||
NotTraitLangItem, "not", not_trait;
|
NotTraitLangItem, "not", not_trait, Target::Trait;
|
||||||
BitXorTraitLangItem, "bitxor", bitxor_trait;
|
BitXorTraitLangItem, "bitxor", bitxor_trait, Target::Trait;
|
||||||
BitAndTraitLangItem, "bitand", bitand_trait;
|
BitAndTraitLangItem, "bitand", bitand_trait, Target::Trait;
|
||||||
BitOrTraitLangItem, "bitor", bitor_trait;
|
BitOrTraitLangItem, "bitor", bitor_trait, Target::Trait;
|
||||||
ShlTraitLangItem, "shl", shl_trait;
|
ShlTraitLangItem, "shl", shl_trait, Target::Trait;
|
||||||
ShrTraitLangItem, "shr", shr_trait;
|
ShrTraitLangItem, "shr", shr_trait, Target::Trait;
|
||||||
AddAssignTraitLangItem, "add_assign", add_assign_trait;
|
AddAssignTraitLangItem, "add_assign", add_assign_trait, Target::Trait;
|
||||||
SubAssignTraitLangItem, "sub_assign", sub_assign_trait;
|
SubAssignTraitLangItem, "sub_assign", sub_assign_trait, Target::Trait;
|
||||||
MulAssignTraitLangItem, "mul_assign", mul_assign_trait;
|
MulAssignTraitLangItem, "mul_assign", mul_assign_trait, Target::Trait;
|
||||||
DivAssignTraitLangItem, "div_assign", div_assign_trait;
|
DivAssignTraitLangItem, "div_assign", div_assign_trait, Target::Trait;
|
||||||
RemAssignTraitLangItem, "rem_assign", rem_assign_trait;
|
RemAssignTraitLangItem, "rem_assign", rem_assign_trait, Target::Trait;
|
||||||
BitXorAssignTraitLangItem, "bitxor_assign", bitxor_assign_trait;
|
BitXorAssignTraitLangItem, "bitxor_assign", bitxor_assign_trait, Target::Trait;
|
||||||
BitAndAssignTraitLangItem, "bitand_assign", bitand_assign_trait;
|
BitAndAssignTraitLangItem, "bitand_assign", bitand_assign_trait, Target::Trait;
|
||||||
BitOrAssignTraitLangItem, "bitor_assign", bitor_assign_trait;
|
BitOrAssignTraitLangItem, "bitor_assign", bitor_assign_trait, Target::Trait;
|
||||||
ShlAssignTraitLangItem, "shl_assign", shl_assign_trait;
|
ShlAssignTraitLangItem, "shl_assign", shl_assign_trait, Target::Trait;
|
||||||
ShrAssignTraitLangItem, "shr_assign", shr_assign_trait;
|
ShrAssignTraitLangItem, "shr_assign", shr_assign_trait, Target::Trait;
|
||||||
IndexTraitLangItem, "index", index_trait;
|
IndexTraitLangItem, "index", index_trait, Target::Trait;
|
||||||
IndexMutTraitLangItem, "index_mut", index_mut_trait;
|
IndexMutTraitLangItem, "index_mut", index_mut_trait, Target::Trait;
|
||||||
|
|
||||||
UnsafeCellTypeLangItem, "unsafe_cell", unsafe_cell_type;
|
UnsafeCellTypeLangItem, "unsafe_cell", unsafe_cell_type, Target::Struct;
|
||||||
|
|
||||||
DerefTraitLangItem, "deref", deref_trait;
|
DerefTraitLangItem, "deref", deref_trait, Target::Trait;
|
||||||
DerefMutTraitLangItem, "deref_mut", deref_mut_trait;
|
DerefMutTraitLangItem, "deref_mut", deref_mut_trait, Target::Trait;
|
||||||
|
|
||||||
FnTraitLangItem, "fn", fn_trait;
|
FnTraitLangItem, "fn", fn_trait, Target::Trait;
|
||||||
FnMutTraitLangItem, "fn_mut", fn_mut_trait;
|
FnMutTraitLangItem, "fn_mut", fn_mut_trait, Target::Trait;
|
||||||
FnOnceTraitLangItem, "fn_once", fn_once_trait;
|
FnOnceTraitLangItem, "fn_once", fn_once_trait, Target::Trait;
|
||||||
|
|
||||||
GeneratorStateLangItem, "generator_state", gen_state;
|
GeneratorStateLangItem, "generator_state", gen_state, Target::Enum;
|
||||||
GeneratorTraitLangItem, "generator", gen_trait;
|
GeneratorTraitLangItem, "generator", gen_trait, Target::Trait;
|
||||||
|
|
||||||
EqTraitLangItem, "eq", eq_trait;
|
EqTraitLangItem, "eq", eq_trait, Target::Trait;
|
||||||
PartialOrdTraitLangItem, "partial_ord", partial_ord_trait;
|
PartialOrdTraitLangItem, "partial_ord", partial_ord_trait, Target::Trait;
|
||||||
OrdTraitLangItem, "ord", ord_trait;
|
OrdTraitLangItem, "ord", ord_trait, Target::Trait;
|
||||||
|
|
||||||
// A number of panic-related lang items. The `panic` item corresponds to
|
// A number of panic-related lang items. The `panic` item corresponds to
|
||||||
// divide-by-zero and various panic cases with `match`. The
|
// divide-by-zero and various panic cases with `match`. The
|
||||||
@ -298,68 +322,68 @@ language_item_table! {
|
|||||||
// defined to use it, but a final product is required to define 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
|
// somewhere. Additionally, there are restrictions on crates that use a weak
|
||||||
// lang item, but do not have it defined.
|
// lang item, but do not have it defined.
|
||||||
PanicFnLangItem, "panic", panic_fn;
|
PanicFnLangItem, "panic", panic_fn, Target::Fn;
|
||||||
PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn;
|
PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn, Target::Fn;
|
||||||
PanicInfoLangItem, "panic_info", panic_info;
|
PanicInfoLangItem, "panic_info", panic_info, Target::Struct;
|
||||||
PanicImplLangItem, "panic_impl", panic_impl;
|
PanicImplLangItem, "panic_impl", panic_impl, Target::Fn;
|
||||||
// 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
|
||||||
BeginPanicFnLangItem, "begin_panic", begin_panic_fn;
|
BeginPanicFnLangItem, "begin_panic", begin_panic_fn, Target::Fn;
|
||||||
|
|
||||||
ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn;
|
ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn, Target::Fn;
|
||||||
BoxFreeFnLangItem, "box_free", box_free_fn;
|
BoxFreeFnLangItem, "box_free", box_free_fn, Target::Fn;
|
||||||
DropInPlaceFnLangItem, "drop_in_place", drop_in_place_fn;
|
DropInPlaceFnLangItem, "drop_in_place", drop_in_place_fn, Target::Fn;
|
||||||
OomLangItem, "oom", oom;
|
OomLangItem, "oom", oom, Target::Fn;
|
||||||
AllocLayoutLangItem, "alloc_layout", alloc_layout;
|
AllocLayoutLangItem, "alloc_layout", alloc_layout, Target::Struct;
|
||||||
|
|
||||||
StartFnLangItem, "start", start_fn;
|
StartFnLangItem, "start", start_fn, Target::Fn;
|
||||||
|
|
||||||
EhPersonalityLangItem, "eh_personality", eh_personality;
|
EhPersonalityLangItem, "eh_personality", eh_personality, Target::Fn;
|
||||||
EhUnwindResumeLangItem, "eh_unwind_resume", eh_unwind_resume;
|
EhUnwindResumeLangItem, "eh_unwind_resume", eh_unwind_resume, Target::Fn;
|
||||||
MSVCTryFilterLangItem, "msvc_try_filter", msvc_try_filter;
|
MSVCTryFilterLangItem, "msvc_try_filter", msvc_try_filter, Target::Static;
|
||||||
|
|
||||||
OwnedBoxLangItem, "owned_box", owned_box;
|
OwnedBoxLangItem, "owned_box", owned_box, Target::Struct;
|
||||||
|
|
||||||
PhantomDataItem, "phantom_data", phantom_data;
|
PhantomDataItem, "phantom_data", phantom_data, Target::Struct;
|
||||||
|
|
||||||
ManuallyDropItem, "manually_drop", manually_drop;
|
ManuallyDropItem, "manually_drop", manually_drop, Target::Struct;
|
||||||
|
|
||||||
DebugTraitLangItem, "debug_trait", debug_trait;
|
DebugTraitLangItem, "debug_trait", debug_trait, Target::Trait;
|
||||||
|
|
||||||
// A lang item for each of the 128-bit operators we can optionally lower.
|
// A lang item for each of the 128-bit operators we can optionally lower.
|
||||||
I128AddFnLangItem, "i128_add", i128_add_fn;
|
I128AddFnLangItem, "i128_add", i128_add_fn, Target::Fn;
|
||||||
U128AddFnLangItem, "u128_add", u128_add_fn;
|
U128AddFnLangItem, "u128_add", u128_add_fn, Target::Fn;
|
||||||
I128SubFnLangItem, "i128_sub", i128_sub_fn;
|
I128SubFnLangItem, "i128_sub", i128_sub_fn, Target::Fn;
|
||||||
U128SubFnLangItem, "u128_sub", u128_sub_fn;
|
U128SubFnLangItem, "u128_sub", u128_sub_fn, Target::Fn;
|
||||||
I128MulFnLangItem, "i128_mul", i128_mul_fn;
|
I128MulFnLangItem, "i128_mul", i128_mul_fn, Target::Fn;
|
||||||
U128MulFnLangItem, "u128_mul", u128_mul_fn;
|
U128MulFnLangItem, "u128_mul", u128_mul_fn, Target::Fn;
|
||||||
I128DivFnLangItem, "i128_div", i128_div_fn;
|
I128DivFnLangItem, "i128_div", i128_div_fn, Target::Fn;
|
||||||
U128DivFnLangItem, "u128_div", u128_div_fn;
|
U128DivFnLangItem, "u128_div", u128_div_fn, Target::Fn;
|
||||||
I128RemFnLangItem, "i128_rem", i128_rem_fn;
|
I128RemFnLangItem, "i128_rem", i128_rem_fn, Target::Fn;
|
||||||
U128RemFnLangItem, "u128_rem", u128_rem_fn;
|
U128RemFnLangItem, "u128_rem", u128_rem_fn, Target::Fn;
|
||||||
I128ShlFnLangItem, "i128_shl", i128_shl_fn;
|
I128ShlFnLangItem, "i128_shl", i128_shl_fn, Target::Fn;
|
||||||
U128ShlFnLangItem, "u128_shl", u128_shl_fn;
|
U128ShlFnLangItem, "u128_shl", u128_shl_fn, Target::Fn;
|
||||||
I128ShrFnLangItem, "i128_shr", i128_shr_fn;
|
I128ShrFnLangItem, "i128_shr", i128_shr_fn, Target::Fn;
|
||||||
U128ShrFnLangItem, "u128_shr", u128_shr_fn;
|
U128ShrFnLangItem, "u128_shr", u128_shr_fn, Target::Fn;
|
||||||
// And overflow versions for the operators that are checkable.
|
// And overflow versions for the operators that are checkable.
|
||||||
// While MIR calls these Checked*, they return (T,bool), not Option<T>.
|
// While MIR calls these Checked*, they return (T,bool), not Option<T>.
|
||||||
I128AddoFnLangItem, "i128_addo", i128_addo_fn;
|
I128AddoFnLangItem, "i128_addo", i128_addo_fn, Target::Fn;
|
||||||
U128AddoFnLangItem, "u128_addo", u128_addo_fn;
|
U128AddoFnLangItem, "u128_addo", u128_addo_fn, Target::Fn;
|
||||||
I128SuboFnLangItem, "i128_subo", i128_subo_fn;
|
I128SuboFnLangItem, "i128_subo", i128_subo_fn, Target::Fn;
|
||||||
U128SuboFnLangItem, "u128_subo", u128_subo_fn;
|
U128SuboFnLangItem, "u128_subo", u128_subo_fn, Target::Fn;
|
||||||
I128MuloFnLangItem, "i128_mulo", i128_mulo_fn;
|
I128MuloFnLangItem, "i128_mulo", i128_mulo_fn, Target::Fn;
|
||||||
U128MuloFnLangItem, "u128_mulo", u128_mulo_fn;
|
U128MuloFnLangItem, "u128_mulo", u128_mulo_fn, Target::Fn;
|
||||||
I128ShloFnLangItem, "i128_shlo", i128_shlo_fn;
|
I128ShloFnLangItem, "i128_shlo", i128_shlo_fn, Target::Fn;
|
||||||
U128ShloFnLangItem, "u128_shlo", u128_shlo_fn;
|
U128ShloFnLangItem, "u128_shlo", u128_shlo_fn, Target::Fn;
|
||||||
I128ShroFnLangItem, "i128_shro", i128_shro_fn;
|
I128ShroFnLangItem, "i128_shro", i128_shro_fn, Target::Fn;
|
||||||
U128ShroFnLangItem, "u128_shro", u128_shro_fn;
|
U128ShroFnLangItem, "u128_shro", u128_shro_fn, Target::Fn;
|
||||||
|
|
||||||
// Align offset for stride != 1, must not panic.
|
// Align offset for stride != 1, must not panic.
|
||||||
AlignOffsetLangItem, "align_offset", align_offset_fn;
|
AlignOffsetLangItem, "align_offset", align_offset_fn, Target::Fn;
|
||||||
|
|
||||||
TerminationTraitLangItem, "termination", termination;
|
TerminationTraitLangItem, "termination", termination, Target::Trait;
|
||||||
|
|
||||||
Arc, "arc", arc;
|
Arc, "arc", arc, Target::Struct;
|
||||||
Rc, "rc", rc;
|
Rc, "rc", rc, Target::Struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx, 'gcx> TyCtxt<'a, 'tcx, 'gcx> {
|
impl<'a, 'tcx, 'gcx> TyCtxt<'a, 'tcx, 'gcx> {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#![feature(lang_items)]
|
#![feature(lang_items)]
|
||||||
|
|
||||||
#[lang = "panic_impl"]
|
#[lang = "arc"]
|
||||||
struct Foo; //~ ERROR E0152
|
struct Foo; //~ ERROR E0152
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
error[E0152]: duplicate lang item found: `panic_impl`.
|
error[E0152]: duplicate lang item found: `arc`.
|
||||||
--> $DIR/E0152.rs:14:1
|
--> $DIR/E0152.rs:14:1
|
||||||
|
|
|
|
||||||
LL | struct Foo; //~ ERROR E0152
|
LL | struct Foo; //~ ERROR E0152
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: first defined in crate `std`.
|
= note: first defined in crate `alloc`.
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
17
src/test/ui/error-codes/E0718.rs
Normal file
17
src/test/ui/error-codes/E0718.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(lang_items)]
|
||||||
|
|
||||||
|
// Arc is expected to be a struct, so this will error.
|
||||||
|
#[lang = "arc"]
|
||||||
|
static X: u32 = 42;
|
||||||
|
|
||||||
|
fn main() {}
|
9
src/test/ui/error-codes/E0718.stderr
Normal file
9
src/test/ui/error-codes/E0718.stderr
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
error[E0718]: `arc` language item must be applied to a struct
|
||||||
|
--> $DIR/E0718.rs:14:1
|
||||||
|
|
|
||||||
|
LL | #[lang = "arc"]
|
||||||
|
| ^^^^^^^^^^^^^^^ attribute should be applied to a struct, not a static item
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0718`.
|
18
src/test/ui/panic-handler/panic-handler-wrong-location.rs
Normal file
18
src/test/ui/panic-handler/panic-handler-wrong-location.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// compile-flags:-C panic=abort
|
||||||
|
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
#[no_mangle]
|
||||||
|
static X: u32 = 42;
|
@ -0,0 +1,11 @@
|
|||||||
|
error[E0718]: `panic_impl` language item must be applied to a function
|
||||||
|
--> $DIR/panic-handler-wrong-location.rs:16:1
|
||||||
|
|
|
||||||
|
LL | #[panic_handler]
|
||||||
|
| ^^^^^^^^^^^^^^^^ attribute should be applied to a function, not a static item
|
||||||
|
|
||||||
|
error: `#[panic_handler]` function required, but not found
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0718`.
|
Loading…
Reference in New Issue
Block a user