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:
bors 2024-03-17 08:44:44 +00:00
commit ecdea9e943
13 changed files with 456 additions and 309 deletions

View File

@ -1519,7 +1519,7 @@ extern "C" {
#[link(name = "llvm-wrapper", kind = "static")] #[link(name = "llvm-wrapper", kind = "static")]
extern "C" { extern "C" {
pub fn LLVMRustInstallFatalErrorHandler(); pub fn LLVMRustInstallErrorHandlers();
pub fn LLVMRustDisableSystemDialogsOnCrash(); pub fn LLVMRustDisableSystemDialogsOnCrash();
// Create and destroy contexts. // Create and destroy contexts.

View File

@ -49,7 +49,7 @@ unsafe fn configure_llvm(sess: &Session) {
let mut llvm_c_strs = Vec::with_capacity(n_args + 1); let mut llvm_c_strs = Vec::with_capacity(n_args + 1);
let mut llvm_args = 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 // 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 // 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. // cause it to hang until it times out, which can take several hours.

View File

@ -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::{add_elided_lifetime_in_path_suggestion, Diag};
use rustc_errors::{Applicability, SuggestionStyle}; use rustc_errors::{Applicability, SuggestionStyle};
use rustc_middle::middle::stability; use rustc_middle::middle::stability;
use rustc_session::config::ExpectedValues;
use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::BuiltinLintDiag;
use rustc_session::Session; use rustc_session::Session;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::BytePos; use rustc_span::BytePos;
const MAX_CHECK_CFG_NAMES_OR_VALUES: usize = 35; mod check_cfg;
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 builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) { pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) {
match diagnostic { match diagnostic {
@ -219,242 +181,11 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
diag.help(help); 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"); 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) => { BuiltinLintDiag::UnexpectedCfgName(name, value) => {
#[allow(rustc::potential_query_instability)] check_cfg::unexpected_cfg_name(sess, diag, name, value)
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::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) => { BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg) => {
let left_sp = diag.span.primary_span().unwrap(); let left_sp = diag.span.primary_span().unwrap();

View 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");
}
}

View File

@ -25,6 +25,13 @@
#include <iostream> #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 // This file defines alternate interfaces to core functions that are more
@ -88,8 +95,24 @@ static void FatalErrorHandler(void *UserData,
exit(101); 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_fatal_error_handler(FatalErrorHandler);
install_out_of_memory_new_handler();
} }
extern "C" void LLVMRustDisableSystemDialogsOnCrash() { extern "C" void LLVMRustDisableSystemDialogsOnCrash() {

View File

@ -112,6 +112,7 @@
// //
// Library features: // Library features:
// tidy-alphabetical-start // tidy-alphabetical-start
#![feature(array_ptr_get)]
#![feature(char_indices_offset)] #![feature(char_indices_offset)]
#![feature(const_align_of_val)] #![feature(const_align_of_val)]
#![feature(const_align_of_val_raw)] #![feature(const_align_of_val_raw)]

View File

@ -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 // Equality for pointers
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> PartialEq for *const T { impl<T: ?Sized> PartialEq for *const T {

View File

@ -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 // Equality for pointers
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> PartialEq for *mut T { impl<T: ?Sized> PartialEq for *mut T {

View File

@ -1,5 +1,6 @@
#![feature(alloc_layout_extra)] #![feature(alloc_layout_extra)]
#![feature(array_chunks)] #![feature(array_chunks)]
#![feature(array_ptr_get)]
#![feature(array_windows)] #![feature(array_windows)]
#![feature(ascii_char)] #![feature(ascii_char)]
#![feature(ascii_char_variants)] #![feature(ascii_char_variants)]
@ -52,6 +53,7 @@
#![feature(sort_internals)] #![feature(sort_internals)]
#![feature(slice_take)] #![feature(slice_take)]
#![feature(slice_from_ptr_range)] #![feature(slice_from_ptr_range)]
#![feature(slice_ptr_len)]
#![feature(slice_split_once)] #![feature(slice_split_once)]
#![feature(split_as_slice)] #![feature(split_as_slice)]
#![feature(maybe_uninit_fill)] #![feature(maybe_uninit_fill)]

View File

@ -1141,3 +1141,16 @@ fn test_const_copy() {
assert!(*ptr2 == 1); 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);
}

View File

@ -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() { if builder.config.cmd.bless() {
// All that we really need to do is cover all combinations of 32/64-bit and unwind/abort, // 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 // 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); run(panic_abort_target);
} }
} else {
run(self.target);
} }
} }
} }

View File

@ -3734,14 +3734,10 @@ impl<'test> TestCx<'test> {
debug!(?support_lib_deps); debug!(?support_lib_deps);
debug!(?support_lib_deps_deps); debug!(?support_lib_deps_deps);
let res = self.cmd2procres( let mut cmd = Command::new(&self.config.rustc_path);
Command::new(&self.config.rustc_path) cmd.arg("-o")
.arg("-o")
.arg(&recipe_bin) .arg(&recipe_bin)
.arg(format!( .arg(format!("-Ldependency={}", &support_lib_path.parent().unwrap().to_string_lossy()))
"-Ldependency={}",
&support_lib_path.parent().unwrap().to_string_lossy()
))
.arg(format!("-Ldependency={}", &support_lib_deps.to_string_lossy())) .arg(format!("-Ldependency={}", &support_lib_deps.to_string_lossy()))
.arg(format!("-Ldependency={}", &support_lib_deps_deps.to_string_lossy())) .arg(format!("-Ldependency={}", &support_lib_deps_deps.to_string_lossy()))
.arg("--extern") .arg("--extern")
@ -3762,8 +3758,18 @@ impl<'test> TestCx<'test> {
// at the top level // at the top level
.env_remove("MAKEFLAGS") .env_remove("MAKEFLAGS")
.env_remove("MFLAGS") .env_remove("MFLAGS")
.env_remove("CARGO_MAKEFLAGS"), .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() { if !res.status.success() {
self.fatal_proc_rec("run-make test failed: could not build `rmake.rs` recipe", &res); self.fatal_proc_rec("run-make test failed: could not build `rmake.rs` recipe", &res);
} }

View File

@ -515,6 +515,9 @@ cc = ["@Nadrieril"]
message = "Some changes occurred in exhaustiveness checking" message = "Some changes occurred in exhaustiveness checking"
cc = ["@Nadrieril"] cc = ["@Nadrieril"]
[mentions."compiler/rustc_lint/src/context/diagnostics/check_cfg.rs"]
cc = ["@Urgau"]
[mentions."library/core/src/intrinsics/simd.rs"] [mentions."library/core/src/intrinsics/simd.rs"]
message = """ message = """
Some changes occurred to the platform-builtins intrinsics. Make sure the 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"] [mentions."src/doc/unstable-book/src/language-features/no-sanitize.md"]
cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
[mentions."src/doc/unstable-book/src/compiler-flags/check-cfg.md"]
cc = ["@Urgau"]
[mentions."tests/codegen/sanitizer"] [mentions."tests/codegen/sanitizer"]
cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
@ -717,6 +723,9 @@ cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
[mentions."tests/ui/stack-protector"] [mentions."tests/ui/stack-protector"]
cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
[mentions."tests/ui/check-cfg"]
cc = ["@Urgau"]
[assign] [assign]
warn_non_default_branch = true warn_non_default_branch = true
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"