Change:
Given this code, the failure message looks like this This is problematic as the useful information (the message passed to )is buried inside the sentence. It'd be better if the failure message was on its own line, something akin to: This format also allows for space to mention other useful information (e.g. issue ).
Is this still something we want to do? I have a small patch that implements something like this and would also but I'm not sure how many people really want another format for panic messages. Changing the format might also break existing tools (for example, there are several run-tests in this repo that expect a panic).
I'd be all for it, I still find those messages hard to read even after all these years.
you should submit it
The pull request didn't really fix this bug... should I make another bug like this, or is this a wontfix now?
Oh sorry, that's because I didn't change the original pull request message. Perhaps can comment on this?
This is somewhat of a wontfix for now, the discussion of concluded that we likely don't want to radically change the format for now due to the concurrency/verbosity reasons mentioned. If this becomes extra onerous in the future, however, we can consider reformatting these messages.

Discussion:
use cell::RefCell; use intrinsics; use sync::StaticRwLock; <ins> use sync::atomic::{AtomicBool, Ordering}; </ins> use sys::stdio::Stderr; use sys_common::backtrace; use sys_common::thread_info;

static HANDLER_LOCK: StaticRwLock = StaticRwLock::new(); static mut HANDLER: Handler = Handler::Default; <ins> static FIRST_PANIC: AtomicBool = AtomicBool::new(true); </ins> /// Registers a custom panic handler, replacing any that was previously /// registered.

let write = |err: &mut ::io::Write| { let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}", name, msg, file, line); if log_backtrace { let _ = backtrace::write(err); <ins> } else if FIRST_PANIC.compare_and_swap(true, false, Ordering::SeqCst) { let _ = writeln!(err, "note: Run with `RUST_BACKTRACE=1` for a backtrace."); </ins> } };

<ins> // Copyright 2016 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. fn main() { let args: Vec<String> = std::env::args().collect(); if args.len() > 1 && args[1] == "run_test" { let _ = std::thread::spawn(|| { panic!(); }).join(); panic!(); } else { let test = std::process::Command::new(&args[0]).arg("run_test").output().unwrap(); assert!(!test.status.success()); let err = String::from_utf8_lossy(&test.stderr); let mut it = err.lines(); assert_eq!(it.next().map(|l| l.starts_with("thread '<unnamed>' panicked at")), Some(true)); assert_eq!(it.next(), Some("note: Run with `RUST_BACKTRACE=1` for a backtrace.")); assert_eq!(it.next().map(|l| l.starts_with("thread '<main>' panicked at")), Some(true)); assert_eq!(it.next(), None); } } </ins>