rust/src/librustc/middle/lang_items.rs

329 lines
12 KiB
Rust
Raw Normal View History

// Copyright 2012 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.
// Detecting language items.
//
// Language items are items that represent concepts intrinsic to the language
// itself. Examples are:
//
// * Traits that specify "kinds"; e.g. "Sync", "Send".
//
// * Traits that represent operators; e.g. "Add", "Sub", "Index".
//
// * Functions called by the compiler itself.
pub use self::LangItem::*;
use session::Session;
2013-03-26 15:38:07 -05:00
use metadata::csearch::each_lang_item;
2014-03-03 16:27:46 -06:00
use middle::ty;
rustc: Add official support for weak failure This commit is part of the ongoing libstd facade efforts (cc #13851). The compiler now recognizes some language items as "extern { fn foo(...); }" and will automatically perform the following actions: 1. The foreign function has a pre-defined name. 2. The crate and downstream crates can only be built as rlibs until a crate defines the lang item itself. 3. The actual lang item has a pre-defined name. This is essentially nicer compiler support for the hokey core-depends-on-std-failure scheme today, but it is implemented the same way. The details are a little more hidden under the covers. In addition to failure, this commit promotes the eh_personality and rust_stack_exhausted functions to official lang items. The compiler can generate calls to these functions, causing linkage errors if they are left undefined. The checking for these items is not as precise as it could be. Crates compiling with `-Z no-landing-pads` will not need the eh_personality lang item, and crates compiling with no split stacks won't need the stack exhausted lang item. For ease, however, these items are checked for presence in all final outputs of the compiler. It is quite easy to define dummy versions of the functions necessary: #[lang = "stack_exhausted"] extern fn stack_exhausted() { /* ... */ } #[lang = "eh_personality"] extern fn eh_personality() { /* ... */ } cc #11922, rust_stack_exhausted is now a lang item cc #13851, libcollections is blocked on eh_personality becoming weak
2014-05-19 11:30:09 -05:00
use middle::weak_lang_items;
use util::nodemap::FnvHashMap;
use syntax::ast;
2013-03-26 15:38:07 -05:00
use syntax::ast_util::local_def;
use syntax::attr::AttrMetaMethods;
2014-07-17 12:56:37 -05:00
use syntax::codemap::{DUMMY_SP, Span};
use syntax::parse::token::InternedString;
use syntax::visit::Visitor;
use syntax::visit;
use std::iter::Enumerate;
use std::num::FromPrimitive;
use std::slice;
// The actual lang items defined come at the end of this file in one handy table.
// So you probably just want to nip down to the end.
macro_rules! lets_do_this {
(
$( $variant:ident, $name:expr, $method:ident; )*
) => {
#[derive(Copy, FromPrimitive, PartialEq, Eq, Hash)]
pub enum LangItem {
$($variant),*
}
pub struct LanguageItems {
rustc: Add official support for weak failure This commit is part of the ongoing libstd facade efforts (cc #13851). The compiler now recognizes some language items as "extern { fn foo(...); }" and will automatically perform the following actions: 1. The foreign function has a pre-defined name. 2. The crate and downstream crates can only be built as rlibs until a crate defines the lang item itself. 3. The actual lang item has a pre-defined name. This is essentially nicer compiler support for the hokey core-depends-on-std-failure scheme today, but it is implemented the same way. The details are a little more hidden under the covers. In addition to failure, this commit promotes the eh_personality and rust_stack_exhausted functions to official lang items. The compiler can generate calls to these functions, causing linkage errors if they are left undefined. The checking for these items is not as precise as it could be. Crates compiling with `-Z no-landing-pads` will not need the eh_personality lang item, and crates compiling with no split stacks won't need the stack exhausted lang item. For ease, however, these items are checked for presence in all final outputs of the compiler. It is quite easy to define dummy versions of the functions necessary: #[lang = "stack_exhausted"] extern fn stack_exhausted() { /* ... */ } #[lang = "eh_personality"] extern fn eh_personality() { /* ... */ } cc #11922, rust_stack_exhausted is now a lang item cc #13851, libcollections is blocked on eh_personality becoming weak
2014-05-19 11:30:09 -05:00
pub items: Vec<Option<ast::DefId>>,
pub missing: Vec<LangItem>,
}
impl LanguageItems {
pub fn new() -> LanguageItems {
fn foo(_: LangItem) -> Option<ast::DefId> { None }
LanguageItems {
rustc: Add official support for weak failure This commit is part of the ongoing libstd facade efforts (cc #13851). The compiler now recognizes some language items as "extern { fn foo(...); }" and will automatically perform the following actions: 1. The foreign function has a pre-defined name. 2. The crate and downstream crates can only be built as rlibs until a crate defines the lang item itself. 3. The actual lang item has a pre-defined name. This is essentially nicer compiler support for the hokey core-depends-on-std-failure scheme today, but it is implemented the same way. The details are a little more hidden under the covers. In addition to failure, this commit promotes the eh_personality and rust_stack_exhausted functions to official lang items. The compiler can generate calls to these functions, causing linkage errors if they are left undefined. The checking for these items is not as precise as it could be. Crates compiling with `-Z no-landing-pads` will not need the eh_personality lang item, and crates compiling with no split stacks won't need the stack exhausted lang item. For ease, however, these items are checked for presence in all final outputs of the compiler. It is quite easy to define dummy versions of the functions necessary: #[lang = "stack_exhausted"] extern fn stack_exhausted() { /* ... */ } #[lang = "eh_personality"] extern fn eh_personality() { /* ... */ } cc #11922, rust_stack_exhausted is now a lang item cc #13851, libcollections is blocked on eh_personality becoming weak
2014-05-19 11:30:09 -05:00
items: vec!($(foo($variant)),*),
missing: Vec::new(),
}
}
pub fn items<'a>(&'a self) -> Enumerate<slice::Iter<'a, Option<ast::DefId>>> {
self.items.iter().enumerate()
2013-05-03 12:08:08 -05:00
}
pub fn item_name(index: uint) -> &'static str {
let item: Option<LangItem> = FromPrimitive::from_usize(index);
match item {
$( Some($variant) => $name, )*
None => "???"
}
}
pub fn require(&self, it: LangItem) -> Result<ast::DefId, String> {
match self.items[it as uint] {
Some(id) => Ok(id),
None => {
Err(format!("requires `{}` lang_item",
LanguageItems::item_name(it as uint)))
}
}
}
pub fn from_builtin_kind(&self, bound: ty::BuiltinBound)
-> Result<ast::DefId, String>
{
match bound {
ty::BoundSend => self.require(SendTraitLangItem),
ty::BoundSized => self.require(SizedTraitLangItem),
ty::BoundCopy => self.require(CopyTraitLangItem),
ty::BoundSync => self.require(SyncTraitLangItem),
}
}
2014-03-03 16:27:46 -06:00
pub fn to_builtin_kind(&self, id: ast::DefId) -> Option<ty::BuiltinBound> {
if Some(id) == self.send_trait() {
2014-03-03 16:27:46 -06:00
Some(ty::BoundSend)
} else if Some(id) == self.sized_trait() {
2014-03-03 16:27:46 -06:00
Some(ty::BoundSized)
} else if Some(id) == self.copy_trait() {
Some(ty::BoundCopy)
} else if Some(id) == self.sync_trait() {
Some(ty::BoundSync)
} else {
None
}
}
pub fn fn_trait_kind(&self, id: ast::DefId) -> Option<ty::ClosureKind> {
let def_id_kinds = [
(self.fn_trait(), ty::FnClosureKind),
(self.fn_mut_trait(), ty::FnMutClosureKind),
(self.fn_once_trait(), ty::FnOnceClosureKind),
];
2015-01-31 11:20:46 -06:00
for &(opt_def_id, kind) in &def_id_kinds {
if Some(id) == opt_def_id {
return Some(kind);
}
}
None
}
$(
2014-04-01 09:26:21 -05:00
#[allow(dead_code)]
pub fn $method(&self) -> Option<ast::DefId> {
self.items[$variant as uint]
}
)*
}
2014-03-05 08:36:01 -06:00
struct LanguageItemCollector<'a> {
2013-03-15 14:24:24 -05:00
items: LanguageItems,
2014-03-05 08:36:01 -06:00
session: &'a Session,
item_refs: FnvHashMap<&'static str, uint>,
}
impl<'a, 'v> Visitor<'v> for LanguageItemCollector<'a> {
fn visit_item(&mut self, item: &ast::Item) {
if let Some(value) = extract(&item.attrs) {
let item_index = self.item_refs.get(&value[..]).cloned();
if let Some(item_index) = item_index {
self.collect_item(item_index, local_def(item.id), item.span)
}
}
visit::walk_item(self, item);
}
}
2014-03-05 08:36:01 -06:00
impl<'a> LanguageItemCollector<'a> {
pub fn new(session: &'a Session) -> LanguageItemCollector<'a> {
let mut item_refs = FnvHashMap();
$( item_refs.insert($name, $variant as uint); )*
LanguageItemCollector {
session: session,
items: LanguageItems::new(),
item_refs: item_refs
}
}
2014-07-17 12:56:37 -05:00
pub fn collect_item(&mut self, item_index: uint,
item_def_id: ast::DefId, span: Span) {
// Check for duplicates.
match self.items.items[item_index] {
Some(original_def_id) if original_def_id != item_def_id => {
2014-07-17 12:56:37 -05:00
span_err!(self.session, span, E0152,
"duplicate entry for `{}`", LanguageItems::item_name(item_index));
}
Some(_) | None => {
// OK.
}
}
// Matched.
2014-11-06 11:25:16 -06:00
self.items.items[item_index] = Some(item_def_id);
}
pub fn collect_local_language_items(&mut self, krate: &ast::Crate) {
visit::walk_crate(self, krate);
}
pub fn collect_external_language_items(&mut self) {
2014-03-09 08:20:44 -05:00
let crate_store = &self.session.cstore;
2013-12-25 14:08:04 -06:00
crate_store.iter_crate_data(|crate_number, _crate_metadata| {
each_lang_item(crate_store, crate_number, |node_id, item_index| {
let def_id = ast::DefId { krate: crate_number, node: node_id };
2014-07-17 12:56:37 -05:00
self.collect_item(item_index, def_id, DUMMY_SP);
true
});
})
}
pub fn collect(&mut self, krate: &ast::Crate) {
self.collect_local_language_items(krate);
self.collect_external_language_items();
}
}
pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
2015-01-31 11:20:46 -06:00
for attribute in attrs {
match attribute.value_str() {
Some(ref value) if attribute.check_name("lang") => {
return Some(value.clone());
}
_ => {}
}
}
return None;
}
pub fn collect_language_items(krate: &ast::Crate,
2014-04-10 08:58:20 -05:00
session: &Session) -> LanguageItems {
let mut collector = LanguageItemCollector::new(session);
collector.collect(krate);
rustc: Add official support for weak failure This commit is part of the ongoing libstd facade efforts (cc #13851). The compiler now recognizes some language items as "extern { fn foo(...); }" and will automatically perform the following actions: 1. The foreign function has a pre-defined name. 2. The crate and downstream crates can only be built as rlibs until a crate defines the lang item itself. 3. The actual lang item has a pre-defined name. This is essentially nicer compiler support for the hokey core-depends-on-std-failure scheme today, but it is implemented the same way. The details are a little more hidden under the covers. In addition to failure, this commit promotes the eh_personality and rust_stack_exhausted functions to official lang items. The compiler can generate calls to these functions, causing linkage errors if they are left undefined. The checking for these items is not as precise as it could be. Crates compiling with `-Z no-landing-pads` will not need the eh_personality lang item, and crates compiling with no split stacks won't need the stack exhausted lang item. For ease, however, these items are checked for presence in all final outputs of the compiler. It is quite easy to define dummy versions of the functions necessary: #[lang = "stack_exhausted"] extern fn stack_exhausted() { /* ... */ } #[lang = "eh_personality"] extern fn eh_personality() { /* ... */ } cc #11922, rust_stack_exhausted is now a lang item cc #13851, libcollections is blocked on eh_personality becoming weak
2014-05-19 11:30:09 -05:00
let LanguageItemCollector { mut items, .. } = collector;
weak_lang_items::check_crate(krate, session, &mut items);
session.abort_if_errors();
2014-04-10 08:58:20 -05:00
items
}
// End of the macro
}
}
lets_do_this! {
// Variant name, Name, Method name;
SendTraitLangItem, "send", send_trait;
SizedTraitLangItem, "sized", sized_trait;
CopyTraitLangItem, "copy", copy_trait;
SyncTraitLangItem, "sync", sync_trait;
DropTraitLangItem, "drop", drop_trait;
AddTraitLangItem, "add", add_trait;
SubTraitLangItem, "sub", sub_trait;
MulTraitLangItem, "mul", mul_trait;
DivTraitLangItem, "div", div_trait;
RemTraitLangItem, "rem", rem_trait;
NegTraitLangItem, "neg", neg_trait;
NotTraitLangItem, "not", not_trait;
BitXorTraitLangItem, "bitxor", bitxor_trait;
BitAndTraitLangItem, "bitand", bitand_trait;
BitOrTraitLangItem, "bitor", bitor_trait;
ShlTraitLangItem, "shl", shl_trait;
ShrTraitLangItem, "shr", shr_trait;
IndexTraitLangItem, "index", index_trait;
IndexMutTraitLangItem, "index_mut", index_mut_trait;
2014-12-12 22:19:54 -06:00
RangeStructLangItem, "range", range_struct;
RangeFromStructLangItem, "range_from", range_from_struct;
RangeToStructLangItem, "range_to", range_to_struct;
2015-01-27 22:06:46 -06:00
RangeFullStructLangItem, "range_full", range_full_struct;
UnsafeCellTypeLangItem, "unsafe_cell", unsafe_cell_type;
2014-03-10 16:55:15 -05:00
2014-02-26 15:02:35 -06:00
DerefTraitLangItem, "deref", deref_trait;
DerefMutTraitLangItem, "deref_mut", deref_mut_trait;
FnTraitLangItem, "fn", fn_trait;
FnMutTraitLangItem, "fn_mut", fn_mut_trait;
FnOnceTraitLangItem, "fn_once", fn_once_trait;
EqTraitLangItem, "eq", eq_trait;
OrdTraitLangItem, "ord", ord_trait;
StrEqFnLangItem, "str_eq", str_eq_fn;
rustc: Add official support for weak failure This commit is part of the ongoing libstd facade efforts (cc #13851). The compiler now recognizes some language items as "extern { fn foo(...); }" and will automatically perform the following actions: 1. The foreign function has a pre-defined name. 2. The crate and downstream crates can only be built as rlibs until a crate defines the lang item itself. 3. The actual lang item has a pre-defined name. This is essentially nicer compiler support for the hokey core-depends-on-std-failure scheme today, but it is implemented the same way. The details are a little more hidden under the covers. In addition to failure, this commit promotes the eh_personality and rust_stack_exhausted functions to official lang items. The compiler can generate calls to these functions, causing linkage errors if they are left undefined. The checking for these items is not as precise as it could be. Crates compiling with `-Z no-landing-pads` will not need the eh_personality lang item, and crates compiling with no split stacks won't need the stack exhausted lang item. For ease, however, these items are checked for presence in all final outputs of the compiler. It is quite easy to define dummy versions of the functions necessary: #[lang = "stack_exhausted"] extern fn stack_exhausted() { /* ... */ } #[lang = "eh_personality"] extern fn eh_personality() { /* ... */ } cc #11922, rust_stack_exhausted is now a lang item cc #13851, libcollections is blocked on eh_personality becoming weak
2014-05-19 11:30:09 -05:00
// 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.
rustc: Add official support for weak failure This commit is part of the ongoing libstd facade efforts (cc #13851). The compiler now recognizes some language items as "extern { fn foo(...); }" and will automatically perform the following actions: 1. The foreign function has a pre-defined name. 2. The crate and downstream crates can only be built as rlibs until a crate defines the lang item itself. 3. The actual lang item has a pre-defined name. This is essentially nicer compiler support for the hokey core-depends-on-std-failure scheme today, but it is implemented the same way. The details are a little more hidden under the covers. In addition to failure, this commit promotes the eh_personality and rust_stack_exhausted functions to official lang items. The compiler can generate calls to these functions, causing linkage errors if they are left undefined. The checking for these items is not as precise as it could be. Crates compiling with `-Z no-landing-pads` will not need the eh_personality lang item, and crates compiling with no split stacks won't need the stack exhausted lang item. For ease, however, these items are checked for presence in all final outputs of the compiler. It is quite easy to define dummy versions of the functions necessary: #[lang = "stack_exhausted"] extern fn stack_exhausted() { /* ... */ } #[lang = "eh_personality"] extern fn eh_personality() { /* ... */ } cc #11922, rust_stack_exhausted is now a lang item cc #13851, libcollections is blocked on eh_personality becoming weak
2014-05-19 11:30:09 -05:00
//
// The `begin_unwind` lang item has a predefined symbol name and is sort of
// a "weak lang item" 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.
PanicFnLangItem, "panic", panic_fn;
PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn;
PanicFmtLangItem, "panic_fmt", panic_fmt;
rustc: Add official support for weak failure This commit is part of the ongoing libstd facade efforts (cc #13851). The compiler now recognizes some language items as "extern { fn foo(...); }" and will automatically perform the following actions: 1. The foreign function has a pre-defined name. 2. The crate and downstream crates can only be built as rlibs until a crate defines the lang item itself. 3. The actual lang item has a pre-defined name. This is essentially nicer compiler support for the hokey core-depends-on-std-failure scheme today, but it is implemented the same way. The details are a little more hidden under the covers. In addition to failure, this commit promotes the eh_personality and rust_stack_exhausted functions to official lang items. The compiler can generate calls to these functions, causing linkage errors if they are left undefined. The checking for these items is not as precise as it could be. Crates compiling with `-Z no-landing-pads` will not need the eh_personality lang item, and crates compiling with no split stacks won't need the stack exhausted lang item. For ease, however, these items are checked for presence in all final outputs of the compiler. It is quite easy to define dummy versions of the functions necessary: #[lang = "stack_exhausted"] extern fn stack_exhausted() { /* ... */ } #[lang = "eh_personality"] extern fn eh_personality() { /* ... */ } cc #11922, rust_stack_exhausted is now a lang item cc #13851, libcollections is blocked on eh_personality becoming weak
2014-05-19 11:30:09 -05:00
ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn;
ExchangeFreeFnLangItem, "exchange_free", exchange_free_fn;
StrDupUniqFnLangItem, "strdup_uniq", strdup_uniq_fn;
StartFnLangItem, "start", start_fn;
TyDescStructLangItem, "ty_desc", ty_desc;
OpaqueStructLangItem, "opaque", opaque;
rustc: Add official support for weak failure This commit is part of the ongoing libstd facade efforts (cc #13851). The compiler now recognizes some language items as "extern { fn foo(...); }" and will automatically perform the following actions: 1. The foreign function has a pre-defined name. 2. The crate and downstream crates can only be built as rlibs until a crate defines the lang item itself. 3. The actual lang item has a pre-defined name. This is essentially nicer compiler support for the hokey core-depends-on-std-failure scheme today, but it is implemented the same way. The details are a little more hidden under the covers. In addition to failure, this commit promotes the eh_personality and rust_stack_exhausted functions to official lang items. The compiler can generate calls to these functions, causing linkage errors if they are left undefined. The checking for these items is not as precise as it could be. Crates compiling with `-Z no-landing-pads` will not need the eh_personality lang item, and crates compiling with no split stacks won't need the stack exhausted lang item. For ease, however, these items are checked for presence in all final outputs of the compiler. It is quite easy to define dummy versions of the functions necessary: #[lang = "stack_exhausted"] extern fn stack_exhausted() { /* ... */ } #[lang = "eh_personality"] extern fn eh_personality() { /* ... */ } cc #11922, rust_stack_exhausted is now a lang item cc #13851, libcollections is blocked on eh_personality becoming weak
2014-05-19 11:30:09 -05:00
EhPersonalityLangItem, "eh_personality", eh_personality;
ExchangeHeapLangItem, "exchange_heap", exchange_heap;
OwnedBoxLangItem, "owned_box", owned_box;
PhantomFnItem, "phantom_fn", phantom_fn;
PhantomDataItem, "phantom_data", phantom_data;
// Deprecated:
CovariantTypeItem, "covariant_type", covariant_type;
ContravariantTypeItem, "contravariant_type", contravariant_type;
InvariantTypeItem, "invariant_type", invariant_type;
CovariantLifetimeItem, "covariant_lifetime", covariant_lifetime;
ContravariantLifetimeItem, "contravariant_lifetime", contravariant_lifetime;
InvariantLifetimeItem, "invariant_lifetime", invariant_lifetime;
NoCopyItem, "no_copy_bound", no_copy_bound;
ManagedItem, "managed_bound", managed_bound;
rustc: Add official support for weak failure This commit is part of the ongoing libstd facade efforts (cc #13851). The compiler now recognizes some language items as "extern { fn foo(...); }" and will automatically perform the following actions: 1. The foreign function has a pre-defined name. 2. The crate and downstream crates can only be built as rlibs until a crate defines the lang item itself. 3. The actual lang item has a pre-defined name. This is essentially nicer compiler support for the hokey core-depends-on-std-failure scheme today, but it is implemented the same way. The details are a little more hidden under the covers. In addition to failure, this commit promotes the eh_personality and rust_stack_exhausted functions to official lang items. The compiler can generate calls to these functions, causing linkage errors if they are left undefined. The checking for these items is not as precise as it could be. Crates compiling with `-Z no-landing-pads` will not need the eh_personality lang item, and crates compiling with no split stacks won't need the stack exhausted lang item. For ease, however, these items are checked for presence in all final outputs of the compiler. It is quite easy to define dummy versions of the functions necessary: #[lang = "stack_exhausted"] extern fn stack_exhausted() { /* ... */ } #[lang = "eh_personality"] extern fn eh_personality() { /* ... */ } cc #11922, rust_stack_exhausted is now a lang item cc #13851, libcollections is blocked on eh_personality becoming weak
2014-05-19 11:30:09 -05:00
NonZeroItem, "non_zero", non_zero;
rustc: Add official support for weak failure This commit is part of the ongoing libstd facade efforts (cc #13851). The compiler now recognizes some language items as "extern { fn foo(...); }" and will automatically perform the following actions: 1. The foreign function has a pre-defined name. 2. The crate and downstream crates can only be built as rlibs until a crate defines the lang item itself. 3. The actual lang item has a pre-defined name. This is essentially nicer compiler support for the hokey core-depends-on-std-failure scheme today, but it is implemented the same way. The details are a little more hidden under the covers. In addition to failure, this commit promotes the eh_personality and rust_stack_exhausted functions to official lang items. The compiler can generate calls to these functions, causing linkage errors if they are left undefined. The checking for these items is not as precise as it could be. Crates compiling with `-Z no-landing-pads` will not need the eh_personality lang item, and crates compiling with no split stacks won't need the stack exhausted lang item. For ease, however, these items are checked for presence in all final outputs of the compiler. It is quite easy to define dummy versions of the functions necessary: #[lang = "stack_exhausted"] extern fn stack_exhausted() { /* ... */ } #[lang = "eh_personality"] extern fn eh_personality() { /* ... */ } cc #11922, rust_stack_exhausted is now a lang item cc #13851, libcollections is blocked on eh_personality becoming weak
2014-05-19 11:30:09 -05:00
StackExhaustedLangItem, "stack_exhausted", stack_exhausted;
DebugTraitLangItem, "debug_trait", debug_trait;
}