mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 11:07:42 +00:00
Auto merge of #131887 - jieyouxu:rollup-ftik4ni, r=jieyouxu
Rollup of 9 pull requests Successful merges: - #130136 (Partially stabilize const_pin) - #131755 (Regression test for AVR `rjmp` offset) - #131774 (Add getentropy for RTEMS) - #131802 (Dont ICE when computing coverage of synthetic async closure body) - #131809 (Fix predicate signatures in retain_mut docs) - #131858 (Remove outdated documentation for `repeat_n`) - #131866 (Avoid use imports in `thread_local_inner!`) - #131874 (Default to the medium code model on OpenHarmony LoongArch target) - #131877 (checktools.sh: add link to issue for more context about disabled Miri tests) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
1350eead10
@ -570,6 +570,7 @@ rustc_queries! {
|
|||||||
/// either `#[coverage(on)]` or no coverage attribute was found.
|
/// either `#[coverage(on)]` or no coverage attribute was found.
|
||||||
query coverage_attr_on(key: LocalDefId) -> bool {
|
query coverage_attr_on(key: LocalDefId) -> bool {
|
||||||
desc { |tcx| "checking for `#[coverage(..)]` on `{}`", tcx.def_path_str(key) }
|
desc { |tcx| "checking for `#[coverage(..)]` on `{}`", tcx.def_path_str(key) }
|
||||||
|
feedable
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass
|
/// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass
|
||||||
|
@ -223,6 +223,7 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
|
|||||||
|
|
||||||
// Inherited from the by-ref coroutine.
|
// Inherited from the by-ref coroutine.
|
||||||
body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone());
|
body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone());
|
||||||
|
body_def.coverage_attr_on(tcx.coverage_attr_on(coroutine_def_id));
|
||||||
body_def.constness(tcx.constness(coroutine_def_id));
|
body_def.constness(tcx.constness(coroutine_def_id));
|
||||||
body_def.coroutine_kind(tcx.coroutine_kind(coroutine_def_id));
|
body_def.coroutine_kind(tcx.coroutine_kind(coroutine_def_id));
|
||||||
body_def.def_ident_span(tcx.def_ident_span(coroutine_def_id));
|
body_def.def_ident_span(tcx.def_ident_span(coroutine_def_id));
|
||||||
|
@ -524,6 +524,11 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir
|
|||||||
// FIXME(#79625): Consider improving MIR to provide the information needed, to avoid going back
|
// FIXME(#79625): Consider improving MIR to provide the information needed, to avoid going back
|
||||||
// to HIR for it.
|
// to HIR for it.
|
||||||
|
|
||||||
|
// HACK: For synthetic MIR bodies (async closures), use the def id of the HIR body.
|
||||||
|
if tcx.is_synthetic_mir(def_id) {
|
||||||
|
return extract_hir_info(tcx, tcx.local_parent(def_id));
|
||||||
|
}
|
||||||
|
|
||||||
let hir_node = tcx.hir_node_by_def_id(def_id);
|
let hir_node = tcx.hir_node_by_def_id(def_id);
|
||||||
let fn_body_id = hir_node.body_id().expect("HIR node is a function with body");
|
let fn_body_id = hir_node.body_id().expect("HIR node is a function with body");
|
||||||
let hir_body = tcx.hir().body(fn_body_id);
|
let hir_body = tcx.hir().body(fn_body_id);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::spec::{SanitizerSet, Target, TargetOptions, base};
|
use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions, base};
|
||||||
|
|
||||||
pub(crate) fn target() -> Target {
|
pub(crate) fn target() -> Target {
|
||||||
Target {
|
Target {
|
||||||
@ -13,6 +13,7 @@ pub(crate) fn target() -> Target {
|
|||||||
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
|
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
|
||||||
arch: "loongarch64".into(),
|
arch: "loongarch64".into(),
|
||||||
options: TargetOptions {
|
options: TargetOptions {
|
||||||
|
code_model: Some(CodeModel::Medium),
|
||||||
cpu: "generic".into(),
|
cpu: "generic".into(),
|
||||||
features: "+f,+d".into(),
|
features: "+f,+d".into(),
|
||||||
llvm_abiname: "lp64d".into(),
|
llvm_abiname: "lp64d".into(),
|
||||||
|
@ -1082,7 +1082,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
|
|||||||
|
|
||||||
/// Retains only the elements specified by the predicate.
|
/// Retains only the elements specified by the predicate.
|
||||||
///
|
///
|
||||||
/// In other words, remove all elements `e` for which `f(&e)` returns false.
|
/// In other words, remove all elements `e` for which `f(&mut e)` returns false.
|
||||||
/// This method operates in place, visiting each element exactly once in the
|
/// This method operates in place, visiting each element exactly once in the
|
||||||
/// original order, and preserves the order of the retained elements.
|
/// original order, and preserves the order of the retained elements.
|
||||||
///
|
///
|
||||||
|
@ -2122,7 +2122,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||||||
|
|
||||||
/// Retains only the elements specified by the predicate.
|
/// Retains only the elements specified by the predicate.
|
||||||
///
|
///
|
||||||
/// In other words, remove all elements `e` for which `f(&e)` returns false.
|
/// In other words, remove all elements `e` for which `f(&mut e)` returns false.
|
||||||
/// This method operates in place, visiting each element exactly once in the
|
/// This method operates in place, visiting each element exactly once in the
|
||||||
/// original order, and preserves the order of the retained elements.
|
/// original order, and preserves the order of the retained elements.
|
||||||
///
|
///
|
||||||
|
@ -112,7 +112,6 @@
|
|||||||
#![feature(const_eval_select)]
|
#![feature(const_eval_select)]
|
||||||
#![feature(const_heap)]
|
#![feature(const_heap)]
|
||||||
#![feature(const_maybe_uninit_write)]
|
#![feature(const_maybe_uninit_write)]
|
||||||
#![feature(const_pin)]
|
|
||||||
#![feature(const_size_of_val)]
|
#![feature(const_size_of_val)]
|
||||||
#![feature(const_vec_string_slice)]
|
#![feature(const_vec_string_slice)]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
|
@ -8,9 +8,7 @@ use crate::num::NonZero;
|
|||||||
/// The `repeat_n()` function repeats a single value exactly `n` times.
|
/// The `repeat_n()` function repeats a single value exactly `n` times.
|
||||||
///
|
///
|
||||||
/// This is very similar to using [`repeat()`] with [`Iterator::take()`],
|
/// This is very similar to using [`repeat()`] with [`Iterator::take()`],
|
||||||
/// but there are two differences:
|
/// but `repeat_n()` can return the original value, rather than always cloning.
|
||||||
/// - `repeat_n()` can return the original value, rather than always cloning.
|
|
||||||
/// - `repeat_n()` produces an [`ExactSizeIterator`].
|
|
||||||
///
|
///
|
||||||
/// [`repeat()`]: crate::iter::repeat
|
/// [`repeat()`]: crate::iter::repeat
|
||||||
///
|
///
|
||||||
|
@ -129,7 +129,7 @@
|
|||||||
#![feature(const_nonnull_new)]
|
#![feature(const_nonnull_new)]
|
||||||
#![feature(const_num_midpoint)]
|
#![feature(const_num_midpoint)]
|
||||||
#![feature(const_option_ext)]
|
#![feature(const_option_ext)]
|
||||||
#![feature(const_pin)]
|
#![feature(const_pin_2)]
|
||||||
#![feature(const_pointer_is_aligned)]
|
#![feature(const_pointer_is_aligned)]
|
||||||
#![feature(const_ptr_is_null)]
|
#![feature(const_ptr_is_null)]
|
||||||
#![feature(const_ptr_sub_ptr)]
|
#![feature(const_ptr_sub_ptr)]
|
||||||
|
@ -1186,7 +1186,7 @@ impl<Ptr: Deref<Target: Unpin>> Pin<Ptr> {
|
|||||||
/// let mut pinned: Pin<&mut u8> = Pin::new(&mut val);
|
/// let mut pinned: Pin<&mut u8> = Pin::new(&mut val);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
#[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[stable(feature = "pin", since = "1.33.0")]
|
#[stable(feature = "pin", since = "1.33.0")]
|
||||||
pub const fn new(pointer: Ptr) -> Pin<Ptr> {
|
pub const fn new(pointer: Ptr) -> Pin<Ptr> {
|
||||||
// SAFETY: the value pointed to is `Unpin`, and so has no requirements
|
// SAFETY: the value pointed to is `Unpin`, and so has no requirements
|
||||||
@ -1214,7 +1214,7 @@ impl<Ptr: Deref<Target: Unpin>> Pin<Ptr> {
|
|||||||
/// assert_eq!(*r, 5);
|
/// assert_eq!(*r, 5);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
#[rustc_const_unstable(feature = "const_pin_2", issue = "76654")]
|
||||||
#[stable(feature = "pin_into_inner", since = "1.39.0")]
|
#[stable(feature = "pin_into_inner", since = "1.39.0")]
|
||||||
pub const fn into_inner(pin: Pin<Ptr>) -> Ptr {
|
pub const fn into_inner(pin: Pin<Ptr>) -> Ptr {
|
||||||
pin.__pointer
|
pin.__pointer
|
||||||
@ -1351,7 +1351,7 @@ impl<Ptr: Deref> Pin<Ptr> {
|
|||||||
/// [`pin` module docs]: self
|
/// [`pin` module docs]: self
|
||||||
#[lang = "new_unchecked"]
|
#[lang = "new_unchecked"]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
#[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[stable(feature = "pin", since = "1.33.0")]
|
#[stable(feature = "pin", since = "1.33.0")]
|
||||||
pub const unsafe fn new_unchecked(pointer: Ptr) -> Pin<Ptr> {
|
pub const unsafe fn new_unchecked(pointer: Ptr) -> Pin<Ptr> {
|
||||||
Pin { __pointer: pointer }
|
Pin { __pointer: pointer }
|
||||||
@ -1503,7 +1503,7 @@ impl<Ptr: Deref> Pin<Ptr> {
|
|||||||
/// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used
|
/// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used
|
||||||
/// instead.
|
/// instead.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
#[rustc_const_unstable(feature = "const_pin_2", issue = "76654")]
|
||||||
#[stable(feature = "pin_into_inner", since = "1.39.0")]
|
#[stable(feature = "pin_into_inner", since = "1.39.0")]
|
||||||
pub const unsafe fn into_inner_unchecked(pin: Pin<Ptr>) -> Ptr {
|
pub const unsafe fn into_inner_unchecked(pin: Pin<Ptr>) -> Ptr {
|
||||||
pin.__pointer
|
pin.__pointer
|
||||||
@ -1559,7 +1559,7 @@ impl<'a, T: ?Sized> Pin<&'a T> {
|
|||||||
/// ["pinning projections"]: self#projections-and-structural-pinning
|
/// ["pinning projections"]: self#projections-and-structural-pinning
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
#[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[stable(feature = "pin", since = "1.33.0")]
|
#[stable(feature = "pin", since = "1.33.0")]
|
||||||
pub const fn get_ref(self) -> &'a T {
|
pub const fn get_ref(self) -> &'a T {
|
||||||
self.__pointer
|
self.__pointer
|
||||||
@ -1570,7 +1570,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
|
|||||||
/// Converts this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime.
|
/// Converts this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use = "`self` will be dropped if the result is not used"]
|
#[must_use = "`self` will be dropped if the result is not used"]
|
||||||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
#[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[stable(feature = "pin", since = "1.33.0")]
|
#[stable(feature = "pin", since = "1.33.0")]
|
||||||
pub const fn into_ref(self) -> Pin<&'a T> {
|
pub const fn into_ref(self) -> Pin<&'a T> {
|
||||||
Pin { __pointer: self.__pointer }
|
Pin { __pointer: self.__pointer }
|
||||||
@ -1588,7 +1588,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use = "`self` will be dropped if the result is not used"]
|
#[must_use = "`self` will be dropped if the result is not used"]
|
||||||
#[stable(feature = "pin", since = "1.33.0")]
|
#[stable(feature = "pin", since = "1.33.0")]
|
||||||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
#[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")]
|
||||||
pub const fn get_mut(self) -> &'a mut T
|
pub const fn get_mut(self) -> &'a mut T
|
||||||
where
|
where
|
||||||
T: Unpin,
|
T: Unpin,
|
||||||
@ -1609,7 +1609,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use = "`self` will be dropped if the result is not used"]
|
#[must_use = "`self` will be dropped if the result is not used"]
|
||||||
#[stable(feature = "pin", since = "1.33.0")]
|
#[stable(feature = "pin", since = "1.33.0")]
|
||||||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
#[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")]
|
||||||
pub const unsafe fn get_unchecked_mut(self) -> &'a mut T {
|
pub const unsafe fn get_unchecked_mut(self) -> &'a mut T {
|
||||||
self.__pointer
|
self.__pointer
|
||||||
}
|
}
|
||||||
@ -1652,7 +1652,7 @@ impl<T: ?Sized> Pin<&'static T> {
|
|||||||
/// This is safe because `T` is borrowed immutably for the `'static` lifetime, which
|
/// This is safe because `T` is borrowed immutably for the `'static` lifetime, which
|
||||||
/// never ends.
|
/// never ends.
|
||||||
#[stable(feature = "pin_static_ref", since = "1.61.0")]
|
#[stable(feature = "pin_static_ref", since = "1.61.0")]
|
||||||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
#[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")]
|
||||||
pub const fn static_ref(r: &'static T) -> Pin<&'static T> {
|
pub const fn static_ref(r: &'static T) -> Pin<&'static T> {
|
||||||
// SAFETY: The 'static borrow guarantees the data will not be
|
// SAFETY: The 'static borrow guarantees the data will not be
|
||||||
// moved/invalidated until it gets dropped (which is never).
|
// moved/invalidated until it gets dropped (which is never).
|
||||||
@ -1666,7 +1666,7 @@ impl<T: ?Sized> Pin<&'static mut T> {
|
|||||||
/// This is safe because `T` is borrowed for the `'static` lifetime, which
|
/// This is safe because `T` is borrowed for the `'static` lifetime, which
|
||||||
/// never ends.
|
/// never ends.
|
||||||
#[stable(feature = "pin_static_ref", since = "1.61.0")]
|
#[stable(feature = "pin_static_ref", since = "1.61.0")]
|
||||||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
#[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")]
|
||||||
pub const fn static_mut(r: &'static mut T) -> Pin<&'static mut T> {
|
pub const fn static_mut(r: &'static mut T) -> Pin<&'static mut T> {
|
||||||
// SAFETY: The 'static borrow guarantees the data will not be
|
// SAFETY: The 'static borrow guarantees the data will not be
|
||||||
// moved/invalidated until it gets dropped (which is never).
|
// moved/invalidated until it gets dropped (which is never).
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#![feature(const_likely)]
|
#![feature(const_likely)]
|
||||||
#![feature(const_nonnull_new)]
|
#![feature(const_nonnull_new)]
|
||||||
#![feature(const_option_ext)]
|
#![feature(const_option_ext)]
|
||||||
#![feature(const_pin)]
|
#![feature(const_pin_2)]
|
||||||
#![feature(const_pointer_is_aligned)]
|
#![feature(const_pointer_is_aligned)]
|
||||||
#![feature(const_three_way_compare)]
|
#![feature(const_three_way_compare)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
@ -19,6 +19,10 @@ fn pin_const() {
|
|||||||
const REF: &'static usize = PINNED.get_ref();
|
const REF: &'static usize = PINNED.get_ref();
|
||||||
assert_eq!(REF, POINTER);
|
assert_eq!(REF, POINTER);
|
||||||
|
|
||||||
|
const INT: u8 = 42;
|
||||||
|
const STATIC_REF: Pin<&'static u8> = Pin::static_ref(&INT);
|
||||||
|
assert_eq!(*STATIC_REF, INT);
|
||||||
|
|
||||||
// Note: `pin_mut_const` tests that the methods of `Pin<&mut T>` are usable in a const context.
|
// Note: `pin_mut_const` tests that the methods of `Pin<&mut T>` are usable in a const context.
|
||||||
// A const fn is used because `&mut` is not (yet) usable in constants.
|
// A const fn is used because `&mut` is not (yet) usable in constants.
|
||||||
const fn pin_mut_const() {
|
const fn pin_mut_const() {
|
||||||
|
@ -40,6 +40,7 @@ use crate::sys::random as sys;
|
|||||||
/// Horizon | `getrandom` shim
|
/// Horizon | `getrandom` shim
|
||||||
/// Hurd, L4Re, QNX | `/dev/urandom`
|
/// Hurd, L4Re, QNX | `/dev/urandom`
|
||||||
/// Redox | `/scheme/rand`
|
/// Redox | `/scheme/rand`
|
||||||
|
/// RTEMS | [`arc4random_buf`](https://docs.rtems.org/branches/master/bsp-howto/getentropy.html)
|
||||||
/// SGX | [`rdrand`](https://en.wikipedia.org/wiki/RDRAND)
|
/// SGX | [`rdrand`](https://en.wikipedia.org/wiki/RDRAND)
|
||||||
/// SOLID | `SOLID_RNG_SampleRandomBytes`
|
/// SOLID | `SOLID_RNG_SampleRandomBytes`
|
||||||
/// TEEOS | `TEE_GenerateRandom`
|
/// TEEOS | `TEE_GenerateRandom`
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#[cfg(not(any(
|
#[cfg(not(any(
|
||||||
target_os = "haiku",
|
target_os = "haiku",
|
||||||
target_os = "illumos",
|
target_os = "illumos",
|
||||||
|
target_os = "rtems",
|
||||||
target_os = "solaris",
|
target_os = "solaris",
|
||||||
target_os = "vita",
|
target_os = "vita",
|
||||||
)))]
|
)))]
|
||||||
@ -21,6 +22,7 @@ use libc::arc4random_buf;
|
|||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
target_os = "haiku", // See https://git.haiku-os.org/haiku/tree/headers/compatibility/bsd/stdlib.h
|
target_os = "haiku", // See https://git.haiku-os.org/haiku/tree/headers/compatibility/bsd/stdlib.h
|
||||||
target_os = "illumos", // See https://www.illumos.org/man/3C/arc4random
|
target_os = "illumos", // See https://www.illumos.org/man/3C/arc4random
|
||||||
|
target_os = "rtems", // See https://docs.rtems.org/branches/master/bsp-howto/getentropy.html
|
||||||
target_os = "solaris", // See https://docs.oracle.com/cd/E88353_01/html/E37843/arc4random-3c.html
|
target_os = "solaris", // See https://docs.oracle.com/cd/E88353_01/html/E37843/arc4random-3c.html
|
||||||
target_os = "vita", // See https://github.com/vitasdk/newlib/blob/b89e5bc183b516945f9ee07eef483ecb916e45ff/newlib/libc/include/stdlib.h#L74
|
target_os = "vita", // See https://github.com/vitasdk/newlib/blob/b89e5bc183b516945f9ee07eef483ecb916e45ff/newlib/libc/include/stdlib.h#L74
|
||||||
))]
|
))]
|
||||||
|
@ -17,6 +17,7 @@ cfg_if::cfg_if! {
|
|||||||
target_os = "illumos",
|
target_os = "illumos",
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
target_os = "openbsd",
|
target_os = "openbsd",
|
||||||
|
target_os = "rtems",
|
||||||
target_os = "solaris",
|
target_os = "solaris",
|
||||||
target_os = "vita",
|
target_os = "vita",
|
||||||
))] {
|
))] {
|
||||||
|
@ -49,20 +49,21 @@ pub use lazy::Storage as LazyStorage;
|
|||||||
#[unstable(feature = "thread_local_internals", issue = "none")]
|
#[unstable(feature = "thread_local_internals", issue = "none")]
|
||||||
#[rustc_macro_transparency = "semitransparent"]
|
#[rustc_macro_transparency = "semitransparent"]
|
||||||
pub macro thread_local_inner {
|
pub macro thread_local_inner {
|
||||||
// used to generate the `LocalKey` value for const-initialized thread locals
|
// NOTE: we cannot import `LocalKey`, `LazyStorage` or `EagerStorage` with a `use` because that
|
||||||
|
// can shadow user provided type or type alias with a matching name. Please update the shadowing
|
||||||
|
// test in `tests/thread.rs` if these types are renamed.
|
||||||
|
|
||||||
|
// Used to generate the `LocalKey` value for const-initialized thread locals.
|
||||||
(@key $t:ty, const $init:expr) => {{
|
(@key $t:ty, const $init:expr) => {{
|
||||||
const __INIT: $t = $init;
|
const __INIT: $t = $init;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
use $crate::mem::needs_drop;
|
$crate::thread::LocalKey::new(const {
|
||||||
use $crate::thread::LocalKey;
|
if $crate::mem::needs_drop::<$t>() {
|
||||||
use $crate::thread::local_impl::EagerStorage;
|
|
||||||
|
|
||||||
LocalKey::new(const {
|
|
||||||
if needs_drop::<$t>() {
|
|
||||||
|_| {
|
|_| {
|
||||||
#[thread_local]
|
#[thread_local]
|
||||||
static VAL: EagerStorage<$t> = EagerStorage::new(__INIT);
|
static VAL: $crate::thread::local_impl::EagerStorage<$t>
|
||||||
|
= $crate::thread::local_impl::EagerStorage::new(__INIT);
|
||||||
VAL.get()
|
VAL.get()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -84,21 +85,19 @@ pub macro thread_local_inner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
use $crate::mem::needs_drop;
|
$crate::thread::LocalKey::new(const {
|
||||||
use $crate::thread::LocalKey;
|
if $crate::mem::needs_drop::<$t>() {
|
||||||
use $crate::thread::local_impl::LazyStorage;
|
|
||||||
|
|
||||||
LocalKey::new(const {
|
|
||||||
if needs_drop::<$t>() {
|
|
||||||
|init| {
|
|init| {
|
||||||
#[thread_local]
|
#[thread_local]
|
||||||
static VAL: LazyStorage<$t, ()> = LazyStorage::new();
|
static VAL: $crate::thread::local_impl::LazyStorage<$t, ()>
|
||||||
|
= $crate::thread::local_impl::LazyStorage::new();
|
||||||
VAL.get_or_init(init, __init)
|
VAL.get_or_init(init, __init)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|init| {
|
|init| {
|
||||||
#[thread_local]
|
#[thread_local]
|
||||||
static VAL: LazyStorage<$t, !> = LazyStorage::new();
|
static VAL: $crate::thread::local_impl::LazyStorage<$t, !>
|
||||||
|
= $crate::thread::local_impl::LazyStorage::new();
|
||||||
VAL.get_or_init(init, __init)
|
VAL.get_or_init(init, __init)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,19 +15,24 @@ pub macro thread_local_inner {
|
|||||||
$crate::thread::local_impl::thread_local_inner!(@key $t, { const INIT_EXPR: $t = $init; INIT_EXPR })
|
$crate::thread::local_impl::thread_local_inner!(@key $t, { const INIT_EXPR: $t = $init; INIT_EXPR })
|
||||||
},
|
},
|
||||||
|
|
||||||
// used to generate the `LocalKey` value for `thread_local!`
|
// NOTE: we cannot import `Storage` or `LocalKey` with a `use` because that can shadow user
|
||||||
|
// provided type or type alias with a matching name. Please update the shadowing test in
|
||||||
|
// `tests/thread.rs` if these types are renamed.
|
||||||
|
|
||||||
|
// used to generate the `LocalKey` value for `thread_local!`.
|
||||||
(@key $t:ty, $init:expr) => {{
|
(@key $t:ty, $init:expr) => {{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn __init() -> $t { $init }
|
fn __init() -> $t { $init }
|
||||||
|
|
||||||
|
// NOTE: this cannot import `LocalKey` or `Storage` with a `use` because that can shadow
|
||||||
|
// user provided type or type alias with a matching name. Please update the shadowing test
|
||||||
|
// in `tests/thread.rs` if these types are renamed.
|
||||||
unsafe {
|
unsafe {
|
||||||
use $crate::thread::LocalKey;
|
|
||||||
use $crate::thread::local_impl::Storage;
|
|
||||||
|
|
||||||
// Inlining does not work on windows-gnu due to linking errors around
|
// Inlining does not work on windows-gnu due to linking errors around
|
||||||
// dllimports. See https://github.com/rust-lang/rust/issues/109797.
|
// dllimports. See https://github.com/rust-lang/rust/issues/109797.
|
||||||
LocalKey::new(#[cfg_attr(windows, inline(never))] |init| {
|
$crate::thread::LocalKey::new(#[cfg_attr(windows, inline(never))] |init| {
|
||||||
static VAL: Storage<$t> = Storage::new();
|
static VAL: $crate::thread::local_impl::Storage<$t>
|
||||||
|
= $crate::thread::local_impl::Storage::new();
|
||||||
VAL.get(init, __init)
|
VAL.get(init, __init)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,29 @@ fn thread_local_containing_const_statements() {
|
|||||||
assert_eq!(REFCELL.take(), 1);
|
assert_eq!(REFCELL.take(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn thread_local_hygeiene() {
|
||||||
|
// Previously `thread_local_inner!` had use imports for `LocalKey`, `Storage`, `EagerStorage`
|
||||||
|
// and `LazyStorage`. The use imports will shadow a user-provided type or type alias if the
|
||||||
|
// user-provided type or type alias has the same name. Make sure that this does not happen. See
|
||||||
|
// <https://github.com/rust-lang/rust/issues/131863>.
|
||||||
|
//
|
||||||
|
// NOTE: if the internal implementation details change (i.e. get renamed), this test should be
|
||||||
|
// updated.
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
type LocalKey = ();
|
||||||
|
type Storage = ();
|
||||||
|
type LazyStorage = ();
|
||||||
|
type EagerStorage = ();
|
||||||
|
thread_local! {
|
||||||
|
static A: LocalKey = const { () };
|
||||||
|
static B: Storage = const { () };
|
||||||
|
static C: LazyStorage = const { () };
|
||||||
|
static D: EagerStorage = const { () };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
// Include an ignore list on purpose, so that new platforms don't miss it
|
// Include an ignore list on purpose, so that new platforms don't miss it
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
|
@ -59,6 +59,8 @@ case $HOST_TARGET in
|
|||||||
# "error: cannot produce cdylib for ... as the target ... does not support these crate types".
|
# "error: cannot produce cdylib for ... as the target ... does not support these crate types".
|
||||||
# Only run "pass" tests, which is quite a bit faster.
|
# Only run "pass" tests, which is quite a bit faster.
|
||||||
#FIXME: Re-enable this once CI issues are fixed
|
#FIXME: Re-enable this once CI issues are fixed
|
||||||
|
# See <https://github.com/rust-lang/rust/issues/127883>
|
||||||
|
# For now, these tests are moved to `x86_64-msvc-ext2` in `src/ci/github-actions/jobs.yml`.
|
||||||
#python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass
|
#python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass
|
||||||
#python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-gnu --test-args pass
|
#python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-gnu --test-args pass
|
||||||
;;
|
;;
|
||||||
|
@ -386,6 +386,8 @@ auto:
|
|||||||
<<: *job-windows-8c
|
<<: *job-windows-8c
|
||||||
|
|
||||||
# Temporary builder to workaround CI issues
|
# Temporary builder to workaround CI issues
|
||||||
|
# See <https://github.com/rust-lang/rust/issues/127883>
|
||||||
|
#FIXME: Remove this, and re-enable the same tests in `checktools.sh`, once CI issues are fixed.
|
||||||
- image: x86_64-msvc-ext2
|
- image: x86_64-msvc-ext2
|
||||||
env:
|
env:
|
||||||
SCRIPT: >
|
SCRIPT: >
|
||||||
|
56
tests/coverage/async_closure.cov-map
Normal file
56
tests/coverage/async_closure.cov-map
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
Function name: async_closure::call_once::<async_closure::main::{closure#0}>
|
||||||
|
Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 2c]
|
||||||
|
Number of files: 1
|
||||||
|
- file 0 => global file 1
|
||||||
|
Number of expressions: 0
|
||||||
|
Number of file 0 mappings: 1
|
||||||
|
- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 44)
|
||||||
|
Highest counter ID seen: c0
|
||||||
|
|
||||||
|
Function name: async_closure::call_once::<async_closure::main::{closure#0}>::{closure#0}
|
||||||
|
Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 2c, 01, 0e, 05, 02, 01, 00, 02]
|
||||||
|
Number of files: 1
|
||||||
|
- file 0 => global file 1
|
||||||
|
Number of expressions: 0
|
||||||
|
Number of file 0 mappings: 2
|
||||||
|
- Code(Counter(0)) at (prev + 7, 44) to (start + 1, 14)
|
||||||
|
- Code(Counter(1)) at (prev + 2, 1) to (start + 0, 2)
|
||||||
|
Highest counter ID seen: c1
|
||||||
|
|
||||||
|
Function name: async_closure::main
|
||||||
|
Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 01, 01, 16, 01, 02, 05, 02, 02]
|
||||||
|
Number of files: 1
|
||||||
|
- file 0 => global file 1
|
||||||
|
Number of expressions: 0
|
||||||
|
Number of file 0 mappings: 2
|
||||||
|
- Code(Counter(0)) at (prev + 11, 1) to (start + 1, 22)
|
||||||
|
- Code(Counter(0)) at (prev + 2, 5) to (start + 2, 2)
|
||||||
|
Highest counter ID seen: c0
|
||||||
|
|
||||||
|
Function name: async_closure::main::{closure#0}
|
||||||
|
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 23, 00, 24]
|
||||||
|
Number of files: 1
|
||||||
|
- file 0 => global file 1
|
||||||
|
Number of expressions: 0
|
||||||
|
Number of file 0 mappings: 1
|
||||||
|
- Code(Counter(0)) at (prev + 12, 35) to (start + 0, 36)
|
||||||
|
Highest counter ID seen: c0
|
||||||
|
|
||||||
|
Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
|
||||||
|
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 22, 00, 24]
|
||||||
|
Number of files: 1
|
||||||
|
- file 0 => global file 1
|
||||||
|
Number of expressions: 0
|
||||||
|
Number of file 0 mappings: 1
|
||||||
|
- Code(Counter(0)) at (prev + 12, 34) to (start + 0, 36)
|
||||||
|
Highest counter ID seen: c0
|
||||||
|
|
||||||
|
Function name: async_closure::main::{closure#0}::{closure#1}::<i32>
|
||||||
|
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 23, 00, 24]
|
||||||
|
Number of files: 1
|
||||||
|
- file 0 => global file 1
|
||||||
|
Number of expressions: 0
|
||||||
|
Number of file 0 mappings: 1
|
||||||
|
- Code(Counter(0)) at (prev + 12, 35) to (start + 0, 36)
|
||||||
|
Highest counter ID seen: c0
|
||||||
|
|
24
tests/coverage/async_closure.coverage
Normal file
24
tests/coverage/async_closure.coverage
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
LL| |#![feature(async_closure)]
|
||||||
|
LL| |//@ edition: 2021
|
||||||
|
LL| |
|
||||||
|
LL| |//@ aux-build: executor.rs
|
||||||
|
LL| |extern crate executor;
|
||||||
|
LL| |
|
||||||
|
LL| 1|async fn call_once(f: impl async FnOnce()) {
|
||||||
|
LL| 1| f().await;
|
||||||
|
LL| 1|}
|
||||||
|
LL| |
|
||||||
|
LL| 1|pub fn main() {
|
||||||
|
LL| 2| let async_closure = async || {};
|
||||||
|
^1
|
||||||
|
------------------
|
||||||
|
| async_closure::main::{closure#0}:
|
||||||
|
| LL| 1| let async_closure = async || {};
|
||||||
|
------------------
|
||||||
|
| async_closure::main::{closure#0}::{closure#1}::<i32>:
|
||||||
|
| LL| 1| let async_closure = async || {};
|
||||||
|
------------------
|
||||||
|
LL| 1| executor::block_on(async_closure());
|
||||||
|
LL| 1| executor::block_on(call_once(async_closure));
|
||||||
|
LL| 1|}
|
||||||
|
|
15
tests/coverage/async_closure.rs
Normal file
15
tests/coverage/async_closure.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#![feature(async_closure)]
|
||||||
|
//@ edition: 2021
|
||||||
|
|
||||||
|
//@ aux-build: executor.rs
|
||||||
|
extern crate executor;
|
||||||
|
|
||||||
|
async fn call_once(f: impl async FnOnce()) {
|
||||||
|
f().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let async_closure = async || {};
|
||||||
|
executor::block_on(async_closure());
|
||||||
|
executor::block_on(call_once(async_closure));
|
||||||
|
}
|
@ -1,19 +0,0 @@
|
|||||||
//@ known-bug: #131190
|
|
||||||
//@ compile-flags: -Cinstrument-coverage --edition=2018
|
|
||||||
|
|
||||||
use std::future::Future;
|
|
||||||
|
|
||||||
pub fn block_on<T>(fut: impl Future<Output = T>) -> T {}
|
|
||||||
|
|
||||||
async fn call_once(f: impl async FnOnce(DropMe)) {
|
|
||||||
f(DropMe("world")).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DropMe(&'static str);
|
|
||||||
|
|
||||||
pub fn main() {
|
|
||||||
block_on(async {
|
|
||||||
let async_closure = async move |a: DropMe| {};
|
|
||||||
call_once(async_closure).await;
|
|
||||||
});
|
|
||||||
}
|
|
47
tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs
Normal file
47
tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
//! This test case is a `#![no_core]`-version of the MVCE presented in #129301.
|
||||||
|
//!
|
||||||
|
//! The function [`delay()`] is removed, as it is not necessary to trigger the
|
||||||
|
//! wrong behavior and would require some additional lang items.
|
||||||
|
#![feature(no_core, lang_items, intrinsics, rustc_attrs)]
|
||||||
|
#![no_core]
|
||||||
|
#![no_main]
|
||||||
|
#![allow(internal_features)]
|
||||||
|
|
||||||
|
use minicore::ptr;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn main() -> ! {
|
||||||
|
let port_b = 0x25 as *mut u8; // the I/O-address of PORTB
|
||||||
|
|
||||||
|
// a simple loop with some trivial instructions within. This loop label has
|
||||||
|
// to be placed correctly before the `ptr::write_volatile()` (some LLVM ver-
|
||||||
|
// sions did place it after the first loop instruction, causing unsoundness)
|
||||||
|
loop {
|
||||||
|
unsafe { ptr::write_volatile(port_b, 1) };
|
||||||
|
unsafe { ptr::write_volatile(port_b, 2) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: replace with proper minicore once available (#130693)
|
||||||
|
mod minicore {
|
||||||
|
#[lang = "sized"]
|
||||||
|
pub trait Sized {}
|
||||||
|
|
||||||
|
#[lang = "copy"]
|
||||||
|
pub trait Copy {}
|
||||||
|
impl Copy for u32 {}
|
||||||
|
impl Copy for &u32 {}
|
||||||
|
impl<T: ?Sized> Copy for *mut T {}
|
||||||
|
|
||||||
|
pub mod ptr {
|
||||||
|
#[inline]
|
||||||
|
#[rustc_diagnostic_item = "ptr_write_volatile"]
|
||||||
|
pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
|
||||||
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_nounwind]
|
||||||
|
pub fn volatile_store<T>(dst: *mut T, val: T);
|
||||||
|
}
|
||||||
|
unsafe { volatile_store(dst, src) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
tests/run-make/avr-rjmp-offset/rmake.rs
Normal file
60
tests/run-make/avr-rjmp-offset/rmake.rs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
//@ needs-llvm-components: avr
|
||||||
|
//@ needs-rust-lld
|
||||||
|
//! Regression test for #129301/llvm-project#106722 within `rustc`.
|
||||||
|
//!
|
||||||
|
//! Some LLVM-versions had wrong offsets in the local labels, causing the first
|
||||||
|
//! loop instruction to be missed. This test therefore contains a simple loop
|
||||||
|
//! with trivial instructions in it, to see, where the label is placed.
|
||||||
|
//!
|
||||||
|
//! This must be a `rmake`-test and cannot be a `tests/assembly`-test, since the
|
||||||
|
//! wrong output is only produced with direct assembly generation, but not when
|
||||||
|
//! "emit-asm" is used, as described in the issue description of #129301:
|
||||||
|
//! https://github.com/rust-lang/rust/issues/129301#issue-2475070770
|
||||||
|
use run_make_support::{llvm_objdump, rustc};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
rustc()
|
||||||
|
.input("avr-rjmp-offsets.rs")
|
||||||
|
.opt_level("s")
|
||||||
|
.panic("abort")
|
||||||
|
.target("avr-unknown-gnu-atmega328")
|
||||||
|
// normally one links with `avr-gcc`, but this is not available in CI,
|
||||||
|
// hence this test diverges from the default behavior to enable linking
|
||||||
|
// at all, which is necessary for the test (to resolve the labels). To
|
||||||
|
// not depend on a special linker script, the main-function is marked as
|
||||||
|
// the entry function, causing the linker to not remove it.
|
||||||
|
.linker("rust-lld")
|
||||||
|
.link_arg("--entry=main")
|
||||||
|
.output("compiled")
|
||||||
|
.run();
|
||||||
|
|
||||||
|
let disassembly = llvm_objdump().disassemble().input("compiled").run().stdout_utf8();
|
||||||
|
|
||||||
|
// search for the following instruction sequence:
|
||||||
|
// ```disassembly
|
||||||
|
// 00000080 <main>:
|
||||||
|
// 80: 81 e0 ldi r24, 0x1
|
||||||
|
// 82: 92 e0 ldi r25, 0x2
|
||||||
|
// 84: 85 b9 out 0x5, r24
|
||||||
|
// 86: 95 b9 out 0x5, r25
|
||||||
|
// 88: fd cf rjmp .-6
|
||||||
|
// ```
|
||||||
|
// This matches on all instructions, since the size of the instructions be-
|
||||||
|
// fore the relative jump has an impact on the label offset. Old versions
|
||||||
|
// of the Rust compiler did produce a label `rjmp .-4` (misses the first
|
||||||
|
// instruction in the loop).
|
||||||
|
assert!(disassembly.contains("<main>"), "no main function in output");
|
||||||
|
disassembly
|
||||||
|
.trim()
|
||||||
|
.lines()
|
||||||
|
.skip_while(|&line| !line.contains("<main>"))
|
||||||
|
.inspect(|line| println!("{line}"))
|
||||||
|
.skip(1)
|
||||||
|
.zip(["ldi\t", "ldi\t", "out\t", "out\t", "rjmp\t.-6"])
|
||||||
|
.for_each(|(line, expected_instruction)| {
|
||||||
|
assert!(
|
||||||
|
line.contains(expected_instruction),
|
||||||
|
"expected instruction `{expected_instruction}`, got `{line}`"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user