mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 23:34:48 +00:00
Auto merge of #122625 - matthiaskrgr:rollup-ue4dmnx, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #119411 (Add as_(mut_)ptr and as_(mut_)slice to raw array pointers) - #122248 (Respect stage0 sysroot when compiling rmake.rs with COMPILETEST_FORCE_STAGE0) - #122295 (mir-opt: always run tests for the current target) - #122574 (Register LLVM handlers for bad-alloc / OOM) - #122608 (Move check-cfg diagnostic logic into a separate file) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
ecdea9e943
@ -1519,7 +1519,7 @@ extern "C" {
|
||||
|
||||
#[link(name = "llvm-wrapper", kind = "static")]
|
||||
extern "C" {
|
||||
pub fn LLVMRustInstallFatalErrorHandler();
|
||||
pub fn LLVMRustInstallErrorHandlers();
|
||||
pub fn LLVMRustDisableSystemDialogsOnCrash();
|
||||
|
||||
// Create and destroy contexts.
|
||||
|
@ -49,7 +49,7 @@ unsafe fn configure_llvm(sess: &Session) {
|
||||
let mut llvm_c_strs = Vec::with_capacity(n_args + 1);
|
||||
let mut llvm_args = Vec::with_capacity(n_args + 1);
|
||||
|
||||
llvm::LLVMRustInstallFatalErrorHandler();
|
||||
llvm::LLVMRustInstallErrorHandlers();
|
||||
// On Windows, an LLVM assertion will open an Abort/Retry/Ignore dialog
|
||||
// box for the purpose of launching a debugger. However, on CI this will
|
||||
// cause it to hang until it times out, which can take several hours.
|
||||
|
@ -5,49 +5,11 @@ use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
|
||||
use rustc_errors::{add_elided_lifetime_in_path_suggestion, Diag};
|
||||
use rustc_errors::{Applicability, SuggestionStyle};
|
||||
use rustc_middle::middle::stability;
|
||||
use rustc_session::config::ExpectedValues;
|
||||
use rustc_session::lint::BuiltinLintDiag;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::BytePos;
|
||||
|
||||
const MAX_CHECK_CFG_NAMES_OR_VALUES: usize = 35;
|
||||
|
||||
fn check_cfg_expected_note(
|
||||
sess: &Session,
|
||||
possibilities: &[Symbol],
|
||||
type_: &str,
|
||||
name: Option<Symbol>,
|
||||
suffix: &str,
|
||||
) -> String {
|
||||
use std::fmt::Write;
|
||||
|
||||
let n_possibilities = if sess.opts.unstable_opts.check_cfg_all_expected {
|
||||
possibilities.len()
|
||||
} else {
|
||||
std::cmp::min(possibilities.len(), MAX_CHECK_CFG_NAMES_OR_VALUES)
|
||||
};
|
||||
|
||||
let mut possibilities = possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
|
||||
possibilities.sort();
|
||||
|
||||
let and_more = possibilities.len().saturating_sub(n_possibilities);
|
||||
let possibilities = possibilities[..n_possibilities].join("`, `");
|
||||
|
||||
let mut note = String::with_capacity(50 + possibilities.len());
|
||||
|
||||
write!(&mut note, "expected {type_}").unwrap();
|
||||
if let Some(name) = name {
|
||||
write!(&mut note, " for `{name}`").unwrap();
|
||||
}
|
||||
write!(&mut note, " are: {suffix}`{possibilities}`").unwrap();
|
||||
if and_more > 0 {
|
||||
write!(&mut note, " and {and_more} more").unwrap();
|
||||
}
|
||||
|
||||
note
|
||||
}
|
||||
mod check_cfg;
|
||||
|
||||
pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) {
|
||||
match diagnostic {
|
||||
@ -219,242 +181,11 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
|
||||
diag.help(help);
|
||||
diag.note("see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information");
|
||||
}
|
||||
BuiltinLintDiag::UnexpectedCfgName((name, name_span), value) => {
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
let possibilities: Vec<Symbol> =
|
||||
sess.psess.check_config.expecteds.keys().copied().collect();
|
||||
|
||||
let mut names_possibilities: Vec<_> = if value.is_none() {
|
||||
// We later sort and display all the possibilities, so the order here does not matter.
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
sess.psess
|
||||
.check_config
|
||||
.expecteds
|
||||
.iter()
|
||||
.filter_map(|(k, v)| match v {
|
||||
ExpectedValues::Some(v) if v.contains(&Some(name)) => Some(k),
|
||||
_ => None,
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let is_from_cargo = rustc_session::utils::was_invoked_from_cargo();
|
||||
let mut is_feature_cfg = name == sym::feature;
|
||||
|
||||
if is_feature_cfg && is_from_cargo {
|
||||
diag.help("consider defining some features in `Cargo.toml`");
|
||||
// Suggest the most probable if we found one
|
||||
} else if let Some(best_match) = find_best_match_for_name(&possibilities, name, None) {
|
||||
if let Some(ExpectedValues::Some(best_match_values)) =
|
||||
sess.psess.check_config.expecteds.get(&best_match)
|
||||
{
|
||||
// We will soon sort, so the initial order does not matter.
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
let mut possibilities =
|
||||
best_match_values.iter().flatten().map(Symbol::as_str).collect::<Vec<_>>();
|
||||
possibilities.sort();
|
||||
|
||||
let mut should_print_possibilities = true;
|
||||
if let Some((value, value_span)) = value {
|
||||
if best_match_values.contains(&Some(value)) {
|
||||
diag.span_suggestion(
|
||||
name_span,
|
||||
"there is a config with a similar name and value",
|
||||
best_match,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
should_print_possibilities = false;
|
||||
} else if best_match_values.contains(&None) {
|
||||
diag.span_suggestion(
|
||||
name_span.to(value_span),
|
||||
"there is a config with a similar name and no value",
|
||||
best_match,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
should_print_possibilities = false;
|
||||
} else if let Some(first_value) = possibilities.first() {
|
||||
diag.span_suggestion(
|
||||
name_span.to(value_span),
|
||||
"there is a config with a similar name and different values",
|
||||
format!("{best_match} = \"{first_value}\""),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
diag.span_suggestion(
|
||||
name_span.to(value_span),
|
||||
"there is a config with a similar name and different values",
|
||||
best_match,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
};
|
||||
} else {
|
||||
diag.span_suggestion(
|
||||
name_span,
|
||||
"there is a config with a similar name",
|
||||
best_match,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
if !possibilities.is_empty() && should_print_possibilities {
|
||||
let possibilities = possibilities.join("`, `");
|
||||
diag.help(format!(
|
||||
"expected values for `{best_match}` are: `{possibilities}`"
|
||||
));
|
||||
}
|
||||
} else {
|
||||
diag.span_suggestion(
|
||||
name_span,
|
||||
"there is a config with a similar name",
|
||||
best_match,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
is_feature_cfg |= best_match == sym::feature;
|
||||
} else {
|
||||
if !names_possibilities.is_empty() && names_possibilities.len() <= 3 {
|
||||
names_possibilities.sort();
|
||||
for cfg_name in names_possibilities.iter() {
|
||||
diag.span_suggestion(
|
||||
name_span,
|
||||
"found config with similar value",
|
||||
format!("{cfg_name} = \"{name}\""),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
if !possibilities.is_empty() {
|
||||
diag.help_once(check_cfg_expected_note(
|
||||
sess,
|
||||
&possibilities,
|
||||
"names",
|
||||
None,
|
||||
"",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let inst = if let Some((value, _value_span)) = value {
|
||||
let pre = if is_from_cargo { "\\" } else { "" };
|
||||
format!("cfg({name}, values({pre}\"{value}{pre}\"))")
|
||||
} else {
|
||||
format!("cfg({name})")
|
||||
};
|
||||
|
||||
if is_from_cargo {
|
||||
if !is_feature_cfg {
|
||||
diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`"));
|
||||
}
|
||||
diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration");
|
||||
} else {
|
||||
diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
|
||||
diag.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
|
||||
}
|
||||
BuiltinLintDiag::UnexpectedCfgName(name, value) => {
|
||||
check_cfg::unexpected_cfg_name(sess, diag, name, value)
|
||||
}
|
||||
BuiltinLintDiag::UnexpectedCfgValue((name, name_span), value) => {
|
||||
let Some(ExpectedValues::Some(values)) = &sess.psess.check_config.expecteds.get(&name)
|
||||
else {
|
||||
bug!(
|
||||
"it shouldn't be possible to have a diagnostic on a value whose name is not in values"
|
||||
);
|
||||
};
|
||||
let mut have_none_possibility = false;
|
||||
// We later sort possibilities if it is not empty, so the
|
||||
// order here does not matter.
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
let possibilities: Vec<Symbol> = values
|
||||
.iter()
|
||||
.inspect(|a| have_none_possibility |= a.is_none())
|
||||
.copied()
|
||||
.flatten()
|
||||
.collect();
|
||||
let is_from_cargo = rustc_session::utils::was_invoked_from_cargo();
|
||||
|
||||
// Show the full list if all possible values for a given name, but don't do it
|
||||
// for names as the possibilities could be very long
|
||||
if !possibilities.is_empty() {
|
||||
diag.note(check_cfg_expected_note(
|
||||
sess,
|
||||
&possibilities,
|
||||
"values",
|
||||
Some(name),
|
||||
if have_none_possibility { "(none), " } else { "" },
|
||||
));
|
||||
|
||||
if let Some((value, value_span)) = value {
|
||||
// Suggest the most probable if we found one
|
||||
if let Some(best_match) = find_best_match_for_name(&possibilities, value, None)
|
||||
{
|
||||
diag.span_suggestion(
|
||||
value_span,
|
||||
"there is a expected value with a similar name",
|
||||
format!("\"{best_match}\""),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
} else if let &[first_possibility] = &possibilities[..] {
|
||||
diag.span_suggestion(
|
||||
name_span.shrink_to_hi(),
|
||||
"specify a config value",
|
||||
format!(" = \"{first_possibility}\""),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
} else if have_none_possibility {
|
||||
diag.note(format!("no expected value for `{name}`"));
|
||||
if let Some((_value, value_span)) = value {
|
||||
diag.span_suggestion(
|
||||
name_span.shrink_to_hi().to(value_span),
|
||||
"remove the value",
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
diag.note(format!("no expected values for `{name}`"));
|
||||
|
||||
let sp = if let Some((_value, value_span)) = value {
|
||||
name_span.to(value_span)
|
||||
} else {
|
||||
name_span
|
||||
};
|
||||
diag.span_suggestion(sp, "remove the condition", "", Applicability::MaybeIncorrect);
|
||||
}
|
||||
|
||||
// We don't want to suggest adding values to well known names
|
||||
// since those are defined by rustc it-self. Users can still
|
||||
// do it if they want, but should not encourage them.
|
||||
let is_cfg_a_well_know_name = sess.psess.check_config.well_known_names.contains(&name);
|
||||
|
||||
let inst = if let Some((value, _value_span)) = value {
|
||||
let pre = if is_from_cargo { "\\" } else { "" };
|
||||
format!("cfg({name}, values({pre}\"{value}{pre}\"))")
|
||||
} else {
|
||||
format!("cfg({name})")
|
||||
};
|
||||
|
||||
if is_from_cargo {
|
||||
if name == sym::feature {
|
||||
if let Some((value, _value_span)) = value {
|
||||
diag.help(format!(
|
||||
"consider adding `{value}` as a feature in `Cargo.toml`"
|
||||
));
|
||||
} else {
|
||||
diag.help("consider defining some features in `Cargo.toml`");
|
||||
}
|
||||
} else if !is_cfg_a_well_know_name {
|
||||
diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`"));
|
||||
}
|
||||
diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration");
|
||||
} else {
|
||||
if !is_cfg_a_well_know_name {
|
||||
diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
|
||||
}
|
||||
diag.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
|
||||
}
|
||||
BuiltinLintDiag::UnexpectedCfgValue(name, value) => {
|
||||
check_cfg::unexpected_cfg_value(sess, diag, name, value)
|
||||
}
|
||||
BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg) => {
|
||||
let left_sp = diag.span.primary_span().unwrap();
|
||||
|
277
compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
Normal file
277
compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
Normal file
@ -0,0 +1,277 @@
|
||||
use rustc_errors::{Applicability, Diag};
|
||||
use rustc_session::{config::ExpectedValues, Session};
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_span::{sym, Span, Symbol};
|
||||
|
||||
const MAX_CHECK_CFG_NAMES_OR_VALUES: usize = 35;
|
||||
|
||||
fn check_cfg_expected_note(
|
||||
sess: &Session,
|
||||
possibilities: &[Symbol],
|
||||
type_: &str,
|
||||
name: Option<Symbol>,
|
||||
suffix: &str,
|
||||
) -> String {
|
||||
use std::fmt::Write;
|
||||
|
||||
let n_possibilities = if sess.opts.unstable_opts.check_cfg_all_expected {
|
||||
possibilities.len()
|
||||
} else {
|
||||
std::cmp::min(possibilities.len(), MAX_CHECK_CFG_NAMES_OR_VALUES)
|
||||
};
|
||||
|
||||
let mut possibilities = possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
|
||||
possibilities.sort();
|
||||
|
||||
let and_more = possibilities.len().saturating_sub(n_possibilities);
|
||||
let possibilities = possibilities[..n_possibilities].join("`, `");
|
||||
|
||||
let mut note = String::with_capacity(50 + possibilities.len());
|
||||
|
||||
write!(&mut note, "expected {type_}").unwrap();
|
||||
if let Some(name) = name {
|
||||
write!(&mut note, " for `{name}`").unwrap();
|
||||
}
|
||||
write!(&mut note, " are: {suffix}`{possibilities}`").unwrap();
|
||||
if and_more > 0 {
|
||||
write!(&mut note, " and {and_more} more").unwrap();
|
||||
}
|
||||
|
||||
note
|
||||
}
|
||||
|
||||
pub(super) fn unexpected_cfg_name(
|
||||
sess: &Session,
|
||||
diag: &mut Diag<'_, ()>,
|
||||
(name, name_span): (Symbol, Span),
|
||||
value: Option<(Symbol, Span)>,
|
||||
) {
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
let possibilities: Vec<Symbol> = sess.psess.check_config.expecteds.keys().copied().collect();
|
||||
|
||||
let mut names_possibilities: Vec<_> = if value.is_none() {
|
||||
// We later sort and display all the possibilities, so the order here does not matter.
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
sess.psess
|
||||
.check_config
|
||||
.expecteds
|
||||
.iter()
|
||||
.filter_map(|(k, v)| match v {
|
||||
ExpectedValues::Some(v) if v.contains(&Some(name)) => Some(k),
|
||||
_ => None,
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let is_from_cargo = rustc_session::utils::was_invoked_from_cargo();
|
||||
let mut is_feature_cfg = name == sym::feature;
|
||||
|
||||
if is_feature_cfg && is_from_cargo {
|
||||
diag.help("consider defining some features in `Cargo.toml`");
|
||||
// Suggest the most probable if we found one
|
||||
} else if let Some(best_match) = find_best_match_for_name(&possibilities, name, None) {
|
||||
if let Some(ExpectedValues::Some(best_match_values)) =
|
||||
sess.psess.check_config.expecteds.get(&best_match)
|
||||
{
|
||||
// We will soon sort, so the initial order does not matter.
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
let mut possibilities =
|
||||
best_match_values.iter().flatten().map(Symbol::as_str).collect::<Vec<_>>();
|
||||
possibilities.sort();
|
||||
|
||||
let mut should_print_possibilities = true;
|
||||
if let Some((value, value_span)) = value {
|
||||
if best_match_values.contains(&Some(value)) {
|
||||
diag.span_suggestion(
|
||||
name_span,
|
||||
"there is a config with a similar name and value",
|
||||
best_match,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
should_print_possibilities = false;
|
||||
} else if best_match_values.contains(&None) {
|
||||
diag.span_suggestion(
|
||||
name_span.to(value_span),
|
||||
"there is a config with a similar name and no value",
|
||||
best_match,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
should_print_possibilities = false;
|
||||
} else if let Some(first_value) = possibilities.first() {
|
||||
diag.span_suggestion(
|
||||
name_span.to(value_span),
|
||||
"there is a config with a similar name and different values",
|
||||
format!("{best_match} = \"{first_value}\""),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
diag.span_suggestion(
|
||||
name_span.to(value_span),
|
||||
"there is a config with a similar name and different values",
|
||||
best_match,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
};
|
||||
} else {
|
||||
diag.span_suggestion(
|
||||
name_span,
|
||||
"there is a config with a similar name",
|
||||
best_match,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
if !possibilities.is_empty() && should_print_possibilities {
|
||||
let possibilities = possibilities.join("`, `");
|
||||
diag.help(format!("expected values for `{best_match}` are: `{possibilities}`"));
|
||||
}
|
||||
} else {
|
||||
diag.span_suggestion(
|
||||
name_span,
|
||||
"there is a config with a similar name",
|
||||
best_match,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
is_feature_cfg |= best_match == sym::feature;
|
||||
} else {
|
||||
if !names_possibilities.is_empty() && names_possibilities.len() <= 3 {
|
||||
names_possibilities.sort();
|
||||
for cfg_name in names_possibilities.iter() {
|
||||
diag.span_suggestion(
|
||||
name_span,
|
||||
"found config with similar value",
|
||||
format!("{cfg_name} = \"{name}\""),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
if !possibilities.is_empty() {
|
||||
diag.help_once(check_cfg_expected_note(sess, &possibilities, "names", None, ""));
|
||||
}
|
||||
}
|
||||
|
||||
let inst = if let Some((value, _value_span)) = value {
|
||||
let pre = if is_from_cargo { "\\" } else { "" };
|
||||
format!("cfg({name}, values({pre}\"{value}{pre}\"))")
|
||||
} else {
|
||||
format!("cfg({name})")
|
||||
};
|
||||
|
||||
if is_from_cargo {
|
||||
if !is_feature_cfg {
|
||||
diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`"));
|
||||
}
|
||||
diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration");
|
||||
} else {
|
||||
diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
|
||||
diag.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn unexpected_cfg_value(
|
||||
sess: &Session,
|
||||
diag: &mut Diag<'_, ()>,
|
||||
(name, name_span): (Symbol, Span),
|
||||
value: Option<(Symbol, Span)>,
|
||||
) {
|
||||
let Some(ExpectedValues::Some(values)) = &sess.psess.check_config.expecteds.get(&name) else {
|
||||
bug!(
|
||||
"it shouldn't be possible to have a diagnostic on a value whose name is not in values"
|
||||
);
|
||||
};
|
||||
let mut have_none_possibility = false;
|
||||
// We later sort possibilities if it is not empty, so the
|
||||
// order here does not matter.
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
let possibilities: Vec<Symbol> = values
|
||||
.iter()
|
||||
.inspect(|a| have_none_possibility |= a.is_none())
|
||||
.copied()
|
||||
.flatten()
|
||||
.collect();
|
||||
let is_from_cargo = rustc_session::utils::was_invoked_from_cargo();
|
||||
|
||||
// Show the full list if all possible values for a given name, but don't do it
|
||||
// for names as the possibilities could be very long
|
||||
if !possibilities.is_empty() {
|
||||
diag.note(check_cfg_expected_note(
|
||||
sess,
|
||||
&possibilities,
|
||||
"values",
|
||||
Some(name),
|
||||
if have_none_possibility { "(none), " } else { "" },
|
||||
));
|
||||
|
||||
if let Some((value, value_span)) = value {
|
||||
// Suggest the most probable if we found one
|
||||
if let Some(best_match) = find_best_match_for_name(&possibilities, value, None) {
|
||||
diag.span_suggestion(
|
||||
value_span,
|
||||
"there is a expected value with a similar name",
|
||||
format!("\"{best_match}\""),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
} else if let &[first_possibility] = &possibilities[..] {
|
||||
diag.span_suggestion(
|
||||
name_span.shrink_to_hi(),
|
||||
"specify a config value",
|
||||
format!(" = \"{first_possibility}\""),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
} else if have_none_possibility {
|
||||
diag.note(format!("no expected value for `{name}`"));
|
||||
if let Some((_value, value_span)) = value {
|
||||
diag.span_suggestion(
|
||||
name_span.shrink_to_hi().to(value_span),
|
||||
"remove the value",
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
diag.note(format!("no expected values for `{name}`"));
|
||||
|
||||
let sp = if let Some((_value, value_span)) = value {
|
||||
name_span.to(value_span)
|
||||
} else {
|
||||
name_span
|
||||
};
|
||||
diag.span_suggestion(sp, "remove the condition", "", Applicability::MaybeIncorrect);
|
||||
}
|
||||
|
||||
// We don't want to suggest adding values to well known names
|
||||
// since those are defined by rustc it-self. Users can still
|
||||
// do it if they want, but should not encourage them.
|
||||
let is_cfg_a_well_know_name = sess.psess.check_config.well_known_names.contains(&name);
|
||||
|
||||
let inst = if let Some((value, _value_span)) = value {
|
||||
let pre = if is_from_cargo { "\\" } else { "" };
|
||||
format!("cfg({name}, values({pre}\"{value}{pre}\"))")
|
||||
} else {
|
||||
format!("cfg({name})")
|
||||
};
|
||||
|
||||
if is_from_cargo {
|
||||
if name == sym::feature {
|
||||
if let Some((value, _value_span)) = value {
|
||||
diag.help(format!("consider adding `{value}` as a feature in `Cargo.toml`"));
|
||||
} else {
|
||||
diag.help("consider defining some features in `Cargo.toml`");
|
||||
}
|
||||
} else if !is_cfg_a_well_know_name {
|
||||
diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`"));
|
||||
}
|
||||
diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration");
|
||||
} else {
|
||||
if !is_cfg_a_well_know_name {
|
||||
diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
|
||||
}
|
||||
diag.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
|
||||
}
|
||||
}
|
@ -25,6 +25,13 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// for raw `write` in the bad-alloc handler
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===
|
||||
//
|
||||
// This file defines alternate interfaces to core functions that are more
|
||||
@ -88,8 +95,24 @@ static void FatalErrorHandler(void *UserData,
|
||||
exit(101);
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustInstallFatalErrorHandler() {
|
||||
// Custom error handler for bad-alloc LLVM errors.
|
||||
//
|
||||
// It aborts the process without any further allocations, similar to LLVM's
|
||||
// default except that may be configured to `throw std::bad_alloc()` instead.
|
||||
static void BadAllocErrorHandler(void *UserData,
|
||||
const char* Reason,
|
||||
bool GenCrashDiag) {
|
||||
const char *OOM = "rustc-LLVM ERROR: out of memory\n";
|
||||
(void)!::write(2, OOM, strlen(OOM));
|
||||
(void)!::write(2, Reason, strlen(Reason));
|
||||
(void)!::write(2, "\n", 1);
|
||||
abort();
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustInstallErrorHandlers() {
|
||||
install_bad_alloc_error_handler(BadAllocErrorHandler);
|
||||
install_fatal_error_handler(FatalErrorHandler);
|
||||
install_out_of_memory_new_handler();
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustDisableSystemDialogsOnCrash() {
|
||||
|
@ -112,6 +112,7 @@
|
||||
//
|
||||
// Library features:
|
||||
// tidy-alphabetical-start
|
||||
#![feature(array_ptr_get)]
|
||||
#![feature(char_indices_offset)]
|
||||
#![feature(const_align_of_val)]
|
||||
#![feature(const_align_of_val_raw)]
|
||||
|
@ -1798,6 +1798,46 @@ impl<T> *const [T] {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> *const [T; N] {
|
||||
/// Returns a raw pointer to the array's buffer.
|
||||
///
|
||||
/// This is equivalent to casting `self` to `*const T`, but more type-safe.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(array_ptr_get)]
|
||||
/// use std::ptr;
|
||||
///
|
||||
/// let arr: *const [i8; 3] = ptr::null();
|
||||
/// assert_eq!(arr.as_ptr(), ptr::null());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
#[rustc_const_unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
pub const fn as_ptr(self) -> *const T {
|
||||
self as *const T
|
||||
}
|
||||
|
||||
/// Returns a raw pointer to a slice containing the entire array.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(array_ptr_get, slice_ptr_len)]
|
||||
///
|
||||
/// let arr: *const [i32; 3] = &[1, 2, 4] as *const [i32; 3];
|
||||
/// let slice: *const [i32] = arr.as_slice();
|
||||
/// assert_eq!(slice.len(), 3);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
#[rustc_const_unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
pub const fn as_slice(self) -> *const [T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// Equality for pointers
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> PartialEq for *const T {
|
||||
|
@ -2209,6 +2209,49 @@ impl<T> *mut [T] {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> *mut [T; N] {
|
||||
/// Returns a raw pointer to the array's buffer.
|
||||
///
|
||||
/// This is equivalent to casting `self` to `*mut T`, but more type-safe.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(array_ptr_get)]
|
||||
/// use std::ptr;
|
||||
///
|
||||
/// let arr: *mut [i8; 3] = ptr::null_mut();
|
||||
/// assert_eq!(arr.as_mut_ptr(), ptr::null_mut());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
#[rustc_const_unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
pub const fn as_mut_ptr(self) -> *mut T {
|
||||
self as *mut T
|
||||
}
|
||||
|
||||
/// Returns a raw pointer to a mutable slice containing the entire array.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(array_ptr_get)]
|
||||
///
|
||||
/// let mut arr = [1, 2, 5];
|
||||
/// let ptr: *mut [i32; 3] = &mut arr;
|
||||
/// unsafe {
|
||||
/// (&mut *ptr.as_mut_slice())[..2].copy_from_slice(&[3, 4]);
|
||||
/// }
|
||||
/// assert_eq!(arr, [3, 4, 5]);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
#[rustc_const_unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
pub const fn as_mut_slice(self) -> *mut [T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// Equality for pointers
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> PartialEq for *mut T {
|
||||
|
@ -1,5 +1,6 @@
|
||||
#![feature(alloc_layout_extra)]
|
||||
#![feature(array_chunks)]
|
||||
#![feature(array_ptr_get)]
|
||||
#![feature(array_windows)]
|
||||
#![feature(ascii_char)]
|
||||
#![feature(ascii_char_variants)]
|
||||
@ -52,6 +53,7 @@
|
||||
#![feature(sort_internals)]
|
||||
#![feature(slice_take)]
|
||||
#![feature(slice_from_ptr_range)]
|
||||
#![feature(slice_ptr_len)]
|
||||
#![feature(slice_split_once)]
|
||||
#![feature(split_as_slice)]
|
||||
#![feature(maybe_uninit_fill)]
|
||||
|
@ -1141,3 +1141,16 @@ fn test_const_copy() {
|
||||
assert!(*ptr2 == 1);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_null_array_as_slice() {
|
||||
let arr: *mut [u8; 4] = null_mut();
|
||||
let ptr: *mut [u8] = arr.as_mut_slice();
|
||||
assert!(ptr.is_null());
|
||||
assert_eq!(ptr.len(), 4);
|
||||
|
||||
let arr: *const [u8; 4] = null();
|
||||
let ptr: *const [u8] = arr.as_slice();
|
||||
assert!(ptr.is_null());
|
||||
assert_eq!(ptr.len(), 4);
|
||||
}
|
||||
|
@ -1548,6 +1548,10 @@ impl Step for MirOpt {
|
||||
})
|
||||
};
|
||||
|
||||
run(self.target);
|
||||
|
||||
// Run more targets with `--bless`. But we always run the host target first, since some
|
||||
// tests use very specific `only` clauses that are not covered by the target set below.
|
||||
if builder.config.cmd.bless() {
|
||||
// All that we really need to do is cover all combinations of 32/64-bit and unwind/abort,
|
||||
// but while we're at it we might as well flex our cross-compilation support. This
|
||||
@ -1566,8 +1570,6 @@ impl Step for MirOpt {
|
||||
});
|
||||
run(panic_abort_target);
|
||||
}
|
||||
} else {
|
||||
run(self.target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3734,36 +3734,42 @@ impl<'test> TestCx<'test> {
|
||||
debug!(?support_lib_deps);
|
||||
debug!(?support_lib_deps_deps);
|
||||
|
||||
let res = self.cmd2procres(
|
||||
Command::new(&self.config.rustc_path)
|
||||
.arg("-o")
|
||||
.arg(&recipe_bin)
|
||||
.arg(format!(
|
||||
"-Ldependency={}",
|
||||
&support_lib_path.parent().unwrap().to_string_lossy()
|
||||
))
|
||||
.arg(format!("-Ldependency={}", &support_lib_deps.to_string_lossy()))
|
||||
.arg(format!("-Ldependency={}", &support_lib_deps_deps.to_string_lossy()))
|
||||
.arg("--extern")
|
||||
.arg(format!("run_make_support={}", &support_lib_path.to_string_lossy()))
|
||||
.arg(&self.testpaths.file.join("rmake.rs"))
|
||||
.env("TARGET", &self.config.target)
|
||||
.env("PYTHON", &self.config.python)
|
||||
.env("S", &src_root)
|
||||
.env("RUST_BUILD_STAGE", &self.config.stage_id)
|
||||
.env("RUSTC", cwd.join(&self.config.rustc_path))
|
||||
.env("TMPDIR", &tmpdir)
|
||||
.env("LD_LIB_PATH_ENVVAR", dylib_env_var())
|
||||
.env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
|
||||
.env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
|
||||
.env("LLVM_COMPONENTS", &self.config.llvm_components)
|
||||
// We for sure don't want these tests to run in parallel, so make
|
||||
// sure they don't have access to these vars if we run via `make`
|
||||
// at the top level
|
||||
.env_remove("MAKEFLAGS")
|
||||
.env_remove("MFLAGS")
|
||||
.env_remove("CARGO_MAKEFLAGS"),
|
||||
);
|
||||
let mut cmd = Command::new(&self.config.rustc_path);
|
||||
cmd.arg("-o")
|
||||
.arg(&recipe_bin)
|
||||
.arg(format!("-Ldependency={}", &support_lib_path.parent().unwrap().to_string_lossy()))
|
||||
.arg(format!("-Ldependency={}", &support_lib_deps.to_string_lossy()))
|
||||
.arg(format!("-Ldependency={}", &support_lib_deps_deps.to_string_lossy()))
|
||||
.arg("--extern")
|
||||
.arg(format!("run_make_support={}", &support_lib_path.to_string_lossy()))
|
||||
.arg(&self.testpaths.file.join("rmake.rs"))
|
||||
.env("TARGET", &self.config.target)
|
||||
.env("PYTHON", &self.config.python)
|
||||
.env("S", &src_root)
|
||||
.env("RUST_BUILD_STAGE", &self.config.stage_id)
|
||||
.env("RUSTC", cwd.join(&self.config.rustc_path))
|
||||
.env("TMPDIR", &tmpdir)
|
||||
.env("LD_LIB_PATH_ENVVAR", dylib_env_var())
|
||||
.env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
|
||||
.env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
|
||||
.env("LLVM_COMPONENTS", &self.config.llvm_components)
|
||||
// We for sure don't want these tests to run in parallel, so make
|
||||
// sure they don't have access to these vars if we run via `make`
|
||||
// at the top level
|
||||
.env_remove("MAKEFLAGS")
|
||||
.env_remove("MFLAGS")
|
||||
.env_remove("CARGO_MAKEFLAGS");
|
||||
|
||||
if std::env::var_os("COMPILETEST_FORCE_STAGE0").is_some() {
|
||||
let mut stage0_sysroot = build_root.clone();
|
||||
stage0_sysroot.push("stage0-sysroot");
|
||||
debug!(?stage0_sysroot);
|
||||
debug!(exists = stage0_sysroot.exists());
|
||||
|
||||
cmd.arg("--sysroot").arg(&stage0_sysroot);
|
||||
}
|
||||
|
||||
let res = self.cmd2procres(&mut cmd);
|
||||
if !res.status.success() {
|
||||
self.fatal_proc_rec("run-make test failed: could not build `rmake.rs` recipe", &res);
|
||||
}
|
||||
|
@ -515,6 +515,9 @@ cc = ["@Nadrieril"]
|
||||
message = "Some changes occurred in exhaustiveness checking"
|
||||
cc = ["@Nadrieril"]
|
||||
|
||||
[mentions."compiler/rustc_lint/src/context/diagnostics/check_cfg.rs"]
|
||||
cc = ["@Urgau"]
|
||||
|
||||
[mentions."library/core/src/intrinsics/simd.rs"]
|
||||
message = """
|
||||
Some changes occurred to the platform-builtins intrinsics. Make sure the
|
||||
@ -699,6 +702,9 @@ cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
|
||||
[mentions."src/doc/unstable-book/src/language-features/no-sanitize.md"]
|
||||
cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
|
||||
|
||||
[mentions."src/doc/unstable-book/src/compiler-flags/check-cfg.md"]
|
||||
cc = ["@Urgau"]
|
||||
|
||||
[mentions."tests/codegen/sanitizer"]
|
||||
cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
|
||||
|
||||
@ -717,6 +723,9 @@ cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
|
||||
[mentions."tests/ui/stack-protector"]
|
||||
cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
|
||||
|
||||
[mentions."tests/ui/check-cfg"]
|
||||
cc = ["@Urgau"]
|
||||
|
||||
[assign]
|
||||
warn_non_default_branch = true
|
||||
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
|
||||
|
Loading…
Reference in New Issue
Block a user