Auto merge of #148462 - Zalathar:rollup-6gckwu6, r=Zalathar

Rollup of 8 pull requests

Successful merges:

 - rust-lang/rust#133149 (Provide more context on `Fn` closure modifying binding)
 - rust-lang/rust#145915 (Stabilize `fmt::from_fn`)
 - rust-lang/rust#145974 (Stabilize -Zno-jump-tables into -Cjump-tables=bool)
 - rust-lang/rust#146057 (feat: add `from_fn_ptr` to `Waker` and `LocalWaker`)
 - rust-lang/rust#146301 (library: std: sys: net: uefi: tcp: Implement write_vectored)
 - rust-lang/rust#148437 (Regression test for undefined `__chkstk` on `aarch64-unknown-uefi`)
 - rust-lang/rust#148448 (Update books)
 - rust-lang/rust#148451 (tidy: Fix false positives with absolute repo paths in `pal.rs` `check()`)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors
2025-11-04 02:46:43 +00:00
36 changed files with 320 additions and 83 deletions
@@ -150,8 +150,8 @@ pub(crate) fn report_mutability_error(
}
}
}
PlaceRef { local: _, projection: [proj_base @ .., ProjectionElem::Deref] } => {
if the_place_err.local == ty::CAPTURE_STRUCT_LOCAL
PlaceRef { local, projection: [proj_base @ .., ProjectionElem::Deref] } => {
if local == ty::CAPTURE_STRUCT_LOCAL
&& proj_base.is_empty()
&& !self.upvars.is_empty()
{
@@ -165,10 +165,8 @@ pub(crate) fn report_mutability_error(
", as `Fn` closures cannot mutate their captured variables".to_string()
}
} else {
let source = self.borrowed_content_source(PlaceRef {
local: the_place_err.local,
projection: proj_base,
});
let source =
self.borrowed_content_source(PlaceRef { local, projection: proj_base });
let pointer_type = source.describe_for_immutable_place(self.infcx.tcx);
opt_source = Some(source);
if let Some(desc) = self.describe_place(access_place.as_ref()) {
@@ -540,6 +538,7 @@ pub(crate) fn report_mutability_error(
PlaceRef { local, projection: [ProjectionElem::Deref] }
if local == ty::CAPTURE_STRUCT_LOCAL && !self.upvars.is_empty() =>
{
self.point_at_binding_outside_closure(&mut err, local, access_place);
self.expected_fn_found_fn_mut_call(&mut err, span, act);
}
@@ -958,6 +957,50 @@ fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) -> Self::Result {
}
}
/// When modifying a binding from inside of an `Fn` closure, point at the binding definition.
fn point_at_binding_outside_closure(
&self,
err: &mut Diag<'_>,
local: Local,
access_place: Place<'tcx>,
) {
let place = access_place.as_ref();
for (index, elem) in place.projection.into_iter().enumerate() {
if let ProjectionElem::Deref = elem {
if index == 0 {
if self.body.local_decls[local].is_ref_for_guard() {
continue;
}
if let LocalInfo::StaticRef { .. } = *self.body.local_decls[local].local_info()
{
continue;
}
}
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
local,
projection: place.projection.split_at(index + 1).0,
}) {
let var_index = field.index();
let upvar = self.upvars[var_index];
if let Some(hir_id) = upvar.info.capture_kind_expr_id {
let node = self.infcx.tcx.hir_node(hir_id);
if let hir::Node::Expr(expr) = node
&& let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
&& let hir::def::Res::Local(hir_id) = path.res
&& let hir::Node::Pat(pat) = self.infcx.tcx.hir_node(hir_id)
{
let name = upvar.to_string(self.infcx.tcx);
err.span_label(
pat.span,
format!("`{name}` declared here, outside the closure"),
);
break;
}
}
}
}
}
}
/// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected.
fn expected_fn_found_fn_mut_call(&self, err: &mut Diag<'_>, sp: Span, act: &str) {
err.span_label(sp, format!("cannot {act}"));
@@ -970,6 +1013,7 @@ fn expected_fn_found_fn_mut_call(&self, err: &mut Diag<'_>, sp: Span, act: &str)
let def_id = tcx.hir_enclosing_body_owner(fn_call_id);
let mut look_at_return = true;
err.span_label(closure_span, "in this closure");
// If the HIR node is a function or method call, get the DefId
// of the callee function or method, the span, and args of the call expr
let get_call_details = || {
@@ -1040,7 +1084,6 @@ fn expected_fn_found_fn_mut_call(&self, err: &mut Diag<'_>, sp: Span, act: &str)
if let Some(span) = arg {
err.span_label(span, "change this to accept `FnMut` instead of `Fn`");
err.span_label(call_span, "expects `Fn` instead of `FnMut`");
err.span_label(closure_span, "in this closure");
look_at_return = false;
}
}
@@ -1067,7 +1110,6 @@ fn expected_fn_found_fn_mut_call(&self, err: &mut Diag<'_>, sp: Span, act: &str)
sig.decl.output.span(),
"change this to return `FnMut` instead of `Fn`",
);
err.span_label(closure_span, "in this closure");
}
_ => {}
}
@@ -229,7 +229,7 @@ fn instrument_function_attr<'ll>(
}
fn nojumptables_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> Option<&'ll Attribute> {
if !sess.opts.unstable_opts.no_jump_tables {
if sess.opts.cg.jump_tables {
return None;
}
+1 -1
View File
@@ -3,9 +3,9 @@
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(debug_closure_helpers))]
#![feature(associated_type_defaults)]
#![feature(closure_track_caller)]
#![feature(debug_closure_helpers)]
#![feature(exhaustive_patterns)]
#![feature(never_type)]
#![feature(variant_count)]
+1 -1
View File
@@ -59,10 +59,10 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(debug_closure_helpers))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(debug_closure_helpers)]
#![feature(gen_blocks)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
+1 -1
View File
@@ -620,6 +620,7 @@ macro_rules! tracked {
tracked!(force_frame_pointers, FramePointer::Always);
tracked!(force_unwind_tables, Some(true));
tracked!(instrument_coverage, InstrumentCoverage::Yes);
tracked!(jump_tables, false);
tracked!(link_dead_code, Some(true));
tracked!(linker_plugin_lto, LinkerPluginLto::LinkerPluginAuto);
tracked!(llvm_args, vec![String::from("1"), String::from("2")]);
@@ -831,7 +832,6 @@ macro_rules! tracked {
tracked!(mutable_noalias, false);
tracked!(next_solver, NextSolverConfig { coherence: true, globally: true });
tracked!(no_generate_arange_section, true);
tracked!(no_jump_tables, true);
tracked!(no_link, true);
tracked!(no_profiler_runtime, true);
tracked!(no_trait_vptr, true);
+2 -2
View File
@@ -2093,6 +2093,8 @@ pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
"instrument the generated code to support LLVM source-based code coverage reports \
(note, the compiler build config must include `profiler = true`); \
implies `-C symbol-mangling-version=v0`"),
jump_tables: bool = (true, parse_bool, [TRACKED],
"allow jump table and lookup table generation from switch case lowering (default: yes)"),
link_arg: (/* redirected to link_args */) = ((), parse_string_push, [UNTRACKED],
"a single extra argument to append to the linker invocation (can be used several times)"),
link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
@@ -2475,8 +2477,6 @@ pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
"omit DWARF address ranges that give faster lookups"),
no_implied_bounds_compat: bool = (false, parse_bool, [TRACKED],
"disable the compatibility version of the `implied_bounds_ty` query"),
no_jump_tables: bool = (false, parse_no_value, [TRACKED],
"disable the jump tables and lookup tables that can be generated from a switch case lowering"),
no_leak_check: bool = (false, parse_no_value, [UNTRACKED],
"disable the 'leak check' for subtyping; unsound, but useful for tests"),
no_link: bool = (false, parse_no_value, [TRACKED],
+1 -1
View File
@@ -9,9 +9,9 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(debug_closure_helpers))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(debug_closure_helpers)]
#![feature(iter_intersperse)]
#![feature(rustdoc_internals)]
// tidy-alphabetical-end
+1 -1
View File
@@ -602,7 +602,7 @@
pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{Formatter, Result, Write};
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
#[stable(feature = "fmt_from_fn", since = "CURRENT_RUSTC_VERSION")]
pub use core::fmt::{FromFn, from_fn};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{LowerExp, UpperExp};
+8 -11
View File
@@ -1210,13 +1210,12 @@ fn is_pretty(&self) -> bool {
}
}
/// Creates a type whose [`fmt::Debug`] and [`fmt::Display`] impls are provided with the function
/// `f`.
/// Creates a type whose [`fmt::Debug`] and [`fmt::Display`] impls are
/// forwarded to the provided closure.
///
/// # Examples
///
/// ```
/// #![feature(debug_closure_helpers)]
/// use std::fmt;
///
/// let value = 'a';
@@ -1227,21 +1226,19 @@ fn is_pretty(&self) -> bool {
/// assert_eq!(format!("{}", wrapped), "'a'");
/// assert_eq!(format!("{:?}", wrapped), "'a'");
/// ```
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
#[stable(feature = "fmt_from_fn", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "returns a type implementing Debug and Display, which do not have any effects unless they are used"]
pub fn from_fn<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result>(f: F) -> FromFn<F> {
FromFn(f)
}
/// Implements [`fmt::Debug`] and [`fmt::Display`] using a function.
/// Implements [`fmt::Debug`] and [`fmt::Display`] via the provided closure.
///
/// Created with [`from_fn`].
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
pub struct FromFn<F>(F)
where
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result;
#[stable(feature = "fmt_from_fn", since = "CURRENT_RUSTC_VERSION")]
pub struct FromFn<F>(F);
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
#[stable(feature = "fmt_from_fn", since = "CURRENT_RUSTC_VERSION")]
impl<F> fmt::Debug for FromFn<F>
where
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
@@ -1251,7 +1248,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
#[stable(feature = "fmt_from_fn", since = "CURRENT_RUSTC_VERSION")]
impl<F> fmt::Display for FromFn<F>
where
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
+1 -1
View File
@@ -39,7 +39,7 @@ pub enum Alignment {
#[stable(feature = "debug_builders", since = "1.2.0")]
pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
#[stable(feature = "fmt_from_fn", since = "CURRENT_RUSTC_VERSION")]
pub use self::builders::{FromFn, from_fn};
/// The type returned by formatter methods.
+44
View File
@@ -584,6 +584,28 @@ pub fn data(&self) -> *const () {
pub fn vtable(&self) -> &'static RawWakerVTable {
self.waker.vtable
}
/// Constructs a `Waker` from a function pointer.
#[inline]
#[must_use]
#[unstable(feature = "waker_from_fn_ptr", issue = "148457")]
pub const fn from_fn_ptr(f: fn()) -> Self {
// SAFETY: Unsafe is used for transmutes, pointer came from `fn()` so it
// is sound to transmute it back to `fn()`.
static VTABLE: RawWakerVTable = unsafe {
RawWakerVTable::new(
|this| RawWaker::new(this, &VTABLE),
|this| transmute::<*const (), fn()>(this)(),
|this| transmute::<*const (), fn()>(this)(),
|_| {},
)
};
let raw = RawWaker::new(f as *const (), &VTABLE);
// SAFETY: `clone` is just a copy, `drop` is a no-op while `wake` and
// `wake_by_ref` just call the function pointer.
unsafe { Self::from_raw(raw) }
}
}
#[stable(feature = "futures_api", since = "1.36.0")]
@@ -879,6 +901,28 @@ pub fn data(&self) -> *const () {
pub fn vtable(&self) -> &'static RawWakerVTable {
self.waker.vtable
}
/// Constructs a `LocalWaker` from a function pointer.
#[inline]
#[must_use]
#[unstable(feature = "waker_from_fn_ptr", issue = "148457")]
pub const fn from_fn_ptr(f: fn()) -> Self {
// SAFETY: Unsafe is used for transmutes, pointer came from `fn()` so it
// is sound to transmute it back to `fn()`.
static VTABLE: RawWakerVTable = unsafe {
RawWakerVTable::new(
|this| RawWaker::new(this, &VTABLE),
|this| transmute::<*const (), fn()>(this)(),
|this| transmute::<*const (), fn()>(this)(),
|_| {},
)
};
let raw = RawWaker::new(f as *const (), &VTABLE);
// SAFETY: `clone` is just a copy, `drop` is a no-op while `wake` and
// `wake_by_ref` just call the function pointer.
unsafe { Self::from_raw(raw) }
}
}
#[unstable(feature = "local_waker", issue = "118959")]
impl Clone for LocalWaker {
@@ -82,12 +82,11 @@ pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
}
pub fn write_vectored(&self, buf: &[IoSlice<'_>]) -> io::Result<usize> {
// FIXME: UEFI does support vectored write, so implement that.
crate::io::default_write_vectored(|b| self.write(b), buf)
self.inner.write_vectored(buf, self.write_timeout()?)
}
pub fn is_write_vectored(&self) -> bool {
false
true
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+11 -1
View File
@@ -1,5 +1,5 @@
use super::tcp4;
use crate::io;
use crate::io::{self, IoSlice};
use crate::net::SocketAddr;
use crate::ptr::NonNull;
use crate::sys::{helpers, unsupported};
@@ -28,6 +28,16 @@ pub(crate) fn write(&self, buf: &[u8], timeout: Option<Duration>) -> io::Result<
}
}
pub(crate) fn write_vectored(
&self,
buf: &[IoSlice<'_>],
timeout: Option<Duration>,
) -> io::Result<usize> {
match self {
Self::V4(client) => client.write_vectored(buf, timeout),
}
}
pub(crate) fn read(&self, buf: &mut [u8], timeout: Option<Duration>) -> io::Result<usize> {
match self {
Self::V4(client) => client.read(buf, timeout),
+57 -12
View File
@@ -1,7 +1,7 @@
use r_efi::efi::{self, Status};
use r_efi::protocols::tcp4;
use crate::io;
use crate::io::{self, IoSlice};
use crate::net::SocketAddrV4;
use crate::ptr::NonNull;
use crate::sync::atomic::{AtomicBool, Ordering};
@@ -108,11 +108,7 @@ pub(crate) fn connect(&self, timeout: Option<Duration>) -> io::Result<()> {
}
pub(crate) fn write(&self, buf: &[u8], timeout: Option<Duration>) -> io::Result<usize> {
let evt = unsafe { self.create_evt() }?;
let completion_token =
tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS };
let data_len = u32::try_from(buf.len()).unwrap_or(u32::MAX);
let fragment = tcp4::FragmentData {
fragment_length: data_len,
fragment_buffer: buf.as_ptr().cast::<crate::ffi::c_void>().cast_mut(),
@@ -125,14 +121,63 @@ pub(crate) fn write(&self, buf: &[u8], timeout: Option<Duration>) -> io::Result<
fragment_table: [fragment],
};
let protocol = self.protocol.as_ptr();
let mut token = tcp4::IoToken {
completion_token,
packet: tcp4::IoTokenPacket {
tx_data: (&raw mut tx_data).cast::<tcp4::TransmitData<0>>(),
},
self.write_inner((&raw mut tx_data).cast(), timeout).map(|_| data_len as usize)
}
pub(crate) fn write_vectored(
&self,
buf: &[IoSlice<'_>],
timeout: Option<Duration>,
) -> io::Result<usize> {
let mut data_length = 0u32;
let mut fragment_count = 0u32;
// Calculate how many IoSlice in buf can be transmitted.
for i in buf {
// IoSlice length is always <= u32::MAX in UEFI.
match data_length
.checked_add(u32::try_from(i.as_slice().len()).expect("value is stored as a u32"))
{
Some(x) => data_length = x,
None => break,
}
fragment_count += 1;
}
let tx_data_size = size_of::<tcp4::TransmitData<0>>()
+ size_of::<tcp4::FragmentData>() * (fragment_count as usize);
let mut tx_data = helpers::UefiBox::<tcp4::TransmitData>::new(tx_data_size)?;
tx_data.write(tcp4::TransmitData {
push: r_efi::efi::Boolean::FALSE,
urgent: r_efi::efi::Boolean::FALSE,
data_length,
fragment_count,
fragment_table: [],
});
unsafe {
// SAFETY: IoSlice and FragmentData are guaranteed to have same layout.
crate::ptr::copy_nonoverlapping(
buf.as_ptr().cast(),
(*tx_data.as_mut_ptr()).fragment_table.as_mut_ptr(),
fragment_count as usize,
);
};
self.write_inner(tx_data.as_mut_ptr(), timeout).map(|_| data_length as usize)
}
fn write_inner(
&self,
tx_data: *mut tcp4::TransmitData,
timeout: Option<Duration>,
) -> io::Result<()> {
let evt = unsafe { self.create_evt() }?;
let completion_token =
tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS };
let protocol = self.protocol.as_ptr();
let mut token = tcp4::IoToken { completion_token, packet: tcp4::IoTokenPacket { tx_data } };
let r = unsafe { ((*protocol).transmit)(protocol, &mut token) };
if r.is_error() {
return Err(io::Error::from_raw_os_error(r.as_usize()));
@@ -143,7 +188,7 @@ pub(crate) fn write(&self, buf: &[u8], timeout: Option<Duration>) -> io::Result<
if completion_token.status.is_error() {
Err(io::Error::from_raw_os_error(completion_token.status.as_usize()))
} else {
Ok(data_len as usize)
Ok(())
}
}
+37
View File
@@ -12,6 +12,7 @@
use r_efi::efi::{self, Guid};
use r_efi::protocols::{device_path, device_path_to_text, service_binding, shell};
use crate::alloc::Layout;
use crate::ffi::{OsStr, OsString};
use crate::io::{self, const_error};
use crate::marker::PhantomData;
@@ -769,3 +770,39 @@ pub(crate) const fn ipv4_to_r_efi(addr: crate::net::Ipv4Addr) -> efi::Ipv4Addres
pub(crate) const fn ipv4_from_r_efi(ip: efi::Ipv4Address) -> crate::net::Ipv4Addr {
crate::net::Ipv4Addr::new(ip.addr[0], ip.addr[1], ip.addr[2], ip.addr[3])
}
/// This type is intended for use with ZSTs. Since such types are unsized, a reference to such types
/// is not valid in Rust. Thus, only pointers should be used when interacting with such types.
pub(crate) struct UefiBox<T> {
inner: NonNull<T>,
size: usize,
}
impl<T> UefiBox<T> {
pub(crate) fn new(len: usize) -> io::Result<Self> {
assert!(len >= size_of::<T>());
// UEFI always expects types to be 8 byte aligned.
let layout = Layout::from_size_align(len, 8).unwrap();
let ptr = unsafe { crate::alloc::alloc(layout) };
match NonNull::new(ptr.cast()) {
Some(inner) => Ok(Self { inner, size: len }),
None => Err(io::Error::new(io::ErrorKind::OutOfMemory, "Allocation failed")),
}
}
pub(crate) fn write(&mut self, data: T) {
unsafe { self.inner.write(data) }
}
pub(crate) fn as_mut_ptr(&mut self) -> *mut T {
self.inner.as_ptr().cast()
}
}
impl<T> Drop for UefiBox<T> {
fn drop(&mut self) {
let layout = Layout::from_size_align(self.size, 8).unwrap();
unsafe { crate::alloc::dealloc(self.inner.as_ptr().cast(), layout) };
}
}
+2 -1
View File
@@ -2,7 +2,8 @@
set -euo pipefail
LINUX_VERSION=v6.17-rc5
# https://github.com/rust-lang/rust/pull/145974
LINUX_VERSION=842cfd8e5aff3157cb25481b2900b49c188d628a
# Build rustc, rustdoc, cargo, clippy-driver and rustfmt
../x.py build --stage 2 library rustdoc clippy rustfmt
@@ -209,6 +209,27 @@ Note that while the `-C instrument-coverage` option is stable, the profile data
format produced by the resulting instrumentation may change, and may not work
with coverage tools other than those built and shipped with the compiler.
## jump-tables
This option is used to allow or prevent the LLVM codegen backend from creating
jump tables when lowering switches from Rust code.
* `y`, `yes`, `on`, `true` or no value: allow jump tables (the default).
* `n`, `no`, `off` or `false`: disable jump tables.
To prevent jump tables being created from Rust code, a target must ensure
all crates are compiled with jump tables disabled.
Note, in many cases the Rust toolchain is distributed with precompiled
crates, such as the core and std crates, which could possibly include
jump tables. Furthermore, this option does not guarantee a target will
be free of jump tables. They could arise from external dependencies,
inline asm, or other complicated interactions when using crates which
are compiled with jump table support.
Disabling jump tables can be used to help provide protection against
jump-oriented-programming (JOP) attacks.
## link-arg
This flag lets you append a single extra argument to the linker invocation.
@@ -1,19 +0,0 @@
# `no-jump-tables`
The tracking issue for this feature is [#116592](https://github.com/rust-lang/rust/issues/116592)
---
This option enables the `-fno-jump-tables` flag for LLVM, which makes the
codegen backend avoid generating jump tables when lowering switches.
This option adds the LLVM `no-jump-tables=true` attribute to every function.
The option can be used to help provide protection against
jump-oriented-programming (JOP) attacks, such as with the linux kernel's [IBT].
```sh
RUSTFLAGS="-Zno-jump-tables" cargo +nightly build -Z build-std
```
[IBT]: https://www.phoronix.com/news/Linux-IBT-By-Default-Tip
+1 -1
View File
@@ -1,4 +1,5 @@
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(debug_closure_helpers))]
#![doc(
html_root_url = "https://doc.rust-lang.org/nightly/",
html_playground_url = "https://play.rust-lang.org/"
@@ -8,7 +9,6 @@
#![feature(assert_matches)]
#![feature(box_into_inner)]
#![feature(box_patterns)]
#![feature(debug_closure_helpers)]
#![feature(file_buffered)]
#![feature(formatting_options)]
#![feature(if_let_guard)]
@@ -190,6 +190,7 @@
"only-aarch64",
"only-aarch64-apple-darwin",
"only-aarch64-unknown-linux-gnu",
"only-aarch64-unknown-uefi",
"only-apple",
"only-arm",
"only-arm64ec",
+9 -3
View File
@@ -68,14 +68,20 @@
"library/std/src/io/error.rs", // Repr unpacked needed for UEFI
];
pub fn check(path: &Path, tidy_ctx: TidyCtx) {
let mut check = tidy_ctx.start_check(CheckId::new("pal").path(path));
pub fn check(library_path: &Path, tidy_ctx: TidyCtx) {
let mut check = tidy_ctx.start_check(CheckId::new("pal").path(library_path));
let root_path = library_path.parent().unwrap();
// Let's double-check that this is the root path by making sure it has `x.py`.
assert!(root_path.join("x.py").is_file());
// Sanity check that the complex parsing here works.
let mut saw_target_arch = false;
let mut saw_cfg_bang = false;
walk(path, |path, _is_dir| filter_dirs(path), &mut |entry, contents| {
walk(library_path, |path, _is_dir| filter_dirs(path), &mut |entry, contents| {
let file = entry.path();
// We don't want the absolute path to matter, so make it relative.
let file = file.strip_prefix(root_path).unwrap();
let filestr = file.to_string_lossy().replace("\\", "/");
if !filestr.ends_with(".rs") {
return;
+2 -2
View File
@@ -1,10 +1,10 @@
// Test that jump tables are (not) emitted when the `-Zno-jump-tables`
// Test that jump tables are (not) emitted when the `-Cjump-tables=no`
// flag is (not) set.
//@ revisions: unset set
//@ assembly-output: emit-asm
//@ compile-flags: -Copt-level=3
//@ [set] compile-flags: -Zno-jump-tables
//@ [set] compile-flags: -Cjump-tables=no
//@ only-x86_64
//@ ignore-sgx
+6 -4
View File
@@ -1,11 +1,12 @@
// Test that the `no-jump-tables` function attribute are (not) emitted when
// the `-Zno-jump-tables` flag is (not) set.
// the `-Cjump-tables=no` flag is (not) set.
//@ add-minicore
//@ revisions: unset set
//@ revisions: unset set_no set_yes
//@ needs-llvm-components: x86
//@ compile-flags: --target x86_64-unknown-linux-gnu
//@ [set] compile-flags: -Zno-jump-tables
//@ [set_no] compile-flags: -Cjump-tables=no
//@ [set_yes] compile-flags: -Cjump-tables=yes
#![crate_type = "lib"]
#![feature(no_core, lang_items)]
@@ -19,5 +20,6 @@ pub fn foo() {
// CHECK: @foo() unnamed_addr #0
// unset-NOT: attributes #0 = { {{.*}}"no-jump-tables"="true"{{.*}} }
// set: attributes #0 = { {{.*}}"no-jump-tables"="true"{{.*}} }
// set_yes-NOT: attributes #0 = { {{.*}}"no-jump-tables"="true"{{.*}} }
// set_no: attributes #0 = { {{.*}}"no-jump-tables"="true"{{.*}} }
}
@@ -25,6 +25,8 @@ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `F
LL | fn needs_async_fn(_: impl AsyncFn()) {}
| -------------- change this to accept `FnMut` instead of `Fn`
...
LL | let mut x = 1;
| ----- `x` declared here, outside the closure
LL | needs_async_fn(async || {
| -------------- ^^^^^^^^
| | |
@@ -4,6 +4,8 @@ error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closu
LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
| - change this to accept `FnMut` instead of `Fn`
...
LL | let mut x = 0;
| ----- `x` declared here, outside the closure
LL | let _f = to_fn(|| x = 42);
| ----- -- ^^^^^^ cannot assign
| | |
@@ -16,6 +18,8 @@ error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `F
LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
| - change this to accept `FnMut` instead of `Fn`
...
LL | let mut y = 0;
| ----- `y` declared here, outside the closure
LL | let _g = to_fn(|| set(&mut y));
| ----- -- ^^^^^^ cannot borrow as mutable
| | |
@@ -28,6 +32,9 @@ error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closu
LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
| - change this to accept `FnMut` instead of `Fn`
...
LL | let mut z = 0;
| ----- `z` declared here, outside the closure
...
LL | to_fn(|| z = 42);
| ----- -- ^^^^^^ cannot assign
| | |
@@ -40,6 +40,8 @@ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `F
LL | fn make_fn<F: Fn()>(f: F) -> F { f }
| - change this to accept `FnMut` instead of `Fn`
...
LL | let mut x = 0;
| ----- `x` declared here, outside the closure
LL | let f = make_fn(|| {
| ------- -- in this closure
| |
+12 -4
View File
@@ -139,7 +139,9 @@ error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closu
|
LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| - change this to accept `FnMut` instead of `Fn`
...
LL |
LL | fn ref_closure(mut x: (i32,)) {
| ----- `x` declared here, outside the closure
LL | fn_ref(|| {
| ------ -- in this closure
| |
@@ -152,7 +154,9 @@ error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captu
|
LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| - change this to accept `FnMut` instead of `Fn`
...
LL |
LL | fn ref_closure(mut x: (i32,)) {
| ----- `x` declared here, outside the closure
LL | fn_ref(|| {
| ------ -- in this closure
| |
@@ -166,7 +170,9 @@ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `F
|
LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| - change this to accept `FnMut` instead of `Fn`
...
LL |
LL | fn ref_closure(mut x: (i32,)) {
| ----- `x` declared here, outside the closure
LL | fn_ref(|| {
| ------ -- in this closure
| |
@@ -180,7 +186,9 @@ error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate the
|
LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| - change this to accept `FnMut` instead of `Fn`
...
LL |
LL | fn ref_closure(mut x: (i32,)) {
| ----- `x` declared here, outside the closure
LL | fn_ref(|| {
| ------ -- in this closure
| |
@@ -4,6 +4,9 @@ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `F
LL | fn call_it<F>(f: F) where F: Fn() { f(); }
| - change this to accept `FnMut` instead of `Fn`
...
LL | let mut x = A;
| ----- `x` declared here, outside the closure
...
LL | call_it(|| x.gen_mut());
| ------- -- ^ cannot borrow as mutable
| | |
@@ -16,6 +19,8 @@ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `F
LL | fn call_it<F>(f: F) where F: Fn() { f(); }
| - change this to accept `FnMut` instead of `Fn`
...
LL | let mut x = A;
| ----- `x` declared here, outside the closure
LL | call_it(|| {
| ------- -- in this closure
| |
@@ -4,6 +4,8 @@ error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closu
LL | fn assoc_func(&self, _f: impl Fn()) -> usize {
| --------- change this to accept `FnMut` instead of `Fn`
...
LL | let mut x = ();
| ----- `x` declared here, outside the closure
LL | s.assoc_func(|| x = ());
| --------------^^^^^^-
| | | |
@@ -17,6 +19,9 @@ error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closu
LL | fn func(_f: impl Fn()) -> usize {
| --------- change this to accept `FnMut` instead of `Fn`
...
LL | let mut x = ();
| ----- `x` declared here, outside the closure
...
LL | func(|| x = ())
| ---- -- ^^^^^^ cannot assign
| | |
+5 -1
View File
@@ -47,7 +47,9 @@ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `F
|
LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| - change this to accept `FnMut` instead of `Fn`
...
LL |
LL | fn two_closures_ref_mut(mut x: i32) {
| ----- `x` declared here, outside the closure
LL | fn_ref(|| {
| ------ -- in this closure
| |
@@ -89,6 +91,8 @@ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `F
LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| - change this to accept `FnMut` instead of `Fn`
...
LL | fn two_closures_ref(x: i32) {
| - `x` declared here, outside the closure
LL | fn_ref(|| {
| ------ -- in this closure
| |
@@ -0,0 +1,16 @@
//! Regression test for #98254, missing `__chkstk` symbol on `aarch64-unknown-uefi`.
//@ build-pass
//@ only-aarch64-unknown-uefi
//@ compile-flags: -Cpanic=abort
//@ compile-flags: -Clinker=rust-lld
#![no_std]
#![no_main]
#[panic_handler]
fn panic_handler(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
#[export_name = "efi_main"]
fn main() {
let b = [0; 1024];
}
@@ -4,6 +4,8 @@ error[E0594]: cannot assign to `counter`, as it is a captured variable in a `Fn`
LL | fn call<F>(f: F) where F : Fn() {
| - change this to accept `FnMut` instead of `Fn`
...
LL | let mut counter = 0;
| ----------- `counter` declared here, outside the closure
LL | call(|| {
| ---- -- in this closure
| |