mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Auto merge of #131869 - matthiaskrgr:rollup-xrkz174, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #131654 (Various fixes for Xous) - #131743 (rustc_metadata: minor tidying) - #131823 (Bump libc to 0.2.161) - #131850 (Missing parenthesis) - #131857 (Allow dropping dyn principal) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
db8043bb19
@ -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}"
|
||||
|
@ -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
|
||||
|
@ -499,8 +499,11 @@ impl<'a> CrateLocator<'a> {
|
||||
dylibs: FxIndexMap<PathBuf, PathKind>,
|
||||
) -> Result<Option<(Svh, Library)>, 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)?,
|
||||
@ -706,54 +709,58 @@ 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())
|
||||
{
|
||||
// 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
|
||||
// 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") {
|
||||
rlibs.insert(loc_canon, PathKind::ExternFlag);
|
||||
} else if loc.file_name().unwrap().to_str().unwrap().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.original().clone(), got: String::new() });
|
||||
}
|
||||
}
|
||||
|
||||
// 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<CratePaths>) -> CrateError {
|
||||
|
@ -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),
|
||||
|
@ -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.
|
||||
|
@ -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(
|
||||
|
@ -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",
|
||||
@ -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",
|
||||
]
|
||||
@ -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",
|
||||
]
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -615,7 +615,7 @@ pub(crate) fn thread_id() -> Result<ThreadId, Error> {
|
||||
/// 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<usize, Error> {
|
||||
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;
|
||||
|
@ -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))]
|
||||
|
53
library/std/src/sys/pal/xous/args.rs
Normal file
53
library/std/src/sys/pal/xous/args.rs
Normal file
@ -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<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)]
|
||||
|
||||
#[path = "../unsupported/args.rs"]
|
||||
pub mod args;
|
||||
#[path = "../unsupported/env.rs"]
|
||||
pub mod env;
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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<u8> = 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<unwind::FrameInfo> {
|
||||
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::<u8>(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<PathBuf> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub struct Env(!);
|
||||
pub(crate) fn get_application_parameters() -> Option<params::ApplicationParameters> {
|
||||
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<HashMap<OsString, OsString>>;
|
||||
|
||||
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::<EnvStore>(ENV.load(Ordering::Relaxed)) }
|
||||
}
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
}
|
||||
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::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 <OsStr as Debug>::fmt matches <str as Debug>::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<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
panic!("not supported on this platform")
|
||||
let clone_to_vec = |map: &HashMap<OsString, OsString>| -> 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<OsString> {
|
||||
None
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
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 {
|
||||
|
271
library/std/src/sys/pal/xous/os/params.rs
Normal file
271
library/std/src/sys/pal/xous/os/params.rs
Normal file
@ -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<ApplicationParameters> {
|
||||
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<Self::Item> {
|
||||
// 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<Self, Self::Error> {
|
||||
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<Self::Item> {
|
||||
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<Self, Self::Error> {
|
||||
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<OsString> for ArgumentEntry {
|
||||
fn into(self) -> OsString {
|
||||
self.value.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for ArgumentList {
|
||||
type Item = ArgumentEntry;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
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 })
|
||||
}
|
||||
}
|
75
library/std/src/sys/pal/xous/os/params/tests.rs
Normal file
75
library/std/src/sys/pal/xous/os/params/tests.rs
Normal file
@ -0,0 +1,75 @@
|
||||
use super::*;
|
||||
use crate::collections::HashMap;
|
||||
use crate::io::Write;
|
||||
|
||||
fn create_args_test() -> std::io::Result<Vec<u8>> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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]
|
||||
|
||||
|
@ -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<dyn Any + Send>) -> Box<dyn Send> {
|
||||
x
|
||||
}
|
||||
|
||||
trait Bar: Send + Sync {}
|
||||
|
||||
impl<T: Send + Sync> Bar for T {}
|
||||
|
||||
const fn yeet_principal_2(x: Box<dyn Bar>) -> Box<dyn Send> {
|
||||
x
|
||||
}
|
||||
|
||||
struct CallMe<F: FnOnce()>(Option<F>);
|
||||
|
||||
impl<F: FnOnce()> CallMe<F> {
|
||||
fn new(f: F) -> Self {
|
||||
CallMe(Some(f))
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: FnOnce()> Drop for CallMe<F> {
|
||||
fn drop(&mut self) {
|
||||
(self.0.take().unwrap())();
|
||||
}
|
||||
}
|
||||
|
||||
fn goodbye() {
|
||||
println!("goodbye");
|
||||
}
|
||||
|
||||
let x = Box::new(CallMe::new(goodbye)) as Box<dyn Any + Send>;
|
||||
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<dyn Bar>;
|
||||
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);
|
||||
}
|
||||
|
4
src/tools/miri/tests/pass/dyn-upcast.stdout
Normal file
4
src/tools/miri/tests/pass/dyn-upcast.stdout
Normal file
@ -0,0 +1,4 @@
|
||||
before
|
||||
goodbye
|
||||
before
|
||||
goodbye
|
@ -1,14 +0,0 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/unsized_coercion5.rs:16:32
|
||||
|
|
||||
LL | let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
|
||||
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `Send`, found trait `Trait + Send`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected struct `Box<dyn Send>`
|
||||
found struct `Box<dyn Trait + Send>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -1,16 +1,5 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/unsized_coercion5.rs:16:32
|
||||
|
|
||||
LL | let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
|
||||
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `Send`, found trait `Trait + Send`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected struct `Box<dyn Send>`
|
||||
found struct `Box<dyn Trait + Send>`
|
||||
|
||||
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<dyn Send> = x as Box<dyn Trait + Send>;
|
||||
| ^ doesn't have a size known at compile-time
|
||||
@ -18,7 +7,6 @@ LL | let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
|
||||
= help: the trait `Sized` is not implemented for `impl Trait + ?Sized`
|
||||
= note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Trait + Send>`
|
||||
|
||||
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`.
|
||||
|
@ -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<impl Trait + ?Sized> {
|
||||
let x = hello();
|
||||
let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
|
||||
//[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
|
||||
//~^^ ERROR: mismatched types
|
||||
}
|
||||
Box::new(1u32)
|
||||
}
|
||||
|
68
tests/ui/traits/dyn-drop-principal.rs
Normal file
68
tests/ui/traits/dyn-drop-principal.rs
Normal file
@ -0,0 +1,68 @@
|
||||
//@ run-pass
|
||||
//@ check-run-results
|
||||
|
||||
use std::{alloc::Layout, any::Any};
|
||||
|
||||
const fn yeet_principal(x: Box<dyn Any + Send>) -> Box<dyn Send> {
|
||||
x
|
||||
}
|
||||
|
||||
trait Bar: Send + Sync {}
|
||||
|
||||
impl<T: Send + Sync> Bar for T {}
|
||||
|
||||
const fn yeet_principal_2(x: Box<dyn Bar>) -> Box<dyn Send> {
|
||||
x
|
||||
}
|
||||
|
||||
struct CallMe<F: FnOnce()>(Option<F>);
|
||||
|
||||
impl<F: FnOnce()> CallMe<F> {
|
||||
fn new(f: F) -> Self {
|
||||
CallMe(Some(f))
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: FnOnce()> Drop for CallMe<F> {
|
||||
fn drop(&mut self) {
|
||||
(self.0.take().unwrap())();
|
||||
}
|
||||
}
|
||||
|
||||
fn goodbye() {
|
||||
println!("goodbye");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = Box::new(CallMe::new(goodbye)) as Box<dyn Any + Send>;
|
||||
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<dyn Bar>;
|
||||
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);
|
||||
}
|
||||
|
||||
// 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);
|
4
tests/ui/traits/dyn-drop-principal.run.stdout
Normal file
4
tests/ui/traits/dyn-drop-principal.run.stdout
Normal file
@ -0,0 +1,4 @@
|
||||
before
|
||||
goodbye
|
||||
before
|
||||
goodbye
|
12
tests/ui/traits/dyn-star-drop-principal.rs
Normal file
12
tests/ui/traits/dyn-star-drop-principal.rs
Normal file
@ -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
|
||||
}
|
11
tests/ui/traits/dyn-star-drop-principal.stderr
Normal file
11
tests/ui/traits/dyn-star-drop-principal.stderr
Normal file
@ -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`.
|
Loading…
Reference in New Issue
Block a user