mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #93621 - JohnTitor:rollup-1bcud0x, r=JohnTitor
Rollup of 7 pull requests Successful merges: - #92310 (rustdoc: Fix ICE report) - #92802 (Deduplicate lines in long const-eval stack trace) - #93515 (Factor convenience functions out of main printer implementation) - #93566 (Make rustc use `RUST_BACKTRACE=full` by default) - #93589 (Use Option::then in two places) - #93600 (fix: Remove extra newlines from junit output) - #93606 (Correct incorrect description of preorder traversals) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
4e8fb743cc
@ -132,6 +132,7 @@
|
|||||||
//! methods called `Printer::scan_*`, and the 'PRINT' process is the
|
//! methods called `Printer::scan_*`, and the 'PRINT' process is the
|
||||||
//! method called `Printer::print`.
|
//! method called `Printer::print`.
|
||||||
|
|
||||||
|
mod convenience;
|
||||||
mod ring;
|
mod ring;
|
||||||
|
|
||||||
use ring::RingBuffer;
|
use ring::RingBuffer;
|
||||||
@ -186,12 +187,6 @@ pub enum Token {
|
|||||||
End,
|
End,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Token {
|
|
||||||
pub fn is_hardbreak_tok(&self) -> bool {
|
|
||||||
matches!(self, Token::Break(BreakToken { offset: 0, blank_space: SIZE_INFINITY }))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
enum PrintFrame {
|
enum PrintFrame {
|
||||||
Fits,
|
Fits,
|
||||||
@ -441,73 +436,4 @@ impl Printer {
|
|||||||
self.out.push_str(string);
|
self.out.push_str(string);
|
||||||
self.space -= string.len() as isize;
|
self.space -= string.len() as isize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience functions to talk to the printer.
|
|
||||||
|
|
||||||
/// "raw box"
|
|
||||||
pub fn rbox(&mut self, indent: usize, breaks: Breaks) {
|
|
||||||
self.scan_begin(BeginToken {
|
|
||||||
indent: IndentStyle::Block { offset: indent as isize },
|
|
||||||
breaks,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Inconsistent breaking box
|
|
||||||
pub fn ibox(&mut self, indent: usize) {
|
|
||||||
self.rbox(indent, Breaks::Inconsistent)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Consistent breaking box
|
|
||||||
pub fn cbox(&mut self, indent: usize) {
|
|
||||||
self.rbox(indent, Breaks::Consistent)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn visual_align(&mut self) {
|
|
||||||
self.scan_begin(BeginToken { indent: IndentStyle::Visual, breaks: Breaks::Consistent });
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn break_offset(&mut self, n: usize, off: isize) {
|
|
||||||
self.scan_break(BreakToken { offset: off, blank_space: n as isize })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn end(&mut self) {
|
|
||||||
self.scan_end()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn eof(mut self) -> String {
|
|
||||||
self.scan_eof();
|
|
||||||
self.out
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn word<S: Into<Cow<'static, str>>>(&mut self, wrd: S) {
|
|
||||||
let string = wrd.into();
|
|
||||||
self.scan_string(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spaces(&mut self, n: usize) {
|
|
||||||
self.break_offset(n, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn zerobreak(&mut self) {
|
|
||||||
self.spaces(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn space(&mut self) {
|
|
||||||
self.spaces(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hardbreak(&mut self) {
|
|
||||||
self.spaces(SIZE_INFINITY as usize)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_beginning_of_line(&self) -> bool {
|
|
||||||
match self.last_token() {
|
|
||||||
Some(last_token) => last_token.is_hardbreak_tok(),
|
|
||||||
None => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hardbreak_tok_offset(off: isize) -> Token {
|
|
||||||
Token::Break(BreakToken { offset: off, blank_space: SIZE_INFINITY })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
77
compiler/rustc_ast_pretty/src/pp/convenience.rs
Normal file
77
compiler/rustc_ast_pretty/src/pp/convenience.rs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
use crate::pp::{BeginToken, BreakToken, Breaks, IndentStyle, Printer, Token, SIZE_INFINITY};
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
impl Printer {
|
||||||
|
/// "raw box"
|
||||||
|
pub fn rbox(&mut self, indent: usize, breaks: Breaks) {
|
||||||
|
self.scan_begin(BeginToken {
|
||||||
|
indent: IndentStyle::Block { offset: indent as isize },
|
||||||
|
breaks,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inconsistent breaking box
|
||||||
|
pub fn ibox(&mut self, indent: usize) {
|
||||||
|
self.rbox(indent, Breaks::Inconsistent)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consistent breaking box
|
||||||
|
pub fn cbox(&mut self, indent: usize) {
|
||||||
|
self.rbox(indent, Breaks::Consistent)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn visual_align(&mut self) {
|
||||||
|
self.scan_begin(BeginToken { indent: IndentStyle::Visual, breaks: Breaks::Consistent });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn break_offset(&mut self, n: usize, off: isize) {
|
||||||
|
self.scan_break(BreakToken { offset: off, blank_space: n as isize })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn end(&mut self) {
|
||||||
|
self.scan_end()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eof(mut self) -> String {
|
||||||
|
self.scan_eof();
|
||||||
|
self.out
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn word<S: Into<Cow<'static, str>>>(&mut self, wrd: S) {
|
||||||
|
let string = wrd.into();
|
||||||
|
self.scan_string(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spaces(&mut self, n: usize) {
|
||||||
|
self.break_offset(n, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn zerobreak(&mut self) {
|
||||||
|
self.spaces(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn space(&mut self) {
|
||||||
|
self.spaces(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hardbreak(&mut self) {
|
||||||
|
self.spaces(SIZE_INFINITY as usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_beginning_of_line(&self) -> bool {
|
||||||
|
match self.last_token() {
|
||||||
|
Some(last_token) => last_token.is_hardbreak_tok(),
|
||||||
|
None => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hardbreak_tok_offset(off: isize) -> Token {
|
||||||
|
Token::Break(BreakToken { offset: off, blank_space: SIZE_INFINITY })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Token {
|
||||||
|
pub fn is_hardbreak_tok(&self) -> bool {
|
||||||
|
matches!(self, Token::Break(BreakToken { offset: 0, blank_space: SIZE_INFINITY }))
|
||||||
|
}
|
||||||
|
}
|
@ -156,9 +156,37 @@ impl<'tcx> ConstEvalErr<'tcx> {
|
|||||||
}
|
}
|
||||||
// Add spans for the stacktrace. Don't print a single-line backtrace though.
|
// Add spans for the stacktrace. Don't print a single-line backtrace though.
|
||||||
if self.stacktrace.len() > 1 {
|
if self.stacktrace.len() > 1 {
|
||||||
|
// Helper closure to print duplicated lines.
|
||||||
|
let mut flush_last_line = |last_frame, times| {
|
||||||
|
if let Some((line, span)) = last_frame {
|
||||||
|
err.span_label(span, &line);
|
||||||
|
// Don't print [... additional calls ...] if the number of lines is small
|
||||||
|
if times < 3 {
|
||||||
|
for _ in 0..times {
|
||||||
|
err.span_label(span, &line);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err.span_label(
|
||||||
|
span,
|
||||||
|
format!("[... {} additional calls {} ...]", times, &line),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut last_frame = None;
|
||||||
|
let mut times = 0;
|
||||||
for frame_info in &self.stacktrace {
|
for frame_info in &self.stacktrace {
|
||||||
err.span_label(frame_info.span, frame_info.to_string());
|
let frame = (frame_info.to_string(), frame_info.span);
|
||||||
|
if last_frame.as_ref() == Some(&frame) {
|
||||||
|
times += 1;
|
||||||
|
} else {
|
||||||
|
flush_last_line(last_frame, times);
|
||||||
|
last_frame = Some(frame);
|
||||||
|
times = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
flush_last_line(last_frame, times);
|
||||||
}
|
}
|
||||||
// Let the caller finish the job.
|
// Let the caller finish the job.
|
||||||
emit(err)
|
emit(err)
|
||||||
|
@ -66,7 +66,7 @@ pub const EXIT_FAILURE: i32 = 1;
|
|||||||
const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/issues/new\
|
const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/issues/new\
|
||||||
?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md";
|
?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md";
|
||||||
|
|
||||||
const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["Z", "C", "crate-type"];
|
const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["-Z", "-C", "--crate-type"];
|
||||||
|
|
||||||
const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &[&str] = &["metadata", "extra-filename"];
|
const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &[&str] = &["metadata", "extra-filename"];
|
||||||
|
|
||||||
@ -1100,31 +1100,31 @@ fn parse_crate_attrs<'a>(sess: &'a Session, input: &Input) -> PResult<'a, Vec<as
|
|||||||
/// debugging, since some ICEs only happens with non-default compiler flags
|
/// debugging, since some ICEs only happens with non-default compiler flags
|
||||||
/// (and the users don't always report them).
|
/// (and the users don't always report them).
|
||||||
fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
|
fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
|
||||||
let args = env::args_os().map(|arg| arg.to_string_lossy().to_string()).collect::<Vec<_>>();
|
let mut args = env::args_os().map(|arg| arg.to_string_lossy().to_string()).peekable();
|
||||||
|
|
||||||
// Avoid printing help because of empty args. This can suggest the compiler
|
|
||||||
// itself is not the program root (consider RLS).
|
|
||||||
if args.len() < 2 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let matches = handle_options(&args)?;
|
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
let mut excluded_cargo_defaults = false;
|
let mut excluded_cargo_defaults = false;
|
||||||
for flag in ICE_REPORT_COMPILER_FLAGS {
|
while let Some(arg) = args.next() {
|
||||||
let prefix = if flag.len() == 1 { "-" } else { "--" };
|
if let Some(a) = ICE_REPORT_COMPILER_FLAGS.iter().find(|a| arg.starts_with(*a)) {
|
||||||
|
let content = if arg.len() == a.len() {
|
||||||
for content in &matches.opt_strs(flag) {
|
match args.next() {
|
||||||
// Split always returns the first element
|
Some(arg) => arg.to_string(),
|
||||||
let name = if let Some(first) = content.split('=').next() { first } else { &content };
|
None => continue,
|
||||||
|
}
|
||||||
let content =
|
} else if arg.get(a.len()..a.len() + 1) == Some("=") {
|
||||||
if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) { name } else { content };
|
arg[a.len() + 1..].to_string()
|
||||||
|
|
||||||
if !ICE_REPORT_COMPILER_FLAGS_EXCLUDE.contains(&name) {
|
|
||||||
result.push(format!("{}{} {}", prefix, flag, content));
|
|
||||||
} else {
|
} else {
|
||||||
|
arg[a.len()..].to_string()
|
||||||
|
};
|
||||||
|
if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.iter().any(|exc| content.starts_with(exc)) {
|
||||||
excluded_cargo_defaults = true;
|
excluded_cargo_defaults = true;
|
||||||
|
} else {
|
||||||
|
result.push(a.to_string());
|
||||||
|
match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| content.starts_with(*s))
|
||||||
|
{
|
||||||
|
Some(s) => result.push(s.to_string()),
|
||||||
|
None => result.push(content),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1240,6 +1240,15 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
|||||||
///
|
///
|
||||||
/// A custom rustc driver can skip calling this to set up a custom ICE hook.
|
/// A custom rustc driver can skip calling this to set up a custom ICE hook.
|
||||||
pub fn install_ice_hook() {
|
pub fn install_ice_hook() {
|
||||||
|
// If the user has not explicitly overriden "RUST_BACKTRACE", then produce
|
||||||
|
// full backtraces. When a compiler ICE happens, we want to gather
|
||||||
|
// as much information as possible to present in the issue opened
|
||||||
|
// by the user. Compiler developers and other rustc users can
|
||||||
|
// opt in to less-verbose backtraces by manually setting "RUST_BACKTRACE"
|
||||||
|
// (e.g. `RUST_BACKTRACE=1`)
|
||||||
|
if std::env::var("RUST_BACKTRACE").is_err() {
|
||||||
|
std::env::set_var("RUST_BACKTRACE", "full");
|
||||||
|
}
|
||||||
SyncLazy::force(&DEFAULT_HOOK);
|
SyncLazy::force(&DEFAULT_HOOK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,9 @@ use super::*;
|
|||||||
|
|
||||||
/// Preorder traversal of a graph.
|
/// Preorder traversal of a graph.
|
||||||
///
|
///
|
||||||
/// Preorder traversal is when each node is visited before any of its
|
/// Preorder traversal is when each node is visited after at least one of its predecessors. If you
|
||||||
/// successors
|
/// are familar with some basic graph theory, then this performs a depth first search and returns
|
||||||
|
/// nodes in order of discovery time.
|
||||||
///
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
///
|
///
|
||||||
@ -82,8 +83,9 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
|
|||||||
|
|
||||||
/// Postorder traversal of a graph.
|
/// Postorder traversal of a graph.
|
||||||
///
|
///
|
||||||
/// Postorder traversal is when each node is visited after all of its
|
/// Postorder traversal is when each node is visited after all of its successors, except when the
|
||||||
/// successors, except when the successor is only reachable by a back-edge
|
/// successor is only reachable by a back-edge. If you are familiar with some basic graph theory,
|
||||||
|
/// then this performs a depth first search and returns nodes in order of completion time.
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
|
@ -264,7 +264,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
// The set of places that we are creating fake borrows of. If there are
|
// The set of places that we are creating fake borrows of. If there are
|
||||||
// no match guards then we don't need any fake borrows, so don't track
|
// no match guards then we don't need any fake borrows, so don't track
|
||||||
// them.
|
// them.
|
||||||
let mut fake_borrows = if match_has_guard { Some(FxHashSet::default()) } else { None };
|
let mut fake_borrows = match_has_guard.then(FxHashSet::default);
|
||||||
|
|
||||||
let mut otherwise = None;
|
let mut otherwise = None;
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ impl<K: DepKind> EncoderState<K> {
|
|||||||
total_edge_count: 0,
|
total_edge_count: 0,
|
||||||
total_node_count: 0,
|
total_node_count: 0,
|
||||||
result: Ok(()),
|
result: Ok(()),
|
||||||
stats: if record_stats { Some(FxHashMap::default()) } else { None },
|
stats: record_stats.then(FxHashMap::default),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
|
|||||||
_shuffle_seed: Option<u64>,
|
_shuffle_seed: Option<u64>,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
// We write xml header on run start
|
// We write xml header on run start
|
||||||
self.out.write_all(b"\n")?;
|
|
||||||
self.write_message("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
|
self.write_message("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +137,7 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
|
|||||||
self.write_message("</testsuite>")?;
|
self.write_message("</testsuite>")?;
|
||||||
self.write_message("</testsuites>")?;
|
self.write_message("</testsuites>")?;
|
||||||
|
|
||||||
self.out.write_all(b"\n\n")?;
|
self.out.write_all(b"\n")?;
|
||||||
|
|
||||||
Ok(state.failed == 0)
|
Ok(state.failed == 0)
|
||||||
}
|
}
|
||||||
|
11
src/test/ui/consts/recursive.rs
Normal file
11
src/test/ui/consts/recursive.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
const fn f<T>(x: T) { //~ WARN function cannot return without recursing
|
||||||
|
f(x);
|
||||||
|
//~^ ERROR any use of this value will cause an error
|
||||||
|
//~| WARN this was previously accepted by the compiler
|
||||||
|
}
|
||||||
|
|
||||||
|
const X: () = f(1);
|
||||||
|
|
||||||
|
fn main() {}
|
31
src/test/ui/consts/recursive.stderr
Normal file
31
src/test/ui/consts/recursive.stderr
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
warning: function cannot return without recursing
|
||||||
|
--> $DIR/recursive.rs:3:1
|
||||||
|
|
|
||||||
|
LL | const fn f<T>(x: T) {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||||
|
LL | f(x);
|
||||||
|
| ---- recursive call site
|
||||||
|
|
|
||||||
|
= note: `#[warn(unconditional_recursion)]` on by default
|
||||||
|
= help: a `loop` may express intention better if this is on purpose
|
||||||
|
|
||||||
|
error: any use of this value will cause an error
|
||||||
|
--> $DIR/recursive.rs:4:5
|
||||||
|
|
|
||||||
|
LL | f(x);
|
||||||
|
| ^^^^
|
||||||
|
| |
|
||||||
|
| reached the configured maximum number of stack frames
|
||||||
|
| inside `f::<i32>` at $DIR/recursive.rs:4:5
|
||||||
|
| [... 126 additional calls inside `f::<i32>` at $DIR/recursive.rs:4:5 ...]
|
||||||
|
| inside `X` at $DIR/recursive.rs:9:15
|
||||||
|
...
|
||||||
|
LL | const X: () = f(1);
|
||||||
|
| -------------------
|
||||||
|
|
|
||||||
|
= note: `#[deny(const_err)]` on by default
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
9
src/test/ui/panics/default-backtrace-ice.rs
Normal file
9
src/test/ui/panics/default-backtrace-ice.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// unset-rustc-env:RUST_BACKTRACE
|
||||||
|
// compile-flags:-Z treat-err-as-bug=1
|
||||||
|
// error-pattern:stack backtrace:
|
||||||
|
// failure-status:101
|
||||||
|
// normalize-stderr-test "note: .*" -> ""
|
||||||
|
// normalize-stderr-test "thread 'rustc' .*" -> ""
|
||||||
|
// normalize-stderr-test " .*\n" -> ""
|
||||||
|
|
||||||
|
fn main() { missing_ident; }
|
18
src/test/ui/panics/default-backtrace-ice.stderr
Normal file
18
src/test/ui/panics/default-backtrace-ice.stderr
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
error[E0425]: cannot find value `missing_ident` in this scope
|
||||||
|
LL | fn main() { missing_ident; }
|
||||||
|
|
||||||
|
|
||||||
|
stack backtrace:
|
||||||
|
|
||||||
|
error: internal compiler error: unexpected panic
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
query stack during panic:
|
||||||
|
end of query stack
|
Loading…
Reference in New Issue
Block a user