mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Auto merge of #108709 - matthiaskrgr:rollup-j2tjbyx, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #104549 (add -Zexport-executable-symbols to unstable book) - #108292 (Label opaque type for 'captures lifetime' error message) - #108540 (Add `Atomic*::from_ptr`) - #108634 (Add link to component dashboard) - #108647 (Remove dead pgo.sh file) - #108678 (Use `Option::as_slice` where applicable) - #108681 (Improve comments in `needs_process_obligation`.) - #108688 (Match unmatched backticks in library/) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
70adb4e5b4
@ -426,6 +426,7 @@ impl<O: ForestObligation> ObligationForest<O> {
|
||||
// nodes. Therefore we use a `while` loop.
|
||||
let mut index = 0;
|
||||
while let Some(node) = self.nodes.get_mut(index) {
|
||||
// This test is extremely hot.
|
||||
if node.state.get() != NodeState::Pending
|
||||
|| !processor.needs_process_obligation(&node.obligation)
|
||||
{
|
||||
@ -439,6 +440,7 @@ impl<O: ForestObligation> ObligationForest<O> {
|
||||
// out of sync with `nodes`. It's not very common, but it does
|
||||
// happen, and code in `compress` has to allow for it.
|
||||
|
||||
// This code is much less hot.
|
||||
match processor.process_obligation(&mut node.obligation) {
|
||||
ProcessResult::Unchanged => {
|
||||
// No change in state.
|
||||
|
@ -36,7 +36,6 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}
|
||||
|
||||
use std::iter;
|
||||
use std::mem;
|
||||
use std::slice;
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub(in super::super) fn check_casts(&mut self) {
|
||||
@ -1507,11 +1506,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let coerce = if blk.targeted_by_break {
|
||||
CoerceMany::new(coerce_to_ty)
|
||||
} else {
|
||||
let tail_expr: &[&hir::Expr<'_>] = match tail_expr {
|
||||
Some(e) => slice::from_ref(e),
|
||||
None => &[],
|
||||
};
|
||||
CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr)
|
||||
CoerceMany::with_coercion_sites(coerce_to_ty, blk.expr.as_slice())
|
||||
};
|
||||
|
||||
let prev_diverges = self.diverges.get();
|
||||
|
@ -5,6 +5,7 @@
|
||||
#![feature(min_specialization)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(option_as_slice)]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
|
@ -749,14 +749,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
let opname = Ident::with_dummy_span(opname);
|
||||
let input_types =
|
||||
opt_rhs.as_ref().map(|(_, ty)| std::slice::from_ref(ty)).unwrap_or_default();
|
||||
let (opt_rhs_expr, opt_rhs_ty) = opt_rhs.unzip();
|
||||
let input_types = opt_rhs_ty.as_slice();
|
||||
let cause = self.cause(
|
||||
span,
|
||||
traits::BinOp {
|
||||
rhs_span: opt_rhs.map(|(expr, _)| expr.span),
|
||||
is_lit: opt_rhs
|
||||
.map_or(false, |(expr, _)| matches!(expr.kind, hir::ExprKind::Lit(_))),
|
||||
rhs_span: opt_rhs_expr.map(|expr| expr.span),
|
||||
is_lit: opt_rhs_expr
|
||||
.map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
|
||||
output_ty: expected.only_has_type(self),
|
||||
},
|
||||
);
|
||||
|
@ -11,7 +11,6 @@ use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutabili
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use std::slice;
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
/// Type-check `*oprnd_expr` with `oprnd_expr` type-checked already.
|
||||
@ -393,11 +392,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
Some(self.typeck_results.borrow().node_substs(expr.hir_id).type_at(1))
|
||||
}
|
||||
};
|
||||
let arg_tys = match arg_ty {
|
||||
None => &[],
|
||||
Some(ref ty) => slice::from_ref(ty),
|
||||
};
|
||||
|
||||
let arg_tys = arg_ty.as_slice();
|
||||
let method = self.try_mutable_overloaded_place_op(expr.span, base_ty, arg_tys, op);
|
||||
let method = match method {
|
||||
Some(ok) => self.register_infer_ok_obligations(ok),
|
||||
|
@ -345,3 +345,6 @@ infer_prlf_defined_without_sub = the lifetime defined here...
|
||||
infer_prlf_must_oultive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
|
||||
infer_prlf_must_oultive_without_sup = ...must outlive the lifetime defined here
|
||||
infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
|
||||
|
||||
infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
|
||||
.label = opaque type defined here
|
||||
|
@ -1147,3 +1147,13 @@ pub enum PlaceholderRelationLfNotSatisfied {
|
||||
note: (),
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(infer_opaque_captures_lifetime, code = "E0700")]
|
||||
pub struct OpaqueCapturesLifetime<'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label]
|
||||
pub opaque_ty_span: Span,
|
||||
pub opaque_ty: Ty<'tcx>,
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ use super::lexical_region_resolve::RegionResolutionError;
|
||||
use super::region_constraints::GenericKind;
|
||||
use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
|
||||
|
||||
use crate::errors;
|
||||
use crate::infer;
|
||||
use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
|
||||
use crate::infer::ExpectedFound;
|
||||
@ -281,15 +282,13 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
|
||||
span: Span,
|
||||
hidden_ty: Ty<'tcx>,
|
||||
hidden_region: ty::Region<'tcx>,
|
||||
opaque_ty: ty::OpaqueTypeKey<'tcx>,
|
||||
opaque_ty_key: ty::OpaqueTypeKey<'tcx>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
let opaque_ty = tcx.mk_opaque(opaque_ty.def_id.to_def_id(), opaque_ty.substs);
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
let mut err = tcx.sess.create_err(errors::OpaqueCapturesLifetime {
|
||||
span,
|
||||
E0700,
|
||||
"hidden type for `{opaque_ty}` captures lifetime that does not appear in bounds",
|
||||
);
|
||||
opaque_ty: tcx.mk_opaque(opaque_ty_key.def_id.to_def_id(), opaque_ty_key.substs),
|
||||
opaque_ty_span: tcx.def_span(opaque_ty_key.def_id),
|
||||
});
|
||||
|
||||
// Explain the region we are capturing.
|
||||
match *hidden_region {
|
||||
|
@ -212,36 +212,44 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||
|
||||
/// Identifies whether a predicate obligation needs processing.
|
||||
///
|
||||
/// This is always inlined, despite its size, because it has a single
|
||||
/// callsite and it is called *very* frequently.
|
||||
/// This is always inlined because it has a single callsite and it is
|
||||
/// called *very* frequently. Be careful modifying this code! Several
|
||||
/// compile-time benchmarks are very sensitive to even small changes.
|
||||
#[inline(always)]
|
||||
fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool {
|
||||
// If we were stalled on some unresolved variables, first check whether
|
||||
// any of them have been resolved; if not, don't bother doing more work
|
||||
// yet.
|
||||
match pending_obligation.stalled_on.len() {
|
||||
// Match arms are in order of frequency, which matters because this
|
||||
// code is so hot. 1 and 0 dominate; 2+ is fairly rare.
|
||||
1 => {
|
||||
let infer_var = pending_obligation.stalled_on[0];
|
||||
self.selcx.infcx.ty_or_const_infer_var_changed(infer_var)
|
||||
}
|
||||
0 => {
|
||||
// In this case we haven't changed, but wish to make a change.
|
||||
true
|
||||
}
|
||||
_ => {
|
||||
// This `for` loop was once a call to `all()`, but this lower-level
|
||||
// form was a perf win. See #64545 for details.
|
||||
(|| {
|
||||
for &infer_var in &pending_obligation.stalled_on {
|
||||
if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
|
||||
return true;
|
||||
}
|
||||
let stalled_on = &pending_obligation.stalled_on;
|
||||
match stalled_on.len() {
|
||||
// This case is the hottest most of the time, being hit up to 99%
|
||||
// of the time. `keccak` and `cranelift-codegen-0.82.1` are
|
||||
// benchmarks that particularly stress this path.
|
||||
1 => self.selcx.infcx.ty_or_const_infer_var_changed(stalled_on[0]),
|
||||
|
||||
// In this case we haven't changed, but wish to make a change. Note
|
||||
// that this is a special case, and is not equivalent to the `_`
|
||||
// case below, which would return `false` for an empty `stalled_on`
|
||||
// vector.
|
||||
//
|
||||
// This case is usually hit only 1% of the time or less, though it
|
||||
// reaches 20% in `wasmparser-0.101.0`.
|
||||
0 => true,
|
||||
|
||||
// This case is usually hit only 1% of the time or less, though it
|
||||
// reaches 95% in `mime-0.3.16`, 64% in `wast-54.0.0`, and 12% in
|
||||
// `inflate-0.4.5`.
|
||||
//
|
||||
// The obvious way of writing this, with a call to `any()` and no
|
||||
// closure, is currently slower than this version.
|
||||
_ => (|| {
|
||||
for &infer_var in stalled_on {
|
||||
if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
})()
|
||||
}
|
||||
}
|
||||
false
|
||||
})(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2145,7 +2145,7 @@ impl<T, I: iter::TrustedLen<Item = T>> ToRcSlice<T> for I {
|
||||
Rc::from_iter_exact(self, low)
|
||||
}
|
||||
} else {
|
||||
// TrustedLen contract guarantees that `upper_bound == `None` implies an iterator
|
||||
// TrustedLen contract guarantees that `upper_bound == None` implies an iterator
|
||||
// length exceeding `usize::MAX`.
|
||||
// The default implementation would collect into a vec which would panic.
|
||||
// Thus we panic here immediately without invoking `Vec` code.
|
||||
|
@ -2895,7 +2895,7 @@ impl<T, I: iter::TrustedLen<Item = T>> ToArcSlice<T> for I {
|
||||
Arc::from_iter_exact(self, low)
|
||||
}
|
||||
} else {
|
||||
// TrustedLen contract guarantees that `upper_bound == `None` implies an iterator
|
||||
// TrustedLen contract guarantees that `upper_bound == None` implies an iterator
|
||||
// length exceeding `usize::MAX`.
|
||||
// The default implementation would collect into a vec which would panic.
|
||||
// Thus we panic here immediately without invoking `Vec` code.
|
||||
|
@ -56,7 +56,7 @@
|
||||
//! let value_any = value as &dyn Any;
|
||||
//!
|
||||
//! // Try to convert our value to a `String`. If successful, we want to
|
||||
//! // output the String`'s length as well as its value. If not, it's a
|
||||
//! // output the `String`'s length as well as its value. If not, it's a
|
||||
//! // different type: just print it out unadorned.
|
||||
//! match value_any.downcast_ref::<String>() {
|
||||
//! Some(as_string) => {
|
||||
|
@ -632,7 +632,7 @@ pub struct RefCell<T: ?Sized> {
|
||||
// Stores the location of the earliest currently active borrow.
|
||||
// This gets updated whenever we go from having zero borrows
|
||||
// to having a single borrow. When a borrow occurs, this gets included
|
||||
// in the generated `BorrowError/`BorrowMutError`
|
||||
// in the generated `BorrowError`/`BorrowMutError`
|
||||
#[cfg(feature = "debug_refcell")]
|
||||
borrowed_at: Cell<Option<&'static crate::panic::Location<'static>>>,
|
||||
value: UnsafeCell<T>,
|
||||
|
@ -42,7 +42,7 @@
|
||||
//! another function. The `dialect` and `phase` parameters indicate which [version of MIR][dialect
|
||||
//! docs] you are inserting here. Generally you'll want to use `#![custom_mir(dialect = "built")]`
|
||||
//! if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
|
||||
//! "runtime", phase = "optimized")] if you don't.
|
||||
//! "runtime", phase = "optimized")]` if you don't.
|
||||
//!
|
||||
//! [dialect docs]:
|
||||
//! https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.MirPhase.html
|
||||
|
@ -41,7 +41,7 @@ impl Alignment {
|
||||
/// Returns the alignment for a type.
|
||||
///
|
||||
/// This provides the same numerical value as [`mem::align_of`],
|
||||
/// but in an `Alignment` instead of a `usize.
|
||||
/// but in an `Alignment` instead of a `usize`.
|
||||
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||
#[inline]
|
||||
pub const fn of<T>() -> Self {
|
||||
|
@ -2955,7 +2955,7 @@ impl<T> [T] {
|
||||
// This operation is still `O(n)`.
|
||||
//
|
||||
// Example: We start in this state, where `r` represents "next
|
||||
// read" and `w` represents "next_write`.
|
||||
// read" and `w` represents "next_write".
|
||||
//
|
||||
// r
|
||||
// +---+---+---+---+---+---+
|
||||
|
@ -317,7 +317,7 @@ where
|
||||
// 1. `block` - Number of elements in the block.
|
||||
// 2. `start` - Start pointer into the `offsets` array.
|
||||
// 3. `end` - End pointer into the `offsets` array.
|
||||
// 4. `offsets - Indices of out-of-order elements within the block.
|
||||
// 4. `offsets` - Indices of out-of-order elements within the block.
|
||||
|
||||
// The current block on the left side (from `l` to `l.add(block_l)`).
|
||||
let mut l = v.as_mut_ptr();
|
||||
@ -327,7 +327,7 @@ where
|
||||
let mut offsets_l = [MaybeUninit::<u8>::uninit(); BLOCK];
|
||||
|
||||
// The current block on the right side (from `r.sub(block_r)` to `r`).
|
||||
// SAFETY: The documentation for .add() specifically mention that `vec.as_ptr().add(vec.len())` is always safe`
|
||||
// SAFETY: The documentation for .add() specifically mention that `vec.as_ptr().add(vec.len())` is always safe
|
||||
let mut r = unsafe { l.add(v.len()) };
|
||||
let mut block_r = BLOCK;
|
||||
let mut start_r = ptr::null_mut();
|
||||
|
@ -305,6 +305,50 @@ impl AtomicBool {
|
||||
AtomicBool { v: UnsafeCell::new(v as u8) }
|
||||
}
|
||||
|
||||
/// Creates a new `AtomicBool` from a pointer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(atomic_from_ptr, pointer_is_aligned)]
|
||||
/// use std::sync::atomic::{self, AtomicBool};
|
||||
/// use std::mem::align_of;
|
||||
///
|
||||
/// // Get a pointer to an allocated value
|
||||
/// let ptr: *mut bool = Box::into_raw(Box::new(false));
|
||||
///
|
||||
/// assert!(ptr.is_aligned_to(align_of::<AtomicBool>()));
|
||||
///
|
||||
/// {
|
||||
/// // Create an atomic view of the allocated value
|
||||
/// let atomic = unsafe { AtomicBool::from_ptr(ptr) };
|
||||
///
|
||||
/// // Use `atomic` for atomic operations, possibly share it with other threads
|
||||
/// atomic.store(true, atomic::Ordering::Relaxed);
|
||||
/// }
|
||||
///
|
||||
/// // It's ok to non-atomically access the value behind `ptr`,
|
||||
/// // since the reference to the atomic ended its lifetime in the block above
|
||||
/// assert_eq!(unsafe { *ptr }, true);
|
||||
///
|
||||
/// // Deallocate the value
|
||||
/// unsafe { drop(Box::from_raw(ptr)) }
|
||||
/// ```
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can be bigger than `align_of::<bool>()`).
|
||||
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
|
||||
/// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`.
|
||||
///
|
||||
/// [valid]: crate::ptr#safety
|
||||
#[unstable(feature = "atomic_from_ptr", issue = "108652")]
|
||||
#[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")]
|
||||
pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool {
|
||||
// SAFETY: guaranteed by the caller
|
||||
unsafe { &*ptr.cast() }
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the underlying [`bool`].
|
||||
///
|
||||
/// This is safe because the mutable reference guarantees that no other threads are
|
||||
@ -1017,6 +1061,50 @@ impl<T> AtomicPtr<T> {
|
||||
AtomicPtr { p: UnsafeCell::new(p) }
|
||||
}
|
||||
|
||||
/// Creates a new `AtomicPtr` from a pointer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(atomic_from_ptr, pointer_is_aligned)]
|
||||
/// use std::sync::atomic::{self, AtomicPtr};
|
||||
/// use std::mem::align_of;
|
||||
///
|
||||
/// // Get a pointer to an allocated value
|
||||
/// let ptr: *mut *mut u8 = Box::into_raw(Box::new(std::ptr::null_mut()));
|
||||
///
|
||||
/// assert!(ptr.is_aligned_to(align_of::<AtomicPtr<u8>>()));
|
||||
///
|
||||
/// {
|
||||
/// // Create an atomic view of the allocated value
|
||||
/// let atomic = unsafe { AtomicPtr::from_ptr(ptr) };
|
||||
///
|
||||
/// // Use `atomic` for atomic operations, possibly share it with other threads
|
||||
/// atomic.store(std::ptr::NonNull::dangling().as_ptr(), atomic::Ordering::Relaxed);
|
||||
/// }
|
||||
///
|
||||
/// // It's ok to non-atomically access the value behind `ptr`,
|
||||
/// // since the reference to the atomic ended its lifetime in the block above
|
||||
/// assert!(!unsafe { *ptr }.is_null());
|
||||
///
|
||||
/// // Deallocate the value
|
||||
/// unsafe { drop(Box::from_raw(ptr)) }
|
||||
/// ```
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// * `ptr` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this can be bigger than `align_of::<*mut T>()`).
|
||||
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
|
||||
/// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`.
|
||||
///
|
||||
/// [valid]: crate::ptr#safety
|
||||
#[unstable(feature = "atomic_from_ptr", issue = "108652")]
|
||||
#[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")]
|
||||
pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr<T> {
|
||||
// SAFETY: guaranteed by the caller
|
||||
unsafe { &*ptr.cast() }
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the underlying pointer.
|
||||
///
|
||||
/// This is safe because the mutable reference guarantees that no other threads are
|
||||
@ -1958,6 +2046,53 @@ macro_rules! atomic_int {
|
||||
Self {v: UnsafeCell::new(v)}
|
||||
}
|
||||
|
||||
/// Creates a new reference to an atomic integer from a pointer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(atomic_from_ptr, pointer_is_aligned)]
|
||||
#[doc = concat!($extra_feature, "use std::sync::atomic::{self, ", stringify!($atomic_type), "};")]
|
||||
/// use std::mem::align_of;
|
||||
///
|
||||
/// // Get a pointer to an allocated value
|
||||
#[doc = concat!("let ptr: *mut ", stringify!($int_type), " = Box::into_raw(Box::new(0));")]
|
||||
///
|
||||
#[doc = concat!("assert!(ptr.is_aligned_to(align_of::<", stringify!($atomic_type), ">()));")]
|
||||
///
|
||||
/// {
|
||||
/// // Create an atomic view of the allocated value
|
||||
// SAFETY: this is a doc comment, tidy, it can't hurt you (also guaranteed by the construction of `ptr` and the assert above)
|
||||
#[doc = concat!(" let atomic = unsafe {", stringify!($atomic_type), "::from_ptr(ptr) };")]
|
||||
///
|
||||
/// // Use `atomic` for atomic operations, possibly share it with other threads
|
||||
/// atomic.store(1, atomic::Ordering::Relaxed);
|
||||
/// }
|
||||
///
|
||||
/// // It's ok to non-atomically access the value behind `ptr`,
|
||||
/// // since the reference to the atomic ended its lifetime in the block above
|
||||
/// assert_eq!(unsafe { *ptr }, 1);
|
||||
///
|
||||
/// // Deallocate the value
|
||||
/// unsafe { drop(Box::from_raw(ptr)) }
|
||||
/// ```
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can be bigger than `align_of::<bool>()`).
|
||||
#[doc = concat!(" * `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this can be bigger than `align_of::<", stringify!($int_type), ">()`).")]
|
||||
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
|
||||
/// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`.
|
||||
///
|
||||
/// [valid]: crate::ptr#safety
|
||||
#[unstable(feature = "atomic_from_ptr", issue = "108652")]
|
||||
#[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")]
|
||||
pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type {
|
||||
// SAFETY: guaranteed by the caller
|
||||
unsafe { &*ptr.cast() }
|
||||
}
|
||||
|
||||
|
||||
/// Returns a mutable reference to the underlying integer.
|
||||
///
|
||||
/// This is safe because the mutable reference guarantees that no other threads are
|
||||
|
@ -24,7 +24,7 @@ mod zip;
|
||||
|
||||
use core::cell::Cell;
|
||||
|
||||
/// An iterator that panics whenever `next` or next_back` is called
|
||||
/// An iterator that panics whenever `next` or `next_back` is called
|
||||
/// after `None` has already been returned. This does not violate
|
||||
/// `Iterator`'s contract. Used to test that iterator adapters don't
|
||||
/// poll their inner iterators after exhausting them.
|
||||
|
@ -28,7 +28,7 @@ use crate::simd::{
|
||||
/// let zm_add = a0.zip(a1).map(|(lhs, rhs)| lhs + rhs);
|
||||
/// let zm_mul = a0.zip(a1).map(|(lhs, rhs)| lhs * rhs);
|
||||
///
|
||||
/// // `Simd<T, N>` implements `From<[T; N]>
|
||||
/// // `Simd<T, N>` implements `From<[T; N]>`
|
||||
/// let (v0, v1) = (Simd::from(a0), Simd::from(a1));
|
||||
/// // Which means arrays implement `Into<Simd<T, N>>`.
|
||||
/// assert_eq!(v0 + v1, zm_add.into());
|
||||
|
@ -1416,7 +1416,7 @@ impl From<fs::File> for Stdio {
|
||||
/// use std::fs::File;
|
||||
/// use std::process::Command;
|
||||
///
|
||||
/// // With the `foo.txt` file containing `Hello, world!"
|
||||
/// // With the `foo.txt` file containing "Hello, world!"
|
||||
/// let file = File::open("foo.txt").unwrap();
|
||||
///
|
||||
/// let reverse = Command::new("rev")
|
||||
|
@ -247,7 +247,7 @@ impl Thread {
|
||||
// [FINISHED → JOINED]
|
||||
// To synchronize with the child task's memory accesses to
|
||||
// `inner` up to the point of the assignment of `FINISHED`,
|
||||
// `Ordering::Acquire` must be used for the above `swap` call`.
|
||||
// `Ordering::Acquire` must be used for the above `swap` call.
|
||||
}
|
||||
_ => unsafe { hint::unreachable_unchecked() },
|
||||
}
|
||||
|
@ -329,7 +329,7 @@ pub fn cvt_nz(error: libc::c_int) -> crate::io::Result<()> {
|
||||
// do so. In 1003.1-2004 this was fixed.
|
||||
//
|
||||
// glibc's implementation did the flush, unsafely, before glibc commit
|
||||
// 91e7cf982d01 `abort: Do not flush stdio streams [BZ #15436]' by Florian
|
||||
// 91e7cf982d01 `abort: Do not flush stdio streams [BZ #15436]` by Florian
|
||||
// Weimer. According to glibc's NEWS:
|
||||
//
|
||||
// The abort function terminates the process immediately, without flushing
|
||||
|
@ -6,7 +6,7 @@ fn no_lookup_host_duplicates() {
|
||||
let mut addrs = HashMap::new();
|
||||
let lh = match LookupHost::try_from(("localhost", 0)) {
|
||||
Ok(lh) => lh,
|
||||
Err(e) => panic!("couldn't resolve `localhost': {e}"),
|
||||
Err(e) => panic!("couldn't resolve `localhost`: {e}"),
|
||||
};
|
||||
for sa in lh {
|
||||
*addrs.entry(sa).or_insert(0) += 1;
|
||||
|
@ -594,7 +594,7 @@ impl Wtf8 {
|
||||
}
|
||||
|
||||
/// Returns the code point at `position` if it is in the ASCII range,
|
||||
/// or `b'\xFF' otherwise.
|
||||
/// or `b'\xFF'` otherwise.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
|
@ -204,7 +204,7 @@ fn make_owned_test(test: &&TestDescAndFn) -> TestDescAndFn {
|
||||
}
|
||||
|
||||
/// Invoked when unit tests terminate. Returns `Result::Err` if the test is
|
||||
/// considered a failure. By default, invokes `report() and checks for a `0`
|
||||
/// considered a failure. By default, invokes `report()` and checks for a `0`
|
||||
/// result.
|
||||
pub fn assert_test_result<T: Termination>(result: T) -> Result<(), String> {
|
||||
let code = result.report().to_i32();
|
||||
|
@ -89,7 +89,7 @@ pub type _Unwind_Exception_Cleanup_Fn =
|
||||
|
||||
// FIXME: The `#[link]` attributes on `extern "C"` block marks those symbols declared in
|
||||
// the block are reexported in dylib build of std. This is needed when build rustc with
|
||||
// feature `llvm-libunwind', as no other cdylib will provided those _Unwind_* symbols.
|
||||
// feature `llvm-libunwind`, as no other cdylib will provided those _Unwind_* symbols.
|
||||
// However the `link` attribute is duplicated multiple times and does not just export symbol,
|
||||
// a better way to manually export symbol would be another attribute like `#[export]`.
|
||||
// See the logic in function rustc_codegen_ssa::src::back::exported_symbols, module
|
||||
|
230
src/ci/pgo.sh
230
src/ci/pgo.sh
@ -1,230 +0,0 @@
|
||||
#!/bin/bash
|
||||
# ignore-tidy-linelength
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
ci_dir=`cd $(dirname $0) && pwd`
|
||||
source "$ci_dir/shared.sh"
|
||||
|
||||
# The root checkout, where the source is located
|
||||
CHECKOUT=/checkout
|
||||
|
||||
DOWNLOADED_LLVM=/rustroot
|
||||
|
||||
# The main directory where the build occurs, which can be different between linux and windows
|
||||
BUILD_ROOT=$CHECKOUT/obj
|
||||
|
||||
if isWindows; then
|
||||
CHECKOUT=$(pwd)
|
||||
DOWNLOADED_LLVM=$CHECKOUT/citools/clang-rust
|
||||
BUILD_ROOT=$CHECKOUT
|
||||
fi
|
||||
|
||||
# The various build artifacts used in other commands: to launch rustc builds, build the perf
|
||||
# collector, and run benchmarks to gather profiling data
|
||||
BUILD_ARTIFACTS=$BUILD_ROOT/build/$PGO_HOST
|
||||
RUSTC_STAGE_0=$BUILD_ARTIFACTS/stage0/bin/rustc
|
||||
CARGO_STAGE_0=$BUILD_ARTIFACTS/stage0/bin/cargo
|
||||
RUSTC_STAGE_2=$BUILD_ARTIFACTS/stage2/bin/rustc
|
||||
|
||||
# Windows needs these to have the .exe extension
|
||||
if isWindows; then
|
||||
RUSTC_STAGE_0="${RUSTC_STAGE_0}.exe"
|
||||
CARGO_STAGE_0="${CARGO_STAGE_0}.exe"
|
||||
RUSTC_STAGE_2="${RUSTC_STAGE_2}.exe"
|
||||
fi
|
||||
|
||||
# Make sure we have a temporary PGO work folder
|
||||
PGO_TMP=/tmp/tmp-pgo
|
||||
mkdir -p $PGO_TMP
|
||||
rm -rf $PGO_TMP/*
|
||||
|
||||
RUSTC_PERF=$PGO_TMP/rustc-perf
|
||||
|
||||
# Compile several crates to gather execution PGO profiles.
|
||||
# Arg0 => profiles (Debug, Opt)
|
||||
# Arg1 => scenarios (Full, IncrFull, All)
|
||||
# Arg2 => crates (syn, cargo, ...)
|
||||
gather_profiles () {
|
||||
cd $BUILD_ROOT
|
||||
|
||||
# Compile libcore, both in opt-level=0 and opt-level=3
|
||||
RUSTC_BOOTSTRAP=1 $RUSTC_STAGE_2 \
|
||||
--edition=2021 --crate-type=lib $CHECKOUT/library/core/src/lib.rs \
|
||||
--out-dir $PGO_TMP
|
||||
RUSTC_BOOTSTRAP=1 $RUSTC_STAGE_2 \
|
||||
--edition=2021 --crate-type=lib -Copt-level=3 $CHECKOUT/library/core/src/lib.rs \
|
||||
--out-dir $PGO_TMP
|
||||
|
||||
cd $RUSTC_PERF
|
||||
|
||||
# Run rustc-perf benchmarks
|
||||
# Benchmark using profile_local with eprintln, which essentially just means
|
||||
# don't actually benchmark -- just make sure we run rustc a bunch of times.
|
||||
RUST_LOG=collector=debug \
|
||||
RUSTC=$RUSTC_STAGE_0 \
|
||||
RUSTC_BOOTSTRAP=1 \
|
||||
$CARGO_STAGE_0 run -p collector --bin collector -- \
|
||||
profile_local \
|
||||
eprintln \
|
||||
$RUSTC_STAGE_2 \
|
||||
--id Test \
|
||||
--profiles $1 \
|
||||
--cargo $CARGO_STAGE_0 \
|
||||
--scenarios $2 \
|
||||
--include $3
|
||||
|
||||
cd $BUILD_ROOT
|
||||
}
|
||||
|
||||
# This path has to be absolute
|
||||
LLVM_PROFILE_DIRECTORY_ROOT=$PGO_TMP/llvm-pgo
|
||||
|
||||
# We collect LLVM profiling information and rustc profiling information in
|
||||
# separate phases. This increases build time -- though not by a huge amount --
|
||||
# but prevents any problems from arising due to different profiling runtimes
|
||||
# being simultaneously linked in.
|
||||
# LLVM IR PGO does not respect LLVM_PROFILE_FILE, so we have to set the profiling file
|
||||
# path through our custom environment variable. We include the PID in the directory path
|
||||
# to avoid updates to profile files being lost because of race conditions.
|
||||
LLVM_PROFILE_DIR=${LLVM_PROFILE_DIRECTORY_ROOT}/prof-%p python3 $CHECKOUT/x.py build \
|
||||
--target=$PGO_HOST \
|
||||
--host=$PGO_HOST \
|
||||
--stage 2 library/std \
|
||||
--llvm-profile-generate
|
||||
|
||||
# Compile rustc-perf:
|
||||
# - get the expected commit source code: on linux, the Dockerfile downloads a source archive before
|
||||
# running this script. On Windows, we do that here.
|
||||
if isLinux; then
|
||||
cp -r /tmp/rustc-perf $RUSTC_PERF
|
||||
chown -R $(whoami): $RUSTC_PERF
|
||||
else
|
||||
# rustc-perf version from 2022-07-22
|
||||
PERF_COMMIT=3c253134664fdcba862c539d37f0de18557a9a4c
|
||||
retry curl -LS -o $PGO_TMP/perf.zip \
|
||||
https://github.com/rust-lang/rustc-perf/archive/$PERF_COMMIT.zip && \
|
||||
cd $PGO_TMP && unzip -q perf.zip && \
|
||||
mv rustc-perf-$PERF_COMMIT $RUSTC_PERF && \
|
||||
rm perf.zip
|
||||
fi
|
||||
|
||||
# - build rustc-perf's collector ahead of time, which is needed to make sure the rustc-fake binary
|
||||
# used by the collector is present.
|
||||
cd $RUSTC_PERF
|
||||
|
||||
RUSTC=$RUSTC_STAGE_0 \
|
||||
RUSTC_BOOTSTRAP=1 \
|
||||
$CARGO_STAGE_0 build -p collector
|
||||
|
||||
# Here we're profiling LLVM, so we only care about `Debug` and `Opt`, because we want to stress
|
||||
# codegen. We also profile some of the most prolific crates.
|
||||
gather_profiles "Debug,Opt" "Full" \
|
||||
"syn-1.0.89,cargo-0.60.0,serde-1.0.136,ripgrep-13.0.0,regex-1.5.5,clap-3.1.6,hyper-0.14.18"
|
||||
|
||||
LLVM_PROFILE_MERGED_FILE=$PGO_TMP/llvm-pgo.profdata
|
||||
|
||||
# Merge the profile data we gathered for LLVM
|
||||
# Note that this uses the profdata from the clang we used to build LLVM,
|
||||
# which likely has a different version than our in-tree clang.
|
||||
$DOWNLOADED_LLVM/bin/llvm-profdata merge -o ${LLVM_PROFILE_MERGED_FILE} ${LLVM_PROFILE_DIRECTORY_ROOT}
|
||||
|
||||
echo "LLVM PGO statistics"
|
||||
du -sh ${LLVM_PROFILE_MERGED_FILE}
|
||||
du -sh ${LLVM_PROFILE_DIRECTORY_ROOT}
|
||||
echo "Profile file count"
|
||||
find ${LLVM_PROFILE_DIRECTORY_ROOT} -type f | wc -l
|
||||
|
||||
# We don't need the individual .profraw files now that they have been merged into a final .profdata
|
||||
rm -r $LLVM_PROFILE_DIRECTORY_ROOT
|
||||
|
||||
# Rustbuild currently doesn't support rebuilding LLVM when PGO options
|
||||
# change (or any other llvm-related options); so just clear out the relevant
|
||||
# directories ourselves.
|
||||
rm -r $BUILD_ARTIFACTS/llvm $BUILD_ARTIFACTS/lld
|
||||
|
||||
# Okay, LLVM profiling is done, switch to rustc PGO.
|
||||
|
||||
# The path has to be absolute
|
||||
RUSTC_PROFILE_DIRECTORY_ROOT=$PGO_TMP/rustc-pgo
|
||||
|
||||
python3 $CHECKOUT/x.py build --target=$PGO_HOST --host=$PGO_HOST \
|
||||
--stage 2 library/std \
|
||||
--rust-profile-generate=${RUSTC_PROFILE_DIRECTORY_ROOT}
|
||||
|
||||
# Here we're profiling the `rustc` frontend, so we also include `Check`.
|
||||
# The benchmark set includes various stress tests that put the frontend under pressure.
|
||||
if isLinux; then
|
||||
# The profile data is written into a single filepath that is being repeatedly merged when each
|
||||
# rustc invocation ends. Empirically, this can result in some profiling data being lost. That's
|
||||
# why we override the profile path to include the PID. This will produce many more profiling
|
||||
# files, but the resulting profile will produce a slightly faster rustc binary.
|
||||
LLVM_PROFILE_FILE=${RUSTC_PROFILE_DIRECTORY_ROOT}/default_%m_%p.profraw gather_profiles \
|
||||
"Check,Debug,Opt" "All" \
|
||||
"externs,ctfe-stress-5,cargo-0.60.0,token-stream-stress,match-stress,tuple-stress,diesel-1.4.8,bitmaps-3.1.0"
|
||||
else
|
||||
# On windows, we don't do that yet (because it generates a lot of data, hitting disk space
|
||||
# limits on the builder), and use the default profraw merging behavior.
|
||||
gather_profiles \
|
||||
"Check,Debug,Opt" "All" \
|
||||
"externs,ctfe-stress-5,cargo-0.60.0,token-stream-stress,match-stress,tuple-stress,diesel-1.4.8,bitmaps-3.1.0"
|
||||
fi
|
||||
|
||||
RUSTC_PROFILE_MERGED_FILE=$PGO_TMP/rustc-pgo.profdata
|
||||
|
||||
# Merge the profile data we gathered
|
||||
$BUILD_ARTIFACTS/llvm/bin/llvm-profdata \
|
||||
merge -o ${RUSTC_PROFILE_MERGED_FILE} ${RUSTC_PROFILE_DIRECTORY_ROOT}
|
||||
|
||||
echo "Rustc PGO statistics"
|
||||
du -sh ${RUSTC_PROFILE_MERGED_FILE}
|
||||
du -sh ${RUSTC_PROFILE_DIRECTORY_ROOT}
|
||||
echo "Profile file count"
|
||||
find ${RUSTC_PROFILE_DIRECTORY_ROOT} -type f | wc -l
|
||||
|
||||
# We don't need the individual .profraw files now that they have been merged into a final .profdata
|
||||
rm -r $RUSTC_PROFILE_DIRECTORY_ROOT
|
||||
|
||||
# Rustbuild currently doesn't support rebuilding LLVM when PGO options
|
||||
# change (or any other llvm-related options); so just clear out the relevant
|
||||
# directories ourselves.
|
||||
rm -r $BUILD_ARTIFACTS/llvm $BUILD_ARTIFACTS/lld
|
||||
|
||||
if isLinux; then
|
||||
# Gather BOLT profile (BOLT is currently only available on Linux)
|
||||
python3 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \
|
||||
--stage 2 library/std \
|
||||
--llvm-profile-use=${LLVM_PROFILE_MERGED_FILE} \
|
||||
--llvm-bolt-profile-generate
|
||||
|
||||
BOLT_PROFILE_MERGED_FILE=/tmp/bolt.profdata
|
||||
|
||||
# Here we're profiling Bolt.
|
||||
gather_profiles "Check,Debug,Opt" "Full" \
|
||||
"syn-1.0.89,serde-1.0.136,ripgrep-13.0.0,regex-1.5.5,clap-3.1.6,hyper-0.14.18"
|
||||
|
||||
merge-fdata /tmp/prof.fdata* > ${BOLT_PROFILE_MERGED_FILE}
|
||||
|
||||
echo "BOLT statistics"
|
||||
du -sh /tmp/prof.fdata*
|
||||
du -sh ${BOLT_PROFILE_MERGED_FILE}
|
||||
echo "Profile file count"
|
||||
find /tmp/prof.fdata* -type f | wc -l
|
||||
|
||||
rm -r $BUILD_ARTIFACTS/llvm $BUILD_ARTIFACTS/lld
|
||||
|
||||
# This produces the actual final set of artifacts, using both the LLVM and rustc
|
||||
# collected profiling data.
|
||||
$@ \
|
||||
--rust-profile-use=${RUSTC_PROFILE_MERGED_FILE} \
|
||||
--llvm-profile-use=${LLVM_PROFILE_MERGED_FILE} \
|
||||
--llvm-bolt-profile-use=${BOLT_PROFILE_MERGED_FILE}
|
||||
else
|
||||
$@ \
|
||||
--rust-profile-use=${RUSTC_PROFILE_MERGED_FILE} \
|
||||
--llvm-profile-use=${LLVM_PROFILE_MERGED_FILE}
|
||||
fi
|
||||
|
||||
echo "Rustc binary size"
|
||||
ls -la ./build/$PGO_HOST/stage2/bin
|
||||
ls -la ./build/$PGO_HOST/stage2/lib
|
@ -13,6 +13,8 @@ for targets at each tier, see the [Target Tier Policy](target-tier-policy.md).
|
||||
Targets are identified by their "target triple" which is the string to inform
|
||||
the compiler what kind of output should be produced.
|
||||
|
||||
Component availability is tracked [here](https://rust-lang.github.io/rustup-components-history/).
|
||||
|
||||
## Tier 1 with Host Tools
|
||||
|
||||
Tier 1 targets can be thought of as "guaranteed to work". The Rust project
|
||||
|
@ -0,0 +1,43 @@
|
||||
# `export-executable-symbols`
|
||||
|
||||
The tracking issue for this feature is: [#84161](https://github.com/rust-lang/rust/issues/84161).
|
||||
|
||||
------------------------
|
||||
|
||||
The `-Zexport-executable-symbols` compiler flag makes `rustc` export symbols from executables. The resulting binary is runnable, but can also be used as a dynamic library. This is useful for interoperating with programs written in other languages, in particular languages with a runtime like Java or Lua.
|
||||
|
||||
For example on windows:
|
||||
```rust
|
||||
#[no_mangle]
|
||||
fn my_function() -> usize {
|
||||
return 42;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
```
|
||||
|
||||
A standard `cargo build` will produce a `.exe` without an export directory. When the `export-executable-symbols` flag is added
|
||||
|
||||
```Bash
|
||||
export RUSTFLAGS="-Zexport-executable-symbols"
|
||||
cargo build
|
||||
```
|
||||
|
||||
the binary has an export directory with the functions:
|
||||
|
||||
```plain
|
||||
The Export Tables (interpreted .edata section contents)
|
||||
|
||||
...
|
||||
|
||||
[Ordinal/Name Pointer] Table
|
||||
[ 0] my_function
|
||||
[ 1] main
|
||||
```
|
||||
(the output of `objdump -x` on the binary)
|
||||
|
||||
Please note that the `#[no_mangle]` attribute is required. Without it, the symbol is not exported.
|
||||
|
||||
The equivalent of this flag in C and C++ compilers is the `__declspec(dllexport)` annotation or the `-rdynamic` linker flag.
|
@ -17,8 +17,9 @@ error[E0700]: hidden type for `impl Trait<'a>` captures lifetime that does not a
|
||||
--> $DIR/ret-impl-trait-one.rs:16:80
|
||||
|
|
||||
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
|
||||
| ____________________________________--__________________________________________^
|
||||
| | |
|
||||
| ____________________________________--___________________________--------------_^
|
||||
| | | |
|
||||
| | | opaque type defined here
|
||||
| | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here
|
||||
LL | |
|
||||
LL | | (a, b)
|
||||
|
@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not a
|
||||
--> $DIR/hidden-lifetimes.rs:29:5
|
||||
|
|
||||
LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
|
||||
| -- hidden type `&'a mut &'b T` captures the lifetime `'b` as defined here
|
||||
| -- -------------- opaque type defined here
|
||||
| |
|
||||
| hidden type `&'a mut &'b T` captures the lifetime `'b` as defined here
|
||||
LL | x
|
||||
| ^
|
||||
|
|
||||
@ -15,7 +17,9 @@ error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not a
|
||||
--> $DIR/hidden-lifetimes.rs:46:5
|
||||
|
|
||||
LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
|
||||
| -- hidden type `Rc<RefCell<&'b T>>` captures the lifetime `'b` as defined here
|
||||
| -- -------------- opaque type defined here
|
||||
| |
|
||||
| hidden type `Rc<RefCell<&'b T>>` captures the lifetime `'b` as defined here
|
||||
LL | x
|
||||
| ^
|
||||
|
|
||||
|
@ -1,6 +1,8 @@
|
||||
error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds
|
||||
--> $DIR/impl-fn-hrtb-bounds-2.rs:5:9
|
||||
|
|
||||
LL | fn a() -> impl Fn(&u8) -> impl Debug {
|
||||
| ---------- opaque type defined here
|
||||
LL | |x| x
|
||||
| --- ^
|
||||
| |
|
||||
|
@ -1,6 +1,9 @@
|
||||
error[E0700]: hidden type for `E<'b, 'c>` captures lifetime that does not appear in bounds
|
||||
--> $DIR/error-handling-2.rs:22:5
|
||||
|
|
||||
LL | type E<'a, 'b> = impl Sized;
|
||||
| ---------- opaque type defined here
|
||||
LL |
|
||||
LL | fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
|
||||
| -- hidden type `*mut &'a i32` captures the lifetime `'a` as defined here
|
||||
...
|
||||
|
@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Trait<'d, 'e>` captures lifetime that does n
|
||||
--> $DIR/ordinary-bounds-unrelated.rs:28:33
|
||||
|
|
||||
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
|
||||
| -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
|
||||
| -- ------------------ opaque type defined here
|
||||
| |
|
||||
| hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
|
||||
...
|
||||
LL | if condition() { a } else { b }
|
||||
| ^
|
||||
|
@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Trait<'a, 'b>` captures lifetime that does n
|
||||
--> $DIR/ordinary-bounds-unsuited.rs:31:33
|
||||
|
|
||||
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
|
||||
| -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
|
||||
| -- ------------------ opaque type defined here
|
||||
| |
|
||||
| hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
|
||||
...
|
||||
LL | if condition() { a } else { b }
|
||||
| ^
|
||||
|
@ -2,8 +2,9 @@ error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:3:35
|
||||
|
|
||||
LL | fn elided(x: &i32) -> impl Copy { x }
|
||||
| ---- ^
|
||||
| |
|
||||
| ---- --------- ^
|
||||
| | |
|
||||
| | opaque type defined here
|
||||
| hidden type `&i32` captures the anonymous lifetime defined here
|
||||
|
|
||||
help: to declare that `impl Copy` captures `'_`, you can add an explicit `'_` lifetime bound
|
||||
@ -15,8 +16,9 @@ error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:6:44
|
||||
|
|
||||
LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
|
||||
| -- ^
|
||||
| |
|
||||
| -- --------- ^
|
||||
| | |
|
||||
| | opaque type defined here
|
||||
| hidden type `&'a i32` captures the lifetime `'a` as defined here
|
||||
|
|
||||
help: to declare that `impl Copy` captures `'a`, you can add an explicit `'a` lifetime bound
|
||||
@ -100,7 +102,9 @@ error[E0700]: hidden type for `impl Fn(&'a u32)` captures lifetime that does not
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:38:5
|
||||
|
|
||||
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
|
||||
| -- hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:13]` captures the lifetime `'b` as defined here
|
||||
| -- ---------------- opaque type defined here
|
||||
| |
|
||||
| hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:13]` captures the lifetime `'b` as defined here
|
||||
LL | move |_| println!("{}", y)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
|
@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Future<Output = impl Sized>` captures lifeti
|
||||
--> $DIR/nested-return-type4.rs:4:5
|
||||
|
|
||||
LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> {
|
||||
| -- hidden type `[async block@$DIR/nested-return-type4.rs:4:5: 4:31]` captures the lifetime `'s` as defined here
|
||||
| -- --------------------------------------------- opaque type defined here
|
||||
| |
|
||||
| hidden type `[async block@$DIR/nested-return-type4.rs:4:5: 4:31]` captures the lifetime `'s` as defined here
|
||||
LL | async move { let _s = s; }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
|
@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Trait<'y>` captures lifetime that does not a
|
||||
--> $DIR/region-escape-via-bound.rs:17:5
|
||||
|
|
||||
LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y>
|
||||
| -- hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here
|
||||
| -- -------------- opaque type defined here
|
||||
| |
|
||||
| hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here
|
||||
...
|
||||
LL | x
|
||||
| ^
|
||||
|
@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that
|
||||
--> $DIR/static-return-lifetime-infered.rs:7:9
|
||||
|
|
||||
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
|
||||
| ----- hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` captures the anonymous lifetime defined here
|
||||
| ----- ----------------------- opaque type defined here
|
||||
| |
|
||||
| hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` captures the anonymous lifetime defined here
|
||||
LL | self.x.iter().map(|a| a.0)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
@ -15,7 +17,9 @@ error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that
|
||||
--> $DIR/static-return-lifetime-infered.rs:11:9
|
||||
|
|
||||
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
|
||||
| -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:11:27: 11:30]>` captures the lifetime `'a` as defined here
|
||||
| -- ----------------------- opaque type defined here
|
||||
| |
|
||||
| hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:11:27: 11:30]>` captures the lifetime `'a` as defined here
|
||||
LL | self.x.iter().map(|a| a.0)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
|
@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime tha
|
||||
--> $DIR/issue-105227.rs:7:5
|
||||
|
|
||||
LL | fn chars0(v :(& str, &str)) -> impl Iterator<Item = char> {
|
||||
| ----- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
|
||||
| ----- -------------------------- opaque type defined here
|
||||
| |
|
||||
| hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
|
||||
LL |
|
||||
LL | v.0.chars().chain(v.1.chars())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -16,7 +18,9 @@ error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime tha
|
||||
--> $DIR/issue-105227.rs:13:5
|
||||
|
|
||||
LL | fn chars1(v0 : & str, v1 : &str) -> impl Iterator<Item = char> {
|
||||
| ----- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
|
||||
| ----- -------------------------- opaque type defined here
|
||||
| |
|
||||
| hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
|
||||
LL |
|
||||
LL | v0.chars().chain(v1.chars())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -31,7 +35,10 @@ error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime tha
|
||||
|
|
||||
LL | fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) ->
|
||||
| ---- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
|
||||
...
|
||||
LL |
|
||||
LL | (impl Iterator<Item = char>, &'b str)
|
||||
| -------------------------- opaque type defined here
|
||||
LL | {
|
||||
LL | (v0.chars().chain(v1.chars()), v2)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
|
@ -4,6 +4,7 @@ error[E0700]: hidden type for `impl Iterator<Item = u8>` captures lifetime that
|
||||
LL | impl<'a> Foo<'a> {
|
||||
| -- hidden type `Copied<std::slice::Iter<'a, u8>>` captures the lifetime `'a` as defined here
|
||||
LL | fn make_it(&self) -> impl Iterator<Item = u8> {
|
||||
| ------------------------ opaque type defined here
|
||||
LL | self.0.iter().copied()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -24,7 +24,9 @@ error[E0700]: hidden type for `impl Cap<'b> + Cap<'c>` captures lifetime that do
|
||||
--> $DIR/min-choice-reject-ambiguous.rs:39:5
|
||||
|
|
||||
LL | fn test_ambiguous<'a, 'b, 'c>(s: &'a u8) -> impl Cap<'b> + Cap<'c>
|
||||
| -- hidden type `&'a u8` captures the lifetime `'a` as defined here
|
||||
| -- ---------------------- opaque type defined here
|
||||
| |
|
||||
| hidden type `&'a u8` captures the lifetime `'a` as defined here
|
||||
...
|
||||
LL | s
|
||||
| ^
|
||||
|
@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>`
|
||||
--> $DIR/nested-impl-trait-fail.rs:17:5
|
||||
|
|
||||
LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>
|
||||
| -- hidden type `[&'s u8; 1]` captures the lifetime `'s` as defined here
|
||||
| -- ------------------------------------------------ opaque type defined here
|
||||
| |
|
||||
| hidden type `[&'s u8; 1]` captures the lifetime `'s` as defined here
|
||||
...
|
||||
LL | [a]
|
||||
| ^^^
|
||||
@ -20,7 +22,9 @@ error[E0700]: hidden type for `impl Cap<'a> + Cap<'b>` captures lifetime that do
|
||||
--> $DIR/nested-impl-trait-fail.rs:17:5
|
||||
|
|
||||
LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>
|
||||
| -- hidden type `&'s u8` captures the lifetime `'s` as defined here
|
||||
| -- ---------------------- opaque type defined here
|
||||
| |
|
||||
| hidden type `&'s u8` captures the lifetime `'s` as defined here
|
||||
...
|
||||
LL | [a]
|
||||
| ^^^
|
||||
@ -40,6 +44,8 @@ error[E0700]: hidden type for `impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>`
|
||||
LL | fn fail_late_bound<'s, 'a, 'b>(
|
||||
| -- hidden type `[&'s u8; 1]` captures the lifetime `'s` as defined here
|
||||
...
|
||||
LL | ) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> {
|
||||
| ------------------------------------------------ opaque type defined here
|
||||
LL | [a]
|
||||
| ^^^
|
||||
|
|
||||
@ -58,6 +64,8 @@ error[E0700]: hidden type for `impl Cap<'a> + Cap<'b>` captures lifetime that do
|
||||
LL | fn fail_late_bound<'s, 'a, 'b>(
|
||||
| -- hidden type `&'s u8` captures the lifetime `'s` as defined here
|
||||
...
|
||||
LL | ) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> {
|
||||
| ---------------------- opaque type defined here
|
||||
LL | [a]
|
||||
| ^^^
|
||||
|
|
||||
|
@ -2,7 +2,9 @@ error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[1afc]::fo
|
||||
--> $DIR/impl-trait-captures.rs:11:5
|
||||
|
|
||||
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
|
||||
| -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here
|
||||
| -- ------------ opaque type defined here
|
||||
| |
|
||||
| hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here
|
||||
LL | x
|
||||
| ^
|
||||
|
|
||||
|
@ -2,8 +2,9 @@ error[E0700]: hidden type for `impl Clone` captures lifetime that does not appea
|
||||
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48
|
||||
|
|
||||
LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
|
||||
| ----- ^^^^^^^^
|
||||
| |
|
||||
| ----- ---------- ^^^^^^^^
|
||||
| | |
|
||||
| | opaque type defined here
|
||||
| hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
|
||||
|
|
||||
help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound
|
||||
|
@ -2,8 +2,9 @@ error[E0700]: hidden type for `impl Clone` captures lifetime that does not appea
|
||||
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44
|
||||
|
|
||||
LL | fn f(self: Pin<&Self>) -> impl Clone { self }
|
||||
| ----- ^^^^
|
||||
| |
|
||||
| ----- ---------- ^^^^
|
||||
| | |
|
||||
| | opaque type defined here
|
||||
| hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
|
||||
|
|
||||
help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound
|
||||
|
@ -10,7 +10,9 @@ error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not ap
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:19:5
|
||||
|
|
||||
LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
|
||||
| ------ hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 19:12]` captures the anonymous lifetime defined here
|
||||
| ------ ------------- opaque type defined here
|
||||
| |
|
||||
| hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 19:12]` captures the anonymous lifetime defined here
|
||||
...
|
||||
LL | / move || {
|
||||
LL | |
|
||||
|
@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl PlusOne` captures lifetime that does not app
|
||||
--> $DIR/imply_bounds_from_bounds_param.rs:24:5
|
||||
|
|
||||
LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne {
|
||||
| -- hidden type `<&'a mut i32 as Callable>::Output` captures the lifetime `'a` as defined here
|
||||
| -- ------------ opaque type defined here
|
||||
| |
|
||||
| hidden type `<&'a mut i32 as Callable>::Output` captures the lifetime `'a` as defined here
|
||||
LL | <&'a mut i32 as Callable>::call(y)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
|
@ -1,6 +1,8 @@
|
||||
error[E0700]: hidden type for `Opaque<'a, T>` captures lifetime that does not appear in bounds
|
||||
--> $DIR/missing_lifetime_bound.rs:4:47
|
||||
|
|
||||
LL | type Opaque<'a, T> = impl Sized;
|
||||
| ---------- opaque type defined here
|
||||
LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x }
|
||||
| -- ^
|
||||
| |
|
||||
|
Loading…
Reference in New Issue
Block a user