diff --git a/Cargo.lock b/Cargo.lock index 117295014e6b8..46b0a01a18ec5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4243,6 +4243,8 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", + "serde", + "serde_json", "smallvec", "tracing", ] diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 0daeecb53a8b9..69a9a58304837 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -34,7 +34,7 @@ pub enum LitError { InvalidIntSuffix, InvalidFloatSuffix, NonDecimalFloat(u32), - IntTooLarge, + IntTooLarge(u32), } impl LitKind { @@ -333,6 +333,6 @@ fn integer_lit(symbol: Symbol, suffix: Option) -> Result= base)); - if from_lexer { LitError::LexerError } else { LitError::IntTooLarge } + if from_lexer { LitError::LexerError } else { LitError::IntTooLarge(base) } }) } diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl index ab9e8b6baae6a..bc37d91a7c6af 100644 --- a/compiler/rustc_error_messages/locales/en-US/session.ftl +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -85,6 +85,7 @@ session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float lite .help = valid suffixes are `f32` and `f64` session_int_literal_too_large = integer literal is too large + .note = value exceeds limit of `{$limit}` session_invalid_int_literal_width = invalid width `{$width}` for integer literal .help = valid widths are 8, 16, 32, 64 and 128 diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 1ff7429e415f8..cf847047c906f 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -17,6 +17,7 @@ use crate::astconv::AstConv; use crate::check::intrinsic::intrinsic_operation_unsafety; use crate::errors; +use hir::def::DefKind; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey}; @@ -24,8 +25,8 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{GenericParamKind, Node}; -use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; use rustc_middle::ty::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; @@ -1195,12 +1196,11 @@ fn infer_return_ty_for_fn_sig<'tcx>( ty::ReErased => tcx.lifetimes.re_static, _ => r, }); - let fn_sig = ty::Binder::dummy(fn_sig); let mut visitor = HirPlaceholderCollector::default(); visitor.visit_ty(ty); let mut diag = bad_placeholder(tcx, visitor.0, "return type"); - let ret_ty = fn_sig.skip_binder().output(); + let ret_ty = fn_sig.output(); if ret_ty.is_suggestable(tcx, false) { diag.span_suggestion( ty.span, @@ -1223,26 +1223,26 @@ fn infer_return_ty_for_fn_sig<'tcx>( Applicability::MachineApplicable, ); } + } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, hir_id, def_id) { + diag.span_suggestion( + ty.span, + "replace with an appropriate return type", + sugg, + Applicability::MachineApplicable, + ); } else if ret_ty.is_closure() { - // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds - // to prevent the user from getting a papercut while trying to use the unique closure - // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`). diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound"); + } + // Also note how `Fn` traits work just in case! + if ret_ty.is_closure() { diag.note( "for more information on `Fn` traits and closure types, see \ https://doc.rust-lang.org/book/ch13-01-closures.html", ); - } else if let Some(i_ty) = suggest_impl_iterator(tcx, ret_ty, ty.span, hir_id, def_id) { - diag.span_suggestion( - ty.span, - "replace with an appropriate return type", - format!("impl Iterator", i_ty), - Applicability::MachineApplicable, - ); } diag.emit(); - fn_sig + ty::Binder::dummy(fn_sig) } None => >::ty_of_fn( icx, @@ -1256,47 +1256,94 @@ fn infer_return_ty_for_fn_sig<'tcx>( } } -fn suggest_impl_iterator<'tcx>( +fn suggest_impl_trait<'tcx>( tcx: TyCtxt<'tcx>, ret_ty: Ty<'tcx>, span: Span, hir_id: hir::HirId, def_id: LocalDefId, -) -> Option> { - let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) else { return None; }; - let Some(iterator_item) = tcx.get_diagnostic_item(sym::IteratorItem) else { return None; }; - if !tcx - .infer_ctxt() - .build() - .type_implements_trait(iter_trait, [ret_ty], tcx.param_env(def_id)) - .must_apply_modulo_regions() - { - return None; - } - let infcx = tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new_in_snapshot(&infcx); - // Find the type of `Iterator::Item`. - let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }; - let ty_var = infcx.next_ty_var(origin); - let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection( - ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(iterator_item, tcx.mk_substs([ret_ty.into()].iter())), - term: ty_var.into(), - }, - ))); - // Add `::Item = _` obligation. - ocx.register_obligation(crate::traits::Obligation::misc( - tcx, - span, - hir_id, - tcx.param_env(def_id), - projection, - )); - if ocx.select_where_possible().is_empty() - && let item_ty = infcx.resolve_vars_if_possible(ty_var) - && item_ty.is_suggestable(tcx, false) - { - return Some(item_ty); +) -> Option { + let format_as_assoc: fn(_, _, _, _, _) -> _ = + |tcx: TyCtxt<'tcx>, + _: ty::SubstsRef<'tcx>, + trait_def_id: DefId, + assoc_item_def_id: DefId, + item_ty: Ty<'tcx>| { + let trait_name = tcx.item_name(trait_def_id); + let assoc_name = tcx.item_name(assoc_item_def_id); + Some(format!("impl {trait_name}<{assoc_name} = {item_ty}>")) + }; + let format_as_parenthesized: fn(_, _, _, _, _) -> _ = + |tcx: TyCtxt<'tcx>, + substs: ty::SubstsRef<'tcx>, + trait_def_id: DefId, + _: DefId, + item_ty: Ty<'tcx>| { + let trait_name = tcx.item_name(trait_def_id); + let args_tuple = substs.type_at(1); + let ty::Tuple(types) = *args_tuple.kind() else { return None; }; + if !types.is_suggestable(tcx, false) { + return None; + } + let maybe_ret = + if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") }; + Some(format!( + "impl {trait_name}({}){maybe_ret}", + types.iter().map(|ty| ty.to_string()).collect::>().join(", ") + )) + }; + + for (trait_def_id, assoc_item_def_id, formatter) in [ + ( + tcx.get_diagnostic_item(sym::Iterator), + tcx.get_diagnostic_item(sym::IteratorItem), + format_as_assoc, + ), + ( + tcx.lang_items().future_trait(), + tcx.get_diagnostic_item(sym::FutureOutput), + format_as_assoc, + ), + (tcx.lang_items().fn_trait(), tcx.lang_items().fn_once_output(), format_as_parenthesized), + ( + tcx.lang_items().fn_mut_trait(), + tcx.lang_items().fn_once_output(), + format_as_parenthesized, + ), + ( + tcx.lang_items().fn_once_trait(), + tcx.lang_items().fn_once_output(), + format_as_parenthesized, + ), + ] { + let Some(trait_def_id) = trait_def_id else { continue; }; + let Some(assoc_item_def_id) = assoc_item_def_id else { continue; }; + if tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy { + continue; + } + let param_env = tcx.param_env(def_id); + let infcx = tcx.infer_ctxt().build(); + let substs = ty::InternalSubsts::for_item(tcx, trait_def_id, |param, _| { + if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(span, param) } + }); + if !infcx.type_implements_trait(trait_def_id, substs, param_env).must_apply_modulo_regions() + { + continue; + } + let ocx = ObligationCtxt::new_in_snapshot(&infcx); + let item_ty = ocx.normalize( + &ObligationCause::misc(span, hir_id), + param_env, + tcx.mk_projection(assoc_item_def_id, substs), + ); + // FIXME(compiler-errors): We may benefit from resolving regions here. + if ocx.select_where_possible().is_empty() + && let item_ty = infcx.resolve_vars_if_possible(item_ty) + && item_ty.is_suggestable(tcx, false) + && let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(substs), trait_def_id, assoc_item_def_id, item_ty) + { + return Some(sugg); + } } None } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index eb3baba999b9c..9ec71c6b87edf 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -3,17 +3,16 @@ use crate::interface::parse_cfgspecs; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; -use rustc_session::config::InstrumentCoverage; -use rustc_session::config::Strip; +use rustc_session::config::rustc_optgroups; use rustc_session::config::{build_configuration, build_session_options, to_crate_config}; -use rustc_session::config::{ - rustc_optgroups, ErrorOutputType, ExternLocation, LocationDetail, Options, Passes, -}; use rustc_session::config::{ BranchProtection, Externs, OomStrategy, OutputType, OutputTypes, PAuthKey, PacRet, ProcMacroExecutionStrategy, SymbolManglingVersion, WasiExecModel, }; use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; +use rustc_session::config::{DumpMonoStatsFormat, MirSpanview}; +use rustc_session::config::{ErrorOutputType, ExternLocation, LocationDetail, Options, Strip}; +use rustc_session::config::{InstrumentCoverage, Passes}; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; @@ -647,6 +646,9 @@ fn test_unstable_options_tracking_hash() { untracked!(dump_mir_dir, String::from("abc")); untracked!(dump_mir_exclude_pass_number, true); untracked!(dump_mir_graphviz, true); + untracked!(dump_mir_spanview, Some(MirSpanview::Statement)); + untracked!(dump_mono_stats, SwitchWithOptPath::Enabled(Some("mono-items-dir/".into()))); + untracked!(dump_mono_stats_format, DumpMonoStatsFormat::Json); untracked!(dylib_lto, true); untracked!(emit_stack_sizes, true); untracked!(future_incompat_test, true); diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index 6ee5330b63f51..c8af10576b42f 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -6,6 +6,8 @@ edition = "2021" [lib] [dependencies] +serde = "1" +serde_json = "1" smallvec = { version = "1.8.1", features = [ "union", "may_dangle" ] } tracing = "0.1" rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index 4f25fc71314ea..97fbb458e792a 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -102,14 +102,14 @@ use std::path::{Path, PathBuf}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync; -use rustc_hir::def_id::DefIdSet; +use rustc_hir::def_id::{DefIdSet, LOCAL_CRATE}; use rustc_middle::mir; use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::{CodegenUnit, Linkage}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; -use rustc_session::config::SwitchWithOptPath; +use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath}; use rustc_span::symbol::Symbol; use crate::collector::InliningMap; @@ -417,7 +417,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co // Output monomorphization stats per def_id if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats { if let Err(err) = - dump_mono_items_stats(tcx, &codegen_units, path, tcx.sess.opts.crate_name.as_deref()) + dump_mono_items_stats(tcx, &codegen_units, path, tcx.crate_name(LOCAL_CRATE)) { tcx.sess.emit_fatal(CouldntDumpMonoStats { error: err.to_string() }); } @@ -483,7 +483,7 @@ fn dump_mono_items_stats<'tcx>( tcx: TyCtxt<'tcx>, codegen_units: &[CodegenUnit<'tcx>], output_directory: &Option, - crate_name: Option<&str>, + crate_name: Symbol, ) -> Result<(), Box> { let output_directory = if let Some(ref directory) = output_directory { fs::create_dir_all(directory)?; @@ -492,9 +492,11 @@ fn dump_mono_items_stats<'tcx>( Path::new(".") }; - let filename = format!("{}.mono_items.md", crate_name.unwrap_or("unknown-crate")); + let format = tcx.sess.opts.unstable_opts.dump_mono_stats_format; + let ext = format.extension(); + let filename = format!("{crate_name}.mono_items.{ext}"); let output_path = output_directory.join(&filename); - let file = File::create(output_path)?; + let file = File::create(&output_path)?; let mut file = BufWriter::new(file); // Gather instantiated mono items grouped by def_id @@ -508,30 +510,44 @@ fn dump_mono_items_stats<'tcx>( } } + #[derive(serde::Serialize)] + struct MonoItem { + name: String, + instantiation_count: usize, + size_estimate: usize, + total_estimate: usize, + } + // Output stats sorted by total instantiated size, from heaviest to lightest let mut stats: Vec<_> = items_per_def_id .into_iter() .map(|(def_id, items)| { + let name = with_no_trimmed_paths!(tcx.def_path_str(def_id)); let instantiation_count = items.len(); let size_estimate = items[0].size_estimate(tcx); let total_estimate = instantiation_count * size_estimate; - (def_id, instantiation_count, size_estimate, total_estimate) + MonoItem { name, instantiation_count, size_estimate, total_estimate } }) .collect(); - stats.sort_unstable_by_key(|(_, _, _, total_estimate)| cmp::Reverse(*total_estimate)); + stats.sort_unstable_by_key(|item| cmp::Reverse(item.total_estimate)); if !stats.is_empty() { - writeln!( - file, - "| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |" - )?; - writeln!(file, "| --- | ---: | ---: | ---: |")?; - for (def_id, instantiation_count, size_estimate, total_estimate) in stats { - let item = with_no_trimmed_paths!(tcx.def_path_str(def_id)); - writeln!( - file, - "| {item} | {instantiation_count} | {size_estimate} | {total_estimate} |" - )?; + match format { + DumpMonoStatsFormat::Json => serde_json::to_writer(file, &stats)?, + DumpMonoStatsFormat::Markdown => { + writeln!( + file, + "| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |" + )?; + writeln!(file, "| --- | ---: | ---: | ---: |")?; + + for MonoItem { name, instantiation_count, size_estimate, total_estimate } in stats { + writeln!( + file, + "| `{name}` | {instantiation_count} | {size_estimate} | {total_estimate} |" + )?; + } + } } } diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index b2111a1262a3c..46e77626479c8 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -4,7 +4,7 @@ version = "0.0.0" edition = "2021" [lib] -doctest = false + [dependencies] measureme = "10.0.0" diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 02e3992a6a940..5f78f6d079d01 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2981,3 +2981,21 @@ pub enum ProcMacroExecutionStrategy { /// Run the proc-macro code on a different thread. CrossThread, } + +/// Which format to use for `-Z dump-mono-stats` +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum DumpMonoStatsFormat { + /// Pretty-print a markdown table + Markdown, + /// Emit structured JSON + Json, +} + +impl DumpMonoStatsFormat { + pub fn extension(self) -> &'static str { + match self { + Self::Markdown => "md", + Self::Json => "json", + } + } +} diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index e72b76cfee9e9..f5a72573d58cd 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -260,9 +260,11 @@ pub(crate) struct InvalidFloatLiteralSuffix { #[derive(Diagnostic)] #[diag(session_int_literal_too_large)] +#[note] pub(crate) struct IntLiteralTooLarge { #[primary_span] pub span: Span, + pub limit: String, } #[derive(Diagnostic)] @@ -361,8 +363,15 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: _ => unreachable!(), }; } - LitError::IntTooLarge => { - sess.emit_err(IntLiteralTooLarge { span }); + LitError::IntTooLarge(base) => { + let max = u128::MAX; + let limit = match base { + 2 => format!("{max:#b}"), + 8 => format!("{max:#o}"), + 16 => format!("{max:#x}"), + _ => format!("{max}"), + }; + sess.emit_err(IntLiteralTooLarge { span, limit }); } } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 9bf581ff73d23..b379aef80fb2e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -377,6 +377,7 @@ mod desc { pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`"; + pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`"; pub const parse_instrument_coverage: &str = "`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`"; pub const parse_unpretty: &str = "`string` or `string=string`"; @@ -820,6 +821,21 @@ mod parse { true } + pub(crate) fn parse_dump_mono_stats(slot: &mut DumpMonoStatsFormat, v: Option<&str>) -> bool { + match v { + None => true, + Some("json") => { + *slot = DumpMonoStatsFormat::Json; + true + } + Some("markdown") => { + *slot = DumpMonoStatsFormat::Markdown; + true + } + Some(_) => false, + } + } + pub(crate) fn parse_instrument_coverage( slot: &mut Option, v: Option<&str>, @@ -1295,7 +1311,9 @@ options! { an additional `.html` file showing the computed coverage spans."), dump_mono_stats: SwitchWithOptPath = (SwitchWithOptPath::Disabled, parse_switch_with_opt_path, [UNTRACKED], - "output statistics about monomorphization collection (format: markdown)"), + "output statistics about monomorphization collection"), + dump_mono_stats_format: DumpMonoStatsFormat = (DumpMonoStatsFormat::Markdown, parse_dump_mono_stats, [UNTRACKED], + "the format to use for -Z dump-mono-stats (`markdown` (default) or `json`)"), dwarf_version: Option = (None, parse_opt_number, [TRACKED], "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"), dylib_lto: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 85510fa2c660c..5d5f8d6d65405 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -193,6 +193,7 @@ symbols! { FromIterator, FromResidual, Future, + FutureOutput, FxHashMap, FxHashSet, GlobalAlloc, diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs index f29d3e1e98b72..8c7111cb3ff0b 100644 --- a/library/core/src/future/future.rs +++ b/library/core/src/future/future.rs @@ -37,6 +37,7 @@ use crate::task::{Context, Poll}; pub trait Future { /// The type of value produced on completion. #[stable(feature = "futures_api", since = "1.36.0")] + #[rustc_diagnostic_item = "FutureOutput"] type Output; /// Attempt to resolve the future to a final value, registering diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index 6e4ba1404e551..fcc5cfafd808d 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -3,6 +3,7 @@ //! This module contains a set of macros which are exported from the standard //! library. Each macro is available for use when linking against the standard //! library. +// ignore-tidy-dbg #[doc = include_str!("../../core/src/macros/panic.md")] #[macro_export] diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs index 05de51f8cc579..e0280854541a0 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/run.rs @@ -105,6 +105,7 @@ impl Step for BumpStage0 { fn run(self, builder: &Builder<'_>) -> Self::Output { let mut cmd = builder.tool_cmd(Tool::BumpStage0); + cmd.args(builder.config.cmd.args()); builder.run(&mut cmd); } } diff --git a/src/doc/unstable-book/src/compiler-flags/dump-mono-stats-format.md b/src/doc/unstable-book/src/compiler-flags/dump-mono-stats-format.md new file mode 100644 index 0000000000000..a497a75261fed --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/dump-mono-stats-format.md @@ -0,0 +1,6 @@ +# `dump-mono-stats-format` + +-------------------- + +The `-Z dump-mono-stats-format` compiler flag controls what file format to use for `-Z dump-mono-stats`. +The default is markdown; currently JSON is also supported. JSON can be useful for programatically manipulating the results (e.g. to find the item that took the longest to compile). diff --git a/src/doc/unstable-book/src/compiler-flags/dump-mono-stats.md b/src/doc/unstable-book/src/compiler-flags/dump-mono-stats.md new file mode 100644 index 0000000000000..4c8bc8b457898 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/dump-mono-stats.md @@ -0,0 +1,14 @@ +# `dump-mono-stats` + +-------------------- + +The `-Z dump-mono-stats` compiler flag generates a file with a list of the monomorphized items in the current crate. +It is useful for investigating compile times. + +It accepts an optional directory where the file will be located. If no directory is specified, the file will be placed in the current directory. + +See also `-Z dump-mono-stats-format` and `-Z print-mono-items`. Unlike `print-mono-items`, +`dump-mono-stats` aggregates monomorphized items by definition and includes a size estimate of how +large the item is when codegened. + +See for an overview of monomorphized items. diff --git a/src/test/codegen/box-maybe-uninit-llvm14.rs b/src/test/codegen/box-maybe-uninit-llvm14.rs index bd1a6599c3365..7b5ae894311ef 100644 --- a/src/test/codegen/box-maybe-uninit-llvm14.rs +++ b/src/test/codegen/box-maybe-uninit-llvm14.rs @@ -2,7 +2,7 @@ // Once we're done with llvm 14 and earlier, this test can be deleted. -#![crate_type="lib"] +#![crate_type = "lib"] use std::mem::MaybeUninit; @@ -17,8 +17,16 @@ pub fn box_uninitialized() -> Box> { Box::new(MaybeUninit::uninit()) } -// FIXME: add a test for a bigger box. Currently broken, see -// https://github.com/rust-lang/rust/issues/58201. +// https://github.com/rust-lang/rust/issues/58201 +#[no_mangle] +pub fn box_uninitialized2() -> Box> { + // CHECK-LABEL: @box_uninitialized2 + // CHECK-NOT: store + // CHECK-NOT: alloca + // CHECK-NOT: memcpy + // CHECK-NOT: memset + Box::new(MaybeUninit::uninit()) +} // Hide the LLVM 15+ `allocalign` attribute in the declaration of __rust_alloc // from the CHECK-NOT above. We don't check the attributes here because we can't rely diff --git a/src/test/codegen/box-maybe-uninit.rs b/src/test/codegen/box-maybe-uninit.rs index e105e26f16a23..c82b56a71f5cf 100644 --- a/src/test/codegen/box-maybe-uninit.rs +++ b/src/test/codegen/box-maybe-uninit.rs @@ -1,6 +1,6 @@ // compile-flags: -O // min-llvm-version: 15.0 -#![crate_type="lib"] +#![crate_type = "lib"] use std::mem::MaybeUninit; @@ -15,8 +15,16 @@ pub fn box_uninitialized() -> Box> { Box::new(MaybeUninit::uninit()) } -// FIXME: add a test for a bigger box. Currently broken, see -// https://github.com/rust-lang/rust/issues/58201. +// https://github.com/rust-lang/rust/issues/58201 +#[no_mangle] +pub fn box_uninitialized2() -> Box> { + // CHECK-LABEL: @box_uninitialized2 + // CHECK-NOT: store + // CHECK-NOT: alloca + // CHECK-NOT: memcpy + // CHECK-NOT: memset + Box::new(MaybeUninit::uninit()) +} // Hide the `allocalign` attribute in the declaration of __rust_alloc // from the CHECK-NOT above, and also verify the attributes got set reasonably. diff --git a/src/test/run-make/dump-mono-stats/Makefile b/src/test/run-make/dump-mono-stats/Makefile new file mode 100644 index 0000000000000..fe1112fb0a4a8 --- /dev/null +++ b/src/test/run-make/dump-mono-stats/Makefile @@ -0,0 +1,5 @@ +include ../../run-make-fulldeps/tools.mk + +all: + $(RUSTC) --crate-type lib foo.rs -Z dump-mono-stats=$(TMPDIR) -Zdump-mono-stats-format=json + cat $(TMPDIR)/foo.mono_items.json | $(CGREP) '"name":"bar"' diff --git a/src/test/run-make/dump-mono-stats/foo.rs b/src/test/run-make/dump-mono-stats/foo.rs new file mode 100644 index 0000000000000..c5c0bc606cd69 --- /dev/null +++ b/src/test/run-make/dump-mono-stats/foo.rs @@ -0,0 +1 @@ +pub fn bar() {} diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout index 53677b1837709..9bd6c5fedf542 100644 --- a/src/test/rustdoc-ui/z-help.stdout +++ b/src/test/rustdoc-ui/z-help.stdout @@ -35,7 +35,8 @@ -Z dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no) -Z dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no) -Z dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans. - -Z dump-mono-stats=val -- output statistics about monomorphization collection (format: markdown) + -Z dump-mono-stats=val -- output statistics about monomorphization collection + -Z dump-mono-stats-format=val -- the format to use for -Z dump-mono-stats (`markdown` (default) or `json`) -Z dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform) -Z dylib-lto=val -- enables LTO for dylib crate type -Z emit-stack-sizes=val -- emit a section containing stack size metadata (default: no) diff --git a/src/test/ui/fn/issue-80179.rs b/src/test/ui/fn/issue-80179.rs index fcef6f1b60ecf..35e39bebb29ab 100644 --- a/src/test/ui/fn/issue-80179.rs +++ b/src/test/ui/fn/issue-80179.rs @@ -18,9 +18,9 @@ fn returns_fn_ptr() -> _ { fn returns_closure() -> _ { //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] //~| NOTE not allowed in type signatures -//~| HELP consider using an `Fn`, `FnMut`, or `FnOnce` trait bound -//~| NOTE for more information on `Fn` traits and closure types, see -// https://doc.rust-lang.org/book/ch13-01-closures.html +//~| HELP replace with an appropriate return type +//~| SUGGESTION impl Fn() -> i32 +//~| NOTE for more information on `Fn` traits and closure types || 0 } diff --git a/src/test/ui/fn/issue-80179.stderr b/src/test/ui/fn/issue-80179.stderr index 2ca4ae982d96f..f5d6c44db7511 100644 --- a/src/test/ui/fn/issue-80179.stderr +++ b/src/test/ui/fn/issue-80179.stderr @@ -11,9 +11,11 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/issue-80179.rs:18:25 | LL | fn returns_closure() -> _ { - | ^ not allowed in type signatures + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl Fn() -> i32` | - = help: consider using an `Fn`, `FnMut`, or `FnOnce` trait bound = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html error: aborting due to 2 previous errors diff --git a/src/test/ui/fn/suggest-return-closure.rs b/src/test/ui/fn/suggest-return-closure.rs new file mode 100644 index 0000000000000..33daa1ea0b400 --- /dev/null +++ b/src/test/ui/fn/suggest-return-closure.rs @@ -0,0 +1,34 @@ +fn fn_once() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + //~| NOTE not allowed in type signatures + //~| HELP replace with an appropriate return type + //~| SUGGESTION impl FnOnce() + //~| NOTE for more information on `Fn` traits and closure types + let x = String::new(); + || { + drop(x); + } +} + +fn fn_mut() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + //~| NOTE not allowed in type signatures + //~| HELP replace with an appropriate return type + //~| SUGGESTION impl FnMut(char) + //~| NOTE for more information on `Fn` traits and closure types + let x = String::new(); + |c| { + x.push(c); + } +} + +fn fun() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + //~| NOTE not allowed in type signatures + //~| HELP replace with an appropriate return type + //~| SUGGESTION impl Fn() -> i32 + //~| NOTE for more information on `Fn` traits and closure types + || 1i32 +} + +fn main() {} diff --git a/src/test/ui/fn/suggest-return-closure.stderr b/src/test/ui/fn/suggest-return-closure.stderr new file mode 100644 index 0000000000000..341044469ea37 --- /dev/null +++ b/src/test/ui/fn/suggest-return-closure.stderr @@ -0,0 +1,36 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-return-closure.rs:1:17 + | +LL | fn fn_once() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl FnOnce()` + | + = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-return-closure.rs:13:16 + | +LL | fn fn_mut() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl FnMut(char)` + | + = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-return-closure.rs:25:13 + | +LL | fn fun() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl Fn() -> i32` + | + = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/fn/suggest-return-future.rs b/src/test/ui/fn/suggest-return-future.rs new file mode 100644 index 0000000000000..750740d942610 --- /dev/null +++ b/src/test/ui/fn/suggest-return-future.rs @@ -0,0 +1,23 @@ +// edition: 2021 + +async fn a() -> i32 { + 0 +} + +fn foo() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + //~| NOTE not allowed in type signatures + //~| HELP replace with an appropriate return type + //~| SUGGESTION impl Future + a() +} + +fn bar() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + //~| NOTE not allowed in type signatures + //~| HELP replace with an appropriate return type + //~| SUGGESTION impl Future + async { a().await } +} + +fn main() {} diff --git a/src/test/ui/fn/suggest-return-future.stderr b/src/test/ui/fn/suggest-return-future.stderr new file mode 100644 index 0000000000000..a4c8b5d8c4b5d --- /dev/null +++ b/src/test/ui/fn/suggest-return-future.stderr @@ -0,0 +1,21 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-return-future.rs:7:13 + | +LL | fn foo() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl Future` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-return-future.rs:15:13 + | +LL | fn bar() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl Future` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/lexer/error-stage.stderr b/src/test/ui/lexer/error-stage.stderr index 697a7c28da16d..ecbdb14dc868e 100644 --- a/src/test/ui/lexer/error-stage.stderr +++ b/src/test/ui/lexer/error-stage.stderr @@ -49,6 +49,8 @@ error: integer literal is too large | LL | 999340282366920938463463374607431768211455999; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` error: aborting due to 8 previous errors diff --git a/src/test/ui/lexer/lex-bad-numeric-literals.rs b/src/test/ui/lexer/lex-bad-numeric-literals.rs index cf8440ca488cc..56bdc50e40d68 100644 --- a/src/test/ui/lexer/lex-bad-numeric-literals.rs +++ b/src/test/ui/lexer/lex-bad-numeric-literals.rs @@ -1,3 +1,5 @@ +// ignore-tidy-linelength + fn main() { 0o1.0; //~ ERROR: octal float literal is not supported 0o2f32; //~ ERROR: octal float literal is not supported @@ -15,6 +17,12 @@ fn main() { //~^ ERROR: integer literal is too large 9900000000000000000000000000999999999999999999999999999999; //~^ ERROR: integer literal is too large + 0b111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110; + //~^ ERROR: integer literal is too large + 0o37777777777777777777777777777777777777777770; + //~^ ERROR: integer literal is too large + 0xffffffffffffffffffffffffffffffff0; + //~^ ERROR: integer literal is too large 0x; //~ ERROR: no valid digits 0xu32; //~ ERROR: no valid digits 0ou32; //~ ERROR: no valid digits diff --git a/src/test/ui/lexer/lex-bad-numeric-literals.stderr b/src/test/ui/lexer/lex-bad-numeric-literals.stderr index f05d61603023c..1457541970af4 100644 --- a/src/test/ui/lexer/lex-bad-numeric-literals.stderr +++ b/src/test/ui/lexer/lex-bad-numeric-literals.stderr @@ -1,141 +1,169 @@ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:2:5 + --> $DIR/lex-bad-numeric-literals.rs:4:5 | LL | 0o1.0; | ^^^^^ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:4:5 + --> $DIR/lex-bad-numeric-literals.rs:6:5 | LL | 0o3.0f32; | ^^^^^ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:5:5 + --> $DIR/lex-bad-numeric-literals.rs:7:5 | LL | 0o4e4; | ^^^^^ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:6:5 + --> $DIR/lex-bad-numeric-literals.rs:8:5 | LL | 0o5.0e5; | ^^^^^^^ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:7:5 + --> $DIR/lex-bad-numeric-literals.rs:9:5 | LL | 0o6e6f32; | ^^^^^ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:8:5 + --> $DIR/lex-bad-numeric-literals.rs:10:5 | LL | 0o7.0e7f64; | ^^^^^^^ error: hexadecimal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:9:5 + --> $DIR/lex-bad-numeric-literals.rs:11:5 | LL | 0x8.0e+9; | ^^^^^^^^ error: hexadecimal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:10:5 + --> $DIR/lex-bad-numeric-literals.rs:12:5 | LL | 0x9.0e-9; | ^^^^^^^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:11:5 + --> $DIR/lex-bad-numeric-literals.rs:13:5 | LL | 0o; | ^^ error: expected at least one digit in exponent - --> $DIR/lex-bad-numeric-literals.rs:12:5 + --> $DIR/lex-bad-numeric-literals.rs:14:5 | LL | 1e+; | ^^^ error: hexadecimal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:13:5 + --> $DIR/lex-bad-numeric-literals.rs:15:5 | LL | 0x539.0; | ^^^^^^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:18:5 + --> $DIR/lex-bad-numeric-literals.rs:26:5 | LL | 0x; | ^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:19:5 + --> $DIR/lex-bad-numeric-literals.rs:27:5 | LL | 0xu32; | ^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:20:5 + --> $DIR/lex-bad-numeric-literals.rs:28:5 | LL | 0ou32; | ^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:21:5 + --> $DIR/lex-bad-numeric-literals.rs:29:5 | LL | 0bu32; | ^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:22:5 + --> $DIR/lex-bad-numeric-literals.rs:30:5 | LL | 0b; | ^^ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:24:5 + --> $DIR/lex-bad-numeric-literals.rs:32:5 | LL | 0o123.456; | ^^^^^^^^^ error: binary float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:26:5 + --> $DIR/lex-bad-numeric-literals.rs:34:5 | LL | 0b111.101; | ^^^^^^^^^ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:3:5 + --> $DIR/lex-bad-numeric-literals.rs:5:5 | LL | 0o2f32; | ^^^^^^ not supported error: integer literal is too large - --> $DIR/lex-bad-numeric-literals.rs:14:5 + --> $DIR/lex-bad-numeric-literals.rs:16:5 | LL | 9900000000000000000000000000999999999999999999999999999999; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` error: integer literal is too large - --> $DIR/lex-bad-numeric-literals.rs:16:5 + --> $DIR/lex-bad-numeric-literals.rs:18:5 | LL | 9900000000000000000000000000999999999999999999999999999999; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` + +error: integer literal is too large + --> $DIR/lex-bad-numeric-literals.rs:20:5 + | +LL | 0b111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `0b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111` + +error: integer literal is too large + --> $DIR/lex-bad-numeric-literals.rs:22:5 + | +LL | 0o37777777777777777777777777777777777777777770; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `0o3777777777777777777777777777777777777777777` + +error: integer literal is too large + --> $DIR/lex-bad-numeric-literals.rs:24:5 + | +LL | 0xffffffffffffffffffffffffffffffff0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `0xffffffffffffffffffffffffffffffff` error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:23:5 + --> $DIR/lex-bad-numeric-literals.rs:31:5 | LL | 0o123f64; | ^^^^^^^^ not supported error: binary float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:25:5 + --> $DIR/lex-bad-numeric-literals.rs:33:5 | LL | 0b101f64; | ^^^^^^^^ not supported -error: aborting due to 23 previous errors +error: aborting due to 26 previous errors For more information about this error, try `rustc --explain E0768`. diff --git a/src/test/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr b/src/test/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr index 8d70faa494dbe..8807279c27f93 100644 --- a/src/test/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr +++ b/src/test/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr @@ -11,6 +11,8 @@ error: integer literal is too large | LL | concat_bytes!(888888888888888888888888888888888888888); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/int-literal-too-large-span.stderr b/src/test/ui/parser/int-literal-too-large-span.stderr index 7cae85fc9fe6d..49d6aa5eff8ce 100644 --- a/src/test/ui/parser/int-literal-too-large-span.stderr +++ b/src/test/ui/parser/int-literal-too-large-span.stderr @@ -3,6 +3,8 @@ error: integer literal is too large | LL | 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-5544-a.stderr b/src/test/ui/parser/issues/issue-5544-a.stderr index de579c3c134e5..6e68c75850afe 100644 --- a/src/test/ui/parser/issues/issue-5544-a.stderr +++ b/src/test/ui/parser/issues/issue-5544-a.stderr @@ -3,6 +3,8 @@ error: integer literal is too large | LL | let __isize = 340282366920938463463374607431768211456; // 2^128 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-5544-b.stderr b/src/test/ui/parser/issues/issue-5544-b.stderr index 7df212dedfede..5d0e76d5d9445 100644 --- a/src/test/ui/parser/issues/issue-5544-b.stderr +++ b/src/test/ui/parser/issues/issue-5544-b.stderr @@ -3,6 +3,8 @@ error: integer literal is too large | LL | let __isize = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff_ff; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `0xffffffffffffffffffffffffffffffff` error: aborting due to previous error diff --git a/src/tools/bump-stage0/src/main.rs b/src/tools/bump-stage0/src/main.rs index aa346daf7e5f3..530a80b1ed374 100644 --- a/src/tools/bump-stage0/src/main.rs +++ b/src/tools/bump-stage0/src/main.rs @@ -1,4 +1,4 @@ -use anyhow::Error; +use anyhow::{Context, Error}; use curl::easy::Easy; use indexmap::IndexMap; use std::collections::HashMap; @@ -13,12 +13,13 @@ struct Tool { comments: Vec, channel: Channel, + date: Option, version: [u16; 3], checksums: IndexMap, } impl Tool { - fn new() -> Result { + fn new(date: Option) -> Result { let channel = match std::fs::read_to_string("src/ci/channel")?.trim() { "stable" => Channel::Stable, "beta" => Channel::Beta, @@ -40,6 +41,7 @@ impl Tool { Ok(Self { channel, version, + date, config: existing.config, comments: existing.comments, checksums: IndexMap::new(), @@ -84,7 +86,7 @@ impl Tool { Channel::Nightly => "beta".to_string(), }; - let manifest = fetch_manifest(&self.config, &channel)?; + let manifest = fetch_manifest(&self.config, &channel, self.date.as_deref())?; self.collect_checksums(&manifest, COMPILER_COMPONENTS)?; Ok(Stage0Toolchain { date: manifest.date, @@ -110,7 +112,7 @@ impl Tool { return Ok(None); } - let manifest = fetch_manifest(&self.config, "nightly")?; + let manifest = fetch_manifest(&self.config, "nightly", self.date.as_deref())?; self.collect_checksums(&manifest, RUSTFMT_COMPONENTS)?; Ok(Some(Stage0Toolchain { date: manifest.date, version: "nightly".into() })) } @@ -141,16 +143,19 @@ impl Tool { } fn main() -> Result<(), Error> { - let tool = Tool::new()?; + let tool = Tool::new(std::env::args().nth(1))?; tool.update_json()?; Ok(()) } -fn fetch_manifest(config: &Config, channel: &str) -> Result { - Ok(toml::from_slice(&http_get(&format!( - "{}/dist/channel-rust-{}.toml", - config.dist_server, channel - ))?)?) +fn fetch_manifest(config: &Config, channel: &str, date: Option<&str>) -> Result { + let url = if let Some(date) = date { + format!("{}/dist/{}/channel-rust-{}.toml", config.dist_server, date, channel) + } else { + format!("{}/dist/channel-rust-{}.toml", config.dist_server, channel) + }; + + Ok(toml::from_slice(&http_get(&url)?)?) } fn http_get(url: &str) -> Result, Error> { @@ -164,7 +169,7 @@ fn http_get(url: &str) -> Result, Error> { data.extend_from_slice(new_data); Ok(new_data.len()) })?; - transfer.perform()?; + transfer.perform().context(format!("failed to fetch {url}"))?; } Ok(data) } diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index f91e38262f64f..f409a86db26c0 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -15,6 +15,7 @@ //! //! A number of these checks can be opted-out of with various directives of the form: //! `// ignore-tidy-CHECK-NAME`. +// ignore-tidy-dbg use crate::walk::{filter_dirs, walk}; use regex::{Regex, RegexSet}; @@ -278,6 +279,7 @@ pub fn check(path: &Path, bad: &mut bool) { let mut skip_leading_newlines = contains_ignore_directive(can_contain, &contents, "leading-newlines"); let mut skip_copyright = contains_ignore_directive(can_contain, &contents, "copyright"); + let mut skip_dbg = contains_ignore_directive(can_contain, &contents, "dbg"); let mut leading_new_lines = false; let mut trailing_new_lines = 0; let mut lines = 0; @@ -306,6 +308,21 @@ pub fn check(path: &Path, bad: &mut bool) { let mut err = |msg: &str| { tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg); }; + + if trimmed.contains("dbg!") + && !trimmed.starts_with("//") + && !file + .ancestors() + .any(|a| a.ends_with("src/test") || a.ends_with("library/alloc/tests")) + && filename != "tests.rs" + { + suppressible_tidy_err!( + err, + skip_dbg, + "`dbg!` macro is intended as a debugging tool. It should not be in version control." + ) + } + if !under_rustfmt && line.chars().count() > max_columns && !long_line_is_ok(&extension, is_error_code, max_columns, line)