mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-16 14:07:04 +00:00
Merge f1d0b9c645
into 65fa0ab924
This commit is contained in:
commit
aaf546e8e5
@ -1212,7 +1212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide 0.8.7",
|
||||
"miniz_oxide 0.8.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2282,9 +2282,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.7"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
|
||||
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
@ -176,9 +176,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.7"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
|
||||
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
"compiler_builtins",
|
||||
|
@ -61,52 +61,4 @@ impl bool {
|
||||
pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
|
||||
if self { Some(f()) } else { None }
|
||||
}
|
||||
|
||||
/// Returns either `true_val` or `false_val` depending on the value of
|
||||
/// `self`, with a hint to the compiler that `self` is unlikely
|
||||
/// to be correctly predicted by a CPU’s branch predictor.
|
||||
///
|
||||
/// This method is functionally equivalent to
|
||||
/// ```ignore (this is just for illustrative purposes)
|
||||
/// fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
|
||||
/// if b { true_val } else { false_val }
|
||||
/// }
|
||||
/// ```
|
||||
/// but might generate different assembly. In particular, on platforms with
|
||||
/// a conditional move or select instruction (like `cmov` on x86 or `csel`
|
||||
/// on ARM) the optimizer might use these instructions to avoid branches,
|
||||
/// which can benefit performance if the branch predictor is struggling
|
||||
/// with predicting `condition`, such as in an implementation of binary
|
||||
/// search.
|
||||
///
|
||||
/// Note however that this lowering is not guaranteed (on any platform) and
|
||||
/// should not be relied upon when trying to write constant-time code. Also
|
||||
/// be aware that this lowering might *decrease* performance if `condition`
|
||||
/// is well-predictable. It is advisable to perform benchmarks to tell if
|
||||
/// this function is useful.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Distribute values evenly between two buckets:
|
||||
/// ```
|
||||
/// #![feature(select_unpredictable)]
|
||||
///
|
||||
/// use std::hash::BuildHasher;
|
||||
///
|
||||
/// fn append<H: BuildHasher>(hasher: &H, v: i32, bucket_one: &mut Vec<i32>, bucket_two: &mut Vec<i32>) {
|
||||
/// let hash = hasher.hash_one(&v);
|
||||
/// let bucket = (hash % 2 == 0).select_unpredictable(bucket_one, bucket_two);
|
||||
/// bucket.push(v);
|
||||
/// }
|
||||
/// # let hasher = std::collections::hash_map::RandomState::new();
|
||||
/// # let mut bucket_one = Vec::new();
|
||||
/// # let mut bucket_two = Vec::new();
|
||||
/// # append(&hasher, 42, &mut bucket_one, &mut bucket_two);
|
||||
/// # assert_eq!(bucket_one.len() + bucket_two.len(), 1);
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[unstable(feature = "select_unpredictable", issue = "133962")]
|
||||
pub fn select_unpredictable<T>(self, true_val: T, false_val: T) -> T {
|
||||
crate::intrinsics::select_unpredictable(self, true_val, false_val)
|
||||
}
|
||||
}
|
||||
|
@ -734,3 +734,52 @@ pub const fn unlikely(b: bool) -> bool {
|
||||
pub const fn cold_path() {
|
||||
crate::intrinsics::cold_path()
|
||||
}
|
||||
|
||||
/// Returns either `true_val` or `false_val` depending on the value of `b`,
|
||||
/// with a hint to the compiler that `b` is unlikely to be correctly
|
||||
/// predicted by a CPU’s branch predictor.
|
||||
///
|
||||
/// This method is functionally equivalent to
|
||||
/// ```ignore (this is just for illustrative purposes)
|
||||
/// fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
|
||||
/// if b { true_val } else { false_val }
|
||||
/// }
|
||||
/// ```
|
||||
/// but might generate different assembly. In particular, on platforms with
|
||||
/// a conditional move or select instruction (like `cmov` on x86 or `csel`
|
||||
/// on ARM) the optimizer might use these instructions to avoid branches,
|
||||
/// which can benefit performance if the branch predictor is struggling
|
||||
/// with predicting `condition`, such as in an implementation of binary
|
||||
/// search.
|
||||
///
|
||||
/// Note however that this lowering is not guaranteed (on any platform) and
|
||||
/// should not be relied upon when trying to write constant-time code. Also
|
||||
/// be aware that this lowering might *decrease* performance if `condition`
|
||||
/// is well-predictable. It is advisable to perform benchmarks to tell if
|
||||
/// this function is useful.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Distribute values evenly between two buckets:
|
||||
/// ```
|
||||
/// #![feature(select_unpredictable)]
|
||||
///
|
||||
/// use std::hash::BuildHasher;
|
||||
/// use std::hint;
|
||||
///
|
||||
/// fn append<H: BuildHasher>(hasher: &H, v: i32, bucket_one: &mut Vec<i32>, bucket_two: &mut Vec<i32>) {
|
||||
/// let hash = hasher.hash_one(&v);
|
||||
/// let bucket = hint::select_unpredictable(hash % 2 == 0, bucket_one, bucket_two);
|
||||
/// bucket.push(v);
|
||||
/// }
|
||||
/// # let hasher = std::collections::hash_map::RandomState::new();
|
||||
/// # let mut bucket_one = Vec::new();
|
||||
/// # let mut bucket_two = Vec::new();
|
||||
/// # append(&hasher, 42, &mut bucket_one, &mut bucket_two);
|
||||
/// # assert_eq!(bucket_one.len() + bucket_two.len(), 1);
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[unstable(feature = "select_unpredictable", issue = "133962")]
|
||||
pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
|
||||
crate::intrinsics::select_unpredictable(b, true_val, false_val)
|
||||
}
|
||||
|
@ -1326,7 +1326,7 @@ pub const fn unlikely(b: bool) -> bool {
|
||||
/// Therefore, implementations must not require the user to uphold
|
||||
/// any safety invariants.
|
||||
///
|
||||
/// The public form of this instrinsic is [`bool::select_unpredictable`].
|
||||
/// The public form of this instrinsic is [`core::hint::select_unpredictable`].
|
||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
|
@ -2822,7 +2822,7 @@ impl<T> [T] {
|
||||
// Binary search interacts poorly with branch prediction, so force
|
||||
// the compiler to use conditional moves if supported by the target
|
||||
// architecture.
|
||||
base = (cmp == Greater).select_unpredictable(base, mid);
|
||||
base = hint::select_unpredictable(cmp == Greater, base, mid);
|
||||
|
||||
// This is imprecise in the case where `size` is odd and the
|
||||
// comparison returns Greater: the mid element still gets included
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use crate::mem::{self, ManuallyDrop, MaybeUninit};
|
||||
use crate::slice::sort::shared::FreezeMarker;
|
||||
use crate::{intrinsics, ptr, slice};
|
||||
use crate::{hint, intrinsics, ptr, slice};
|
||||
|
||||
// It's important to differentiate between SMALL_SORT_THRESHOLD performance for
|
||||
// small slices and small-sort performance sorting small sub-slices as part of
|
||||
@ -408,8 +408,8 @@ where
|
||||
// }
|
||||
|
||||
// The goal is to generate cmov instructions here.
|
||||
let v_a_swap = should_swap.select_unpredictable(v_b, v_a);
|
||||
let v_b_swap = should_swap.select_unpredictable(v_a, v_b);
|
||||
let v_a_swap = hint::select_unpredictable(should_swap, v_b, v_a);
|
||||
let v_b_swap = hint::select_unpredictable(should_swap, v_a, v_b);
|
||||
|
||||
let v_b_swap_tmp = ManuallyDrop::new(ptr::read(v_b_swap));
|
||||
ptr::copy(v_a_swap, v_a, 1);
|
||||
@ -640,15 +640,15 @@ pub unsafe fn sort4_stable<T, F: FnMut(&T, &T) -> bool>(
|
||||
// 1, 1 | c b a d
|
||||
let c3 = is_less(&*c, &*a);
|
||||
let c4 = is_less(&*d, &*b);
|
||||
let min = c3.select_unpredictable(c, a);
|
||||
let max = c4.select_unpredictable(b, d);
|
||||
let unknown_left = c3.select_unpredictable(a, c4.select_unpredictable(c, b));
|
||||
let unknown_right = c4.select_unpredictable(d, c3.select_unpredictable(b, c));
|
||||
let min = hint::select_unpredictable(c3, c, a);
|
||||
let max = hint::select_unpredictable(c4, b, d);
|
||||
let unknown_left = hint::select_unpredictable(c3, a, hint::select_unpredictable(c4, c, b));
|
||||
let unknown_right = hint::select_unpredictable(c4, d, hint::select_unpredictable(c3, b, c));
|
||||
|
||||
// Sort the last two unknown elements.
|
||||
let c5 = is_less(&*unknown_right, &*unknown_left);
|
||||
let lo = c5.select_unpredictable(unknown_right, unknown_left);
|
||||
let hi = c5.select_unpredictable(unknown_left, unknown_right);
|
||||
let lo = hint::select_unpredictable(c5, unknown_right, unknown_left);
|
||||
let hi = hint::select_unpredictable(c5, unknown_left, unknown_right);
|
||||
|
||||
ptr::copy_nonoverlapping(min, dst, 1);
|
||||
ptr::copy_nonoverlapping(lo, dst.add(1), 1);
|
||||
|
@ -9,8 +9,14 @@ use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
if let Ok(rt) = tracked_env_var("LLVM_PROFILER_RT_LIB") {
|
||||
println!("cargo::rustc-link-lib=static:+verbatim={rt}");
|
||||
return;
|
||||
let rt = PathBuf::from(rt);
|
||||
if let Some(lib) = rt.file_name() {
|
||||
if let Some(dir) = rt.parent() {
|
||||
println!("cargo::rustc-link-search=native={}", dir.display());
|
||||
}
|
||||
println!("cargo::rustc-link-lib=static:+verbatim={}", lib.to_str().unwrap());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let target_os = env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS was not set");
|
||||
|
43
library/std/src/sys/args/common.rs
Normal file
43
library/std/src/sys/args/common.rs
Normal file
@ -0,0 +1,43 @@
|
||||
use crate::ffi::OsString;
|
||||
use crate::{fmt, vec};
|
||||
|
||||
pub struct Args {
|
||||
iter: vec::IntoIter<OsString>,
|
||||
}
|
||||
|
||||
impl !Send for Args {}
|
||||
impl !Sync for Args {}
|
||||
|
||||
impl Args {
|
||||
pub(super) fn new(args: Vec<OsString>) -> Self {
|
||||
Args { iter: args.into_iter() }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Args {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.iter.as_slice().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> {
|
||||
self.iter.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
fn len(&self) -> usize {
|
||||
self.iter.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<OsString> {
|
||||
self.iter.next_back()
|
||||
}
|
||||
}
|
@ -1,8 +1,12 @@
|
||||
use crate::ffi::{CStr, OsString, c_char};
|
||||
use crate::os::hermit::ffi::OsStringExt;
|
||||
use crate::ptr;
|
||||
use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
|
||||
use crate::sync::atomic::{AtomicIsize, AtomicPtr};
|
||||
use crate::{fmt, ptr, vec};
|
||||
|
||||
#[path = "common.rs"]
|
||||
mod common;
|
||||
pub use common::Args;
|
||||
|
||||
static ARGC: AtomicIsize = AtomicIsize::new(0);
|
||||
static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
|
||||
@ -27,40 +31,5 @@ pub fn args() -> Args {
|
||||
})
|
||||
.collect();
|
||||
|
||||
Args { iter: args.into_iter() }
|
||||
}
|
||||
|
||||
pub struct Args {
|
||||
iter: vec::IntoIter<OsString>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Args {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.iter.as_slice().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl !Send for Args {}
|
||||
impl !Sync for Args {}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> {
|
||||
self.iter.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
fn len(&self) -> usize {
|
||||
self.iter.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<OsString> {
|
||||
self.iter.next_back()
|
||||
}
|
||||
Args::new(args)
|
||||
}
|
34
library/std/src/sys/args/mod.rs
Normal file
34
library/std/src/sys/args/mod.rs
Normal file
@ -0,0 +1,34 @@
|
||||
//! Platform-dependent command line arguments abstraction.
|
||||
|
||||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))))] {
|
||||
mod unix;
|
||||
pub use unix::*;
|
||||
} else if #[cfg(target_family = "windows")] {
|
||||
mod windows;
|
||||
pub use windows::*;
|
||||
} else if #[cfg(target_os = "hermit")] {
|
||||
mod hermit;
|
||||
pub use hermit::*;
|
||||
} else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
|
||||
mod sgx;
|
||||
pub use sgx::*;
|
||||
} else if #[cfg(target_os = "uefi")] {
|
||||
mod uefi;
|
||||
pub use uefi::*;
|
||||
} else if #[cfg(target_os = "wasi")] {
|
||||
mod wasi;
|
||||
pub use wasi::*;
|
||||
} else if #[cfg(target_os = "xous")] {
|
||||
mod xous;
|
||||
pub use xous::*;
|
||||
} else if #[cfg(target_os = "zkvm")] {
|
||||
mod zkvm;
|
||||
pub use zkvm::*;
|
||||
} else {
|
||||
mod unsupported;
|
||||
pub use unsupported::*;
|
||||
}
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
use super::abi::usercalls::alloc;
|
||||
use super::abi::usercalls::raw::ByteBuffer;
|
||||
#![allow(fuzzy_provenance_casts)] // FIXME: this module systematically confuses pointers and integers
|
||||
|
||||
use crate::ffi::OsString;
|
||||
use crate::sync::atomic::{AtomicUsize, Ordering};
|
||||
use crate::sys::os_str::Buf;
|
||||
use crate::sys::pal::abi::usercalls::alloc;
|
||||
use crate::sys::pal::abi::usercalls::raw::ByteBuffer;
|
||||
use crate::sys_common::FromInner;
|
||||
use crate::{fmt, slice};
|
||||
|
@ -1,14 +1,13 @@
|
||||
use r_efi::protocols::loaded_image;
|
||||
|
||||
use super::helpers;
|
||||
use crate::env::current_exe;
|
||||
use crate::ffi::OsString;
|
||||
use crate::iter::Iterator;
|
||||
use crate::{fmt, vec};
|
||||
use crate::sys::pal::helpers;
|
||||
|
||||
pub struct Args {
|
||||
parsed_args_list: vec::IntoIter<OsString>,
|
||||
}
|
||||
#[path = "common.rs"]
|
||||
mod common;
|
||||
pub use common::Args;
|
||||
|
||||
pub fn args() -> Args {
|
||||
let lazy_current_exe = || Vec::from([current_exe().map(Into::into).unwrap_or_default()]);
|
||||
@ -22,51 +21,17 @@ pub fn args() -> Args {
|
||||
let lp_size = unsafe { (*protocol.as_ptr()).load_options_size } as usize;
|
||||
// Break if we are sure that it cannot be UTF-16
|
||||
if lp_size < size_of::<u16>() || lp_size % size_of::<u16>() != 0 {
|
||||
return Args { parsed_args_list: lazy_current_exe().into_iter() };
|
||||
return Args::new(lazy_current_exe());
|
||||
}
|
||||
let lp_size = lp_size / size_of::<u16>();
|
||||
|
||||
let lp_cmd_line = unsafe { (*protocol.as_ptr()).load_options as *const u16 };
|
||||
if !lp_cmd_line.is_aligned() {
|
||||
return Args { parsed_args_list: lazy_current_exe().into_iter() };
|
||||
return Args::new(lazy_current_exe());
|
||||
}
|
||||
let lp_cmd_line = unsafe { crate::slice::from_raw_parts(lp_cmd_line, lp_size) };
|
||||
|
||||
Args {
|
||||
parsed_args_list: parse_lp_cmd_line(lp_cmd_line)
|
||||
.unwrap_or_else(lazy_current_exe)
|
||||
.into_iter(),
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Args {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.parsed_args_list.as_slice().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
|
||||
fn next(&mut self) -> Option<OsString> {
|
||||
self.parsed_args_list.next()
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.parsed_args_list.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
fn len(&self) -> usize {
|
||||
self.parsed_args_list.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<OsString> {
|
||||
self.parsed_args_list.next_back()
|
||||
}
|
||||
Args::new(parse_lp_cmd_line(lp_cmd_line).unwrap_or_else(lazy_current_exe))
|
||||
}
|
||||
|
||||
/// Implements the UEFI command-line argument parsing algorithm.
|
@ -5,13 +5,16 @@
|
||||
|
||||
#![allow(dead_code)] // runtime init functions not used during testing
|
||||
|
||||
use crate::ffi::{CStr, OsString};
|
||||
use crate::ffi::CStr;
|
||||
use crate::os::unix::ffi::OsStringExt;
|
||||
use crate::{fmt, vec};
|
||||
|
||||
#[path = "common.rs"]
|
||||
mod common;
|
||||
pub use common::Args;
|
||||
|
||||
/// One-time global initialization.
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8) {
|
||||
imp::init(argc, argv)
|
||||
unsafe { imp::init(argc, argv) }
|
||||
}
|
||||
|
||||
/// Returns the command line arguments
|
||||
@ -55,42 +58,7 @@ pub fn args() -> Args {
|
||||
vec.push(OsStringExt::from_vec(cstr.to_bytes().to_vec()));
|
||||
}
|
||||
|
||||
Args { iter: vec.into_iter() }
|
||||
}
|
||||
|
||||
pub struct Args {
|
||||
iter: vec::IntoIter<OsString>,
|
||||
}
|
||||
|
||||
impl !Send for Args {}
|
||||
impl !Sync for Args {}
|
||||
|
||||
impl fmt::Debug for Args {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.iter.as_slice().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> {
|
||||
self.iter.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
fn len(&self) -> usize {
|
||||
self.iter.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<OsString> {
|
||||
self.iter.next_back()
|
||||
}
|
||||
Args::new(vec)
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
@ -141,7 +109,7 @@ mod imp {
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8) {
|
||||
// on GNU/Linux if we are main then we will init argv and argc twice, it "duplicates work"
|
||||
// BUT edge-cases are real: only using .init_array can break most emulators, dlopen, etc.
|
||||
really_init(argc, argv);
|
||||
unsafe { really_init(argc, argv) };
|
||||
}
|
||||
|
||||
/// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension.
|
||||
@ -159,9 +127,7 @@ mod imp {
|
||||
argv: *const *const u8,
|
||||
_envp: *const *const u8,
|
||||
) {
|
||||
unsafe {
|
||||
really_init(argc as isize, argv);
|
||||
}
|
||||
unsafe { really_init(argc as isize, argv) };
|
||||
}
|
||||
init_wrapper
|
||||
};
|
||||
@ -228,16 +194,3 @@ mod imp {
|
||||
(argc as isize, argv.cast())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "espidf", target_os = "vita"))]
|
||||
mod imp {
|
||||
use crate::ffi::c_char;
|
||||
use crate::ptr;
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
|
||||
|
||||
pub fn argc_argv() -> (isize, *const *const c_char) {
|
||||
(0, ptr::null())
|
||||
}
|
||||
}
|
29
library/std/src/sys/args/wasi.rs
Normal file
29
library/std/src/sys/args/wasi.rs
Normal file
@ -0,0 +1,29 @@
|
||||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use crate::ffi::{CStr, OsStr, OsString};
|
||||
use crate::os::wasi::ffi::OsStrExt;
|
||||
|
||||
#[path = "common.rs"]
|
||||
mod common;
|
||||
pub use common::Args;
|
||||
|
||||
/// Returns the command line arguments
|
||||
pub fn args() -> Args {
|
||||
Args::new(maybe_args().unwrap_or(Vec::new()))
|
||||
}
|
||||
|
||||
fn maybe_args() -> Option<Vec<OsString>> {
|
||||
unsafe {
|
||||
let (argc, buf_size) = wasi::args_sizes_get().ok()?;
|
||||
let mut argv = Vec::with_capacity(argc);
|
||||
let mut buf = Vec::with_capacity(buf_size);
|
||||
wasi::args_get(argv.as_mut_ptr(), buf.as_mut_ptr()).ok()?;
|
||||
argv.set_len(argc);
|
||||
let mut ret = Vec::with_capacity(argc);
|
||||
for ptr in argv {
|
||||
let s = CStr::from_ptr(ptr.cast());
|
||||
ret.push(OsStr::from_bytes(s.to_bytes()).to_owned());
|
||||
}
|
||||
Some(ret)
|
||||
}
|
||||
}
|
@ -6,17 +6,21 @@
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use super::ensure_no_nuls;
|
||||
use super::os::current_exe;
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::num::NonZero;
|
||||
use crate::os::windows::prelude::*;
|
||||
use crate::path::{Path, PathBuf};
|
||||
use crate::sys::pal::os::current_exe;
|
||||
use crate::sys::pal::{ensure_no_nuls, fill_utf16_buf};
|
||||
use crate::sys::path::get_long_path;
|
||||
use crate::sys::{c, to_u16s};
|
||||
use crate::sys_common::AsInner;
|
||||
use crate::sys_common::wstr::WStrUnits;
|
||||
use crate::{fmt, io, iter, vec};
|
||||
use crate::{io, iter, ptr};
|
||||
|
||||
#[path = "common.rs"]
|
||||
mod common;
|
||||
pub use common::Args;
|
||||
|
||||
pub fn args() -> Args {
|
||||
// SAFETY: `GetCommandLineW` returns a pointer to a null terminated UTF-16
|
||||
@ -27,7 +31,7 @@ pub fn args() -> Args {
|
||||
current_exe().map(PathBuf::into_os_string).unwrap_or_else(|_| OsString::new())
|
||||
});
|
||||
|
||||
Args { parsed_args_list: parsed_args_list.into_iter() }
|
||||
Args::new(parsed_args_list)
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,38 +157,6 @@ fn parse_lp_cmd_line<'a, F: Fn() -> OsString>(
|
||||
ret_val
|
||||
}
|
||||
|
||||
pub struct Args {
|
||||
parsed_args_list: vec::IntoIter<OsString>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Args {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.parsed_args_list.as_slice().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> {
|
||||
self.parsed_args_list.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.parsed_args_list.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<OsString> {
|
||||
self.parsed_args_list.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
fn len(&self) -> usize {
|
||||
self.parsed_args_list.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum Arg {
|
||||
/// Add quotes (if needed)
|
||||
@ -384,9 +356,6 @@ pub(crate) fn to_user_path(path: &Path) -> io::Result<Vec<u16>> {
|
||||
from_wide_to_user_path(to_u16s(path)?)
|
||||
}
|
||||
pub(crate) fn from_wide_to_user_path(mut path: Vec<u16>) -> io::Result<Vec<u16>> {
|
||||
use super::fill_utf16_buf;
|
||||
use crate::ptr;
|
||||
|
||||
// UTF-16 encoded code points, used in parsing and building UTF-16 paths.
|
||||
// All of these are in the ASCII range so they can be cast directly to `u16`.
|
||||
const SEP: u16 = b'\\' as _;
|
23
library/std/src/sys/args/xous.rs
Normal file
23
library/std/src/sys/args/xous.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use crate::sys::pal::os::get_application_parameters;
|
||||
use crate::sys::pal::os::params::ArgumentList;
|
||||
|
||||
#[path = "common.rs"]
|
||||
mod common;
|
||||
pub use common::Args;
|
||||
|
||||
pub fn args() -> Args {
|
||||
let Some(params) = get_application_parameters() else {
|
||||
return Args::new(vec![]);
|
||||
};
|
||||
|
||||
for param in params {
|
||||
if let Ok(args) = ArgumentList::try_from(¶m) {
|
||||
let mut parsed_args = vec![];
|
||||
for arg in args {
|
||||
parsed_args.push(arg.into());
|
||||
}
|
||||
return Args::new(parsed_args);
|
||||
}
|
||||
}
|
||||
Args::new(vec![])
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
use super::{WORD_SIZE, abi};
|
||||
use crate::ffi::OsString;
|
||||
use crate::fmt;
|
||||
use crate::sys::os_str;
|
||||
use crate::sys::pal::{WORD_SIZE, abi};
|
||||
use crate::sys_common::FromInner;
|
||||
|
||||
pub struct Args {
|
@ -71,9 +71,11 @@ const fn max_iov() -> usize {
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "espidf",
|
||||
target_os = "freebsd",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "nuttx",
|
||||
target_os = "nto",
|
||||
target_os = "openbsd",
|
||||
target_os = "horizon",
|
||||
|
@ -20,6 +20,7 @@ cfg_if::cfg_if! {
|
||||
mod windows;
|
||||
use windows as imp;
|
||||
pub use windows::{symlink_inner, junction_point};
|
||||
use crate::sys::path::with_native_path;
|
||||
} else if #[cfg(target_os = "hermit")] {
|
||||
mod hermit;
|
||||
use hermit as imp;
|
||||
@ -39,7 +40,7 @@ cfg_if::cfg_if! {
|
||||
}
|
||||
|
||||
// FIXME: Replace this with platform-specific path conversion functions.
|
||||
#[cfg(not(target_family = "unix"))]
|
||||
#[cfg(not(any(target_family = "unix", target_os = "windows")))]
|
||||
#[inline]
|
||||
pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&Path) -> io::Result<T>) -> io::Result<T> {
|
||||
f(path)
|
||||
@ -51,7 +52,7 @@ pub use imp::{
|
||||
};
|
||||
|
||||
pub fn read_dir(path: &Path) -> io::Result<ReadDir> {
|
||||
// FIXME: use with_native_path
|
||||
// FIXME: use with_native_path on all platforms
|
||||
imp::readdir(path)
|
||||
}
|
||||
|
||||
@ -68,8 +69,11 @@ pub fn remove_dir(path: &Path) -> io::Result<()> {
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
|
||||
// FIXME: use with_native_path
|
||||
imp::remove_dir_all(path)
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(not(windows))]
|
||||
return imp::remove_dir_all(path);
|
||||
#[cfg(windows)]
|
||||
with_native_path(path, &imp::remove_dir_all)
|
||||
}
|
||||
|
||||
pub fn read_link(path: &Path) -> io::Result<PathBuf> {
|
||||
@ -77,6 +81,10 @@ pub fn read_link(path: &Path) -> io::Result<PathBuf> {
|
||||
}
|
||||
|
||||
pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(windows)]
|
||||
return imp::symlink(original, link);
|
||||
#[cfg(not(windows))]
|
||||
with_native_path(original, &|original| {
|
||||
with_native_path(link, &|link| imp::symlink(original, link))
|
||||
})
|
||||
@ -105,11 +113,17 @@ pub fn canonicalize(path: &Path) -> io::Result<PathBuf> {
|
||||
}
|
||||
|
||||
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
||||
// FIXME: use with_native_path
|
||||
imp::copy(from, to)
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(not(windows))]
|
||||
return imp::copy(from, to);
|
||||
#[cfg(windows)]
|
||||
with_native_path(from, &|from| with_native_path(to, &|to| imp::copy(from, to)))
|
||||
}
|
||||
|
||||
pub fn exists(path: &Path) -> io::Result<bool> {
|
||||
// FIXME: use with_native_path
|
||||
imp::exists(path)
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(not(windows))]
|
||||
return imp::exists(path);
|
||||
#[cfg(windows)]
|
||||
with_native_path(path, &imp::exists)
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ use crate::sync::Arc;
|
||||
use crate::sys::handle::Handle;
|
||||
use crate::sys::pal::api::{self, WinError, set_file_information_by_handle};
|
||||
use crate::sys::pal::{IoResult, fill_utf16_buf, to_u16s, truncate_utf16_at_nul};
|
||||
use crate::sys::path::maybe_verbatim;
|
||||
use crate::sys::path::{WCStr, maybe_verbatim};
|
||||
use crate::sys::time::SystemTime;
|
||||
use crate::sys::{Align8, c, cvt};
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
@ -298,10 +298,12 @@ impl OpenOptions {
|
||||
impl File {
|
||||
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
|
||||
let path = maybe_verbatim(path)?;
|
||||
// SAFETY: maybe_verbatim returns null-terminated strings
|
||||
let path = unsafe { WCStr::from_wchars_with_null_unchecked(&path) };
|
||||
Self::open_native(&path, opts)
|
||||
}
|
||||
|
||||
fn open_native(path: &[u16], opts: &OpenOptions) -> io::Result<File> {
|
||||
fn open_native(path: &WCStr, opts: &OpenOptions) -> io::Result<File> {
|
||||
let creation = opts.get_creation_mode()?;
|
||||
let handle = unsafe {
|
||||
c::CreateFileW(
|
||||
@ -1212,9 +1214,8 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unlink(p: &Path) -> io::Result<()> {
|
||||
let p_u16s = maybe_verbatim(p)?;
|
||||
if unsafe { c::DeleteFileW(p_u16s.as_ptr()) } == 0 {
|
||||
pub fn unlink(path: &WCStr) -> io::Result<()> {
|
||||
if unsafe { c::DeleteFileW(path.as_ptr()) } == 0 {
|
||||
let err = api::get_last_error();
|
||||
// if `DeleteFileW` fails with ERROR_ACCESS_DENIED then try to remove
|
||||
// the file while ignoring the readonly attribute.
|
||||
@ -1223,7 +1224,7 @@ pub fn unlink(p: &Path) -> io::Result<()> {
|
||||
let mut opts = OpenOptions::new();
|
||||
opts.access_mode(c::DELETE);
|
||||
opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT);
|
||||
if let Ok(f) = File::open_native(&p_u16s, &opts) {
|
||||
if let Ok(f) = File::open_native(&path, &opts) {
|
||||
if f.posix_delete().is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
@ -1236,10 +1237,7 @@ pub fn unlink(p: &Path) -> io::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
|
||||
let old = maybe_verbatim(old)?;
|
||||
let new = maybe_verbatim(new)?;
|
||||
|
||||
pub fn rename(old: &WCStr, new: &WCStr) -> io::Result<()> {
|
||||
if unsafe { c::MoveFileExW(old.as_ptr(), new.as_ptr(), c::MOVEFILE_REPLACE_EXISTING) } == 0 {
|
||||
let err = api::get_last_error();
|
||||
// if `MoveFileExW` fails with ERROR_ACCESS_DENIED then try to move
|
||||
@ -1253,7 +1251,8 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
|
||||
|
||||
// Calculate the layout of the `FILE_RENAME_INFO` we pass to `SetFileInformation`
|
||||
// This is a dynamically sized struct so we need to get the position of the last field to calculate the actual size.
|
||||
let Ok(new_len_without_nul_in_bytes): Result<u32, _> = ((new.len() - 1) * 2).try_into()
|
||||
let Ok(new_len_without_nul_in_bytes): Result<u32, _> =
|
||||
((new.count_bytes() - 1) * 2).try_into()
|
||||
else {
|
||||
return Err(err).io_result();
|
||||
};
|
||||
@ -1282,7 +1281,7 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
|
||||
|
||||
new.as_ptr().copy_to_nonoverlapping(
|
||||
(&raw mut (*file_rename_info).FileName).cast::<u16>(),
|
||||
new.len(),
|
||||
new.count_bytes(),
|
||||
);
|
||||
}
|
||||
|
||||
@ -1309,20 +1308,19 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn rmdir(p: &Path) -> io::Result<()> {
|
||||
let p = maybe_verbatim(p)?;
|
||||
pub fn rmdir(p: &WCStr) -> io::Result<()> {
|
||||
cvt(unsafe { c::RemoveDirectoryW(p.as_ptr()) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
|
||||
pub fn remove_dir_all(path: &WCStr) -> io::Result<()> {
|
||||
// Open a file or directory without following symlinks.
|
||||
let mut opts = OpenOptions::new();
|
||||
opts.access_mode(c::FILE_LIST_DIRECTORY);
|
||||
// `FILE_FLAG_BACKUP_SEMANTICS` allows opening directories.
|
||||
// `FILE_FLAG_OPEN_REPARSE_POINT` opens a link instead of its target.
|
||||
opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | c::FILE_FLAG_OPEN_REPARSE_POINT);
|
||||
let file = File::open(path, &opts)?;
|
||||
let file = File::open_native(path, &opts)?;
|
||||
|
||||
// Test if the file is not a directory or a symlink to a directory.
|
||||
if (file.basic_info()?.FileAttributes & c::FILE_ATTRIBUTE_DIRECTORY) == 0 {
|
||||
@ -1333,14 +1331,14 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> {
|
||||
remove_dir_all_iterative(file).io_result()
|
||||
}
|
||||
|
||||
pub fn readlink(path: &Path) -> io::Result<PathBuf> {
|
||||
pub fn readlink(path: &WCStr) -> io::Result<PathBuf> {
|
||||
// Open the link with no access mode, instead of generic read.
|
||||
// By default FILE_LIST_DIRECTORY is denied for the junction "C:\Documents and Settings", so
|
||||
// this is needed for a common case.
|
||||
let mut opts = OpenOptions::new();
|
||||
opts.access_mode(0);
|
||||
opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS);
|
||||
let file = File::open(path, &opts)?;
|
||||
let file = File::open_native(&path, &opts)?;
|
||||
file.readlink()
|
||||
}
|
||||
|
||||
@ -1378,19 +1376,17 @@ pub fn symlink_inner(original: &Path, link: &Path, dir: bool) -> io::Result<()>
|
||||
}
|
||||
|
||||
#[cfg(not(target_vendor = "uwp"))]
|
||||
pub fn link(original: &Path, link: &Path) -> io::Result<()> {
|
||||
let original = maybe_verbatim(original)?;
|
||||
let link = maybe_verbatim(link)?;
|
||||
pub fn link(original: &WCStr, link: &WCStr) -> io::Result<()> {
|
||||
cvt(unsafe { c::CreateHardLinkW(link.as_ptr(), original.as_ptr(), ptr::null_mut()) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_vendor = "uwp")]
|
||||
pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
|
||||
pub fn link(_original: &WCStr, _link: &WCStr) -> io::Result<()> {
|
||||
return Err(io::const_error!(io::ErrorKind::Unsupported, "hard link are not supported on UWP"));
|
||||
}
|
||||
|
||||
pub fn stat(path: &Path) -> io::Result<FileAttr> {
|
||||
pub fn stat(path: &WCStr) -> io::Result<FileAttr> {
|
||||
match metadata(path, ReparsePoint::Follow) {
|
||||
Err(err) if err.raw_os_error() == Some(c::ERROR_CANT_ACCESS_FILE as i32) => {
|
||||
if let Ok(attrs) = lstat(path) {
|
||||
@ -1404,7 +1400,7 @@ pub fn stat(path: &Path) -> io::Result<FileAttr> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lstat(path: &Path) -> io::Result<FileAttr> {
|
||||
pub fn lstat(path: &WCStr) -> io::Result<FileAttr> {
|
||||
metadata(path, ReparsePoint::Open)
|
||||
}
|
||||
|
||||
@ -1420,7 +1416,7 @@ impl ReparsePoint {
|
||||
}
|
||||
}
|
||||
|
||||
fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
|
||||
fn metadata(path: &WCStr, reparse: ReparsePoint) -> io::Result<FileAttr> {
|
||||
let mut opts = OpenOptions::new();
|
||||
// No read or write permissions are necessary
|
||||
opts.access_mode(0);
|
||||
@ -1429,7 +1425,7 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
|
||||
// Attempt to open the file normally.
|
||||
// If that fails with `ERROR_SHARING_VIOLATION` then retry using `FindFirstFileExW`.
|
||||
// If the fallback fails for any reason we return the original error.
|
||||
match File::open(path, &opts) {
|
||||
match File::open_native(&path, &opts) {
|
||||
Ok(file) => file.file_attr(),
|
||||
Err(e)
|
||||
if [Some(c::ERROR_SHARING_VIOLATION as _), Some(c::ERROR_ACCESS_DENIED as _)]
|
||||
@ -1442,8 +1438,6 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
|
||||
// However, there are special system files, such as
|
||||
// `C:\hiberfil.sys`, that are locked in a way that denies even that.
|
||||
unsafe {
|
||||
let path = maybe_verbatim(path)?;
|
||||
|
||||
// `FindFirstFileExW` accepts wildcard file names.
|
||||
// Fortunately wildcards are not valid file names and
|
||||
// `ERROR_SHARING_VIOLATION` means the file exists (but is locked)
|
||||
@ -1482,8 +1476,7 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
|
||||
let p = maybe_verbatim(p)?;
|
||||
pub fn set_perm(p: &WCStr, perm: FilePermissions) -> io::Result<()> {
|
||||
unsafe {
|
||||
cvt(c::SetFileAttributesW(p.as_ptr(), perm.attrs))?;
|
||||
Ok(())
|
||||
@ -1499,17 +1492,17 @@ fn get_path(f: &File) -> io::Result<PathBuf> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
|
||||
pub fn canonicalize(p: &WCStr) -> io::Result<PathBuf> {
|
||||
let mut opts = OpenOptions::new();
|
||||
// No read or write permissions are necessary
|
||||
opts.access_mode(0);
|
||||
// This flag is so we can open directories too
|
||||
opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS);
|
||||
let f = File::open(p, &opts)?;
|
||||
let f = File::open_native(p, &opts)?;
|
||||
get_path(&f)
|
||||
}
|
||||
|
||||
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
||||
pub fn copy(from: &WCStr, to: &WCStr) -> io::Result<u64> {
|
||||
unsafe extern "system" fn callback(
|
||||
_TotalFileSize: i64,
|
||||
_TotalBytesTransferred: i64,
|
||||
@ -1528,13 +1521,11 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
||||
c::PROGRESS_CONTINUE
|
||||
}
|
||||
}
|
||||
let pfrom = maybe_verbatim(from)?;
|
||||
let pto = maybe_verbatim(to)?;
|
||||
let mut size = 0i64;
|
||||
cvt(unsafe {
|
||||
c::CopyFileExW(
|
||||
pfrom.as_ptr(),
|
||||
pto.as_ptr(),
|
||||
from.as_ptr(),
|
||||
to.as_ptr(),
|
||||
Some(callback),
|
||||
(&raw mut size) as *mut _,
|
||||
ptr::null_mut(),
|
||||
@ -1624,14 +1615,14 @@ pub fn junction_point(original: &Path, link: &Path) -> io::Result<()> {
|
||||
}
|
||||
|
||||
// Try to see if a file exists but, unlike `exists`, report I/O errors.
|
||||
pub fn exists(path: &Path) -> io::Result<bool> {
|
||||
pub fn exists(path: &WCStr) -> io::Result<bool> {
|
||||
// Open the file to ensure any symlinks are followed to their target.
|
||||
let mut opts = OpenOptions::new();
|
||||
// No read, write, etc access rights are needed.
|
||||
opts.access_mode(0);
|
||||
// Backup semantics enables opening directories as well as files.
|
||||
opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS);
|
||||
match File::open(path, &opts) {
|
||||
match File::open_native(path, &opts) {
|
||||
Err(e) => match e.kind() {
|
||||
// The file definitely does not exist
|
||||
io::ErrorKind::NotFound => Ok(false),
|
||||
|
@ -9,6 +9,7 @@ mod alloc;
|
||||
mod personality;
|
||||
|
||||
pub mod anonymous_pipe;
|
||||
pub mod args;
|
||||
pub mod backtrace;
|
||||
pub mod cmath;
|
||||
pub mod exit_guard;
|
||||
|
@ -1,5 +1,6 @@
|
||||
use libc::{MSG_PEEK, c_int, c_void, size_t, sockaddr, socklen_t};
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "nuttx")))]
|
||||
use crate::ffi::CStr;
|
||||
use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut};
|
||||
use crate::net::{Shutdown, SocketAddr};
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
use crate::os::raw::c_char;
|
||||
|
||||
pub mod args;
|
||||
pub mod env;
|
||||
pub mod futex;
|
||||
pub mod os;
|
||||
@ -58,7 +57,7 @@ pub extern "C" fn __rust_abort() {
|
||||
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
|
||||
unsafe {
|
||||
args::init(argc, argv);
|
||||
crate::sys::args::init(argc, argv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,6 @@ use crate::io::ErrorKind;
|
||||
use crate::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
pub mod abi;
|
||||
pub mod args;
|
||||
pub mod env;
|
||||
mod libunwind_integration;
|
||||
pub mod os;
|
||||
@ -24,7 +23,7 @@ pub mod waitqueue;
|
||||
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
|
||||
unsafe {
|
||||
args::init(argc, argv);
|
||||
crate::sys::args::init(argc, argv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,6 @@ pub mod itron {
|
||||
use super::unsupported;
|
||||
}
|
||||
|
||||
#[path = "../unsupported/args.rs"]
|
||||
pub mod args;
|
||||
pub mod env;
|
||||
// `error` is `pub(crate)` so that it can be accessed by `itron/error.rs` as
|
||||
// `crate::sys::error`
|
||||
|
@ -6,8 +6,6 @@
|
||||
#![allow(unused_variables)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
#[path = "../unsupported/args.rs"]
|
||||
pub mod args;
|
||||
#[path = "../unsupported/env.rs"]
|
||||
pub mod env;
|
||||
//pub mod fd;
|
||||
|
@ -1,7 +1,5 @@
|
||||
//! System bindings for the Trusty OS.
|
||||
|
||||
#[path = "../unsupported/args.rs"]
|
||||
pub mod args;
|
||||
#[path = "../unsupported/common.rs"]
|
||||
#[deny(unsafe_op_in_unsafe_fn)]
|
||||
mod common;
|
||||
|
@ -13,7 +13,6 @@
|
||||
//! [`OsString`]: crate::ffi::OsString
|
||||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
pub mod args;
|
||||
pub mod env;
|
||||
pub mod helpers;
|
||||
pub mod os;
|
||||
|
@ -6,7 +6,6 @@ use crate::io::ErrorKind;
|
||||
#[macro_use]
|
||||
pub mod weak;
|
||||
|
||||
pub mod args;
|
||||
pub mod env;
|
||||
#[cfg(target_os = "fuchsia")]
|
||||
pub mod fuchsia;
|
||||
@ -27,6 +26,7 @@ pub mod time;
|
||||
pub fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
|
||||
|
||||
#[cfg(not(target_os = "espidf"))]
|
||||
#[cfg_attr(target_os = "vita", allow(unused_variables))]
|
||||
// SAFETY: must be called only once during runtime initialization.
|
||||
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
|
||||
// See `fn init()` in `library/std/src/rt.rs` for docs on `sigpipe`.
|
||||
@ -47,7 +47,8 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
|
||||
reset_sigpipe(sigpipe);
|
||||
|
||||
stack_overflow::init();
|
||||
args::init(argc, argv);
|
||||
#[cfg(not(target_os = "vita"))]
|
||||
crate::sys::args::init(argc, argv);
|
||||
|
||||
// Normally, `thread::spawn` will call `Thread::set_name` but since this thread
|
||||
// already exists, we have to call it ourselves. We only do this on Apple targets
|
||||
|
@ -1,6 +1,5 @@
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
pub mod args;
|
||||
pub mod env;
|
||||
pub mod os;
|
||||
pub mod pipe;
|
||||
|
@ -1,61 +0,0 @@
|
||||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use crate::ffi::{CStr, OsStr, OsString};
|
||||
use crate::os::wasi::ffi::OsStrExt;
|
||||
use crate::{fmt, vec};
|
||||
|
||||
pub struct Args {
|
||||
iter: vec::IntoIter<OsString>,
|
||||
}
|
||||
|
||||
impl !Send for Args {}
|
||||
impl !Sync for Args {}
|
||||
|
||||
/// Returns the command line arguments
|
||||
pub fn args() -> Args {
|
||||
Args { iter: maybe_args().unwrap_or(Vec::new()).into_iter() }
|
||||
}
|
||||
|
||||
fn maybe_args() -> Option<Vec<OsString>> {
|
||||
unsafe {
|
||||
let (argc, buf_size) = wasi::args_sizes_get().ok()?;
|
||||
let mut argv = Vec::with_capacity(argc);
|
||||
let mut buf = Vec::with_capacity(buf_size);
|
||||
wasi::args_get(argv.as_mut_ptr(), buf.as_mut_ptr()).ok()?;
|
||||
argv.set_len(argc);
|
||||
let mut ret = Vec::with_capacity(argc);
|
||||
for ptr in argv {
|
||||
let s = CStr::from_ptr(ptr.cast());
|
||||
ret.push(OsStr::from_bytes(s.to_bytes()).to_owned());
|
||||
}
|
||||
Some(ret)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Args {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.iter.as_slice().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> {
|
||||
self.iter.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
fn len(&self) -> usize {
|
||||
self.iter.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<OsString> {
|
||||
self.iter.next_back()
|
||||
}
|
||||
}
|
@ -13,7 +13,6 @@
|
||||
//! compiling for wasm. That way it's a compile time error for something that's
|
||||
//! guaranteed to be a runtime error!
|
||||
|
||||
pub mod args;
|
||||
pub mod env;
|
||||
#[allow(unused)]
|
||||
#[path = "../wasm/atomics/futex.rs"]
|
||||
|
@ -6,8 +6,6 @@
|
||||
//! To begin with, this target mirrors the wasi target 1 to 1, but over
|
||||
//! time this will change significantly.
|
||||
|
||||
#[path = "../wasi/args.rs"]
|
||||
pub mod args;
|
||||
#[path = "../wasi/env.rs"]
|
||||
pub mod env;
|
||||
#[allow(unused)]
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
#[path = "../unsupported/args.rs"]
|
||||
pub mod args;
|
||||
pub mod env;
|
||||
#[path = "../unsupported/os.rs"]
|
||||
pub mod os;
|
||||
|
@ -14,7 +14,6 @@ pub mod compat;
|
||||
|
||||
pub mod api;
|
||||
|
||||
pub mod args;
|
||||
pub mod c;
|
||||
pub mod env;
|
||||
#[cfg(not(target_vendor = "win7"))]
|
||||
|
@ -1,53 +0,0 @@
|
||||
use crate::ffi::OsString;
|
||||
use crate::sys::pal::xous::os::get_application_parameters;
|
||||
use crate::sys::pal::xous::os::params::ArgumentList;
|
||||
use crate::{fmt, vec};
|
||||
|
||||
pub struct Args {
|
||||
parsed_args_list: vec::IntoIter<OsString>,
|
||||
}
|
||||
|
||||
pub fn args() -> Args {
|
||||
let Some(params) = get_application_parameters() else {
|
||||
return Args { parsed_args_list: vec![].into_iter() };
|
||||
};
|
||||
|
||||
for param in params {
|
||||
if let Ok(args) = ArgumentList::try_from(¶m) {
|
||||
let mut parsed_args = vec![];
|
||||
for arg in args {
|
||||
parsed_args.push(arg.into());
|
||||
}
|
||||
return Args { parsed_args_list: parsed_args.into_iter() };
|
||||
}
|
||||
}
|
||||
Args { parsed_args_list: vec![].into_iter() }
|
||||
}
|
||||
|
||||
impl fmt::Debug for Args {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.parsed_args_list.as_slice().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> {
|
||||
self.parsed_args_list.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.parsed_args_list.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<OsString> {
|
||||
self.parsed_args_list.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
fn len(&self) -> usize {
|
||||
self.parsed_args_list.len()
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
pub mod args;
|
||||
#[path = "../unsupported/env.rs"]
|
||||
pub mod env;
|
||||
pub mod os;
|
||||
|
@ -8,11 +8,9 @@
|
||||
//! will likely change over time.
|
||||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
const WORD_SIZE: usize = size_of::<u32>();
|
||||
pub const WORD_SIZE: usize = size_of::<u32>();
|
||||
|
||||
pub mod abi;
|
||||
#[path = "../zkvm/args.rs"]
|
||||
pub mod args;
|
||||
pub mod env;
|
||||
pub mod os;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
|
@ -10,6 +10,40 @@ mod tests;
|
||||
pub const MAIN_SEP_STR: &str = "\\";
|
||||
pub const MAIN_SEP: char = '\\';
|
||||
|
||||
/// A null terminated wide string.
|
||||
#[repr(transparent)]
|
||||
pub struct WCStr([u16]);
|
||||
|
||||
impl WCStr {
|
||||
/// Convert a slice to a WCStr without checks.
|
||||
///
|
||||
/// Though it is memory safe, the slice should also not contain interior nulls
|
||||
/// as this may lead to unwanted truncation.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The slice must end in a null.
|
||||
pub unsafe fn from_wchars_with_null_unchecked(s: &[u16]) -> &Self {
|
||||
unsafe { &*(s as *const [u16] as *const Self) }
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *const u16 {
|
||||
self.0.as_ptr()
|
||||
}
|
||||
|
||||
pub fn count_bytes(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&WCStr) -> io::Result<T>) -> io::Result<T> {
|
||||
let path = maybe_verbatim(path)?;
|
||||
// SAFETY: maybe_verbatim returns null-terminated strings
|
||||
let path = unsafe { WCStr::from_wchars_with_null_unchecked(&path) };
|
||||
f(path)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_sep_byte(b: u8) -> bool {
|
||||
b == b'/' || b == b'\\'
|
||||
|
@ -666,10 +666,11 @@ fn run_test_in_process(
|
||||
|
||||
io::set_output_capture(None);
|
||||
|
||||
let test_result = match result {
|
||||
Ok(()) => calc_result(&desc, Ok(()), time_opts.as_ref(), exec_time.as_ref()),
|
||||
Err(e) => calc_result(&desc, Err(e.as_ref()), time_opts.as_ref(), exec_time.as_ref()),
|
||||
};
|
||||
// Determine whether the test passed or failed, by comparing its panic
|
||||
// payload (if any) with its `ShouldPanic` value, and by checking for
|
||||
// fatal timeout.
|
||||
let test_result =
|
||||
calc_result(&desc, result.err().as_deref(), time_opts.as_ref(), exec_time.as_ref());
|
||||
let stdout = data.lock().unwrap_or_else(|e| e.into_inner()).to_vec();
|
||||
let message = CompletedTest::new(id, desc, test_result, exec_time, stdout);
|
||||
monitor_ch.send(message).unwrap();
|
||||
@ -741,10 +742,7 @@ fn spawn_test_subprocess(
|
||||
fn run_test_in_spawned_subprocess(desc: TestDesc, runnable_test: RunnableTest) -> ! {
|
||||
let builtin_panic_hook = panic::take_hook();
|
||||
let record_result = Arc::new(move |panic_info: Option<&'_ PanicHookInfo<'_>>| {
|
||||
let test_result = match panic_info {
|
||||
Some(info) => calc_result(&desc, Err(info.payload()), None, None),
|
||||
None => calc_result(&desc, Ok(()), None, None),
|
||||
};
|
||||
let test_result = calc_result(&desc, panic_info.map(|info| info.payload()), None, None);
|
||||
|
||||
// We don't support serializing TrFailedMsg, so just
|
||||
// print the message out to stderr.
|
||||
|
@ -39,15 +39,18 @@ pub enum TestResult {
|
||||
|
||||
/// Creates a `TestResult` depending on the raw result of test execution
|
||||
/// and associated data.
|
||||
pub(crate) fn calc_result<'a>(
|
||||
pub(crate) fn calc_result(
|
||||
desc: &TestDesc,
|
||||
task_result: Result<(), &'a (dyn Any + 'static + Send)>,
|
||||
panic_payload: Option<&(dyn Any + Send)>,
|
||||
time_opts: Option<&time::TestTimeOptions>,
|
||||
exec_time: Option<&time::TestExecTime>,
|
||||
) -> TestResult {
|
||||
let result = match (&desc.should_panic, task_result) {
|
||||
(&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TestResult::TrOk,
|
||||
(&ShouldPanic::YesWithMessage(msg), Err(err)) => {
|
||||
let result = match (desc.should_panic, panic_payload) {
|
||||
// The test did or didn't panic, as expected.
|
||||
(ShouldPanic::No, None) | (ShouldPanic::Yes, Some(_)) => TestResult::TrOk,
|
||||
|
||||
// Check the actual panic message against the expected message.
|
||||
(ShouldPanic::YesWithMessage(msg), Some(err)) => {
|
||||
let maybe_panic_str = err
|
||||
.downcast_ref::<String>()
|
||||
.map(|e| &**e)
|
||||
@ -71,10 +74,14 @@ pub(crate) fn calc_result<'a>(
|
||||
))
|
||||
}
|
||||
}
|
||||
(&ShouldPanic::Yes, Ok(())) | (&ShouldPanic::YesWithMessage(_), Ok(())) => {
|
||||
|
||||
// The test should have panicked, but didn't panic.
|
||||
(ShouldPanic::Yes, None) | (ShouldPanic::YesWithMessage(_), None) => {
|
||||
TestResult::TrFailedMsg("test did not panic as expected".to_string())
|
||||
}
|
||||
_ => TestResult::TrFailed,
|
||||
|
||||
// The test should not have panicked, but did panic.
|
||||
(ShouldPanic::No, Some(_)) => TestResult::TrFailed,
|
||||
};
|
||||
|
||||
// If test is already failed (or allowed to fail), do not change the result.
|
||||
|
@ -563,9 +563,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.5"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
|
||||
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
@ -101,6 +101,7 @@ for more details.
|
||||
| `normalize-stdout` | Normalize actual stdout with a rule `"<raw>" -> "<normalized>"` before comparing against snapshot | `ui`, `incremental` | `"<RAW>" -> "<NORMALIZED>"`, `<RAW>`/`<NORMALIZED>` is regex capture and replace syntax |
|
||||
| `dont-check-compiler-stderr` | Don't check actual compiler stderr vs stderr snapshot | `ui` | N/A |
|
||||
| `dont-check-compiler-stdout` | Don't check actual compiler stdout vs stdout snapshot | `ui` | N/A |
|
||||
| `dont-require-annotations` | Don't require line annotations for the given diagnostic kind (`//~ KIND`) to be exhaustive | `ui`, `incremental` | `ERROR`, `WARN`, `NOTE`, `HELP`, `SUGGESTION` |
|
||||
| `run-rustfix` | Apply all suggestions via `rustfix`, snapshot fixed output, and check fixed output builds | `ui` | N/A |
|
||||
| `rustfix-only-machine-applicable` | `run-rustfix` but only machine-applicable suggestions | `ui` | N/A |
|
||||
| `exec-env` | Env var to set when executing a test | `ui`, `crashes` | `<KEY>=<VALUE>` |
|
||||
|
@ -303,8 +303,7 @@ It should be preferred to using `error-pattern`, which is imprecise and non-exha
|
||||
### `error-pattern`
|
||||
|
||||
The `error-pattern` [directive](directives.md) can be used for runtime messages, which don't
|
||||
have a specific span, or for compile time messages if imprecise matching is required due to
|
||||
multi-line platform specific diagnostics.
|
||||
have a specific span, or in exceptional cases for compile time messages.
|
||||
|
||||
Let's think about this test:
|
||||
|
||||
@ -318,7 +317,7 @@ fn main() {
|
||||
```
|
||||
|
||||
We want to ensure this shows "index out of bounds" but we cannot use the `ERROR`
|
||||
annotation since the error doesn't have any span. Then it's time to use the
|
||||
annotation since the runtime error doesn't have any span. Then it's time to use the
|
||||
`error-pattern` directive:
|
||||
|
||||
```rust,ignore
|
||||
@ -331,29 +330,51 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
But for strict testing, try to use the `ERROR` annotation as much as possible,
|
||||
including `//~?` annotations for diagnostics without span.
|
||||
For compile time diagnostics `error-pattern` should very rarely be necessary.
|
||||
Use of `error-pattern` is not recommended in general.
|
||||
|
||||
Per-line annotations (`//~`) are still checked in tests using `error-pattern`.
|
||||
To opt out of these checks, use `//@ compile-flags: --error-format=human`.
|
||||
Do that only in exceptional cases.
|
||||
For strict testing of compile time output, try to use the line annotations `//~` as much as
|
||||
possible, including `//~?` annotations for diagnostics without span.
|
||||
|
||||
### Error levels
|
||||
If the compile time output is target dependent or too verbose, use directive
|
||||
`//@ dont-require-annotations: <diagnostic-kind>` to make the line annotation checking
|
||||
non-exhaustive, some of the compiler messages can stay uncovered by annotations in this mode.
|
||||
|
||||
The error levels that you can have are:
|
||||
For checking runtime output `//@ check-run-results` may be preferable.
|
||||
|
||||
Only use `error-pattern` if none of the above works.
|
||||
|
||||
Line annotations `//~` are still checked in tests using `error-pattern`.
|
||||
In exceptional cases use `//@ compile-flags: --error-format=human` to opt out of these checks.
|
||||
|
||||
### Diagnostic kinds (error levels)
|
||||
|
||||
The diagnostic kinds that you can have are:
|
||||
|
||||
- `ERROR`
|
||||
- `WARN` or `WARNING`
|
||||
- `WARN` (or `WARNING`)
|
||||
- `NOTE`
|
||||
- `HELP` and `SUGGESTION`
|
||||
- `HELP`
|
||||
- `SUGGESTION`
|
||||
|
||||
You are allowed to not include a level, but you should include it at least for
|
||||
the primary message.
|
||||
|
||||
The `SUGGESTION` level is used for specifying what the expected replacement text
|
||||
The `SUGGESTION` kind is used for specifying what the expected replacement text
|
||||
should be for a diagnostic suggestion.
|
||||
|
||||
`ERROR` and `WARN` kinds are required to be exhaustively covered by line annotations
|
||||
`//~` by default.
|
||||
|
||||
Other kinds only need to be line-annotated if at least one annotation of that kind appears
|
||||
in the test file. For example, one `//~ NOTE` will also require all other `//~ NOTE`s in the file
|
||||
to be written out explicitly.
|
||||
|
||||
Use directive `//@ dont-require-annotations` to opt out of exhaustive annotations.
|
||||
E.g. use `//@ dont-require-annotations: NOTE` to annotate notes selectively.
|
||||
Avoid using this directive for `ERROR`s and `WARN`ings, unless there's a serious reason, like
|
||||
target-dependent compiler output.
|
||||
|
||||
Missing diagnostic kinds (`//~ message`) are currently accepted, but are being phased away.
|
||||
They will match any compiler output kind, but will not force exhaustive annotations for that kind.
|
||||
Prefer explicit kind and `//@ dont-require-annotations` to achieve the same effect.
|
||||
|
||||
UI tests use the `-A unused` flag by default to ignore all unused warnings, as
|
||||
unused warnings are usually not the focus of a test. However, simple code
|
||||
samples often have unused warnings. If the test is specifically testing an
|
||||
|
@ -476,4 +476,4 @@ dist/2025-04-02/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=e67a33440c3e021ff2
|
||||
dist/2025-04-02/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=0ea7e17d7bb67d6a6c4b2f864aaffcd96512f15f17f0acc63751eb1df6c486a7
|
||||
dist/2025-04-02/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=b73d37b704ab58921172cc561f5598db6a504dcd4d7980966f7c26caaf6d3594
|
||||
dist/2025-04-02/rustc-nightly-x86_64-unknown-netbsd.tar.gz=986f6c594d37bcbd3833e053640ba8775f68d26a65c5618386654ef55d7b3542
|
||||
dist/2025-04-02/rustc-nightly-x86_64-unknown-netbsd.tar.xz=c0d9a88c30d2ab38ec3a11fabb5515ed9bc3ac1a8e35a438d68bf7ff82f6b843
|
||||
dist/2025-04-02/rustc-nightly-x86_64-unknown-netbsd.tar.xz=c0d9a88c30d2ab38ec3a11fabb5515ed9bc3ac1a8e35a438d68bf7ff82f6b843
|
||||
|
@ -65,32 +65,33 @@ impl Tool {
|
||||
nightly_branch,
|
||||
} = &self.config;
|
||||
|
||||
file_content.push_str(&format!("dist_server={}", dist_server));
|
||||
file_content.push_str(&format!("\nartifacts_server={}", artifacts_server));
|
||||
file_content.push_str(&format!("dist_server={}\n", dist_server));
|
||||
file_content.push_str(&format!("artifacts_server={}\n", artifacts_server));
|
||||
file_content.push_str(&format!(
|
||||
"\nartifacts_with_llvm_assertions_server={}",
|
||||
"artifacts_with_llvm_assertions_server={}\n",
|
||||
artifacts_with_llvm_assertions_server
|
||||
));
|
||||
file_content.push_str(&format!("\ngit_merge_commit_email={}", git_merge_commit_email));
|
||||
file_content.push_str(&format!("\ngit_repository={}", git_repository));
|
||||
file_content.push_str(&format!("\nnightly_branch={}", nightly_branch));
|
||||
file_content.push_str(&format!("git_merge_commit_email={}\n", git_merge_commit_email));
|
||||
file_content.push_str(&format!("git_repository={}\n", git_repository));
|
||||
file_content.push_str(&format!("nightly_branch={}\n", nightly_branch));
|
||||
|
||||
file_content.push_str("\n\n");
|
||||
file_content.push_str("\n");
|
||||
file_content.push_str(COMMENTS);
|
||||
file_content.push_str("\n");
|
||||
|
||||
let compiler = self.detect_compiler()?;
|
||||
file_content.push_str(&format!("\ncompiler_date={}", compiler.date));
|
||||
file_content.push_str(&format!("\ncompiler_version={}", compiler.version));
|
||||
file_content.push_str(&format!("compiler_date={}\n", compiler.date));
|
||||
file_content.push_str(&format!("compiler_version={}\n", compiler.version));
|
||||
|
||||
if let Some(rustfmt) = self.detect_rustfmt()? {
|
||||
file_content.push_str(&format!("\nrustfmt_date={}", rustfmt.date));
|
||||
file_content.push_str(&format!("\nrustfmt_version={}", rustfmt.version));
|
||||
file_content.push_str(&format!("rustfmt_date={}\n", rustfmt.date));
|
||||
file_content.push_str(&format!("rustfmt_version={}\n", rustfmt.version));
|
||||
}
|
||||
|
||||
file_content.push_str("\n");
|
||||
|
||||
for (key, value) in self.checksums {
|
||||
file_content.push_str(&format!("\n{}={}", key, value));
|
||||
file_content.push_str(&format!("{}={}\n", key, value));
|
||||
}
|
||||
|
||||
std::fs::write(PATH, file_content)?;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
@ -198,7 +198,7 @@ pub struct TestProps {
|
||||
/// that don't otherwise want/need `-Z build-std`.
|
||||
pub add_core_stubs: bool,
|
||||
/// Whether line annotatins are required for the given error kind.
|
||||
pub require_annotations: HashMap<ErrorKind, bool>,
|
||||
pub dont_require_annotations: HashSet<ErrorKind>,
|
||||
}
|
||||
|
||||
mod directives {
|
||||
@ -301,13 +301,7 @@ impl TestProps {
|
||||
no_auto_check_cfg: false,
|
||||
has_enzyme: false,
|
||||
add_core_stubs: false,
|
||||
require_annotations: HashMap::from([
|
||||
(ErrorKind::Help, true),
|
||||
(ErrorKind::Note, true),
|
||||
(ErrorKind::Error, true),
|
||||
(ErrorKind::Warning, true),
|
||||
(ErrorKind::Suggestion, false),
|
||||
]),
|
||||
dont_require_annotations: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -593,8 +587,8 @@ impl TestProps {
|
||||
if let Some(err_kind) =
|
||||
config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS)
|
||||
{
|
||||
self.require_annotations
|
||||
.insert(ErrorKind::expect_from_user_str(&err_kind), false);
|
||||
self.dont_require_annotations
|
||||
.insert(ErrorKind::expect_from_user_str(err_kind.trim()));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@ -22,7 +22,7 @@ use crate::common::{
|
||||
output_base_dir, output_base_name, output_testname_unique,
|
||||
};
|
||||
use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff};
|
||||
use crate::errors::{self, Error, ErrorKind};
|
||||
use crate::errors::{Error, ErrorKind};
|
||||
use crate::header::TestProps;
|
||||
use crate::read2::{Truncated, read2_abbreviated};
|
||||
use crate::util::{PathBufExt, add_dylib_path, logv, static_regex};
|
||||
@ -675,7 +675,7 @@ impl<'test> TestCx<'test> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_expected_errors(&self, expected_errors: Vec<errors::Error>, proc_res: &ProcRes) {
|
||||
fn check_expected_errors(&self, expected_errors: Vec<Error>, proc_res: &ProcRes) {
|
||||
debug!(
|
||||
"check_expected_errors: expected_errors={:?} proc_res.status={:?}",
|
||||
expected_errors, proc_res.status
|
||||
@ -710,8 +710,12 @@ impl<'test> TestCx<'test> {
|
||||
self.testpaths.file.display().to_string()
|
||||
};
|
||||
|
||||
let expect_help = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Help));
|
||||
let expect_note = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Note));
|
||||
// Errors and warnings are always expected, other diagnostics are only expected
|
||||
// if one of them actually occurs in the test.
|
||||
let expected_kinds: HashSet<_> = [ErrorKind::Error, ErrorKind::Warning]
|
||||
.into_iter()
|
||||
.chain(expected_errors.iter().filter_map(|e| e.kind))
|
||||
.collect();
|
||||
|
||||
// Parse the JSON output from the compiler and extract out the messages.
|
||||
let actual_errors = json::parse_output(&diagnostic_file_name, &proc_res.stderr, proc_res);
|
||||
@ -737,8 +741,11 @@ impl<'test> TestCx<'test> {
|
||||
}
|
||||
|
||||
None => {
|
||||
// If the test is a known bug, don't require that the error is annotated
|
||||
if self.is_unexpected_compiler_message(&actual_error, expect_help, expect_note)
|
||||
if actual_error.require_annotation
|
||||
&& actual_error.kind.map_or(false, |kind| {
|
||||
expected_kinds.contains(&kind)
|
||||
&& !self.props.dont_require_annotations.contains(&kind)
|
||||
})
|
||||
{
|
||||
self.error(&format!(
|
||||
"{}:{}: unexpected {}: '{}'",
|
||||
@ -796,27 +803,6 @@ impl<'test> TestCx<'test> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if we should report an error about `actual_error`,
|
||||
/// which did not match any of the expected error.
|
||||
fn is_unexpected_compiler_message(
|
||||
&self,
|
||||
actual_error: &Error,
|
||||
expect_help: bool,
|
||||
expect_note: bool,
|
||||
) -> bool {
|
||||
actual_error.require_annotation
|
||||
&& actual_error.kind.map_or(false, |err_kind| {
|
||||
// If the test being checked doesn't contain any "help" or "note" annotations, then
|
||||
// we don't require annotating "help" or "note" (respecively) diagnostics at all.
|
||||
let default_require_annotations = self.props.require_annotations[&err_kind];
|
||||
match err_kind {
|
||||
ErrorKind::Help => expect_help && default_require_annotations,
|
||||
ErrorKind::Note => expect_note && default_require_annotations,
|
||||
_ => default_require_annotations,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn should_emit_metadata(&self, pm: Option<PassMode>) -> Emit {
|
||||
match (pm, self.props.fail_mode, self.config.mode) {
|
||||
(Some(PassMode::Check), ..) | (_, Some(FailMode::Check), Ui) => Emit::Metadata,
|
||||
|
@ -156,9 +156,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.7"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
|
||||
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
@ -981,9 +981,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.7"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
|
||||
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
@ -1,8 +1,11 @@
|
||||
//@ revisions: OPT2 OPT3
|
||||
//@ revisions: OPT2 OPT3 OPT3_S390X
|
||||
//@[OPT2] compile-flags: -Copt-level=2
|
||||
//@[OPT3] compile-flags: -C opt-level=3
|
||||
// some targets don't do the opt we are looking for
|
||||
//@[OPT3] only-64bit
|
||||
//@[OPT3] ignore-s390x
|
||||
//@[OPT3_S390X] compile-flags: -C opt-level=3 -C target-cpu=z13
|
||||
//@[OPT3_S390X] only-s390x
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![no_std]
|
||||
@ -17,6 +20,10 @@
|
||||
// OPT3-NEXT: call <8 x i16> @llvm.bswap
|
||||
// OPT3-NEXT: store <8 x i16>
|
||||
// OPT3-NEXT: ret void
|
||||
// OPT3_S390X: load <8 x i16>
|
||||
// OPT3_S390X-NEXT: call <8 x i16> @llvm.bswap
|
||||
// OPT3_S390X-NEXT: store <8 x i16>
|
||||
// OPT3_S390X-NEXT: ret void
|
||||
#[no_mangle]
|
||||
pub fn convert(value: [u16; 8]) -> [u8; 16] {
|
||||
#[cfg(target_endian = "little")]
|
||||
|
@ -46,21 +46,21 @@ pub fn test_zst(p: bool, a: (), b: ()) -> () {
|
||||
pub fn test_int2(p: bool, a: u64, b: u64) -> u64 {
|
||||
// CHECK-LABEL: define{{.*}} @test_int2
|
||||
// CHECK: select i1 %p, i64 %a, i64 %b, !unpredictable
|
||||
p.select_unpredictable(a, b)
|
||||
core::hint::select_unpredictable(p, a, b)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn test_pair2(p: bool, a: (u64, u64), b: (u64, u64)) -> (u64, u64) {
|
||||
// CHECK-LABEL: define{{.*}} @test_pair2
|
||||
// CHECK: select i1 %p, {{.*}}, !unpredictable
|
||||
p.select_unpredictable(a, b)
|
||||
core::hint::select_unpredictable(p, a, b)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn test_struct2(p: bool, a: Large, b: Large) -> Large {
|
||||
// CHECK-LABEL: define{{.*}} @test_struct2
|
||||
// CHECK: select i1 %p, {{.*}}, !unpredictable
|
||||
p.select_unpredictable(a, b)
|
||||
core::hint::select_unpredictable(p, a, b)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -68,5 +68,5 @@ pub fn test_zst2(p: bool, a: (), b: ()) -> () {
|
||||
// CHECK-LABEL: define{{.*}} @test_zst2
|
||||
// CHECK-NEXT: start:
|
||||
// CHECK-NEXT: ret void
|
||||
p.select_unpredictable(a, b)
|
||||
core::hint::select_unpredictable(p, a, b)
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
//@ edition:2018
|
||||
//@ dont-require-annotations: SUGGESTION
|
||||
|
||||
fn take_u32(_x: u32) {}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-missing-await.rs:12:14
|
||||
--> $DIR/suggest-missing-await.rs:13:14
|
||||
|
|
||||
LL | take_u32(x)
|
||||
| -------- ^ expected `u32`, found future
|
||||
@ -7,12 +7,12 @@ LL | take_u32(x)
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
note: calling an async function returns a future
|
||||
--> $DIR/suggest-missing-await.rs:12:14
|
||||
--> $DIR/suggest-missing-await.rs:13:14
|
||||
|
|
||||
LL | take_u32(x)
|
||||
| ^
|
||||
note: function defined here
|
||||
--> $DIR/suggest-missing-await.rs:3:4
|
||||
--> $DIR/suggest-missing-await.rs:4:4
|
||||
|
|
||||
LL | fn take_u32(_x: u32) {}
|
||||
| ^^^^^^^^ -------
|
||||
@ -22,13 +22,13 @@ LL | take_u32(x.await)
|
||||
| ++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-missing-await.rs:22:5
|
||||
--> $DIR/suggest-missing-await.rs:23:5
|
||||
|
|
||||
LL | dummy()
|
||||
| ^^^^^^^ expected `()`, found future
|
||||
|
|
||||
note: calling an async function returns a future
|
||||
--> $DIR/suggest-missing-await.rs:22:5
|
||||
--> $DIR/suggest-missing-await.rs:23:5
|
||||
|
|
||||
LL | dummy()
|
||||
| ^^^^^^^
|
||||
@ -42,7 +42,7 @@ LL | dummy();
|
||||
| +
|
||||
|
||||
error[E0308]: `if` and `else` have incompatible types
|
||||
--> $DIR/suggest-missing-await.rs:35:9
|
||||
--> $DIR/suggest-missing-await.rs:36:9
|
||||
|
|
||||
LL | let _x = if true {
|
||||
| ______________-
|
||||
@ -64,7 +64,7 @@ LL | dummy().await
|
||||
| ++++++
|
||||
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> $DIR/suggest-missing-await.rs:45:14
|
||||
--> $DIR/suggest-missing-await.rs:46:14
|
||||
|
|
||||
LL | let _x = match 0usize {
|
||||
| ______________-
|
||||
@ -87,7 +87,7 @@ LL ~ 1 => dummy().await,
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-missing-await.rs:53:9
|
||||
--> $DIR/suggest-missing-await.rs:54:9
|
||||
|
|
||||
LL | let _x = match dummy() {
|
||||
| ------- this expression has type `impl Future<Output = ()>`
|
||||
@ -102,7 +102,7 @@ LL | let _x = match dummy().await {
|
||||
| ++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-missing-await.rs:67:9
|
||||
--> $DIR/suggest-missing-await.rs:68:9
|
||||
|
|
||||
LL | match dummy_result() {
|
||||
| -------------- this expression has type `impl Future<Output = Result<(), ()>>`
|
||||
@ -118,7 +118,7 @@ LL | match dummy_result().await {
|
||||
| ++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-missing-await.rs:69:9
|
||||
--> $DIR/suggest-missing-await.rs:70:9
|
||||
|
|
||||
LL | match dummy_result() {
|
||||
| -------------- this expression has type `impl Future<Output = Result<(), ()>>`
|
||||
@ -134,7 +134,7 @@ LL | match dummy_result().await {
|
||||
| ++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-missing-await.rs:77:27
|
||||
--> $DIR/suggest-missing-await.rs:78:27
|
||||
|
|
||||
LL | Some(do_async()).map(|()| {});
|
||||
| ^^
|
||||
|
@ -1,3 +1,5 @@
|
||||
//@ dont-require-annotations: SUGGESTION
|
||||
|
||||
fn main() {
|
||||
let u = 5 as bool; //~ ERROR cannot cast `i32` as `bool`
|
||||
//~| HELP compare with zero instead
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0054]: cannot cast `i32` as `bool`
|
||||
--> $DIR/cast-as-bool.rs:2:13
|
||||
--> $DIR/cast-as-bool.rs:4:13
|
||||
|
|
||||
LL | let u = 5 as bool;
|
||||
| ^^^^^^^^^
|
||||
@ -11,7 +11,7 @@ LL + let u = 5 != 0;
|
||||
|
|
||||
|
||||
error[E0054]: cannot cast `i32` as `bool`
|
||||
--> $DIR/cast-as-bool.rs:6:13
|
||||
--> $DIR/cast-as-bool.rs:8:13
|
||||
|
|
||||
LL | let t = (1 + 2) as bool;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
@ -23,7 +23,7 @@ LL + let t = (1 + 2) != 0;
|
||||
|
|
||||
|
||||
error[E0054]: cannot cast `u32` as `bool`
|
||||
--> $DIR/cast-as-bool.rs:10:13
|
||||
--> $DIR/cast-as-bool.rs:12:13
|
||||
|
|
||||
LL | let _ = 5_u32 as bool;
|
||||
| ^^^^^^^^^^^^^
|
||||
@ -35,7 +35,7 @@ LL + let _ = 5_u32 != 0;
|
||||
|
|
||||
|
||||
error[E0054]: cannot cast `f64` as `bool`
|
||||
--> $DIR/cast-as-bool.rs:13:13
|
||||
--> $DIR/cast-as-bool.rs:15:13
|
||||
|
|
||||
LL | let _ = 64.0_f64 as bool;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@ -47,43 +47,43 @@ LL + let _ = 64.0_f64 != 0;
|
||||
|
|
||||
|
||||
error[E0054]: cannot cast `IntEnum` as `bool`
|
||||
--> $DIR/cast-as-bool.rs:24:13
|
||||
--> $DIR/cast-as-bool.rs:26:13
|
||||
|
|
||||
LL | let _ = IntEnum::One as bool;
|
||||
| ^^^^^^^^^^^^^^^^^^^^ unsupported cast
|
||||
|
||||
error[E0054]: cannot cast `fn(u8) -> String {uwu}` as `bool`
|
||||
--> $DIR/cast-as-bool.rs:33:13
|
||||
--> $DIR/cast-as-bool.rs:35:13
|
||||
|
|
||||
LL | let _ = uwu as bool;
|
||||
| ^^^^^^^^^^^ unsupported cast
|
||||
|
||||
error[E0054]: cannot cast `unsafe fn() {owo}` as `bool`
|
||||
--> $DIR/cast-as-bool.rs:35:13
|
||||
--> $DIR/cast-as-bool.rs:37:13
|
||||
|
|
||||
LL | let _ = owo as bool;
|
||||
| ^^^^^^^^^^^ unsupported cast
|
||||
|
||||
error[E0054]: cannot cast `fn(u8) -> String` as `bool`
|
||||
--> $DIR/cast-as-bool.rs:38:13
|
||||
--> $DIR/cast-as-bool.rs:40:13
|
||||
|
|
||||
LL | let _ = uwu as fn(u8) -> String as bool;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported cast
|
||||
|
||||
error[E0054]: cannot cast `char` as `bool`
|
||||
--> $DIR/cast-as-bool.rs:40:13
|
||||
--> $DIR/cast-as-bool.rs:42:13
|
||||
|
|
||||
LL | let _ = 'x' as bool;
|
||||
| ^^^^^^^^^^^ unsupported cast
|
||||
|
||||
error[E0054]: cannot cast `*const ()` as `bool`
|
||||
--> $DIR/cast-as-bool.rs:44:13
|
||||
--> $DIR/cast-as-bool.rs:46:13
|
||||
|
|
||||
LL | let _ = ptr as bool;
|
||||
| ^^^^^^^^^^^ unsupported cast
|
||||
|
||||
error[E0606]: casting `&'static str` as `bool` is invalid
|
||||
--> $DIR/cast-as-bool.rs:46:13
|
||||
--> $DIR/cast-as-bool.rs:48:13
|
||||
|
|
||||
LL | let v = "hello" as bool;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Error, the linked empty library is `no_std` and doesn't provide a panic handler.
|
||||
|
||||
//@ dont-require-annotations:ERROR
|
||||
//@ dont-require-annotations: ERROR
|
||||
//@ dont-check-compiler-stderr
|
||||
//@ aux-build: cfg_false_lib_no_std_before.rs
|
||||
|
||||
|
@ -19,6 +19,7 @@ fn fn_mut() -> _ {
|
||||
let x = String::new();
|
||||
//~^ HELP: consider changing this to be mutable
|
||||
//~| NOTE binding `x` declared here
|
||||
//~| SUGGESTION mut
|
||||
|c| { //~ NOTE: value captured here
|
||||
x.push(c);
|
||||
//~^ ERROR: does not live long enough
|
||||
|
@ -21,7 +21,7 @@ LL | fn fn_mut() -> _ {
|
||||
= note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/suggest-return-closure.rs:32:13
|
||||
--> $DIR/suggest-return-closure.rs:33:13
|
||||
|
|
||||
LL | fn fun() -> _ {
|
||||
| ^
|
||||
@ -32,7 +32,7 @@ LL | fn fun() -> _ {
|
||||
= note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
|
||||
--> $DIR/suggest-return-closure.rs:23:9
|
||||
--> $DIR/suggest-return-closure.rs:24:9
|
||||
|
|
||||
LL | x.push(c);
|
||||
| ^ cannot borrow as mutable
|
||||
@ -43,7 +43,7 @@ LL | let mut x = String::new();
|
||||
| +++
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/suggest-return-closure.rs:23:9
|
||||
--> $DIR/suggest-return-closure.rs:24:9
|
||||
|
|
||||
LL | let x = String::new();
|
||||
| - binding `x` declared here
|
||||
|
@ -1,6 +1,6 @@
|
||||
// ignore-tidy-linelength
|
||||
//@ build-fail
|
||||
//@ dont-require-annotations:ERROR
|
||||
//@ dont-require-annotations: ERROR
|
||||
//@ dont-check-compiler-stderr
|
||||
//@ aux-build:panic-runtime-unwind.rs
|
||||
//@ aux-build:panic-runtime-unwind2.rs
|
||||
|
@ -1,6 +1,6 @@
|
||||
// ignore-tidy-linelength
|
||||
//@ build-fail
|
||||
//@ dont-require-annotations:ERROR
|
||||
//@ dont-require-annotations: ERROR
|
||||
//@ dont-check-compiler-stderr
|
||||
//@ aux-build:panic-runtime-unwind.rs
|
||||
//@ compile-flags:-C panic=abort
|
||||
|
@ -1,6 +1,6 @@
|
||||
// ignore-tidy-linelength
|
||||
//@ build-fail
|
||||
//@ dont-require-annotations:ERROR
|
||||
//@ dont-require-annotations: ERROR
|
||||
//@ dont-check-compiler-stderr
|
||||
//@ aux-build:panic-runtime-unwind.rs
|
||||
//@ aux-build:wants-panic-runtime-unwind.rs
|
||||
|
@ -1,3 +1,5 @@
|
||||
//@ dont-require-annotations: SUGGESTION
|
||||
|
||||
struct S;
|
||||
|
||||
impl S {
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: expected one of `:`, `@`, or `|`, found `bar`
|
||||
--> $DIR/inverted-parameters.rs:4:24
|
||||
--> $DIR/inverted-parameters.rs:6:24
|
||||
|
|
||||
LL | fn foo(&self, &str bar) {}
|
||||
| -----^^^
|
||||
@ -8,7 +8,7 @@ LL | fn foo(&self, &str bar) {}
|
||||
| help: declare the type after the parameter binding: `<identifier>: <type>`
|
||||
|
||||
error: expected one of `:`, `@`, or `|`, found `quux`
|
||||
--> $DIR/inverted-parameters.rs:10:10
|
||||
--> $DIR/inverted-parameters.rs:12:10
|
||||
|
|
||||
LL | fn baz(S quux, xyzzy: i32) {}
|
||||
| --^^^^
|
||||
@ -17,19 +17,19 @@ LL | fn baz(S quux, xyzzy: i32) {}
|
||||
| help: declare the type after the parameter binding: `<identifier>: <type>`
|
||||
|
||||
error: expected one of `:`, `@`, or `|`, found `a`
|
||||
--> $DIR/inverted-parameters.rs:15:12
|
||||
--> $DIR/inverted-parameters.rs:17:12
|
||||
|
|
||||
LL | fn one(i32 a b) {}
|
||||
| ^ expected one of `:`, `@`, or `|`
|
||||
|
||||
error: expected one of `:` or `|`, found `(`
|
||||
--> $DIR/inverted-parameters.rs:18:23
|
||||
--> $DIR/inverted-parameters.rs:20:23
|
||||
|
|
||||
LL | fn pattern((i32, i32) (a, b)) {}
|
||||
| ^ expected one of `:` or `|`
|
||||
|
||||
error: expected one of `:`, `@`, or `|`, found `)`
|
||||
--> $DIR/inverted-parameters.rs:21:12
|
||||
--> $DIR/inverted-parameters.rs:23:12
|
||||
|
|
||||
LL | fn fizz(i32) {}
|
||||
| ^ expected one of `:`, `@`, or `|`
|
||||
@ -49,7 +49,7 @@ LL | fn fizz(_: i32) {}
|
||||
| ++
|
||||
|
||||
error: expected one of `:`, `@`, or `|`, found `S`
|
||||
--> $DIR/inverted-parameters.rs:27:23
|
||||
--> $DIR/inverted-parameters.rs:29:23
|
||||
|
|
||||
LL | fn missing_colon(quux S) {}
|
||||
| -----^
|
||||
|
@ -1,3 +1,5 @@
|
||||
//@ dont-require-annotations: SUGGESTION
|
||||
|
||||
struct X(usize);
|
||||
|
||||
impl X {
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0594]: cannot assign to `self.0`, which is behind a `&` reference
|
||||
--> $DIR/suggest-ref-mut.rs:7:9
|
||||
--> $DIR/suggest-ref-mut.rs:9:9
|
||||
|
|
||||
LL | self.0 = 32;
|
||||
| ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written
|
||||
@ -10,7 +10,7 @@ LL | fn zap(&mut self) {
|
||||
| +++
|
||||
|
||||
error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
|
||||
--> $DIR/suggest-ref-mut.rs:15:5
|
||||
--> $DIR/suggest-ref-mut.rs:17:5
|
||||
|
|
||||
LL | *foo = 32;
|
||||
| ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
|
||||
@ -21,7 +21,7 @@ LL | let ref mut foo = 16;
|
||||
| +++
|
||||
|
||||
error[E0594]: cannot assign to `*bar`, which is behind a `&` reference
|
||||
--> $DIR/suggest-ref-mut.rs:19:9
|
||||
--> $DIR/suggest-ref-mut.rs:21:9
|
||||
|
|
||||
LL | *bar = 32;
|
||||
| ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
|
||||
@ -32,7 +32,7 @@ LL | if let Some(ref mut bar) = Some(16) {
|
||||
| +++
|
||||
|
||||
error[E0594]: cannot assign to `*quo`, which is behind a `&` reference
|
||||
--> $DIR/suggest-ref-mut.rs:23:22
|
||||
--> $DIR/suggest-ref-mut.rs:25:22
|
||||
|
|
||||
LL | ref quo => { *quo = 32; },
|
||||
| ^^^^^^^^^ `quo` is a `&` reference, so the data it refers to cannot be written
|
||||
|
@ -1,4 +1,5 @@
|
||||
//@ edition:2018
|
||||
//@ dont-require-annotations: SUGGESTION
|
||||
|
||||
async fn hello() { //~ HELP try adding a return type
|
||||
0
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-90027-async-fn-return-suggestion.rs:4:5
|
||||
--> $DIR/issue-90027-async-fn-return-suggestion.rs:5:5
|
||||
|
|
||||
LL | async fn hello() {
|
||||
| - help: try adding a return type: `-> i32`
|
||||
@ -7,7 +7,7 @@ LL | 0
|
||||
| ^ expected `()`, found integer
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-90027-async-fn-return-suggestion.rs:9:5
|
||||
--> $DIR/issue-90027-async-fn-return-suggestion.rs:10:5
|
||||
|
|
||||
LL | async fn world() -> () {
|
||||
| -- expected `()` because of return type
|
||||
@ -15,13 +15,13 @@ LL | 0
|
||||
| ^ expected `()`, found integer
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-90027-async-fn-return-suggestion.rs:14:5
|
||||
--> $DIR/issue-90027-async-fn-return-suggestion.rs:15:5
|
||||
|
|
||||
LL | hello()
|
||||
| ^^^^^^^ expected `()`, found future
|
||||
|
|
||||
note: calling an async function returns a future
|
||||
--> $DIR/issue-90027-async-fn-return-suggestion.rs:14:5
|
||||
--> $DIR/issue-90027-async-fn-return-suggestion.rs:15:5
|
||||
|
|
||||
LL | hello()
|
||||
| ^^^^^^^
|
||||
|
Loading…
Reference in New Issue
Block a user