diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 8f754debaf0..3120b5bf0af 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -3305,23 +3305,6 @@ fn add_lld_args( let self_contained_cli = sess.opts.cg.link_self_contained.is_linker_enabled(); let self_contained_target = self_contained_components.is_linker_enabled(); - // FIXME: in the future, codegen backends may need to have more control over this process: they - // don't always support all the features the linker expects here, and vice versa. For example, - // at the time of writing this, lld expects a newer style of aarch64 TLS relocations that - // cranelift doesn't implement yet. That in turn can impact whether linking would succeed on - // such a target when using the `cg_clif` backend and lld. - // - // Until interactions between backends and linker features are expressible, we limit target - // specs to opt-in to lld only when we're on the llvm backend, where it's expected to work and - // tested on CI. As usual, the CLI still has precedence over this, so that users and developers - // can still override this default when needed (e.g. for tests). - let uses_llvm_backend = - matches!(sess.opts.unstable_opts.codegen_backend.as_deref(), None | Some("llvm")); - if !uses_llvm_backend && !self_contained_cli && sess.opts.cg.linker_flavor.is_none() { - // We bail if we're not using llvm and lld was not explicitly requested on the CLI. - return; - } - let self_contained_linker = self_contained_cli || self_contained_target; if self_contained_linker && !sess.opts.cg.link_self_contained.is_linker_disabled() { let mut linker_path_exists = false; diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index d2c4335cf2b..78ba841d89f 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -937,7 +937,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) { let groups = if verbose { config::rustc_optgroups() } else { config::rustc_short_optgroups() }; let mut options = getopts::Options::new(); for option in groups.iter().filter(|x| include_unstable_options || x.is_stable()) { - (option.apply)(&mut options); + option.apply(&mut options); } let message = "Usage: rustc [OPTIONS] INPUT"; let nightly_help = if nightly_build { @@ -1219,7 +1219,7 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option = match e { @@ -1233,7 +1233,7 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option(locations: I) -> ExternEntry fn optgroups() -> getopts::Options { let mut opts = getopts::Options::new(); for group in rustc_optgroups() { - (group.apply)(&mut opts); + group.apply(&mut opts); } return opts; } diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index b0ab50dd773..f9f2a14dbd2 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -715,7 +715,17 @@ fn lifetime_or_char(&mut self) -> TokenKind { self.bump(); self.bump(); self.eat_while(is_id_continue); - return RawLifetime; + match self.first() { + '\'' => { + // Check if after skipping literal contents we've met a closing + // single quote (which means that user attempted to create a + // string with single quotes). + self.bump(); + let kind = Char { terminated: true }; + return Literal { kind, suffix_start: self.pos_within_token() }; + } + _ => return RawLifetime, + } } // Either a lifetime or a character literal with diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index e27bb2fd135..142db8a17f0 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1933,6 +1933,7 @@ pub fn primitive_symbol(self) -> Option { ty::UintTy::U64 => Some(sym::u64), ty::UintTy::U128 => Some(sym::u128), }, + ty::Str => Some(sym::str), _ => None, } } diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 1af7fb9b86a..ef259703f0c 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -77,6 +77,8 @@ parse_box_syntax_removed_suggestion = use `Box::new()` instead parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier +parse_cannot_be_raw_lifetime = `{$ident}` cannot be a raw lifetime + parse_catch_after_try = keyword `catch` cannot follow a `try` block .help = try using `match` on the result of the `try` block instead diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index fdd500e90f8..7ec4ad6dc35 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2018,6 +2018,14 @@ pub(crate) struct CannotBeRawIdent { pub ident: Symbol, } +#[derive(Diagnostic)] +#[diag(parse_cannot_be_raw_lifetime)] +pub(crate) struct CannotBeRawLifetime { + #[primary_span] + pub span: Span, + pub ident: Symbol, +} + #[derive(Diagnostic)] #[diag(parse_keyword_lifetime)] pub(crate) struct KeywordLifetime { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index d627ef3d2cb..226de65445c 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -294,15 +294,21 @@ fn next_token(&mut self) -> (Token, bool) { let prefix_span = self.mk_sp(start, ident_start); if prefix_span.at_least_rust_2021() { - let lifetime_name_without_tick = self.str_from(ident_start); + let span = self.mk_sp(start, self.pos); + + let lifetime_name_without_tick = Symbol::intern(&self.str_from(ident_start)); + if !lifetime_name_without_tick.can_be_raw() { + self.dcx().emit_err(errors::CannotBeRawLifetime { span, ident: lifetime_name_without_tick }); + } + // Put the `'` back onto the lifetime name. - let mut lifetime_name = String::with_capacity(lifetime_name_without_tick.len() + 1); + let mut lifetime_name = String::with_capacity(lifetime_name_without_tick.as_str().len() + 1); lifetime_name.push('\''); - lifetime_name += lifetime_name_without_tick; + lifetime_name += lifetime_name_without_tick.as_str(); let sym = Symbol::intern(&lifetime_name); // Make sure we mark this as a raw identifier. - self.psess.raw_identifier_spans.push(self.mk_sp(start, self.pos)); + self.psess.raw_identifier_spans.push(span); token::Lifetime(sym, IdentIsRaw::Yes) } else { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index fe05605c1b9..fa2403db925 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -12,7 +12,7 @@ use std::path::{Path, PathBuf}; use std::str::{self, FromStr}; use std::sync::LazyLock; -use std::{fmt, fs, iter}; +use std::{cmp, fmt, fs, iter}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey}; @@ -1367,13 +1367,38 @@ pub fn build_target_config(early_dcx: &EarlyDiagCtxt, opts: &Options, sysroot: & } #[derive(Copy, Clone, PartialEq, Eq, Debug)] -enum OptionStability { +pub enum OptionStability { Stable, Unstable, } +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum OptionKind { + /// An option that takes a value, and cannot appear more than once (e.g. `--out-dir`). + /// + /// Corresponds to [`getopts::Options::optopt`]. + Opt, + + /// An option that takes a value, and can appear multiple times (e.g. `--emit`). + /// + /// Corresponds to [`getopts::Options::optmulti`]. + Multi, + + /// An option that does not take a value, and cannot appear more than once (e.g. `--help`). + /// + /// Corresponds to [`getopts::Options::optflag`]. + /// The `hint` string must be empty. + Flag, + + /// An option that does not take a value, and can appear multiple times (e.g. `-O`). + /// + /// Corresponds to [`getopts::Options::optflagmulti`]. + /// The `hint` string must be empty. + FlagMulti, +} + pub struct RustcOptGroup { - pub apply: Box &mut getopts::Options>, + apply: Box &mut getopts::Options>, pub name: &'static str, stability: OptionStability, } @@ -1383,73 +1408,42 @@ pub fn is_stable(&self) -> bool { self.stability == OptionStability::Stable } - pub fn stable(name: &'static str, f: F) -> RustcOptGroup - where - F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, - { - RustcOptGroup { name, apply: Box::new(f), stability: OptionStability::Stable } - } - - pub fn unstable(name: &'static str, f: F) -> RustcOptGroup - where - F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, - { - RustcOptGroup { name, apply: Box::new(f), stability: OptionStability::Unstable } + pub fn apply(&self, options: &mut getopts::Options) { + (self.apply)(options); } } -// The `opt` local module holds wrappers around the `getopts` API that -// adds extra rustc-specific metadata to each option; such metadata -// is exposed by . The public -// functions below ending with `_u` are the functions that return -// *unstable* options, i.e., options that are only enabled when the -// user also passes the `-Z unstable-options` debugging flag. -mod opt { - // The `fn flag*` etc below are written so that we can use them - // in the future; do not warn about them not being used right now. - #![allow(dead_code)] - - use super::RustcOptGroup; - - type R = RustcOptGroup; - type S = &'static str; - - fn stable(name: S, f: F) -> R - where - F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, - { - RustcOptGroup::stable(name, f) - } - - fn unstable(name: S, f: F) -> R - where - F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, - { - RustcOptGroup::unstable(name, f) - } - - fn longer(a: S, b: S) -> S { - if a.len() > b.len() { a } else { b } - } - - pub(crate) fn opt_s(a: S, b: S, c: S, d: S) -> R { - stable(longer(a, b), move |opts| opts.optopt(a, b, c, d)) - } - pub(crate) fn multi_s(a: S, b: S, c: S, d: S) -> R { - stable(longer(a, b), move |opts| opts.optmulti(a, b, c, d)) - } - pub(crate) fn flag_s(a: S, b: S, c: S) -> R { - stable(longer(a, b), move |opts| opts.optflag(a, b, c)) - } - pub(crate) fn flagmulti_s(a: S, b: S, c: S) -> R { - stable(longer(a, b), move |opts| opts.optflagmulti(a, b, c)) - } - - fn opt(a: S, b: S, c: S, d: S) -> R { - unstable(longer(a, b), move |opts| opts.optopt(a, b, c, d)) - } - pub(crate) fn multi(a: S, b: S, c: S, d: S) -> R { - unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d)) +pub fn make_opt( + stability: OptionStability, + kind: OptionKind, + short_name: &'static str, + long_name: &'static str, + desc: &'static str, + hint: &'static str, +) -> RustcOptGroup { + RustcOptGroup { + name: cmp::max_by_key(short_name, long_name, |s| s.len()), + stability, + apply: match kind { + OptionKind::Opt => Box::new(move |opts: &mut getopts::Options| { + opts.optopt(short_name, long_name, desc, hint) + }), + OptionKind::Multi => Box::new(move |opts: &mut getopts::Options| { + opts.optmulti(short_name, long_name, desc, hint) + }), + OptionKind::Flag => { + assert_eq!(hint, ""); + Box::new(move |opts: &mut getopts::Options| { + opts.optflag(short_name, long_name, desc) + }) + } + OptionKind::FlagMulti => { + assert_eq!(hint, ""); + Box::new(move |opts: &mut getopts::Options| { + opts.optflagmulti(short_name, long_name, desc) + }) + } + }, } } @@ -1464,46 +1458,60 @@ pub(crate) fn multi(a: S, b: S, c: S, d: S) -> R { /// including metadata for each option, such as whether the option is /// part of the stable long-term interface for rustc. pub fn rustc_short_optgroups() -> Vec { + use OptionKind::{Flag, FlagMulti, Multi, Opt}; + use OptionStability::Stable; + + use self::make_opt as opt; + vec![ - opt::flag_s("h", "help", "Display this message"), - opt::multi_s("", "cfg", "Configure the compilation environment. - SPEC supports the syntax `NAME[=\"VALUE\"]`.", "SPEC"), - opt::multi_s("", "check-cfg", "Provide list of expected cfgs for checking", "SPEC"), - opt::multi_s( + opt(Stable, Flag, "h", "help", "Display this message", ""), + opt( + Stable, + Multi, + "", + "cfg", + "Configure the compilation environment.\n\ + SPEC supports the syntax `NAME[=\"VALUE\"]`.", + "SPEC", + ), + opt(Stable, Multi, "", "check-cfg", "Provide list of expected cfgs for checking", "SPEC"), + opt( + Stable, + Multi, "L", "", - "Add a directory to the library search path. The - optional KIND can be one of dependency, crate, native, - framework, or all (the default).", + "Add a directory to the library search path. \ + The optional KIND can be one of dependency, crate, native, framework, or all (the default).", "[KIND=]PATH", ), - opt::multi_s( + opt( + Stable, + Multi, "l", "", - "Link the generated crate(s) to the specified native - library NAME. The optional KIND can be one of - static, framework, or dylib (the default). - Optional comma separated MODIFIERS (bundle|verbatim|whole-archive|as-needed) - may be specified each with a prefix of either '+' to - enable or '-' to disable.", + "Link the generated crate(s) to the specified native\n\ + library NAME. The optional KIND can be one of\n\ + static, framework, or dylib (the default).\n\ + Optional comma separated MODIFIERS\n\ + (bundle|verbatim|whole-archive|as-needed)\n\ + may be specified each with a prefix of either '+' to\n\ + enable or '-' to disable.", "[KIND[:MODIFIERS]=]NAME[:RENAME]", ), make_crate_type_option(), - opt::opt_s("", "crate-name", "Specify the name of the crate being built", "NAME"), - opt::opt_s( - "", - "edition", - &EDITION_STRING, - EDITION_NAME_LIST, - ), - opt::multi_s( + opt(Stable, Opt, "", "crate-name", "Specify the name of the crate being built", "NAME"), + opt(Stable, Opt, "", "edition", &EDITION_STRING, EDITION_NAME_LIST), + opt( + Stable, + Multi, "", "emit", - "Comma separated list of types of output for \ - the compiler to emit", + "Comma separated list of types of output for the compiler to emit", "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]", ), - opt::multi_s( + opt( + Stable, + Multi, "", "print", "Compiler information to print on stdout", @@ -1512,41 +1520,36 @@ pub fn rustc_short_optgroups() -> Vec { tls-models|target-spec-json|all-target-specs-json|native-static-libs|\ stack-protector-strategies|link-args|deployment-target]", ), - opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), - opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), - opt::opt_s("o", "", "Write output to ", "FILENAME"), - opt::opt_s( - "", - "out-dir", - "Write output to compiler-chosen filename \ - in ", - "DIR", - ), - opt::opt_s( + opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""), + opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=2", ""), + opt(Stable, Opt, "o", "", "Write output to ", "FILENAME"), + opt(Stable, Opt, "", "out-dir", "Write output to compiler-chosen filename in ", "DIR"), + opt( + Stable, + Opt, "", "explain", - "Provide a detailed explanation of an error \ - message", + "Provide a detailed explanation of an error message", "OPT", ), - opt::flag_s("", "test", "Build a test harness"), - opt::opt_s("", "target", "Target triple for which the code is compiled", "TARGET"), - opt::multi_s("A", "allow", "Set lint allowed", "LINT"), - opt::multi_s("W", "warn", "Set lint warnings", "LINT"), - opt::multi_s("", "force-warn", "Set lint force-warn", "LINT"), - opt::multi_s("D", "deny", "Set lint denied", "LINT"), - opt::multi_s("F", "forbid", "Set lint forbidden", "LINT"), - opt::multi_s( + opt(Stable, Flag, "", "test", "Build a test harness", ""), + opt(Stable, Opt, "", "target", "Target triple for which the code is compiled", "TARGET"), + opt(Stable, Multi, "A", "allow", "Set lint allowed", "LINT"), + opt(Stable, Multi, "W", "warn", "Set lint warnings", "LINT"), + opt(Stable, Multi, "", "force-warn", "Set lint force-warn", "LINT"), + opt(Stable, Multi, "D", "deny", "Set lint denied", "LINT"), + opt(Stable, Multi, "F", "forbid", "Set lint forbidden", "LINT"), + opt( + Stable, + Multi, "", "cap-lints", - "Set the most restrictive lint level. \ - More restrictive lints are capped at this \ - level", + "Set the most restrictive lint level. More restrictive lints are capped at this level", "LEVEL", ), - opt::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"), - opt::flag_s("V", "version", "Print version info and exit"), - opt::flag_s("v", "verbose", "Use verbose output"), + opt(Stable, Multi, "C", "codegen", "Set a codegen option", "OPT[=VALUE]"), + opt(Stable, Flag, "V", "version", "Print version info and exit", ""), + opt(Stable, Flag, "v", "verbose", "Use verbose output", ""), ] } @@ -1554,25 +1557,36 @@ pub fn rustc_short_optgroups() -> Vec { /// each option, such as whether the option is part of the stable /// long-term interface for rustc. pub fn rustc_optgroups() -> Vec { + use OptionKind::{Multi, Opt}; + use OptionStability::{Stable, Unstable}; + + use self::make_opt as opt; + let mut opts = rustc_short_optgroups(); // FIXME: none of these descriptions are actually used opts.extend(vec![ - opt::multi_s( + opt( + Stable, + Multi, "", "extern", "Specify where an external rust library is located", "NAME[=PATH]", ), - opt::opt_s("", "sysroot", "Override the system root", "PATH"), - opt::multi("Z", "", "Set unstable / perma-unstable options", "FLAG"), - opt::opt_s( + opt(Stable, Opt, "", "sysroot", "Override the system root", "PATH"), + opt(Unstable, Multi, "Z", "", "Set unstable / perma-unstable options", "FLAG"), + opt( + Stable, + Opt, "", "error-format", "How errors and other messages are produced", "human|json|short", ), - opt::multi_s("", "json", "Configure the JSON output of the compiler", "CONFIG"), - opt::opt_s( + opt(Stable, Multi, "", "json", "Configure the JSON output of the compiler", "CONFIG"), + opt( + Stable, + Opt, "", "color", "Configure coloring of output: @@ -1581,19 +1595,23 @@ pub fn rustc_optgroups() -> Vec { never = never colorize output", "auto|always|never", ), - opt::opt_s( + opt( + Stable, + Opt, "", "diagnostic-width", "Inform rustc of the width of the output so that diagnostics can be truncated to fit", "WIDTH", ), - opt::multi_s( + opt( + Stable, + Multi, "", "remap-path-prefix", "Remap source names in all output (compiler messages and output files)", "FROM=TO", ), - opt::multi("", "env-set", "Inject an environment variable", "VAR=VALUE"), + opt(Unstable, Multi, "", "env-set", "Inject an environment variable", "VAR=VALUE"), ]); opts } @@ -2756,7 +2774,9 @@ fn parse_pretty(early_dcx: &EarlyDiagCtxt, unstable_opts: &UnstableOptions) -> O } pub fn make_crate_type_option() -> RustcOptGroup { - opt::multi_s( + make_opt( + OptionStability::Stable, + OptionKind::Multi, "", "crate-type", "Comma separated list of types of crates diff --git a/src/bootstrap/defaults/config.dist.toml b/src/bootstrap/defaults/config.dist.toml index d4feffe0227..4346a9c2dd1 100644 --- a/src/bootstrap/defaults/config.dist.toml +++ b/src/bootstrap/defaults/config.dist.toml @@ -11,6 +11,7 @@ extended = true # Most users installing from source want to build all parts of the project from source. [llvm] download-ci-llvm = false + [rust] # We have several defaults in bootstrap that depend on whether the channel is `dev` (e.g. `omit-git-hash` and `download-ci-llvm`). # Make sure they don't get set when installing from source. diff --git a/src/bootstrap/defaults/config.library.toml b/src/bootstrap/defaults/config.library.toml index 3d697be8156..5447565a4b0 100644 --- a/src/bootstrap/defaults/config.library.toml +++ b/src/bootstrap/defaults/config.library.toml @@ -8,9 +8,6 @@ bench-stage = 0 [rust] # This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower. incremental = true -# Download rustc from CI instead of building it from source. -# For stage > 1 builds, this cuts compile times significantly when there are no changes on "compiler" tree. -download-rustc = "if-unchanged" # Make the compiler and standard library faster to build, at the expense of a ~20% runtime slowdown. lto = "off" diff --git a/src/bootstrap/defaults/config.tools.toml b/src/bootstrap/defaults/config.tools.toml index 27c1d1cf26d..76b47a841b3 100644 --- a/src/bootstrap/defaults/config.tools.toml +++ b/src/bootstrap/defaults/config.tools.toml @@ -3,11 +3,6 @@ [rust] # This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower. incremental = true -# Download rustc from CI instead of building it from source. -# For stage > 1 builds, this cuts compile times significantly when there are no changes on "compiler" tree. -# Using these defaults will download the stage2 compiler (see `download-rustc` -# setting) and the stage2 toolchain should therefore be used for these defaults. -download-rustc = "if-unchanged" [build] # Document with the in-tree rustdoc by default, since `download-rustc` makes it quick to compile. diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index f977c285a74..a93038d51d3 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1665,10 +1665,26 @@ fn get_table(option: &str) -> Result { let mut debuginfo_level_tools = None; let mut debuginfo_level_tests = None; let mut optimize = None; - let mut omit_git_hash = None; let mut lld_enabled = None; let mut std_features = None; + let default = config.channel == "dev"; + config.omit_git_hash = toml.rust.as_ref().and_then(|r| r.omit_git_hash).unwrap_or(default); + + config.rust_info = GitInfo::new(config.omit_git_hash, &config.src); + config.cargo_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/cargo")); + config.rust_analyzer_info = + GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rust-analyzer")); + config.clippy_info = + GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/clippy")); + config.miri_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/miri")); + config.rustfmt_info = + GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rustfmt")); + config.enzyme_info = + GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/enzyme")); + config.in_tree_llvm_info = GitInfo::new(false, &config.src.join("src/llvm-project")); + config.in_tree_gcc_info = GitInfo::new(false, &config.src.join("src/gcc")); + let mut is_user_configured_rust_channel = false; if let Some(rust) = toml.rust { @@ -1699,7 +1715,7 @@ fn get_table(option: &str) -> Result { verbose_tests, optimize_tests, codegen_tests, - omit_git_hash: omit_git_hash_toml, + omit_git_hash: _, // already handled above dist_src, save_toolstates, codegen_backends, @@ -1750,7 +1766,6 @@ fn get_table(option: &str) -> Result { std_features = std_features_toml; optimize = optimize_toml; - omit_git_hash = omit_git_hash_toml; config.rust_new_symbol_mangling = new_symbol_mangling; set(&mut config.rust_optimize_tests, optimize_tests); set(&mut config.codegen_tests, codegen_tests); @@ -1826,24 +1841,6 @@ fn get_table(option: &str) -> Result { config.reproducible_artifacts = flags.reproducible_artifact; - // rust_info must be set before is_ci_llvm_available() is called. - let default = config.channel == "dev"; - config.omit_git_hash = omit_git_hash.unwrap_or(default); - config.rust_info = GitInfo::new(config.omit_git_hash, &config.src); - - config.cargo_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/cargo")); - config.rust_analyzer_info = - GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rust-analyzer")); - config.clippy_info = - GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/clippy")); - config.miri_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/miri")); - config.rustfmt_info = - GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rustfmt")); - config.enzyme_info = - GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/enzyme")); - config.in_tree_llvm_info = GitInfo::new(false, &config.src.join("src/llvm-project")); - config.in_tree_gcc_info = GitInfo::new(false, &config.src.join("src/gcc")); - // We need to override `rust.channel` if it's manually specified when using the CI rustc. // This is because if the compiler uses a different channel than the one specified in config.toml, // tests may fail due to using a different channel than the one used by the compiler during tests. @@ -2760,9 +2757,19 @@ fn download_ci_rustc_commit( // If `download-rustc` is not set, default to rebuilding. let if_unchanged = match download_rustc { - None | Some(StringOrBool::Bool(false)) => return None, + None => self.rust_info.is_managed_git_subrepository(), + Some(StringOrBool::Bool(false)) => return None, Some(StringOrBool::Bool(true)) => false, - Some(StringOrBool::String(s)) if s == "if-unchanged" => true, + Some(StringOrBool::String(s)) if s == "if-unchanged" => { + if !self.rust_info.is_managed_git_subrepository() { + println!( + "ERROR: `download-rustc=if-unchanged` is only compatible with Git managed sources." + ); + crate::exit!(1); + } + + true + } Some(StringOrBool::String(other)) => { panic!("unrecognized option for download-rustc: {other}") } @@ -2789,7 +2796,7 @@ fn download_ci_rustc_commit( } println!("ERROR: could not find commit hash for downloading rustc"); println!("HELP: maybe your repository history is too shallow?"); - println!("HELP: consider disabling `download-rustc`"); + println!("HELP: consider setting `rust.download-rustc=false` in config.toml"); println!("HELP: or fetch enough history to include one upstream commit"); crate::exit!(1); } diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 1f02757682c..b6523a458e2 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -135,6 +135,7 @@ fn override_toml() { [rust] lto = "off" deny-warnings = true +download-rustc=false [build] gdb = "foo" @@ -200,6 +201,8 @@ fn override_toml() { .collect(), "setting dictionary value" ); + assert!(!config.llvm_from_ci); + assert!(!config.download_rustc()); } #[test] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 7c9dcd41e6a..78dc0b8e2f9 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -215,477 +215,482 @@ fn init_logging(early_dcx: &EarlyDiagCtxt) { } fn opts() -> Vec { - let stable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::stable; - let unstable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::unstable; + use rustc_session::config::OptionKind::{Flag, FlagMulti, Multi, Opt}; + use rustc_session::config::OptionStability::{Stable, Unstable}; + use rustc_session::config::make_opt as opt; + vec![ - stable("h", |o| o.optflagmulti("h", "help", "show this help message")), - stable("V", |o| o.optflagmulti("V", "version", "print rustdoc's version")), - stable("v", |o| o.optflagmulti("v", "verbose", "use verbose output")), - stable("w", |o| o.optopt("w", "output-format", "the output type to write", "[html]")), - stable("output", |o| { - o.optopt( - "", - "output", - "Which directory to place the output. \ - This option is deprecated, use --out-dir instead.", - "PATH", - ) - }), - stable("o", |o| o.optopt("o", "out-dir", "which directory to place the output", "PATH")), - stable("crate-name", |o| { - o.optopt("", "crate-name", "specify the name of this crate", "NAME") - }), + opt(Stable, FlagMulti, "h", "help", "show this help message", ""), + opt(Stable, FlagMulti, "V", "version", "print rustdoc's version", ""), + opt(Stable, FlagMulti, "v", "verbose", "use verbose output", ""), + opt(Stable, Opt, "w", "output-format", "the output type to write", "[html]"), + opt( + Stable, + Opt, + "", + "output", + "Which directory to place the output. This option is deprecated, use --out-dir instead.", + "PATH", + ), + opt(Stable, Opt, "o", "out-dir", "which directory to place the output", "PATH"), + opt(Stable, Opt, "", "crate-name", "specify the name of this crate", "NAME"), make_crate_type_option(), - stable("L", |o| { - o.optmulti("L", "library-path", "directory to add to crate search path", "DIR") - }), - stable("cfg", |o| o.optmulti("", "cfg", "pass a --cfg to rustc", "")), - stable("check-cfg", |o| o.optmulti("", "check-cfg", "pass a --check-cfg to rustc", "")), - stable("extern", |o| o.optmulti("", "extern", "pass an --extern to rustc", "NAME[=PATH]")), - unstable("extern-html-root-url", |o| { - o.optmulti( - "", - "extern-html-root-url", - "base URL to use for dependencies; for example, \ - \"std=/doc\" links std::vec::Vec to /doc/std/vec/struct.Vec.html", - "NAME=URL", - ) - }), - unstable("extern-html-root-takes-precedence", |o| { - o.optflagmulti( - "", - "extern-html-root-takes-precedence", - "give precedence to `--extern-html-root-url`, not `html_root_url`", - ) - }), - stable("C", |o| { - o.optmulti("C", "codegen", "pass a codegen option to rustc", "OPT[=VALUE]") - }), - stable("document-private-items", |o| { - o.optflagmulti("", "document-private-items", "document private items") - }), - unstable("document-hidden-items", |o| { - o.optflagmulti("", "document-hidden-items", "document items that have doc(hidden)") - }), - stable("test", |o| o.optflagmulti("", "test", "run code examples as tests")), - stable("test-args", |o| { - o.optmulti("", "test-args", "arguments to pass to the test runner", "ARGS") - }), - stable("test-run-directory", |o| { - o.optopt( - "", - "test-run-directory", - "The working directory in which to run tests", - "PATH", - ) - }), - stable("target", |o| o.optopt("", "target", "target triple to document", "TRIPLE")), - stable("markdown-css", |o| { - o.optmulti( - "", - "markdown-css", - "CSS files to include via in a rendered Markdown file", - "FILES", - ) - }), - stable("html-in-header", |o| { - o.optmulti( - "", - "html-in-header", - "files to include inline in the section of a rendered Markdown file \ - or generated documentation", - "FILES", - ) - }), - stable("html-before-content", |o| { - o.optmulti( - "", - "html-before-content", - "files to include inline between and the content of a rendered \ - Markdown file or generated documentation", - "FILES", - ) - }), - stable("html-after-content", |o| { - o.optmulti( - "", - "html-after-content", - "files to include inline between the content and of a rendered \ - Markdown file or generated documentation", - "FILES", - ) - }), - unstable("markdown-before-content", |o| { - o.optmulti( - "", - "markdown-before-content", - "files to include inline between and the content of a rendered \ - Markdown file or generated documentation", - "FILES", - ) - }), - unstable("markdown-after-content", |o| { - o.optmulti( - "", - "markdown-after-content", - "files to include inline between the content and of a rendered \ - Markdown file or generated documentation", - "FILES", - ) - }), - stable("markdown-playground-url", |o| { - o.optopt("", "markdown-playground-url", "URL to send code snippets to", "URL") - }), - stable("markdown-no-toc", |o| { - o.optflagmulti("", "markdown-no-toc", "don't include table of contents") - }), - stable("e", |o| { - o.optopt( - "e", - "extend-css", - "To add some CSS rules with a given file to generate doc with your \ - own theme. However, your theme might break if the rustdoc's generated HTML \ - changes, so be careful!", - "PATH", - ) - }), - unstable("Z", |o| { - o.optmulti("Z", "", "unstable / perma-unstable options (only on nightly build)", "FLAG") - }), - stable("sysroot", |o| o.optopt("", "sysroot", "Override the system root", "PATH")), - unstable("playground-url", |o| { - o.optopt( - "", - "playground-url", - "URL to send code snippets to, may be reset by --markdown-playground-url \ - or `#![doc(html_playground_url=...)]`", - "URL", - ) - }), - unstable("display-doctest-warnings", |o| { - o.optflagmulti( - "", - "display-doctest-warnings", - "show warnings that originate in doctests", - ) - }), - stable("crate-version", |o| { - o.optopt("", "crate-version", "crate version to print into documentation", "VERSION") - }), - unstable("sort-modules-by-appearance", |o| { - o.optflagmulti( - "", - "sort-modules-by-appearance", - "sort modules by where they appear in the program, rather than alphabetically", - ) - }), - stable("default-theme", |o| { - o.optopt( - "", - "default-theme", - "Set the default theme. THEME should be the theme name, generally lowercase. \ - If an unknown default theme is specified, the builtin default is used. \ - The set of themes, and the rustdoc built-in default, are not stable.", - "THEME", - ) - }), - unstable("default-setting", |o| { - o.optmulti( - "", - "default-setting", - "Default value for a rustdoc setting (used when \"rustdoc-SETTING\" is absent \ - from web browser Local Storage). If VALUE is not supplied, \"true\" is used. \ - Supported SETTINGs and VALUEs are not documented and not stable.", - "SETTING[=VALUE]", - ) - }), - stable("theme", |o| { - o.optmulti( - "", - "theme", - "additional themes which will be added to the generated docs", - "FILES", - ) - }), - stable("check-theme", |o| { - o.optmulti("", "check-theme", "check if given theme is valid", "FILES") - }), - unstable("resource-suffix", |o| { - o.optopt( - "", - "resource-suffix", - "suffix to add to CSS and JavaScript files, e.g., \"search-index.js\" will \ - become \"search-index-suffix.js\"", - "PATH", - ) - }), - stable("edition", |o| { - o.optopt( - "", - "edition", - "edition to use when compiling rust code (default: 2015)", - "EDITION", - ) - }), - stable("color", |o| { - o.optopt( - "", - "color", - "Configure coloring of output: + opt(Stable, Multi, "L", "library-path", "directory to add to crate search path", "DIR"), + opt(Stable, Multi, "", "cfg", "pass a --cfg to rustc", ""), + opt(Stable, Multi, "", "check-cfg", "pass a --check-cfg to rustc", ""), + opt(Stable, Multi, "", "extern", "pass an --extern to rustc", "NAME[=PATH]"), + opt( + Unstable, + Multi, + "", + "extern-html-root-url", + "base URL to use for dependencies; for example, \ + \"std=/doc\" links std::vec::Vec to /doc/std/vec/struct.Vec.html", + "NAME=URL", + ), + opt( + Unstable, + FlagMulti, + "", + "extern-html-root-takes-precedence", + "give precedence to `--extern-html-root-url`, not `html_root_url`", + "", + ), + opt(Stable, Multi, "C", "codegen", "pass a codegen option to rustc", "OPT[=VALUE]"), + opt(Stable, FlagMulti, "", "document-private-items", "document private items", ""), + opt( + Unstable, + FlagMulti, + "", + "document-hidden-items", + "document items that have doc(hidden)", + "", + ), + opt(Stable, FlagMulti, "", "test", "run code examples as tests", ""), + opt(Stable, Multi, "", "test-args", "arguments to pass to the test runner", "ARGS"), + opt( + Stable, + Opt, + "", + "test-run-directory", + "The working directory in which to run tests", + "PATH", + ), + opt(Stable, Opt, "", "target", "target triple to document", "TRIPLE"), + opt( + Stable, + Multi, + "", + "markdown-css", + "CSS files to include via in a rendered Markdown file", + "FILES", + ), + opt( + Stable, + Multi, + "", + "html-in-header", + "files to include inline in the section of a rendered Markdown file \ + or generated documentation", + "FILES", + ), + opt( + Stable, + Multi, + "", + "html-before-content", + "files to include inline between and the content of a rendered \ + Markdown file or generated documentation", + "FILES", + ), + opt( + Stable, + Multi, + "", + "html-after-content", + "files to include inline between the content and of a rendered \ + Markdown file or generated documentation", + "FILES", + ), + opt( + Unstable, + Multi, + "", + "markdown-before-content", + "files to include inline between and the content of a rendered \ + Markdown file or generated documentation", + "FILES", + ), + opt( + Unstable, + Multi, + "", + "markdown-after-content", + "files to include inline between the content and of a rendered \ + Markdown file or generated documentation", + "FILES", + ), + opt(Stable, Opt, "", "markdown-playground-url", "URL to send code snippets to", "URL"), + opt(Stable, FlagMulti, "", "markdown-no-toc", "don't include table of contents", ""), + opt( + Stable, + Opt, + "e", + "extend-css", + "To add some CSS rules with a given file to generate doc with your own theme. \ + However, your theme might break if the rustdoc's generated HTML changes, so be careful!", + "PATH", + ), + opt( + Unstable, + Multi, + "Z", + "", + "unstable / perma-unstable options (only on nightly build)", + "FLAG", + ), + opt(Stable, Opt, "", "sysroot", "Override the system root", "PATH"), + opt( + Unstable, + Opt, + "", + "playground-url", + "URL to send code snippets to, may be reset by --markdown-playground-url \ + or `#![doc(html_playground_url=...)]`", + "URL", + ), + opt( + Unstable, + FlagMulti, + "", + "display-doctest-warnings", + "show warnings that originate in doctests", + "", + ), + opt( + Stable, + Opt, + "", + "crate-version", + "crate version to print into documentation", + "VERSION", + ), + opt( + Unstable, + FlagMulti, + "", + "sort-modules-by-appearance", + "sort modules by where they appear in the program, rather than alphabetically", + "", + ), + opt( + Stable, + Opt, + "", + "default-theme", + "Set the default theme. THEME should be the theme name, generally lowercase. \ + If an unknown default theme is specified, the builtin default is used. \ + The set of themes, and the rustdoc built-in default, are not stable.", + "THEME", + ), + opt( + Unstable, + Multi, + "", + "default-setting", + "Default value for a rustdoc setting (used when \"rustdoc-SETTING\" is absent \ + from web browser Local Storage). If VALUE is not supplied, \"true\" is used. \ + Supported SETTINGs and VALUEs are not documented and not stable.", + "SETTING[=VALUE]", + ), + opt( + Stable, + Multi, + "", + "theme", + "additional themes which will be added to the generated docs", + "FILES", + ), + opt(Stable, Multi, "", "check-theme", "check if given theme is valid", "FILES"), + opt( + Unstable, + Opt, + "", + "resource-suffix", + "suffix to add to CSS and JavaScript files, \ + e.g., \"search-index.js\" will become \"search-index-suffix.js\"", + "PATH", + ), + opt( + Stable, + Opt, + "", + "edition", + "edition to use when compiling rust code (default: 2015)", + "EDITION", + ), + opt( + Stable, + Opt, + "", + "color", + "Configure coloring of output: auto = colorize, if output goes to a tty (default); always = always colorize output; never = never colorize output", - "auto|always|never", - ) - }), - stable("error-format", |o| { - o.optopt( - "", - "error-format", - "How errors and other messages are produced", - "human|json|short", - ) - }), - stable("diagnostic-width", |o| { - o.optopt( - "", - "diagnostic-width", - "Provide width of the output for truncated error messages", - "WIDTH", - ) - }), - stable("json", |o| { - o.optopt("", "json", "Configure the structure of JSON diagnostics", "CONFIG") - }), - stable("allow", |o| o.optmulti("A", "allow", "Set lint allowed", "LINT")), - stable("warn", |o| o.optmulti("W", "warn", "Set lint warnings", "LINT")), - stable("force-warn", |o| o.optmulti("", "force-warn", "Set lint force-warn", "LINT")), - stable("deny", |o| o.optmulti("D", "deny", "Set lint denied", "LINT")), - stable("forbid", |o| o.optmulti("F", "forbid", "Set lint forbidden", "LINT")), - stable("cap-lints", |o| { - o.optmulti( - "", - "cap-lints", - "Set the most restrictive lint level. \ - More restrictive lints are capped at this \ - level. By default, it is at `forbid` level.", - "LEVEL", - ) - }), - unstable("index-page", |o| { - o.optopt("", "index-page", "Markdown file to be used as index page", "PATH") - }), - unstable("enable-index-page", |o| { - o.optflagmulti("", "enable-index-page", "To enable generation of the index page") - }), - unstable("static-root-path", |o| { - o.optopt( - "", - "static-root-path", - "Path string to force loading static files from in output pages. \ - If not set, uses combinations of '../' to reach the documentation root.", - "PATH", - ) - }), - unstable("persist-doctests", |o| { - o.optopt( - "", - "persist-doctests", - "Directory to persist doctest executables into", - "PATH", - ) - }), - unstable("show-coverage", |o| { - o.optflagmulti( - "", - "show-coverage", - "calculate percentage of public items with documentation", - ) - }), - unstable("enable-per-target-ignores", |o| { - o.optflagmulti( - "", - "enable-per-target-ignores", - "parse ignore-foo for ignoring doctests on a per-target basis", - ) - }), - unstable("runtool", |o| { - o.optopt( - "", - "runtool", - "", - "The tool to run tests with when building for a different target than host", - ) - }), - unstable("runtool-arg", |o| { - o.optmulti( - "", - "runtool-arg", - "", - "One (of possibly many) arguments to pass to the runtool", - ) - }), - unstable("test-builder", |o| { - o.optopt("", "test-builder", "The rustc-like binary to use as the test builder", "PATH") - }), - unstable("test-builder-wrapper", |o| { - o.optmulti( - "", - "test-builder-wrapper", - "Wrapper program to pass test-builder and arguments", - "PATH", - ) - }), - unstable("check", |o| o.optflagmulti("", "check", "Run rustdoc checks")), - unstable("generate-redirect-map", |o| { - o.optflagmulti( - "", - "generate-redirect-map", - "Generate JSON file at the top level instead of generating HTML redirection files", - ) - }), - unstable("emit", |o| { - o.optmulti( - "", - "emit", - "Comma separated list of types of output for rustdoc to emit", - "[unversioned-shared-resources,toolchain-shared-resources,invocation-specific]", - ) - }), - unstable("no-run", |o| { - o.optflagmulti("", "no-run", "Compile doctests without running them") - }), - unstable("remap-path-prefix", |o| { - o.optmulti( - "", - "remap-path-prefix", - "Remap source names in compiler messages", - "FROM=TO", - ) - }), - unstable("show-type-layout", |o| { - o.optflagmulti("", "show-type-layout", "Include the memory layout of types in the docs") - }), - unstable("nocapture", |o| { - o.optflag("", "nocapture", "Don't capture stdout and stderr of tests") - }), - unstable("generate-link-to-definition", |o| { - o.optflag( - "", - "generate-link-to-definition", - "Make the identifiers in the HTML source code pages navigable", - ) - }), - unstable("scrape-examples-output-path", |o| { - o.optopt( - "", - "scrape-examples-output-path", - "", - "collect function call information and output at the given path", - ) - }), - unstable("scrape-examples-target-crate", |o| { - o.optmulti( - "", - "scrape-examples-target-crate", - "", - "collect function call information for functions from the target crate", - ) - }), - unstable("scrape-tests", |o| { - o.optflag("", "scrape-tests", "Include test code when scraping examples") - }), - unstable("with-examples", |o| { - o.optmulti( - "", - "with-examples", - "", - "path to function call information (for displaying examples in the documentation)", - ) - }), - unstable("merge", |o| { - o.optopt( - "", - "merge", - "Controls how rustdoc handles files from previously documented crates in the doc root - none = Do not write cross-crate information to the --out-dir - shared = Append current crate's info to files found in the --out-dir - finalize = Write current crate's info and --include-parts-dir info to the --out-dir, overwriting conflicting files", - "none|shared|finalize", - ) - }), - unstable("parts-out-dir", |o| { - o.optopt( - "", - "parts-out-dir", - "Writes trait implementations and other info for the current crate to provided path. Only use with --merge=none", - "path/to/doc.parts/", - ) - }), - unstable("include-parts-dir", |o| { - o.optmulti( - "", - "include-parts-dir", - "Includes trait implementations and other crate info from provided path. Only use with --merge=finalize", - "path/to/doc.parts/", - ) - }), + "auto|always|never", + ), + opt( + Stable, + Opt, + "", + "error-format", + "How errors and other messages are produced", + "human|json|short", + ), + opt( + Stable, + Opt, + "", + "diagnostic-width", + "Provide width of the output for truncated error messages", + "WIDTH", + ), + opt(Stable, Opt, "", "json", "Configure the structure of JSON diagnostics", "CONFIG"), + opt(Stable, Multi, "A", "allow", "Set lint allowed", "LINT"), + opt(Stable, Multi, "W", "warn", "Set lint warnings", "LINT"), + opt(Stable, Multi, "", "force-warn", "Set lint force-warn", "LINT"), + opt(Stable, Multi, "D", "deny", "Set lint denied", "LINT"), + opt(Stable, Multi, "F", "forbid", "Set lint forbidden", "LINT"), + opt( + Stable, + Multi, + "", + "cap-lints", + "Set the most restrictive lint level. \ + More restrictive lints are capped at this level. \ + By default, it is at `forbid` level.", + "LEVEL", + ), + opt(Unstable, Opt, "", "index-page", "Markdown file to be used as index page", "PATH"), + opt( + Unstable, + FlagMulti, + "", + "enable-index-page", + "To enable generation of the index page", + "", + ), + opt( + Unstable, + Opt, + "", + "static-root-path", + "Path string to force loading static files from in output pages. \ + If not set, uses combinations of '../' to reach the documentation root.", + "PATH", + ), + opt( + Unstable, + Opt, + "", + "persist-doctests", + "Directory to persist doctest executables into", + "PATH", + ), + opt( + Unstable, + FlagMulti, + "", + "show-coverage", + "calculate percentage of public items with documentation", + "", + ), + opt( + Unstable, + FlagMulti, + "", + "enable-per-target-ignores", + "parse ignore-foo for ignoring doctests on a per-target basis", + "", + ), + opt( + Unstable, + Opt, + "", + "runtool", + "", + "The tool to run tests with when building for a different target than host", + ), + opt( + Unstable, + Multi, + "", + "runtool-arg", + "", + "One (of possibly many) arguments to pass to the runtool", + ), + opt( + Unstable, + Opt, + "", + "test-builder", + "The rustc-like binary to use as the test builder", + "PATH", + ), + opt( + Unstable, + Multi, + "", + "test-builder-wrapper", + "Wrapper program to pass test-builder and arguments", + "PATH", + ), + opt(Unstable, FlagMulti, "", "check", "Run rustdoc checks", ""), + opt( + Unstable, + FlagMulti, + "", + "generate-redirect-map", + "Generate JSON file at the top level instead of generating HTML redirection files", + "", + ), + opt( + Unstable, + Multi, + "", + "emit", + "Comma separated list of types of output for rustdoc to emit", + "[unversioned-shared-resources,toolchain-shared-resources,invocation-specific]", + ), + opt(Unstable, FlagMulti, "", "no-run", "Compile doctests without running them", ""), + opt( + Unstable, + Multi, + "", + "remap-path-prefix", + "Remap source names in compiler messages", + "FROM=TO", + ), + opt( + Unstable, + FlagMulti, + "", + "show-type-layout", + "Include the memory layout of types in the docs", + "", + ), + opt(Unstable, Flag, "", "nocapture", "Don't capture stdout and stderr of tests", ""), + opt( + Unstable, + Flag, + "", + "generate-link-to-definition", + "Make the identifiers in the HTML source code pages navigable", + "", + ), + opt( + Unstable, + Opt, + "", + "scrape-examples-output-path", + "", + "collect function call information and output at the given path", + ), + opt( + Unstable, + Multi, + "", + "scrape-examples-target-crate", + "", + "collect function call information for functions from the target crate", + ), + opt(Unstable, Flag, "", "scrape-tests", "Include test code when scraping examples", ""), + opt( + Unstable, + Multi, + "", + "with-examples", + "", + "path to function call information (for displaying examples in the documentation)", + ), + opt( + Unstable, + Opt, + "", + "merge", + "Controls how rustdoc handles files from previously documented crates in the doc root\n\ + none = Do not write cross-crate information to the --out-dir\n\ + shared = Append current crate's info to files found in the --out-dir\n\ + finalize = Write current crate's info and --include-parts-dir info to the --out-dir, overwriting conflicting files", + "none|shared|finalize", + ), + opt( + Unstable, + Opt, + "", + "parts-out-dir", + "Writes trait implementations and other info for the current crate to provided path. Only use with --merge=none", + "path/to/doc.parts/", + ), + opt( + Unstable, + Multi, + "", + "include-parts-dir", + "Includes trait implementations and other crate info from provided path. Only use with --merge=finalize", + "path/to/doc.parts/", + ), // deprecated / removed options - unstable("disable-minification", |o| o.optflagmulti("", "disable-minification", "removed")), - stable("plugin-path", |o| { - o.optmulti( - "", - "plugin-path", - "removed, see issue #44136 \ - for more information", - "DIR", - ) - }), - stable("passes", |o| { - o.optmulti( - "", - "passes", - "removed, see issue #44136 \ - for more information", - "PASSES", - ) - }), - stable("plugins", |o| { - o.optmulti( - "", - "plugins", - "removed, see issue #44136 \ - for more information", - "PLUGINS", - ) - }), - stable("no-default", |o| { - o.optflagmulti( - "", - "no-defaults", - "removed, see issue #44136 \ - for more information", - ) - }), - stable("r", |o| { - o.optopt( - "r", - "input-format", - "removed, see issue #44136 \ - for more information", - "[rust]", - ) - }), - unstable("html-no-source", |o| { - o.optflag("", "html-no-source", "Disable HTML source code pages generation") - }), + opt(Unstable, FlagMulti, "", "disable-minification", "removed", ""), + opt( + Stable, + Multi, + "", + "plugin-path", + "removed, see issue #44136 for more information", + "DIR", + ), + opt( + Stable, + Multi, + "", + "passes", + "removed, see issue #44136 for more information", + "PASSES", + ), + opt( + Stable, + Multi, + "", + "plugins", + "removed, see issue #44136 for more information", + "PLUGINS", + ), + opt( + Stable, + FlagMulti, + "", + "no-defaults", + "removed, see issue #44136 for more information", + "", + ), + opt( + Stable, + Opt, + "r", + "input-format", + "removed, see issue #44136 for more information", + "[rust]", + ), + opt(Unstable, Flag, "", "html-no-source", "Disable HTML source code pages generation", ""), ] } fn usage(argv0: &str) { let mut options = getopts::Options::new(); for option in opts() { - (option.apply)(&mut options); + option.apply(&mut options); } println!("{}", options.usage(&format!("{argv0} [options] "))); println!(" @path Read newline separated options from `path`\n"); @@ -769,7 +774,7 @@ fn main_args( let mut options = getopts::Options::new(); for option in opts() { - (option.apply)(&mut options); + option.apply(&mut options); } let matches = match options.parse(&args) { Ok(m) => m, diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 368b98c9f0d..5765cb97a7e 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -41,6 +41,7 @@ pub mod rfs { pub use object; pub use regex; pub use serde_json; +pub use similar; pub use wasmparser; // tidy-alphabetical-end diff --git a/tests/run-make/rustc-help/help-v.diff b/tests/run-make/rustc-help/help-v.diff new file mode 100644 index 00000000000..22c5dd81bdb --- /dev/null +++ b/tests/run-make/rustc-help/help-v.diff @@ -0,0 +1,29 @@ +@@ -51,10 +51,27 @@ + Set a codegen option + -V, --version Print version info and exit + -v, --verbose Use verbose output ++ --extern NAME[=PATH] ++ Specify where an external rust library is located ++ --sysroot PATH Override the system root ++ --error-format human|json|short ++ How errors and other messages are produced ++ --json CONFIG Configure the JSON output of the compiler ++ --color auto|always|never ++ Configure coloring of output: ++ auto = colorize, if output goes to a tty (default); ++ always = always colorize output; ++ never = never colorize output ++ --diagnostic-width WIDTH ++ Inform rustc of the width of the output so that ++ diagnostics can be truncated to fit ++ --remap-path-prefix FROM=TO ++ Remap source names in all output (compiler messages ++ and output files) ++ @path Read newline separated options from `path` + + Additional help: + -C help Print codegen options + -W help Print 'lint' options and default settings + -Z help Print unstable compiler options +- --help -v Print the full set of options rustc accepts + diff --git a/tests/run-make/rustc-help/help-v.stdout b/tests/run-make/rustc-help/help-v.stdout new file mode 100644 index 00000000000..dbd67b57df2 --- /dev/null +++ b/tests/run-make/rustc-help/help-v.stdout @@ -0,0 +1,77 @@ +Usage: rustc [OPTIONS] INPUT + +Options: + -h, --help Display this message + --cfg SPEC Configure the compilation environment. + SPEC supports the syntax `NAME[="VALUE"]`. + --check-cfg SPEC + Provide list of expected cfgs for checking + -L [KIND=]PATH Add a directory to the library search path. The + optional KIND can be one of dependency, crate, native, + framework, or all (the default). + -l [KIND[:MODIFIERS]=]NAME[:RENAME] + Link the generated crate(s) to the specified native + library NAME. The optional KIND can be one of + static, framework, or dylib (the default). + Optional comma separated MODIFIERS + (bundle|verbatim|whole-archive|as-needed) + may be specified each with a prefix of either '+' to + enable or '-' to disable. + --crate-type [bin|lib|rlib|dylib|cdylib|staticlib|proc-macro] + Comma separated list of types of crates + for the compiler to emit + --crate-name NAME + Specify the name of the crate being built + --edition 2015|2018|2021|2024 + Specify which edition of the compiler to use when + compiling code. The default is 2015 and the latest + stable edition is 2021. + --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir] + Comma separated list of types of output for the + compiler to emit + --print [crate-name|file-names|sysroot|target-libdir|cfg|check-cfg|calling-conventions|target-list|target-cpus|target-features|relocation-models|code-models|tls-models|target-spec-json|all-target-specs-json|native-static-libs|stack-protector-strategies|link-args|deployment-target] + Compiler information to print on stdout + -g Equivalent to -C debuginfo=2 + -O Equivalent to -C opt-level=2 + -o FILENAME Write output to + --out-dir DIR Write output to compiler-chosen filename in + --explain OPT Provide a detailed explanation of an error message + --test Build a test harness + --target TARGET Target triple for which the code is compiled + -A, --allow LINT Set lint allowed + -W, --warn LINT Set lint warnings + --force-warn LINT + Set lint force-warn + -D, --deny LINT Set lint denied + -F, --forbid LINT Set lint forbidden + --cap-lints LEVEL + Set the most restrictive lint level. More restrictive + lints are capped at this level + -C, --codegen OPT[=VALUE] + Set a codegen option + -V, --version Print version info and exit + -v, --verbose Use verbose output + --extern NAME[=PATH] + Specify where an external rust library is located + --sysroot PATH Override the system root + --error-format human|json|short + How errors and other messages are produced + --json CONFIG Configure the JSON output of the compiler + --color auto|always|never + Configure coloring of output: + auto = colorize, if output goes to a tty (default); + always = always colorize output; + never = never colorize output + --diagnostic-width WIDTH + Inform rustc of the width of the output so that + diagnostics can be truncated to fit + --remap-path-prefix FROM=TO + Remap source names in all output (compiler messages + and output files) + @path Read newline separated options from `path` + +Additional help: + -C help Print codegen options + -W help Print 'lint' options and default settings + -Z help Print unstable compiler options + diff --git a/tests/run-make/rustc-help/help.stdout b/tests/run-make/rustc-help/help.stdout new file mode 100644 index 00000000000..a7d07162799 --- /dev/null +++ b/tests/run-make/rustc-help/help.stdout @@ -0,0 +1,60 @@ +Usage: rustc [OPTIONS] INPUT + +Options: + -h, --help Display this message + --cfg SPEC Configure the compilation environment. + SPEC supports the syntax `NAME[="VALUE"]`. + --check-cfg SPEC + Provide list of expected cfgs for checking + -L [KIND=]PATH Add a directory to the library search path. The + optional KIND can be one of dependency, crate, native, + framework, or all (the default). + -l [KIND[:MODIFIERS]=]NAME[:RENAME] + Link the generated crate(s) to the specified native + library NAME. The optional KIND can be one of + static, framework, or dylib (the default). + Optional comma separated MODIFIERS + (bundle|verbatim|whole-archive|as-needed) + may be specified each with a prefix of either '+' to + enable or '-' to disable. + --crate-type [bin|lib|rlib|dylib|cdylib|staticlib|proc-macro] + Comma separated list of types of crates + for the compiler to emit + --crate-name NAME + Specify the name of the crate being built + --edition 2015|2018|2021|2024 + Specify which edition of the compiler to use when + compiling code. The default is 2015 and the latest + stable edition is 2021. + --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir] + Comma separated list of types of output for the + compiler to emit + --print [crate-name|file-names|sysroot|target-libdir|cfg|check-cfg|calling-conventions|target-list|target-cpus|target-features|relocation-models|code-models|tls-models|target-spec-json|all-target-specs-json|native-static-libs|stack-protector-strategies|link-args|deployment-target] + Compiler information to print on stdout + -g Equivalent to -C debuginfo=2 + -O Equivalent to -C opt-level=2 + -o FILENAME Write output to + --out-dir DIR Write output to compiler-chosen filename in + --explain OPT Provide a detailed explanation of an error message + --test Build a test harness + --target TARGET Target triple for which the code is compiled + -A, --allow LINT Set lint allowed + -W, --warn LINT Set lint warnings + --force-warn LINT + Set lint force-warn + -D, --deny LINT Set lint denied + -F, --forbid LINT Set lint forbidden + --cap-lints LEVEL + Set the most restrictive lint level. More restrictive + lints are capped at this level + -C, --codegen OPT[=VALUE] + Set a codegen option + -V, --version Print version info and exit + -v, --verbose Use verbose output + +Additional help: + -C help Print codegen options + -W help Print 'lint' options and default settings + -Z help Print unstable compiler options + --help -v Print the full set of options rustc accepts + diff --git a/tests/run-make/rustc-help/rmake.rs b/tests/run-make/rustc-help/rmake.rs new file mode 100644 index 00000000000..85e90e6352d --- /dev/null +++ b/tests/run-make/rustc-help/rmake.rs @@ -0,0 +1,21 @@ +// Tests `rustc --help` and similar invocations against snapshots and each other. + +use run_make_support::{bare_rustc, diff, similar}; + +fn main() { + // `rustc --help` + let help = bare_rustc().arg("--help").run().stdout_utf8(); + diff().expected_file("help.stdout").actual_text("(rustc --help)", &help).run(); + + // `rustc` should be the same as `rustc --help` + let bare = bare_rustc().run().stdout_utf8(); + diff().expected_text("(rustc --help)", &help).actual_text("(rustc)", &bare).run(); + + // `rustc --help -v` should give a similar but longer help message + let help_v = bare_rustc().arg("--help").arg("-v").run().stdout_utf8(); + diff().expected_file("help-v.stdout").actual_text("(rustc --help -v)", &help_v).run(); + + // Check the diff between `rustc --help` and `rustc --help -v`. + let help_v_diff = similar::TextDiff::from_lines(&help, &help_v).unified_diff().to_string(); + diff().expected_file("help-v.diff").actual_text("actual", &help_v_diff).run(); +} diff --git a/tests/rustdoc/hidden-implementors-90781.rs b/tests/rustdoc/hidden-implementors-90781.rs new file mode 100644 index 00000000000..960a85b91f0 --- /dev/null +++ b/tests/rustdoc/hidden-implementors-90781.rs @@ -0,0 +1,78 @@ +//@ compile-flags: -Z unstable-options --document-hidden-items --document-private-items + +// regression test for https://github.com/rust-lang/rust/issues/90781 +#![crate_name = "foo"] + +//@ has foo/trait.TPubVis.html +//@ has - '//*[@id="implementors-list"]' 'HidPriv' +//@ has - '//*[@id="implementors-list"]' 'HidPub' +//@ has - '//*[@id="implementors-list"]' 'VisPriv' +//@ has - '//*[@id="implementors-list"]' 'VisPub' +pub trait TPubVis {} + +//@ has foo/trait.TPubHidden.html +//@ has - '//*[@id="implementors-list"]' 'HidPriv' +//@ has - '//*[@id="implementors-list"]' 'HidPub' +//@ has - '//*[@id="implementors-list"]' 'VisPriv' +//@ has - '//*[@id="implementors-list"]' 'VisPub' +#[doc(hidden)] +pub trait TPubHidden {} + +//@ has foo/trait.TPrivVis.html +//@ has - '//*[@id="implementors-list"]' 'HidPriv' +//@ has - '//*[@id="implementors-list"]' 'HidPub' +//@ has - '//*[@id="implementors-list"]' 'VisPriv' +//@ has - '//*[@id="implementors-list"]' 'VisPub' +trait TPrivVis {} + +#[doc(hidden)] +//@ has foo/trait.TPrivHidden.html +//@ has - '//*[@id="impl-TPrivHidden-for-HidPriv"]' 'HidPriv' +//@ has - '//*[@id="impl-TPrivHidden-for-HidPub"]' 'HidPub' +//@ has - '//*[@id="impl-TPrivHidden-for-VisPriv"]' 'VisPriv' +//@ has - '//*[@id="impl-TPrivHidden-for-VisPub"]' 'VisPub' +trait TPrivHidden {} + +//@ has foo/struct.VisPub.html +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivVis' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubVis' +pub struct VisPub; + +//@ has foo/struct.VisPriv.html +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivVis' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubVis' +struct VisPriv; + +//@ has foo/struct.HidPub.html +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivVis' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubVis' +#[doc(hidden)] +pub struct HidPub; + +//@ has foo/struct.HidPriv.html +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivVis' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubVis' +#[doc(hidden)] +struct HidPriv; + +macro_rules! implement { + ($trait:ident - $($struct:ident)+) => { + $( + impl $trait for $struct {} + )+ + } +} + + +implement!(TPubVis - VisPub VisPriv HidPub HidPriv); +implement!(TPubHidden - VisPub VisPriv HidPub HidPriv); +implement!(TPrivVis - VisPub VisPriv HidPub HidPriv); +implement!(TPrivHidden - VisPub VisPriv HidPub HidPriv); diff --git a/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs b/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs new file mode 100644 index 00000000000..fe2b6de7bb3 --- /dev/null +++ b/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs @@ -0,0 +1,14 @@ +//@ edition: 2021 + +// Make sure we reject the case where a raw lifetime is immediately followed by another +// lifetime. This reserves a modest amount of space for changing lexing to, for example, +// delay rejection of overlong char literals like `'r#long'id`. + +macro_rules! w { + ($($tt:tt)*) => {} +} + +w!('r#long'id); +//~^ ERROR character literal may only contain one codepoint + +fn main() {} diff --git a/tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr b/tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr new file mode 100644 index 00000000000..1caeec84b22 --- /dev/null +++ b/tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr @@ -0,0 +1,13 @@ +error: character literal may only contain one codepoint + --> $DIR/immediately-followed-by-lt.rs:11:4 + | +LL | w!('r#long'id); + | ^^^^^^^^ + | +help: if you meant to write a string literal, use double quotes + | +LL | w!("r#long"id); + | ~ ~ + +error: aborting due to 1 previous error + diff --git a/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs new file mode 100644 index 00000000000..882fad925f3 --- /dev/null +++ b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs @@ -0,0 +1,20 @@ +//@ edition: 2021 + +// Reject raw lifetimes with identifier parts that wouldn't be valid raw identifiers. + +macro_rules! w { + ($tt:tt) => {}; +} + +w!('r#_); +//~^ ERROR `_` cannot be a raw lifetime +w!('r#self); +//~^ ERROR `self` cannot be a raw lifetime +w!('r#super); +//~^ ERROR `super` cannot be a raw lifetime +w!('r#Self); +//~^ ERROR `Self` cannot be a raw lifetime +w!('r#crate); +//~^ ERROR `crate` cannot be a raw lifetime + +fn main() {} diff --git a/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr new file mode 100644 index 00000000000..4cbb89b7a55 --- /dev/null +++ b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr @@ -0,0 +1,32 @@ +error: `_` cannot be a raw lifetime + --> $DIR/raw-lt-invalid-raw-id.rs:9:4 + | +LL | w!('r#_); + | ^^^^ + +error: `self` cannot be a raw lifetime + --> $DIR/raw-lt-invalid-raw-id.rs:11:4 + | +LL | w!('r#self); + | ^^^^^^^ + +error: `super` cannot be a raw lifetime + --> $DIR/raw-lt-invalid-raw-id.rs:13:4 + | +LL | w!('r#super); + | ^^^^^^^^ + +error: `Self` cannot be a raw lifetime + --> $DIR/raw-lt-invalid-raw-id.rs:15:4 + | +LL | w!('r#Self); + | ^^^^^^^ + +error: `crate` cannot be a raw lifetime + --> $DIR/raw-lt-invalid-raw-id.rs:17:4 + | +LL | w!('r#crate); + | ^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/mismatched_types/similar_paths_primitive.rs b/tests/ui/mismatched_types/similar_paths_primitive.rs index 8f5b7cce469..98890a15d98 100644 --- a/tests/ui/mismatched_types/similar_paths_primitive.rs +++ b/tests/ui/mismatched_types/similar_paths_primitive.rs @@ -1,10 +1,14 @@ #![allow(non_camel_case_types)] struct bool; +struct str; fn foo(_: bool) {} +fn bar(_: &str) {} fn main() { foo(true); //~^ ERROR mismatched types [E0308] + bar("hello"); + //~^ ERROR mismatched types [E0308] } diff --git a/tests/ui/mismatched_types/similar_paths_primitive.stderr b/tests/ui/mismatched_types/similar_paths_primitive.stderr index c9881891319..0530bf5863e 100644 --- a/tests/ui/mismatched_types/similar_paths_primitive.stderr +++ b/tests/ui/mismatched_types/similar_paths_primitive.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/similar_paths_primitive.rs:8:9 + --> $DIR/similar_paths_primitive.rs:10:9 | LL | foo(true); | --- ^^^^ expected `bool`, found a different `bool` @@ -14,11 +14,32 @@ note: `bool` is defined in the current crate LL | struct bool; | ^^^^^^^^^^^ note: function defined here - --> $DIR/similar_paths_primitive.rs:5:4 + --> $DIR/similar_paths_primitive.rs:6:4 | LL | fn foo(_: bool) {} | ^^^ ------- -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/similar_paths_primitive.rs:12:9 + | +LL | bar("hello"); + | --- ^^^^^^^ expected `str`, found a different `str` + | | + | arguments to this function are incorrect + | + = note: str and `str` have similar names, but are actually distinct types + = note: str is a primitive defined by the language +note: `str` is defined in the current crate + --> $DIR/similar_paths_primitive.rs:4:1 + | +LL | struct str; + | ^^^^^^^^^^ +note: function defined here + --> $DIR/similar_paths_primitive.rs:7:4 + | +LL | fn bar(_: &str) {} + | ^^^ ------- + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`.