Auto merge of #128805 - tgross35:rollup-wajzi6w, r=tgross35
Rollup of 7 pull requests Successful merges: - #128520 (Skip over args when determining if async-closure's inner coroutine consumes its upvars) - #128552 (Emit an error for invalid use of the `#[no_sanitize]` attribute) - #128691 (Update `compiler-builtins` to 0.1.117) - #128702 (Add -Zmetrics-dir=PATH to save diagnostic metadata to disk) - #128797 (Fuchsia Test Runner: enable ffx repository server) - #128798 (refactor(rustc_expand::mbe): Don't require full ExtCtxt when not necessary) - #128800 (Add tracking issue to core-pattern-type) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
9337f7afa6
1
.gitignore
vendored
1
.gitignore
vendored
@ -19,6 +19,7 @@ Session.vim
|
||||
*.iml
|
||||
.vscode
|
||||
.project
|
||||
.vim/
|
||||
.favorites.json
|
||||
.settings/
|
||||
.vs/
|
||||
|
@ -51,7 +51,8 @@
|
||||
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<Option<PathBuf>> = 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<PathBuf> {
|
||||
ice_path_with_config(None)
|
||||
}
|
||||
|
||||
fn ice_path_with_config(config: Option<&UnstableOptions>) -> &'static Option<PathBuf> {
|
||||
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
|
||||
|
@ -3,34 +3,32 @@
|
||||
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<MatcherLoc>],
|
||||
) -> Box<dyn MacResult + 'cx> {
|
||||
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 <https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment> 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<BestFailure>,
|
||||
root_span: Span,
|
||||
result: Option<Box<dyn MacResult + 'cx>>,
|
||||
result: Option<(Span, ErrorGuaranteed)>,
|
||||
}
|
||||
|
||||
struct BestFailure {
|
||||
@ -131,7 +128,7 @@ fn is_better_position(&self, position: u32) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ fn after_arm(&mut self, result: &NamedParseResult<Self::Failure>) {
|
||||
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 @@ fn after_arm(&mut self, result: &NamedParseResult<Self::Failure>) {
|
||||
}
|
||||
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 @@ fn recovery() -> Recovery {
|
||||
}
|
||||
}
|
||||
|
||||
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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +219,8 @@ fn analyze_closure(
|
||||
// `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 @@ fn analyze_closure(
|
||||
// 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 @@ fn analyze_closure(
|
||||
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 @@ fn analyze_closure(
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<Ty<'tcx>> {
|
||||
self.typeck_results
|
||||
|
@ -125,6 +125,7 @@ fn check_attributes(
|
||||
[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, ..] => {
|
||||
@ -256,7 +257,6 @@ fn check_attributes(
|
||||
| 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
|
||||
@ -451,6 +451,11 @@ fn check_optimize(&self, hir_id: HirId, attr: &Attribute, target: Target) {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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,
|
||||
|
@ -1827,6 +1827,8 @@ pub(crate) fn parse_wasm_c_abi(slot: &mut WasmCAbi, v: Option<&str>) -> bool {
|
||||
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<PathBuf> = (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)"),
|
||||
|
@ -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",
|
||||
|
@ -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"] }
|
||||
|
@ -391,7 +391,7 @@ pub mod assert_matches {
|
||||
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")]
|
||||
|
@ -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 */
|
||||
|
@ -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 = [
|
||||
|
@ -586,7 +586,7 @@
|
||||
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")]
|
||||
|
@ -571,6 +571,19 @@ class TestEnvironment:
|
||||
)
|
||||
|
||||
# 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,
|
||||
|
@ -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 @@
|
||||
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() {
|
||||
|
@ -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;
|
||||
});
|
||||
}
|
34
tests/ui/attributes/no-sanitize.rs
Normal file
34
tests/ui/attributes/no-sanitize.rs
Normal file
@ -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() {}
|
55
tests/ui/attributes/no-sanitize.stderr
Normal file
55
tests/ui/attributes/no-sanitize.stderr
Normal file
@ -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
|
||||
|
@ -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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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<u32> is Some(_));
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #123646 <https://github.com/rust-lang/rust/issues/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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user