Merge from rustc
This commit is contained in:
commit
352545f16f
357 changed files with 3354 additions and 1745 deletions
|
|
@ -25,6 +25,7 @@ path = "src/driver.rs"
|
|||
[dependencies]
|
||||
clippy_config = { path = "clippy_config" }
|
||||
clippy_lints = { path = "clippy_lints" }
|
||||
clippy_utils = { path = "clippy_utils" }
|
||||
rustc_tools_util = { path = "rustc_tools_util", version = "0.4.2" }
|
||||
tempfile = { version = "3.3", optional = true }
|
||||
termize = "0.1"
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use super::{Attribute, DEPRECATED_CFG_ATTR, DEPRECATED_CLIPPY_CFG_ATTR, unnecessary_clippy_cfg};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::msrvs::{self, MsrvStack};
|
||||
use clippy_utils::sym;
|
||||
use rustc_ast::AttrStyle;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::sym;
|
||||
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &MsrvStack) {
|
||||
// check cfg_attr
|
||||
|
|
@ -18,7 +18,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &MsrvStack) {
|
|||
&& msrv.meets(msrvs::TOOL_ATTRIBUTES)
|
||||
// check for `rustfmt_skip` and `rustfmt::skip`
|
||||
&& let Some(skip_item) = &items[1].meta_item()
|
||||
&& (skip_item.has_name(sym!(rustfmt_skip))
|
||||
&& (skip_item.has_name(sym::rustfmt_skip)
|
||||
|| skip_item
|
||||
.path
|
||||
.segments
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ use super::USELESS_ATTRIBUTE;
|
|||
use super::utils::{is_lint_level, is_word, namespace_and_lint};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::{SpanRangeExt, first_line_of_span};
|
||||
use clippy_utils::sym;
|
||||
use rustc_ast::{Attribute, Item, ItemKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, LintContext};
|
||||
use rustc_span::sym;
|
||||
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
|
||||
let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use));
|
||||
|
|
@ -61,7 +61,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
|
|||
if is_word(lint, sym::unused_imports) && skip_unused_imports {
|
||||
return;
|
||||
}
|
||||
if is_word(lint, sym!(unused_extern_crates)) {
|
||||
if is_word(lint, sym::unused_extern_crates) {
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -
|
|||
.not_trait()
|
||||
.filter(|trait_id| implements_trait(cx, ty, *trait_id, &[]))
|
||||
.and_then(|trait_id| {
|
||||
cx.tcx.associated_items(trait_id).find_by_name_and_kind(
|
||||
cx.tcx.associated_items(trait_id).find_by_ident_and_kind(
|
||||
cx.tcx,
|
||||
Ident::from_str("Output"),
|
||||
ty::AssocKind::Type,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ pub fn check(
|
|||
// of all `#[test]` attributes in not ignored code examples
|
||||
fn check_code_sample(code: String, edition: Edition, ignore: bool) -> (bool, Vec<Range<usize>>) {
|
||||
rustc_driver::catch_fatal_errors(|| {
|
||||
rustc_span::create_session_globals_then(edition, None, || {
|
||||
rustc_span::create_session_globals_then(edition, &[], None, || {
|
||||
let mut test_attr_spans = vec![];
|
||||
let filename = FileName::anon_source_code(&code);
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, item: &ImplItem<'_>, ignored
|
|||
&& let Some(did) = trait_item_def_id_of_impl(items, item.owner_id)
|
||||
&& !is_from_ignored_trait(trait_ref, ignored_traits)
|
||||
{
|
||||
let mut param_idents_iter = cx.tcx.hir_body_param_names(body_id);
|
||||
let mut default_param_idents_iter = cx.tcx.fn_arg_names(did).iter().copied();
|
||||
let mut param_idents_iter = cx.tcx.hir_body_param_idents(body_id);
|
||||
let mut default_param_idents_iter = cx.tcx.fn_arg_idents(did).iter().copied();
|
||||
|
||||
let renames = RenamedFnArgs::new(&mut default_param_idents_iter, &mut param_idents_iter);
|
||||
if !renames.0.is_empty() {
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) -
|
|||
.instantiate_bound_regions_with_erased(sig.rebind(search_ty))
|
||||
.kind()
|
||||
&& let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator)
|
||||
&& let Some(iter_item) = cx.tcx.associated_items(iter_trait).find_by_name_and_kind(
|
||||
&& let Some(iter_item) = cx.tcx.associated_items(iter_trait).find_by_ident_and_kind(
|
||||
cx.tcx,
|
||||
Ident::with_dummy_span(sym::Item),
|
||||
AssocKind::Type,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#![feature(f128)]
|
||||
#![feature(f16)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(macro_metavar_expr)]
|
||||
#![feature(macro_metavar_expr_concat)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
|
|
@ -74,6 +75,7 @@ pub mod qualify_min_const_fn;
|
|||
pub mod source;
|
||||
pub mod str_utils;
|
||||
pub mod sugg;
|
||||
pub mod sym;
|
||||
pub mod ty;
|
||||
pub mod usage;
|
||||
pub mod visitors;
|
||||
|
|
@ -126,7 +128,7 @@ use rustc_middle::ty::{
|
|||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::symbol::{Ident, Symbol, kw};
|
||||
use rustc_span::{InnerSpan, Span, sym};
|
||||
use rustc_span::{InnerSpan, Span};
|
||||
use visitors::{Visitable, for_each_unconsumed_temporary};
|
||||
|
||||
use crate::consts::{ConstEvalCtxt, Constant, mir_to_const};
|
||||
|
|
@ -3502,7 +3504,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
|
|||
// a::b::c ::d::sym refers to
|
||||
// e::f::sym:: ::
|
||||
// result should be super::super::super::super::e::f
|
||||
if let DefPathData::TypeNs(Some(s)) = l {
|
||||
if let DefPathData::TypeNs(s) = l {
|
||||
path.push(s.to_string());
|
||||
}
|
||||
if let DefPathData::TypeNs(_) = r {
|
||||
|
|
@ -3513,7 +3515,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
|
|||
// a::b::sym:: :: refers to
|
||||
// c::d::e ::f::sym
|
||||
// when looking at `f`
|
||||
Left(DefPathData::TypeNs(Some(sym))) => path.push(sym.to_string()),
|
||||
Left(DefPathData::TypeNs(sym)) => path.push(sym.to_string()),
|
||||
// consider:
|
||||
// a::b::c ::d::sym refers to
|
||||
// e::f::sym:: ::
|
||||
|
|
@ -3527,7 +3529,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
|
|||
// `super` chain would be too long, just use the absolute path instead
|
||||
once(String::from("crate"))
|
||||
.chain(to.data.iter().filter_map(|el| {
|
||||
if let DefPathData::TypeNs(Some(sym)) = el.data {
|
||||
if let DefPathData::TypeNs(sym) = el.data {
|
||||
Some(sym.to_string())
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
23
src/tools/clippy/clippy_utils/src/sym.rs
Normal file
23
src/tools/clippy/clippy_utils/src/sym.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use rustc_span::symbol::{Symbol, PREDEFINED_SYMBOLS_COUNT};
|
||||
|
||||
pub use rustc_span::sym::*;
|
||||
|
||||
macro_rules! generate {
|
||||
($($sym:ident,)*) => {
|
||||
/// To be supplied to `rustc_interface::Config`
|
||||
pub const EXTRA_SYMBOLS: &[&str] = &[
|
||||
$(stringify!($sym),)*
|
||||
];
|
||||
|
||||
$(
|
||||
pub const $sym: Symbol = Symbol::new(PREDEFINED_SYMBOLS_COUNT + ${index()});
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
generate! {
|
||||
rustfmt_skip,
|
||||
unused_extern_crates,
|
||||
}
|
||||
|
|
@ -1109,7 +1109,7 @@ pub fn make_projection<'tcx>(
|
|||
assoc_ty: Symbol,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
) -> Option<AliasTy<'tcx>> {
|
||||
let Some(assoc_item) = tcx.associated_items(container_id).find_by_name_and_kind(
|
||||
let Some(assoc_item) = tcx.associated_items(container_id).find_by_ident_and_kind(
|
||||
tcx,
|
||||
Ident::with_dummy_span(assoc_ty),
|
||||
AssocKind::Type,
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
|
|||
clippy_lints::register_lints(lint_store, conf);
|
||||
clippy_lints::register_pre_expansion_lints(lint_store, conf);
|
||||
}));
|
||||
config.extra_symbols = clippy_utils::sym::EXTRA_SYMBOLS.into();
|
||||
|
||||
// FIXME: #4825; This is required, because Clippy lints that are based on MIR have to be
|
||||
// run on the unoptimized MIR. On the other hand this results in some false negatives. If
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "compiletest"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
|
|
|||
|
|
@ -395,6 +395,7 @@ pub struct Config {
|
|||
|
||||
pub target_cfgs: OnceLock<TargetCfgs>,
|
||||
pub builtin_cfg_names: OnceLock<HashSet<String>>,
|
||||
pub supported_crate_types: OnceLock<HashSet<String>>,
|
||||
|
||||
pub nocapture: bool,
|
||||
|
||||
|
|
@ -472,6 +473,11 @@ impl Config {
|
|||
self.builtin_cfg_names.get_or_init(|| builtin_cfg_names(self))
|
||||
}
|
||||
|
||||
/// Get the list of crate types that the target platform supports.
|
||||
pub fn supported_crate_types(&self) -> &HashSet<String> {
|
||||
self.supported_crate_types.get_or_init(|| supported_crate_types(self))
|
||||
}
|
||||
|
||||
pub fn has_threads(&self) -> bool {
|
||||
// Wasm targets don't have threads unless `-threads` is in the target
|
||||
// name, such as `wasm32-wasip1-threads`.
|
||||
|
|
@ -745,6 +751,31 @@ fn builtin_cfg_names(config: &Config) -> HashSet<String> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub const KNOWN_CRATE_TYPES: &[&str] =
|
||||
&["bin", "cdylib", "dylib", "lib", "proc-macro", "rlib", "staticlib"];
|
||||
|
||||
fn supported_crate_types(config: &Config) -> HashSet<String> {
|
||||
let crate_types: HashSet<_> = rustc_output(
|
||||
config,
|
||||
&["--target", &config.target, "--print=supported-crate-types", "-Zunstable-options"],
|
||||
Default::default(),
|
||||
)
|
||||
.lines()
|
||||
.map(|l| l.to_string())
|
||||
.collect();
|
||||
|
||||
for crate_type in crate_types.iter() {
|
||||
assert!(
|
||||
KNOWN_CRATE_TYPES.contains(&crate_type.as_str()),
|
||||
"unexpected crate type `{}`: known crate types are {:?}",
|
||||
crate_type,
|
||||
KNOWN_CRATE_TYPES
|
||||
);
|
||||
}
|
||||
|
||||
crate_types
|
||||
}
|
||||
|
||||
fn rustc_output(config: &Config, args: &[&str], envs: HashMap<String, String>) -> String {
|
||||
let mut command = Command::new(&config.rustc_path);
|
||||
add_dylib_path(&mut command, iter::once(&config.compile_lib_path));
|
||||
|
|
|
|||
|
|
@ -40,7 +40,9 @@ pub(crate) fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
|
|||
//
|
||||
// we should figure out how to lift this restriction! (run them all
|
||||
// on different ports allocated dynamically).
|
||||
env::set_var("RUST_TEST_THREADS", "1");
|
||||
//
|
||||
// SAFETY: at this point we are still single-threaded.
|
||||
unsafe { env::set_var("RUST_TEST_THREADS", "1") };
|
||||
}
|
||||
|
||||
Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() }))
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
|
|||
"min-llvm-version",
|
||||
"min-system-llvm-version",
|
||||
"needs-asm-support",
|
||||
"needs-crate-type",
|
||||
"needs-deterministic-layouts",
|
||||
"needs-dlltool",
|
||||
"needs-dynamic-linking",
|
||||
|
|
|
|||
|
|
@ -389,14 +389,22 @@ impl TestProps {
|
|||
}
|
||||
|
||||
if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) {
|
||||
self.compile_flags.extend(split_flags(&flags));
|
||||
let flags = split_flags(&flags);
|
||||
for flag in &flags {
|
||||
if flag == "--edition" || flag.starts_with("--edition=") {
|
||||
panic!("you must use `//@ edition` to configure the edition");
|
||||
}
|
||||
}
|
||||
self.compile_flags.extend(flags);
|
||||
}
|
||||
if config.parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS).is_some() {
|
||||
panic!("`compiler-flags` directive should be spelled `compile-flags`");
|
||||
}
|
||||
|
||||
if let Some(edition) = config.parse_edition(ln) {
|
||||
self.compile_flags.push(format!("--edition={}", edition.trim()));
|
||||
// The edition is added at the start, since flags from //@compile-flags must
|
||||
// be passed to rustc last.
|
||||
self.compile_flags.insert(0, format!("--edition={}", edition.trim()));
|
||||
has_edition = true;
|
||||
}
|
||||
|
||||
|
|
@ -452,7 +460,7 @@ impl TestProps {
|
|||
ln,
|
||||
UNSET_EXEC_ENV,
|
||||
&mut self.unset_exec_env,
|
||||
|r| r,
|
||||
|r| r.trim().to_owned(),
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
|
|
@ -464,7 +472,7 @@ impl TestProps {
|
|||
ln,
|
||||
UNSET_RUSTC_ENV,
|
||||
&mut self.unset_rustc_env,
|
||||
|r| r,
|
||||
|r| r.trim().to_owned(),
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
|
|
@ -624,7 +632,9 @@ impl TestProps {
|
|||
}
|
||||
|
||||
if let (Some(edition), false) = (&config.edition, has_edition) {
|
||||
self.compile_flags.push(format!("--edition={}", edition));
|
||||
// The edition is added at the start, since flags from //@compile-flags must be passed
|
||||
// to rustc last.
|
||||
self.compile_flags.insert(0, format!("--edition={}", edition));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -997,16 +1007,13 @@ impl Config {
|
|||
|
||||
fn parse_env(nv: String) -> (String, String) {
|
||||
// nv is either FOO or FOO=BAR
|
||||
let mut strs: Vec<String> = nv.splitn(2, '=').map(str::to_owned).collect();
|
||||
|
||||
match strs.len() {
|
||||
1 => (strs.pop().unwrap(), String::new()),
|
||||
2 => {
|
||||
let end = strs.pop().unwrap();
|
||||
(strs.pop().unwrap(), end)
|
||||
}
|
||||
n => panic!("Expected 1 or 2 strings, not {}", n),
|
||||
}
|
||||
// FIXME(Zalathar): The form without `=` seems to be unused; should
|
||||
// we drop support for it?
|
||||
let (name, value) = nv.split_once('=').unwrap_or((&nv, ""));
|
||||
// Trim whitespace from the name, so that `//@ exec-env: FOO=BAR`
|
||||
// sees the name as `FOO` and not ` FOO`.
|
||||
let name = name.trim();
|
||||
(name.to_owned(), value.to_owned())
|
||||
}
|
||||
|
||||
fn parse_pp_exact(&self, line: &str, testfile: &Path) -> Option<PathBuf> {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::common::{Config, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer};
|
||||
use crate::common::{Config, KNOWN_CRATE_TYPES, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer};
|
||||
use crate::header::{IgnoreDecision, llvm_has_libzstd};
|
||||
|
||||
pub(super) fn handle_needs(
|
||||
|
|
@ -6,7 +6,7 @@ pub(super) fn handle_needs(
|
|||
config: &Config,
|
||||
ln: &str,
|
||||
) -> IgnoreDecision {
|
||||
// Note thet we intentionally still put the needs- prefix here to make the file show up when
|
||||
// Note that we intentionally still put the needs- prefix here to make the file show up when
|
||||
// grepping for a directive name, even though we could technically strip that.
|
||||
let needs = &[
|
||||
Need {
|
||||
|
|
@ -224,6 +224,50 @@ pub(super) fn handle_needs(
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME(jieyouxu): share multi-value directive logic with `needs-target-has-atomic` above.
|
||||
if name == "needs-crate-type" {
|
||||
let Some(rest) = rest else {
|
||||
return IgnoreDecision::Error {
|
||||
message:
|
||||
"expected `needs-crate-type` to have a comma-separated list of crate types"
|
||||
.to_string(),
|
||||
};
|
||||
};
|
||||
|
||||
// Expect directive value to be a list of comma-separated crate-types.
|
||||
let specified_crate_types = rest
|
||||
.split(',')
|
||||
.map(|crate_type| crate_type.trim())
|
||||
.map(ToString::to_string)
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
for crate_type in &specified_crate_types {
|
||||
if !KNOWN_CRATE_TYPES.contains(&crate_type.as_str()) {
|
||||
return IgnoreDecision::Error {
|
||||
message: format!(
|
||||
"unknown crate type specified in `needs-crate-type`: `{crate_type}` is not \
|
||||
a known crate type, known values are `{:?}`",
|
||||
KNOWN_CRATE_TYPES
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let satisfies_all_crate_types = specified_crate_types
|
||||
.iter()
|
||||
.all(|specified| config.supported_crate_types().contains(specified));
|
||||
if satisfies_all_crate_types {
|
||||
return IgnoreDecision::Continue;
|
||||
} else {
|
||||
return IgnoreDecision::Ignore {
|
||||
reason: format!(
|
||||
"skipping test as target does not support all of the crate types `{:?}`",
|
||||
specified_crate_types
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if !name.starts_with("needs-") {
|
||||
return IgnoreDecision::Continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -902,3 +902,41 @@ fn test_rustc_abi() {
|
|||
assert!(!check_ignore(&config, "//@ ignore-rustc_abi-x86-sse2"));
|
||||
assert!(check_ignore(&config, "//@ only-rustc_abi-x86-sse2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_supported_crate_types() {
|
||||
// Basic assumptions check on under-test compiler's `--print=supported-crate-types` output based
|
||||
// on knowledge about the cherry-picked `x86_64-unknown-linux-gnu` and `wasm32-unknown-unknown`
|
||||
// targets. Also smoke tests the `needs-crate-type` directive itself.
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
let config = cfg().target("x86_64-unknown-linux-gnu").build();
|
||||
assert_eq!(
|
||||
config.supported_crate_types().iter().map(String::as_str).collect::<HashSet<_>>(),
|
||||
HashSet::from(["bin", "cdylib", "dylib", "lib", "proc-macro", "rlib", "staticlib"]),
|
||||
);
|
||||
assert!(!check_ignore(&config, "//@ needs-crate-type: rlib"));
|
||||
assert!(!check_ignore(&config, "//@ needs-crate-type: dylib"));
|
||||
assert!(!check_ignore(
|
||||
&config,
|
||||
"//@ needs-crate-type: bin, cdylib, dylib, lib, proc-macro, rlib, staticlib"
|
||||
));
|
||||
|
||||
let config = cfg().target("wasm32-unknown-unknown").build();
|
||||
assert_eq!(
|
||||
config.supported_crate_types().iter().map(String::as_str).collect::<HashSet<_>>(),
|
||||
HashSet::from(["bin", "cdylib", "lib", "rlib", "staticlib"]),
|
||||
);
|
||||
|
||||
// rlib is supported
|
||||
assert!(!check_ignore(&config, "//@ needs-crate-type: rlib"));
|
||||
// dylib is not
|
||||
assert!(check_ignore(&config, "//@ needs-crate-type: dylib"));
|
||||
// If multiple crate types are specified, then all specified crate types need to be supported.
|
||||
assert!(check_ignore(&config, "//@ needs-crate-type: cdylib, dylib"));
|
||||
assert!(check_ignore(
|
||||
&config,
|
||||
"//@ needs-crate-type: bin, cdylib, dylib, lib, proc-macro, rlib, staticlib"
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -431,6 +431,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||
|
||||
target_cfgs: OnceLock::new(),
|
||||
builtin_cfg_names: OnceLock::new(),
|
||||
supported_crate_types: OnceLock::new(),
|
||||
|
||||
nocapture: matches.opt_present("no-capture"),
|
||||
|
||||
|
|
@ -529,10 +530,14 @@ pub fn run_tests(config: Arc<Config>) {
|
|||
}
|
||||
// Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows
|
||||
// If #11207 is resolved (adding manifest to .exe) this becomes unnecessary
|
||||
env::set_var("__COMPAT_LAYER", "RunAsInvoker");
|
||||
//
|
||||
// SAFETY: at this point we're still single-threaded.
|
||||
unsafe { env::set_var("__COMPAT_LAYER", "RunAsInvoker") };
|
||||
|
||||
// Let tests know which target they're running as
|
||||
env::set_var("TARGET", &config.target);
|
||||
// Let tests know which target they're running as.
|
||||
//
|
||||
// SAFETY: at this point we're still single-threaded.
|
||||
unsafe { env::set_var("TARGET", &config.target) };
|
||||
|
||||
let mut configs = Vec::new();
|
||||
if let Mode::DebugInfo = config.mode {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
/// This fixes issue #7772.
|
||||
#[cfg(target_vendor = "apple")]
|
||||
#[allow(non_camel_case_types)]
|
||||
// FIXME(#139616): document caller contract.
|
||||
pub unsafe fn raise_fd_limit() {
|
||||
use std::ptr::null_mut;
|
||||
use std::{cmp, io};
|
||||
|
|
@ -21,8 +22,10 @@ pub unsafe fn raise_fd_limit() {
|
|||
let mut mib: [libc::c_int; 2] = [CTL_KERN, KERN_MAXFILESPERPROC];
|
||||
let mut maxfiles: libc::c_int = 0;
|
||||
let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t;
|
||||
if libc::sysctl(&mut mib[0], 2, &mut maxfiles as *mut _ as *mut _, &mut size, null_mut(), 0)
|
||||
!= 0
|
||||
// FIXME(#139616): justify why this is sound.
|
||||
if unsafe {
|
||||
libc::sysctl(&mut mib[0], 2, &mut maxfiles as *mut _ as *mut _, &mut size, null_mut(), 0)
|
||||
} != 0
|
||||
{
|
||||
let err = io::Error::last_os_error();
|
||||
panic!("raise_fd_limit: error calling sysctl: {}", err);
|
||||
|
|
@ -30,7 +33,8 @@ pub unsafe fn raise_fd_limit() {
|
|||
|
||||
// Fetch the current resource limits
|
||||
let mut rlim = libc::rlimit { rlim_cur: 0, rlim_max: 0 };
|
||||
if libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) != 0 {
|
||||
// FIXME(#139616): justify why this is sound.
|
||||
if unsafe { libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) } != 0 {
|
||||
let err = io::Error::last_os_error();
|
||||
panic!("raise_fd_limit: error calling getrlimit: {}", err);
|
||||
}
|
||||
|
|
@ -41,7 +45,8 @@ pub unsafe fn raise_fd_limit() {
|
|||
rlim.rlim_cur = cmp::min(maxfiles as libc::rlim_t, rlim.rlim_max);
|
||||
|
||||
// Set our newly-increased resource limit.
|
||||
if libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) != 0 {
|
||||
// FIXME(#139616): justify why this is sound.
|
||||
if unsafe { libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) } != 0 {
|
||||
let err = io::Error::last_os_error();
|
||||
panic!("raise_fd_limit: error calling setrlimit: {}", err);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ mod imp {
|
|||
mut err_pipe: ChildStderr,
|
||||
data: &mut dyn FnMut(bool, &mut Vec<u8>, bool),
|
||||
) -> io::Result<()> {
|
||||
// FIXME(#139616): justify why this is sound.
|
||||
unsafe {
|
||||
libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
|
||||
libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
|
||||
|
|
@ -175,6 +176,7 @@ mod imp {
|
|||
let mut out = Vec::new();
|
||||
let mut err = Vec::new();
|
||||
|
||||
// FIXME(#139616): justify why this is sound.
|
||||
let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
|
||||
fds[0].fd = out_pipe.as_raw_fd();
|
||||
fds[0].events = libc::POLLIN;
|
||||
|
|
@ -185,6 +187,7 @@ mod imp {
|
|||
|
||||
while nfds > 0 {
|
||||
// wait for either pipe to become readable using `select`
|
||||
// FIXME(#139616): justify why this is sound.
|
||||
let r = unsafe { libc::poll(fds.as_mut_ptr(), nfds, -1) };
|
||||
if r == -1 {
|
||||
let err = io::Error::last_os_error();
|
||||
|
|
@ -256,6 +259,7 @@ mod imp {
|
|||
port.add_handle(0, &out_pipe)?;
|
||||
port.add_handle(1, &err_pipe)?;
|
||||
|
||||
// FIXME(#139616): justify why this is sound.
|
||||
unsafe {
|
||||
let mut out_pipe = Pipe::new(out_pipe, &mut out);
|
||||
let mut err_pipe = Pipe::new(err_pipe, &mut err);
|
||||
|
|
@ -284,18 +288,23 @@ mod imp {
|
|||
}
|
||||
|
||||
impl<'a> Pipe<'a> {
|
||||
// FIXME(#139616): document caller contract.
|
||||
unsafe fn new<P: IntoRawHandle>(p: P, dst: &'a mut Vec<u8>) -> Pipe<'a> {
|
||||
Pipe {
|
||||
dst,
|
||||
pipe: NamedPipe::from_raw_handle(p.into_raw_handle()),
|
||||
// FIXME(#139616): justify why this is sound.
|
||||
pipe: unsafe { NamedPipe::from_raw_handle(p.into_raw_handle()) },
|
||||
overlapped: Overlapped::zero(),
|
||||
done: false,
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(#139616): document caller contract.
|
||||
unsafe fn read(&mut self) -> io::Result<()> {
|
||||
let dst = slice_to_end(self.dst);
|
||||
match self.pipe.read_overlapped(dst, self.overlapped.raw()) {
|
||||
// FIXME(#139616): justify why this is sound.
|
||||
let dst = unsafe { slice_to_end(self.dst) };
|
||||
// FIXME(#139616): justify why this is sound.
|
||||
match unsafe { self.pipe.read_overlapped(dst, self.overlapped.raw()) } {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => {
|
||||
if e.raw_os_error() == Some(ERROR_BROKEN_PIPE.0 as i32) {
|
||||
|
|
@ -308,15 +317,18 @@ mod imp {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME(#139616): document caller contract.
|
||||
unsafe fn complete(&mut self, status: &CompletionStatus) {
|
||||
let prev = self.dst.len();
|
||||
self.dst.set_len(prev + status.bytes_transferred() as usize);
|
||||
// FIXME(#139616): justify why this is sound.
|
||||
unsafe { self.dst.set_len(prev + status.bytes_transferred() as usize) };
|
||||
if status.bytes_transferred() == 0 {
|
||||
self.done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(#139616): document caller contract.
|
||||
unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
|
||||
if v.capacity() == 0 {
|
||||
v.reserve(16);
|
||||
|
|
@ -324,6 +336,12 @@ mod imp {
|
|||
if v.capacity() == v.len() {
|
||||
v.reserve(1);
|
||||
}
|
||||
slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize), v.capacity() - v.len())
|
||||
// FIXME(#139616): justify why this is sound.
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
v.as_mut_ptr().offset(v.len() as isize),
|
||||
v.capacity() - v.len(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ pub fn compute_stamp_hash(config: &Config) -> String {
|
|||
let mut hash = DefaultHasher::new();
|
||||
config.stage_id.hash(&mut hash);
|
||||
config.run.hash(&mut hash);
|
||||
config.edition.hash(&mut hash);
|
||||
|
||||
match config.debugger {
|
||||
Some(Debugger::Cdb) => {
|
||||
|
|
@ -445,8 +446,8 @@ impl<'test> TestCx<'test> {
|
|||
|
||||
self.compose_and_run(
|
||||
rustc,
|
||||
self.config.compile_lib_path.to_str().unwrap(),
|
||||
Some(aux_dir.to_str().unwrap()),
|
||||
self.config.compile_lib_path.as_path(),
|
||||
Some(aux_dir.as_path()),
|
||||
src,
|
||||
)
|
||||
}
|
||||
|
|
@ -968,16 +969,16 @@ impl<'test> TestCx<'test> {
|
|||
delete_after_success: bool,
|
||||
) -> ProcRes {
|
||||
let prepare_env = |cmd: &mut Command| {
|
||||
for key in &self.props.unset_exec_env {
|
||||
cmd.env_remove(key);
|
||||
}
|
||||
|
||||
for (key, val) in &self.props.exec_env {
|
||||
cmd.env(key, val);
|
||||
}
|
||||
for (key, val) in env_extra {
|
||||
cmd.env(key, val);
|
||||
}
|
||||
|
||||
for key in &self.props.unset_exec_env {
|
||||
cmd.env_remove(key);
|
||||
}
|
||||
};
|
||||
|
||||
let proc_res = match &*self.config.target {
|
||||
|
|
@ -1020,8 +1021,8 @@ impl<'test> TestCx<'test> {
|
|||
|
||||
self.compose_and_run(
|
||||
test_client,
|
||||
self.config.run_lib_path.to_str().unwrap(),
|
||||
Some(aux_dir.to_str().unwrap()),
|
||||
self.config.run_lib_path.as_path(),
|
||||
Some(aux_dir.as_path()),
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
|
@ -1035,8 +1036,8 @@ impl<'test> TestCx<'test> {
|
|||
|
||||
self.compose_and_run(
|
||||
wr_run,
|
||||
self.config.run_lib_path.to_str().unwrap(),
|
||||
Some(aux_dir.to_str().unwrap()),
|
||||
self.config.run_lib_path.as_path(),
|
||||
Some(aux_dir.as_path()),
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
|
@ -1050,8 +1051,8 @@ impl<'test> TestCx<'test> {
|
|||
|
||||
self.compose_and_run(
|
||||
program,
|
||||
self.config.run_lib_path.to_str().unwrap(),
|
||||
Some(aux_dir.to_str().unwrap()),
|
||||
self.config.run_lib_path.as_path(),
|
||||
Some(aux_dir.as_path()),
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
|
@ -1197,8 +1198,8 @@ impl<'test> TestCx<'test> {
|
|||
self.props.unset_rustc_env.iter().fold(&mut rustc, Command::env_remove);
|
||||
self.compose_and_run(
|
||||
rustc,
|
||||
self.config.compile_lib_path.to_str().unwrap(),
|
||||
Some(aux_dir.to_str().unwrap()),
|
||||
self.config.compile_lib_path.as_path(),
|
||||
Some(aux_dir.as_path()),
|
||||
input,
|
||||
)
|
||||
}
|
||||
|
|
@ -1219,8 +1220,7 @@ impl<'test> TestCx<'test> {
|
|||
rustc.args(&["--crate-type", "rlib"]);
|
||||
rustc.arg("-Cpanic=abort");
|
||||
|
||||
let res =
|
||||
self.compose_and_run(rustc, self.config.compile_lib_path.to_str().unwrap(), None, None);
|
||||
let res = self.compose_and_run(rustc, self.config.compile_lib_path.as_path(), None, None);
|
||||
if !res.status.success() {
|
||||
self.fatal_proc_rec(
|
||||
&format!(
|
||||
|
|
@ -1332,8 +1332,8 @@ impl<'test> TestCx<'test> {
|
|||
|
||||
let auxres = aux_cx.compose_and_run(
|
||||
aux_rustc,
|
||||
aux_cx.config.compile_lib_path.to_str().unwrap(),
|
||||
Some(aux_dir.to_str().unwrap()),
|
||||
aux_cx.config.compile_lib_path.as_path(),
|
||||
Some(aux_dir.as_path()),
|
||||
None,
|
||||
);
|
||||
if !auxres.status.success() {
|
||||
|
|
@ -1373,8 +1373,8 @@ impl<'test> TestCx<'test> {
|
|||
fn compose_and_run(
|
||||
&self,
|
||||
mut command: Command,
|
||||
lib_path: &str,
|
||||
aux_path: Option<&str>,
|
||||
lib_path: &Path,
|
||||
aux_path: Option<&Path>,
|
||||
input: Option<String>,
|
||||
) -> ProcRes {
|
||||
let cmdline = {
|
||||
|
|
@ -1806,7 +1806,7 @@ impl<'test> TestCx<'test> {
|
|||
}
|
||||
}
|
||||
|
||||
fn make_cmdline(&self, command: &Command, libpath: &str) -> String {
|
||||
fn make_cmdline(&self, command: &Command, libpath: &Path) -> String {
|
||||
use crate::util;
|
||||
|
||||
// Linux and mac don't require adjusting the library search path
|
||||
|
|
@ -1819,7 +1819,7 @@ impl<'test> TestCx<'test> {
|
|||
format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path))
|
||||
}
|
||||
|
||||
format!("{} {:?}", lib_path_cmd_prefix(libpath), command)
|
||||
format!("{} {:?}", lib_path_cmd_prefix(libpath.to_str().unwrap()), command)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1980,7 +1980,8 @@ impl<'test> TestCx<'test> {
|
|||
// Add custom flags supplied by the `filecheck-flags:` test header.
|
||||
filecheck.args(&self.props.filecheck_flags);
|
||||
|
||||
self.compose_and_run(filecheck, "", None, None)
|
||||
// FIXME(jieyouxu): don't pass an empty Path
|
||||
self.compose_and_run(filecheck, Path::new(""), None, None)
|
||||
}
|
||||
|
||||
fn charset() -> &'static str {
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ impl TestCx<'_> {
|
|||
|
||||
let debugger_run_result = self.compose_and_run(
|
||||
cdb,
|
||||
self.config.run_lib_path.to_str().unwrap(),
|
||||
self.config.run_lib_path.as_path(),
|
||||
None, // aux_path
|
||||
None, // input
|
||||
);
|
||||
|
|
@ -241,7 +241,8 @@ impl TestCx<'_> {
|
|||
let cmdline = {
|
||||
let mut gdb = Command::new(&format!("{}-gdb", self.config.target));
|
||||
gdb.args(debugger_opts);
|
||||
let cmdline = self.make_cmdline(&gdb, "");
|
||||
// FIXME(jieyouxu): don't pass an empty Path
|
||||
let cmdline = self.make_cmdline(&gdb, Path::new(""));
|
||||
logv(self.config, format!("executing {}", cmdline));
|
||||
cmdline
|
||||
};
|
||||
|
|
@ -340,7 +341,7 @@ impl TestCx<'_> {
|
|||
gdb.args(debugger_opts).env("PYTHONPATH", pythonpath);
|
||||
|
||||
debugger_run_result =
|
||||
self.compose_and_run(gdb, self.config.run_lib_path.to_str().unwrap(), None, None);
|
||||
self.compose_and_run(gdb, self.config.run_lib_path.as_path(), None, None);
|
||||
}
|
||||
|
||||
if !debugger_run_result.status.success() {
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
|
|||
let num_failed = sync::IntoDynSyncSend(AtomicU32::new(0));
|
||||
sync::par_for_each_in(many_seeds.seeds.clone(), |seed| {
|
||||
let mut config = config.clone();
|
||||
config.seed = Some(seed.into());
|
||||
config.seed = Some((*seed).into());
|
||||
eprintln!("Trying seed: {seed}");
|
||||
let return_code = miri::eval_entry(tcx, entry_def_id, entry_type, config)
|
||||
.unwrap_or(rustc_driver::EXIT_FAILURE);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
use std::mem::{size_of, align_of};
|
||||
|
||||
// See <https://github.com/rust-lang/rust/issues/134713>
|
||||
|
||||
#[repr(C)]
|
||||
struct Foo(usize, u8);
|
||||
|
||||
fn main() {
|
||||
let buf1: [usize; 2] = [1000, 2000];
|
||||
let buf2: [usize; 2] = [3000, 4000];
|
||||
|
||||
// Foo and [usize; 2] have the same size and alignment,
|
||||
// so swap_nonoverlapping should treat them the same
|
||||
assert_eq!(size_of::<Foo>(), size_of::<[usize; 2]>());
|
||||
assert_eq!(align_of::<Foo>(), align_of::<[usize; 2]>());
|
||||
|
||||
let mut b1 = buf1;
|
||||
let mut b2 = buf2;
|
||||
// Safety: b1 and b2 are distinct local variables,
|
||||
// with the same size and alignment as Foo.
|
||||
unsafe {
|
||||
std::ptr::swap_nonoverlapping(
|
||||
b1.as_mut_ptr().cast::<Foo>(),
|
||||
b2.as_mut_ptr().cast::<Foo>(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
assert_eq!(b1, buf2);
|
||||
assert_eq!(b2, buf1);
|
||||
}
|
||||
|
|
@ -361,7 +361,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
|
|||
"rustc-demangle",
|
||||
"rustc-hash",
|
||||
"rustc-literal-escaper",
|
||||
"rustc-rayon",
|
||||
"rustc-rayon-core",
|
||||
"rustc-stable-hash",
|
||||
"rustc_apfloat",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue