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:
bors 2023-03-03 22:45:58 +00:00
commit 70adb4e5b4
50 changed files with 341 additions and 324 deletions

View File

@ -426,6 +426,7 @@ impl<O: ForestObligation> ObligationForest<O> {
// nodes. Therefore we use a `while` loop. // nodes. Therefore we use a `while` loop.
let mut index = 0; let mut index = 0;
while let Some(node) = self.nodes.get_mut(index) { while let Some(node) = self.nodes.get_mut(index) {
// This test is extremely hot.
if node.state.get() != NodeState::Pending if node.state.get() != NodeState::Pending
|| !processor.needs_process_obligation(&node.obligation) || !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 // out of sync with `nodes`. It's not very common, but it does
// happen, and code in `compress` has to allow for it. // happen, and code in `compress` has to allow for it.
// This code is much less hot.
match processor.process_obligation(&mut node.obligation) { match processor.process_obligation(&mut node.obligation) {
ProcessResult::Unchanged => { ProcessResult::Unchanged => {
// No change in state. // No change in state.

View File

@ -36,7 +36,6 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}
use std::iter; use std::iter;
use std::mem; use std::mem;
use std::slice;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(in super::super) fn check_casts(&mut self) { 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 { let coerce = if blk.targeted_by_break {
CoerceMany::new(coerce_to_ty) CoerceMany::new(coerce_to_ty)
} else { } else {
let tail_expr: &[&hir::Expr<'_>] = match tail_expr { CoerceMany::with_coercion_sites(coerce_to_ty, blk.expr.as_slice())
Some(e) => slice::from_ref(e),
None => &[],
};
CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr)
}; };
let prev_diverges = self.diverges.get(); let prev_diverges = self.diverges.get();

View File

@ -5,6 +5,7 @@
#![feature(min_specialization)] #![feature(min_specialization)]
#![feature(control_flow_enum)] #![feature(control_flow_enum)]
#![feature(drain_filter)] #![feature(drain_filter)]
#![feature(option_as_slice)]
#![allow(rustc::potential_query_instability)] #![allow(rustc::potential_query_instability)]
#![recursion_limit = "256"] #![recursion_limit = "256"]

View File

@ -749,14 +749,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
let opname = Ident::with_dummy_span(opname); let opname = Ident::with_dummy_span(opname);
let input_types = let (opt_rhs_expr, opt_rhs_ty) = opt_rhs.unzip();
opt_rhs.as_ref().map(|(_, ty)| std::slice::from_ref(ty)).unwrap_or_default(); let input_types = opt_rhs_ty.as_slice();
let cause = self.cause( let cause = self.cause(
span, span,
traits::BinOp { traits::BinOp {
rhs_span: opt_rhs.map(|(expr, _)| expr.span), rhs_span: opt_rhs_expr.map(|expr| expr.span),
is_lit: opt_rhs is_lit: opt_rhs_expr
.map_or(false, |(expr, _)| matches!(expr.kind, hir::ExprKind::Lit(_))), .map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
output_ty: expected.only_has_type(self), output_ty: expected.only_has_type(self),
}, },
); );

View File

@ -11,7 +11,6 @@ use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutabili
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::{sym, Ident}; use rustc_span::symbol::{sym, Ident};
use rustc_span::Span; use rustc_span::Span;
use std::slice;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Type-check `*oprnd_expr` with `oprnd_expr` type-checked already. /// 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)) Some(self.typeck_results.borrow().node_substs(expr.hir_id).type_at(1))
} }
}; };
let arg_tys = match arg_ty { let arg_tys = arg_ty.as_slice();
None => &[],
Some(ref ty) => slice::from_ref(ty),
};
let method = self.try_mutable_overloaded_place_op(expr.span, base_ty, arg_tys, op); let method = self.try_mutable_overloaded_place_op(expr.span, base_ty, arg_tys, op);
let method = match method { let method = match method {
Some(ok) => self.register_infer_ok_obligations(ok), Some(ok) => self.register_infer_ok_obligations(ok),

View File

@ -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_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
infer_prlf_must_oultive_without_sup = ...must outlive the lifetime 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_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

View File

@ -1147,3 +1147,13 @@ pub enum PlaceholderRelationLfNotSatisfied {
note: (), 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>,
}

View File

@ -49,6 +49,7 @@ use super::lexical_region_resolve::RegionResolutionError;
use super::region_constraints::GenericKind; use super::region_constraints::GenericKind;
use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs}; use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
use crate::errors;
use crate::infer; use crate::infer;
use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type; use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
use crate::infer::ExpectedFound; use crate::infer::ExpectedFound;
@ -281,15 +282,13 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
span: Span, span: Span,
hidden_ty: Ty<'tcx>, hidden_ty: Ty<'tcx>,
hidden_region: ty::Region<'tcx>, hidden_region: ty::Region<'tcx>,
opaque_ty: ty::OpaqueTypeKey<'tcx>, opaque_ty_key: ty::OpaqueTypeKey<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let opaque_ty = tcx.mk_opaque(opaque_ty.def_id.to_def_id(), opaque_ty.substs); let mut err = tcx.sess.create_err(errors::OpaqueCapturesLifetime {
let mut err = struct_span_err!(
tcx.sess,
span, span,
E0700, opaque_ty: tcx.mk_opaque(opaque_ty_key.def_id.to_def_id(), opaque_ty_key.substs),
"hidden type for `{opaque_ty}` captures lifetime that does not appear in bounds", opaque_ty_span: tcx.def_span(opaque_ty_key.def_id),
); });
// Explain the region we are capturing. // Explain the region we are capturing.
match *hidden_region { match *hidden_region {

View File

@ -212,36 +212,44 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
/// Identifies whether a predicate obligation needs processing. /// Identifies whether a predicate obligation needs processing.
/// ///
/// This is always inlined, despite its size, because it has a single /// This is always inlined because it has a single callsite and it is
/// callsite and it is called *very* frequently. /// called *very* frequently. Be careful modifying this code! Several
/// compile-time benchmarks are very sensitive to even small changes.
#[inline(always)] #[inline(always)]
fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool { fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool {
// If we were stalled on some unresolved variables, first check whether // 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 // any of them have been resolved; if not, don't bother doing more work
// yet. // yet.
match pending_obligation.stalled_on.len() { let stalled_on = &pending_obligation.stalled_on;
// Match arms are in order of frequency, which matters because this match stalled_on.len() {
// code is so hot. 1 and 0 dominate; 2+ is fairly rare. // This case is the hottest most of the time, being hit up to 99%
1 => { // of the time. `keccak` and `cranelift-codegen-0.82.1` are
let infer_var = pending_obligation.stalled_on[0]; // benchmarks that particularly stress this path.
self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) 1 => self.selcx.infcx.ty_or_const_infer_var_changed(stalled_on[0]),
}
0 => { // In this case we haven't changed, but wish to make a change. Note
// In this case we haven't changed, but wish to make a change. // that this is a special case, and is not equivalent to the `_`
true // case below, which would return `false` for an empty `stalled_on`
} // vector.
_ => { //
// This `for` loop was once a call to `all()`, but this lower-level // This case is usually hit only 1% of the time or less, though it
// form was a perf win. See #64545 for details. // reaches 20% in `wasmparser-0.101.0`.
(|| { 0 => true,
for &infer_var in &pending_obligation.stalled_on {
// 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) { if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
return true; return true;
} }
} }
false false
})() })(),
}
} }
} }

View File

@ -2145,7 +2145,7 @@ impl<T, I: iter::TrustedLen<Item = T>> ToRcSlice<T> for I {
Rc::from_iter_exact(self, low) Rc::from_iter_exact(self, low)
} }
} else { } 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`. // length exceeding `usize::MAX`.
// The default implementation would collect into a vec which would panic. // The default implementation would collect into a vec which would panic.
// Thus we panic here immediately without invoking `Vec` code. // Thus we panic here immediately without invoking `Vec` code.

View File

@ -2895,7 +2895,7 @@ impl<T, I: iter::TrustedLen<Item = T>> ToArcSlice<T> for I {
Arc::from_iter_exact(self, low) Arc::from_iter_exact(self, low)
} }
} else { } 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`. // length exceeding `usize::MAX`.
// The default implementation would collect into a vec which would panic. // The default implementation would collect into a vec which would panic.
// Thus we panic here immediately without invoking `Vec` code. // Thus we panic here immediately without invoking `Vec` code.

View File

@ -56,7 +56,7 @@
//! let value_any = value as &dyn Any; //! let value_any = value as &dyn Any;
//! //!
//! // Try to convert our value to a `String`. If successful, we want to //! // 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. //! // different type: just print it out unadorned.
//! match value_any.downcast_ref::<String>() { //! match value_any.downcast_ref::<String>() {
//! Some(as_string) => { //! Some(as_string) => {

View File

@ -632,7 +632,7 @@ pub struct RefCell<T: ?Sized> {
// Stores the location of the earliest currently active borrow. // Stores the location of the earliest currently active borrow.
// This gets updated whenever we go from having zero borrows // This gets updated whenever we go from having zero borrows
// to having a single borrow. When a borrow occurs, this gets included // 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")] #[cfg(feature = "debug_refcell")]
borrowed_at: Cell<Option<&'static crate::panic::Location<'static>>>, borrowed_at: Cell<Option<&'static crate::panic::Location<'static>>>,
value: UnsafeCell<T>, value: UnsafeCell<T>,

View File

@ -42,7 +42,7 @@
//! another function. The `dialect` and `phase` parameters indicate which [version of MIR][dialect //! 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")]` //! 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 = //! 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]: //! [dialect docs]:
//! https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.MirPhase.html //! https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.MirPhase.html

View File

@ -41,7 +41,7 @@ impl Alignment {
/// Returns the alignment for a type. /// Returns the alignment for a type.
/// ///
/// This provides the same numerical value as [`mem::align_of`], /// 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")] #[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline] #[inline]
pub const fn of<T>() -> Self { pub const fn of<T>() -> Self {

View File

@ -2955,7 +2955,7 @@ impl<T> [T] {
// This operation is still `O(n)`. // This operation is still `O(n)`.
// //
// Example: We start in this state, where `r` represents "next // Example: We start in this state, where `r` represents "next
// read" and `w` represents "next_write`. // read" and `w` represents "next_write".
// //
// r // r
// +---+---+---+---+---+---+ // +---+---+---+---+---+---+

View File

@ -317,7 +317,7 @@ where
// 1. `block` - Number of elements in the block. // 1. `block` - Number of elements in the block.
// 2. `start` - Start pointer into the `offsets` array. // 2. `start` - Start pointer into the `offsets` array.
// 3. `end` - End 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)`). // The current block on the left side (from `l` to `l.add(block_l)`).
let mut l = v.as_mut_ptr(); let mut l = v.as_mut_ptr();
@ -327,7 +327,7 @@ where
let mut offsets_l = [MaybeUninit::<u8>::uninit(); BLOCK]; let mut offsets_l = [MaybeUninit::<u8>::uninit(); BLOCK];
// The current block on the right side (from `r.sub(block_r)` to `r`). // 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 r = unsafe { l.add(v.len()) };
let mut block_r = BLOCK; let mut block_r = BLOCK;
let mut start_r = ptr::null_mut(); let mut start_r = ptr::null_mut();

View File

@ -305,6 +305,50 @@ impl AtomicBool {
AtomicBool { v: UnsafeCell::new(v as u8) } 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`]. /// Returns a mutable reference to the underlying [`bool`].
/// ///
/// This is safe because the mutable reference guarantees that no other threads are /// 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) } 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. /// Returns a mutable reference to the underlying pointer.
/// ///
/// This is safe because the mutable reference guarantees that no other threads are /// 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)} 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. /// Returns a mutable reference to the underlying integer.
/// ///
/// This is safe because the mutable reference guarantees that no other threads are /// This is safe because the mutable reference guarantees that no other threads are

View File

@ -24,7 +24,7 @@ mod zip;
use core::cell::Cell; 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 /// after `None` has already been returned. This does not violate
/// `Iterator`'s contract. Used to test that iterator adapters don't /// `Iterator`'s contract. Used to test that iterator adapters don't
/// poll their inner iterators after exhausting them. /// poll their inner iterators after exhausting them.

View File

@ -28,7 +28,7 @@ use crate::simd::{
/// let zm_add = a0.zip(a1).map(|(lhs, rhs)| lhs + rhs); /// let zm_add = a0.zip(a1).map(|(lhs, rhs)| lhs + rhs);
/// let zm_mul = 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)); /// let (v0, v1) = (Simd::from(a0), Simd::from(a1));
/// // Which means arrays implement `Into<Simd<T, N>>`. /// // Which means arrays implement `Into<Simd<T, N>>`.
/// assert_eq!(v0 + v1, zm_add.into()); /// assert_eq!(v0 + v1, zm_add.into());

View File

@ -1416,7 +1416,7 @@ impl From<fs::File> for Stdio {
/// use std::fs::File; /// use std::fs::File;
/// use std::process::Command; /// 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 file = File::open("foo.txt").unwrap();
/// ///
/// let reverse = Command::new("rev") /// let reverse = Command::new("rev")

View File

@ -247,7 +247,7 @@ impl Thread {
// [FINISHED → JOINED] // [FINISHED → JOINED]
// To synchronize with the child task's memory accesses to // To synchronize with the child task's memory accesses to
// `inner` up to the point of the assignment of `FINISHED`, // `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() }, _ => unsafe { hint::unreachable_unchecked() },
} }

View File

@ -329,7 +329,7 @@ pub fn cvt_nz(error: libc::c_int) -> crate::io::Result<()> {
// do so. In 1003.1-2004 this was fixed. // do so. In 1003.1-2004 this was fixed.
// //
// glibc's implementation did the flush, unsafely, before glibc commit // 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: // Weimer. According to glibc's NEWS:
// //
// The abort function terminates the process immediately, without flushing // The abort function terminates the process immediately, without flushing

View File

@ -6,7 +6,7 @@ fn no_lookup_host_duplicates() {
let mut addrs = HashMap::new(); let mut addrs = HashMap::new();
let lh = match LookupHost::try_from(("localhost", 0)) { let lh = match LookupHost::try_from(("localhost", 0)) {
Ok(lh) => lh, Ok(lh) => lh,
Err(e) => panic!("couldn't resolve `localhost': {e}"), Err(e) => panic!("couldn't resolve `localhost`: {e}"),
}; };
for sa in lh { for sa in lh {
*addrs.entry(sa).or_insert(0) += 1; *addrs.entry(sa).or_insert(0) += 1;

View File

@ -594,7 +594,7 @@ impl Wtf8 {
} }
/// Returns the code point at `position` if it is in the ASCII range, /// Returns the code point at `position` if it is in the ASCII range,
/// or `b'\xFF' otherwise. /// or `b'\xFF'` otherwise.
/// ///
/// # Panics /// # Panics
/// ///

View File

@ -204,7 +204,7 @@ fn make_owned_test(test: &&TestDescAndFn) -> TestDescAndFn {
} }
/// Invoked when unit tests terminate. Returns `Result::Err` if the test is /// 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. /// result.
pub fn assert_test_result<T: Termination>(result: T) -> Result<(), String> { pub fn assert_test_result<T: Termination>(result: T) -> Result<(), String> {
let code = result.report().to_i32(); let code = result.report().to_i32();

View File

@ -89,7 +89,7 @@ pub type _Unwind_Exception_Cleanup_Fn =
// FIXME: The `#[link]` attributes on `extern "C"` block marks those symbols declared in // 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 // 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, // 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]`. // 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 // See the logic in function rustc_codegen_ssa::src::back::exported_symbols, module

View File

@ -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

View File

@ -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 Targets are identified by their "target triple" which is the string to inform
the compiler what kind of output should be produced. 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 with Host Tools
Tier 1 targets can be thought of as "guaranteed to work". The Rust project Tier 1 targets can be thought of as "guaranteed to work". The Rust project

View File

@ -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.

View File

@ -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 --> $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> { 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 | | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here
LL | | LL | |
LL | | (a, b) LL | | (a, b)

View File

@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not a
--> $DIR/hidden-lifetimes.rs:29:5 --> $DIR/hidden-lifetimes.rs:29:5
| |
LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { 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 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 --> $DIR/hidden-lifetimes.rs:46:5
| |
LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a { 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 LL | x
| ^ | ^
| |

View File

@ -1,6 +1,8 @@
error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds
--> $DIR/impl-fn-hrtb-bounds-2.rs:5:9 --> $DIR/impl-fn-hrtb-bounds-2.rs:5:9
| |
LL | fn a() -> impl Fn(&u8) -> impl Debug {
| ---------- opaque type defined here
LL | |x| x LL | |x| x
| --- ^ | --- ^
| | | |

View File

@ -1,6 +1,9 @@
error[E0700]: hidden type for `E<'b, 'c>` captures lifetime that does not appear in bounds error[E0700]: hidden type for `E<'b, 'c>` captures lifetime that does not appear in bounds
--> $DIR/error-handling-2.rs:22:5 --> $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> { 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 | -- hidden type `*mut &'a i32` captures the lifetime `'a` as defined here
... ...

View File

@ -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 --> $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> 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 } LL | if condition() { a } else { b }
| ^ | ^

View File

@ -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 --> $DIR/ordinary-bounds-unsuited.rs:31:33
| |
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> 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 } LL | if condition() { a } else { b }
| ^ | ^

View File

@ -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 --> $DIR/must_outlive_least_region_or_bound.rs:3:35
| |
LL | fn elided(x: &i32) -> impl Copy { x } LL | fn elided(x: &i32) -> impl Copy { x }
| ---- ^ | ---- --------- ^
| | | | |
| | opaque type defined here
| hidden type `&i32` captures the anonymous lifetime 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 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 --> $DIR/must_outlive_least_region_or_bound.rs:6:44
| |
LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } 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 | 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 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 --> $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) { 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) LL | move |_| println!("{}", y)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
| |

View File

@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Future<Output = impl Sized>` captures lifeti
--> $DIR/nested-return-type4.rs:4:5 --> $DIR/nested-return-type4.rs:4:5
| |
LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> { 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; } LL | async move { let _s = s; }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
| |

View File

@ -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 --> $DIR/region-escape-via-bound.rs:17:5
| |
LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> 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 LL | x
| ^ | ^

View File

@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that
--> $DIR/static-return-lifetime-infered.rs:7:9 --> $DIR/static-return-lifetime-infered.rs:7:9
| |
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> { 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) 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 --> $DIR/static-return-lifetime-infered.rs:11:9
| |
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> { 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) LL | self.x.iter().map(|a| a.0)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
| |

View File

@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime tha
--> $DIR/issue-105227.rs:7:5 --> $DIR/issue-105227.rs:7:5
| |
LL | fn chars0(v :(& str, &str)) -> impl Iterator<Item = char> { 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 |
LL | v.0.chars().chain(v.1.chars()) 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 --> $DIR/issue-105227.rs:13:5
| |
LL | fn chars1(v0 : & str, v1 : &str) -> impl Iterator<Item = char> { 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 |
LL | v0.chars().chain(v1.chars()) 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) -> LL | fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) ->
| ---- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here | ---- 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) LL | (v0.chars().chain(v1.chars()), v2)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |

View File

@ -4,6 +4,7 @@ error[E0700]: hidden type for `impl Iterator<Item = u8>` captures lifetime that
LL | impl<'a> Foo<'a> { LL | impl<'a> Foo<'a> {
| -- hidden type `Copied<std::slice::Iter<'a, u8>>` captures the lifetime `'a` as defined here | -- hidden type `Copied<std::slice::Iter<'a, u8>>` captures the lifetime `'a` as defined here
LL | fn make_it(&self) -> impl Iterator<Item = u8> { LL | fn make_it(&self) -> impl Iterator<Item = u8> {
| ------------------------ opaque type defined here
LL | self.0.iter().copied() LL | self.0.iter().copied()
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^

View File

@ -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 --> $DIR/min-choice-reject-ambiguous.rs:39:5
| |
LL | fn test_ambiguous<'a, 'b, 'c>(s: &'a u8) -> impl Cap<'b> + Cap<'c> 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 LL | s
| ^ | ^

View File

@ -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 --> $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>> 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] 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 --> $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>> 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] 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>( LL | fn fail_late_bound<'s, 'a, 'b>(
| -- hidden type `[&'s u8; 1]` captures the lifetime `'s` as defined here | -- 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] 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>( LL | fn fail_late_bound<'s, 'a, 'b>(
| -- hidden type `&'s u8` captures the lifetime `'s` as defined here | -- 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] LL | [a]
| ^^^ | ^^^
| |

View File

@ -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 --> $DIR/impl-trait-captures.rs:11:5
| |
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { 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 LL | x
| ^ | ^
| |

View File

@ -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 --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48
| |
LL | async fn f(self: Pin<&Self>) -> impl Clone { self } LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
| ----- ^^^^^^^^ | ----- ---------- ^^^^^^^^
| | | | |
| | opaque type defined here
| hidden type `Pin<&Foo>` captures the anonymous lifetime 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 help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound

View File

@ -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 --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44
| |
LL | fn f(self: Pin<&Self>) -> impl Clone { self } LL | fn f(self: Pin<&Self>) -> impl Clone { self }
| ----- ^^^^ | ----- ---------- ^^^^
| | | | |
| | opaque type defined here
| hidden type `Pin<&Foo>` captures the anonymous lifetime 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 help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound

View File

@ -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 --> $DIR/missing-lifetimes-in-signature.rs:19:5
| |
LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() 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 | / move || {
LL | | LL | |

View File

@ -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 --> $DIR/imply_bounds_from_bounds_param.rs:24:5
| |
LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne { 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) LL | <&'a mut i32 as Callable>::call(y)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |

View File

@ -1,6 +1,8 @@
error[E0700]: hidden type for `Opaque<'a, T>` captures lifetime that does not appear in bounds error[E0700]: hidden type for `Opaque<'a, T>` captures lifetime that does not appear in bounds
--> $DIR/missing_lifetime_bound.rs:4:47 --> $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 } LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x }
| -- ^ | -- ^
| | | |