Skip to content

Commit 978b3e0

Browse files
committed
Auto merge of rust-lang#121897 - matthiaskrgr:rollup-89tcmau, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - rust-lang#121194 (Refactor pre-getopts command line argument handling) - rust-lang#121666 (Use the OS thread name by default if `THREAD_INFO` has not been initialized) - rust-lang#121758 (Move thread local implementation to `sys`) - rust-lang#121759 (attempt to further clarify addr_of docs) - rust-lang#121888 (style library/core/src/error.rs) - rust-lang#121892 (The ordinary lowering of `thir::ExprKind::Let` is unreachable) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 5257aee + 6eaf971 commit 978b3e0

File tree

69 files changed

+510
-140
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+510
-140
lines changed

compiler/rustc_driver_impl/src/args.rs

+41-14
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
use std::error;
2-
use std::fmt;
3-
use std::fs;
4-
use std::io;
1+
use std::{env, error, fmt, fs, io};
52

63
use rustc_session::EarlyDiagCtxt;
4+
use rustc_span::ErrorGuaranteed;
75

86
/// Expands argfiles in command line arguments.
97
#[derive(Default)]
@@ -86,41 +84,70 @@ impl Expander {
8684
fn read_file(path: &str) -> Result<String, Error> {
8785
fs::read_to_string(path).map_err(|e| {
8886
if e.kind() == io::ErrorKind::InvalidData {
89-
Error::Utf8Error(Some(path.to_string()))
87+
Error::Utf8Error(path.to_string())
9088
} else {
9189
Error::IOError(path.to_string(), e)
9290
}
9391
})
9492
}
9593
}
9694

95+
/// Replaces any `@file` arguments with the contents of `file`, with each line of `file` as a
96+
/// separate argument.
97+
///
9798
/// **Note:** This function doesn't interpret argument 0 in any special way.
9899
/// If this function is intended to be used with command line arguments,
99100
/// `argv[0]` must be removed prior to calling it manually.
100-
pub fn arg_expand_all(early_dcx: &EarlyDiagCtxt, at_args: &[String]) -> Vec<String> {
101+
pub fn arg_expand_all(
102+
early_dcx: &EarlyDiagCtxt,
103+
at_args: &[String],
104+
) -> Result<Vec<String>, ErrorGuaranteed> {
101105
let mut expander = Expander::default();
106+
let mut result = Ok(());
102107
for arg in at_args {
103108
if let Err(err) = expander.arg(arg) {
104-
early_dcx.early_fatal(format!("Failed to load argument file: {err}"));
109+
result = Err(early_dcx.early_err(format!("failed to load argument file: {err}")));
105110
}
106111
}
107-
expander.finish()
112+
result.map(|()| expander.finish())
113+
}
114+
115+
/// Gets the raw unprocessed command-line arguments as Unicode strings, without doing any further
116+
/// processing (e.g., without `@file` expansion).
117+
///
118+
/// This function is identical to [`env::args()`] except that it emits an error when it encounters
119+
/// non-Unicode arguments instead of panicking.
120+
pub fn raw_args(early_dcx: &EarlyDiagCtxt) -> Result<Vec<String>, ErrorGuaranteed> {
121+
let mut res = Ok(Vec::new());
122+
for (i, arg) in env::args_os().enumerate() {
123+
match arg.into_string() {
124+
Ok(arg) => {
125+
if let Ok(args) = &mut res {
126+
args.push(arg);
127+
}
128+
}
129+
Err(arg) => {
130+
res =
131+
Err(early_dcx.early_err(format!("argument {i} is not valid Unicode: {arg:?}")))
132+
}
133+
}
134+
}
135+
res
108136
}
109137

110138
#[derive(Debug)]
111-
pub enum Error {
112-
Utf8Error(Option<String>),
139+
enum Error {
140+
Utf8Error(String),
113141
IOError(String, io::Error),
114142
ShellParseError(String),
115143
}
116144

117145
impl fmt::Display for Error {
118146
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
119147
match self {
120-
Error::Utf8Error(None) => write!(fmt, "Utf8 error"),
121-
Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"),
122-
Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"),
123-
Error::ShellParseError(path) => write!(fmt, "Invalid shell-style arguments in {path}"),
148+
Error::Utf8Error(path) => write!(fmt, "UTF-8 error in {path}"),
149+
Error::IOError(path, err) => write!(fmt, "IO error: {path}: {err}"),
150+
Error::ShellParseError(path) => write!(fmt, "invalid shell-style arguments in {path}"),
124151
}
125152
}
126153
}

compiler/rustc_driver_impl/src/lib.rs

+2-10
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ fn run_compiler(
291291
// the compiler with @empty_file as argv[0] and no more arguments.
292292
let at_args = at_args.get(1..).unwrap_or_default();
293293

294-
let args = args::arg_expand_all(&default_early_dcx, at_args);
294+
let args = args::arg_expand_all(&default_early_dcx, at_args)?;
295295

296296
let Some(matches) = handle_options(&default_early_dcx, &args) else { return Ok(()) };
297297

@@ -1489,15 +1489,7 @@ pub fn main() -> ! {
14891489
let mut callbacks = TimePassesCallbacks::default();
14901490
let using_internal_features = install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ());
14911491
let exit_code = catch_with_exit_code(|| {
1492-
let args = env::args_os()
1493-
.enumerate()
1494-
.map(|(i, arg)| {
1495-
arg.into_string().unwrap_or_else(|arg| {
1496-
early_dcx.early_fatal(format!("argument {i} is not valid Unicode: {arg:?}"))
1497-
})
1498-
})
1499-
.collect::<Vec<_>>();
1500-
RunCompiler::new(&args, &mut callbacks)
1492+
RunCompiler::new(&args::raw_args(&early_dcx)?, &mut callbacks)
15011493
.set_using_internal_features(using_internal_features)
15021494
.run()
15031495
});

compiler/rustc_mir_build/src/build/expr/into.rs

+6-32
Original file line numberDiff line numberDiff line change
@@ -109,38 +109,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
109109
this.cfg.goto(else_blk, source_info, join_block);
110110
join_block.unit()
111111
}
112-
ExprKind::Let { expr, ref pat } => {
113-
let scope = this.local_scope();
114-
let (true_block, false_block) = this.in_if_then_scope(scope, expr_span, |this| {
115-
this.lower_let_expr(block, expr, pat, scope, None, expr_span, true)
116-
});
117-
118-
this.cfg.push_assign_constant(
119-
true_block,
120-
source_info,
121-
destination,
122-
ConstOperand {
123-
span: expr_span,
124-
user_ty: None,
125-
const_: Const::from_bool(this.tcx, true),
126-
},
127-
);
128-
129-
this.cfg.push_assign_constant(
130-
false_block,
131-
source_info,
132-
destination,
133-
ConstOperand {
134-
span: expr_span,
135-
user_ty: None,
136-
const_: Const::from_bool(this.tcx, false),
137-
},
138-
);
139-
140-
let join_block = this.cfg.start_new_block();
141-
this.cfg.goto(true_block, source_info, join_block);
142-
this.cfg.goto(false_block, source_info, join_block);
143-
join_block.unit()
112+
ExprKind::Let { .. } => {
113+
// After desugaring, `let` expressions should only appear inside `if`
114+
// expressions or `match` guards, possibly nested within a let-chain.
115+
// In both cases they are specifically handled by the lowerings of
116+
// those expressions, so this case is currently unreachable.
117+
span_bug!(expr_span, "unexpected let expression outside of if or match-guard");
144118
}
145119
ExprKind::NeverToAny { source } => {
146120
let source_expr = &this.thir[source];

library/core/src/error.rs

+1
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ pub trait Error: Debug + Display {
183183
#[allow(unused_variables)]
184184
fn provide<'a>(&'a self, request: &mut Request<'a>) {}
185185
}
186+
186187
mod private {
187188
// This is a hack to prevent `type_id` from being overridden by `Error`
188189
// implementations, since that can enable unsound downcasting.

library/core/src/ptr/mod.rs

+63-15
Original file line numberDiff line numberDiff line change
@@ -2071,11 +2071,16 @@ impl<F: FnPtr> fmt::Debug for F {
20712071
/// as all other references. This macro can create a raw pointer *without* creating
20722072
/// a reference first.
20732073
///
2074-
/// The `expr` in `addr_of!(expr)` is evaluated as a place expression, but never loads
2075-
/// from the place or requires the place to be dereferenceable. This means that
2076-
/// `addr_of!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned.
2077-
/// Note however that `addr_of!((*ptr).field)` still requires the projection to
2078-
/// `field` to be in-bounds, using the same rules as [`offset`].
2074+
/// See [`addr_of_mut`] for how to create a pointer to uninitialized data.
2075+
/// Doing that with `addr_of` would not make much sense since one could only
2076+
/// read the data, and that would be Undefined Behavior.
2077+
///
2078+
/// # Safety
2079+
///
2080+
/// The `expr` in `addr_of!(expr)` is evaluated as a place expression, but never loads from the
2081+
/// place or requires the place to be dereferenceable. This means that `addr_of!((*ptr).field)`
2082+
/// still requires the projection to `field` to be in-bounds, using the same rules as [`offset`].
2083+
/// However, `addr_of!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned.
20792084
///
20802085
/// Note that `Deref`/`Index` coercions (and their mutable counterparts) are applied inside
20812086
/// `addr_of!` like everywhere else, in which case a reference is created to call `Deref::deref` or
@@ -2086,6 +2091,8 @@ impl<F: FnPtr> fmt::Debug for F {
20862091
///
20872092
/// # Example
20882093
///
2094+
/// **Correct usage: Creating a pointer to unaligned data**
2095+
///
20892096
/// ```
20902097
/// use std::ptr;
20912098
///
@@ -2101,9 +2108,27 @@ impl<F: FnPtr> fmt::Debug for F {
21012108
/// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2);
21022109
/// ```
21032110
///
2104-
/// See [`addr_of_mut`] for how to create a pointer to uninitialized data.
2105-
/// Doing that with `addr_of` would not make much sense since one could only
2106-
/// read the data, and that would be Undefined Behavior.
2111+
/// **Incorrect usage: Out-of-bounds fields projection**
2112+
///
2113+
/// ```rust,no_run
2114+
/// use std::ptr;
2115+
///
2116+
/// #[repr(C)]
2117+
/// struct MyStruct {
2118+
/// field1: i32,
2119+
/// field2: i32,
2120+
/// }
2121+
///
2122+
/// let ptr: *const MyStruct = ptr::null();
2123+
/// let fieldptr = unsafe { ptr::addr_of!((*ptr).field2) }; // Undefined Behavior ⚠️
2124+
/// ```
2125+
///
2126+
/// The field projection `.field2` would offset the pointer by 4 bytes,
2127+
/// but the pointer is not in-bounds of an allocation for 4 bytes,
2128+
/// so this offset is Undefined Behavior.
2129+
/// See the [`offset`] docs for a full list of requirements for inbounds pointer arithmetic; the
2130+
/// same requirements apply to field projections, even inside `addr_of!`. (In particular, it makes
2131+
/// no difference whether the pointer is null or dangling.)
21072132
#[stable(feature = "raw_ref_macros", since = "1.51.0")]
21082133
#[rustc_macro_transparency = "semitransparent"]
21092134
#[allow_internal_unstable(raw_ref_op)]
@@ -2120,11 +2145,12 @@ pub macro addr_of($place:expr) {
21202145
/// as all other references. This macro can create a raw pointer *without* creating
21212146
/// a reference first.
21222147
///
2123-
/// The `expr` in `addr_of_mut!(expr)` is evaluated as a place expression, but never loads
2124-
/// from the place or requires the place to be dereferenceable. This means that
2125-
/// `addr_of_mut!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned.
2126-
/// Note however that `addr_of_mut!((*ptr).field)` still requires the projection to
2127-
/// `field` to be in-bounds, using the same rules as [`offset`].
2148+
/// # Safety
2149+
///
2150+
/// The `expr` in `addr_of_mut!(expr)` is evaluated as a place expression, but never loads from the
2151+
/// place or requires the place to be dereferenceable. This means that `addr_of_mut!((*ptr).field)`
2152+
/// still requires the projection to `field` to be in-bounds, using the same rules as [`offset`].
2153+
/// However, `addr_of_mut!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned.
21282154
///
21292155
/// Note that `Deref`/`Index` coercions (and their mutable counterparts) are applied inside
21302156
/// `addr_of_mut!` like everywhere else, in which case a reference is created to call `Deref::deref`
@@ -2135,7 +2161,7 @@ pub macro addr_of($place:expr) {
21352161
///
21362162
/// # Examples
21372163
///
2138-
/// **Creating a pointer to unaligned data:**
2164+
/// **Correct usage: Creating a pointer to unaligned data**
21392165
///
21402166
/// ```
21412167
/// use std::ptr;
@@ -2153,7 +2179,7 @@ pub macro addr_of($place:expr) {
21532179
/// assert_eq!({packed.f2}, 42); // `{...}` forces copying the field instead of creating a reference.
21542180
/// ```
21552181
///
2156-
/// **Creating a pointer to uninitialized data:**
2182+
/// **Correct usage: Creating a pointer to uninitialized data**
21572183
///
21582184
/// ```rust
21592185
/// use std::{ptr, mem::MaybeUninit};
@@ -2169,6 +2195,28 @@ pub macro addr_of($place:expr) {
21692195
/// unsafe { f1_ptr.write(true); }
21702196
/// let init = unsafe { uninit.assume_init() };
21712197
/// ```
2198+
///
2199+
/// **Incorrect usage: Out-of-bounds fields projection**
2200+
///
2201+
/// ```rust,no_run
2202+
/// use std::ptr;
2203+
///
2204+
/// #[repr(C)]
2205+
/// struct MyStruct {
2206+
/// field1: i32,
2207+
/// field2: i32,
2208+
/// }
2209+
///
2210+
/// let ptr: *mut MyStruct = ptr::null_mut();
2211+
/// let fieldptr = unsafe { ptr::addr_of_mut!((*ptr).field2) }; // Undefined Behavior ⚠️
2212+
/// ```
2213+
///
2214+
/// The field projection `.field2` would offset the pointer by 4 bytes,
2215+
/// but the pointer is not in-bounds of an allocation for 4 bytes,
2216+
/// so this offset is Undefined Behavior.
2217+
/// See the [`offset`] docs for a full list of requirements for inbounds pointer arithmetic; the
2218+
/// same requirements apply to field projections, even inside `addr_of_mut!`. (In particular, it
2219+
/// makes no difference whether the pointer is null or dangling.)
21722220
#[stable(feature = "raw_ref_macros", since = "1.51.0")]
21732221
#[rustc_macro_transparency = "semitransparent"]
21742222
#[allow_internal_unstable(raw_ref_op)]

library/std/src/sys/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ pub mod cmath;
99
pub mod locks;
1010
pub mod os_str;
1111
pub mod path;
12+
#[allow(dead_code)]
13+
#[allow(unused_imports)]
14+
pub mod thread_local;
1215

1316
// FIXME(117276): remove this, move feature implementations into individual
1417
// submodules.

library/std/src/sys/pal/common/mod.rs

-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212

1313
pub mod alloc;
1414
pub mod small_c_string;
15-
#[allow(unused_imports)]
16-
pub mod thread_local;
1715

1816
#[cfg(test)]
1917
mod tests;

library/std/src/sys/pal/hermit/thread.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use super::abi;
44
use super::thread_local_dtor::run_dtors;
5-
use crate::ffi::CStr;
5+
use crate::ffi::{CStr, CString};
66
use crate::io;
77
use crate::mem;
88
use crate::num::NonZero;
@@ -71,6 +71,10 @@ impl Thread {
7171
// nope
7272
}
7373

74+
pub fn get_name() -> Option<CString> {
75+
None
76+
}
77+
7478
#[inline]
7579
pub fn sleep(dur: Duration) {
7680
unsafe {

library/std/src/sys/pal/itron/thread.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use super::{
88
};
99
use crate::{
1010
cell::UnsafeCell,
11-
ffi::CStr,
11+
ffi::{CStr, CString},
1212
hint, io,
1313
mem::ManuallyDrop,
1414
num::NonZero,
@@ -204,6 +204,10 @@ impl Thread {
204204
// nope
205205
}
206206

207+
pub fn get_name() -> Option<CString> {
208+
None
209+
}
210+
207211
pub fn sleep(dur: Duration) {
208212
for timeout in dur2reltims(dur) {
209213
expect_success(unsafe { abi::dly_tsk(timeout) }, &"dly_tsk");

library/std/src/sys/pal/sgx/thread.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![cfg_attr(test, allow(dead_code))] // why is this necessary?
22
use super::unsupported;
3-
use crate::ffi::CStr;
3+
use crate::ffi::{CStr, CString};
44
use crate::io;
55
use crate::num::NonZero;
66
use crate::time::Duration;
@@ -133,6 +133,10 @@ impl Thread {
133133
// which succeeds as-is with the SGX target.
134134
}
135135

136+
pub fn get_name() -> Option<CString> {
137+
None
138+
}
139+
136140
pub fn sleep(dur: Duration) {
137141
usercalls::wait_timeout(0, dur, || true);
138142
}

library/std/src/sys/pal/teeos/thread.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use core::convert::TryInto;
22

33
use crate::cmp;
4-
use crate::ffi::CStr;
4+
use crate::ffi::{CStr, CString};
55
use crate::io;
66
use crate::mem;
77
use crate::num::NonZero;
@@ -101,6 +101,10 @@ impl Thread {
101101
// contact the teeos rustzone team.
102102
}
103103

104+
pub fn get_name() -> Option<CString> {
105+
None
106+
}
107+
104108
/// only main thread could wait for sometime in teeos
105109
pub fn sleep(dur: Duration) {
106110
let sleep_millis = dur.as_millis();

0 commit comments

Comments
 (0)