diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index 6a7aea7f1c27e..bac619fd4a30d 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -19,6 +19,7 @@ sugar for dynamic allocations via `malloc` and `free`: #![feature(lang_items, box_syntax, start, libc, core_intrinsics)] #![no_std] use core::intrinsics; +use core::panic::PanicInfo; extern crate libc; @@ -50,7 +51,7 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { } #[lang = "eh_personality"] extern fn rust_eh_personality() {} -#[lang = "panic_fmt"] extern fn rust_begin_panic() -> ! { unsafe { intrinsics::abort() } } +#[lang = "panic_impl"] extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } } #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {} #[no_mangle] pub extern fn rust_eh_register_frames () {} #[no_mangle] pub extern fn rust_eh_unregister_frames () {} @@ -110,6 +111,7 @@ in the same format as C: #![feature(start)] #![no_std] use core::intrinsics; +use core::panic::PanicInfo; // Pull in the system libc library for what crt0.o likely requires. extern crate libc; @@ -134,12 +136,9 @@ pub extern fn rust_eh_personality() { pub extern fn rust_eh_unwind_resume() { } -#[lang = "panic_fmt"] +#[lang = "panic_impl"] #[no_mangle] -pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, - _file: &'static str, - _line: u32, - _column: u32) -> ! { +pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } } ``` @@ -155,6 +154,7 @@ compiler's name mangling too: #![no_std] #![no_main] use core::intrinsics; +use core::panic::PanicInfo; // Pull in the system libc library for what crt0.o likely requires. extern crate libc; @@ -179,12 +179,9 @@ pub extern fn rust_eh_personality() { pub extern fn rust_eh_unwind_resume() { } -#[lang = "panic_fmt"] +#[lang = "panic_impl"] #[no_mangle] -pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, - _file: &'static str, - _line: u32, - _column: u32) -> ! { +pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } } ``` @@ -215,7 +212,7 @@ called. The language item's name is `eh_personality`. The second function, `rust_begin_panic`, is also used by the failure mechanisms of the compiler. When a panic happens, this controls the message that's displayed on -the screen. While the language item's name is `panic_fmt`, the symbol name is +the screen. While the language item's name is `panic_impl`, the symbol name is `rust_begin_panic`. A third function, `rust_eh_unwind_resume`, is also needed if the `custom_unwind_resume` @@ -259,8 +256,8 @@ the source code. - `msvc_try_filter`: `libpanic_unwind/seh.rs` (SEH) - `panic`: `libcore/panicking.rs` - `panic_bounds_check`: `libcore/panicking.rs` - - `panic_fmt`: `libcore/panicking.rs` - - `panic_fmt`: `libstd/panicking.rs` + - `panic_impl`: `libcore/panicking.rs` + - `panic_impl`: `libstd/panicking.rs` - Allocations - `owned_box`: `liballoc/boxed.rs` - `exchange_malloc`: `liballoc/heap.rs` diff --git a/src/doc/unstable-book/src/language-features/used.md b/src/doc/unstable-book/src/language-features/used.md index 75a8b2774f422..c3b7f2e41e15b 100644 --- a/src/doc/unstable-book/src/language-features/used.md +++ b/src/doc/unstable-book/src/language-features/used.md @@ -87,11 +87,13 @@ This condition can be met using `#[used]` and `#[link_section]` plus a linker script. ``` rust,ignore -#![feature(lang_items)] +#![feature(panic_implementation)] #![feature(used)] #![no_main] #![no_std] +use core::panic::PanicInfo; + extern "C" fn reset_handler() -> ! { loop {} } @@ -100,8 +102,10 @@ extern "C" fn reset_handler() -> ! { #[used] static RESET_HANDLER: extern "C" fn() -> ! = reset_handler; -#[lang = "panic_fmt"] -fn panic_fmt() {} +#[panic_implementation] +fn panic_impl(info: &PanicInfo) -> ! { + loop {} +} ``` ``` text diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 32cf31231c301..e6ab64a331272 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -41,7 +41,7 @@ //! dictate the panic message, the file at which panic was invoked, and the //! line and column inside the file. It is up to consumers of this core //! library to define this panic function; it is only required to never -//! return. This requires a `lang` attribute named `panic_fmt`. +//! return. This requires a `lang` attribute named `panic_impl`. //! //! * `rust_eh_personality` - is used by the failure mechanisms of the //! compiler. This is often mapped to GCC's personality function, but crates diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs index 27ec4aaac75de..37ae05309af1d 100644 --- a/src/libcore/panic.rs +++ b/src/libcore/panic.rs @@ -35,6 +35,7 @@ use fmt; /// /// panic!("Normal panic"); /// ``` +#[cfg_attr(not(stage0), lang = "panic_info")] #[stable(feature = "panic_hooks", since = "1.10.0")] #[derive(Debug)] pub struct PanicInfo<'a> { @@ -53,7 +54,8 @@ impl<'a> PanicInfo<'a> { pub fn internal_constructor(message: Option<&'a fmt::Arguments<'a>>, location: Location<'a>) -> Self { - PanicInfo { payload: &(), location, message } + struct NoPayload; + PanicInfo { payload: &NoPayload, location, message } } #[doc(hidden)] @@ -121,7 +123,7 @@ impl<'a> PanicInfo<'a> { #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn location(&self) -> Option<&Location> { // NOTE: If this is changed to sometimes return None, - // deal with that case in std::panicking::default_hook. + // deal with that case in std::panicking::default_hook and std::panicking::begin_panic_fmt. Some(&self.location) } } diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 6b3dc75af4633..0d4f8d1141e73 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -37,6 +37,8 @@ issue = "0")] use fmt; +#[cfg(not(stage0))] +use panic::{Location, PanicInfo}; #[cold] #[inline(never)] // this is the slow path, always #[lang = "panic"] @@ -59,6 +61,7 @@ fn panic_bounds_check(file_line_col: &(&'static str, u32, u32), len, index), file_line_col) } +#[cfg(stage0)] #[cold] #[inline(never)] pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! { #[allow(improper_ctypes)] @@ -70,3 +73,21 @@ pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) let (file, line, col) = *file_line_col; unsafe { panic_impl(fmt, file, line, col) } } + +#[cfg(not(stage0))] +#[cold] #[inline(never)] +pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! { + // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call + #[allow(improper_ctypes)] // PanicInfo contains a trait object which is not FFI safe + extern "Rust" { + #[lang = "panic_impl"] + fn panic_impl(pi: &PanicInfo) -> !; + } + + let (file, line, col) = *file_line_col; + let pi = PanicInfo::internal_constructor( + Some(&fmt), + Location::internal_constructor(file, line, col), + ); + unsafe { panic_impl(&pi) } +} diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 2662e70999196..61f05ca347358 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -637,8 +637,8 @@ Erroneous code example: ```compile_fail,E0152 #![feature(lang_items)] -#[lang = "panic_fmt"] -struct Foo; // error: duplicate lang item found: `panic_fmt` +#[lang = "panic_impl"] +struct Foo; // error: duplicate lang item found: `panic_impl` ``` Lang items are already implemented in the standard library. Unless you are @@ -824,7 +824,7 @@ A list of available external lang items is available in #![feature(lang_items)] extern "C" { - #[lang = "panic_fmt"] // ok! + #[lang = "panic_impl"] // ok! fn cake(); } ``` diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index e3b2078971439..7ebc0d4a4de5a 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -284,7 +284,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt, id: ast::NodeId, attrs: &[ast::Attribute]) -> bool { - if attr::contains_name(attrs, "lang") { + if attr::contains_name(attrs, "lang") || attr::contains_name(attrs, "panic_implementation") { return true; } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index d70f994e87ba7..fe676919a7d14 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -185,6 +185,8 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { if let Some(value) = attribute.value_str() { return Some((value, attribute.span)); } + } else if attribute.check_name("panic_implementation") { + return Some((Symbol::intern("panic_impl"), attribute.span)) } } @@ -299,7 +301,8 @@ language_item_table! { // 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; + PanicInfoLangItem, "panic_info", panic_info; + PanicImplLangItem, "panic_impl", panic_impl; ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn; BoxFreeFnLangItem, "box_free", box_free_fn; diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index 42e4d3861bae3..3c2ea047218a7 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -148,7 +148,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { ) } weak_lang_items! { - panic_fmt, PanicFmtLangItem, rust_begin_unwind; + panic_impl, PanicImplLangItem, rust_begin_unwind; eh_personality, EhPersonalityLangItem, rust_eh_personality; eh_unwind_resume, EhUnwindResumeLangItem, rust_eh_unwind_resume; oom, OomLangItem, rust_oom; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 90b974fb972c0..c2c71d90f0674 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -96,7 +96,7 @@ use rustc::middle::region; use rustc::mir::interpret::{GlobalId}; use rustc::ty::subst::{UnpackedKind, Subst, Substs}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; -use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate}; +use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind}; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::fold::TypeFoldable; use rustc::ty::maps::Providers; @@ -130,7 +130,7 @@ use syntax_pos::{self, BytePos, Span, MultiSpan}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::map::Node; -use rustc::hir::{self, PatKind}; +use rustc::hir::{self, PatKind, Item_}; use rustc::middle::lang_items; mod autoderef; @@ -1129,6 +1129,60 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, } } + // Check that a function marked as `#[panic_implementation]` has signature `fn(&PanicInfo) -> !` + if let Some(panic_impl_did) = fcx.tcx.lang_items().panic_impl() { + if panic_impl_did == fn_hir_id.owner_def_id() { + if let Some(panic_info_did) = fcx.tcx.lang_items().panic_info() { + if declared_ret_ty.sty != ty::TyNever { + fcx.tcx.sess.span_err( + decl.output.span(), + "return type should be `!`", + ); + } + + let inputs = fn_sig.inputs(); + let span = fcx.tcx.hir.span(fn_id); + if inputs.len() == 1 { + let arg_is_panic_info = match inputs[0].sty { + ty::TyRef(region, ty, mutbl) => match ty.sty { + ty::TyAdt(ref adt, _) => { + adt.did == panic_info_did && + mutbl == hir::Mutability::MutImmutable && + *region != RegionKind::ReStatic + }, + _ => false, + }, + _ => false, + }; + + if !arg_is_panic_info { + fcx.tcx.sess.span_err( + decl.inputs[0].span, + "argument should be `&PanicInfo`", + ); + } + + if let Node::NodeItem(item) = fcx.tcx.hir.get(fn_id) { + if let Item_::ItemFn(_, _, _, _, ref generics, _) = item.node { + if !generics.params.is_empty() { + fcx.tcx.sess.span_err( + span, + "`#[panic_implementation]` function should have no type \ + parameters", + ); + } + } + } + } else { + fcx.tcx.sess.span_err(span, "function should have one argument"); + } + } else { + fcx.tcx.sess.err("language item required, but not found: `panic_info`"); + } + } + + } + (fcx, gen_ty) } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index f7d06852f2793..c576245edb755 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -317,6 +317,8 @@ #![cfg_attr(windows, feature(used))] #![feature(doc_alias)] #![feature(float_internals)] +#![feature(panic_info_message)] +#![cfg_attr(not(stage0), feature(panic_implementation))] #![default_lib_allocator] diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 403056240bf57..0808efa2ecea5 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -319,8 +319,8 @@ pub fn panicking() -> bool { /// Entry point of panic from the libcore crate. #[cfg(not(test))] +#[cfg(stage0)] #[lang = "panic_fmt"] -#[unwind(allowed)] pub extern fn rust_begin_panic(msg: fmt::Arguments, file: &'static str, line: u32, @@ -328,59 +328,107 @@ pub extern fn rust_begin_panic(msg: fmt::Arguments, begin_panic_fmt(&msg, &(file, line, col)) } +/// Entry point of panic from the libcore crate. +#[cfg(not(test))] +#[cfg(not(stage0))] +#[panic_implementation] +#[unwind(allowed)] +pub fn rust_begin_panic(info: &PanicInfo) -> ! { + continue_panic_fmt(&info) +} + /// The entry point for panicking with a formatted message. /// /// This is designed to reduce the amount of code required at the call /// site as much as possible (so that `panic!()` has as low an impact /// on (e.g.) the inlining of other functions as possible), by moving /// the actual formatting into this shared place. +#[cfg(stage0)] #[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "0")] #[inline(never)] #[cold] pub fn begin_panic_fmt(msg: &fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! { - use fmt::Write; - // We do two allocations here, unfortunately. But (a) they're // required with the current scheme, and (b) we don't handle // panic + OOM properly anyway (see comment in begin_panic // below). rust_panic_with_hook(&mut PanicPayload::new(msg), Some(msg), file_line_col); +} + +// NOTE(stage0) move into `continue_panic_fmt` on next stage0 update +struct PanicPayload<'a> { + inner: &'a fmt::Arguments<'a>, + string: Option, +} - struct PanicPayload<'a> { - inner: &'a fmt::Arguments<'a>, - string: Option, +impl<'a> PanicPayload<'a> { + fn new(inner: &'a fmt::Arguments<'a>) -> PanicPayload<'a> { + PanicPayload { inner, string: None } } - impl<'a> PanicPayload<'a> { - fn new(inner: &'a fmt::Arguments<'a>) -> PanicPayload<'a> { - PanicPayload { inner, string: None } - } + fn fill(&mut self) -> &mut String { + use fmt::Write; - fn fill(&mut self) -> &mut String { - let inner = self.inner; - self.string.get_or_insert_with(|| { - let mut s = String::new(); - drop(s.write_fmt(*inner)); - s - }) - } + let inner = self.inner; + self.string.get_or_insert_with(|| { + let mut s = String::new(); + drop(s.write_fmt(*inner)); + s + }) } +} - unsafe impl<'a> BoxMeUp for PanicPayload<'a> { - fn box_me_up(&mut self) -> *mut (Any + Send) { - let contents = mem::replace(self.fill(), String::new()); - Box::into_raw(Box::new(contents)) - } +unsafe impl<'a> BoxMeUp for PanicPayload<'a> { + fn box_me_up(&mut self) -> *mut (Any + Send) { + let contents = mem::replace(self.fill(), String::new()); + Box::into_raw(Box::new(contents)) + } - fn get(&mut self) -> &(Any + Send) { - self.fill() - } + fn get(&mut self) -> &(Any + Send) { + self.fill() } } +/// The entry point for panicking with a formatted message. +/// +/// This is designed to reduce the amount of code required at the call +/// site as much as possible (so that `panic!()` has as low an impact +/// on (e.g.) the inlining of other functions as possible), by moving +/// the actual formatting into this shared place. +#[cfg(not(stage0))] +#[unstable(feature = "libstd_sys_internals", + reason = "used by the panic! macro", + issue = "0")] +#[inline(never)] #[cold] +pub fn begin_panic_fmt(msg: &fmt::Arguments, + file_line_col: &(&'static str, u32, u32)) -> ! { + let (file, line, col) = *file_line_col; + let info = PanicInfo::internal_constructor( + Some(msg), + Location::internal_constructor(file, line, col), + ); + continue_panic_fmt(&info) +} + +#[cfg(not(stage0))] +fn continue_panic_fmt(info: &PanicInfo) -> ! { + // We do two allocations here, unfortunately. But (a) they're + // required with the current scheme, and (b) we don't handle + // panic + OOM properly anyway (see comment in begin_panic + // below). + + let loc = info.location().unwrap(); // The current implementation always returns Some + let msg = info.message().unwrap(); // The current implementation always returns Some + let file_line_col = (loc.file(), loc.line(), loc.column()); + rust_panic_with_hook( + &mut PanicPayload::new(msg), + info.message(), + &file_line_col); +} + /// This is the entry point of panicking for panic!() and assert!(). #[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", @@ -431,7 +479,7 @@ pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u3 /// abort or unwind. fn rust_panic_with_hook(payload: &mut BoxMeUp, message: Option<&fmt::Arguments>, - file_line_col: &(&'static str, u32, u32)) -> ! { + file_line_col: &(&str, u32, u32)) -> ! { let (file, line, col) = *file_line_col; let panics = update_panic_count(1); diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9b84713b0f90f..7349745fefea1 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -475,6 +475,9 @@ declare_features! ( // 'a: { break 'a; } (active, label_break_value, "1.28.0", Some(48594), None), + + // #[panic_implementation] + (active, panic_implementation, "1.28.0", Some(44489), None), ); declare_features! ( @@ -1069,6 +1072,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG "attribute is currently unstable", cfg_fn!(wasm_custom_section))), + // RFC 2070 + ("panic_implementation", Normal, Gated(Stability::Unstable, + "panic_implementation", + "#[panic_implementation] is an unstable feature", + cfg_fn!(panic_implementation))), + // Crate level attributes ("crate_name", CrateLevel, Ungated), ("crate_type", CrateLevel, Ungated), diff --git a/src/test/compile-fail/auxiliary/some-panic-impl.rs b/src/test/compile-fail/auxiliary/some-panic-impl.rs new file mode 100644 index 0000000000000..db16ac325ac59 --- /dev/null +++ b/src/test/compile-fail/auxiliary/some-panic-impl.rs @@ -0,0 +1,22 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![feature(panic_implementation)] +#![no_std] + +use core::panic::PanicInfo; + +#[panic_implementation] +fn panic(info: &PanicInfo) -> ! { + loop {} +} diff --git a/src/test/compile-fail/duplicate_entry_error.rs b/src/test/compile-fail/duplicate_entry_error.rs index 485519e8c3d7e..176aa7cca5357 100644 --- a/src/test/compile-fail/duplicate_entry_error.rs +++ b/src/test/compile-fail/duplicate_entry_error.rs @@ -14,9 +14,11 @@ #![feature(lang_items)] -#[lang = "panic_fmt"] -fn panic_fmt() -> ! { -//~^ ERROR: duplicate lang item found: `panic_fmt`. +use std::panic::PanicInfo; + +#[lang = "panic_impl"] +fn panic_impl(info: &PanicInfo) -> ! { +//~^ ERROR: duplicate lang item found: `panic_impl`. loop {} } diff --git a/src/test/compile-fail/feature-gate-panic-implementation.rs b/src/test/compile-fail/feature-gate-panic-implementation.rs new file mode 100644 index 0000000000000..ae9fbc7b13bd5 --- /dev/null +++ b/src/test/compile-fail/feature-gate-panic-implementation.rs @@ -0,0 +1,21 @@ +// 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 or the MIT license +// , 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] + +use core::panic::PanicInfo; + +#[panic_implementation] //~ ERROR #[panic_implementation] is an unstable feature (see issue #44489) +fn panic(info: &PanicInfo) -> ! { + loop {} +} diff --git a/src/test/compile-fail/no_owned_box_lang_item.rs b/src/test/compile-fail/no_owned_box_lang_item.rs index 72eb687adc602..1c2bf1573dcc1 100644 --- a/src/test/compile-fail/no_owned_box_lang_item.rs +++ b/src/test/compile-fail/no_owned_box_lang_item.rs @@ -21,4 +21,4 @@ fn main() { #[lang = "eh_personality"] extern fn eh_personality() {} #[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {} -#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } +#[lang = "panic_impl"] fn panic_impl() -> ! { loop {} } diff --git a/src/test/compile-fail/panic-implementation-bad-signature-1.rs b/src/test/compile-fail/panic-implementation-bad-signature-1.rs new file mode 100644 index 0000000000000..fec11fdbd7ba1 --- /dev/null +++ b/src/test/compile-fail/panic-implementation-bad-signature-1.rs @@ -0,0 +1,24 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-C panic=abort + +#![feature(panic_implementation)] +#![no_std] +#![no_main] + +use core::panic::PanicInfo; + +#[panic_implementation] +fn panic( + info: PanicInfo, //~ ERROR argument should be `&PanicInfo` +) -> () //~ ERROR return type should be `!` +{ +} diff --git a/src/test/compile-fail/panic-implementation-bad-signature-2.rs b/src/test/compile-fail/panic-implementation-bad-signature-2.rs new file mode 100644 index 0000000000000..2a628c05699cc --- /dev/null +++ b/src/test/compile-fail/panic-implementation-bad-signature-2.rs @@ -0,0 +1,25 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-C panic=abort + +#![feature(panic_implementation)] +#![no_std] +#![no_main] + +use core::panic::PanicInfo; + +#[panic_implementation] +fn panic( + info: &'static PanicInfo, //~ ERROR argument should be `&PanicInfo` +) -> ! +{ + loop {} +} diff --git a/src/test/compile-fail/panic-implementation-bad-signature-3.rs b/src/test/compile-fail/panic-implementation-bad-signature-3.rs new file mode 100644 index 0000000000000..29337025b7076 --- /dev/null +++ b/src/test/compile-fail/panic-implementation-bad-signature-3.rs @@ -0,0 +1,22 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-C panic=abort + +#![feature(panic_implementation)] +#![no_std] +#![no_main] + +use core::panic::PanicInfo; + +#[panic_implementation] +fn panic() -> ! { //~ ERROR function should have one argument + loop {} +} diff --git a/src/test/compile-fail/panic-implementation-bad-signature-4.rs b/src/test/compile-fail/panic-implementation-bad-signature-4.rs new file mode 100644 index 0000000000000..d5f942ba2d62f --- /dev/null +++ b/src/test/compile-fail/panic-implementation-bad-signature-4.rs @@ -0,0 +1,23 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-C panic=abort + +#![feature(panic_implementation)] +#![no_std] +#![no_main] + +use core::panic::PanicInfo; + +#[panic_implementation] +fn panic(pi: &PanicInfo) -> ! { + //~^ ERROR `#[panic_implementation]` function should have no type parameters + loop {} +} diff --git a/src/test/compile-fail/panic-implementation-duplicate.rs b/src/test/compile-fail/panic-implementation-duplicate.rs new file mode 100644 index 0000000000000..017113af409bb --- /dev/null +++ b/src/test/compile-fail/panic-implementation-duplicate.rs @@ -0,0 +1,28 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-C panic=abort + +#![feature(lang_items)] +#![feature(panic_implementation)] +#![no_std] +#![no_main] + +use core::panic::PanicInfo; + +#[panic_implementation] +fn panic(info: &PanicInfo) -> ! { + loop {} +} + +#[lang = "panic_impl"] +fn panic2(info: &PanicInfo) -> ! { //~ ERROR duplicate lang item found: `panic_impl`. + loop {} +} diff --git a/src/test/compile-fail/panic-implementation-requires-panic-info.rs b/src/test/compile-fail/panic-implementation-requires-panic-info.rs new file mode 100644 index 0000000000000..597f44d98326d --- /dev/null +++ b/src/test/compile-fail/panic-implementation-requires-panic-info.rs @@ -0,0 +1,26 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-C panic=abort +// error-pattern: language item required, but not found: `panic_info` + +#![feature(lang_items)] +#![feature(no_core)] +#![feature(panic_implementation)] +#![no_core] +#![no_main] + +#[panic_implementation] +fn panic() -> ! { + loop {} +} + +#[lang = "sized"] +trait Sized {} diff --git a/src/test/compile-fail/panic-implementation-std.rs b/src/test/compile-fail/panic-implementation-std.rs new file mode 100644 index 0000000000000..f25cd3605c1dd --- /dev/null +++ b/src/test/compile-fail/panic-implementation-std.rs @@ -0,0 +1,22 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern: duplicate lang item found: `panic_impl`. + +#![feature(panic_implementation)] + +use std::panic::PanicInfo; + +#[panic_implementation] +fn panic(info: PanicInfo) -> ! { + loop {} +} + +fn main() {} diff --git a/src/test/compile-fail/panic-implementation-twice.rs b/src/test/compile-fail/panic-implementation-twice.rs new file mode 100644 index 0000000000000..78dc545c036f8 --- /dev/null +++ b/src/test/compile-fail/panic-implementation-twice.rs @@ -0,0 +1,29 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:some-panic-impl.rs + +#![feature(panic_implementation)] +#![feature(lang_items)] +#![no_std] +#![no_main] + +extern crate some_panic_impl; + +use core::panic::PanicInfo; + +#[panic_implementation] +fn panic(info: &PanicInfo) -> ! { + //~^ error duplicate lang item found: `panic_impl` + loop {} +} + +#[lang = "eh_personality"] +fn eh() {} diff --git a/src/test/compile-fail/panic-runtime/auxiliary/panic-runtime-lang-items.rs b/src/test/compile-fail/panic-runtime/auxiliary/panic-runtime-lang-items.rs index fbf70b3d3fefe..d9848a554aba5 100644 --- a/src/test/compile-fail/panic-runtime/auxiliary/panic-runtime-lang-items.rs +++ b/src/test/compile-fail/panic-runtime/auxiliary/panic-runtime-lang-items.rs @@ -15,8 +15,10 @@ #![no_std] #![feature(lang_items)] -#[lang = "panic_fmt"] -fn panic_fmt() {} +use core::panic::PanicInfo; + +#[lang = "panic_impl"] +fn panic_impl(info: &PanicInfo) -> ! { loop {} } #[lang = "eh_personality"] fn eh_personality() {} #[lang = "eh_unwind_resume"] diff --git a/src/test/compile-fail/weak-lang-item.rs b/src/test/compile-fail/weak-lang-item.rs index 8579611b9380a..7b988c3595f5e 100644 --- a/src/test/compile-fail/weak-lang-item.rs +++ b/src/test/compile-fail/weak-lang-item.rs @@ -9,7 +9,7 @@ // except according to those terms. // aux-build:weak-lang-items.rs -// error-pattern: language item required, but not found: `panic_fmt` +// error-pattern: language item required, but not found: `panic_impl` // error-pattern: language item required, but not found: `eh_personality` // ignore-wasm32-bare compiled with panic=abort, personality not required diff --git a/src/test/run-make-fulldeps/panic-impl-transitive/Makefile b/src/test/run-make-fulldeps/panic-impl-transitive/Makefile new file mode 100644 index 0000000000000..1714578b2ba28 --- /dev/null +++ b/src/test/run-make-fulldeps/panic-impl-transitive/Makefile @@ -0,0 +1,7 @@ +-include ../../run-make-fulldeps/tools.mk + +# NOTE we use --emit=llvm-ir to avoid running the linker (linking will fail because there's no main +# in this crate) +all: + $(RUSTC) panic-impl-provider.rs + $(RUSTC) panic-impl-consumer.rs -C panic=abort --emit=llvm-ir -L $(TMPDIR) diff --git a/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-consumer.rs b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-consumer.rs new file mode 100644 index 0000000000000..592fab8be85ec --- /dev/null +++ b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-consumer.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![no_std] +#![no_main] + +// this crate provides the `panic_impl` lang item so we don't need to define it here +extern crate panic_impl_provider; diff --git a/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs new file mode 100644 index 0000000000000..46cdf2e2fa55e --- /dev/null +++ b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs @@ -0,0 +1,20 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] +#![feature(panic_implementation)] +#![no_std] + +use core::panic::PanicInfo; + +#[panic_implementation] +fn panic(info: &PanicInfo) -> ! { + loop {} +} diff --git a/src/test/ui/error-codes/E0152.rs b/src/test/ui/error-codes/E0152.rs index ae501b94e3f05..8fbad7b3ff301 100644 --- a/src/test/ui/error-codes/E0152.rs +++ b/src/test/ui/error-codes/E0152.rs @@ -10,7 +10,7 @@ #![feature(lang_items)] -#[lang = "panic_fmt"] +#[lang = "panic_impl"] struct Foo; //~ ERROR E0152 fn main() { diff --git a/src/test/ui/error-codes/E0152.stderr b/src/test/ui/error-codes/E0152.stderr index f67022bd6d3f9..c7f5f362efb28 100644 --- a/src/test/ui/error-codes/E0152.stderr +++ b/src/test/ui/error-codes/E0152.stderr @@ -1,4 +1,4 @@ -error[E0152]: duplicate lang item found: `panic_fmt`. +error[E0152]: duplicate lang item found: `panic_impl`. --> $DIR/E0152.rs:14:1 | LL | struct Foo; //~ ERROR E0152