[] IsPanicRuntime(CrateNum),
[] IsCompilerBuiltins(CrateNum),
[] HasGlobalAllocator(CrateNum),
+ [] HasPanicHandler(CrateNum),
[input] ExternCrate(DefId),
[eval_always] LintLevels,
[] Specializes { impl1: DefId, impl2: DefId },
/// Metadata about the allocators for the current crate being compiled
pub has_global_allocator: Once<bool>,
+ /// Metadata about the panic handlers for the current crate being compiled
+ pub has_panic_handler: Once<bool>,
+
/// Cap lint level specified by a driver specifically.
pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
}
(*GLOBAL_JOBSERVER).clone()
},
has_global_allocator: Once::new(),
+ has_panic_handler: Once::new(),
driver_lint_caps: FxHashMap(),
};
}
}
+impl<'tcx> QueryDescription<'tcx> for queries::has_panic_handler<'tcx> {
+ fn describe(_: TyCtxt, _: CrateNum) -> String {
+ "checking if the crate has_panic_handler".to_string()
+ }
+}
+
impl<'tcx> QueryDescription<'tcx> for queries::extern_crate<'tcx> {
fn describe(_: TyCtxt, _: DefId) -> String {
"getting crate's ExternCrateData".to_string()
[fatal_cycle] fn is_panic_runtime: IsPanicRuntime(CrateNum) -> bool,
[fatal_cycle] fn is_compiler_builtins: IsCompilerBuiltins(CrateNum) -> bool,
[fatal_cycle] fn has_global_allocator: HasGlobalAllocator(CrateNum) -> bool,
+ [fatal_cycle] fn has_panic_handler: HasPanicHandler(CrateNum) -> bool,
[fatal_cycle] fn is_sanitizer_runtime: IsSanitizerRuntime(CrateNum) -> bool,
[fatal_cycle] fn is_profiler_runtime: IsProfilerRuntime(CrateNum) -> bool,
[fatal_cycle] fn panic_strategy: GetPanicStrategy(CrateNum) -> PanicStrategy,
DepKind::IsPanicRuntime => { force!(is_panic_runtime, krate!()); }
DepKind::IsCompilerBuiltins => { force!(is_compiler_builtins, krate!()); }
DepKind::HasGlobalAllocator => { force!(has_global_allocator, krate!()); }
+ DepKind::HasPanicHandler => { force!(has_panic_handler, krate!()); }
DepKind::ExternCrate => { force!(extern_crate, def_id!()); }
DepKind::LintLevels => { force!(lint_levels, LOCAL_CRATE); }
DepKind::InScopeTraits => { force!(in_scope_traits_map, def_id!().index); }
is_panic_runtime => { cdata.root.panic_runtime }
is_compiler_builtins => { cdata.root.compiler_builtins }
has_global_allocator => { cdata.root.has_global_allocator }
+ has_panic_handler => { cdata.root.has_panic_handler }
is_sanitizer_runtime => { cdata.root.sanitizer_runtime }
is_profiler_runtime => { cdata.root.profiler_runtime }
panic_strategy => { cdata.root.panic_strategy }
let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
let has_default_lib_allocator = attr::contains_name(&attrs, "default_lib_allocator");
let has_global_allocator = *tcx.sess.has_global_allocator.get();
+ let has_panic_handler = *tcx.sess.has_panic_handler.try_get().unwrap_or(&false);
let root = self.lazy(&CrateRoot {
name: tcx.crate_name(LOCAL_CRATE),
panic_strategy: tcx.sess.panic_strategy(),
edition: hygiene::default_edition(),
has_global_allocator: has_global_allocator,
+ has_panic_handler: has_panic_handler,
has_default_lib_allocator: has_default_lib_allocator,
plugin_registrar_fn: tcx.sess
.plugin_registrar_fn
pub panic_strategy: PanicStrategy,
pub edition: Edition,
pub has_global_allocator: bool,
+ pub has_panic_handler: bool,
pub has_default_lib_allocator: bool,
pub plugin_registrar_fn: Option<DefIndex>,
pub macro_derive_registrar: Option<DefIndex>,
if let Some(panic_impl_did) = fcx.tcx.lang_items().panic_impl() {
if panic_impl_did == fcx.tcx.hir.local_def_id(fn_id) {
if let Some(panic_info_did) = fcx.tcx.lang_items().panic_info() {
+ // at this point we don't care if there are duplicate handlers or if the handler has
+ // the wrong signature as this value we'll be used when writing metadata and that
+ // only happens if compilation succeeded
+ fcx.tcx.sess.has_panic_handler.try_set_same(true);
+
if declared_ret_ty.sty != ty::Never {
fcx.tcx.sess.span_err(
decl.output.span(),
!tcx.is_compiler_builtins(cnum)
&& !tcx.is_panic_runtime(cnum)
&& !tcx.has_global_allocator(cnum)
+ && !tcx.has_panic_handler(cnum)
})
.cloned()
.collect();
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(RUSTC) panic.rs
+ $(RUSTC) -C panic=abort --emit=obj app.rs -L $(TMPDIR)
--- /dev/null
+#![crate_type = "bin"]
+#![no_main]
+#![no_std]
+
+#![deny(unused_extern_crates)]
+
+// `panic` provides a `panic_handler` so it shouldn't trip the `unused_extern_crates` lint
+extern crate panic;
--- /dev/null
+// 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.
+
+#![crate_type = "lib"]
+#![feature(panic_handler)]
+#![no_std]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic(_: &PanicInfo) -> ! {
+ loop {}
+}