Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit db8043b

Browse files
committedOct 18, 2024
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
2 parents d9c4b8d + 13b3984 commit db8043b

File tree

28 files changed

+738
-121
lines changed

28 files changed

+738
-121
lines changed
 

‎compiler/rustc_codegen_cranelift/src/unsize.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ pub(crate) fn unsized_info<'tcx>(
3434
{
3535
let old_info =
3636
old_info.expect("unsized_info: missing old info for trait upcasting coercion");
37-
if data_a.principal_def_id() == data_b.principal_def_id() {
37+
let b_principal_def_id = data_b.principal_def_id();
38+
if data_a.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
39+
// A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables.
3840
debug_assert!(
3941
validate_trivial_unsize(fx.tcx, data_a, data_b),
4042
"NOP unsize vtable changed principal trait ref: {data_a} -> {data_b}"

‎compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ pub fn validate_trivial_unsize<'tcx>(
147147
infcx.leak_check(universe, None).is_ok()
148148
})
149149
}
150-
(None, None) => true,
150+
(_, None) => true,
151151
_ => false,
152152
}
153153
}
@@ -175,7 +175,8 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
175175
{
176176
let old_info =
177177
old_info.expect("unsized_info: missing old info for trait upcasting coercion");
178-
if data_a.principal_def_id() == data_b.principal_def_id() {
178+
let b_principal_def_id = data_b.principal_def_id();
179+
if data_a.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
179180
// Codegen takes advantage of the additional assumption, where if the
180181
// principal trait def id of what's being casted doesn't change,
181182
// then we don't need to adjust the vtable at all. This

‎compiler/rustc_metadata/src/locator.rs

Lines changed: 49 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -499,8 +499,11 @@ impl<'a> CrateLocator<'a> {
499499
dylibs: FxIndexMap<PathBuf, PathKind>,
500500
) -> Result<Option<(Svh, Library)>, CrateError> {
501501
let mut slot = None;
502-
// Order here matters, rmeta should come first. See comment in
503-
// `extract_one` below.
502+
// Order here matters, rmeta should come first.
503+
//
504+
// Make sure there's at most one rlib and at most one dylib.
505+
//
506+
// See comment in `extract_one` below.
504507
let source = CrateSource {
505508
rmeta: self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot)?,
506509
rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot)?,
@@ -706,54 +709,58 @@ impl<'a> CrateLocator<'a> {
706709
let mut rmetas = FxIndexMap::default();
707710
let mut dylibs = FxIndexMap::default();
708711
for loc in &self.exact_paths {
709-
if !loc.canonicalized().exists() {
710-
return Err(CrateError::ExternLocationNotExist(
711-
self.crate_name,
712-
loc.original().clone(),
713-
));
712+
let loc_canon = loc.canonicalized();
713+
let loc_orig = loc.original();
714+
if !loc_canon.exists() {
715+
return Err(CrateError::ExternLocationNotExist(self.crate_name, loc_orig.clone()));
714716
}
715-
if !loc.original().is_file() {
716-
return Err(CrateError::ExternLocationNotFile(
717-
self.crate_name,
718-
loc.original().clone(),
719-
));
717+
if !loc_orig.is_file() {
718+
return Err(CrateError::ExternLocationNotFile(self.crate_name, loc_orig.clone()));
720719
}
721-
let Some(file) = loc.original().file_name().and_then(|s| s.to_str()) else {
722-
return Err(CrateError::ExternLocationNotFile(
723-
self.crate_name,
724-
loc.original().clone(),
725-
));
720+
// Note to take care and match against the non-canonicalized name:
721+
// some systems save build artifacts into content-addressed stores
722+
// that do not preserve extensions, and then link to them using
723+
// e.g. symbolic links. If we canonicalize too early, we resolve
724+
// the symlink, the file type is lost and we might treat rlibs and
725+
// rmetas as dylibs.
726+
let Some(file) = loc_orig.file_name().and_then(|s| s.to_str()) else {
727+
return Err(CrateError::ExternLocationNotFile(self.crate_name, loc_orig.clone()));
726728
};
727-
728-
if file.starts_with("lib") && (file.ends_with(".rlib") || file.ends_with(".rmeta"))
729-
|| file.starts_with(self.target.dll_prefix.as_ref())
730-
&& file.ends_with(self.target.dll_suffix.as_ref())
731-
{
732-
// Make sure there's at most one rlib and at most one dylib.
733-
// Note to take care and match against the non-canonicalized name:
734-
// some systems save build artifacts into content-addressed stores
735-
// that do not preserve extensions, and then link to them using
736-
// e.g. symbolic links. If we canonicalize too early, we resolve
737-
// the symlink, the file type is lost and we might treat rlibs and
738-
// rmetas as dylibs.
739-
let loc_canon = loc.canonicalized().clone();
740-
let loc = loc.original();
741-
if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
742-
rlibs.insert(loc_canon, PathKind::ExternFlag);
743-
} else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") {
744-
rmetas.insert(loc_canon, PathKind::ExternFlag);
745-
} else {
746-
dylibs.insert(loc_canon, PathKind::ExternFlag);
729+
// FnMut cannot return reference to captured value, so references
730+
// must be taken outside the closure.
731+
let rlibs = &mut rlibs;
732+
let rmetas = &mut rmetas;
733+
let dylibs = &mut dylibs;
734+
let type_via_filename = (|| {
735+
if file.starts_with("lib") {
736+
if file.ends_with(".rlib") {
737+
return Some(rlibs);
738+
}
739+
if file.ends_with(".rmeta") {
740+
return Some(rmetas);
741+
}
742+
}
743+
let dll_prefix = self.target.dll_prefix.as_ref();
744+
let dll_suffix = self.target.dll_suffix.as_ref();
745+
if file.starts_with(dll_prefix) && file.ends_with(dll_suffix) {
746+
return Some(dylibs);
747+
}
748+
None
749+
})();
750+
match type_via_filename {
751+
Some(type_via_filename) => {
752+
type_via_filename.insert(loc_canon.clone(), PathKind::ExternFlag);
753+
}
754+
None => {
755+
self.crate_rejections
756+
.via_filename
757+
.push(CrateMismatch { path: loc_orig.clone(), got: String::new() });
747758
}
748-
} else {
749-
self.crate_rejections
750-
.via_filename
751-
.push(CrateMismatch { path: loc.original().clone(), got: String::new() });
752759
}
753760
}
754761

755762
// Extract the dylib/rlib/rmeta triple.
756-
Ok(self.extract_lib(rlibs, rmetas, dylibs)?.map(|(_, lib)| lib))
763+
self.extract_lib(rlibs, rmetas, dylibs).map(|opt| opt.map(|(_, lib)| lib))
757764
}
758765

759766
pub(crate) fn into_error(self, root: Option<CratePaths>) -> CrateError {

‎compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,8 @@ where
785785
let mut responses = vec![];
786786
// If the principal def ids match (or are both none), then we're not doing
787787
// trait upcasting. We're just removing auto traits (or shortening the lifetime).
788-
if a_data.principal_def_id() == b_data.principal_def_id() {
788+
let b_principal_def_id = b_data.principal_def_id();
789+
if a_data.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
789790
responses.extend(self.consider_builtin_upcast_to_principal(
790791
goal,
791792
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),

‎compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10181018
// #2 (region bounds).
10191019
let principal_def_id_a = a_data.principal_def_id();
10201020
let principal_def_id_b = b_data.principal_def_id();
1021-
if principal_def_id_a == principal_def_id_b {
1021+
if principal_def_id_a == principal_def_id_b || principal_def_id_b.is_none() {
10221022
// We may upcast to auto traits that are either explicitly listed in
10231023
// the object type's bounds, or implied by the principal trait ref's
10241024
// supertraits.

‎compiler/rustc_trait_selection/src/traits/select/confirmation.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11531153
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
11541154
let iter = data_a
11551155
.principal()
1156+
.filter(|_| {
1157+
// optionally drop the principal, if we're unsizing to no principal
1158+
data_b.principal().is_some()
1159+
})
11561160
.map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
11571161
.into_iter()
11581162
.chain(

‎library/Cargo.lock

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This file is automatically @generated by Cargo.
22
# It is not intended for manual editing.
3-
version = 3
3+
version = 4
44

55
[[package]]
66
name = "addr2line"
@@ -124,9 +124,9 @@ dependencies = [
124124

125125
[[package]]
126126
name = "gimli"
127-
version = "0.30.0"
127+
version = "0.31.1"
128128
source = "registry+https://github.com/rust-lang/crates.io-index"
129-
checksum = "e2e1d97fbe9722ba9bbd0c97051c2956e726562b61f86a25a4360398a40edfc9"
129+
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
130130
dependencies = [
131131
"compiler_builtins",
132132
"rustc-std-workspace-alloc",
@@ -158,9 +158,9 @@ dependencies = [
158158

159159
[[package]]
160160
name = "libc"
161-
version = "0.2.159"
161+
version = "0.2.161"
162162
source = "registry+https://github.com/rust-lang/crates.io-index"
163-
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
163+
checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
164164
dependencies = [
165165
"rustc-std-workspace-core",
166166
]
@@ -406,12 +406,12 @@ dependencies = [
406406

407407
[[package]]
408408
name = "unwinding"
409-
version = "0.2.2"
409+
version = "0.2.3"
410410
source = "registry+https://github.com/rust-lang/crates.io-index"
411-
checksum = "dc55842d0db6329a669d55a623c674b02d677b16bfb2d24857d4089d41eba882"
411+
checksum = "637d511437df708cee34bdec7ba2f1548d256b7acf3ff20e0a1c559f9bf3a987"
412412
dependencies = [
413413
"compiler_builtins",
414-
"gimli 0.30.0",
414+
"gimli 0.31.1",
415415
"rustc-std-workspace-core",
416416
]
417417

‎library/core/src/macros/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1550,7 +1550,7 @@ pub(crate) mod builtin {
15501550
/// MODE is any of Forward, Reverse, ForwardFirst, ReverseFirst.
15511551
/// INPUT_ACTIVITIES consists of one valid activity for each input parameter.
15521552
/// OUTPUT_ACTIVITY must not be set if we implicitely return nothing (or explicitely return
1553-
/// `-> ()`. Otherwise it must be set to one of the allowed activities.
1553+
/// `-> ()`). Otherwise it must be set to one of the allowed activities.
15541554
#[unstable(feature = "autodiff", issue = "124509")]
15551555
#[allow_internal_unstable(rustc_attrs)]
15561556
#[rustc_builtin_macro]

‎library/std/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ miniz_oxide = { version = "0.7.0", optional = true, default-features = false }
3939
addr2line = { version = "0.22.0", optional = true, default-features = false }
4040

4141
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
42-
libc = { version = "0.2.159", default-features = false, features = [
42+
libc = { version = "0.2.161", default-features = false, features = [
4343
'rustc-dep-of-std',
4444
], public = true }
4545

‎library/std/src/os/xous/ffi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ pub(crate) fn thread_id() -> Result<ThreadId, Error> {
615615
/// An error is generated if the `knob` is not a valid limit, or if the call
616616
/// would not succeed.
617617
pub(crate) fn adjust_limit(knob: Limits, current: usize, new: usize) -> Result<usize, Error> {
618-
let mut a0 = Syscall::JoinThread as usize;
618+
let mut a0 = Syscall::AdjustProcessLimit as usize;
619619
let mut a1 = knob as usize;
620620
let a2 = current;
621621
let a3 = new;

‎library/std/src/sys/alloc/xous.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
2+
#![allow(static_mut_refs)]
3+
14
use crate::alloc::{GlobalAlloc, Layout, System};
25

36
#[cfg(not(test))]

‎library/std/src/sys/pal/xous/args.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use crate::ffi::OsString;
2+
use crate::sys::pal::xous::os::get_application_parameters;
3+
use crate::sys::pal::xous::os::params::ArgumentList;
4+
use crate::{fmt, vec};
5+
6+
pub struct Args {
7+
parsed_args_list: vec::IntoIter<OsString>,
8+
}
9+
10+
pub fn args() -> Args {
11+
let Some(params) = get_application_parameters() else {
12+
return Args { parsed_args_list: vec![].into_iter() };
13+
};
14+
15+
for param in params {
16+
if let Ok(args) = ArgumentList::try_from(&param) {
17+
let mut parsed_args = vec![];
18+
for arg in args {
19+
parsed_args.push(arg.into());
20+
}
21+
return Args { parsed_args_list: parsed_args.into_iter() };
22+
}
23+
}
24+
Args { parsed_args_list: vec![].into_iter() }
25+
}
26+
27+
impl fmt::Debug for Args {
28+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29+
self.parsed_args_list.as_slice().fmt(f)
30+
}
31+
}
32+
33+
impl Iterator for Args {
34+
type Item = OsString;
35+
fn next(&mut self) -> Option<OsString> {
36+
self.parsed_args_list.next()
37+
}
38+
fn size_hint(&self) -> (usize, Option<usize>) {
39+
self.parsed_args_list.size_hint()
40+
}
41+
}
42+
43+
impl DoubleEndedIterator for Args {
44+
fn next_back(&mut self) -> Option<OsString> {
45+
self.parsed_args_list.next_back()
46+
}
47+
}
48+
49+
impl ExactSizeIterator for Args {
50+
fn len(&self) -> usize {
51+
self.parsed_args_list.len()
52+
}
53+
}

‎library/std/src/sys/pal/xous/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#![forbid(unsafe_op_in_unsafe_fn)]
22

3-
#[path = "../unsupported/args.rs"]
43
pub mod args;
54
#[path = "../unsupported/env.rs"]
65
pub mod env;

‎library/std/src/sys/pal/xous/net/dns.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::os::xous::ffi::lend_mut;
66
use crate::os::xous::services::{DnsLendMut, dns_server};
77

88
pub struct DnsError {
9+
#[allow(dead_code)]
910
pub code: u8,
1011
}
1112

‎library/std/src/sys/pal/xous/net/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ pub mod netc {
6060

6161
#[derive(Copy, Clone)]
6262
pub struct sockaddr_in {
63+
#[allow(dead_code)]
6364
pub sin_family: sa_family_t,
6465
pub sin_port: u16,
6566
pub sin_addr: in_addr,
@@ -72,6 +73,7 @@ pub mod netc {
7273

7374
#[derive(Copy, Clone)]
7475
pub struct sockaddr_in6 {
76+
#[allow(dead_code)]
7577
pub sin6_family: sa_family_t,
7678
pub sin6_port: u16,
7779
pub sin6_addr: in6_addr,

‎library/std/src/sys/pal/xous/os.rs

Lines changed: 105 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,35 @@
11
use super::unsupported;
2+
use crate::collections::HashMap;
23
use crate::error::Error as StdError;
34
use crate::ffi::{OsStr, OsString};
45
use crate::marker::PhantomData;
56
use crate::os::xous::ffi::Error as XousError;
67
use crate::path::{self, PathBuf};
7-
use crate::{fmt, io};
8+
use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
9+
use crate::sync::{Mutex, Once};
10+
use crate::{fmt, io, vec};
11+
12+
pub(crate) mod params;
13+
14+
static PARAMS_ADDRESS: AtomicPtr<u8> = AtomicPtr::new(core::ptr::null_mut());
815

916
#[cfg(not(test))]
1017
#[cfg(feature = "panic_unwind")]
1118
mod eh_unwinding {
12-
pub(crate) struct EhFrameFinder(usize /* eh_frame */);
13-
pub(crate) static mut EH_FRAME_SETTINGS: EhFrameFinder = EhFrameFinder(0);
14-
impl EhFrameFinder {
15-
pub(crate) unsafe fn init(&mut self, eh_frame: usize) {
16-
unsafe {
17-
EH_FRAME_SETTINGS.0 = eh_frame;
18-
}
19-
}
20-
}
19+
pub(crate) struct EhFrameFinder;
20+
pub(crate) static mut EH_FRAME_ADDRESS: usize = 0;
21+
pub(crate) static EH_FRAME_SETTINGS: EhFrameFinder = EhFrameFinder;
22+
2123
unsafe impl unwind::EhFrameFinder for EhFrameFinder {
2224
fn find(&self, _pc: usize) -> Option<unwind::FrameInfo> {
23-
Some(unwind::FrameInfo {
24-
text_base: None,
25-
kind: unwind::FrameInfoKind::EhFrame(self.0),
26-
})
25+
if unsafe { EH_FRAME_ADDRESS == 0 } {
26+
None
27+
} else {
28+
Some(unwind::FrameInfo {
29+
text_base: None,
30+
kind: unwind::FrameInfoKind::EhFrame(unsafe { EH_FRAME_ADDRESS }),
31+
})
32+
}
2733
}
2834
}
2935
}
@@ -41,12 +47,21 @@ mod c_compat {
4147
}
4248

4349
#[no_mangle]
44-
pub extern "C" fn _start(eh_frame: usize) {
50+
pub extern "C" fn _start(eh_frame: usize, params_address: usize) {
4551
#[cfg(feature = "panic_unwind")]
46-
unsafe {
47-
super::eh_unwinding::EH_FRAME_SETTINGS.init(eh_frame);
52+
{
53+
unsafe { super::eh_unwinding::EH_FRAME_ADDRESS = eh_frame };
4854
unwind::set_custom_eh_frame_finder(&super::eh_unwinding::EH_FRAME_SETTINGS).ok();
4955
}
56+
57+
if params_address != 0 {
58+
let params_address = crate::ptr::with_exposed_provenance_mut::<u8>(params_address);
59+
if unsafe {
60+
super::params::ApplicationParameters::new_from_ptr(params_address).is_some()
61+
} {
62+
super::PARAMS_ADDRESS.store(params_address, core::sync::atomic::Ordering::Relaxed);
63+
}
64+
}
5065
exit(unsafe { main() });
5166
}
5267

@@ -116,44 +131,103 @@ pub fn current_exe() -> io::Result<PathBuf> {
116131
unsupported()
117132
}
118133

119-
pub struct Env(!);
134+
pub(crate) fn get_application_parameters() -> Option<params::ApplicationParameters> {
135+
let params_address = PARAMS_ADDRESS.load(Ordering::Relaxed);
136+
unsafe { params::ApplicationParameters::new_from_ptr(params_address) }
137+
}
138+
139+
// ---------- Environment handling ---------- //
140+
static ENV: AtomicUsize = AtomicUsize::new(0);
141+
static ENV_INIT: Once = Once::new();
142+
type EnvStore = Mutex<HashMap<OsString, OsString>>;
143+
144+
fn get_env_store() -> &'static EnvStore {
145+
ENV_INIT.call_once(|| {
146+
let env_store = EnvStore::default();
147+
if let Some(params) = get_application_parameters() {
148+
for param in params {
149+
if let Ok(envs) = params::EnvironmentBlock::try_from(&param) {
150+
let mut env_store = env_store.lock().unwrap();
151+
for env in envs {
152+
env_store.insert(env.key.into(), env.value.into());
153+
}
154+
break;
155+
}
156+
}
157+
}
158+
ENV.store(Box::into_raw(Box::new(env_store)) as _, Ordering::Relaxed)
159+
});
160+
unsafe { &*core::ptr::with_exposed_provenance::<EnvStore>(ENV.load(Ordering::Relaxed)) }
161+
}
162+
163+
pub struct Env {
164+
iter: vec::IntoIter<(OsString, OsString)>,
165+
}
166+
167+
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
168+
pub struct EnvStrDebug<'a> {
169+
slice: &'a [(OsString, OsString)],
170+
}
171+
172+
impl fmt::Debug for EnvStrDebug<'_> {
173+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174+
let Self { slice } = self;
175+
f.debug_list()
176+
.entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
177+
.finish()
178+
}
179+
}
120180

121181
impl Env {
122182
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
123183
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
124-
let Self(inner) = self;
125-
match *inner {}
184+
let Self { iter } = self;
185+
EnvStrDebug { slice: iter.as_slice() }
126186
}
127187
}
128188

129189
impl fmt::Debug for Env {
130-
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
131-
let Self(inner) = self;
132-
match *inner {}
190+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191+
let Self { iter } = self;
192+
f.debug_list().entries(iter.as_slice()).finish()
133193
}
134194
}
135195

196+
impl !Send for Env {}
197+
impl !Sync for Env {}
198+
136199
impl Iterator for Env {
137200
type Item = (OsString, OsString);
138201
fn next(&mut self) -> Option<(OsString, OsString)> {
139-
self.0
202+
self.iter.next()
203+
}
204+
fn size_hint(&self) -> (usize, Option<usize>) {
205+
self.iter.size_hint()
140206
}
141207
}
142208

143209
pub fn env() -> Env {
144-
panic!("not supported on this platform")
210+
let clone_to_vec = |map: &HashMap<OsString, OsString>| -> Vec<_> {
211+
map.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
212+
};
213+
214+
let iter = clone_to_vec(&*get_env_store().lock().unwrap()).into_iter();
215+
Env { iter }
145216
}
146217

147-
pub fn getenv(_: &OsStr) -> Option<OsString> {
148-
None
218+
pub fn getenv(k: &OsStr) -> Option<OsString> {
219+
get_env_store().lock().unwrap().get(k).cloned()
149220
}
150221

151-
pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
152-
Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))
222+
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
223+
let (k, v) = (k.to_owned(), v.to_owned());
224+
get_env_store().lock().unwrap().insert(k, v);
225+
Ok(())
153226
}
154227

155-
pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {
156-
Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))
228+
pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> {
229+
get_env_store().lock().unwrap().remove(k);
230+
Ok(())
157231
}
158232

159233
pub fn temp_dir() -> PathBuf {
Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
/// Xous passes a pointer to the parameter block as the second argument.
2+
/// This is used for passing flags such as environment variables. The
3+
/// format of the argument block is:
4+
///
5+
/// #[repr(C)]
6+
/// struct BlockHeader {
7+
/// /// Magic number that identifies this block. Must be printable ASCII.
8+
/// magic: [u8; 4],
9+
///
10+
/// /// The size of the data block. Does not include this header. May be 0.
11+
/// size: u32,
12+
///
13+
/// /// The contents of this block. Varies depending on the block type.
14+
/// data: [u8; 0],
15+
/// }
16+
///
17+
/// There is a BlockHeader at the start that has magic `AppP`, and the data
18+
/// that follows is the number of blocks present:
19+
///
20+
/// #[repr(C)]
21+
/// struct ApplicationParameters {
22+
/// magic: b"AppP",
23+
/// size: 4u32,
24+
///
25+
/// /// The size of the entire application slice, in bytes, including all headers
26+
/// length: u32,
27+
///
28+
/// /// Number of application parameters present. Must be at least 1 (this block)
29+
/// entries: (parameter_count as u32).to_bytes_le(),
30+
/// }
31+
///
32+
/// #[repr(C)]
33+
/// struct EnvironmentBlock {
34+
/// magic: b"EnvB",
35+
///
36+
/// /// Total number of bytes, excluding this header
37+
/// size: 2+data.len(),
38+
///
39+
/// /// The number of environment variables
40+
/// count: u16,
41+
///
42+
/// /// Environment variable iteration
43+
/// data: [u8; 0],
44+
/// }
45+
///
46+
/// Environment variables are present in an `EnvB` block. The `data` section is
47+
/// a sequence of bytes of the form:
48+
///
49+
/// (u16 /* key_len */; [0u8; key_len as usize] /* key */,
50+
/// u16 /* val_len */ [0u8; val_len as usize])
51+
///
52+
/// #[repr(C)]
53+
/// struct ArgumentList {
54+
/// magic: b"ArgL",
55+
///
56+
/// /// Total number of bytes, excluding this header
57+
/// size: 2+data.len(),
58+
///
59+
/// /// The number of arguments variables
60+
/// count: u16,
61+
///
62+
/// /// Argument variable iteration
63+
/// data: [u8; 0],
64+
/// }
65+
///
66+
/// Args are just an array of strings that represent command line arguments.
67+
/// They are a sequence of the form:
68+
///
69+
/// (u16 /* val_len */ [0u8; val_len as usize])
70+
use core::slice;
71+
72+
use crate::ffi::OsString;
73+
74+
/// Magic number indicating we have an environment block
75+
const ENV_MAGIC: [u8; 4] = *b"EnvB";
76+
77+
/// Command line arguments list
78+
const ARGS_MAGIC: [u8; 4] = *b"ArgL";
79+
80+
/// Magic number indicating the loader has passed application parameters
81+
const PARAMS_MAGIC: [u8; 4] = *b"AppP";
82+
83+
#[cfg(test)]
84+
mod tests;
85+
86+
pub(crate) struct ApplicationParameters {
87+
data: &'static [u8],
88+
offset: usize,
89+
_entries: usize,
90+
}
91+
92+
impl ApplicationParameters {
93+
pub(crate) unsafe fn new_from_ptr(data: *const u8) -> Option<ApplicationParameters> {
94+
if data.is_null() {
95+
return None;
96+
}
97+
98+
let magic = unsafe { core::slice::from_raw_parts(data, 4) };
99+
let block_length = unsafe {
100+
u32::from_le_bytes(slice::from_raw_parts(data.add(4), 4).try_into().ok()?) as usize
101+
};
102+
let data_length = unsafe {
103+
u32::from_le_bytes(slice::from_raw_parts(data.add(8), 4).try_into().ok()?) as usize
104+
};
105+
let entries = unsafe {
106+
u32::from_le_bytes(slice::from_raw_parts(data.add(12), 4).try_into().ok()?) as usize
107+
};
108+
109+
// Check for the main header
110+
if data_length < 16 || magic != PARAMS_MAGIC || block_length != 8 {
111+
return None;
112+
}
113+
114+
let data = unsafe { slice::from_raw_parts(data, data_length) };
115+
116+
Some(ApplicationParameters { data, offset: 0, _entries: entries })
117+
}
118+
}
119+
120+
impl Iterator for ApplicationParameters {
121+
type Item = ApplicationParameter;
122+
123+
fn next(&mut self) -> Option<Self::Item> {
124+
// Fetch magic, ensuring we don't run off the end
125+
if self.offset + 4 > self.data.len() {
126+
return None;
127+
}
128+
let magic = &self.data[self.offset..self.offset + 4];
129+
self.offset += 4;
130+
131+
// Fetch header size
132+
if self.offset + 4 > self.data.len() {
133+
return None;
134+
}
135+
let size = u32::from_le_bytes(self.data[self.offset..self.offset + 4].try_into().unwrap())
136+
as usize;
137+
self.offset += 4;
138+
139+
// Fetch data contents
140+
if self.offset + size > self.data.len() {
141+
return None;
142+
}
143+
let data = &self.data[self.offset..self.offset + size];
144+
self.offset += size;
145+
146+
Some(ApplicationParameter { data, magic: magic.try_into().unwrap() })
147+
}
148+
}
149+
150+
pub(crate) struct ApplicationParameter {
151+
data: &'static [u8],
152+
magic: [u8; 4],
153+
}
154+
155+
pub(crate) struct ApplicationParameterError;
156+
157+
pub(crate) struct EnvironmentBlock {
158+
_count: usize,
159+
data: &'static [u8],
160+
offset: usize,
161+
}
162+
163+
impl TryFrom<&ApplicationParameter> for EnvironmentBlock {
164+
type Error = ApplicationParameterError;
165+
166+
fn try_from(value: &ApplicationParameter) -> Result<Self, Self::Error> {
167+
if value.data.len() < 2 || value.magic != ENV_MAGIC {
168+
return Err(ApplicationParameterError);
169+
}
170+
171+
let count = u16::from_le_bytes(value.data[0..2].try_into().unwrap()) as usize;
172+
173+
Ok(EnvironmentBlock { data: &value.data[2..], offset: 0, _count: count })
174+
}
175+
}
176+
177+
pub(crate) struct EnvironmentEntry {
178+
pub key: &'static str,
179+
pub value: &'static str,
180+
}
181+
182+
impl Iterator for EnvironmentBlock {
183+
type Item = EnvironmentEntry;
184+
185+
fn next(&mut self) -> Option<Self::Item> {
186+
if self.offset + 2 > self.data.len() {
187+
return None;
188+
}
189+
let key_len =
190+
u16::from_le_bytes(self.data[self.offset..self.offset + 2].try_into().ok()?) as usize;
191+
self.offset += 2;
192+
193+
if self.offset + key_len > self.data.len() {
194+
return None;
195+
}
196+
let key = core::str::from_utf8(&self.data[self.offset..self.offset + key_len]).ok()?;
197+
self.offset += key_len;
198+
199+
if self.offset + 2 > self.data.len() {
200+
return None;
201+
}
202+
let value_len =
203+
u16::from_le_bytes(self.data[self.offset..self.offset + 2].try_into().ok()?) as usize;
204+
self.offset += 2;
205+
206+
if self.offset + value_len > self.data.len() {
207+
return None;
208+
}
209+
let value = core::str::from_utf8(&self.data[self.offset..self.offset + value_len]).ok()?;
210+
self.offset += value_len;
211+
212+
Some(EnvironmentEntry { key, value })
213+
}
214+
}
215+
216+
pub(crate) struct ArgumentList {
217+
data: &'static [u8],
218+
_count: usize,
219+
offset: usize,
220+
}
221+
222+
impl TryFrom<&ApplicationParameter> for ArgumentList {
223+
type Error = ApplicationParameterError;
224+
225+
fn try_from(value: &ApplicationParameter) -> Result<Self, Self::Error> {
226+
if value.data.len() < 2 || value.magic != ARGS_MAGIC {
227+
return Err(ApplicationParameterError);
228+
}
229+
let count =
230+
u16::from_le_bytes(value.data[0..2].try_into().or(Err(ApplicationParameterError))?)
231+
as usize;
232+
Ok(ArgumentList { data: &value.data[2..], _count: count, offset: 0 })
233+
}
234+
}
235+
236+
pub(crate) struct ArgumentEntry {
237+
value: &'static str,
238+
}
239+
240+
impl Into<&str> for ArgumentEntry {
241+
fn into(self) -> &'static str {
242+
self.value
243+
}
244+
}
245+
246+
impl Into<OsString> for ArgumentEntry {
247+
fn into(self) -> OsString {
248+
self.value.into()
249+
}
250+
}
251+
252+
impl Iterator for ArgumentList {
253+
type Item = ArgumentEntry;
254+
255+
fn next(&mut self) -> Option<Self::Item> {
256+
if self.offset + 2 > self.data.len() {
257+
return None;
258+
}
259+
let value_len =
260+
u16::from_le_bytes(self.data[self.offset..self.offset + 2].try_into().ok()?) as usize;
261+
self.offset += 2;
262+
263+
if self.offset + value_len > self.data.len() {
264+
return None;
265+
}
266+
let value = core::str::from_utf8(&self.data[self.offset..self.offset + value_len]).ok()?;
267+
self.offset += value_len;
268+
269+
Some(ArgumentEntry { value })
270+
}
271+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use super::*;
2+
use crate::collections::HashMap;
3+
use crate::io::Write;
4+
5+
fn create_args_test() -> std::io::Result<Vec<u8>> {
6+
let mut sample_data = vec![];
7+
let mut h = HashMap::new();
8+
9+
h.insert("foo", "bar");
10+
h.insert("baz", "qux");
11+
h.insert("some", "val");
12+
13+
// Magic number
14+
sample_data.write_all(&PARAMS_MAGIC)?;
15+
// Size of the AppP block
16+
sample_data.write_all(&4u32.to_le_bytes())?;
17+
// Number of blocks
18+
sample_data.write_all(&2u32.to_le_bytes())?;
19+
20+
// Magic number
21+
sample_data.write_all(&ENV_MAGIC)?;
22+
let mut data = vec![];
23+
for (key, value) in h.iter() {
24+
data.extend_from_slice(&(key.len() as u16).to_le_bytes());
25+
data.extend_from_slice(key.as_bytes());
26+
data.extend_from_slice(&(value.len() as u16).to_le_bytes());
27+
data.extend_from_slice(value.as_bytes());
28+
}
29+
// Size of the EnvB block
30+
sample_data.write_all(&(data.len() as u32 + 2).to_le_bytes())?;
31+
32+
// Number of environment variables
33+
sample_data.write_all(&(h.len() as u16).to_le_bytes())?;
34+
35+
// Environment variables
36+
sample_data.write_all(&data)?;
37+
38+
// Write command line arguments
39+
let args = vec!["some", "command", "line variable", "entries"];
40+
sample_data.write_all(&ARGS_MAGIC)?;
41+
let mut args_size = 0;
42+
for entry in args.iter() {
43+
args_size += entry.len() + 2;
44+
}
45+
sample_data.write_all(&(args_size as u32 + 2).to_le_bytes())?;
46+
sample_data.write_all(&(args.len() as u16).to_le_bytes())?;
47+
for entry in args {
48+
sample_data.write_all(&(entry.len() as u16).to_le_bytes())?;
49+
sample_data.write_all(entry.as_bytes())?;
50+
}
51+
52+
Ok(sample_data)
53+
}
54+
55+
#[test]
56+
fn basic_arg_parsing() {
57+
let arg_data = create_args_test().expect("couldn't create test data");
58+
for byte in &arg_data {
59+
print!("{:02x} ", byte);
60+
}
61+
println!();
62+
63+
let args = ApplicationParameters::new(&arg_data).expect("Unable to parse arguments");
64+
for arg in args {
65+
if let Ok(env) = EnvironmentBlock::try_from(&arg) {
66+
for env in env {
67+
println!("{}={}", env.key, env.value);
68+
}
69+
} else if let Ok(args) = ArgumentList::try_from(&arg) {
70+
for arg in args {
71+
println!("Arg: {}", arg.value);
72+
}
73+
}
74+
}
75+
}

‎library/unwind/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ cfg-if = "1.0"
2222
libc = { version = "0.2.140", features = ['rustc-dep-of-std'], default-features = false }
2323

2424
[target.'cfg(target_os = "xous")'.dependencies]
25-
unwinding = { version = "0.2.1", features = ['rustc-dep-of-std', 'unwinder', 'fde-custom'], default-features = false }
25+
unwinding = { version = "0.2.3", features = ['rustc-dep-of-std', 'unwinder', 'fde-custom'], default-features = false }
2626

2727
[features]
2828

‎src/tools/miri/tests/pass/dyn-upcast.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ fn main() {
99
struct_();
1010
replace_vptr();
1111
vtable_nop_cast();
12+
drop_principal();
1213
}
1314

1415
fn vtable_nop_cast() {
@@ -430,3 +431,53 @@ fn replace_vptr() {
430431
let s = S(42);
431432
invoke_outer(&s);
432433
}
434+
435+
fn drop_principal() {
436+
use std::{alloc::Layout, any::Any};
437+
438+
const fn yeet_principal(x: Box<dyn Any + Send>) -> Box<dyn Send> {
439+
x
440+
}
441+
442+
trait Bar: Send + Sync {}
443+
444+
impl<T: Send + Sync> Bar for T {}
445+
446+
const fn yeet_principal_2(x: Box<dyn Bar>) -> Box<dyn Send> {
447+
x
448+
}
449+
450+
struct CallMe<F: FnOnce()>(Option<F>);
451+
452+
impl<F: FnOnce()> CallMe<F> {
453+
fn new(f: F) -> Self {
454+
CallMe(Some(f))
455+
}
456+
}
457+
458+
impl<F: FnOnce()> Drop for CallMe<F> {
459+
fn drop(&mut self) {
460+
(self.0.take().unwrap())();
461+
}
462+
}
463+
464+
fn goodbye() {
465+
println!("goodbye");
466+
}
467+
468+
let x = Box::new(CallMe::new(goodbye)) as Box<dyn Any + Send>;
469+
let x_layout = Layout::for_value(&*x);
470+
let y = yeet_principal(x);
471+
let y_layout = Layout::for_value(&*y);
472+
assert_eq!(x_layout, y_layout);
473+
println!("before");
474+
drop(y);
475+
476+
let x = Box::new(CallMe::new(goodbye)) as Box<dyn Bar>;
477+
let x_layout = Layout::for_value(&*x);
478+
let y = yeet_principal_2(x);
479+
let y_layout = Layout::for_value(&*y);
480+
assert_eq!(x_layout, y_layout);
481+
println!("before");
482+
drop(y);
483+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
before
2+
goodbye
3+
before
4+
goodbye

‎tests/ui/impl-trait/unsized_coercion5.next.stderr

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,12 @@
1-
error[E0308]: mismatched types
2-
--> $DIR/unsized_coercion5.rs:16:32
3-
|
4-
LL | let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
5-
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `Send`, found trait `Trait + Send`
6-
| |
7-
| expected due to this
8-
|
9-
= note: expected struct `Box<dyn Send>`
10-
found struct `Box<dyn Trait + Send>`
11-
121
error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
13-
--> $DIR/unsized_coercion5.rs:16:32
2+
--> $DIR/unsized_coercion5.rs:17:32
143
|
154
LL | let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
165
| ^ doesn't have a size known at compile-time
176
|
187
= help: the trait `Sized` is not implemented for `impl Trait + ?Sized`
198
= note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Trait + Send>`
209

21-
error: aborting due to 2 previous errors
10+
error: aborting due to 1 previous error
2211

23-
Some errors have detailed explanations: E0277, E0308.
24-
For more information about an error, try `rustc --explain E0277`.
12+
For more information about this error, try `rustc --explain E0277`.

‎tests/ui/impl-trait/unsized_coercion5.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
44
//@ revisions: next old
55
//@[next] compile-flags: -Znext-solver
6+
//@[next] check-pass
67

78
#![feature(trait_upcasting)]
89

@@ -15,7 +16,6 @@ fn hello() -> Box<impl Trait + ?Sized> {
1516
let x = hello();
1617
let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
1718
//[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
18-
//~^^ ERROR: mismatched types
1919
}
2020
Box::new(1u32)
2121
}

‎tests/ui/traits/dyn-drop-principal.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//@ run-pass
2+
//@ check-run-results
3+
4+
use std::{alloc::Layout, any::Any};
5+
6+
const fn yeet_principal(x: Box<dyn Any + Send>) -> Box<dyn Send> {
7+
x
8+
}
9+
10+
trait Bar: Send + Sync {}
11+
12+
impl<T: Send + Sync> Bar for T {}
13+
14+
const fn yeet_principal_2(x: Box<dyn Bar>) -> Box<dyn Send> {
15+
x
16+
}
17+
18+
struct CallMe<F: FnOnce()>(Option<F>);
19+
20+
impl<F: FnOnce()> CallMe<F> {
21+
fn new(f: F) -> Self {
22+
CallMe(Some(f))
23+
}
24+
}
25+
26+
impl<F: FnOnce()> Drop for CallMe<F> {
27+
fn drop(&mut self) {
28+
(self.0.take().unwrap())();
29+
}
30+
}
31+
32+
fn goodbye() {
33+
println!("goodbye");
34+
}
35+
36+
fn main() {
37+
let x = Box::new(CallMe::new(goodbye)) as Box<dyn Any + Send>;
38+
let x_layout = Layout::for_value(&*x);
39+
let y = yeet_principal(x);
40+
let y_layout = Layout::for_value(&*y);
41+
assert_eq!(x_layout, y_layout);
42+
println!("before");
43+
drop(y);
44+
45+
let x = Box::new(CallMe::new(goodbye)) as Box<dyn Bar>;
46+
let x_layout = Layout::for_value(&*x);
47+
let y = yeet_principal_2(x);
48+
let y_layout = Layout::for_value(&*y);
49+
assert_eq!(x_layout, y_layout);
50+
println!("before");
51+
drop(y);
52+
}
53+
54+
// Test that upcast works in `const`
55+
56+
const fn yeet_principal_3(x: &(dyn Any + Send + Sync)) -> &(dyn Send + Sync) {
57+
x
58+
}
59+
60+
#[used]
61+
pub static FOO: &(dyn Send + Sync) = yeet_principal_3(&false);
62+
63+
const fn yeet_principal_4(x: &dyn Bar) -> &(dyn Send + Sync) {
64+
x
65+
}
66+
67+
#[used]
68+
pub static BAR: &(dyn Send + Sync) = yeet_principal_4(&false);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
before
2+
goodbye
3+
before
4+
goodbye
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![feature(dyn_star)]
2+
#![allow(incomplete_features)]
3+
4+
trait Trait {}
5+
impl Trait for usize {}
6+
7+
fn main() {
8+
// We allow &dyn Trait + Send -> &dyn Send (i.e. dropping principal),
9+
// but we don't (currently?) allow the same for dyn*
10+
let x: dyn* Trait + Send = 1usize;
11+
x as dyn* Send; //~ error: `dyn* Trait + Send` needs to have the same ABI as a pointer
12+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0277]: `dyn* Trait + Send` needs to have the same ABI as a pointer
2+
--> $DIR/dyn-star-drop-principal.rs:11:5
3+
|
4+
LL | x as dyn* Send;
5+
| ^ `dyn* Trait + Send` needs to be a pointer-like type
6+
|
7+
= help: the trait `PointerLike` is not implemented for `dyn* Trait + Send`
8+
9+
error: aborting due to 1 previous error
10+
11+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)
Please sign in to comment.