diff options
Diffstat (limited to 'compiler/rustc_session')
| -rw-r--r-- | compiler/rustc_session/Cargo.toml | 2 | ||||
| -rw-r--r-- | compiler/rustc_session/messages.ftl | 3 | ||||
| -rw-r--r-- | compiler/rustc_session/src/code_stats.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_session/src/config.rs | 314 | ||||
| -rw-r--r-- | compiler/rustc_session/src/cstore.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_session/src/errors.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_session/src/options.rs | 79 | ||||
| -rw-r--r-- | compiler/rustc_session/src/output.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_session/src/parse.rs | 30 | ||||
| -rw-r--r-- | compiler/rustc_session/src/session.rs | 34 | ||||
| -rw-r--r-- | compiler/rustc_session/src/utils.rs | 1 |
11 files changed, 383 insertions, 116 deletions
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index 90ad3f90f2c..e26d25d9a41 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -4,7 +4,7 @@ version = "0.0.0" edition = "2021" [dependencies] -atty = "0.2.13" +bitflags = "1.2.1" getopts = "0.2" rustc_macros = { path = "../rustc_macros" } tracing = "0.1" diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index 4897bd8d5da..d4042a2e61a 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -26,6 +26,8 @@ session_feature_gate_error = {$explain} session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions +session_file_write_fail = failed to write `{$path}` due to error `{$err}` + session_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported session_incompatible_linker_flavor = linker flavor `{$flavor}` is incompatible with the current target @@ -43,6 +45,7 @@ session_int_literal_too_large = integer literal is too large .note = value exceeds limit of `{$limit}` session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}` +session_invalid_character_in_create_name_help = you can either pass `--crate-name` on the command line or add `#![crate_name="…"]` to set the crate name session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal .label = invalid suffix `{$suffix}` diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs index cabe1c96bf7..df81e1f8305 100644 --- a/compiler/rustc_session/src/code_stats.rs +++ b/compiler/rustc_session/src/code_stats.rs @@ -227,10 +227,8 @@ impl CodeStats { } pub fn print_vtable_sizes(&self, crate_name: &str) { - let mut infos = std::mem::take(&mut *self.vtable_sizes.lock()) - .into_iter() - .map(|(_did, stats)| stats) - .collect::<Vec<_>>(); + let mut infos = + std::mem::take(&mut *self.vtable_sizes.lock()).into_values().collect::<Vec<_>>(); // Primary sort: cost % in reverse order (from largest to smallest) // Secondary sort: trait_name diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 480d2478e81..28ae88424ab 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3,16 +3,16 @@ pub use crate::options::*; +use crate::errors::FileWriteFail; use crate::search_paths::SearchPath; use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; use crate::{lint, HashStableContext}; use crate::{EarlyErrorHandler, Session}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; - use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey}; use rustc_target::abi::Align; -use rustc_target::spec::{LinkerFlavorCli, PanicStrategy, SanitizerSet, SplitDebuginfo}; +use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo}; use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS}; use crate::parse::{CrateCheckConfig, CrateConfig}; @@ -32,6 +32,7 @@ use std::collections::btree_map::{ use std::collections::{BTreeMap, BTreeSet}; use std::ffi::OsStr; use std::fmt; +use std::fs; use std::hash::Hash; use std::iter; use std::path::{Path, PathBuf}; @@ -201,6 +202,128 @@ pub enum LinkerPluginLto { Disabled, } +impl LinkerPluginLto { + pub fn enabled(&self) -> bool { + match *self { + LinkerPluginLto::LinkerPlugin(_) | LinkerPluginLto::LinkerPluginAuto => true, + LinkerPluginLto::Disabled => false, + } + } +} + +/// The different values `-C link-self-contained` can take: a list of individually enabled or +/// disabled components used during linking, coming from the rustc distribution, instead of being +/// found somewhere on the host system. +/// +/// They can be set in bulk via `-C link-self-contained=yes|y|on` or `-C +/// link-self-contained=no|n|off`, and those boolean values are the historical defaults. +/// +/// But each component is fine-grained, and can be unstably targeted, to use: +/// - some CRT objects +/// - the libc static library +/// - libgcc/libunwind libraries +/// - a linker we distribute +/// - some sanitizer runtime libraries +/// - all other MinGW libraries and Windows import libs +/// +#[derive(Default, Clone, PartialEq, Debug)] +pub struct LinkSelfContained { + /// Whether the user explicitly set `-C link-self-contained` on or off, the historical values. + /// Used for compatibility with the existing opt-in and target inference. + pub explicitly_set: Option<bool>, + + /// The components that are enabled. + components: LinkSelfContainedComponents, +} + +bitflags::bitflags! { + #[derive(Default)] + /// The `-C link-self-contained` components that can individually be enabled or disabled. + pub struct LinkSelfContainedComponents: u8 { + /// CRT objects (e.g. on `windows-gnu`, `musl`, `wasi` targets) + const CRT_OBJECTS = 1 << 0; + /// libc static library (e.g. on `musl`, `wasi` targets) + const LIBC = 1 << 1; + /// libgcc/libunwind (e.g. on `windows-gnu`, `fuchsia`, `fortanix`, `gnullvm` targets) + const UNWIND = 1 << 2; + /// Linker, dlltool, and their necessary libraries (e.g. on `windows-gnu` and for `rust-lld`) + const LINKER = 1 << 3; + /// Sanitizer runtime libraries + const SANITIZERS = 1 << 4; + /// Other MinGW libs and Windows import libs + const MINGW = 1 << 5; + } +} + +impl FromStr for LinkSelfContainedComponents { + type Err = (); + + fn from_str(s: &str) -> Result<Self, Self::Err> { + Ok(match s { + "crto" => LinkSelfContainedComponents::CRT_OBJECTS, + "libc" => LinkSelfContainedComponents::LIBC, + "unwind" => LinkSelfContainedComponents::UNWIND, + "linker" => LinkSelfContainedComponents::LINKER, + "sanitizers" => LinkSelfContainedComponents::SANITIZERS, + "mingw" => LinkSelfContainedComponents::MINGW, + _ => return Err(()), + }) + } +} + +impl LinkSelfContained { + /// Incorporates an enabled or disabled component as specified on the CLI, if possible. + /// For example: `+linker`, and `-crto`. + pub(crate) fn handle_cli_component(&mut self, component: &str) -> Result<(), ()> { + // Note that for example `-Cself-contained=y -Cself-contained=-linker` is not an explicit + // set of all values like `y` or `n` used to be. Therefore, if this flag had previously been + // set in bulk with its historical values, then manually setting a component clears that + // `explicitly_set` state. + if let Some(component_to_enable) = component.strip_prefix('+') { + self.explicitly_set = None; + self.components.insert(component_to_enable.parse()?); + Ok(()) + } else if let Some(component_to_disable) = component.strip_prefix('-') { + self.explicitly_set = None; + self.components.remove(component_to_disable.parse()?); + Ok(()) + } else { + Err(()) + } + } + + /// Turns all components on or off and records that this was done explicitly for compatibility + /// purposes. + pub(crate) fn set_all_explicitly(&mut self, enabled: bool) { + self.explicitly_set = Some(enabled); + self.components = if enabled { + LinkSelfContainedComponents::all() + } else { + LinkSelfContainedComponents::empty() + }; + } + + /// Helper creating a fully enabled `LinkSelfContained` instance. Used in tests. + pub fn on() -> Self { + let mut on = LinkSelfContained::default(); + on.set_all_explicitly(true); + on + } + + /// To help checking CLI usage while some of the values are unstable: returns whether one of the + /// components was set individually. This would also require the `-Zunstable-options` flag, to + /// be allowed. + fn are_unstable_variants_set(&self) -> bool { + let any_component_set = !self.components.is_empty(); + self.explicitly_set.is_none() && any_component_set + } + + /// Returns whether the self-contained linker component is enabled. + pub fn linker(&self) -> bool { + self.components.contains(LinkSelfContainedComponents::LINKER) + } +} + /// Used with `-Z assert-incr-state`. #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum IncrementalStateAssertion { @@ -213,15 +336,6 @@ pub enum IncrementalStateAssertion { NotLoaded, } -impl LinkerPluginLto { - pub fn enabled(&self) -> bool { - match *self { - LinkerPluginLto::LinkerPlugin(_) | LinkerPluginLto::LinkerPluginAuto => true, - LinkerPluginLto::Disabled => false, - } - } -} - /// The different settings that can be enabled via the `-Z location-detail` flag. #[derive(Copy, Clone, PartialEq, Hash, Debug)] pub struct LocationDetail { @@ -598,8 +712,14 @@ impl ExternEntry { } } +#[derive(Clone, PartialEq, Debug)] +pub struct PrintRequest { + pub kind: PrintKind, + pub out: OutFileName, +} + #[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum PrintRequest { +pub enum PrintKind { FileNames, Sysroot, TargetLibdir, @@ -625,14 +745,20 @@ pub enum PrintRequest { pub enum TraitSolver { /// Classic trait solver in `rustc_trait_selection::traits::select` Classic, - /// Chalk trait solver - Chalk, /// Experimental trait solver in `rustc_trait_selection::solve` Next, /// Use the new trait solver during coherence NextCoherence, } +#[derive(Default, Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum DumpSolverProofTree { + Always, + OnError, + #[default] + Never, +} + pub enum Input { /// Load source code from a file. File(PathBuf), @@ -708,9 +834,10 @@ impl OutFileName { } pub fn is_tty(&self) -> bool { + use std::io::IsTerminal; match *self { OutFileName::Real(_) => false, - OutFileName::Stdout => atty::is(atty::Stream::Stdout), + OutFileName::Stdout => std::io::stdout().is_terminal(), } } @@ -737,6 +864,17 @@ impl OutFileName { OutFileName::Stdout => outputs.temp_path(flavor, codegen_unit_name), } } + + pub fn overwrite(&self, content: &str, sess: &Session) { + match self { + OutFileName::Stdout => print!("{content}"), + OutFileName::Real(path) => { + if let Err(e) = fs::write(path, content) { + sess.emit_fatal(FileWriteFail { path, err: e.to_string() }); + } + } + } + } } #[derive(Clone, Hash, Debug, HashStable_Generic)] @@ -909,6 +1047,7 @@ impl Default for Options { json_future_incompat: false, pretty: None, working_dir: RealFileName::LocalPath(std::env::current_dir().unwrap()), + color: ColorConfig::Auto, } } } @@ -1400,9 +1539,8 @@ pub(super) fn build_target_config( ); let (target, target_warnings) = target_result.unwrap_or_else(|e| { handler.early_error(format!( - "Error loading target specification: {}. \ - Run `rustc --print target-list` for a list of built-in targets", - e + "Error loading target specification: {e}. \ + Run `rustc --print target-list` for a list of built-in targets" )) }); for warning in target_warnings.warning_messages() { @@ -1839,8 +1977,7 @@ pub fn parse_crate_edition(handler: &EarlyErrorHandler, matches: &getopts::Match let is_nightly = nightly_options::match_is_nightly_build(matches); let msg = if !is_nightly { format!( - "the crate requires edition {}, but the latest edition supported by this Rust version is {}", - edition, LATEST_STABLE_EDITION + "the crate requires edition {edition}, but the latest edition supported by this Rust version is {LATEST_STABLE_EDITION}" ) } else { format!("edition {edition} is unstable and only available with -Z unstable-options") @@ -1886,13 +2023,7 @@ fn parse_output_types( if !unstable_opts.parse_only { for list in matches.opt_strs("emit") { for output_type in list.split(',') { - let (shorthand, path) = match output_type.split_once('=') { - None => (output_type, None), - Some((shorthand, "-")) => (shorthand, Some(OutFileName::Stdout)), - Some((shorthand, path)) => { - (shorthand, Some(OutFileName::Real(PathBuf::from(path)))) - } - }; + let (shorthand, path) = split_out_file_name(output_type); let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| { handler.early_error(format!( "unknown emission type: `{shorthand}` - expected one of: {display}", @@ -1909,6 +2040,14 @@ fn parse_output_types( OutputTypes(output_types) } +fn split_out_file_name(arg: &str) -> (&str, Option<OutFileName>) { + match arg.split_once('=') { + None => (arg, None), + Some((kind, "-")) => (kind, Some(OutFileName::Stdout)), + Some((kind, path)) => (kind, Some(OutFileName::Real(PathBuf::from(path)))), + } +} + fn should_override_cgus_and_disable_thinlto( handler: &EarlyErrorHandler, output_types: &OutputTypes, @@ -1972,41 +2111,55 @@ fn collect_print_requests( ) -> Vec<PrintRequest> { let mut prints = Vec::<PrintRequest>::new(); if cg.target_cpu.as_ref().is_some_and(|s| s == "help") { - prints.push(PrintRequest::TargetCPUs); + prints.push(PrintRequest { kind: PrintKind::TargetCPUs, out: OutFileName::Stdout }); cg.target_cpu = None; }; if cg.target_feature == "help" { - prints.push(PrintRequest::TargetFeatures); + prints.push(PrintRequest { kind: PrintKind::TargetFeatures, out: OutFileName::Stdout }); cg.target_feature = String::new(); } - const PRINT_REQUESTS: &[(&str, PrintRequest)] = &[ - ("crate-name", PrintRequest::CrateName), - ("file-names", PrintRequest::FileNames), - ("sysroot", PrintRequest::Sysroot), - ("target-libdir", PrintRequest::TargetLibdir), - ("cfg", PrintRequest::Cfg), - ("calling-conventions", PrintRequest::CallingConventions), - ("target-list", PrintRequest::TargetList), - ("target-cpus", PrintRequest::TargetCPUs), - ("target-features", PrintRequest::TargetFeatures), - ("relocation-models", PrintRequest::RelocationModels), - ("code-models", PrintRequest::CodeModels), - ("tls-models", PrintRequest::TlsModels), - ("native-static-libs", PrintRequest::NativeStaticLibs), - ("stack-protector-strategies", PrintRequest::StackProtectorStrategies), - ("target-spec-json", PrintRequest::TargetSpec), - ("all-target-specs-json", PrintRequest::AllTargetSpecs), - ("link-args", PrintRequest::LinkArgs), - ("split-debuginfo", PrintRequest::SplitDebuginfo), - ("deployment-target", PrintRequest::DeploymentTarget), + const PRINT_KINDS: &[(&str, PrintKind)] = &[ + ("crate-name", PrintKind::CrateName), + ("file-names", PrintKind::FileNames), + ("sysroot", PrintKind::Sysroot), + ("target-libdir", PrintKind::TargetLibdir), + ("cfg", PrintKind::Cfg), + ("calling-conventions", PrintKind::CallingConventions), + ("target-list", PrintKind::TargetList), + ("target-cpus", PrintKind::TargetCPUs), + ("target-features", PrintKind::TargetFeatures), + ("relocation-models", PrintKind::RelocationModels), + ("code-models", PrintKind::CodeModels), + ("tls-models", PrintKind::TlsModels), + ("native-static-libs", PrintKind::NativeStaticLibs), + ("stack-protector-strategies", PrintKind::StackProtectorStrategies), + ("target-spec-json", PrintKind::TargetSpec), + ("all-target-specs-json", PrintKind::AllTargetSpecs), + ("link-args", PrintKind::LinkArgs), + ("split-debuginfo", PrintKind::SplitDebuginfo), + ("deployment-target", PrintKind::DeploymentTarget), ]; + // We disallow reusing the same path in multiple prints, such as `--print + // cfg=output.txt --print link-args=output.txt`, because outputs are printed + // by disparate pieces of the compiler, and keeping track of which files + // need to be overwritten vs appended to is annoying. + let mut printed_paths = FxHashSet::default(); + prints.extend(matches.opt_strs("print").into_iter().map(|req| { - match PRINT_REQUESTS.iter().find(|&&(name, _)| name == req) { - Some((_, PrintRequest::TargetSpec)) => { + let (req, out) = split_out_file_name(&req); + + if out.is_some() && !unstable_opts.unstable_options { + handler.early_error( + "the `-Z unstable-options` flag must also be passed to \ + enable the path print option", + ); + } + let kind = match PRINT_KINDS.iter().find(|&&(name, _)| name == req) { + Some((_, PrintKind::TargetSpec)) => { if unstable_opts.unstable_options { - PrintRequest::TargetSpec + PrintKind::TargetSpec } else { handler.early_error( "the `-Z unstable-options` flag must also be passed to \ @@ -2014,9 +2167,9 @@ fn collect_print_requests( ); } } - Some((_, PrintRequest::AllTargetSpecs)) => { + Some((_, PrintKind::AllTargetSpecs)) => { if unstable_opts.unstable_options { - PrintRequest::AllTargetSpecs + PrintKind::AllTargetSpecs } else { handler.early_error( "the `-Z unstable-options` flag must also be passed to \ @@ -2024,16 +2177,28 @@ fn collect_print_requests( ); } } - Some(&(_, print_request)) => print_request, + Some(&(_, print_kind)) => print_kind, None => { let prints = - PRINT_REQUESTS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>(); + PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>(); let prints = prints.join(", "); handler.early_error(format!( "unknown print request `{req}`. Valid print requests are: {prints}" )); } + }; + + let out = out.unwrap_or(OutFileName::Stdout); + if let OutFileName::Real(path) = &out { + if !printed_paths.insert(path.clone()) { + handler.early_error(format!( + "cannot print multiple outputs to the same path: {}", + path.display(), + )); + } } + + PrintRequest { kind, out } })); prints @@ -2405,6 +2570,8 @@ pub fn build_session_options( let error_format = parse_error_format(handler, matches, color, json_rendered); + handler.abort_if_error_and_set_error_format(error_format); + let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_else(|_| { handler.early_error("`--diagnostic-width` must be an positive integer"); }); @@ -2544,16 +2711,28 @@ pub fn build_session_options( } } - if let Some(flavor) = cg.linker_flavor { - if matches!(flavor, LinkerFlavorCli::BpfLinker | LinkerFlavorCli::PtxLinker) - && !nightly_options::is_unstable_enabled(matches) - { - let msg = format!( - "linker flavor `{}` is unstable, `-Z unstable-options` \ - flag must also be passed to explicitly use it", - flavor.desc() + // For testing purposes, until we have more feedback about these options: ensure `-Z + // unstable-options` is required when using the unstable `-C link-self-contained` options, like + // `-C link-self-contained=+linker`, and when using the unstable `-C linker-flavor` options, like + // `-C linker-flavor=gnu-lld-cc`. + if !nightly_options::is_unstable_enabled(matches) { + let uses_unstable_self_contained_option = + cg.link_self_contained.are_unstable_variants_set(); + if uses_unstable_self_contained_option { + handler.early_error( + "only `-C link-self-contained` values `y`/`yes`/`on`/`n`/`no`/`off` are stable, \ + the `-Z unstable-options` flag must also be passed to use the unstable values", ); - handler.early_error(msg); + } + + if let Some(flavor) = cg.linker_flavor { + if flavor.is_unstable() { + handler.early_error(format!( + "the linker flavor `{}` is unstable, the `-Z unstable-options` \ + flag must also be passed to use the unstable values", + flavor.desc() + )); + } } } @@ -2583,6 +2762,10 @@ pub fn build_session_options( handler.early_warn("-C remark requires \"-C debuginfo=n\" to show source locations"); } + if cg.remark.is_empty() && unstable_opts.remark_dir.is_some() { + handler.early_warn("using -Z remark-dir without enabling remarks using e.g. -C remark=all"); + } + let externs = parse_externs(handler, matches, &unstable_opts); let crate_name = matches.opt_str("crate-name"); @@ -2673,6 +2856,7 @@ pub fn build_session_options( json_future_incompat, pretty, working_dir, + color, } } diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index dc475e8c6d5..c53a355b533 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -13,6 +13,7 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions}; use rustc_span::hygiene::{ExpnHash, ExpnId}; use rustc_span::symbol::Symbol; use rustc_span::Span; +use rustc_target::spec::abi::Abi; use rustc_target::spec::Target; use std::any::Any; @@ -147,6 +148,7 @@ pub enum DllCallingConvention { pub struct ForeignModule { pub foreign_items: Vec<DefId>, pub def_id: DefId, + pub abi: Abi, } #[derive(Copy, Clone, Debug, HashStable_Generic)] diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 4a3e668da11..1ffee01b2f1 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -164,6 +164,13 @@ pub struct FileIsNotWriteable<'a> { } #[derive(Diagnostic)] +#[diag(session_file_write_fail)] +pub(crate) struct FileWriteFail<'a> { + pub path: &'a std::path::Path, + pub err: String, +} + +#[derive(Diagnostic)] #[diag(session_crate_name_does_not_match)] pub struct CrateNameDoesNotMatch { #[primary_span] @@ -192,6 +199,14 @@ pub struct InvalidCharacterInCrateName { pub span: Option<Span>, pub character: char, pub crate_name: Symbol, + #[subdiagnostic] + pub crate_name_help: Option<InvalidCrateNameHelp>, +} + +#[derive(Subdiagnostic)] +pub enum InvalidCrateNameHelp { + #[help(session_invalid_character_in_create_name_help)] + AddCrateName, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index e5063eef47a..055ab2d9c15 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -4,6 +4,7 @@ use crate::search_paths::SearchPath; use crate::utils::NativeLib; use crate::{lint, EarlyErrorHandler}; use rustc_data_structures::profiling::TimePassesFormat; +use rustc_errors::ColorConfig; use rustc_errors::{LanguageIdentifier, TerminalUrl}; use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet}; use rustc_target::spec::{ @@ -212,6 +213,7 @@ top_level_options!( /// The (potentially remapped) working directory working_dir: RealFileName [TRACKED], + color: ColorConfig [UNTRACKED], } ); @@ -328,8 +330,7 @@ fn build_options<O: Default>( match value { None => handler.early_error( format!( - "{0} option `{1}` requires {2} ({3} {1}=<value>)", - outputname, key, type_desc, prefix + "{outputname} option `{key}` requires {type_desc} ({prefix} {key}=<value>)" ), ), Some(value) => handler.early_error( @@ -386,7 +387,7 @@ mod desc { pub const parse_unpretty: &str = "`string` or `string=string`"; pub const parse_treat_err_as_bug: &str = "either no value or a number bigger than 0"; pub const parse_trait_solver: &str = - "one of the supported solver modes (`classic`, `chalk`, or `next`)"; + "one of the supported solver modes (`classic`, `next`, or `next-coherence`)"; pub const parse_lto: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted"; pub const parse_linker_plugin_lto: &str = @@ -410,12 +411,15 @@ mod desc { pub const parse_split_dwarf_kind: &str = "one of supported split dwarf modes (`split` or `single`)"; pub const parse_gcc_ld: &str = "one of: no value, `lld`"; + pub const parse_link_self_contained: &str = "one of: `y`, `yes`, `on`, `n`, `no`, `off`, or a list of enabled (`+` prefix) and disabled (`-` prefix) \ + components: `crto`, `libc`, `unwind`, `linker`, `sanitizers`, `mingw`"; pub const parse_stack_protector: &str = "one of (`none` (default), `basic`, `strong`, or `all`)"; pub const parse_branch_protection: &str = "a `,` separated combination of `bti`, `b-key`, `pac-ret`, or `leaf`"; pub const parse_proc_macro_execution_strategy: &str = "one of supported execution strategies (`same-thread`, or `cross-thread`)"; + pub const parse_dump_solver_proof_tree: &str = "one of: `always`, `on-request`, `on-error`"; } mod parse { @@ -981,7 +985,6 @@ mod parse { pub(crate) fn parse_trait_solver(slot: &mut TraitSolver, v: Option<&str>) -> bool { match v { Some("classic") => *slot = TraitSolver::Classic, - Some("chalk") => *slot = TraitSolver::Chalk, Some("next") => *slot = TraitSolver::Next, Some("next-coherence") => *slot = TraitSolver::NextCoherence, // default trait solver is subject to change.. @@ -1122,6 +1125,34 @@ mod parse { } } + pub(crate) fn parse_link_self_contained(slot: &mut LinkSelfContained, v: Option<&str>) -> bool { + // Whenever `-C link-self-contained` is passed without a value, it's an opt-in + // just like `parse_opt_bool`, the historical value of this flag. + // + // 1. Parse historical single bool values + let s = v.unwrap_or("y"); + match s { + "y" | "yes" | "on" => { + slot.set_all_explicitly(true); + return true; + } + "n" | "no" | "off" => { + slot.set_all_explicitly(false); + return true; + } + _ => {} + } + + // 2. Parse a list of enabled and disabled components. + for comp in s.split(',') { + if slot.handle_cli_component(comp).is_err() { + return false; + } + } + + true + } + pub(crate) fn parse_wasi_exec_model(slot: &mut Option<WasiExecModel>, v: Option<&str>) -> bool { match v { Some("command") => *slot = Some(WasiExecModel::Command), @@ -1208,6 +1239,19 @@ mod parse { }; true } + + pub(crate) fn parse_dump_solver_proof_tree( + slot: &mut DumpSolverProofTree, + v: Option<&str>, + ) -> bool { + match v { + None | Some("always") => *slot = DumpSolverProofTree::Always, + Some("never") => *slot = DumpSolverProofTree::Never, + Some("on-error") => *slot = DumpSolverProofTree::OnError, + _ => return false, + }; + true + } } options! { @@ -1265,9 +1309,9 @@ options! { #[rustc_lint_opt_deny_field_access("use `Session::link_dead_code` instead of this field")] link_dead_code: Option<bool> = (None, parse_opt_bool, [TRACKED], "keep dead code at link time (useful for code coverage) (default: no)"), - link_self_contained: Option<bool> = (None, parse_opt_bool, [UNTRACKED], + link_self_contained: LinkSelfContained = (LinkSelfContained::default(), parse_link_self_contained, [UNTRACKED], "control whether to link Rust provided C objects/libraries or rely - on C toolchain installed in the system"), + on a C toolchain or linker installed in the system"), linker: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED], "system linker to link outputs with"), linker_flavor: Option<LinkerFlavorCli> = (None, parse_linker_flavor, [UNTRACKED], @@ -1314,7 +1358,7 @@ options! { "control generation of position-independent code (PIC) \ (`rustc --print relocation-models` for details)"), remark: Passes = (Passes::Some(Vec::new()), parse_passes, [UNTRACKED], - "print remarks for these optimization passes (space separated, or \"all\")"), + "output remarks for these optimization passes (space separated, or \"all\")"), rpath: bool = (false, parse_bool, [UNTRACKED], "set rpath values in libs/exes (default: no)"), save_temps: bool = (false, parse_bool, [UNTRACKED], @@ -1388,8 +1432,6 @@ options! { dep_tasks: bool = (false, parse_bool, [UNTRACKED], "print tasks that execute and the color their dep node gets (requires debug build) \ (default: no)"), - diagnostic_width: Option<usize> = (None, parse_opt_number, [UNTRACKED], - "set the current output width for diagnostic truncation"), dont_buffer_diagnostics: bool = (false, parse_bool, [UNTRACKED], "emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) \ (default: no)"), @@ -1433,8 +1475,11 @@ options! { "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`)"), - dump_solver_proof_tree: bool = (false, parse_bool, [UNTRACKED], - "dump a proof tree for every goal evaluated by the new trait solver"), + dump_solver_proof_tree: DumpSolverProofTree = (DumpSolverProofTree::Never, parse_dump_solver_proof_tree, [UNTRACKED], + "dump a proof tree for every goal evaluated by the new trait solver. If the flag is specified without any options after it + then it defaults to `always`. If the flag is not specified at all it defaults to `on-request`."), + dump_solver_proof_tree_use_cache: Option<bool> = (None, parse_opt_bool, [UNTRACKED], + "determines whether dumped proof trees use the global cache"), dwarf_version: Option<u32> = (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], @@ -1535,9 +1580,6 @@ options! { "what location details should be tracked when using caller_location, either \ `none`, or a comma separated list of location details, for which \ valid options are `file`, `line`, and `column` (default: `file,line,column`)"), - lower_impl_trait_in_trait_to_assoc_ty: bool = (false, parse_bool, [TRACKED], - "modify the lowering strategy for `impl Trait` in traits so that they are lowered to \ - generic associated types"), ls: bool = (false, parse_bool, [UNTRACKED], "list the symbols defined by a library crate (default: no)"), macro_backtrace: bool = (false, parse_bool, [UNTRACKED], @@ -1623,6 +1665,9 @@ options! { "use a more precise version of drop elaboration for matches on enums (default: yes). \ This results in better codegen, but has caused miscompilations on some tier 2 platforms. \ See #77382 and #74551."), + #[rustc_lint_opt_deny_field_access("use `Session::print_codegen_stats` instead of this field")] + print_codegen_stats: bool = (false, parse_bool, [UNTRACKED], + "print codegen statistics (default: no)"), print_fuel: Option<String> = (None, parse_opt_string, [TRACKED], "make rustc print the total optimization fuel used by a crate"), print_llvm_passes: bool = (false, parse_bool, [UNTRACKED], @@ -1659,6 +1704,9 @@ options! { "choose which RELRO level to use"), remap_cwd_prefix: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED], "remap paths under the current working directory to this path prefix"), + remark_dir: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED], + "directory into which to write optimization remarks (if not specified, they will be \ +written to standard error output)"), report_delayed_bugs: bool = (false, parse_bool, [TRACKED], "immediately print bugs registered with `delay_span_bug` (default: no)"), sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED], @@ -1827,10 +1875,13 @@ options! { Requires `-Clto[=[fat,yes]]`"), wasi_exec_model: Option<WasiExecModel> = (None, parse_wasi_exec_model, [TRACKED], "whether to build a wasi command or reactor"), + write_long_types_to_disk: bool = (true, parse_bool, [UNTRACKED], + "whether long type names should be written to files instead of being printed in errors"), // tidy-alphabetical-end // If you add a new option, please update: // - compiler/rustc_interface/src/tests.rs + // - src/doc/unstable-book/src/compiler-flags } #[derive(Clone, Hash, PartialEq, Eq, Debug)] diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index 2088744bc5b..c0884fb21cd 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -2,7 +2,7 @@ use crate::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType}; use crate::errors::{ CrateNameDoesNotMatch, CrateNameEmpty, CrateNameInvalid, FileIsNotWriteable, - InvalidCharacterInCrateName, + InvalidCharacterInCrateName, InvalidCrateNameHelp, }; use crate::Session; use rustc_ast::{self as ast, attr}; @@ -101,7 +101,16 @@ pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option<Span>) { continue; } err_count += 1; - sess.emit_err(InvalidCharacterInCrateName { span: sp, character: c, crate_name: s }); + sess.emit_err(InvalidCharacterInCrateName { + span: sp, + character: c, + crate_name: s, + crate_name_help: if sp.is_none() { + Some(InvalidCrateNameHelp::AddCrateName) + } else { + None + }, + }); } } diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 194f7201ff3..bca49981668 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -9,7 +9,7 @@ use crate::lint::{ use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::sync::{AppendOnlyVec, AtomicBool, Lock, Lrc}; -use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler}; +use rustc_errors::{emitter::SilentEmitter, Handler}; use rustc_errors::{ fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, EmissionGuarantee, ErrorGuaranteed, IntoDiagnostic, MultiSpan, Noted, StashKey, @@ -117,6 +117,7 @@ pub fn feature_err_issue( /// Construct a future incompatibility diagnostic for a feature gate. /// /// This diagnostic is only a warning and *does not cause compilation to fail*. +#[track_caller] pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'static str) { feature_warn_issue(sess, feature, span, GateIssue::Language, explain); } @@ -129,6 +130,7 @@ pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'st /// Almost always, you want to use this for a language feature. If so, prefer `feature_warn`. #[allow(rustc::diagnostic_outside_of_impl)] #[allow(rustc::untranslatable_diagnostic)] +#[track_caller] pub fn feature_warn_issue( sess: &ParseSess, feature: Symbol, @@ -222,14 +224,7 @@ impl ParseSess { pub fn new(locale_resources: Vec<&'static str>, file_path_mapping: FilePathMapping) -> Self { let fallback_bundle = fallback_fluent_bundle(locale_resources, false); let sm = Lrc::new(SourceMap::new(file_path_mapping)); - let handler = Handler::with_tty_emitter( - ColorConfig::Auto, - true, - None, - Some(sm.clone()), - None, - fallback_bundle, - ); + let handler = Handler::with_tty_emitter(Some(sm.clone()), fallback_bundle); ParseSess::with_span_handler(handler, sm) } @@ -259,13 +254,9 @@ impl ParseSess { pub fn with_silent_emitter(fatal_note: Option<String>) -> Self { let fallback_bundle = fallback_fluent_bundle(Vec::new(), false); let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let fatal_handler = - Handler::with_tty_emitter(ColorConfig::Auto, false, None, None, None, fallback_bundle); - let handler = Handler::with_emitter( - false, - None, - Box::new(SilentEmitter { fatal_handler, fatal_note }), - ); + let fatal_handler = Handler::with_tty_emitter(None, fallback_bundle).disable_warnings(); + let handler = Handler::with_emitter(Box::new(SilentEmitter { fatal_handler, fatal_note })) + .disable_warnings(); ParseSess::with_span_handler(handler, sm) } @@ -351,6 +342,7 @@ impl ParseSess { self.create_warning(warning).emit() } + #[track_caller] pub fn create_note<'a>( &'a self, note: impl IntoDiagnostic<'a, Noted>, @@ -358,10 +350,12 @@ impl ParseSess { note.into_diagnostic(&self.span_diagnostic) } + #[track_caller] pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted { self.create_note(note).emit() } + #[track_caller] pub fn create_fatal<'a>( &'a self, fatal: impl IntoDiagnostic<'a, !>, @@ -369,6 +363,7 @@ impl ParseSess { fatal.into_diagnostic(&self.span_diagnostic) } + #[track_caller] pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! { self.create_fatal(fatal).emit() } @@ -383,16 +378,19 @@ impl ParseSess { } #[rustc_lint_diagnostics] + #[track_caller] pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { self.span_diagnostic.struct_warn(msg) } #[rustc_lint_diagnostics] + #[track_caller] pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> { self.span_diagnostic.struct_fatal(msg) } #[rustc_lint_diagnostics] + #[track_caller] pub fn struct_diagnostic<G: EmissionGuarantee>( &self, msg: impl Into<DiagnosticMessage>, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 5be122ffbde..ad22e7c703d 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -677,7 +677,7 @@ impl Session { pub fn delay_span_bug<S: Into<MultiSpan>>( &self, sp: S, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<String>, ) -> ErrorGuaranteed { self.diagnostic().delay_span_bug(sp, msg) } @@ -995,18 +995,18 @@ impl Session { } /// Are we allowed to use features from the Rust 2018 edition? - pub fn rust_2018(&self) -> bool { - self.edition().rust_2018() + pub fn at_least_rust_2018(&self) -> bool { + self.edition().at_least_rust_2018() } /// Are we allowed to use features from the Rust 2021 edition? - pub fn rust_2021(&self) -> bool { - self.edition().rust_2021() + pub fn at_least_rust_2021(&self) -> bool { + self.edition().at_least_rust_2021() } /// Are we allowed to use features from the Rust 2024 edition? - pub fn rust_2024(&self) -> bool { - self.edition().rust_2024() + pub fn at_least_rust_2024(&self) -> bool { + self.edition().at_least_rust_2024() } /// Returns `true` if we should use the PLT for shared library calls. @@ -1057,6 +1057,10 @@ impl Session { self.opts.unstable_opts.verbose } + pub fn print_llvm_stats(&self) -> bool { + self.opts.unstable_opts.print_codegen_stats + } + pub fn verify_llvm_ir(&self) -> bool { self.opts.unstable_opts.verify_llvm_ir || option_env!("RUSTC_VERIFY_LLVM_IR").is_some() } @@ -1392,6 +1396,7 @@ pub fn build_session( file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>, target_override: Option<Target>, cfg_version: &'static str, + ice_file: Option<PathBuf>, ) -> Session { // FIXME: This is not general enough to make the warning lint completely override // normal diagnostic warnings, since the warning lint can also be denied and changed @@ -1420,7 +1425,7 @@ pub fn build_session( let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader)); let hash_kind = sopts.unstable_opts.src_hash_algorithm.unwrap_or_else(|| { if target_cfg.is_like_msvc { - SourceFileHashAlgorithm::Sha1 + SourceFileHashAlgorithm::Sha256 } else { SourceFileHashAlgorithm::Md5 } @@ -1437,10 +1442,11 @@ pub fn build_session( ); let emitter = default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle); - let span_diagnostic = rustc_errors::Handler::with_emitter_and_flags( - emitter, - sopts.unstable_opts.diagnostic_handler_flags(can_emit_warnings), - ); + let mut span_diagnostic = rustc_errors::Handler::with_emitter(emitter) + .with_flags(sopts.unstable_opts.diagnostic_handler_flags(can_emit_warnings)); + if let Some(ice_file) = ice_file { + span_diagnostic = span_diagnostic.with_ice_file(ice_file); + } let self_profiler = if let SwitchWithOptPath::Enabled(ref d) = sopts.unstable_opts.self_profile { @@ -1731,7 +1737,7 @@ pub struct EarlyErrorHandler { impl EarlyErrorHandler { pub fn new(output: ErrorOutputType) -> Self { let emitter = mk_emitter(output); - Self { handler: rustc_errors::Handler::with_emitter(true, None, emitter) } + Self { handler: rustc_errors::Handler::with_emitter(emitter) } } pub fn abort_if_errors(&self) { @@ -1745,7 +1751,7 @@ impl EarlyErrorHandler { self.handler.abort_if_errors(); let emitter = mk_emitter(output); - self.handler = Handler::with_emitter(true, None, emitter); + self.handler = Handler::with_emitter(emitter); } #[allow(rustc::untranslatable_diagnostic)] diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index 1d15e2c28d8..71f2591fe66 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -7,6 +7,7 @@ impl Session { pub fn timer(&self, what: &'static str) -> VerboseTimingGuard<'_> { self.prof.verbose_generic_activity(what) } + /// Used by `-Z self-profile`. pub fn time<R>(&self, what: &'static str, f: impl FnOnce() -> R) -> R { self.prof.verbose_generic_activity(what).run(f) } |
