Skip to content

Commit 42b1224

Browse files
committed
Auto merge of rust-lang#116772 - matthiaskrgr:rollup-mpff3lh, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#116172 (Broaden the consequences of recursive TLS initialization) - rust-lang#116341 (Implement sys::args for UEFI) - rust-lang#116522 (use `PatKind::Error` when an ADT const value has violation) - rust-lang#116732 (Make x capable of resolving symlinks) - rust-lang#116755 (Remove me from libcore review rotation) - rust-lang#116760 (Remove trivial cast in `guaranteed_eq`) - rust-lang#116771 (Ignore let-chains formatting) r? `@ghost` `@rustbot` modify labels: rollup
2 parents f70779b + 66417cb commit 42b1224

File tree

12 files changed

+206
-9
lines changed

12 files changed

+206
-9
lines changed

.git-blame-ignore-revs

+2
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ b39a1d6f1a30ba29f25d7141038b9a5bf0126e36
1818
f97fddab91fbf290ea5b691fe355d6f915220b6e
1919
# format let-else
2020
cc907f80b95c6ec530c5ee1b05b044a468f07eca
21+
# format let-chains
22+
b2d2184edea578109a48ec3d8decbee5948e8f35

compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

+8
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,14 @@ impl<'tcx> ConstToPat<'tcx> {
198198
// We errored. Signal that in the pattern, so that follow up errors can be silenced.
199199
let kind = PatKind::Error(e);
200200
return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
201+
} else if let ty::Adt(..) = cv.ty().kind() && matches!(cv, mir::Const::Val(..)) {
202+
// This branch is only entered when the current `cv` is `mir::Const::Val`.
203+
// This is because `mir::Const::ty` has already been handled by `Self::recur`
204+
// and the invalid types may be ignored.
205+
let err = TypeNotStructural { span: self.span, non_sm_ty };
206+
let e = self.tcx().sess.emit_err(err);
207+
let kind = PatKind::Error(e);
208+
return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
201209
} else if !self.saw_const_match_lint.get() {
202210
if let Some(mir_structural_match_violation) = mir_structural_match_violation {
203211
match non_sm_ty.kind() {

library/core/src/ptr/const_ptr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ impl<T: ?Sized> *const T {
842842
where
843843
T: Sized,
844844
{
845-
match intrinsics::ptr_guaranteed_cmp(self as _, other as _) {
845+
match intrinsics::ptr_guaranteed_cmp(self, other) {
846846
2 => None,
847847
other => Some(other == 1),
848848
}

library/std/src/sys/uefi/args.rs

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
use r_efi::protocols::loaded_image;
2+
3+
use crate::env::current_exe;
4+
use crate::ffi::OsString;
5+
use crate::fmt;
6+
use crate::iter::Iterator;
7+
use crate::mem::size_of;
8+
use crate::sys::uefi::helpers;
9+
use crate::vec;
10+
11+
pub struct Args {
12+
parsed_args_list: vec::IntoIter<OsString>,
13+
}
14+
15+
pub fn args() -> Args {
16+
let lazy_current_exe = || Vec::from([current_exe().map(Into::into).unwrap_or_default()]);
17+
18+
// Each loaded image has an image handle that supports `EFI_LOADED_IMAGE_PROTOCOL`. Thus, this
19+
// will never fail.
20+
let protocol =
21+
helpers::image_handle_protocol::<loaded_image::Protocol>(loaded_image::PROTOCOL_GUID)
22+
.unwrap();
23+
24+
let lp_size = unsafe { (*protocol.as_ptr()).load_options_size } as usize;
25+
// Break if we are sure that it cannot be UTF-16
26+
if lp_size < size_of::<u16>() || lp_size % size_of::<u16>() != 0 {
27+
return Args { parsed_args_list: lazy_current_exe().into_iter() };
28+
}
29+
let lp_size = lp_size / size_of::<u16>();
30+
31+
let lp_cmd_line = unsafe { (*protocol.as_ptr()).load_options as *const u16 };
32+
if !lp_cmd_line.is_aligned() {
33+
return Args { parsed_args_list: lazy_current_exe().into_iter() };
34+
}
35+
let lp_cmd_line = unsafe { crate::slice::from_raw_parts(lp_cmd_line, lp_size) };
36+
37+
Args {
38+
parsed_args_list: parse_lp_cmd_line(lp_cmd_line)
39+
.unwrap_or_else(lazy_current_exe)
40+
.into_iter(),
41+
}
42+
}
43+
44+
impl fmt::Debug for Args {
45+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46+
self.parsed_args_list.as_slice().fmt(f)
47+
}
48+
}
49+
50+
impl Iterator for Args {
51+
type Item = OsString;
52+
53+
fn next(&mut self) -> Option<OsString> {
54+
self.parsed_args_list.next()
55+
}
56+
57+
fn size_hint(&self) -> (usize, Option<usize>) {
58+
self.parsed_args_list.size_hint()
59+
}
60+
}
61+
62+
impl ExactSizeIterator for Args {
63+
fn len(&self) -> usize {
64+
self.parsed_args_list.len()
65+
}
66+
}
67+
68+
impl DoubleEndedIterator for Args {
69+
fn next_back(&mut self) -> Option<OsString> {
70+
self.parsed_args_list.next_back()
71+
}
72+
}
73+
74+
/// Implements the UEFI command-line argument parsing algorithm.
75+
///
76+
/// This implementation is based on what is defined in Section 3.4 of
77+
/// [UEFI Shell Specification](https://uefi.org/sites/default/files/resources/UEFI_Shell_Spec_2_0.pdf)
78+
///
79+
/// Return None in the following cases:
80+
/// - Invalid UTF-16 (unpaired surrogate)
81+
/// - Empty/improper arguments
82+
fn parse_lp_cmd_line(code_units: &[u16]) -> Option<Vec<OsString>> {
83+
const QUOTE: char = '"';
84+
const SPACE: char = ' ';
85+
const CARET: char = '^';
86+
const NULL: char = '\0';
87+
88+
let mut ret_val = Vec::new();
89+
let mut code_units_iter = char::decode_utf16(code_units.iter().cloned()).peekable();
90+
91+
// The executable name at the beginning is special.
92+
let mut in_quotes = false;
93+
let mut cur = String::new();
94+
while let Some(w) = code_units_iter.next() {
95+
let w = w.ok()?;
96+
match w {
97+
// break on NULL
98+
NULL => break,
99+
// A quote mark always toggles `in_quotes` no matter what because
100+
// there are no escape characters when parsing the executable name.
101+
QUOTE => in_quotes = !in_quotes,
102+
// If not `in_quotes` then whitespace ends argv[0].
103+
SPACE if !in_quotes => break,
104+
// In all other cases the code unit is taken literally.
105+
_ => cur.push(w),
106+
}
107+
}
108+
109+
// If exe name is missing, the cli args are invalid
110+
if cur.is_empty() {
111+
return None;
112+
}
113+
114+
ret_val.push(OsString::from(cur));
115+
// Skip whitespace.
116+
while code_units_iter.next_if_eq(&Ok(SPACE)).is_some() {}
117+
118+
// Parse the arguments according to these rules:
119+
// * All code units are taken literally except space, quote and caret.
120+
// * When not `in_quotes`, space separate arguments. Consecutive spaces are
121+
// treated as a single separator.
122+
// * A space `in_quotes` is taken literally.
123+
// * A quote toggles `in_quotes` mode unless it's escaped. An escaped quote is taken literally.
124+
// * A quote can be escaped if preceded by caret.
125+
// * A caret can be escaped if preceded by caret.
126+
let mut cur = String::new();
127+
let mut in_quotes = false;
128+
while let Some(w) = code_units_iter.next() {
129+
let w = w.ok()?;
130+
match w {
131+
// break on NULL
132+
NULL => break,
133+
// If not `in_quotes`, a space or tab ends the argument.
134+
SPACE if !in_quotes => {
135+
ret_val.push(OsString::from(&cur[..]));
136+
cur.truncate(0);
137+
138+
// Skip whitespace.
139+
while code_units_iter.next_if_eq(&Ok(SPACE)).is_some() {}
140+
}
141+
// Caret can escape quotes or carets
142+
CARET if in_quotes => {
143+
if let Some(x) = code_units_iter.next() {
144+
cur.push(x.ok()?);
145+
}
146+
}
147+
// If quote then flip `in_quotes`
148+
QUOTE => in_quotes = !in_quotes,
149+
// Everything else is always taken literally.
150+
_ => cur.push(w),
151+
}
152+
}
153+
// Push the final argument, if any.
154+
if !cur.is_empty() || in_quotes {
155+
ret_val.push(OsString::from(cur));
156+
}
157+
Some(ret_val)
158+
}

library/std/src/sys/uefi/helpers.rs

+7
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,10 @@ pub(crate) unsafe fn close_event(evt: NonNull<crate::ffi::c_void>) -> io::Result
139139

140140
if r.is_error() { Err(crate::io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
141141
}
142+
143+
/// Get the Protocol for current system handle.
144+
/// Note: Some protocols need to be manually freed. It is the callers responsibility to do so.
145+
pub(crate) fn image_handle_protocol<T>(protocol_guid: Guid) -> Option<NonNull<T>> {
146+
let system_handle = uefi::env::try_image_handle()?;
147+
open_protocol(system_handle, protocol_guid).ok()
148+
}

library/std/src/sys/uefi/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
//! [`OsString`]: crate::ffi::OsString
1414
1515
pub mod alloc;
16-
#[path = "../unsupported/args.rs"]
1716
pub mod args;
1817
#[path = "../unix/cmath.rs"]
1918
pub mod cmath;

library/std/src/thread/local.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ use crate::fmt;
2929
/// within a thread, and values that implement [`Drop`] get destructed when a
3030
/// thread exits. Some caveats apply, which are explained below.
3131
///
32-
/// A `LocalKey`'s initializer cannot recursively depend on itself, and using
33-
/// a `LocalKey` in this way will cause the initializer to infinitely recurse
34-
/// on the first call to `with`.
32+
/// A `LocalKey`'s initializer cannot recursively depend on itself. Using a
33+
/// `LocalKey` in this way may cause panics, aborts or infinite recursion on
34+
/// the first call to `with`.
3535
///
3636
/// # Examples
3737
///

src/doc/rustc/src/platform-support/unknown-uefi.md

+2
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ cargo build --target x86_64-unknown-uefi -Zbuild-std=std,panic_abort
268268
#### stdio
269269
- Uses `Simple Text Input Protocol` and `Simple Text Output Protocol`.
270270
- Note: UEFI uses CRLF for new line. This means Enter key is registered as CR instead of LF.
271+
#### args
272+
- Uses `EFI_LOADED_IMAGE_PROTOCOL->LoadOptions`
271273

272274
## Example: Hello World With std
273275
The following code features a valid UEFI application, including `stdio` and `alloc` (`OsString` and `Vec`):

tests/ui/pattern/issue-115599.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const CONST_STRING: String = String::new();
2+
3+
fn main() {
4+
let empty_str = String::from("");
5+
if let CONST_STRING = empty_str {}
6+
//~^ ERROR to use a constant of type `Vec<u8>` in a pattern, `Vec<u8>` must be annotated with `#[derive(PartialEq, Eq)]`
7+
}

tests/ui/pattern/issue-115599.stderr

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: to use a constant of type `Vec<u8>` in a pattern, `Vec<u8>` must be annotated with `#[derive(PartialEq, Eq)]`
2+
--> $DIR/issue-115599.rs:5:12
3+
|
4+
LL | if let CONST_STRING = empty_str {}
5+
| ^^^^^^^^^^^^
6+
|
7+
= note: the traits must be derived, manual `impl`s are not sufficient
8+
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
9+
10+
error: aborting due to previous error
11+

triagebot.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,7 @@ style-team = [
728728
"/compiler/rustc_traits" = ["compiler", "types"]
729729
"/compiler/rustc_type_ir" = ["compiler", "types"]
730730
"/library/alloc" = ["libs"]
731-
"/library/core" = ["libs", "@scottmcm"]
731+
"/library/core" = ["libs"]
732732
"/library/panic_abort" = ["libs"]
733733
"/library/panic_unwind" = ["libs"]
734734
"/library/proc_macro" = ["@petrochenkov"]

x

+6-3
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@ set -eu
1111
sh -n "$0"
1212

1313
realpath() {
14-
if [ -d "$1" ]; then
15-
CDPATH='' command cd "$1" && pwd -P
14+
local path="$1"
15+
if [ -L "$path" ]; then
16+
readlink -f "$path"
17+
elif [ -d "$path" ]; then
18+
(cd -P "$path" && pwd)
1619
else
17-
echo "$(realpath "$(dirname "$1")")/$(basename "$1")"
20+
echo "$(realpath "$(dirname "$path")")/$(basename "$path")"
1821
fi
1922
}
2023

0 commit comments

Comments
 (0)