From dcdb192b554a339ce9ec418629e86847afb8ff42 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sun, 13 Oct 2024 21:27:29 +0800 Subject: [PATCH 01/13] unwind: update unwinding dependency to 0.2.3 The recent changes to naked `asm!()` macros made this unbuildable on Xous. The upstream package maintainer released 0.2.3 to fix support on newer nightly toolchains. Update the dependency to 0.2.3, which is the oldest version that works with the current nightly compiler. This closes #131602 and fixes the build on xous. Signed-off-by: Sean Cross --- library/Cargo.lock | 12 ++++++------ library/unwind/Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index 877ae0cc1cc93..13db69e5e9909 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -124,9 +124,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.30.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e1d97fbe9722ba9bbd0c97051c2956e726562b61f86a25a4360398a40edfc9" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" dependencies = [ "compiler_builtins", "rustc-std-workspace-alloc", @@ -406,12 +406,12 @@ dependencies = [ [[package]] name = "unwinding" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc55842d0db6329a669d55a623c674b02d677b16bfb2d24857d4089d41eba882" +checksum = "637d511437df708cee34bdec7ba2f1548d256b7acf3ff20e0a1c559f9bf3a987" dependencies = [ "compiler_builtins", - "gimli 0.30.0", + "gimli 0.31.1", "rustc-std-workspace-core", ] diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index 590de31a678ca..569a1b3299e5f 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -22,7 +22,7 @@ cfg-if = "1.0" libc = { version = "0.2.140", features = ['rustc-dep-of-std'], default-features = false } [target.'cfg(target_os = "xous")'.dependencies] -unwinding = { version = "0.2.1", features = ['rustc-dep-of-std', 'unwinder', 'fde-custom'], default-features = false } +unwinding = { version = "0.2.3", features = ['rustc-dep-of-std', 'unwinder', 'fde-custom'], default-features = false } [features] From 7304cf4765120f1e81066821fe4566fdee1bc7c2 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Tue, 6 Aug 2024 22:41:06 +0800 Subject: [PATCH 02/13] std: xous: add support for args and env Process arguments and environment variables are both passed by way of Application Parameters. These are a TLV format that gets passed in as the second process argument. This patch combines both as they are very similar in their decode. Signed-off-by: Sean Cross --- library/std/src/sys/pal/xous/args.rs | 53 ++++ library/std/src/sys/pal/xous/mod.rs | 1 - library/std/src/sys/pal/xous/os.rs | 136 +++++++-- library/std/src/sys/pal/xous/os/params.rs | 271 ++++++++++++++++++ .../std/src/sys/pal/xous/os/params/tests.rs | 75 +++++ 5 files changed, 504 insertions(+), 32 deletions(-) create mode 100644 library/std/src/sys/pal/xous/args.rs create mode 100644 library/std/src/sys/pal/xous/os/params.rs create mode 100644 library/std/src/sys/pal/xous/os/params/tests.rs diff --git a/library/std/src/sys/pal/xous/args.rs b/library/std/src/sys/pal/xous/args.rs new file mode 100644 index 0000000000000..00c44ca220a9e --- /dev/null +++ b/library/std/src/sys/pal/xous/args.rs @@ -0,0 +1,53 @@ +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, +} + +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 { + self.parsed_args_list.next() + } + fn size_hint(&self) -> (usize, Option) { + self.parsed_args_list.size_hint() + } +} + +impl DoubleEndedIterator for Args { + fn next_back(&mut self) -> Option { + self.parsed_args_list.next_back() + } +} + +impl ExactSizeIterator for Args { + fn len(&self) -> usize { + self.parsed_args_list.len() + } +} diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs index b211e94db65d6..a64cd06856006 100644 --- a/library/std/src/sys/pal/xous/mod.rs +++ b/library/std/src/sys/pal/xous/mod.rs @@ -1,6 +1,5 @@ #![forbid(unsafe_op_in_unsafe_fn)] -#[path = "../unsupported/args.rs"] pub mod args; #[path = "../unsupported/env.rs"] pub mod env; diff --git a/library/std/src/sys/pal/xous/os.rs b/library/std/src/sys/pal/xous/os.rs index 8f8f35428c487..b0ab01a6383d2 100644 --- a/library/std/src/sys/pal/xous/os.rs +++ b/library/std/src/sys/pal/xous/os.rs @@ -1,29 +1,35 @@ use super::unsupported; +use crate::collections::HashMap; use crate::error::Error as StdError; use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; use crate::os::xous::ffi::Error as XousError; use crate::path::{self, PathBuf}; -use crate::{fmt, io}; +use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; +use crate::sync::{Mutex, Once}; +use crate::{fmt, io, vec}; + +pub(crate) mod params; + +static PARAMS_ADDRESS: AtomicPtr = AtomicPtr::new(core::ptr::null_mut()); #[cfg(not(test))] #[cfg(feature = "panic_unwind")] mod eh_unwinding { - pub(crate) struct EhFrameFinder(usize /* eh_frame */); - pub(crate) static mut EH_FRAME_SETTINGS: EhFrameFinder = EhFrameFinder(0); - impl EhFrameFinder { - pub(crate) unsafe fn init(&mut self, eh_frame: usize) { - unsafe { - EH_FRAME_SETTINGS.0 = eh_frame; - } - } - } + pub(crate) struct EhFrameFinder; + pub(crate) static mut EH_FRAME_ADDRESS: usize = 0; + pub(crate) static EH_FRAME_SETTINGS: EhFrameFinder = EhFrameFinder; + unsafe impl unwind::EhFrameFinder for EhFrameFinder { fn find(&self, _pc: usize) -> Option { - Some(unwind::FrameInfo { - text_base: None, - kind: unwind::FrameInfoKind::EhFrame(self.0), - }) + if unsafe { EH_FRAME_ADDRESS == 0 } { + None + } else { + Some(unwind::FrameInfo { + text_base: None, + kind: unwind::FrameInfoKind::EhFrame(unsafe { EH_FRAME_ADDRESS }), + }) + } } } } @@ -41,12 +47,21 @@ mod c_compat { } #[no_mangle] - pub extern "C" fn _start(eh_frame: usize) { + pub extern "C" fn _start(eh_frame: usize, params_address: usize) { #[cfg(feature = "panic_unwind")] - unsafe { - super::eh_unwinding::EH_FRAME_SETTINGS.init(eh_frame); + { + unsafe { super::eh_unwinding::EH_FRAME_ADDRESS = eh_frame }; unwind::set_custom_eh_frame_finder(&super::eh_unwinding::EH_FRAME_SETTINGS).ok(); } + + if params_address != 0 { + let params_address = crate::ptr::with_exposed_provenance_mut::(params_address); + if unsafe { + super::params::ApplicationParameters::new_from_ptr(params_address).is_some() + } { + super::PARAMS_ADDRESS.store(params_address, core::sync::atomic::Ordering::Relaxed); + } + } exit(unsafe { main() }); } @@ -116,44 +131,103 @@ pub fn current_exe() -> io::Result { unsupported() } -pub struct Env(!); +pub(crate) fn get_application_parameters() -> Option { + let params_address = PARAMS_ADDRESS.load(Ordering::Relaxed); + unsafe { params::ApplicationParameters::new_from_ptr(params_address) } +} + +// ---------- Environment handling ---------- // +static ENV: AtomicUsize = AtomicUsize::new(0); +static ENV_INIT: Once = Once::new(); +type EnvStore = Mutex>; + +fn get_env_store() -> &'static EnvStore { + ENV_INIT.call_once(|| { + let env_store = EnvStore::default(); + if let Some(params) = get_application_parameters() { + for param in params { + if let Ok(envs) = params::EnvironmentBlock::try_from(¶m) { + let mut env_store = env_store.lock().unwrap(); + for env in envs { + env_store.insert(env.key.into(), env.value.into()); + } + break; + } + } + } + ENV.store(Box::into_raw(Box::new(env_store)) as _, Ordering::Relaxed) + }); + unsafe { &*core::ptr::with_exposed_provenance::(ENV.load(Ordering::Relaxed)) } +} + +pub struct Env { + iter: vec::IntoIter<(OsString, OsString)>, +} + +// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. +pub struct EnvStrDebug<'a> { + slice: &'a [(OsString, OsString)], +} + +impl fmt::Debug for EnvStrDebug<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { slice } = self; + f.debug_list() + .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap()))) + .finish() + } +} impl Env { // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. pub fn str_debug(&self) -> impl fmt::Debug + '_ { - let Self(inner) = self; - match *inner {} + let Self { iter } = self; + EnvStrDebug { slice: iter.as_slice() } } } impl fmt::Debug for Env { - fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self(inner) = self; - match *inner {} + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { iter } = self; + f.debug_list().entries(iter.as_slice()).finish() } } +impl !Send for Env {} +impl !Sync for Env {} + impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { - self.0 + self.iter.next() + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() } } pub fn env() -> Env { - panic!("not supported on this platform") + let clone_to_vec = |map: &HashMap| -> Vec<_> { + map.iter().map(|(k, v)| (k.clone(), v.clone())).collect() + }; + + let iter = clone_to_vec(&*get_env_store().lock().unwrap()).into_iter(); + Env { iter } } -pub fn getenv(_: &OsStr) -> Option { - None +pub fn getenv(k: &OsStr) -> Option { + get_env_store().lock().unwrap().get(k).cloned() } -pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { - Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform")) +pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + let (k, v) = (k.to_owned(), v.to_owned()); + get_env_store().lock().unwrap().insert(k, v); + Ok(()) } -pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> { - Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform")) +pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> { + get_env_store().lock().unwrap().remove(k); + Ok(()) } pub fn temp_dir() -> PathBuf { diff --git a/library/std/src/sys/pal/xous/os/params.rs b/library/std/src/sys/pal/xous/os/params.rs new file mode 100644 index 0000000000000..0d02cf35477f9 --- /dev/null +++ b/library/std/src/sys/pal/xous/os/params.rs @@ -0,0 +1,271 @@ +/// Xous passes a pointer to the parameter block as the second argument. +/// This is used for passing flags such as environment variables. The +/// format of the argument block is: +/// +/// #[repr(C)] +/// struct BlockHeader { +/// /// Magic number that identifies this block. Must be printable ASCII. +/// magic: [u8; 4], +/// +/// /// The size of the data block. Does not include this header. May be 0. +/// size: u32, +/// +/// /// The contents of this block. Varies depending on the block type. +/// data: [u8; 0], +/// } +/// +/// There is a BlockHeader at the start that has magic `AppP`, and the data +/// that follows is the number of blocks present: +/// +/// #[repr(C)] +/// struct ApplicationParameters { +/// magic: b"AppP", +/// size: 4u32, +/// +/// /// The size of the entire application slice, in bytes, including all headers +/// length: u32, +/// +/// /// Number of application parameters present. Must be at least 1 (this block) +/// entries: (parameter_count as u32).to_bytes_le(), +/// } +/// +/// #[repr(C)] +/// struct EnvironmentBlock { +/// magic: b"EnvB", +/// +/// /// Total number of bytes, excluding this header +/// size: 2+data.len(), +/// +/// /// The number of environment variables +/// count: u16, +/// +/// /// Environment variable iteration +/// data: [u8; 0], +/// } +/// +/// Environment variables are present in an `EnvB` block. The `data` section is +/// a sequence of bytes of the form: +/// +/// (u16 /* key_len */; [0u8; key_len as usize] /* key */, +/// u16 /* val_len */ [0u8; val_len as usize]) +/// +/// #[repr(C)] +/// struct ArgumentList { +/// magic: b"ArgL", +/// +/// /// Total number of bytes, excluding this header +/// size: 2+data.len(), +/// +/// /// The number of arguments variables +/// count: u16, +/// +/// /// Argument variable iteration +/// data: [u8; 0], +/// } +/// +/// Args are just an array of strings that represent command line arguments. +/// They are a sequence of the form: +/// +/// (u16 /* val_len */ [0u8; val_len as usize]) +use core::slice; + +use crate::ffi::OsString; + +/// Magic number indicating we have an environment block +const ENV_MAGIC: [u8; 4] = *b"EnvB"; + +/// Command line arguments list +const ARGS_MAGIC: [u8; 4] = *b"ArgL"; + +/// Magic number indicating the loader has passed application parameters +const PARAMS_MAGIC: [u8; 4] = *b"AppP"; + +#[cfg(test)] +mod tests; + +pub(crate) struct ApplicationParameters { + data: &'static [u8], + offset: usize, + _entries: usize, +} + +impl ApplicationParameters { + pub(crate) unsafe fn new_from_ptr(data: *const u8) -> Option { + if data.is_null() { + return None; + } + + let magic = unsafe { core::slice::from_raw_parts(data, 4) }; + let block_length = unsafe { + u32::from_le_bytes(slice::from_raw_parts(data.add(4), 4).try_into().ok()?) as usize + }; + let data_length = unsafe { + u32::from_le_bytes(slice::from_raw_parts(data.add(8), 4).try_into().ok()?) as usize + }; + let entries = unsafe { + u32::from_le_bytes(slice::from_raw_parts(data.add(12), 4).try_into().ok()?) as usize + }; + + // Check for the main header + if data_length < 16 || magic != PARAMS_MAGIC || block_length != 8 { + return None; + } + + let data = unsafe { slice::from_raw_parts(data, data_length) }; + + Some(ApplicationParameters { data, offset: 0, _entries: entries }) + } +} + +impl Iterator for ApplicationParameters { + type Item = ApplicationParameter; + + fn next(&mut self) -> Option { + // Fetch magic, ensuring we don't run off the end + if self.offset + 4 > self.data.len() { + return None; + } + let magic = &self.data[self.offset..self.offset + 4]; + self.offset += 4; + + // Fetch header size + if self.offset + 4 > self.data.len() { + return None; + } + let size = u32::from_le_bytes(self.data[self.offset..self.offset + 4].try_into().unwrap()) + as usize; + self.offset += 4; + + // Fetch data contents + if self.offset + size > self.data.len() { + return None; + } + let data = &self.data[self.offset..self.offset + size]; + self.offset += size; + + Some(ApplicationParameter { data, magic: magic.try_into().unwrap() }) + } +} + +pub(crate) struct ApplicationParameter { + data: &'static [u8], + magic: [u8; 4], +} + +pub(crate) struct ApplicationParameterError; + +pub(crate) struct EnvironmentBlock { + _count: usize, + data: &'static [u8], + offset: usize, +} + +impl TryFrom<&ApplicationParameter> for EnvironmentBlock { + type Error = ApplicationParameterError; + + fn try_from(value: &ApplicationParameter) -> Result { + if value.data.len() < 2 || value.magic != ENV_MAGIC { + return Err(ApplicationParameterError); + } + + let count = u16::from_le_bytes(value.data[0..2].try_into().unwrap()) as usize; + + Ok(EnvironmentBlock { data: &value.data[2..], offset: 0, _count: count }) + } +} + +pub(crate) struct EnvironmentEntry { + pub key: &'static str, + pub value: &'static str, +} + +impl Iterator for EnvironmentBlock { + type Item = EnvironmentEntry; + + fn next(&mut self) -> Option { + if self.offset + 2 > self.data.len() { + return None; + } + let key_len = + u16::from_le_bytes(self.data[self.offset..self.offset + 2].try_into().ok()?) as usize; + self.offset += 2; + + if self.offset + key_len > self.data.len() { + return None; + } + let key = core::str::from_utf8(&self.data[self.offset..self.offset + key_len]).ok()?; + self.offset += key_len; + + if self.offset + 2 > self.data.len() { + return None; + } + let value_len = + u16::from_le_bytes(self.data[self.offset..self.offset + 2].try_into().ok()?) as usize; + self.offset += 2; + + if self.offset + value_len > self.data.len() { + return None; + } + let value = core::str::from_utf8(&self.data[self.offset..self.offset + value_len]).ok()?; + self.offset += value_len; + + Some(EnvironmentEntry { key, value }) + } +} + +pub(crate) struct ArgumentList { + data: &'static [u8], + _count: usize, + offset: usize, +} + +impl TryFrom<&ApplicationParameter> for ArgumentList { + type Error = ApplicationParameterError; + + fn try_from(value: &ApplicationParameter) -> Result { + if value.data.len() < 2 || value.magic != ARGS_MAGIC { + return Err(ApplicationParameterError); + } + let count = + u16::from_le_bytes(value.data[0..2].try_into().or(Err(ApplicationParameterError))?) + as usize; + Ok(ArgumentList { data: &value.data[2..], _count: count, offset: 0 }) + } +} + +pub(crate) struct ArgumentEntry { + value: &'static str, +} + +impl Into<&str> for ArgumentEntry { + fn into(self) -> &'static str { + self.value + } +} + +impl Into for ArgumentEntry { + fn into(self) -> OsString { + self.value.into() + } +} + +impl Iterator for ArgumentList { + type Item = ArgumentEntry; + + fn next(&mut self) -> Option { + if self.offset + 2 > self.data.len() { + return None; + } + let value_len = + u16::from_le_bytes(self.data[self.offset..self.offset + 2].try_into().ok()?) as usize; + self.offset += 2; + + if self.offset + value_len > self.data.len() { + return None; + } + let value = core::str::from_utf8(&self.data[self.offset..self.offset + value_len]).ok()?; + self.offset += value_len; + + Some(ArgumentEntry { value }) + } +} diff --git a/library/std/src/sys/pal/xous/os/params/tests.rs b/library/std/src/sys/pal/xous/os/params/tests.rs new file mode 100644 index 0000000000000..0ef04ee30919f --- /dev/null +++ b/library/std/src/sys/pal/xous/os/params/tests.rs @@ -0,0 +1,75 @@ +use super::*; +use crate::collections::HashMap; +use crate::io::Write; + +fn create_args_test() -> std::io::Result> { + let mut sample_data = vec![]; + let mut h = HashMap::new(); + + h.insert("foo", "bar"); + h.insert("baz", "qux"); + h.insert("some", "val"); + + // Magic number + sample_data.write_all(&PARAMS_MAGIC)?; + // Size of the AppP block + sample_data.write_all(&4u32.to_le_bytes())?; + // Number of blocks + sample_data.write_all(&2u32.to_le_bytes())?; + + // Magic number + sample_data.write_all(&ENV_MAGIC)?; + let mut data = vec![]; + for (key, value) in h.iter() { + data.extend_from_slice(&(key.len() as u16).to_le_bytes()); + data.extend_from_slice(key.as_bytes()); + data.extend_from_slice(&(value.len() as u16).to_le_bytes()); + data.extend_from_slice(value.as_bytes()); + } + // Size of the EnvB block + sample_data.write_all(&(data.len() as u32 + 2).to_le_bytes())?; + + // Number of environment variables + sample_data.write_all(&(h.len() as u16).to_le_bytes())?; + + // Environment variables + sample_data.write_all(&data)?; + + // Write command line arguments + let args = vec!["some", "command", "line variable", "entries"]; + sample_data.write_all(&ARGS_MAGIC)?; + let mut args_size = 0; + for entry in args.iter() { + args_size += entry.len() + 2; + } + sample_data.write_all(&(args_size as u32 + 2).to_le_bytes())?; + sample_data.write_all(&(args.len() as u16).to_le_bytes())?; + for entry in args { + sample_data.write_all(&(entry.len() as u16).to_le_bytes())?; + sample_data.write_all(entry.as_bytes())?; + } + + Ok(sample_data) +} + +#[test] +fn basic_arg_parsing() { + let arg_data = create_args_test().expect("couldn't create test data"); + for byte in &arg_data { + print!("{:02x} ", byte); + } + println!(); + + let args = ApplicationParameters::new(&arg_data).expect("Unable to parse arguments"); + for arg in args { + if let Ok(env) = EnvironmentBlock::try_from(&arg) { + for env in env { + println!("{}={}", env.key, env.value); + } + } else if let Ok(args) = ArgumentList::try_from(&arg) { + for arg in args { + println!("Arg: {}", arg.value); + } + } + } +} From 3d00c5cd5e2ceb0d5b87a8754af3dff45de0b32b Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Tue, 11 Jun 2024 00:31:32 +0800 Subject: [PATCH 03/13] net: fix dead code warning Signed-off-by: Sean Cross --- library/std/src/sys/pal/xous/net/dns.rs | 1 + library/std/src/sys/pal/xous/net/mod.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/library/std/src/sys/pal/xous/net/dns.rs b/library/std/src/sys/pal/xous/net/dns.rs index d0083c6183793..1a2b56b4da5d3 100644 --- a/library/std/src/sys/pal/xous/net/dns.rs +++ b/library/std/src/sys/pal/xous/net/dns.rs @@ -6,6 +6,7 @@ use crate::os::xous::ffi::lend_mut; use crate::os::xous::services::{DnsLendMut, dns_server}; pub struct DnsError { + #[allow(dead_code)] pub code: u8, } diff --git a/library/std/src/sys/pal/xous/net/mod.rs b/library/std/src/sys/pal/xous/net/mod.rs index dd8b765aa74ae..3e18ed24208d3 100644 --- a/library/std/src/sys/pal/xous/net/mod.rs +++ b/library/std/src/sys/pal/xous/net/mod.rs @@ -60,6 +60,7 @@ pub mod netc { #[derive(Copy, Clone)] pub struct sockaddr_in { + #[allow(dead_code)] pub sin_family: sa_family_t, pub sin_port: u16, pub sin_addr: in_addr, @@ -72,6 +73,7 @@ pub mod netc { #[derive(Copy, Clone)] pub struct sockaddr_in6 { + #[allow(dead_code)] pub sin6_family: sa_family_t, pub sin6_port: u16, pub sin6_addr: in6_addr, From 4c23cdf7415c0f81b17dd534b59ecc3f7cd5db15 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Wed, 28 Aug 2024 20:42:27 +0800 Subject: [PATCH 04/13] xous: ffi: correct syscall number for adjust_process The AdjustProcessLimit syscall was using the correct call number. Signed-off-by: Sean Cross --- library/std/src/os/xous/ffi.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/xous/ffi.rs b/library/std/src/os/xous/ffi.rs index 1a4a940bf358a..1db314e9ddad7 100644 --- a/library/std/src/os/xous/ffi.rs +++ b/library/std/src/os/xous/ffi.rs @@ -615,7 +615,7 @@ pub(crate) fn thread_id() -> Result { /// An error is generated if the `knob` is not a valid limit, or if the call /// would not succeed. pub(crate) fn adjust_limit(knob: Limits, current: usize, new: usize) -> Result { - let mut a0 = Syscall::JoinThread as usize; + let mut a0 = Syscall::AdjustProcessLimit as usize; let mut a1 = knob as usize; let a2 = current; let a3 = new; From 99de67af35b90b3e1a90849ec8bc6e92e0b73370 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sun, 13 Oct 2024 21:52:06 +0800 Subject: [PATCH 05/13] library: xous: mark alloc as `FIXME(static_mut_refs)` The allocator on Xous is now throwing warnings because the allocator needs to be mutable, and allocators hand out mutable pointers, which the `static_mut_refs` lint now catches. Give the same treatment to Xous as wasm, at least until a solution is devised for fixing the warning on wasm. Signed-off-by: Sean Cross --- library/std/src/sys/alloc/xous.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/std/src/sys/alloc/xous.rs b/library/std/src/sys/alloc/xous.rs index 9ea43445d0206..321d30e0b11b2 100644 --- a/library/std/src/sys/alloc/xous.rs +++ b/library/std/src/sys/alloc/xous.rs @@ -1,3 +1,6 @@ +// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] + use crate::alloc::{GlobalAlloc, Layout, System}; #[cfg(not(test))] From 93cee99368d0d268c1b3ba01f5691fa90e35ece1 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 15 Oct 2024 11:13:28 -0400 Subject: [PATCH 06/13] rustc_metadata: move comment closer to code This was added in cc3c8bbfaf5af19caf3deb131a995a65ca4674f9 when it was closer to the `extract_one` call. Move it back near that call. --- compiler/rustc_metadata/src/locator.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 99c673b021a90..d53a19aa47b30 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -499,8 +499,11 @@ impl<'a> CrateLocator<'a> { dylibs: FxIndexMap, ) -> Result, CrateError> { let mut slot = None; - // Order here matters, rmeta should come first. See comment in - // `extract_one` below. + // Order here matters, rmeta should come first. + // + // Make sure there's at most one rlib and at most one dylib. + // + // See comment in `extract_one` below. let source = CrateSource { rmeta: self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot)?, rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot)?, @@ -729,7 +732,6 @@ impl<'a> CrateLocator<'a> { || file.starts_with(self.target.dll_prefix.as_ref()) && file.ends_with(self.target.dll_suffix.as_ref()) { - // Make sure there's at most one rlib and at most one dylib. // Note to take care and match against the non-canonicalized name: // some systems save build artifacts into content-addressed stores // that do not preserve extensions, and then link to them using From f39555135293d27c361b373a522b347f9328d619 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 15 Oct 2024 11:14:34 -0400 Subject: [PATCH 07/13] rustc_metadata: replace `?` in expression with map --- compiler/rustc_metadata/src/locator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index d53a19aa47b30..bc2f6c11552b4 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -755,7 +755,7 @@ impl<'a> CrateLocator<'a> { } // Extract the dylib/rlib/rmeta triple. - Ok(self.extract_lib(rlibs, rmetas, dylibs)?.map(|(_, lib)| lib)) + self.extract_lib(rlibs, rmetas, dylibs).map(|opt| opt.map(|(_, lib)| lib)) } pub(crate) fn into_error(self, root: Option) -> CrateError { From 69be18d4e2c5783978f2c8dfcabf8a6fca5aa99c Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 15 Oct 2024 11:19:06 -0400 Subject: [PATCH 08/13] rustc_metadata: reduce repetition --- compiler/rustc_metadata/src/locator.rs | 45 +++++++++++--------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index bc2f6c11552b4..35954ea088d4f 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -709,40 +709,31 @@ impl<'a> CrateLocator<'a> { let mut rmetas = FxIndexMap::default(); let mut dylibs = FxIndexMap::default(); for loc in &self.exact_paths { - if !loc.canonicalized().exists() { - return Err(CrateError::ExternLocationNotExist( - self.crate_name, - loc.original().clone(), - )); + let loc_canon = loc.canonicalized(); + let loc_orig = loc.original(); + if !loc_canon.exists() { + return Err(CrateError::ExternLocationNotExist(self.crate_name, loc_orig.clone())); } - if !loc.original().is_file() { - return Err(CrateError::ExternLocationNotFile( - self.crate_name, - loc.original().clone(), - )); + if !loc_orig.is_file() { + return Err(CrateError::ExternLocationNotFile(self.crate_name, loc_orig.clone())); } - let Some(file) = loc.original().file_name().and_then(|s| s.to_str()) else { - return Err(CrateError::ExternLocationNotFile( - self.crate_name, - loc.original().clone(), - )); + // Note to take care and match against the non-canonicalized name: + // some systems save build artifacts into content-addressed stores + // that do not preserve extensions, and then link to them using + // e.g. symbolic links. If we canonicalize too early, we resolve + // the symlink, the file type is lost and we might treat rlibs and + // rmetas as dylibs. + let Some(file) = loc_orig.file_name().and_then(|s| s.to_str()) else { + return Err(CrateError::ExternLocationNotFile(self.crate_name, loc_orig.clone())); }; - if file.starts_with("lib") && (file.ends_with(".rlib") || file.ends_with(".rmeta")) || file.starts_with(self.target.dll_prefix.as_ref()) && file.ends_with(self.target.dll_suffix.as_ref()) { - // Note to take care and match against the non-canonicalized name: - // some systems save build artifacts into content-addressed stores - // that do not preserve extensions, and then link to them using - // e.g. symbolic links. If we canonicalize too early, we resolve - // the symlink, the file type is lost and we might treat rlibs and - // rmetas as dylibs. - let loc_canon = loc.canonicalized().clone(); - let loc = loc.original(); - if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") { + let loc_canon = loc_canon.clone(); + if file.ends_with(".rlib") { rlibs.insert(loc_canon, PathKind::ExternFlag); - } else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") { + } else if file.ends_with(".rmeta") { rmetas.insert(loc_canon, PathKind::ExternFlag); } else { dylibs.insert(loc_canon, PathKind::ExternFlag); @@ -750,7 +741,7 @@ impl<'a> CrateLocator<'a> { } else { self.crate_rejections .via_filename - .push(CrateMismatch { path: loc.original().clone(), got: String::new() }); + .push(CrateMismatch { path: loc_orig.clone(), got: String::new() }); } } From 94a2be998d58d8dd05dc53568409be634a93f3a2 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 15 Oct 2024 11:37:40 -0400 Subject: [PATCH 09/13] rustc_metadata: reduce repetition --- compiler/rustc_metadata/src/locator.rs | 44 +++++++++++++++++--------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 35954ea088d4f..a4a69ae95144e 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -726,22 +726,36 @@ impl<'a> CrateLocator<'a> { let Some(file) = loc_orig.file_name().and_then(|s| s.to_str()) else { return Err(CrateError::ExternLocationNotFile(self.crate_name, loc_orig.clone())); }; - if file.starts_with("lib") && (file.ends_with(".rlib") || file.ends_with(".rmeta")) - || file.starts_with(self.target.dll_prefix.as_ref()) - && file.ends_with(self.target.dll_suffix.as_ref()) - { - let loc_canon = loc_canon.clone(); - if file.ends_with(".rlib") { - rlibs.insert(loc_canon, PathKind::ExternFlag); - } else if file.ends_with(".rmeta") { - rmetas.insert(loc_canon, PathKind::ExternFlag); - } else { - dylibs.insert(loc_canon, PathKind::ExternFlag); + // FnMut cannot return reference to captured value, so references + // must be taken outside the closure. + let rlibs = &mut rlibs; + let rmetas = &mut rmetas; + let dylibs = &mut dylibs; + let type_via_filename = (|| { + if file.starts_with("lib") { + if file.ends_with(".rlib") { + return Some(rlibs); + } + if file.ends_with(".rmeta") { + return Some(rmetas); + } + } + let dll_prefix = self.target.dll_prefix.as_ref(); + let dll_suffix = self.target.dll_suffix.as_ref(); + if file.starts_with(dll_prefix) && file.ends_with(dll_suffix) { + return Some(dylibs); + } + None + })(); + match type_via_filename { + Some(type_via_filename) => { + type_via_filename.insert(loc_canon.clone(), PathKind::ExternFlag); + } + None => { + self.crate_rejections + .via_filename + .push(CrateMismatch { path: loc_orig.clone(), got: String::new() }); } - } else { - self.crate_rejections - .via_filename - .push(CrateMismatch { path: loc_orig.clone(), got: String::new() }); } } From e3800a1a04f338ce69bd403f230a019cebc54ece Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 9 Aug 2023 00:31:26 +0000 Subject: [PATCH 10/13] Allow dropping dyn principal --- .../rustc_codegen_cranelift/src/unsize.rs | 4 +- compiler/rustc_codegen_ssa/src/base.rs | 5 +- .../src/solve/trait_goals.rs | 3 +- .../src/traits/select/candidate_assembly.rs | 2 +- .../src/traits/select/confirmation.rs | 4 ++ .../impl-trait/unsized_coercion5.next.stderr | 14 ----- .../impl-trait/unsized_coercion5.old.stderr | 18 +----- tests/ui/impl-trait/unsized_coercion5.rs | 2 +- tests/ui/traits/dyn-drop-principal.rs | 62 +++++++++++++++++++ tests/ui/traits/dyn-drop-principal.run.stdout | 4 ++ 10 files changed, 83 insertions(+), 35 deletions(-) delete mode 100644 tests/ui/impl-trait/unsized_coercion5.next.stderr create mode 100644 tests/ui/traits/dyn-drop-principal.rs create mode 100644 tests/ui/traits/dyn-drop-principal.run.stdout diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index 5c297ebfadbfd..336934354e11b 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -34,7 +34,9 @@ pub(crate) fn unsized_info<'tcx>( { let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); - if data_a.principal_def_id() == data_b.principal_def_id() { + let b_principal_def_id = data_b.principal_def_id(); + if data_a.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() { + // A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables. debug_assert!( validate_trivial_unsize(fx.tcx, data_a, data_b), "NOP unsize vtable changed principal trait ref: {data_a} -> {data_b}" diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index d91c0f0790d9d..f3d9a7d37e6cc 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -147,7 +147,7 @@ pub fn validate_trivial_unsize<'tcx>( infcx.leak_check(universe, None).is_ok() }) } - (None, None) => true, + (_, None) => true, _ => false, } } @@ -175,7 +175,8 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( { let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); - if data_a.principal_def_id() == data_b.principal_def_id() { + let b_principal_def_id = data_b.principal_def_id(); + if data_a.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() { // Codegen takes advantage of the additional assumption, where if the // principal trait def id of what's being casted doesn't change, // then we don't need to adjust the vtable at all. This diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 5828b2ecf34d5..2cbed0bceb2d9 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -785,7 +785,8 @@ where let mut responses = vec![]; // If the principal def ids match (or are both none), then we're not doing // trait upcasting. We're just removing auto traits (or shortening the lifetime). - if a_data.principal_def_id() == b_data.principal_def_id() { + let b_principal_def_id = b_data.principal_def_id(); + if a_data.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() { responses.extend(self.consider_builtin_upcast_to_principal( goal, CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 52048ca79f92f..aa313a526c1db 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -1018,7 +1018,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // #2 (region bounds). let principal_def_id_a = a_data.principal_def_id(); let principal_def_id_b = b_data.principal_def_id(); - if principal_def_id_a == principal_def_id_b { + if principal_def_id_a == principal_def_id_b || principal_def_id_b.is_none() { // We may upcast to auto traits that are either explicitly listed in // the object type's bounds, or implied by the principal trait ref's // supertraits. diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index cc5c7532b5053..0ba3b4e6e5518 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1153,6 +1153,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`. let iter = data_a .principal() + .filter(|_| { + // optionally drop the principal, if we're unsizing to no principal + data_b.principal().is_some() + }) .map(|b| b.map_bound(ty::ExistentialPredicate::Trait)) .into_iter() .chain( diff --git a/tests/ui/impl-trait/unsized_coercion5.next.stderr b/tests/ui/impl-trait/unsized_coercion5.next.stderr deleted file mode 100644 index 5644ac7ab04bc..0000000000000 --- a/tests/ui/impl-trait/unsized_coercion5.next.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/unsized_coercion5.rs:16:32 - | -LL | let y: Box = x as Box; - | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `Send`, found trait `Trait + Send` - | | - | expected due to this - | - = note: expected struct `Box` - found struct `Box` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/unsized_coercion5.old.stderr b/tests/ui/impl-trait/unsized_coercion5.old.stderr index 06ad54b1f1d8b..e56c026b037c6 100644 --- a/tests/ui/impl-trait/unsized_coercion5.old.stderr +++ b/tests/ui/impl-trait/unsized_coercion5.old.stderr @@ -1,16 +1,5 @@ -error[E0308]: mismatched types - --> $DIR/unsized_coercion5.rs:16:32 - | -LL | let y: Box = x as Box; - | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `Send`, found trait `Trait + Send` - | | - | expected due to this - | - = note: expected struct `Box` - found struct `Box` - error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time - --> $DIR/unsized_coercion5.rs:16:32 + --> $DIR/unsized_coercion5.rs:17:32 | LL | let y: Box = x as Box; | ^ doesn't have a size known at compile-time @@ -18,7 +7,6 @@ LL | let y: Box = x as Box; = help: the trait `Sized` is not implemented for `impl Trait + ?Sized` = note: required for the cast from `Box` to `Box` -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/unsized_coercion5.rs b/tests/ui/impl-trait/unsized_coercion5.rs index 85d313caa1355..81f8a6afe9ac1 100644 --- a/tests/ui/impl-trait/unsized_coercion5.rs +++ b/tests/ui/impl-trait/unsized_coercion5.rs @@ -3,6 +3,7 @@ //@ revisions: next old //@[next] compile-flags: -Znext-solver +//@[next] check-pass #![feature(trait_upcasting)] @@ -15,7 +16,6 @@ fn hello() -> Box { let x = hello(); let y: Box = x as Box; //[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know - //~^^ ERROR: mismatched types } Box::new(1u32) } diff --git a/tests/ui/traits/dyn-drop-principal.rs b/tests/ui/traits/dyn-drop-principal.rs new file mode 100644 index 0000000000000..eeff0550fcbe3 --- /dev/null +++ b/tests/ui/traits/dyn-drop-principal.rs @@ -0,0 +1,62 @@ +//@ run-pass +//@ check-run-results + +use std::any::Any; + +const fn yeet_principal(x: Box) -> Box { + x +} + +trait Bar: Send + Sync {} + +impl Bar for T {} + +const fn yeet_principal_2(x: Box) -> Box { + x +} + +struct CallMe(Option); + +impl CallMe { + fn new(f: F) -> Self { + CallMe(Some(f)) + } +} + +impl Drop for CallMe { + fn drop(&mut self) { + (self.0.take().unwrap())(); + } +} + +fn goodbye() { + println!("goodbye"); +} + +fn main() { + let x = Box::new(CallMe::new(goodbye)) as Box; + let y = yeet_principal(x); + println!("before"); + drop(y); + + let x = Box::new(CallMe::new(goodbye)) as Box; + let y = yeet_principal_2(x); + println!("before"); + drop(y); +} + +// Test that upcast works in `const` + +const fn yeet_principal_3(x: &(dyn Any + Send + Sync)) -> &(dyn Send + Sync) { + x +} + +#[used] +pub static FOO: &(dyn Send + Sync) = yeet_principal_3(&false); + +const fn yeet_principal_4(x: &dyn Bar) -> &(dyn Send + Sync) { + x +} + +#[used] +pub static BAR: &(dyn Send + Sync) = yeet_principal_4(&false); diff --git a/tests/ui/traits/dyn-drop-principal.run.stdout b/tests/ui/traits/dyn-drop-principal.run.stdout new file mode 100644 index 0000000000000..edd99a114a112 --- /dev/null +++ b/tests/ui/traits/dyn-drop-principal.run.stdout @@ -0,0 +1,4 @@ +before +goodbye +before +goodbye From 4ab307f9e81e863f7f7946fd5f1183cd1b5cea22 Mon Sep 17 00:00:00 2001 From: lexx <35109763+lexeyOK@users.noreply.github.com> Date: Fri, 18 Oct 2024 01:04:01 +0500 Subject: [PATCH 11/13] Missing parenthesis the line was missing closing parenthesis --- library/core/src/macros/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 6a4f2af10efc6..771c2d31b60e0 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1550,7 +1550,7 @@ pub(crate) mod builtin { /// MODE is any of Forward, Reverse, ForwardFirst, ReverseFirst. /// INPUT_ACTIVITIES consists of one valid activity for each input parameter. /// OUTPUT_ACTIVITY must not be set if we implicitely return nothing (or explicitely return - /// `-> ()`. Otherwise it must be set to one of the allowed activities. + /// `-> ()`). Otherwise it must be set to one of the allowed activities. #[unstable(feature = "autodiff", issue = "124509")] #[allow_internal_unstable(rustc_attrs)] #[rustc_builtin_macro] From a09c54d4d34627444d4d1416930c11ffeebd0d2e Mon Sep 17 00:00:00 2001 From: Jan Sommer Date: Thu, 17 Oct 2024 11:03:45 +0200 Subject: [PATCH 12/13] Bump libc to 0.2.161 --- library/Cargo.lock | 6 +++--- library/std/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index 59b76d8d4427d..268367cd9c144 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -158,9 +158,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" dependencies = [ "rustc-std-workspace-core", ] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 358bd25ff1bc6..5f8dcde189bcf 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -39,7 +39,7 @@ miniz_oxide = { version = "0.7.0", optional = true, default-features = false } addr2line = { version = "0.22.0", optional = true, default-features = false } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] -libc = { version = "0.2.159", default-features = false, features = [ +libc = { version = "0.2.161", default-features = false, features = [ 'rustc-dep-of-std', ], public = true } From c4bce0b8b13f2ae39bfd01e55bf98a556b2d703f Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Wed, 10 Jul 2024 13:00:36 -0400 Subject: [PATCH 13/13] Add more tests --- src/tools/miri/tests/pass/dyn-upcast.rs | 51 +++++++++++++++++++ src/tools/miri/tests/pass/dyn-upcast.stdout | 4 ++ tests/ui/traits/dyn-drop-principal.rs | 8 ++- tests/ui/traits/dyn-star-drop-principal.rs | 12 +++++ .../ui/traits/dyn-star-drop-principal.stderr | 11 ++++ 5 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 src/tools/miri/tests/pass/dyn-upcast.stdout create mode 100644 tests/ui/traits/dyn-star-drop-principal.rs create mode 100644 tests/ui/traits/dyn-star-drop-principal.stderr diff --git a/src/tools/miri/tests/pass/dyn-upcast.rs b/src/tools/miri/tests/pass/dyn-upcast.rs index ff995f38196fa..306e9ab9c6715 100644 --- a/src/tools/miri/tests/pass/dyn-upcast.rs +++ b/src/tools/miri/tests/pass/dyn-upcast.rs @@ -9,6 +9,7 @@ fn main() { struct_(); replace_vptr(); vtable_nop_cast(); + drop_principal(); } fn vtable_nop_cast() { @@ -430,3 +431,53 @@ fn replace_vptr() { let s = S(42); invoke_outer(&s); } + +fn drop_principal() { + use std::{alloc::Layout, any::Any}; + + const fn yeet_principal(x: Box) -> Box { + x + } + + trait Bar: Send + Sync {} + + impl Bar for T {} + + const fn yeet_principal_2(x: Box) -> Box { + x + } + + struct CallMe(Option); + + impl CallMe { + fn new(f: F) -> Self { + CallMe(Some(f)) + } + } + + impl Drop for CallMe { + fn drop(&mut self) { + (self.0.take().unwrap())(); + } + } + + fn goodbye() { + println!("goodbye"); + } + + let x = Box::new(CallMe::new(goodbye)) as Box; + let x_layout = Layout::for_value(&*x); + let y = yeet_principal(x); + let y_layout = Layout::for_value(&*y); + assert_eq!(x_layout, y_layout); + println!("before"); + drop(y); + + let x = Box::new(CallMe::new(goodbye)) as Box; + let x_layout = Layout::for_value(&*x); + let y = yeet_principal_2(x); + let y_layout = Layout::for_value(&*y); + assert_eq!(x_layout, y_layout); + println!("before"); + drop(y); +} diff --git a/src/tools/miri/tests/pass/dyn-upcast.stdout b/src/tools/miri/tests/pass/dyn-upcast.stdout new file mode 100644 index 0000000000000..edd99a114a112 --- /dev/null +++ b/src/tools/miri/tests/pass/dyn-upcast.stdout @@ -0,0 +1,4 @@ +before +goodbye +before +goodbye diff --git a/tests/ui/traits/dyn-drop-principal.rs b/tests/ui/traits/dyn-drop-principal.rs index eeff0550fcbe3..c233127e43d2d 100644 --- a/tests/ui/traits/dyn-drop-principal.rs +++ b/tests/ui/traits/dyn-drop-principal.rs @@ -1,7 +1,7 @@ //@ run-pass //@ check-run-results -use std::any::Any; +use std::{alloc::Layout, any::Any}; const fn yeet_principal(x: Box) -> Box { x @@ -35,12 +35,18 @@ fn goodbye() { fn main() { let x = Box::new(CallMe::new(goodbye)) as Box; + let x_layout = Layout::for_value(&*x); let y = yeet_principal(x); + let y_layout = Layout::for_value(&*y); + assert_eq!(x_layout, y_layout); println!("before"); drop(y); let x = Box::new(CallMe::new(goodbye)) as Box; + let x_layout = Layout::for_value(&*x); let y = yeet_principal_2(x); + let y_layout = Layout::for_value(&*y); + assert_eq!(x_layout, y_layout); println!("before"); drop(y); } diff --git a/tests/ui/traits/dyn-star-drop-principal.rs b/tests/ui/traits/dyn-star-drop-principal.rs new file mode 100644 index 0000000000000..1ad99070339ad --- /dev/null +++ b/tests/ui/traits/dyn-star-drop-principal.rs @@ -0,0 +1,12 @@ +#![feature(dyn_star)] +#![allow(incomplete_features)] + +trait Trait {} +impl Trait for usize {} + +fn main() { + // We allow &dyn Trait + Send -> &dyn Send (i.e. dropping principal), + // but we don't (currently?) allow the same for dyn* + let x: dyn* Trait + Send = 1usize; + x as dyn* Send; //~ error: `dyn* Trait + Send` needs to have the same ABI as a pointer +} diff --git a/tests/ui/traits/dyn-star-drop-principal.stderr b/tests/ui/traits/dyn-star-drop-principal.stderr new file mode 100644 index 0000000000000..721ae7e191ef0 --- /dev/null +++ b/tests/ui/traits/dyn-star-drop-principal.stderr @@ -0,0 +1,11 @@ +error[E0277]: `dyn* Trait + Send` needs to have the same ABI as a pointer + --> $DIR/dyn-star-drop-principal.rs:11:5 + | +LL | x as dyn* Send; + | ^ `dyn* Trait + Send` needs to be a pointer-like type + | + = help: the trait `PointerLike` is not implemented for `dyn* Trait + Send` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`.