From 1990f1560801ca3f9e6a3286e58204aa329ee037 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 30 Oct 2024 01:10:33 +0000 Subject: [PATCH 01/14] Reject raw lifetime followed by \' as well --- compiler/rustc_lexer/src/lib.rs | 12 +++++++++++- .../ui/lifetimes/raw/immediately-followed-by-lt.rs | 14 ++++++++++++++ .../raw/immediately-followed-by-lt.stderr | 13 +++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lifetimes/raw/immediately-followed-by-lt.rs create mode 100644 tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr 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/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 + From 9785c7cf94f5e30742f886764f2d25b6a4da66e8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 30 Oct 2024 14:45:17 +0000 Subject: [PATCH 02/14] Enforce that raw lifetime identifiers must be valid raw identifiers --- compiler/rustc_parse/messages.ftl | 2 ++ compiler/rustc_parse/src/errors.rs | 8 +++++ compiler/rustc_parse/src/lexer/mod.rs | 14 +++++--- .../ui/lifetimes/raw/raw-lt-invalid-raw-id.rs | 20 ++++++++++++ .../raw/raw-lt-invalid-raw-id.stderr | 32 +++++++++++++++++++ 5 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs create mode 100644 tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr 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/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 + From 90fa5b608ddf6b8715dbd780e7f986e741ac9bf3 Mon Sep 17 00:00:00 2001 From: binarycat Date: Thu, 7 Nov 2024 14:23:53 -0600 Subject: [PATCH 03/14] add regression test for #90781 --- tests/rustdoc/hidden-implementors-90781.rs | 78 ++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 tests/rustdoc/hidden-implementors-90781.rs 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); From 8f7f9b93b2cf1f16d4ded534ff14ce9a673177c0 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 8 Nov 2024 00:11:21 +1100 Subject: [PATCH 04/14] Add a run-make test for `rustc --help` and similar --- src/tools/run-make-support/src/lib.rs | 1 + tests/run-make/rustc-help/help-v.diff | 29 ++++++++++ tests/run-make/rustc-help/help-v.stdout | 77 +++++++++++++++++++++++++ tests/run-make/rustc-help/help.stdout | 60 +++++++++++++++++++ tests/run-make/rustc-help/rmake.rs | 21 +++++++ 5 files changed, 188 insertions(+) create mode 100644 tests/run-make/rustc-help/help-v.diff create mode 100644 tests/run-make/rustc-help/help-v.stdout create mode 100644 tests/run-make/rustc-help/help.stdout create mode 100644 tests/run-make/rustc-help/rmake.rs 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(); +} From 584c8200de3c83078d7cbb271a16ef4962be761e Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 8 Nov 2024 12:20:51 +1100 Subject: [PATCH 05/14] Use a method to apply `RustcOptGroup` to `getopts::Options` --- compiler/rustc_driver_impl/src/lib.rs | 6 +++--- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_session/src/config.rs | 6 +++++- src/librustdoc/lib.rs | 4 ++-- 4 files changed, 11 insertions(+), 7 deletions(-) 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_session/src/config.rs b/compiler/rustc_session/src/config.rs index fe05605c1b9..0c4827ef54d 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1373,7 +1373,7 @@ enum OptionStability { } pub struct RustcOptGroup { - pub apply: Box &mut getopts::Options>, + apply: Box &mut getopts::Options>, pub name: &'static str, stability: OptionStability, } @@ -1383,6 +1383,10 @@ pub fn is_stable(&self) -> bool { self.stability == OptionStability::Stable } + pub fn apply(&self, options: &mut getopts::Options) { + (self.apply)(options); + } + pub fn stable(name: &'static str, f: F) -> RustcOptGroup where F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 7c9dcd41e6a..40e649915cf 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -685,7 +685,7 @@ fn opts() -> Vec { 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 +769,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, From 001013c63cccb3ca88b547596cec5b891e09151a Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 7 Nov 2024 22:47:15 +1100 Subject: [PATCH 06/14] Simplify command-line-option declarations in the compiler --- compiler/rustc_session/src/config.rs | 264 +++++++++++++++------------ 1 file changed, 147 insertions(+), 117 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 0c4827ef54d..979db9424f3 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,11 +1367,36 @@ 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 { apply: Box &mut getopts::Options>, pub name: &'static str, @@ -1402,58 +1427,37 @@ pub fn unstable(name: &'static str, f: F) -> RustcOptGroup } } -// 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) + }) + } + }, } } @@ -1468,46 +1472,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", @@ -1516,41 +1534,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", ""), ] } @@ -1558,25 +1571,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: @@ -1585,19 +1609,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 } @@ -2760,7 +2788,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 From b8377e58445fe5488664bcbbedd04a686cfdad03 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 7 Nov 2024 23:27:20 +1100 Subject: [PATCH 07/14] Simplify command-line-argument declarations in librustdoc --- compiler/rustc_session/src/config.rs | 14 - src/librustdoc/lib.rs | 921 ++++++++++++++------------- 2 files changed, 463 insertions(+), 472 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 979db9424f3..fa2403db925 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1411,20 +1411,6 @@ pub fn is_stable(&self) -> bool { pub fn apply(&self, options: &mut getopts::Options) { (self.apply)(options); } - - 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 make_opt( diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 40e649915cf..78dc0b8e2f9 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -215,470 +215,475 @@ 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", ""), ] } From 76b6090df593ee41c76e519649fba7acc930bd43 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 8 Nov 2024 16:23:07 +0300 Subject: [PATCH 08/14] read repository information configs at an earlier stage Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 39 ++++++++++++------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 8115aea033d..e222a11065a 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1663,10 +1663,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 { @@ -1697,7 +1713,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, @@ -1748,7 +1764,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); @@ -1824,24 +1839,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. From cce6f03754f096f8a2bdfb357e3739b855e29366 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 8 Nov 2024 16:23:59 +0300 Subject: [PATCH 09/14] use `download-rustc="if-unchanged"` as default whenever possible "whenever possible" means applying it if `download-rustc` isn't explicitly set and the source is Git-managed. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index e222a11065a..b1fa7da0712 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2756,9 +2756,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}") } @@ -2785,7 +2795,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); } From 2e0afc8b71d9908911f424ff9893b52b3c642ab4 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 8 Nov 2024 16:26:00 +0300 Subject: [PATCH 10/14] respect to global `download-rustc` default in non-dist profiles Signed-off-by: onur-ozkan --- src/bootstrap/defaults/config.dist.toml | 1 + src/bootstrap/defaults/config.library.toml | 3 --- src/bootstrap/defaults/config.tools.toml | 5 ----- 3 files changed, 1 insertion(+), 8 deletions(-) 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. From 6ffab47e553f6fcd5590a3c86c646860bace5823 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 8 Nov 2024 15:16:37 +0100 Subject: [PATCH 11/14] Use lld with non-LLVM backends On arm64, Cranelift used to produce object files that don't work with lld. This has since been fixed. The GCC backend should always produce object files that work with lld unless lld for whatever reason drops GCC support. Most of the other more niche backends don't use cg_ssa's linker code at all. If they do and don't work with lld, they can always disable lld usage using a cli argument. Without this commit using cg_clif is by default in a non-trivial amount of cases a perf regression on Linux due to ld.bfd being a fair bit slower than lld. It is possible to explicitly enable it without this commit, but most users are unlikely to do this. --- compiler/rustc_codegen_ssa/src/back/link.rs | 17 ----------------- 1 file changed, 17 deletions(-) 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; From 2a381086bbaf2ba29bbac33be0805d8a1d20f9fb Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 8 Nov 2024 20:25:54 +0300 Subject: [PATCH 12/14] fix `core::config::tests::override_toml` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/tests.rs | 3 +++ 1 file changed, 3 insertions(+) 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] From d37e6dfee8afcf0482dd12dbe82d2caf26606675 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sat, 9 Nov 2024 00:18:47 -0600 Subject: [PATCH 13/14] Add str to "expected primitive, found type" diagnostic --- compiler/rustc_middle/src/ty/sty.rs | 1 + 1 file changed, 1 insertion(+) 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, } } From 5f6645dc51e0e8dbb57bf815e19e59007f25d762 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sat, 9 Nov 2024 00:23:53 -0600 Subject: [PATCH 14/14] Add test for str for "expected primitive, found type" --- .../similar_paths_primitive.rs | 4 +++ .../similar_paths_primitive.stderr | 27 ++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) 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`.