Skip to content

Commit da88707

Browse files
committed
Output line column info when panicking
1 parent c3a130c commit da88707

File tree

9 files changed

+207
-54
lines changed

9 files changed

+207
-54
lines changed

src/libcore/lib.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@
3939
//! * `rust_begin_panic` - This function takes three arguments, a
4040
//! `fmt::Arguments`, a `&'static str`, and a `u32`. These three arguments
4141
//! dictate the panic message, the file at which panic was invoked, and the
42-
//! line. It is up to consumers of this core library to define this panic
43-
//! function; it is only required to never return. This requires a `lang`
44-
//! attribute named `panic_fmt`.
42+
//! line and column inside the file. It is up to consumers of this core
43+
//! library to define this panic function; it is only required to never
44+
//! return. This requires a `lang` attribute named `panic_fmt`.
4545
//!
4646
//! * `rust_eh_personality` - is used by the failure mechanisms of the
4747
//! compiler. This is often mapped to GCC's personality function, but crates
@@ -160,6 +160,11 @@ pub mod array;
160160
pub mod sync;
161161
pub mod cell;
162162
pub mod char;
163+
// FIXME: remove when SNAP
164+
#[cfg(stage0)]
165+
#[path = "panicking_stage0.rs"]
166+
pub mod panicking;
167+
#[cfg(not(stage0))]
163168
pub mod panicking;
164169
pub mod iter;
165170
pub mod option;

src/libcore/macros.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@ macro_rules! panic {
1717
panic!("explicit panic")
1818
);
1919
($msg:expr) => ({
20-
static _MSG_FILE_LINE: (&'static str, &'static str, u32) = ($msg, file!(), line!());
21-
$crate::panicking::panic(&_MSG_FILE_LINE)
20+
static _MSG_FILE_LINE_COL: (&'static str, &'static str, u32, u32) =
21+
($msg, file!(), line!(), column!());
22+
$crate::panicking::panic_new(&_MSG_FILE_LINE_COL)
2223
});
2324
($fmt:expr, $($arg:tt)*) => ({
2425
// The leading _'s are to avoid dead code warnings if this is
2526
// used inside a dead function. Just `#[allow(dead_code)]` is
2627
// insufficient, since the user may have
2728
// `#[forbid(dead_code)]` and which cannot be overridden.
28-
static _FILE_LINE: (&'static str, u32) = (file!(), line!());
29-
$crate::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE)
29+
static _MSG_FILE_LINE_COL: (&'static str, u32, u32) =
30+
(file!(), line!(), column!());
31+
$crate::panicking::panic_fmt_new(format_args!($fmt, $($arg)*), &_MSG_FILE_LINE_COL)
3032
});
3133
}
3234

src/libcore/panicking.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
//!
1818
//! ```
1919
//! # use std::fmt;
20-
//! fn panic_impl(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> !
20+
//! fn panic_impl(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> !
2121
//! # { loop {} }
2222
//! ```
2323
//!
@@ -38,35 +38,45 @@
3838

3939
use fmt;
4040

41+
#[cold] #[inline(never)]
42+
pub fn panic_new(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! {
43+
panic(&expr_file_line_col)
44+
}
45+
4146
#[cold] #[inline(never)] // this is the slow path, always
4247
#[lang = "panic"]
43-
pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! {
48+
pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! {
4449
// Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
4550
// reduce size overhead. The format_args! macro uses str's Display trait to
4651
// write expr, which calls Formatter::pad, which must accommodate string
4752
// truncation and padding (even though none is used here). Using
4853
// Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
4954
// output binary, saving up to a few kilobytes.
50-
let (expr, file, line) = *expr_file_line;
51-
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line))
55+
let (expr, file, line, col) = *expr_file_line_col;
56+
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line, col))
5257
}
5358

5459
#[cold] #[inline(never)]
5560
#[lang = "panic_bounds_check"]
56-
fn panic_bounds_check(file_line: &(&'static str, u32),
61+
fn panic_bounds_check(file_line_col: &(&'static str, u32, u32),
5762
index: usize, len: usize) -> ! {
5863
panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
59-
len, index), file_line)
64+
len, index), file_line_col)
65+
}
66+
67+
#[cold] #[inline(never)]
68+
pub fn panic_fmt_new(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! {
69+
panic_fmt(fmt, &file_line_col)
6070
}
6171

6272
#[cold] #[inline(never)]
63-
pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! {
73+
pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! {
6474
#[allow(improper_ctypes)]
6575
extern {
6676
#[lang = "panic_fmt"]
6777
#[unwind]
68-
fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32) -> !;
78+
fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32, col :u32) -> !;
6979
}
70-
let (file, line) = *file_line;
71-
unsafe { panic_impl(fmt, file, line) }
80+
let (file, line, col) = *file_line_col;
81+
unsafe { panic_impl(fmt, file, line, col) }
7282
}

src/libcore/panicking_stage0.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! Panic support for libcore
12+
//!
13+
//! The core library cannot define panicking, but it does *declare* panicking. This
14+
//! means that the functions inside of libcore are allowed to panic, but to be
15+
//! useful an upstream crate must define panicking for libcore to use. The current
16+
//! interface for panicking is:
17+
//!
18+
//! ```
19+
//! # use std::fmt;
20+
//! fn panic_impl(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> !
21+
//! # { loop {} }
22+
//! ```
23+
//!
24+
//! This definition allows for panicking with any general message, but it does not
25+
//! allow for failing with a `Box<Any>` value. The reason for this is that libcore
26+
//! is not allowed to allocate.
27+
//!
28+
//! This module contains a few other panicking functions, but these are just the
29+
//! necessary lang items for the compiler. All panics are funneled through this
30+
//! one function. Currently, the actual symbol is declared in the standard
31+
//! library, but the location of this may change over time.
32+
33+
#![allow(dead_code, missing_docs)]
34+
#![unstable(feature = "core_panic",
35+
reason = "internal details of the implementation of the `panic!` \
36+
and related macros",
37+
issue = "0")]
38+
39+
use fmt;
40+
41+
#[cold] #[inline(never)]
42+
pub fn panic_new(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! {
43+
let (expr, file, line, _) = *expr_file_line_col;
44+
let expr_file_line = (expr, file, line);
45+
panic(&expr_file_line)
46+
}
47+
48+
#[cold] #[inline(never)] // this is the slow path, always
49+
#[lang = "panic"]
50+
pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! {
51+
// Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
52+
// reduce size overhead. The format_args! macro uses str's Display trait to
53+
// write expr, which calls Formatter::pad, which must accommodate string
54+
// truncation and padding (even though none is used here). Using
55+
// Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
56+
// output binary, saving up to a few kilobytes.
57+
let (expr, file, line) = *expr_file_line;
58+
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line))
59+
}
60+
61+
#[cold] #[inline(never)]
62+
#[lang = "panic_bounds_check"]
63+
fn panic_bounds_check(file_line: &(&'static str, u32),
64+
index: usize, len: usize) -> ! {
65+
panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
66+
len, index), file_line)
67+
}
68+
69+
#[cold] #[inline(never)]
70+
pub fn panic_fmt_new(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! {
71+
let (file, line, _) = *file_line_col;
72+
let file_line = (file, line);
73+
panic_fmt(fmt, &file_line)
74+
}
75+
76+
#[cold] #[inline(never)]
77+
pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! {
78+
#[allow(improper_ctypes)]
79+
extern {
80+
#[lang = "panic_fmt"]
81+
#[unwind]
82+
fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32, col: u32) -> !;
83+
}
84+
let (file, line) = *file_line;
85+
unsafe { panic_impl(fmt, file, line, 0) }
86+
}

src/librustc_trans/mir/block.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use type_of;
2828
use type_::Type;
2929

3030
use syntax::symbol::Symbol;
31+
use syntax_pos::Pos;
3132

3233
use std::cmp;
3334

@@ -333,6 +334,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
333334
let filename = Symbol::intern(&loc.file.name).as_str();
334335
let filename = C_str_slice(bcx.ccx, filename);
335336
let line = C_u32(bcx.ccx, loc.line as u32);
337+
let col = C_u32(bcx.ccx, loc.col.to_usize() as u32 + 1);
336338

337339
// Put together the arguments to the panic entry point.
338340
let (lang_item, args, const_err) = match *msg {
@@ -347,29 +349,29 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
347349
index: index as u64
348350
}));
349351

350-
let file_line = C_struct(bcx.ccx, &[filename, line], false);
351-
let align = llalign_of_min(bcx.ccx, common::val_ty(file_line));
352-
let file_line = consts::addr_of(bcx.ccx,
353-
file_line,
354-
align,
355-
"panic_bounds_check_loc");
352+
let file_line_col = C_struct(bcx.ccx, &[filename, line, col], false);
353+
let align = llalign_of_min(bcx.ccx, common::val_ty(file_line_col));
354+
let file_line_col = consts::addr_of(bcx.ccx,
355+
file_line_col,
356+
align,
357+
"panic_bounds_check_loc");
356358
(lang_items::PanicBoundsCheckFnLangItem,
357-
vec![file_line, index, len],
359+
vec![file_line_col, index, len],
358360
const_err)
359361
}
360362
mir::AssertMessage::Math(ref err) => {
361363
let msg_str = Symbol::intern(err.description()).as_str();
362364
let msg_str = C_str_slice(bcx.ccx, msg_str);
363-
let msg_file_line = C_struct(bcx.ccx,
364-
&[msg_str, filename, line],
365+
let msg_file_line_col = C_struct(bcx.ccx,
366+
&[msg_str, filename, line, col],
365367
false);
366-
let align = llalign_of_min(bcx.ccx, common::val_ty(msg_file_line));
367-
let msg_file_line = consts::addr_of(bcx.ccx,
368-
msg_file_line,
369-
align,
370-
"panic_loc");
368+
let align = llalign_of_min(bcx.ccx, common::val_ty(msg_file_line_col));
369+
let msg_file_line_col = consts::addr_of(bcx.ccx,
370+
msg_file_line_col,
371+
align,
372+
"panic_loc");
371373
(lang_items::PanicFnLangItem,
372-
vec![msg_file_line],
374+
vec![msg_file_line_col],
373375
Some(ErrKind::Math(err.clone())))
374376
}
375377
};

src/libstd/macros.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ macro_rules! panic {
4141
panic!("explicit panic")
4242
});
4343
($msg:expr) => ({
44-
$crate::rt::begin_panic($msg, {
44+
$crate::rt::begin_panic_new($msg, {
4545
// static requires less code at runtime, more constant data
46-
static _FILE_LINE: (&'static str, u32) = (file!(), line!());
47-
&_FILE_LINE
46+
static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), column!());
47+
&_FILE_LINE_COL
4848
})
4949
});
5050
($fmt:expr, $($arg:tt)+) => ({
@@ -53,8 +53,8 @@ macro_rules! panic {
5353
// used inside a dead function. Just `#[allow(dead_code)]` is
5454
// insufficient, since the user may have
5555
// `#[forbid(dead_code)]` and which cannot be overridden.
56-
static _FILE_LINE: (&'static str, u32) = (file!(), line!());
57-
&_FILE_LINE
56+
static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), column!());
57+
&_FILE_LINE_COL
5858
})
5959
});
6060
}

0 commit comments

Comments
 (0)