diff --git a/Cargo.lock b/Cargo.lock index 234d709f3c315..91fce715c8cd1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3789,7 +3789,6 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", - "rustc_fluent_macro", "rustc_hir_analysis", "rustc_hir_pretty", "rustc_hir_typeck", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index c160240a18a77..d97c552b412b5 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -21,7 +21,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir_analysis = { path = "../rustc_hir_analysis" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_hir_typeck = { path = "../rustc_hir_typeck" } diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl deleted file mode 100644 index b62cdc35f5130..0000000000000 --- a/compiler/rustc_driver_impl/messages.ftl +++ /dev/null @@ -1,29 +0,0 @@ -driver_impl_cant_emit_mir = could not emit MIR: {$error} - -driver_impl_ice = the compiler unexpectedly panicked. this is a bug. -driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url} -driver_impl_ice_bug_report_internal_feature = using internal features is not supported and expected to cause internal compiler errors when used incorrectly -driver_impl_ice_bug_report_update_note = please make sure that you have updated to the latest nightly -driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden - -driver_impl_ice_flags = compiler flags: {$flags} -driver_impl_ice_path = please attach the file at `{$path}` to your bug report -driver_impl_ice_path_error = the ICE couldn't be written to `{$path}`: {$error} -driver_impl_ice_path_error_env = the environment variable `RUSTC_ICE` is set to `{$env_var}` -driver_impl_ice_version = rustc {$version} running on {$triple} - -driver_impl_rlink_corrupt_file = corrupt metadata encountered in `{$file}` - -driver_impl_rlink_empty_version_number = the input does not contain version number - -driver_impl_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}` - -driver_impl_rlink_no_a_file = rlink must be a file - -driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}` - -driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}` - -driver_impl_rlink_wrong_file_type = the input does not look like a .rlink file - -driver_impl_unstable_feature_usage = cannot dump feature usage metrics: {$error} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 38ee87601614b..b163ae2068a66 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -108,15 +108,12 @@ use crate::session_diagnostics::{ RLinkWrongFileType, RlinkCorruptFile, RlinkNotAFile, RlinkUnableToRead, UnstableFeatureUsage, }; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn default_translator() -> Translator { Translator::with_fallback_bundle(DEFAULT_LOCALE_RESOURCES.to_vec(), false) } pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ // tidy-alphabetical-start - crate::DEFAULT_LOCALE_RESOURCE, rustc_ast_lowering::DEFAULT_LOCALE_RESOURCE, rustc_ast_passes::DEFAULT_LOCALE_RESOURCE, rustc_attr_parsing::DEFAULT_LOCALE_RESOURCE, @@ -491,10 +488,18 @@ fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, col } text.push('\n'); } + + // If output is a terminal, use a pager to display the content. if io::stdout().is_terminal() { show_md_content_with_pager(&text, color); } else { - safe_print!("{text}"); + // Otherwise, if the user has requested colored output + // print the content in color, else print the md content. + if color == ColorConfig::Always { + show_colored_md_content(&text); + } else { + safe_print!("{text}"); + } } } else { early_dcx.early_fatal(format!("{code} is not a valid error code")); @@ -564,6 +569,33 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) { safe_print!("{content}"); } +/// Prints the markdown content with colored output. +/// +/// This function is used when the output is not a terminal, +/// but the user has requested colored output with `--color=always`. +fn show_colored_md_content(content: &str) { + // Try to prettify the raw markdown text. + let mut pretty_data = { + let mdstream = markdown::MdStream::parse_str(content); + let bufwtr = markdown::create_stdout_bufwtr(); + let mut mdbuf = Vec::new(); + if mdstream.write_anstream_buf(&mut mdbuf, Some(&highlighter::highlight)).is_ok() { + Some((bufwtr, mdbuf)) + } else { + None + } + }; + + if let Some((bufwtr, mdbuf)) = &mut pretty_data + && bufwtr.write_all(&mdbuf).is_ok() + { + return; + } + + // Everything failed. Print the raw markdown text. + safe_print!("{content}"); +} + fn process_rlink(sess: &Session, compiler: &interface::Compiler) { assert!(sess.opts.unstable_opts.link_only); let dcx = sess.dcx(); diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs index 774221fd396a6..565c176645dee 100644 --- a/compiler/rustc_driver_impl/src/session_diagnostics.rs +++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs @@ -3,82 +3,88 @@ use std::error::Error; use rustc_macros::{Diagnostic, Subdiagnostic}; #[derive(Diagnostic)] -#[diag(driver_impl_cant_emit_mir)] +#[diag("could not emit MIR: {$error}")] pub struct CantEmitMIR { pub error: std::io::Error, } #[derive(Diagnostic)] -#[diag(driver_impl_rlink_unable_to_read)] +#[diag("failed to read rlink file: `{$err}`")] pub(crate) struct RlinkUnableToRead { pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(driver_impl_rlink_wrong_file_type)] +#[diag("the input does not look like a .rlink file")] pub(crate) struct RLinkWrongFileType; #[derive(Diagnostic)] -#[diag(driver_impl_rlink_empty_version_number)] +#[diag("the input does not contain version number")] pub(crate) struct RLinkEmptyVersionNumber; #[derive(Diagnostic)] -#[diag(driver_impl_rlink_encoding_version_mismatch)] +#[diag( + ".rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`" +)] pub(crate) struct RLinkEncodingVersionMismatch { pub version_array: String, pub rlink_version: u32, } #[derive(Diagnostic)] -#[diag(driver_impl_rlink_rustc_version_mismatch)] +#[diag( + ".rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`" +)] pub(crate) struct RLinkRustcVersionMismatch<'a> { pub rustc_version: String, pub current_version: &'a str, } #[derive(Diagnostic)] -#[diag(driver_impl_rlink_no_a_file)] +#[diag("rlink must be a file")] pub(crate) struct RlinkNotAFile; #[derive(Diagnostic)] -#[diag(driver_impl_rlink_corrupt_file)] +#[diag("corrupt metadata encountered in `{$file}`")] pub(crate) struct RlinkCorruptFile<'a> { pub file: &'a std::path::Path, } #[derive(Diagnostic)] -#[diag(driver_impl_ice)] +#[diag("the compiler unexpectedly panicked. this is a bug.")] pub(crate) struct Ice; #[derive(Diagnostic)] -#[diag(driver_impl_ice_bug_report)] +#[diag("we would appreciate a bug report: {$bug_report_url}")] pub(crate) struct IceBugReport<'a> { pub bug_report_url: &'a str, } #[derive(Diagnostic)] -#[diag(driver_impl_ice_bug_report_update_note)] +#[diag("please make sure that you have updated to the latest nightly")] pub(crate) struct UpdateNightlyNote; #[derive(Diagnostic)] -#[diag(driver_impl_ice_bug_report_internal_feature)] +#[diag( + "using internal features is not supported and expected to cause internal compiler errors when used incorrectly" +)] pub(crate) struct IceBugReportInternalFeature; #[derive(Diagnostic)] -#[diag(driver_impl_ice_version)] +#[diag("rustc {$version} running on {$triple}")] pub(crate) struct IceVersion<'a> { pub version: &'a str, pub triple: &'a str, } #[derive(Diagnostic)] -#[diag(driver_impl_ice_path)] +#[diag("please attach the file at `{$path}` to your bug report")] pub(crate) struct IcePath { pub path: std::path::PathBuf, } #[derive(Diagnostic)] -#[diag(driver_impl_ice_path_error)] +#[diag("the ICE couldn't be written to `{$path}`: {$error}")] pub(crate) struct IcePathError { pub path: std::path::PathBuf, pub error: String, @@ -87,23 +93,23 @@ pub(crate) struct IcePathError { } #[derive(Subdiagnostic)] -#[note(driver_impl_ice_path_error_env)] +#[note("the environment variable `RUSTC_ICE` is set to `{$env_var}`")] pub(crate) struct IcePathErrorEnv { pub env_var: std::path::PathBuf, } #[derive(Diagnostic)] -#[diag(driver_impl_ice_flags)] +#[diag("compiler flags: {$flags}")] pub(crate) struct IceFlags { pub flags: String, } #[derive(Diagnostic)] -#[diag(driver_impl_ice_exclude_cargo_defaults)] +#[diag("some of the compiler flags provided by cargo are hidden")] pub(crate) struct IceExcludeCargoDefaults; #[derive(Diagnostic)] -#[diag(driver_impl_unstable_feature_usage)] +#[diag("cannot dump feature usage metrics: {$error}")] pub(crate) struct UnstableFeatureUsage { pub error: Box, } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index ef90b81fb2a73..1804490a5f12c 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1438,7 +1438,7 @@ impl<'test> TestCx<'test> { } else if aux_type.is_some() { panic!("aux_type {aux_type:?} not expected"); } else if aux_props.no_prefer_dynamic { - (AuxType::Dylib, None) + (AuxType::Lib, None) } else if self.config.target.contains("emscripten") || (self.config.target.contains("musl") && !aux_props.force_host diff --git a/tests/ui/compiletest-self-test/auxiliary/no_prefer_dynamic_lib.rs b/tests/ui/compiletest-self-test/auxiliary/no_prefer_dynamic_lib.rs new file mode 100644 index 0000000000000..6688dadbab24f --- /dev/null +++ b/tests/ui/compiletest-self-test/auxiliary/no_prefer_dynamic_lib.rs @@ -0,0 +1,10 @@ +//@ no-prefer-dynamic + +//! Since this is `no-prefer-dynamic` we expect compiletest to _not_ look for +//! this create as `libno_prefer_dynamic_lib.so`. + +#![crate_type = "rlib"] + +pub fn return_42() -> i32 { + 42 +} diff --git a/tests/ui/compiletest-self-test/no-prefer-dynamic-means-no-so.rs b/tests/ui/compiletest-self-test/no-prefer-dynamic-means-no-so.rs new file mode 100644 index 0000000000000..b7e8fae506c39 --- /dev/null +++ b/tests/ui/compiletest-self-test/no-prefer-dynamic-means-no-so.rs @@ -0,0 +1,10 @@ +//! Since we and our `aux-crate` is `no-prefer-dynamic`, we expect compiletest +//! to _not_ look for `libno_prefer_dynamic_lib.so`. + +//@ check-pass +//@ no-prefer-dynamic +//@ aux-crate: no_prefer_dynamic_lib=no_prefer_dynamic_lib.rs + +fn main() { + no_prefer_dynamic_lib::return_42(); +} diff --git a/tests/ui/explain/ensure-color-always-works.rs b/tests/ui/explain/ensure-color-always-works.rs new file mode 100644 index 0000000000000..81ee716e78b4d --- /dev/null +++ b/tests/ui/explain/ensure-color-always-works.rs @@ -0,0 +1,2 @@ +//@ compile-flags: --explain E0591 --color always --error-format=human +//@ check-pass diff --git a/tests/ui/explain/ensure-color-always-works.stdout b/tests/ui/explain/ensure-color-always-works.stdout new file mode 100644 index 0000000000000..7e5358bcfb7ec --- /dev/null +++ b/tests/ui/explain/ensure-color-always-works.stdout @@ -0,0 +1,50 @@ +Per ]8;;https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md\RFC 401]8;;\, if you have a function declaration foo: + +struct S; + +// For the purposes of this explanation, all of these +// different kinds of `fn` declarations are equivalent: + +fn foo(x: S) { /* ... */ } +extern "C" { + fn foo(x: S); +} +impl S { + fn foo(self) { /* ... */ } +} + +the type of foo is not fn(S), as one might expect. Rather, it is a unique, zero-sized marker type written here as typeof(foo). However, typeof(foo) + can be coerced to a function pointer fn(S), so you rarely notice this: + +let x: fn(S) = foo; // OK, coerces + +The reason that this matter is that the type fn(S) is not specific to any particular function: it's a function pointer. So calling x() +results in a virtual call, whereas foo() is statically dispatched, because the type of foo tells us precisely what function is being called. + +As noted above, coercions mean that most code doesn't have to be concerned with this distinction. However, you can tell the difference when +using transmute to convert a fn item into a fn pointer. + +This is sometimes done as part of an FFI: + +extern "C" fn foo(userdata: Box<i32>) { + /* ... */ +} + +unsafe { + let f: extern "C" fn(*mut i32) = transmute(foo); + callback(f); +} + +Here, transmute is being used to convert the types of the fn arguments. This pattern is incorrect because the type of foo is a function item +(typeof(foo)), which is zero-sized, and the target type (fn()) is a function pointer, which is not zero-sized. This pattern should be +rewritten. There are a few possible ways to do this: + +* change the original fn declaration to match the expected signature, and do the cast in the fn body (the preferred option) +* cast the fn item of a fn pointer before calling transmute, as shown here: + +let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); +let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too + +The same applies to transmutes to *mut fn(), which were observed in practice. Note though that use of this type is generally incorrect. The +intention is typically to describe a function pointer, but just fn() alone suffices for that. *mut fn() is a pointer to a fn pointer. (Since these +values are typically just passed to C code, however, this rarely makes a difference in practice.)