1
Fork 0

Provide more context for rustc +nightly -Zunstable-options on stable

This commit is contained in:
许杰友 Jieyou Xu (Joe) 2023-06-23 05:56:09 +08:00
parent f42f19b6d3
commit cef812bd95
No known key found for this signature in database
GPG key ID: C5FD5D32014FDB47
19 changed files with 509 additions and 471 deletions

View file

@ -5,8 +5,8 @@ pub use crate::options::*;
use crate::search_paths::SearchPath;
use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
use crate::{early_error, early_warn, Session};
use crate::{lint, HashStableContext};
use crate::{EarlyErrorHandler, Session};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@ -1389,6 +1389,7 @@ pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateCo
}
pub(super) fn build_target_config(
handler: &EarlyErrorHandler,
opts: &Options,
target_override: Option<Target>,
sysroot: &Path,
@ -1398,27 +1399,21 @@ pub(super) fn build_target_config(
|t| Ok((t, TargetWarnings::empty())),
);
let (target, target_warnings) = target_result.unwrap_or_else(|e| {
early_error(
opts.error_format,
format!(
"Error loading target specification: {}. \
handler.early_error(format!(
"Error loading target specification: {}. \
Run `rustc --print target-list` for a list of built-in targets",
e
),
)
e
))
});
for warning in target_warnings.warning_messages() {
early_warn(opts.error_format, warning)
handler.early_warn(warning)
}
if !matches!(target.pointer_width, 16 | 32 | 64) {
early_error(
opts.error_format,
format!(
"target specification was invalid: unrecognized target-pointer-width {}",
target.pointer_width
),
)
handler.early_error(format!(
"target specification was invalid: unrecognized target-pointer-width {}",
target.pointer_width
))
}
target
@ -1654,8 +1649,8 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
}
pub fn get_cmd_lint_options(
handler: &EarlyErrorHandler,
matches: &getopts::Matches,
error_format: ErrorOutputType,
) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) {
let mut lint_opts_with_position = vec![];
let mut describe_lints = false;
@ -1679,14 +1674,14 @@ pub fn get_cmd_lint_options(
let lint_cap = matches.opt_str("cap-lints").map(|cap| {
lint::Level::from_str(&cap)
.unwrap_or_else(|| early_error(error_format, format!("unknown lint level: `{cap}`")))
.unwrap_or_else(|| handler.early_error(format!("unknown lint level: `{cap}`")))
});
(lint_opts, describe_lints, lint_cap)
}
/// Parses the `--color` flag.
pub fn parse_color(matches: &getopts::Matches) -> ColorConfig {
pub fn parse_color(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> ColorConfig {
match matches.opt_str("color").as_deref() {
Some("auto") => ColorConfig::Auto,
Some("always") => ColorConfig::Always,
@ -1694,13 +1689,10 @@ pub fn parse_color(matches: &getopts::Matches) -> ColorConfig {
None => ColorConfig::Auto,
Some(arg) => early_error(
ErrorOutputType::default(),
format!(
"argument for `--color` must be auto, \
Some(arg) => handler.early_error(format!(
"argument for `--color` must be auto, \
always or never (instead was `{arg}`)"
),
),
)),
}
}
@ -1743,7 +1735,7 @@ impl JsonUnusedExterns {
///
/// The first value returned is how to render JSON diagnostics, and the second
/// is whether or not artifact notifications are enabled.
pub fn parse_json(matches: &getopts::Matches) -> JsonConfig {
pub fn parse_json(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> JsonConfig {
let mut json_rendered: fn(ColorConfig) -> HumanReadableErrorType =
HumanReadableErrorType::Default;
let mut json_color = ColorConfig::Never;
@ -1755,10 +1747,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig {
// won't actually be emitting any colors and anything colorized is
// embedded in a diagnostic message anyway.
if matches.opt_str("color").is_some() {
early_error(
ErrorOutputType::default(),
"cannot specify the `--color` option with `--json`",
);
handler.early_error("cannot specify the `--color` option with `--json`");
}
for sub_option in option.split(',') {
@ -1769,10 +1758,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig {
"unused-externs" => json_unused_externs = JsonUnusedExterns::Loud,
"unused-externs-silent" => json_unused_externs = JsonUnusedExterns::Silent,
"future-incompat" => json_future_incompat = true,
s => early_error(
ErrorOutputType::default(),
format!("unknown `--json` option `{s}`"),
),
s => handler.early_error(format!("unknown `--json` option `{s}`")),
}
}
}
@ -1787,6 +1773,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig {
/// Parses the `--error-format` flag.
pub fn parse_error_format(
handler: &mut EarlyErrorHandler,
matches: &getopts::Matches,
color: ColorConfig,
json_rendered: HumanReadableErrorType,
@ -1807,13 +1794,15 @@ pub fn parse_error_format(
Some("pretty-json") => ErrorOutputType::Json { pretty: true, json_rendered },
Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)),
Some(arg) => early_error(
ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)),
format!(
Some(arg) => {
handler.abort_if_error_and_set_error_format(ErrorOutputType::HumanReadable(
HumanReadableErrorType::Default(color),
));
handler.early_error(format!(
"argument for `--error-format` must be `human`, `json` or \
`short` (instead was `{arg}`)"
),
),
))
}
}
} else {
ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color))
@ -1826,10 +1815,7 @@ pub fn parse_error_format(
// `--error-format=json`. This means that `--json` is specified we
// should actually be emitting JSON blobs.
_ if !matches.opt_strs("json").is_empty() => {
early_error(
ErrorOutputType::default(),
"using `--json` requires also using `--error-format=json`",
);
handler.early_error("using `--json` requires also using `--error-format=json`");
}
_ => {}
@ -1838,16 +1824,13 @@ pub fn parse_error_format(
error_format
}
pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
pub fn parse_crate_edition(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> Edition {
let edition = match matches.opt_str("edition") {
Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| {
early_error(
ErrorOutputType::default(),
format!(
"argument for `--edition` must be one of: \
handler.early_error(format!(
"argument for `--edition` must be one of: \
{EDITION_NAME_LIST}. (instead was `{arg}`)"
),
)
))
}),
None => DEFAULT_EDITION,
};
@ -1862,39 +1845,42 @@ pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
} else {
format!("edition {edition} is unstable and only available with -Z unstable-options")
};
early_error(ErrorOutputType::default(), msg)
handler.early_error(msg)
}
edition
}
fn check_error_format_stability(
handler: &mut EarlyErrorHandler,
unstable_opts: &UnstableOptions,
error_format: ErrorOutputType,
json_rendered: HumanReadableErrorType,
) {
if !unstable_opts.unstable_options {
if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format {
early_error(
ErrorOutputType::Json { pretty: false, json_rendered },
"`--error-format=pretty-json` is unstable",
);
handler.abort_if_error_and_set_error_format(ErrorOutputType::Json {
pretty: false,
json_rendered,
});
handler.early_error("`--error-format=pretty-json` is unstable");
}
if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) =
error_format
{
early_error(
ErrorOutputType::Json { pretty: false, json_rendered },
"`--error-format=human-annotate-rs` is unstable",
);
handler.abort_if_error_and_set_error_format(ErrorOutputType::Json {
pretty: false,
json_rendered,
});
handler.early_error("`--error-format=human-annotate-rs` is unstable");
}
}
}
fn parse_output_types(
handler: &EarlyErrorHandler,
unstable_opts: &UnstableOptions,
matches: &getopts::Matches,
error_format: ErrorOutputType,
) -> OutputTypes {
let mut output_types = BTreeMap::new();
if !unstable_opts.parse_only {
@ -1908,13 +1894,10 @@ fn parse_output_types(
}
};
let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| {
early_error(
error_format,
format!(
"unknown emission type: `{shorthand}` - expected one of: {display}",
display = OutputType::shorthands_display(),
),
)
handler.early_error(format!(
"unknown emission type: `{shorthand}` - expected one of: {display}",
display = OutputType::shorthands_display(),
))
});
output_types.insert(output_type, path);
}
@ -1927,9 +1910,9 @@ fn parse_output_types(
}
fn should_override_cgus_and_disable_thinlto(
handler: &EarlyErrorHandler,
output_types: &OutputTypes,
matches: &getopts::Matches,
error_format: ErrorOutputType,
mut codegen_units: Option<usize>,
) -> (bool, Option<usize>) {
let mut disable_local_thinlto = false;
@ -1947,15 +1930,12 @@ fn should_override_cgus_and_disable_thinlto(
Some(n) if n > 1 => {
if matches.opt_present("o") {
for ot in &incompatible {
early_warn(
error_format,
format!(
"`--emit={ot}` with `-o` incompatible with \
handler.early_warn(format!(
"`--emit={ot}` with `-o` incompatible with \
`-C codegen-units=N` for N > 1",
),
);
));
}
early_warn(error_format, "resetting to default -C codegen-units=1");
handler.early_warn("resetting to default -C codegen-units=1");
codegen_units = Some(1);
disable_local_thinlto = true;
}
@ -1968,27 +1948,27 @@ fn should_override_cgus_and_disable_thinlto(
}
if codegen_units == Some(0) {
early_error(error_format, "value for codegen units must be a positive non-zero integer");
handler.early_error("value for codegen units must be a positive non-zero integer");
}
(disable_local_thinlto, codegen_units)
}
fn check_thread_count(unstable_opts: &UnstableOptions, error_format: ErrorOutputType) {
fn check_thread_count(handler: &EarlyErrorHandler, unstable_opts: &UnstableOptions) {
if unstable_opts.threads == 0 {
early_error(error_format, "value for threads must be a positive non-zero integer");
handler.early_error("value for threads must be a positive non-zero integer");
}
if unstable_opts.threads > 1 && unstable_opts.fuel.is_some() {
early_error(error_format, "optimization fuel is incompatible with multiple threads");
handler.early_error("optimization fuel is incompatible with multiple threads");
}
}
fn collect_print_requests(
handler: &EarlyErrorHandler,
cg: &mut CodegenOptions,
unstable_opts: &mut UnstableOptions,
matches: &getopts::Matches,
error_format: ErrorOutputType,
) -> Vec<PrintRequest> {
let mut prints = Vec::<PrintRequest>::new();
if cg.target_cpu.as_ref().is_some_and(|s| s == "help") {
@ -2028,8 +2008,7 @@ fn collect_print_requests(
if unstable_opts.unstable_options {
PrintRequest::TargetSpec
} else {
early_error(
error_format,
handler.early_error(
"the `-Z unstable-options` flag must also be passed to \
enable the target-spec-json print option",
);
@ -2039,8 +2018,7 @@ fn collect_print_requests(
if unstable_opts.unstable_options {
PrintRequest::AllTargetSpecs
} else {
early_error(
error_format,
handler.early_error(
"the `-Z unstable-options` flag must also be passed to \
enable the all-target-specs-json print option",
);
@ -2051,10 +2029,9 @@ fn collect_print_requests(
let prints =
PRINT_REQUESTS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>();
let prints = prints.join(", ");
early_error(
error_format,
format!("unknown print request `{req}`. Valid print requests are: {prints}"),
);
handler.early_error(format!(
"unknown print request `{req}`. Valid print requests are: {prints}"
));
}
}
}));
@ -2063,14 +2040,14 @@ fn collect_print_requests(
}
pub fn parse_target_triple(
handler: &EarlyErrorHandler,
matches: &getopts::Matches,
error_format: ErrorOutputType,
) -> TargetTriple {
match matches.opt_str("target") {
Some(target) if target.ends_with(".json") => {
let path = Path::new(&target);
TargetTriple::from_path(path).unwrap_or_else(|_| {
early_error(error_format, format!("target file {path:?} does not exist"))
handler.early_error(format!("target file {path:?} does not exist"))
})
}
Some(target) => TargetTriple::TargetTriple(target),
@ -2079,9 +2056,9 @@ pub fn parse_target_triple(
}
fn parse_opt_level(
handler: &EarlyErrorHandler,
matches: &getopts::Matches,
cg: &CodegenOptions,
error_format: ErrorOutputType,
) -> OptLevel {
// The `-O` and `-C opt-level` flags specify the same setting, so we want to be able
// to use them interchangeably. However, because they're technically different flags,
@ -2109,13 +2086,10 @@ fn parse_opt_level(
"s" => OptLevel::Size,
"z" => OptLevel::SizeMin,
arg => {
early_error(
error_format,
format!(
"optimization level needs to be \
handler.early_error(format!(
"optimization level needs to be \
between 0-3, s or z (instead was `{arg}`)"
),
);
));
}
}
}
@ -2135,23 +2109,23 @@ fn select_debuginfo(matches: &getopts::Matches, cg: &CodegenOptions) -> DebugInf
}
pub(crate) fn parse_assert_incr_state(
handler: &EarlyErrorHandler,
opt_assertion: &Option<String>,
error_format: ErrorOutputType,
) -> Option<IncrementalStateAssertion> {
match opt_assertion {
Some(s) if s.as_str() == "loaded" => Some(IncrementalStateAssertion::Loaded),
Some(s) if s.as_str() == "not-loaded" => Some(IncrementalStateAssertion::NotLoaded),
Some(s) => {
early_error(error_format, format!("unexpected incremental state assertion value: {s}"))
handler.early_error(format!("unexpected incremental state assertion value: {s}"))
}
None => None,
}
}
fn parse_native_lib_kind(
handler: &EarlyErrorHandler,
matches: &getopts::Matches,
kind: &str,
error_format: ErrorOutputType,
) -> (NativeLibKind, Option<bool>) {
let (kind, modifiers) = match kind.split_once(':') {
None => (kind, None),
@ -2169,35 +2143,31 @@ fn parse_native_lib_kind(
} else {
", the `-Z unstable-options` flag must also be passed to use it"
};
early_error(error_format, format!("library kind `link-arg` is unstable{why}"))
handler.early_error(format!("library kind `link-arg` is unstable{why}"))
}
NativeLibKind::LinkArg
}
_ => early_error(
error_format,
format!(
"unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg"
),
),
_ => handler.early_error(format!(
"unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg"
)),
};
match modifiers {
None => (kind, None),
Some(modifiers) => parse_native_lib_modifiers(kind, modifiers, error_format, matches),
Some(modifiers) => parse_native_lib_modifiers(handler, kind, modifiers, matches),
}
}
fn parse_native_lib_modifiers(
handler: &EarlyErrorHandler,
mut kind: NativeLibKind,
modifiers: &str,
error_format: ErrorOutputType,
matches: &getopts::Matches,
) -> (NativeLibKind, Option<bool>) {
let mut verbatim = None;
for modifier in modifiers.split(',') {
let (modifier, value) = match modifier.strip_prefix(['+', '-']) {
Some(m) => (m, modifier.starts_with('+')),
None => early_error(
error_format,
None => handler.early_error(
"invalid linking modifier syntax, expected '+' or '-' prefix \
before one of: bundle, verbatim, whole-archive, as-needed",
),
@ -2210,21 +2180,20 @@ fn parse_native_lib_modifiers(
} else {
", the `-Z unstable-options` flag must also be passed to use it"
};
early_error(error_format, format!("linking modifier `{modifier}` is unstable{why}"))
handler.early_error(format!("linking modifier `{modifier}` is unstable{why}"))
}
};
let assign_modifier = |dst: &mut Option<bool>| {
if dst.is_some() {
let msg = format!("multiple `{modifier}` modifiers in a single `-l` option");
early_error(error_format, msg)
handler.early_error(msg)
} else {
*dst = Some(value);
}
};
match (modifier, &mut kind) {
("bundle", NativeLibKind::Static { bundle, .. }) => assign_modifier(bundle),
("bundle", _) => early_error(
error_format,
("bundle", _) => handler.early_error(
"linking modifier `bundle` is only compatible with `static` linking kind",
),
@ -2233,8 +2202,7 @@ fn parse_native_lib_modifiers(
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
assign_modifier(whole_archive)
}
("whole-archive", _) => early_error(
error_format,
("whole-archive", _) => handler.early_error(
"linking modifier `whole-archive` is only compatible with `static` linking kind",
),
@ -2243,28 +2211,24 @@ fn parse_native_lib_modifiers(
report_unstable_modifier();
assign_modifier(as_needed)
}
("as-needed", _) => early_error(
error_format,
("as-needed", _) => handler.early_error(
"linking modifier `as-needed` is only compatible with \
`dylib` and `framework` linking kinds",
),
// Note: this error also excludes the case with empty modifier
// string, like `modifiers = ""`.
_ => early_error(
error_format,
format!(
"unknown linking modifier `{modifier}`, expected one \
_ => handler.early_error(format!(
"unknown linking modifier `{modifier}`, expected one \
of: bundle, verbatim, whole-archive, as-needed"
),
),
)),
}
}
(kind, verbatim)
}
fn parse_libs(matches: &getopts::Matches, error_format: ErrorOutputType) -> Vec<NativeLib> {
fn parse_libs(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> Vec<NativeLib> {
matches
.opt_strs("l")
.into_iter()
@ -2278,7 +2242,7 @@ fn parse_libs(matches: &getopts::Matches, error_format: ErrorOutputType) -> Vec<
let (name, kind, verbatim) = match s.split_once('=') {
None => (s, NativeLibKind::Unspecified, None),
Some((kind, name)) => {
let (kind, verbatim) = parse_native_lib_kind(matches, kind, error_format);
let (kind, verbatim) = parse_native_lib_kind(handler, matches, kind);
(name.to_string(), kind, verbatim)
}
};
@ -2288,7 +2252,7 @@ fn parse_libs(matches: &getopts::Matches, error_format: ErrorOutputType) -> Vec<
Some((name, new_name)) => (name.to_string(), Some(new_name.to_owned())),
};
if name.is_empty() {
early_error(error_format, "library name must not be empty");
handler.early_error("library name must not be empty");
}
NativeLib { name, new_name, kind, verbatim }
})
@ -2296,9 +2260,9 @@ fn parse_libs(matches: &getopts::Matches, error_format: ErrorOutputType) -> Vec<
}
pub fn parse_externs(
handler: &EarlyErrorHandler,
matches: &getopts::Matches,
unstable_opts: &UnstableOptions,
error_format: ErrorOutputType,
) -> Externs {
let is_unstable_enabled = unstable_opts.unstable_options;
let mut externs: BTreeMap<String, ExternEntry> = BTreeMap::new();
@ -2362,8 +2326,7 @@ pub fn parse_externs(
let mut force = false;
if let Some(opts) = options {
if !is_unstable_enabled {
early_error(
error_format,
handler.early_error(
"the `-Z unstable-options` flag must also be passed to \
enable `--extern` options",
);
@ -2375,15 +2338,14 @@ pub fn parse_externs(
if let ExternLocation::ExactPaths(_) = &entry.location {
add_prelude = false;
} else {
early_error(
error_format,
handler.early_error(
"the `noprelude` --extern option requires a file path",
);
}
}
"nounused" => nounused_dep = true,
"force" => force = true,
_ => early_error(error_format, format!("unknown --extern option `{opt}`")),
_ => handler.early_error(format!("unknown --extern option `{opt}`")),
}
}
}
@ -2402,18 +2364,15 @@ pub fn parse_externs(
}
fn parse_remap_path_prefix(
handler: &EarlyErrorHandler,
matches: &getopts::Matches,
unstable_opts: &UnstableOptions,
error_format: ErrorOutputType,
) -> Vec<(PathBuf, PathBuf)> {
let mut mapping: Vec<(PathBuf, PathBuf)> = matches
.opt_strs("remap-path-prefix")
.into_iter()
.map(|remap| match remap.rsplit_once('=') {
None => early_error(
error_format,
"--remap-path-prefix must contain '=' between FROM and TO",
),
None => handler.early_error("--remap-path-prefix must contain '=' between FROM and TO"),
Some((from, to)) => (PathBuf::from(from), PathBuf::from(to)),
})
.collect();
@ -2429,86 +2388,75 @@ fn parse_remap_path_prefix(
// JUSTIFICATION: before wrapper fn is available
#[allow(rustc::bad_opt_access)]
pub fn build_session_options(matches: &getopts::Matches) -> Options {
let color = parse_color(matches);
pub fn build_session_options(
handler: &mut EarlyErrorHandler,
matches: &getopts::Matches,
) -> Options {
let color = parse_color(handler, matches);
let edition = parse_crate_edition(matches);
let edition = parse_crate_edition(handler, matches);
let JsonConfig {
json_rendered,
json_artifact_notifications,
json_unused_externs,
json_future_incompat,
} = parse_json(matches);
} = parse_json(handler, matches);
let error_format = parse_error_format(matches, color, json_rendered);
let error_format = parse_error_format(handler, matches, color, json_rendered);
let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_else(|_| {
early_error(error_format, "`--diagnostic-width` must be an positive integer");
handler.early_error("`--diagnostic-width` must be an positive integer");
});
let unparsed_crate_types = matches.opt_strs("crate-type");
let crate_types = parse_crate_types_from_list(unparsed_crate_types)
.unwrap_or_else(|e| early_error(error_format, e));
.unwrap_or_else(|e| handler.early_error(e));
let mut unstable_opts = UnstableOptions::build(matches, error_format);
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
let mut unstable_opts = UnstableOptions::build(handler, matches);
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(handler, matches);
check_error_format_stability(&unstable_opts, error_format, json_rendered);
check_error_format_stability(handler, &unstable_opts, error_format, json_rendered);
if !unstable_opts.unstable_options && json_unused_externs.is_enabled() {
early_error(
error_format,
handler.early_error(
"the `-Z unstable-options` flag must also be passed to enable \
the flag `--json=unused-externs`",
);
}
let output_types = parse_output_types(&unstable_opts, matches, error_format);
let output_types = parse_output_types(handler, &unstable_opts, matches);
let mut cg = CodegenOptions::build(matches, error_format);
let (disable_local_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto(
&output_types,
matches,
error_format,
cg.codegen_units,
);
let mut cg = CodegenOptions::build(handler, matches);
let (disable_local_thinlto, mut codegen_units) =
should_override_cgus_and_disable_thinlto(handler, &output_types, matches, cg.codegen_units);
check_thread_count(&unstable_opts, error_format);
check_thread_count(handler, &unstable_opts);
let incremental = cg.incremental.as_ref().map(PathBuf::from);
let assert_incr_state = parse_assert_incr_state(&unstable_opts.assert_incr_state, error_format);
let assert_incr_state = parse_assert_incr_state(handler, &unstable_opts.assert_incr_state);
if unstable_opts.profile && incremental.is_some() {
early_error(
error_format,
"can't instrument with gcov profiling when compiling incrementally",
);
handler.early_error("can't instrument with gcov profiling when compiling incrementally");
}
if unstable_opts.profile {
match codegen_units {
Some(1) => {}
None => codegen_units = Some(1),
Some(_) => early_error(
error_format,
"can't instrument with gcov profiling with multiple codegen units",
),
Some(_) => handler
.early_error("can't instrument with gcov profiling with multiple codegen units"),
}
}
if cg.profile_generate.enabled() && cg.profile_use.is_some() {
early_error(
error_format,
"options `-C profile-generate` and `-C profile-use` are exclusive",
);
handler.early_error("options `-C profile-generate` and `-C profile-use` are exclusive");
}
if unstable_opts.profile_sample_use.is_some()
&& (cg.profile_generate.enabled() || cg.profile_use.is_some())
{
early_error(
error_format,
handler.early_error(
"option `-Z profile-sample-use` cannot be used with `-C profile-generate` or `-C profile-use`",
);
}
@ -2517,23 +2465,19 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
// precedence.
match (cg.symbol_mangling_version, unstable_opts.symbol_mangling_version) {
(Some(smv_c), Some(smv_z)) if smv_c != smv_z => {
early_error(
error_format,
handler.early_error(
"incompatible values passed for `-C symbol-mangling-version` \
and `-Z symbol-mangling-version`",
);
}
(Some(SymbolManglingVersion::V0), _) => {}
(Some(_), _) if !unstable_opts.unstable_options => {
early_error(
error_format,
"`-C symbol-mangling-version=legacy` requires `-Z unstable-options`",
);
handler
.early_error("`-C symbol-mangling-version=legacy` requires `-Z unstable-options`");
}
(None, None) => {}
(None, smv) => {
early_warn(
error_format,
handler.early_warn(
"`-Z symbol-mangling-version` is deprecated; use `-C symbol-mangling-version`",
);
cg.symbol_mangling_version = smv;
@ -2545,25 +2489,19 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
// precedence.
match (cg.instrument_coverage, unstable_opts.instrument_coverage) {
(Some(ic_c), Some(ic_z)) if ic_c != ic_z => {
early_error(
error_format,
handler.early_error(
"incompatible values passed for `-C instrument-coverage` \
and `-Z instrument-coverage`",
);
}
(Some(InstrumentCoverage::Off | InstrumentCoverage::All), _) => {}
(Some(_), _) if !unstable_opts.unstable_options => {
early_error(
error_format,
"`-C instrument-coverage=except-*` requires `-Z unstable-options`",
);
handler.early_error("`-C instrument-coverage=except-*` requires `-Z unstable-options`");
}
(None, None) => {}
(None, ic) => {
early_warn(
error_format,
"`-Z instrument-coverage` is deprecated; use `-C instrument-coverage`",
);
handler
.early_warn("`-Z instrument-coverage` is deprecated; use `-C instrument-coverage`");
cg.instrument_coverage = ic;
}
_ => {}
@ -2571,8 +2509,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
if cg.instrument_coverage.is_some() && cg.instrument_coverage != Some(InstrumentCoverage::Off) {
if cg.profile_generate.enabled() || cg.profile_use.is_some() {
early_error(
error_format,
handler.early_error(
"option `-C instrument-coverage` is not compatible with either `-C profile-use` \
or `-C profile-generate`",
);
@ -2585,8 +2522,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
match cg.symbol_mangling_version {
None => cg.symbol_mangling_version = Some(SymbolManglingVersion::V0),
Some(SymbolManglingVersion::Legacy) => {
early_warn(
error_format,
handler.early_warn(
"-C instrument-coverage requires symbol mangling version `v0`, \
but `-C symbol-mangling-version=legacy` was specified",
);
@ -2602,10 +2538,9 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
if !cg.embed_bitcode {
match cg.lto {
LtoCli::No | LtoCli::Unspecified => {}
LtoCli::Yes | LtoCli::NoParam | LtoCli::Thin | LtoCli::Fat => early_error(
error_format,
"options `-C embed-bitcode=no` and `-C lto` are incompatible",
),
LtoCli::Yes | LtoCli::NoParam | LtoCli::Thin | LtoCli::Fat => {
handler.early_error("options `-C embed-bitcode=no` and `-C lto` are incompatible")
}
}
}
@ -2618,17 +2553,17 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
flag must also be passed to explicitly use it",
flavor.desc()
);
early_error(error_format, msg);
handler.early_error(msg);
}
}
let prints = collect_print_requests(&mut cg, &mut unstable_opts, matches, error_format);
let prints = collect_print_requests(handler, &mut cg, &mut unstable_opts, matches);
let cg = cg;
let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
let target_triple = parse_target_triple(matches, error_format);
let opt_level = parse_opt_level(matches, &cg, error_format);
let target_triple = parse_target_triple(handler, matches);
let opt_level = parse_opt_level(handler, matches, &cg);
// The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able
// to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`)
// for more details.
@ -2637,28 +2572,28 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
let mut search_paths = vec![];
for s in &matches.opt_strs("L") {
search_paths.push(SearchPath::from_cli_opt(s, error_format));
search_paths.push(SearchPath::from_cli_opt(handler, s));
}
let libs = parse_libs(matches, error_format);
let libs = parse_libs(handler, matches);
let test = matches.opt_present("test");
if !cg.remark.is_empty() && debuginfo == DebugInfo::None {
early_warn(error_format, "-C remark requires \"-C debuginfo=n\" to show source locations");
handler.early_warn("-C remark requires \"-C debuginfo=n\" to show source locations");
}
let externs = parse_externs(matches, &unstable_opts, error_format);
let externs = parse_externs(handler, matches, &unstable_opts);
let crate_name = matches.opt_str("crate-name");
let remap_path_prefix = parse_remap_path_prefix(matches, &unstable_opts, error_format);
let remap_path_prefix = parse_remap_path_prefix(handler, matches, &unstable_opts);
let pretty = parse_pretty(&unstable_opts, error_format);
let pretty = parse_pretty(handler, &unstable_opts);
// query-dep-graph is required if dump-dep-graph is given #106736
if unstable_opts.dump_dep_graph && !unstable_opts.query_dep_graph {
early_error(error_format, "can't dump dependency graph without `-Z query-dep-graph`");
handler.early_error("can't dump dependency graph without `-Z query-dep-graph`");
}
// Try to find a directory containing the Rust `src`, for more details see
@ -2690,7 +2625,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
};
let working_dir = std::env::current_dir().unwrap_or_else(|e| {
early_error(error_format, format!("Current directory is invalid: {e}"));
handler.early_error(format!("Current directory is invalid: {e}"));
});
let remap = FilePathMapping::new(remap_path_prefix.clone());
@ -2741,7 +2676,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
}
}
fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Option<PpMode> {
fn parse_pretty(handler: &EarlyErrorHandler, unstable_opts: &UnstableOptions) -> Option<PpMode> {
use PpMode::*;
let first = match unstable_opts.unpretty.as_deref()? {
@ -2760,16 +2695,13 @@ fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Optio
"thir-flat" => ThirFlat,
"mir" => Mir,
"mir-cfg" => MirCFG,
name => early_error(
efmt,
format!(
"argument to `unpretty` must be one of `normal`, `identified`, \
name => handler.early_error(format!(
"argument to `unpretty` must be one of `normal`, `identified`, \
`expanded`, `expanded,identified`, `expanded,hygiene`, \
`ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \
`hir,typed`, `hir-tree`, `thir-tree`, `thir-flat`, `mir` or \
`mir-cfg`; got {name}"
),
),
)),
};
debug!("got unpretty option: {first:?}");
Some(first)
@ -2809,8 +2741,8 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
}
pub mod nightly_options {
use super::{ErrorOutputType, OptionStability, RustcOptGroup};
use crate::early_error;
use super::{OptionStability, RustcOptGroup};
use crate::EarlyErrorHandler;
use rustc_feature::UnstableFeatures;
pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool {
@ -2826,7 +2758,11 @@ pub mod nightly_options {
UnstableFeatures::from_environment(krate).is_nightly_build()
}
pub fn check_nightly_options(matches: &getopts::Matches, flags: &[RustcOptGroup]) {
pub fn check_nightly_options(
handler: &EarlyErrorHandler,
matches: &getopts::Matches,
flags: &[RustcOptGroup],
) {
let has_z_unstable_option = matches.opt_strs("Z").iter().any(|x| *x == "unstable-options");
let really_allows_unstable_options = match_is_nightly_build(matches);
@ -2838,14 +2774,11 @@ pub mod nightly_options {
continue;
}
if opt.name != "Z" && !has_z_unstable_option {
early_error(
ErrorOutputType::default(),
format!(
"the `-Z unstable-options` flag must also be passed to enable \
handler.early_error(format!(
"the `-Z unstable-options` flag must also be passed to enable \
the flag `{}`",
opt.name
),
);
opt.name
));
}
if really_allows_unstable_options {
continue;
@ -2856,7 +2789,12 @@ pub mod nightly_options {
"the option `{}` is only accepted on the nightly compiler",
opt.name
);
early_error(ErrorOutputType::default(), msg);
let _ = handler.early_error_no_abort(msg);
handler.early_note("selecting a toolchain with `+toolchain` arguments require a rustup proxy; see <https://rust-lang.github.io/rustup/concepts/index.html>");
handler.early_help(
"consider switching to a nightly toolchain: `rustup default nightly`",
);
handler.early_note("for more information about Rust's stability policy, see <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html#unstable-features>");
}
OptionStability::Stable => {}
}