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")]
|
#[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.
|
||||||
|
@ -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.
|
||||||
|
@ -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();
|
||||||
|
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>
|
#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() {
|
||||||
|
@ -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)]
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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)]
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user