From 5138586678fa3186118e5e3eaaf623759d839bb7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 1 Aug 2024 18:23:50 -0400 Subject: [PATCH 1/7] Skip over args when determining if coroutine-closure's inner coroutine consumes its upvars --- compiler/rustc_hir_typeck/src/upvar.rs | 66 +++++++++++++++---- .../non-copy-arg-does-not-force-inner-move.rs | 17 +++++ 2 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index e64f4ebf45df1..55f002291f071 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -219,7 +219,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `async-await/async-closures/force-move-due-to-inferred-kind.rs`. // // 2. If the coroutine-closure is forced to be `FnOnce` due to the way it - // uses its upvars, but not *all* upvars would force the closure to `FnOnce`. + // uses its upvars (e.g. it consumes a non-copy value), but not *all* upvars + // would force the closure to `FnOnce`. // See the test: `async-await/async-closures/force-move-due-to-actually-fnonce.rs`. // // This would lead to an impossible to satisfy situation, since `AsyncFnOnce` @@ -227,11 +228,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // we force the inner coroutine to also be `move`. This only matters for // coroutine-closures that are `move` since otherwise they themselves will // be borrowing from the outer environment, so there's no self-borrows occuring. - // - // One *important* note is that we do a call to `process_collected_capture_information` - // to eagerly test whether the coroutine would end up `FnOnce`, but we do this - // *before* capturing all the closure args by-value below, since that would always - // cause the analysis to return `FnOnce`. if let UpvarArgs::Coroutine(..) = args && let hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) = self.tcx.coroutine_kind(closure_def_id).expect("coroutine should have kind") @@ -246,19 +242,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { capture_clause = hir::CaptureBy::Value { move_kw }; } // (2.) The way that the closure uses its upvars means it's `FnOnce`. - else if let (_, ty::ClosureKind::FnOnce, _) = self - .process_collected_capture_information( - capture_clause, - &delegate.capture_information, - ) - { + else if self.coroutine_body_consumes_upvars(closure_def_id, body) { capture_clause = hir::CaptureBy::Value { move_kw }; } } // As noted in `lower_coroutine_body_with_moved_arguments`, we default the capture mode // to `ByRef` for the `async {}` block internal to async fns/closure. This means - // that we would *not* be moving all of the parameters into the async block by default. + // that we would *not* be moving all of the parameters into the async block in all cases. + // For example, when one of the arguments is `Copy`, we turn a consuming use into a copy of + // a reference, so for `async fn x(t: i32) {}`, we'd only take a reference to `t`. // // We force all of these arguments to be captured by move before we do expr use analysis. // @@ -535,6 +528,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Determines whether the body of the coroutine uses its upvars in a way that + /// consumes (i.e. moves) the value, which would force the coroutine to `FnOnce`. + /// In a more detailed comment above, we care whether this happens, since if + /// this happens, we want to force the coroutine to move all of the upvars it + /// would've borrowed from the parent coroutine-closure. + /// + /// This only really makes sense to be called on the child coroutine of a + /// coroutine-closure. + fn coroutine_body_consumes_upvars( + &self, + coroutine_def_id: LocalDefId, + body: &'tcx hir::Body<'tcx>, + ) -> bool { + // This block contains argument capturing details. Since arguments + // aren't upvars, we do not care about them for determining if the + // coroutine body actually consumes its upvars. + let hir::ExprKind::Block(&hir::Block { expr: Some(body), .. }, None) = body.value.kind + else { + bug!(); + }; + // Specifically, we only care about the *real* body of the coroutine. + // We skip out into the drop-temps within the block of the body in order + // to skip over the args of the desugaring. + let hir::ExprKind::DropTemps(body) = body.kind else { + bug!(); + }; + + let mut delegate = InferBorrowKind { + closure_def_id: coroutine_def_id, + capture_information: Default::default(), + fake_reads: Default::default(), + }; + + let _ = euv::ExprUseVisitor::new( + &FnCtxt::new(self, self.tcx.param_env(coroutine_def_id), coroutine_def_id), + &mut delegate, + ) + .consume_expr(body); + + let (_, kind, _) = self.process_collected_capture_information( + hir::CaptureBy::Ref, + &delegate.capture_information, + ); + + matches!(kind, ty::ClosureKind::FnOnce) + } + // Returns a list of `Ty`s for each upvar. fn final_upvar_tys(&self, closure_id: LocalDefId) -> Vec> { self.typeck_results diff --git a/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs b/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs new file mode 100644 index 0000000000000..cd9d98d079925 --- /dev/null +++ b/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs @@ -0,0 +1,17 @@ +//@ aux-build:block-on.rs +//@ edition:2021 +//@ build-pass + +#![feature(async_closure)] + +extern crate block_on; + +fn wrapper(f: impl Fn(String)) -> impl async Fn(String) { + async move |s| f(s) +} + +fn main() { + block_on::block_on(async { + wrapper(|who| println!("Hello, {who}!"))(String::from("world")).await; + }); +} From 61ea488309ee87c35177171dc98478b94d9f76a1 Mon Sep 17 00:00:00 2001 From: Shina <53410646+s7tya@users.noreply.github.com> Date: Mon, 5 Aug 2024 19:07:32 +0900 Subject: [PATCH 2/7] Emit an error for invalid use of the `#[no_sanitize]` attribute --- compiler/rustc_passes/src/check_attr.rs | 7 +++- tests/ui/attributes/no-sanitize.rs | 34 +++++++++++++++ tests/ui/attributes/no-sanitize.stderr | 55 +++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 tests/ui/attributes/no-sanitize.rs create mode 100644 tests/ui/attributes/no-sanitize.stderr diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index a0d0d80b9572e..996ea6aa072c1 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -125,6 +125,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::inline, ..] => self.check_inline(hir_id, attr, span, target), [sym::coverage, ..] => self.check_coverage(attr, span, target), [sym::optimize, ..] => self.check_optimize(hir_id, attr, target), + [sym::no_sanitize, ..] => self.check_no_sanitize(hir_id, attr, span, target), [sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target), [sym::marker, ..] => self.check_marker(hir_id, attr, span, target), [sym::target_feature, ..] => { @@ -255,7 +256,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::may_dangle // FIXME(dropck_eyepatch) | sym::pointee // FIXME(derive_smart_pointer) | sym::linkage // FIXME(linkage) - | sym::no_sanitize // FIXME(no_sanitize) | sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section) | sym::used // handled elsewhere to restrict to static items | sym::repr // handled elsewhere to restrict to type decls items @@ -450,6 +450,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } + /// Checks that `#[no_sanitize(..)]` is applied to a function or method. + fn check_no_sanitize(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { + self.check_applied_to_fn_or_method(hir_id, attr, span, target) + } + fn check_generic_attr( &self, hir_id: HirId, diff --git a/tests/ui/attributes/no-sanitize.rs b/tests/ui/attributes/no-sanitize.rs new file mode 100644 index 0000000000000..82b7a22d5701e --- /dev/null +++ b/tests/ui/attributes/no-sanitize.rs @@ -0,0 +1,34 @@ +#![feature(no_sanitize)] +#![feature(stmt_expr_attributes)] +#![deny(unused_attributes)] +#![allow(dead_code)] + +fn invalid() { + #[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition + { + 1 + }; +} + +#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition +type InvalidTy = (); + +#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition +mod invalid_module {} + +fn main() { + let _ = #[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition + (|| 1); +} + +#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition +struct F; + +#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition +impl F { + #[no_sanitize(memory)] + fn valid(&self) {} +} + +#[no_sanitize(memory)] +fn valid() {} diff --git a/tests/ui/attributes/no-sanitize.stderr b/tests/ui/attributes/no-sanitize.stderr new file mode 100644 index 0000000000000..f742ba0beed18 --- /dev/null +++ b/tests/ui/attributes/no-sanitize.stderr @@ -0,0 +1,55 @@ +error: attribute should be applied to a function definition + --> $DIR/no-sanitize.rs:7:5 + | +LL | #[no_sanitize(memory)] + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | / { +LL | | 1 +LL | | }; + | |_____- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/no-sanitize.rs:13:1 + | +LL | #[no_sanitize(memory)] + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | type InvalidTy = (); + | -------------------- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/no-sanitize.rs:16:1 + | +LL | #[no_sanitize(memory)] + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | mod invalid_module {} + | --------------------- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/no-sanitize.rs:20:13 + | +LL | let _ = #[no_sanitize(memory)] + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | (|| 1); + | ------ not a function definition + +error: attribute should be applied to a function definition + --> $DIR/no-sanitize.rs:24:1 + | +LL | #[no_sanitize(memory)] + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | struct F; + | --------- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/no-sanitize.rs:27:1 + | +LL | #[no_sanitize(memory)] + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | / impl F { +LL | | #[no_sanitize(memory)] +LL | | fn valid(&self) {} +LL | | } + | |_- not a function definition + +error: aborting due to 6 previous errors + From 51e68c3006f415141a73fec60acc50f1f2cd49d3 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 5 Aug 2024 12:20:17 -0500 Subject: [PATCH 3/7] Update `compiler-builtins` to 0.1.117 This includes [1] which means we can remove the (nonworking) configuration of `no-f16-f128`. Fixes https://github.com/rust-lang/rust/issues/128401. [1]: https://github.com/rust-lang/compiler-builtins/pull/652 --- library/Cargo.lock | 4 ++-- library/alloc/Cargo.toml | 5 +---- library/std/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index 223b61456c267..c5182516f7d14 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.114" +version = "0.1.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb58b199190fcfe0846f55a3b545cd6b07a34bdd5930a476ff856f3ebcc5558a" +checksum = "a91dae36d82fe12621dfb5b596d7db766187747749b22e33ac068e1bfc356f4a" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 479eb0a2ba743..82d5893dc5e55 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -10,10 +10,7 @@ edition = "2021" [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.114", features = ['rustc-dep-of-std'] } - -[target.'cfg(not(any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64")))'.dependencies] -compiler_builtins = { version = "0.1.114", features = ["no-f16-f128"] } +compiler_builtins = { version = "0.1.117", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index fe601855cc1e7..06e818fb7c09d 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "0.1.114" } +compiler_builtins = { version = "0.1.117" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = [ From 5212c759076c4b4ada74c86979bb298ec0a8a5fb Mon Sep 17 00:00:00 2001 From: Jane Losare-Lusby Date: Wed, 31 Jul 2024 11:47:07 -0700 Subject: [PATCH 4/7] Add -Zerror-metrics=PATH to save diagnostic metadata to disk --- .gitignore | 1 + compiler/rustc_driver_impl/src/lib.rs | 37 +++++++--- compiler/rustc_session/src/options.rs | 2 + tests/run-make/dump-ice-to-disk/rmake.rs | 86 +++++++++++++++++++----- 4 files changed, 103 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index aabec0988a99e..f2cdd8762f230 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ Session.vim *.iml .vscode .project +.vim/ .favorites.json .settings/ .vs/ diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 627a0ebb4e5e3..b014fc2dc585e 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -51,7 +51,8 @@ use rustc_metadata::creader::MetadataLoader; use rustc_metadata::locator; use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_session::config::{ - nightly_options, ErrorOutputType, Input, OutFileName, OutputType, CG_OPTIONS, Z_OPTIONS, + nightly_options, ErrorOutputType, Input, OutFileName, OutputType, UnstableOptions, CG_OPTIONS, + Z_OPTIONS, }; use rustc_session::getopts::{self, Matches}; use rustc_session::lint::{Lint, LintId}; @@ -301,6 +302,8 @@ fn run_compiler( let Some(matches) = handle_options(&default_early_dcx, &args) else { return Ok(()) }; let sopts = config::build_session_options(&mut default_early_dcx, &matches); + // fully initialize ice path static once unstable options are available as context + let ice_file = ice_path_with_config(Some(&sopts.unstable_opts)).clone(); if let Some(ref code) = matches.opt_str("explain") { handle_explain(&default_early_dcx, diagnostics_registry(), code, sopts.color); @@ -315,7 +318,7 @@ fn run_compiler( input: Input::File(PathBuf::new()), output_file: ofile, output_dir: odir, - ice_file: ice_path().clone(), + ice_file, file_loader, locale_resources: DEFAULT_LOCALE_RESOURCES, lint_caps: Default::default(), @@ -1306,25 +1309,43 @@ pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 { static ICE_PATH: OnceLock> = OnceLock::new(); +// This function should only be called from the ICE hook. +// +// The intended behavior is that `run_compiler` will invoke `ice_path_with_config` early in the +// initialization process to properly initialize the ICE_PATH static based on parsed CLI flags. +// +// Subsequent calls to either function will then return the proper ICE path as configured by +// the environment and cli flags fn ice_path() -> &'static Option { + ice_path_with_config(None) +} + +fn ice_path_with_config(config: Option<&UnstableOptions>) -> &'static Option { + if ICE_PATH.get().is_some() && config.is_some() && cfg!(debug_assertions) { + tracing::warn!( + "ICE_PATH has already been initialized -- files may be emitted at unintended paths" + ) + } + ICE_PATH.get_or_init(|| { if !rustc_feature::UnstableFeatures::from_environment(None).is_nightly_build() { return None; } - if let Some(s) = std::env::var_os("RUST_BACKTRACE") - && s == "0" - { - return None; - } let mut path = match std::env::var_os("RUSTC_ICE") { Some(s) => { if s == "0" { // Explicitly opting out of writing ICEs to disk. return None; } + if let Some(unstable_opts) = config && unstable_opts.metrics_dir.is_some() { + tracing::warn!("ignoring -Zerror-metrics in favor of RUSTC_ICE for destination of ICE report files"); + } PathBuf::from(s) } - None => std::env::current_dir().unwrap_or_default(), + None => config + .and_then(|unstable_opts| unstable_opts.metrics_dir.to_owned()) + .or_else(|| std::env::current_dir().ok()) + .unwrap_or_default(), }; let now: OffsetDateTime = SystemTime::now().into(); let file_now = now diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index bf54aae1cfeb0..4b87f5d62b21e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1827,6 +1827,8 @@ options! { the same values as the target option of the same name"), meta_stats: bool = (false, parse_bool, [UNTRACKED], "gather metadata statistics (default: no)"), + metrics_dir: Option = (None, parse_opt_pathbuf, [UNTRACKED], + "stores metrics about the errors being emitted by rustc to disk"), mir_emit_retag: bool = (false, parse_bool, [TRACKED], "emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \ (default: no)"), diff --git a/tests/run-make/dump-ice-to-disk/rmake.rs b/tests/run-make/dump-ice-to-disk/rmake.rs index 2fb5c825064b0..a64103fa516d6 100644 --- a/tests/run-make/dump-ice-to-disk/rmake.rs +++ b/tests/run-make/dump-ice-to-disk/rmake.rs @@ -4,6 +4,10 @@ // or full. // - Check that disabling ICE logging results in zero files created. // - Check that the ICE files contain some of the expected strings. +// - exercise the -Zmetrics-dir nightly flag +// - verify what happens when both the nightly flag and env variable are set +// - test the RUST_BACKTRACE=0 behavior against the file creation + // See https://github.com/rust-lang/rust/pull/108714 use run_make_support::{cwd, has_extension, has_prefix, rfs, rustc, shallow_find_files}; @@ -11,8 +15,8 @@ use run_make_support::{cwd, has_extension, has_prefix, rfs, rustc, shallow_find_ fn main() { rustc().input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail(); let default = get_text_from_ice(".").lines().count(); - clear_ice_files(); + clear_ice_files(); rustc().env("RUSTC_ICE", cwd()).input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail(); let ice_text = get_text_from_ice(cwd()); let default_set = ice_text.lines().count(); @@ -25,7 +29,28 @@ fn main() { ice_files.first().and_then(|f| f.file_name()).and_then(|n| n.to_str()).unwrap(); // Ensure that the ICE dump path doesn't contain `:`, because they cause problems on Windows. assert!(!ice_file_name.contains(":"), "{ice_file_name}"); + assert_eq!(default, default_set); + assert!(default > 0); + // Some of the expected strings in an ICE file should appear. + assert!(content.contains("thread 'rustc' panicked at")); + assert!(content.contains("stack backtrace:")); + + test_backtrace_short(default); + test_backtrace_full(default); + test_backtrace_disabled(default); + + clear_ice_files(); + // The ICE dump is explicitly disabled. Therefore, this should produce no files. + rustc().env("RUSTC_ICE", "0").input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail(); + let ice_files = shallow_find_files(cwd(), |path| { + has_prefix(path, "rustc-ice") && has_extension(path, "txt") + }); + assert!(ice_files.is_empty()); // There should be 0 ICE files. + + metrics_dir(default); +} +fn test_backtrace_short(baseline: usize) { clear_ice_files(); rustc() .env("RUSTC_ICE", cwd()) @@ -34,6 +59,11 @@ fn main() { .arg("-Ztreat-err-as-bug=1") .run_fail(); let short = get_text_from_ice(cwd()).lines().count(); + // backtrace length in dump shouldn't be changed by RUST_BACKTRACE + assert_eq!(short, baseline); +} + +fn test_backtrace_full(baseline: usize) { clear_ice_files(); rustc() .env("RUSTC_ICE", cwd()) @@ -42,23 +72,49 @@ fn main() { .arg("-Ztreat-err-as-bug=1") .run_fail(); let full = get_text_from_ice(cwd()).lines().count(); + // backtrace length in dump shouldn't be changed by RUST_BACKTRACE + assert_eq!(full, baseline); +} + +fn test_backtrace_disabled(baseline: usize) { clear_ice_files(); + rustc() + .env("RUSTC_ICE", cwd()) + .input("lib.rs") + .env("RUST_BACKTRACE", "0") + .arg("-Ztreat-err-as-bug=1") + .run_fail(); + let disabled = get_text_from_ice(cwd()).lines().count(); + // backtrace length in dump shouldn't be changed by RUST_BACKTRACE + assert_eq!(disabled, baseline); +} - // The ICE dump is explicitly disabled. Therefore, this should produce no files. - rustc().env("RUSTC_ICE", "0").input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail(); - let ice_files = shallow_find_files(cwd(), |path| { - has_prefix(path, "rustc-ice") && has_extension(path, "txt") - }); - assert!(ice_files.is_empty()); // There should be 0 ICE files. +fn metrics_dir(baseline: usize) { + test_flag_only(baseline); + test_flag_and_env(baseline); +} - // The line count should not change. - assert_eq!(short, default_set); - assert_eq!(short, default); - assert_eq!(full, default_set); - assert!(default > 0); - // Some of the expected strings in an ICE file should appear. - assert!(content.contains("thread 'rustc' panicked at")); - assert!(content.contains("stack backtrace:")); +fn test_flag_only(baseline: usize) { + clear_ice_files(); + let metrics_arg = format!("-Zmetrics-dir={}", cwd().display()); + rustc().input("lib.rs").arg("-Ztreat-err-as-bug=1").arg(metrics_arg).run_fail(); + let output = get_text_from_ice(cwd()).lines().count(); + assert_eq!(output, baseline); +} + +fn test_flag_and_env(baseline: usize) { + clear_ice_files(); + let metrics_arg = format!("-Zmetrics-dir={}", cwd().display()); + let real_dir = cwd().join("actually_put_ice_here"); + rfs::create_dir(real_dir.clone()); + rustc() + .input("lib.rs") + .env("RUSTC_ICE", real_dir.clone()) + .arg("-Ztreat-err-as-bug=1") + .arg(metrics_arg) + .run_fail(); + let output = get_text_from_ice(real_dir).lines().count(); + assert_eq!(output, baseline); } fn clear_ice_files() { From a70c9e1f8617aa723f8ead57903b00ff117a89f6 Mon Sep 17 00:00:00 2001 From: Felix Rath Date: Wed, 7 Aug 2024 21:58:05 +0200 Subject: [PATCH 5/7] refactor(rustc_expand::mbe): Don't require full ExtCtxt when not necessary --- compiler/rustc_expand/src/mbe/diagnostics.rs | 51 +++++++++----------- compiler/rustc_expand/src/mbe/macro_rules.rs | 5 +- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 6ce9ff18c279f..628c6bfeb7932 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -3,34 +3,32 @@ use std::borrow::Cow; use rustc_ast::token::{self, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; -use rustc_errors::{Applicability, Diag, DiagMessage}; +use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagMessage}; use rustc_macros::Subdiagnostic; use rustc_parse::parser::{Parser, Recovery}; +use rustc_session::parse::ParseSess; use rustc_span::source_map::SourceMap; use rustc_span::symbol::Ident; use rustc_span::{ErrorGuaranteed, Span}; use tracing::debug; use super::macro_rules::{parser_from_cx, NoopTracker}; -use crate::base::{DummyResult, ExtCtxt, MacResult}; use crate::expand::{parse_ast_fragment, AstFragmentKind}; use crate::mbe::macro_parser::ParseResult::*; use crate::mbe::macro_parser::{MatcherLoc, NamedParseResult, TtParser}; use crate::mbe::macro_rules::{try_match_macro, Tracker}; -pub(super) fn failed_to_match_macro<'cx>( - cx: &'cx mut ExtCtxt<'_>, +pub(super) fn failed_to_match_macro( + psess: &ParseSess, sp: Span, def_span: Span, name: Ident, arg: TokenStream, lhses: &[Vec], -) -> Box { - let psess = &cx.sess.psess; - +) -> (Span, ErrorGuaranteed) { // An error occurred, try the expansion again, tracking the expansion closely for better // diagnostics. - let mut tracker = CollectTrackerAndEmitter::new(cx, sp); + let mut tracker = CollectTrackerAndEmitter::new(psess.dcx(), sp); let try_success_result = try_match_macro(psess, name, &arg, lhses, &mut tracker); @@ -38,7 +36,7 @@ pub(super) fn failed_to_match_macro<'cx>( // Nonterminal parser recovery might turn failed matches into successful ones, // but for that it must have emitted an error already assert!( - tracker.cx.dcx().has_errors().is_some(), + tracker.dcx.has_errors().is_some(), "Macro matching returned a success on the second try" ); } @@ -50,15 +48,15 @@ pub(super) fn failed_to_match_macro<'cx>( let Some(BestFailure { token, msg: label, remaining_matcher, .. }) = tracker.best_failure else { - return DummyResult::any(sp, cx.dcx().span_delayed_bug(sp, "failed to match a macro")); + return (sp, psess.dcx().span_delayed_bug(sp, "failed to match a macro")); }; let span = token.span.substitute_dummy(sp); - let mut err = cx.dcx().struct_span_err(span, parse_failure_msg(&token, None)); + let mut err = psess.dcx().struct_span_err(span, parse_failure_msg(&token, None)); err.span_label(span, label); - if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) { - err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro"); + if !def_span.is_dummy() && !psess.source_map().is_imported(def_span) { + err.span_label(psess.source_map().guess_head_span(def_span), "when calling this macro"); } annotate_doc_comment(&mut err, psess.source_map(), span); @@ -76,7 +74,7 @@ pub(super) fn failed_to_match_macro<'cx>( err.note("captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens"); err.note("see for more information"); - if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) { + if !def_span.is_dummy() && !psess.source_map().is_imported(def_span) { err.help("try using `:tt` instead in the macro definition"); } } @@ -104,18 +102,17 @@ pub(super) fn failed_to_match_macro<'cx>( } } let guar = err.emit(); - cx.trace_macros_diag(); - DummyResult::any(sp, guar) + (sp, guar) } /// The tracker used for the slow error path that collects useful info for diagnostics. -struct CollectTrackerAndEmitter<'a, 'cx, 'matcher> { - cx: &'a mut ExtCtxt<'cx>, +struct CollectTrackerAndEmitter<'dcx, 'matcher> { + dcx: DiagCtxtHandle<'dcx>, remaining_matcher: Option<&'matcher MatcherLoc>, /// Which arm's failure should we report? (the one furthest along) best_failure: Option, root_span: Span, - result: Option>, + result: Option<(Span, ErrorGuaranteed)>, } struct BestFailure { @@ -131,7 +128,7 @@ impl BestFailure { } } -impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, 'matcher> { +impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'matcher> { type Failure = (Token, u32, &'static str); fn build_failure(tok: Token, position: u32, msg: &'static str) -> Self::Failure { @@ -151,7 +148,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, Success(_) => { // Nonterminal parser recovery might turn failed matches into successful ones, // but for that it must have emitted an error already - self.cx.dcx().span_delayed_bug( + self.dcx.span_delayed_bug( self.root_span, "should not collect detailed info for successful macro match", ); @@ -177,10 +174,10 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, } Error(err_sp, msg) => { let span = err_sp.substitute_dummy(self.root_span); - let guar = self.cx.dcx().span_err(span, msg.clone()); - self.result = Some(DummyResult::any(span, guar)); + let guar = self.dcx.span_err(span, msg.clone()); + self.result = Some((span, guar)); } - ErrorReported(guar) => self.result = Some(DummyResult::any(self.root_span, *guar)), + ErrorReported(guar) => self.result = Some((self.root_span, *guar)), } } @@ -193,9 +190,9 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, } } -impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx, '_> { - fn new(cx: &'a mut ExtCtxt<'cx>, root_span: Span) -> Self { - Self { cx, remaining_matcher: None, best_failure: None, root_span, result: None } +impl<'dcx> CollectTrackerAndEmitter<'dcx, '_> { + fn new(dcx: DiagCtxtHandle<'dcx>, root_span: Span) -> Self { + Self { dcx, remaining_matcher: None, best_failure: None, root_span, result: None } } } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 1502177563d9b..6f177107e7025 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -268,7 +268,10 @@ fn expand_macro<'cx>( } Err(CanRetry::Yes) => { // Retry and emit a better error. - diagnostics::failed_to_match_macro(cx, sp, def_span, name, arg, lhses) + let (span, guar) = + diagnostics::failed_to_match_macro(cx.psess(), sp, def_span, name, arg, lhses); + cx.trace_macros_diag(); + DummyResult::any(span, guar) } } } From 5db9d432070087c13330e85221010671174025d5 Mon Sep 17 00:00:00 2001 From: Jeff Martin Date: Wed, 7 Aug 2024 16:08:41 -0400 Subject: [PATCH 6/7] Fuchsia Test Runner: enable ffx repository server The default repository server setting has changed on Fuchsia (default is newly "false"). Now, in order to start the repository server, the config `repository.server.enabled` must be set to true. --- src/ci/docker/scripts/fuchsia-test-runner.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py index 00269e68422d3..a5458b8645d7f 100755 --- a/src/ci/docker/scripts/fuchsia-test-runner.py +++ b/src/ci/docker/scripts/fuchsia-test-runner.py @@ -571,6 +571,19 @@ def start(self): ) # Start repository server + # Note that we must first enable the repository server daemon. + check_call_with_logging( + [ + ffx_path, + "config", + "set", + "repository.server.enabled", + "true", + ], + env=ffx_env, + stdout_handler=self.subprocess_logger.debug, + stderr_handler=self.subprocess_logger.debug, + ) check_call_with_logging( [ ffx_path, From 0257f42089c11511e67f3ab1086f1be85eca829e Mon Sep 17 00:00:00 2001 From: ltdk Date: Wed, 7 Aug 2024 20:43:05 -0400 Subject: [PATCH 7/7] Add tracking issue to core-pattern-type --- library/core/src/lib.rs | 2 +- library/core/src/pat.rs | 2 +- library/std/src/lib.rs | 2 +- .../ui/type/pattern_types/feature-gate-pattern_types.stderr | 5 +++++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e74900ff7471b..9d4520d4ee813 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -391,7 +391,7 @@ pub mod net; pub mod option; pub mod panic; pub mod panicking; -#[unstable(feature = "core_pattern_types", issue = "none")] +#[unstable(feature = "core_pattern_types", issue = "123646")] pub mod pat; pub mod pin; #[unstable(feature = "new_range_api", issue = "125687")] diff --git a/library/core/src/pat.rs b/library/core/src/pat.rs index a10c45933428d..1f89d960be67b 100644 --- a/library/core/src/pat.rs +++ b/library/core/src/pat.rs @@ -6,7 +6,7 @@ /// ``` #[macro_export] #[rustc_builtin_macro(pattern_type)] -#[unstable(feature = "core_pattern_type", issue = "none")] +#[unstable(feature = "core_pattern_type", issue = "123646")] macro_rules! pattern_type { ($($arg:tt)*) => { /* compiler built-in */ diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 67405d788bd9b..7fc1bc46fef84 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -586,7 +586,7 @@ pub mod net; pub mod num; pub mod os; pub mod panic; -#[unstable(feature = "core_pattern_types", issue = "none")] +#[unstable(feature = "core_pattern_types", issue = "123646")] pub mod pat; pub mod path; #[unstable(feature = "anonymous_pipe", issue = "127154")] diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr index 6f74b89d2247b..03e91b52a2aae 100644 --- a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr @@ -4,6 +4,7 @@ error[E0658]: use of unstable library feature 'core_pattern_type' LL | type NonNullU32 = pattern_type!(u32 is 1..); | ^^^^^^^^^^^^ | + = note: see issue #123646 for more information = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -13,6 +14,7 @@ error[E0658]: use of unstable library feature 'core_pattern_type' LL | type Percent = pattern_type!(u32 is 0..=100); | ^^^^^^^^^^^^ | + = note: see issue #123646 for more information = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -22,6 +24,7 @@ error[E0658]: use of unstable library feature 'core_pattern_type' LL | type Negative = pattern_type!(i32 is ..=0); | ^^^^^^^^^^^^ | + = note: see issue #123646 for more information = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -31,6 +34,7 @@ error[E0658]: use of unstable library feature 'core_pattern_type' LL | type Positive = pattern_type!(i32 is 0..); | ^^^^^^^^^^^^ | + = note: see issue #123646 for more information = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -40,6 +44,7 @@ error[E0658]: use of unstable library feature 'core_pattern_type' LL | type Always = pattern_type!(Option is Some(_)); | ^^^^^^^^^^^^ | + = note: see issue #123646 for more information = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date