Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3789,7 +3789,6 @@ dependencies = [
"rustc_errors",
"rustc_expand",
"rustc_feature",
"rustc_fluent_macro",
"rustc_hir_analysis",
"rustc_hir_pretty",
"rustc_hir_typeck",
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_driver_impl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
29 changes: 0 additions & 29 deletions compiler/rustc_driver_impl/messages.ftl

This file was deleted.

40 changes: 36 additions & 4 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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"));
Expand Down Expand Up @@ -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();
Expand Down
44 changes: 25 additions & 19 deletions compiler/rustc_driver_impl/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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<dyn Error>,
}
2 changes: 1 addition & 1 deletion src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/compiletest-self-test/auxiliary/no_prefer_dynamic_lib.rs
Original file line number Diff line number Diff line change
@@ -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
}
10 changes: 10 additions & 0 deletions tests/ui/compiletest-self-test/no-prefer-dynamic-means-no-so.rs
Original file line number Diff line number Diff line change
@@ -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();
}
2 changes: 2 additions & 0 deletions tests/ui/explain/ensure-color-always-works.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@ compile-flags: --explain E0591 --color always --error-format=human
//@ check-pass
50 changes: 50 additions & 0 deletions tests/ui/explain/ensure-color-always-works.stdout
Original file line number Diff line number Diff line change
@@ -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.)
Loading