From fc7ec6b61438f5a7fef5afd4830f009acd02d8f2 Mon Sep 17 00:00:00 2001 From: Benjamin Herr Date: Thu, 24 Mar 2016 00:35:26 +0100 Subject: [PATCH] librustc: add {span_,}bug! macros ... as single "internal compiler error" entry point. The macros pass `file!()`, `line!()` and `format_args!(...)` on to a cold, never-inlined function, ultimately calling `bug()` or `span_bug()` on the `Handler` from `session::diagnostic()` via the tcx in tls or, failing that, panicking directly. --- src/librustc/macros.rs | 15 +++++++++++++++ src/librustc/session/mod.rs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/src/librustc/macros.rs b/src/librustc/macros.rs index ed764ebd9f9..76dca1bb5b6 100644 --- a/src/librustc/macros.rs +++ b/src/librustc/macros.rs @@ -44,3 +44,18 @@ macro_rules! enum_from_u32 { } } } + +#[macro_export] +macro_rules! bug { + () => ( bug!("impossible case reached") ); + ($($message:tt)*) => ({ + $crate::session::bug_fmt(file!(), line!(), format_args!($($message)*)) + }) +} + +#[macro_export] +macro_rules! span_bug { + ($span:expr, $($message:tt)*) => ({ + $crate::session::span_bug_fmt(file!(), line!(), $span, format_args!($($message)*)) + }) +} diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 20ca6213254..d8792928f5e 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -12,6 +12,7 @@ use lint; use middle::cstore::CrateStore; use middle::dependency_format; use session::search_paths::PathKind; +use ty::tls; use util::nodemap::{NodeMap, FnvHashMap}; use mir::transform as mir_pass; @@ -35,6 +36,7 @@ use std::cell::{Cell, RefCell}; use std::collections::{HashMap, HashSet}; use std::env; use std::rc::Rc; +use std::fmt; pub mod config; pub mod filesearch; @@ -541,3 +543,35 @@ pub fn compile_result_from_err_count(err_count: usize) -> CompileResult { Err(err_count) } } + +#[cold] +#[inline(never)] +pub fn bug_fmt(file: &'static str, line: u32, args: fmt::Arguments) -> ! { + // this wrapper mostly exists so I don't have to write a fully + // qualified path of None:: inside the bug!() macro defintion + opt_span_bug_fmt(file, line, None::, args); +} + +#[cold] +#[inline(never)] +pub fn span_bug_fmt>(file: &'static str, + line: u32, + span: S, + args: fmt::Arguments) -> ! { + opt_span_bug_fmt(file, line, Some(span), args); +} + +fn opt_span_bug_fmt>(file: &'static str, + line: u32, + span: Option, + args: fmt::Arguments) -> ! { + tls::with_opt(move |tcx| { + let msg = format!("{}:{}: {}", file, line, args); + match (tcx, span) { + (Some(tcx), Some(span)) => tcx.sess.diagnostic().span_bug(span, &msg), + (Some(tcx), None) => tcx.sess.diagnostic().bug(&msg), + (None, _) => panic!(msg) + } + }); + unreachable!(); +}