Skip to content

Rename begin_unwind lang item and core function #17428

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 25, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/doc/guide-unsafe.md
Original file line number Diff line number Diff line change
Expand Up @@ -573,8 +573,8 @@ pub extern fn dot_product(a: *const u32, a_len: u32,
return ret;
}

#[lang = "begin_unwind"]
extern fn begin_unwind(args: &core::fmt::Arguments,
#[lang = "fail_fmt"]
extern fn fail_fmt(args: &core::fmt::Arguments,
file: &str,
line: uint) -> ! {
loop {}
Expand All @@ -587,8 +587,8 @@ extern fn begin_unwind(args: &core::fmt::Arguments,
```

Note that there is one extra lang item here which differs from the examples
above, `begin_unwind`. This must be defined by consumers of libcore because the
core library declares failure, but it does not define it. The `begin_unwind`
above, `fail_fmt`. This must be defined by consumers of libcore because the
core library declares failure, but it does not define it. The `fail_fmt`
lang item is this crate's definition of failure, and it must be guaranteed to
never return.

Expand Down Expand Up @@ -706,7 +706,7 @@ Other features provided by lang items include:
`==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all
marked with lang items; those specific four are `eq`, `ord`,
`deref`, and `add` respectively.
- stack unwinding and general failure; the `eh_personality`, `fail_`
- stack unwinding and general failure; the `eh_personality`, `fail`
and `fail_bounds_checks` lang items.
- the traits in `std::kinds` used to indicate types that satisfy
various kinds; lang items `send`, `sync` and `copy`.
Expand Down
41 changes: 32 additions & 9 deletions src/libcore/failure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
//! interface for failure is:
//!
//! ```ignore
//! fn begin_unwind(fmt: &fmt::Arguments, &(&'static str, uint)) -> !;
//! fn fail_impl(fmt: &fmt::Arguments, &(&'static str, uint)) -> !;
//! ```
//!
//! This definition allows for failing with any general message, but it does not
Expand All @@ -33,13 +33,28 @@
use fmt;
use intrinsics;

// NOTE: remove after next snapshot
#[cfg(stage0)]
#[cold] #[inline(never)] // this is the slow path, always
#[lang="fail_"]
fn fail_(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
let (expr, file, line) = *expr_file_line;
let ref file_line = (file, line);
format_args!(|args| -> () {
begin_unwind(args, file_line);
fail_fmt(args, file_line);
}, "{}", expr);

unsafe { intrinsics::abort() }
}

#[cfg(not(stage0))]
#[cold] #[inline(never)] // this is the slow path, always
#[lang="fail"]
fn fail(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
let (expr, file, line) = *expr_file_line;
let ref file_line = (file, line);
format_args!(|args| -> () {
fail_fmt(args, file_line);
}, "{}", expr);

unsafe { intrinsics::abort() }
Expand All @@ -50,25 +65,33 @@ fn fail_(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
fn fail_bounds_check(file_line: &(&'static str, uint),
index: uint, len: uint) -> ! {
format_args!(|args| -> () {
begin_unwind(args, file_line);
fail_fmt(args, file_line);
}, "index out of bounds: the len is {} but the index is {}", len, index);
unsafe { intrinsics::abort() }
}

#[cold] #[inline(never)]
pub fn begin_unwind_string(msg: &str, file: &(&'static str, uint)) -> ! {
format_args!(|fmt| begin_unwind(fmt, file), "{}", msg)
pub fn fail_str(msg: &str, file: &(&'static str, uint)) -> ! {
format_args!(|fmt| fail_fmt(fmt, file), "{}", msg)
}

#[cold] #[inline(never)]
pub fn begin_unwind(fmt: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
pub fn fail_fmt(fmt: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
#[allow(ctypes)]
extern {

// NOTE: remove after next snapshot
#[cfg(stage0)]
#[lang = "begin_unwind"]
fn begin_unwind(fmt: &fmt::Arguments, file: &'static str,
fn fail_impl(fmt: &fmt::Arguments, file: &'static str,
line: uint) -> !;

#[cfg(not(stage0))]
#[lang = "fail_fmt"]
fn fail_impl(fmt: &fmt::Arguments, file: &'static str,
line: uint) -> !;

}
let (file, line) = *file_line;
unsafe { begin_unwind(fmt, file, line) }
unsafe { fail_impl(fmt, file, line) }
}

4 changes: 2 additions & 2 deletions src/libcore/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ macro_rules! fail(
);
($msg:expr) => ({
static _FILE_LINE: (&'static str, uint) = (file!(), line!());
::core::failure::begin_unwind_string($msg, &_FILE_LINE)
::core::failure::fail_str($msg, &_FILE_LINE)
});
($fmt:expr, $($arg:tt)*) => ({
// a closure can't have return type !, so we need a full
Expand All @@ -40,7 +40,7 @@ macro_rules! fail(
#[inline(always)]
fn _run_fmt(fmt: &::std::fmt::Arguments) -> ! {
static _FILE_LINE: (&'static str, uint) = (file!(), line!());
::core::failure::begin_unwind(fmt, &_FILE_LINE)
::core::failure::fail_fmt(fmt, &_FILE_LINE)
}
format_args!(_run_fmt, $fmt, $($arg)*)
});
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ lets_do_this! {

StrEqFnLangItem, "str_eq", str_eq_fn;

// A number of failure-related lang items. The `fail_` item corresponds to
// A number of failure-related lang items. The `fail` item corresponds to
// divide-by-zero and various failure cases with `match`. The
// `fail_bounds_check` item is for indexing arrays.
//
Expand All @@ -273,9 +273,9 @@ lets_do_this! {
// 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.
FailFnLangItem, "fail_", fail_fn;
FailFnLangItem, "fail", fail_fn;
FailBoundsCheckFnLangItem, "fail_bounds_check", fail_bounds_check_fn;
BeginUnwindLangItem, "begin_unwind", begin_unwind;
FailFmtLangItem, "fail_fmt", fail_fmt;

ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn;
ExchangeFreeFnLangItem, "exchange_free", exchange_free_fn;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/weak_lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
) )

weak_lang_items!(
begin_unwind, BeginUnwindLangItem, rust_begin_unwind;
fail_fmt, FailFmtLangItem, rust_begin_unwind;
stack_exhausted, StackExhaustedLangItem, rust_stack_exhausted;
eh_personality, EhPersonalityLangItem, rust_eh_personality;
)
11 changes: 10 additions & 1 deletion src/librustrt/unwind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,16 @@ pub mod eabi {
}

// Entry point of failure from the libcore crate
#[cfg(not(test))]
#[cfg(not(test), not(stage0))]
#[lang = "fail_fmt"]
pub extern fn rust_begin_unwind(msg: &fmt::Arguments,
file: &'static str, line: uint) -> ! {
begin_unwind_fmt(msg, &(file, line))
}

//
// Entry point of failure from the libcore crate
#[cfg(stage0, not(test))]
#[lang = "begin_unwind"]
pub extern fn rust_begin_unwind(msg: &fmt::Arguments,
file: &'static str, line: uint) -> ! {
Expand Down
2 changes: 1 addition & 1 deletion src/test/auxiliary/lang-item-public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#![no_std]
#![feature(lang_items)]

#[lang="fail_"]
#[lang="fail"]
fn fail(_: &(&'static str, &'static str, uint)) -> ! { loop {} }

#[lang = "stack_exhausted"]
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/lint-dead-code-1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,5 +104,5 @@ fn g() { h(); }
fn h() {}

// Similarly, lang items are live
#[lang="fail_"]
#[lang="fail"]
fn fail(_: *const u8, _: *const u8, _: uint) -> ! { loop {} }
2 changes: 1 addition & 1 deletion src/test/compile-fail/weak-lang-item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// except according to those terms.

// aux-build:weak-lang-items.rs
// error-pattern: language item required, but not found: `begin_unwind`
// error-pattern: language item required, but not found: `fail_fmt`
// error-pattern: language item required, but not found: `stack_exhausted`
// error-pattern: language item required, but not found: `eh_personality`

Expand Down