diff --git a/Cargo.lock b/Cargo.lock index 1fe03a06c7974..8ca66b6ae6146 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3808,7 +3808,6 @@ dependencies = [ name = "rustc_driver" version = "0.0.0" dependencies = [ - "atty", "libc", "rustc_ast", "rustc_ast_pretty", @@ -3822,6 +3821,7 @@ dependencies = [ "rustc_hir_pretty", "rustc_interface", "rustc_lint", + "rustc_log", "rustc_metadata", "rustc_middle", "rustc_parse", @@ -3833,8 +3833,6 @@ dependencies = [ "rustc_target", "rustc_typeck", "tracing", - "tracing-subscriber", - "tracing-tree", "winapi", ] @@ -4077,6 +4075,17 @@ dependencies = [ "libc", ] +[[package]] +name = "rustc_log" +version = "0.0.0" +dependencies = [ + "atty", + "rustc_span", + "tracing", + "tracing-subscriber", + "tracing-tree", +] + [[package]] name = "rustc_macros" version = "0.1.0" diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index 2383a000687fa..872f946bf7d91 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -8,10 +8,8 @@ crate-type = ["dylib"] [dependencies] libc = "0.2" -atty = "0.2" tracing = { version = "0.1.28" } -tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } -tracing-tree = "0.2.0" +rustc_log = { path = "../rustc_log" } rustc_middle = { path = "../rustc_middle" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_target = { path = "../rustc_target" } @@ -40,4 +38,4 @@ winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] [features] llvm = ['rustc_interface/llvm'] -max_level_info = ['tracing/max_level_info'] +max_level_info = ['rustc_log/max_level_info'] diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 12e0b7a4977e1..3d58b27f83922 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -24,6 +24,7 @@ use rustc_feature::find_gated_cfg; use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; use rustc_lint::LintStore; +use rustc_log::stdout_isatty; use rustc_metadata::locator; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; @@ -514,14 +515,6 @@ impl Compilation { #[derive(Copy, Clone)] pub struct RustcDefaultCalls; -fn stdout_isatty() -> bool { - atty::is(atty::Stream::Stdout) -} - -fn stderr_isatty() -> bool { - atty::is(atty::Stream::Stderr) -} - fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { let upper_cased_code = code.to_ascii_uppercase(); let normalised = if upper_cased_code.starts_with('E') { @@ -1254,54 +1247,18 @@ pub fn install_ice_hook() { /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. pub fn init_rustc_env_logger() { - init_env_logger("RUSTC_LOG") + if let Err(error) = rustc_log::init_rustc_env_logger() { + early_error(ErrorOutputType::default(), &error.to_string()); + } } /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var /// other than `RUSTC_LOG`. pub fn init_env_logger(env: &str) { - use tracing_subscriber::{ - filter::{self, EnvFilter, LevelFilter}, - layer::SubscriberExt, - }; - - let filter = match std::env::var(env) { - Ok(env) => EnvFilter::new(env), - _ => EnvFilter::default().add_directive(filter::Directive::from(LevelFilter::WARN)), - }; - - let color_logs = match std::env::var(String::from(env) + "_COLOR") { - Ok(value) => match value.as_ref() { - "always" => true, - "never" => false, - "auto" => stderr_isatty(), - _ => early_error( - ErrorOutputType::default(), - &format!( - "invalid log color value '{}': expected one of always, never, or auto", - value - ), - ), - }, - Err(std::env::VarError::NotPresent) => stderr_isatty(), - Err(std::env::VarError::NotUnicode(_value)) => early_error( - ErrorOutputType::default(), - "non-Unicode log color value: expected one of always, never, or auto", - ), - }; - - let layer = tracing_tree::HierarchicalLayer::default() - .with_writer(io::stderr) - .with_indent_lines(true) - .with_ansi(color_logs) - .with_targets(true) - .with_indent_amount(2); - #[cfg(parallel_compiler)] - let layer = layer.with_thread_ids(true).with_thread_names(true); - - let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); - tracing::subscriber::set_global_default(subscriber).unwrap(); + if let Err(error) = rustc_log::init_env_logger(env) { + early_error(ErrorOutputType::default(), &error.to_string()); + } } #[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))] diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml new file mode 100644 index 0000000000000..1b2cde605556d --- /dev/null +++ b/compiler/rustc_log/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rustc_log" +version = "0.0.0" +edition = "2021" + +[dependencies] +atty = "0.2" +tracing = "0.1.28" +tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } +tracing-tree = "0.2.0" + +[dev-dependencies] +rustc_span = { path = "../rustc_span" } + +[features] +max_level_info = ['tracing/max_level_info'] diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs new file mode 100644 index 0000000000000..f5e7435d36e36 --- /dev/null +++ b/compiler/rustc_log/src/lib.rs @@ -0,0 +1,115 @@ +//! This crate allows tools to enable rust logging without having to magically +//! match rustc's tracing crate version. +//! +//! For example if someone is working on rustc_ast and wants to write some +//! minimal code against it to run in a debugger, with access to the `debug!` +//! logs emitted by rustc_ast, that can be done by writing: +//! +//! ```toml +//! [dependencies] +//! rustc_ast = { path = "../rust/compiler/rustc_ast" } +//! rustc_log = { path = "../rust/compiler/rustc_log" } +//! rustc_span = { path = "../rust/compiler/rustc_span" } +//! ``` +//! +//! ``` +//! fn main() { +//! rustc_log::init_rustc_env_logger().unwrap(); +//! +//! let edition = rustc_span::edition::Edition::Edition2021; +//! rustc_span::create_session_globals_then(edition, || { +//! /* ... */ +//! }); +//! } +//! ``` +//! +//! Now `RUSTC_LOG=debug cargo run` will run your minimal main.rs and show +//! rustc's debug logging. In a workflow like this, one might also add +//! `std::env::set_var("RUSTC_LOG", "debug")` to the top of main so that `cargo +//! run` by itself is sufficient to get logs. +//! +//! The reason rustc_log is a tiny separate crate, as opposed to exposing the +//! same things in rustc_driver only, is to enable the above workflow. If you +//! had to depend on rustc_driver in order to turn on rustc's debug logs, that's +//! an enormously bigger dependency tree; every change you make to rustc_ast (or +//! whichever piece of the compiler you are interested in) would involve +//! rebuilding all the rest of rustc up to rustc_driver in order to run your +//! main.rs. Whereas by depending only on rustc_log and the few crates you are +//! debugging, you can make changes inside those crates and quickly run main.rs +//! to read the debug logs. + +use std::env::{self, VarError}; +use std::fmt::{self, Display}; +use std::io; +use tracing_subscriber::filter::{Directive, EnvFilter, LevelFilter}; +use tracing_subscriber::layer::SubscriberExt; + +pub fn init_rustc_env_logger() -> Result<(), Error> { + init_env_logger("RUSTC_LOG") +} + +/// In contrast to `init_rustc_env_logger` this allows you to choose an env var +/// other than `RUSTC_LOG`. +pub fn init_env_logger(env: &str) -> Result<(), Error> { + let filter = match env::var(env) { + Ok(env) => EnvFilter::new(env), + _ => EnvFilter::default().add_directive(Directive::from(LevelFilter::WARN)), + }; + + let color_logs = match env::var(String::from(env) + "_COLOR") { + Ok(value) => match value.as_ref() { + "always" => true, + "never" => false, + "auto" => stderr_isatty(), + _ => return Err(Error::InvalidColorValue(value)), + }, + Err(VarError::NotPresent) => stderr_isatty(), + Err(VarError::NotUnicode(_value)) => return Err(Error::NonUnicodeColorValue), + }; + + let layer = tracing_tree::HierarchicalLayer::default() + .with_writer(io::stderr) + .with_indent_lines(true) + .with_ansi(color_logs) + .with_targets(true) + .with_indent_amount(2); + #[cfg(parallel_compiler)] + let layer = layer.with_thread_ids(true).with_thread_names(true); + + let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); + tracing::subscriber::set_global_default(subscriber).unwrap(); + + Ok(()) +} + +pub fn stdout_isatty() -> bool { + atty::is(atty::Stream::Stdout) +} + +pub fn stderr_isatty() -> bool { + atty::is(atty::Stream::Stderr) +} + +#[derive(Debug)] +pub enum Error { + InvalidColorValue(String), + NonUnicodeColorValue, +} + +impl std::error::Error for Error {} + +impl Display for Error { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::InvalidColorValue(value) => write!( + formatter, + "invalid log color value '{}': expected one of always, never, or auto", + value, + ), + Error::NonUnicodeColorValue => write!( + formatter, + "non-Unicode log color value: expected one of always, never, or auto", + ), + } + } +} diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 6fc3cd0b7c4ad..8a2a64f8dc97f 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -570,11 +570,30 @@ impl Display for Arguments<'_> { /// There are a number of helper methods on the [`Formatter`] struct to help you with manual /// implementations, such as [`debug_struct`]. /// +/// [`debug_struct`]: Formatter::debug_struct +/// +/// Types that do not wish to use the standard suite of debug representations +/// provided by the `Formatter` trait (`debug_struct`, `debug_tuple`, +/// `debut_list`, `debug_set`, `debug_map`) can do something totally custom by +/// manually writing an arbitrary representation to the `Formatter`. +/// +/// ``` +/// # use std::fmt; +/// # struct Point { +/// # x: i32, +/// # y: i32, +/// # } +/// # +/// impl fmt::Debug for Point { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// write!(f, "Point [{} {}]", self.x, self.y) +/// } +/// } +/// ``` +/// /// `Debug` implementations using either `derive` or the debug builder API /// on [`Formatter`] support pretty-printing using the alternate flag: `{:#?}`. /// -/// [`debug_struct`]: Formatter::debug_struct -/// /// Pretty-printing with `#?`: /// /// ``` diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index e84dfbce4a754..5ad570427978e 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -268,7 +268,7 @@ impl Command { } else { None }; - let program = resolve_exe(&self.program, child_paths)?; + let program = resolve_exe(&self.program, || env::var_os("PATH"), child_paths)?; let mut cmd_str = make_command_line(program.as_os_str(), &self.args, self.force_quotes_enabled)?; cmd_str.push(0); // add null terminator @@ -362,7 +362,11 @@ impl fmt::Debug for Command { // Therefore this functions first assumes `.exe` was intended. // It falls back to the plain file name if a full path is given and the extension is omitted // or if only a file name is given and it already contains an extension. -fn resolve_exe<'a>(exe_path: &'a OsStr, child_paths: Option<&OsStr>) -> io::Result { +fn resolve_exe<'a>( + exe_path: &'a OsStr, + parent_paths: impl FnOnce() -> Option, + child_paths: Option<&OsStr>, +) -> io::Result { // Early return if there is no filename. if exe_path.is_empty() || path::has_trailing_slash(exe_path) { return Err(io::Error::new_const( @@ -406,7 +410,7 @@ fn resolve_exe<'a>(exe_path: &'a OsStr, child_paths: Option<&OsStr>) -> io::Resu let has_extension = exe_path.bytes().contains(&b'.'); // Search the directories given by `search_paths`. - let result = search_paths(child_paths, |mut path| { + let result = search_paths(parent_paths, child_paths, |mut path| { path.push(&exe_path); if !has_extension { path.set_extension(EXE_EXTENSION); @@ -423,15 +427,20 @@ fn resolve_exe<'a>(exe_path: &'a OsStr, child_paths: Option<&OsStr>) -> io::Resu // Calls `f` for every path that should be used to find an executable. // Returns once `f` returns the path to an executable or all paths have been searched. -fn search_paths(child_paths: Option<&OsStr>, mut f: F) -> Option +fn search_paths( + parent_paths: Paths, + child_paths: Option<&OsStr>, + mut exists: Exists, +) -> Option where - F: FnMut(PathBuf) -> Option, + Paths: FnOnce() -> Option, + Exists: FnMut(PathBuf) -> Option, { // 1. Child paths // This is for consistency with Rust's historic behaviour. if let Some(paths) = child_paths { for path in env::split_paths(paths).filter(|p| !p.as_os_str().is_empty()) { - if let Some(path) = f(path) { + if let Some(path) = exists(path) { return Some(path); } } @@ -440,7 +449,7 @@ where // 2. Application path if let Ok(mut app_path) = env::current_exe() { app_path.pop(); - if let Some(path) = f(app_path) { + if let Some(path) = exists(app_path) { return Some(path); } } @@ -450,7 +459,7 @@ where unsafe { if let Ok(Some(path)) = super::fill_utf16_buf( |buf, size| c::GetSystemDirectoryW(buf, size), - |buf| f(PathBuf::from(OsString::from_wide(buf))), + |buf| exists(PathBuf::from(OsString::from_wide(buf))), ) { return Some(path); } @@ -458,7 +467,7 @@ where { if let Ok(Some(path)) = super::fill_utf16_buf( |buf, size| c::GetWindowsDirectoryW(buf, size), - |buf| f(PathBuf::from(OsString::from_wide(buf))), + |buf| exists(PathBuf::from(OsString::from_wide(buf))), ) { return Some(path); } @@ -466,9 +475,9 @@ where } // 5. Parent paths - if let Some(parent_paths) = env::var_os("PATH") { + if let Some(parent_paths) = parent_paths() { for path in env::split_paths(&parent_paths).filter(|p| !p.as_os_str().is_empty()) { - if let Some(path) = f(path) { + if let Some(path) = exists(path) { return Some(path); } } diff --git a/library/std/src/sys/windows/process/tests.rs b/library/std/src/sys/windows/process/tests.rs index 6159a679c0e69..f1221767af30e 100644 --- a/library/std/src/sys/windows/process/tests.rs +++ b/library/std/src/sys/windows/process/tests.rs @@ -136,51 +136,46 @@ fn windows_exe_resolver() { use super::resolve_exe; use crate::io; + let env_paths = || env::var_os("PATH"); + // Test a full path, with and without the `exe` extension. let mut current_exe = env::current_exe().unwrap(); - assert!(resolve_exe(current_exe.as_ref(), None).is_ok()); + assert!(resolve_exe(current_exe.as_ref(), env_paths, None).is_ok()); current_exe.set_extension(""); - assert!(resolve_exe(current_exe.as_ref(), None).is_ok()); + assert!(resolve_exe(current_exe.as_ref(), env_paths, None).is_ok()); // Test lone file names. - assert!(resolve_exe(OsStr::new("cmd"), None).is_ok()); - assert!(resolve_exe(OsStr::new("cmd.exe"), None).is_ok()); - assert!(resolve_exe(OsStr::new("cmd.EXE"), None).is_ok()); - assert!(resolve_exe(OsStr::new("fc"), None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd"), env_paths, None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd.exe"), env_paths, None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd.EXE"), env_paths, None).is_ok()); + assert!(resolve_exe(OsStr::new("fc"), env_paths, None).is_ok()); // Invalid file names should return InvalidInput. - assert_eq!(resolve_exe(OsStr::new(""), None).unwrap_err().kind(), io::ErrorKind::InvalidInput); assert_eq!( - resolve_exe(OsStr::new("\0"), None).unwrap_err().kind(), + resolve_exe(OsStr::new(""), env_paths, None).unwrap_err().kind(), + io::ErrorKind::InvalidInput + ); + assert_eq!( + resolve_exe(OsStr::new("\0"), env_paths, None).unwrap_err().kind(), io::ErrorKind::InvalidInput ); // Trailing slash, therefore there's no file name component. assert_eq!( - resolve_exe(OsStr::new(r"C:\Path\to\"), None).unwrap_err().kind(), + resolve_exe(OsStr::new(r"C:\Path\to\"), env_paths, None).unwrap_err().kind(), io::ErrorKind::InvalidInput ); - /* FIXME: fix and re-enable these tests before making changes to the resolver. - /* Some of the following tests may need to be changed if you are deliberately changing the behaviour of `resolve_exe`. */ - let paths = env::var_os("PATH").unwrap(); - env::set_var("PATH", ""); - - assert_eq!(resolve_exe(OsStr::new("rustc"), None).unwrap_err().kind(), io::ErrorKind::NotFound); - - let child_paths = Some(paths.as_os_str()); - assert!(resolve_exe(OsStr::new("rustc"), child_paths).is_ok()); + let empty_paths = || None; // The resolver looks in system directories even when `PATH` is empty. - assert!(resolve_exe(OsStr::new("cmd.exe"), None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd.exe"), empty_paths, None).is_ok()); // The application's directory is also searched. let current_exe = env::current_exe().unwrap(); - assert!(resolve_exe(current_exe.file_name().unwrap().as_ref(), None).is_ok()); - - */ + assert!(resolve_exe(current_exe.file_name().unwrap().as_ref(), empty_paths, None).is_ok()); } diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 5a33073e6b022..5235a6b818053 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -974,6 +974,7 @@ def bootstrap_binary(self): def build_bootstrap(self): """Build bootstrap""" + print("Building rustbuild") build_dir = os.path.join(self.build_dir, "bootstrap") if self.clean and os.path.exists(build_dir): shutil.rmtree(build_dir) @@ -1133,7 +1134,7 @@ def update_submodules(self): recorded_submodules[data[3]] = data[2] for module in filtered_submodules: self.update_submodule(module[0], module[1], recorded_submodules) - print("Submodules updated in %.2f seconds" % (time() - start_time)) + print(" Submodules updated in %.2f seconds" % (time() - start_time)) def set_dist_environment(self, url): """Set download URL for normal environment""" diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 2fddda74a28e9..9180c5f03af68 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -401,26 +401,19 @@ To learn more about a subcommand, run `./x.py -h`", "\n Arguments: This subcommand accepts a number of paths to directories to the crates - and/or artifacts to compile. For example: - - ./x.py build library/core - ./x.py build library/core library/proc_macro - ./x.py build library/std --stage 1 - - If no arguments are passed then the complete artifacts for that stage are - also compiled. + and/or artifacts to compile. For example, for a quick build of a usable + compiler: - ./x.py build - ./x.py build --stage 1 + ./x.py build --stage 1 library/std - For a quick build of a usable compiler, you can pass: + This will build a compiler and standard library from the local source code. + Once this is done, build/$ARCH/stage1 contains a usable compiler. - ./x.py build --stage 1 library/test + If no arguments are passed then the default artifacts for that stage are + compiled. For example: - This will first build everything once (like `--stage 0` without further - arguments would), and then use the compiler built in stage 0 to build - library/test and its dependencies. - Once this is done, build/$ARCH/stage1 contains a usable compiler.", + ./x.py build --stage 0 + ./x.py build ", ); } "check" | "c" => { @@ -430,14 +423,9 @@ Arguments: This subcommand accepts a number of paths to directories to the crates and/or artifacts to compile. For example: - ./x.py check library/core - ./x.py check library/core library/proc_macro + ./x.py check library/std - If no arguments are passed then the complete artifacts are compiled: std, test, and rustc. Note - also that since we use `cargo check`, by default this will automatically enable incremental - compilation, so there's no need to pass it separately, though it won't hurt. We also completely - ignore the stage passed, as there's no way to compile in non-stage 0 without actually building - the compiler.", + If no arguments are passed then many artifacts are checked.", ); } "clippy" => { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 2ee5de24687f1..f0f61bb94c8e8 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -889,20 +889,25 @@ impl AttributesExt for [ast::Attribute] { } crate trait NestedAttributesExt { - /// Returns `true` if the attribute list contains a specific `Word` - fn has_word(self, word: Symbol) -> bool; + /// Returns `true` if the attribute list contains a specific `word` + fn has_word(self, word: Symbol) -> bool + where + Self: std::marker::Sized, + { + ::get_word_attr(self, word).is_some() + } + + /// Returns `Some(attr)` if the attribute list contains 'attr' + /// corresponding to a specific `word` fn get_word_attr(self, word: Symbol) -> Option; } -impl + IntoIterator> - NestedAttributesExt for I +impl NestedAttributesExt for I +where + I: IntoIterator, { - fn has_word(self, word: Symbol) -> bool { - self.into_iter().any(|attr| attr.is_word() && attr.has_name(word)) - } - - fn get_word_attr(mut self, word: Symbol) -> Option { - self.find(|attr| attr.is_word() && attr.has_name(word)) + fn get_word_attr(self, word: Symbol) -> Option { + self.into_iter().find(|attr| attr.is_word() && attr.has_name(word)) } } diff --git a/src/test/ui/closures/issue-84044-drop-non-mut.rs b/src/test/ui/closures/issue-84044-drop-non-mut.rs new file mode 100644 index 0000000000000..aed7750f1b9df --- /dev/null +++ b/src/test/ui/closures/issue-84044-drop-non-mut.rs @@ -0,0 +1,6 @@ +// #84044: This used to ICE. + +fn main() { + let f = || {}; + drop(&mut f); //~ ERROR cannot borrow `f` as mutable, as it is not declared as mutable +} diff --git a/src/test/ui/closures/issue-84044-drop-non-mut.stderr b/src/test/ui/closures/issue-84044-drop-non-mut.stderr new file mode 100644 index 0000000000000..c0bfad263f178 --- /dev/null +++ b/src/test/ui/closures/issue-84044-drop-non-mut.stderr @@ -0,0 +1,11 @@ +error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable + --> $DIR/issue-84044-drop-non-mut.rs:5:10 + | +LL | let f = || {}; + | - help: consider changing this to be mutable: `mut f` +LL | drop(&mut f); + | ^^^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/panics/panic-short-backtrace-windows-x86_64.rs b/src/test/ui/panics/panic-short-backtrace-windows-x86_64.rs index fd01337296fb7..39ffe86dd496b 100644 --- a/src/test/ui/panics/panic-short-backtrace-windows-x86_64.rs +++ b/src/test/ui/panics/panic-short-backtrace-windows-x86_64.rs @@ -1,3 +1,7 @@ +// This test has been spuriously failing a lot recently (#92000). +// Ignore it until the underlying issue is fixed. +// ignore-test + // Regression test for #87481: short backtrace formatting cut off the entire stack trace. // Codegen-units is specified here so that we can replicate a typical rustc invocation which diff --git a/src/test/ui/save-analysis/issue-89066.rs b/src/test/ui/save-analysis/issue-89066.rs new file mode 100644 index 0000000000000..c670483ec1c9e --- /dev/null +++ b/src/test/ui/save-analysis/issue-89066.rs @@ -0,0 +1,30 @@ +// compile-flags: -Zsave-analysis + +// Check that this does not ICE. +// Stolen from src/test/ui/inference/infer-arg-test.rs + +#![feature(generic_arg_infer)] + +struct All<'a, T, const N: usize> { + v: &'a T, +} + +struct BadInfer<_>; +//~^ ERROR expected identifier +//~| ERROR parameter `_` is never used + +fn all_fn<'a, T, const N: usize>() {} + +fn bad_infer_fn<_>() {} +//~^ ERROR expected identifier + + +fn main() { + let a: All<_, _, _>; + //~^ ERROR this struct takes 2 generic arguments but 3 generic arguments were supplied + all_fn(); + let v: [u8; _]; + //~^ ERROR in expressions + let v: [u8; 10] = [0; _]; + //~^ ERROR in expressions +} diff --git a/src/test/ui/save-analysis/issue-89066.stderr b/src/test/ui/save-analysis/issue-89066.stderr new file mode 100644 index 0000000000000..4476a3fc556da --- /dev/null +++ b/src/test/ui/save-analysis/issue-89066.stderr @@ -0,0 +1,51 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/issue-89066.rs:12:17 + | +LL | struct BadInfer<_>; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/issue-89066.rs:18:17 + | +LL | fn bad_infer_fn<_>() {} + | ^ expected identifier, found reserved identifier + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/issue-89066.rs:26:15 + | +LL | let v: [u8; _]; + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/issue-89066.rs:28:25 + | +LL | let v: [u8; 10] = [0; _]; + | ^ `_` not allowed here + +error[E0392]: parameter `_` is never used + --> $DIR/issue-89066.rs:12:17 + | +LL | struct BadInfer<_>; + | ^ unused parameter + | + = help: consider removing `_`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `_` to be a const parameter, use `const _: usize` instead + +error[E0107]: this struct takes 2 generic arguments but 3 generic arguments were supplied + --> $DIR/issue-89066.rs:23:10 + | +LL | let a: All<_, _, _>; + | ^^^ - help: remove this generic argument + | | + | expected 2 generic arguments + | +note: struct defined here, with 2 generic parameters: `T`, `N` + --> $DIR/issue-89066.rs:8:8 + | +LL | struct All<'a, T, const N: usize> { + | ^^^ - - + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0107, E0392. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/traits/issue-91594.rs b/src/test/ui/traits/issue-91594.rs new file mode 100644 index 0000000000000..930f7f0c6ad6b --- /dev/null +++ b/src/test/ui/traits/issue-91594.rs @@ -0,0 +1,17 @@ +// #91594: This used to ICE. + +trait Component { + type Interface; +} +trait HasComponent {} + +struct Foo; + +impl HasComponent<>::Interface> for Foo {} +//~^ ERROR the trait bound `Foo: HasComponent<()>` is not satisfied + +impl> Component for Foo { + type Interface = u8; +} + +fn main() {} diff --git a/src/test/ui/traits/issue-91594.stderr b/src/test/ui/traits/issue-91594.stderr new file mode 100644 index 0000000000000..10298a0c7037a --- /dev/null +++ b/src/test/ui/traits/issue-91594.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied + --> $DIR/issue-91594.rs:10:6 + | +LL | impl HasComponent<>::Interface> for Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo` + | + = help: the following implementations were found: + >::Interface>> +note: required because of the requirements on the impl of `Component` for `Foo` + --> $DIR/issue-91594.rs:13:27 + | +LL | impl> Component for Foo { + | ^^^^^^^^^^^^ ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.