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

View File

@ -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();

View File

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

View File

@ -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),
},
);

View File

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

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

View File

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

View File

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

View File

@ -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
})(),
}
}

View File

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

View File

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

View File

@ -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) => {

View File

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

View File

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

View File

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

View File

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

View File

@ -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();

View File

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

View File

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

View File

@ -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());

View File

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

View File

@ -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() },
}

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

View File

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

View File

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

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
/// 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();

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

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

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

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

View File

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

View File

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

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
|
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 }
| ^

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
|
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 }
| ^

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
|
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)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|

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
|
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; }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|

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

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
|
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)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|

View File

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

View File

@ -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()
| ^^^^^^^^^^^^^^^^^^^^^^

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

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
|
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]
| ^^^
|

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

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

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

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

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
|
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)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|

View File

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