Skip to content

Commit

Permalink
Auto merge of rust-lang#133423 - jieyouxu:rollup-m3gyoz6, r=jieyouxu
Browse files Browse the repository at this point in the history
Rollup of 6 pull requests

Successful merges:

 - rust-lang#132730 (std: allow after-main use of synchronization primitives)
 - rust-lang#133105 (only store valid proc macro item for doc link)
 - rust-lang#133260 (Constify the `Deref`/`DerefMut` traits, too)
 - rust-lang#133297 (Remove legacy bitcode for iOS)
 - rust-lang#133298 (Mention that std::fs::remove_dir_all fails on files)
 - rust-lang#133384 (add a test for target-feature-ABI warnings in closures and when calling extern fn)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Nov 24, 2024
2 parents 481b5fa + c50e19b commit 28fc2ba
Show file tree
Hide file tree
Showing 26 changed files with 269 additions and 120 deletions.
19 changes: 1 addition & 18 deletions compiler/rustc_codegen_llvm/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -955,24 +955,7 @@ pub(crate) fn bitcode_section_name(cgcx: &CodegenContext<LlvmCodegenBackend>) ->
}
}

/// Embed the bitcode of an LLVM module in the LLVM module itself.
///
/// This is done primarily for iOS where it appears to be standard to compile C
/// code at least with `-fembed-bitcode` which creates two sections in the
/// executable:
///
/// * __LLVM,__bitcode
/// * __LLVM,__cmdline
///
/// It appears *both* of these sections are necessary to get the linker to
/// recognize what's going on. A suitable cmdline value is taken from the
/// target spec.
///
/// Furthermore debug/O1 builds don't actually embed bitcode but rather just
/// embed an empty section.
///
/// Basically all of this is us attempting to follow in the footsteps of clang
/// on iOS. See #35968 for lots more info.
/// Embed the bitcode of an LLVM module for LTO in the LLVM module itself.
unsafe fn embed_bitcode(
cgcx: &CodegenContext<LlvmCodegenBackend>,
llcx: &llvm::Context,
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,11 +432,9 @@ struct CompiledModules {

fn need_bitcode_in_object(tcx: TyCtxt<'_>) -> bool {
let sess = tcx.sess;
let requested_for_rlib = sess.opts.cg.embed_bitcode
sess.opts.cg.embed_bitcode
&& tcx.crate_types().contains(&CrateType::Rlib)
&& sess.opts.output_types.contains_key(&OutputType::Exe);
let forced_by_target = sess.target.forces_embed_bitcode;
requested_for_rlib || forced_by_target
&& sess.opts.output_types.contains_key(&OutputType::Exe)
}

fn need_pre_lto_bitcode_for_incr_comp(sess: &Session) -> bool {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,9 +576,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
// If this closure is marked `#[inline(always)]`, simply skip adding `#[target_feature]`.
//
// At this point, `unsafe` has already been checked and `#[target_feature]` only affects codegen.
// Emitting both `#[inline(always)]` and `#[target_feature]` can potentially result in an
// ICE, because LLVM errors when the function fails to be inlined due to a target feature
// mismatch.
// Due to LLVM limitations, emitting both `#[inline(always)]` and `#[target_feature]` is *unsound*:
// the function may be inlined into a caller with fewer target features. Also see
// <https://github.com/rust-lang/rust/issues/116573>.
//
// Using `#[inline(always)]` implies that this closure will most likely be inlined into
// its parent function, which effectively inherits the features anyway. Boxing this closure
Expand Down
32 changes: 17 additions & 15 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4794,14 +4794,10 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
let res = self.r.resolve_rustdoc_path(path.as_str(), *ns, self.parent_scope);
if let Some(res) = res
&& let Some(def_id) = res.opt_def_id()
&& !def_id.is_local()
&& self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
&& matches!(
self.r.tcx.sess.opts.resolve_doc_links,
ResolveDocLinks::ExportedMetadata
)
&& self.is_invalid_proc_macro_item_for_doc(def_id)
{
// Encoding foreign def ids in proc macro crate metadata will ICE.
// Encoding def ids in proc macro crate metadata will ICE,
// because it will only store proc macros for it.
return None;
}
res
Expand All @@ -4810,6 +4806,17 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
res
}

fn is_invalid_proc_macro_item_for_doc(&self, did: DefId) -> bool {
if !matches!(self.r.tcx.sess.opts.resolve_doc_links, ResolveDocLinks::ExportedMetadata)
|| !self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
{
return false;
}
let Some(local_did) = did.as_local() else { return true };
let Some(node_id) = self.r.def_id_to_node_id.get(local_did) else { return true };
!self.r.proc_macros.contains(node_id)
}

fn resolve_doc_links(&mut self, attrs: &[Attribute], maybe_exported: MaybeExported<'_>) {
match self.r.tcx.sess.opts.resolve_doc_links {
ResolveDocLinks::None => return,
Expand Down Expand Up @@ -4872,14 +4879,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
.traits_in_scope(None, &self.parent_scope, SyntaxContext::root(), None)
.into_iter()
.filter_map(|tr| {
if !tr.def_id.is_local()
&& self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
&& matches!(
self.r.tcx.sess.opts.resolve_doc_links,
ResolveDocLinks::ExportedMetadata
)
{
// Encoding foreign def ids in proc macro crate metadata will ICE.
if self.is_invalid_proc_macro_item_for_doc(tr.def_id) {
// Encoding def ids in proc macro crate metadata will ICE.
// because it will only store proc macros for it.
return None;
}
Some(tr.def_id)
Expand Down
5 changes: 0 additions & 5 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2327,8 +2327,6 @@ pub struct TargetOptions {
/// If we give emcc .o files that are actually .bc files it
/// will 'just work'.
pub obj_is_bitcode: bool,
/// Whether the target requires that emitted object code includes bitcode.
pub forces_embed_bitcode: bool,
/// Content of the LLVM cmdline section associated with embedded bitcode.
pub bitcode_llvm_cmdline: StaticCow<str>,

Expand Down Expand Up @@ -2671,7 +2669,6 @@ impl Default for TargetOptions {
allow_asm: true,
has_thread_local: false,
obj_is_bitcode: false,
forces_embed_bitcode: false,
bitcode_llvm_cmdline: "".into(),
min_atomic_width: None,
max_atomic_width: None,
Expand Down Expand Up @@ -3412,7 +3409,6 @@ impl Target {
key!(main_needs_argc_argv, bool);
key!(has_thread_local, bool);
key!(obj_is_bitcode, bool);
key!(forces_embed_bitcode, bool);
key!(bitcode_llvm_cmdline);
key!(max_atomic_width, Option<u64>);
key!(min_atomic_width, Option<u64>);
Expand Down Expand Up @@ -3687,7 +3683,6 @@ impl ToJson for Target {
target_option_val!(main_needs_argc_argv);
target_option_val!(has_thread_local);
target_option_val!(obj_is_bitcode);
target_option_val!(forces_embed_bitcode);
target_option_val!(bitcode_llvm_cmdline);
target_option_val!(min_atomic_width);
target_option_val!(max_atomic_width);
Expand Down
47 changes: 47 additions & 0 deletions library/core/src/ops/deref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
#[doc(alias = "&*")]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "Deref"]
#[cfg_attr(not(bootstrap), const_trait)]
pub trait Deref {
/// The resulting type after dereferencing.
#[stable(feature = "rust1", since = "1.0.0")]
Expand All @@ -147,6 +148,7 @@ pub trait Deref {
fn deref(&self) -> &Self::Target;
}

#[cfg(bootstrap)]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for &T {
type Target = T;
Expand All @@ -157,9 +159,21 @@ impl<T: ?Sized> Deref for &T {
}
}

#[cfg(not(bootstrap))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> const Deref for &T {
type Target = T;

#[rustc_diagnostic_item = "noop_method_deref"]
fn deref(&self) -> &T {
*self
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> !DerefMut for &T {}

#[cfg(bootstrap)]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for &mut T {
type Target = T;
Expand All @@ -169,6 +183,16 @@ impl<T: ?Sized> Deref for &mut T {
}
}

#[cfg(not(bootstrap))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> const Deref for &mut T {
type Target = T;

fn deref(&self) -> &T {
*self
}
}

/// Used for mutable dereferencing operations, like in `*v = 1;`.
///
/// In addition to being used for explicit dereferencing operations with the
Expand Down Expand Up @@ -258,23 +282,46 @@ impl<T: ?Sized> Deref for &mut T {
/// *x = 'b';
/// assert_eq!('b', x.value);
/// ```
#[cfg(not(bootstrap))]
#[lang = "deref_mut"]
#[doc(alias = "*")]
#[stable(feature = "rust1", since = "1.0.0")]
#[const_trait]
pub trait DerefMut: ~const Deref {
/// Mutably dereferences the value.
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "deref_mut_method"]
fn deref_mut(&mut self) -> &mut Self::Target;
}

/// Bootstrap
#[lang = "deref_mut"]
#[doc(alias = "*")]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(bootstrap)]
pub trait DerefMut: Deref {
/// Mutably dereferences the value.
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "deref_mut_method"]
fn deref_mut(&mut self) -> &mut Self::Target;
}

#[cfg(bootstrap)]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for &mut T {
fn deref_mut(&mut self) -> &mut T {
*self
}
}

#[cfg(not(bootstrap))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> const DerefMut for &mut T {
fn deref_mut(&mut self) -> &mut T {
*self
}
}

/// Perma-unstable marker trait. Indicates that the type has a well-behaved [`Deref`]
/// (and, if applicable, [`DerefMut`]) implementation. This is relied on for soundness
/// of deref patterns.
Expand Down
3 changes: 2 additions & 1 deletion library/std/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2804,8 +2804,9 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
///
/// See [`fs::remove_file`] and [`fs::remove_dir`].
///
/// `remove_dir_all` will fail if `remove_dir` or `remove_file` fail on any constituent paths, including the root path.
/// `remove_dir_all` will fail if `remove_dir` or `remove_file` fail on any constituent paths, including the root `path`.
/// As a result, the directory you are deleting must exist, meaning that this function is not idempotent.
/// Additionally, `remove_dir_all` will also fail if the `path` is not a directory.
///
/// Consider ignoring the error if validating the removal is not required for your use case.
///
Expand Down
3 changes: 0 additions & 3 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,6 @@
//!
//! - after-main use of thread-locals, which also affects additional features:
//! - [`thread::current()`]
//! - [`thread::scope()`]
//! - [`sync::mpmc`]
//! - [`sync::mpsc`]
//! - before-main stdio file descriptors are not guaranteed to be open on unix platforms
//!
//!
Expand Down
6 changes: 4 additions & 2 deletions library/std/src/sync/mpmc/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,8 @@ impl<T> Channel<T> {
}

// Block the current thread.
let sel = cx.wait_until(deadline);
// SAFETY: the context belongs to the current thread.
let sel = unsafe { cx.wait_until(deadline) };

match sel {
Selected::Waiting => unreachable!(),
Expand Down Expand Up @@ -397,7 +398,8 @@ impl<T> Channel<T> {
}

// Block the current thread.
let sel = cx.wait_until(deadline);
// SAFETY: the context belongs to the current thread.
let sel = unsafe { cx.wait_until(deadline) };

match sel {
Selected::Waiting => unreachable!(),
Expand Down
13 changes: 9 additions & 4 deletions library/std/src/sync/mpmc/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ impl Context {
inner: Arc::new(Inner {
select: AtomicUsize::new(Selected::Waiting.into()),
packet: AtomicPtr::new(ptr::null_mut()),
thread: thread::current(),
thread: thread::current_or_unnamed(),
thread_id: current_thread_id(),
}),
}
Expand Down Expand Up @@ -112,8 +112,11 @@ impl Context {
/// Waits until an operation is selected and returns it.
///
/// If the deadline is reached, `Selected::Aborted` will be selected.
///
/// # Safety
/// This may only be called from the thread this `Context` belongs to.
#[inline]
pub fn wait_until(&self, deadline: Option<Instant>) -> Selected {
pub unsafe fn wait_until(&self, deadline: Option<Instant>) -> Selected {
loop {
// Check whether an operation has been selected.
let sel = Selected::from(self.inner.select.load(Ordering::Acquire));
Expand All @@ -126,7 +129,8 @@ impl Context {
let now = Instant::now();

if now < end {
thread::park_timeout(end - now);
// SAFETY: guaranteed by caller.
unsafe { self.inner.thread.park_timeout(end - now) };
} else {
// The deadline has been reached. Try aborting select.
return match self.try_select(Selected::Aborted) {
Expand All @@ -135,7 +139,8 @@ impl Context {
};
}
} else {
thread::park();
// SAFETY: guaranteed by caller.
unsafe { self.inner.thread.park() };
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion library/std/src/sync/mpmc/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,8 @@ impl<T> Channel<T> {
}

// Block the current thread.
let sel = cx.wait_until(deadline);
// SAFETY: the context belongs to the current thread.
let sel = unsafe { cx.wait_until(deadline) };

match sel {
Selected::Waiting => unreachable!(),
Expand Down
6 changes: 4 additions & 2 deletions library/std/src/sync/mpmc/zero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ impl<T> Channel<T> {
drop(inner);

// Block the current thread.
let sel = cx.wait_until(deadline);
// SAFETY: the context belongs to the current thread.
let sel = unsafe { cx.wait_until(deadline) };

match sel {
Selected::Waiting => unreachable!(),
Expand Down Expand Up @@ -257,7 +258,8 @@ impl<T> Channel<T> {
drop(inner);

// Block the current thread.
let sel = cx.wait_until(deadline);
// SAFETY: the context belongs to the current thread.
let sel = unsafe { cx.wait_until(deadline) };

match sel {
Selected::Waiting => unreachable!(),
Expand Down
9 changes: 5 additions & 4 deletions library/std/src/sys/sync/once/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ const QUEUE_MASK: usize = !STATE_MASK;
// use interior mutability.
#[repr(align(4))] // Ensure the two lower bits are free to use as state bits.
struct Waiter {
thread: Cell<Option<Thread>>,
thread: Thread,
signaled: AtomicBool,
next: Cell<*const Waiter>,
}
Expand Down Expand Up @@ -238,7 +238,7 @@ fn wait(
return_on_poisoned: bool,
) -> StateAndQueue {
let node = &Waiter {
thread: Cell::new(Some(thread::current())),
thread: thread::current_or_unnamed(),
signaled: AtomicBool::new(false),
next: Cell::new(ptr::null()),
};
Expand Down Expand Up @@ -277,7 +277,8 @@ fn wait(
// can park ourselves, the result could be this thread never gets
// unparked. Luckily `park` comes with the guarantee that if it got
// an `unpark` just before on an unparked thread it does not park.
thread::park();
// SAFETY: we retrieved this handle on the current thread above.
unsafe { node.thread.park() }
}

return state_and_queue.load(Acquire);
Expand Down Expand Up @@ -309,7 +310,7 @@ impl Drop for WaiterQueue<'_> {
let mut queue = to_queue(current);
while !queue.is_null() {
let next = (*queue).next.get();
let thread = (*queue).thread.take().unwrap();
let thread = (*queue).thread.clone();
(*queue).signaled.store(true, Release);
thread.unpark();
queue = next;
Expand Down
Loading

0 comments on commit 28fc2ba

Please sign in to comment.