1
Fork 0

Auto merge of #137010 - workingjubilee:rollup-g00c07v, r=workingjubilee

Rollup of 9 pull requests

Successful merges:

 - #135439 (Make `-O` mean `OptLevel::Aggressive`)
 - #136460 (Simplify `rustc_span` `analyze_source_file`)
 - #136904 (add `IntoBounds` trait)
 - #136908 ([AIX] expect `EINVAL` for `pthread_mutex_destroy`)
 - #136924 (Add profiling of bootstrap commands using Chrome events)
 - #136951 (Use the right binder for rebinding `PolyTraitRef`)
 - #136981 (ci: switch loongarch jobs to free runners)
 - #136992 (Update backtrace)
 - #136993 ([cg_llvm] Remove dead error message)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-02-14 06:13:42 +00:00
commit 905b1bf1cc
33 changed files with 307 additions and 179 deletions

View file

@ -289,7 +289,7 @@ fn build_isa(sess: &Session) -> Arc<dyn TargetIsa + 'static> {
flags_builder.set("opt_level", "none").unwrap();
}
OptLevel::Less
| OptLevel::Default
| OptLevel::More
| OptLevel::Size
| OptLevel::SizeMin
| OptLevel::Aggressive => {

View file

@ -476,7 +476,7 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
Some(level) => match level {
OptLevel::No => OptimizationLevel::None,
OptLevel::Less => OptimizationLevel::Limited,
OptLevel::Default => OptimizationLevel::Standard,
OptLevel::More => OptimizationLevel::Standard,
OptLevel::Aggressive => OptimizationLevel::Aggressive,
OptLevel::Size | OptLevel::SizeMin => OptimizationLevel::Limited,
},

View file

@ -38,9 +38,6 @@ codegen_llvm_lto_proc_macro = lto cannot be used for `proc-macro` crate type wit
codegen_llvm_mismatch_data_layout =
data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}`
codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found
codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err}
codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module
codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err}

View file

@ -141,7 +141,7 @@ fn to_llvm_opt_settings(cfg: config::OptLevel) -> (llvm::CodeGenOptLevel, llvm::
match cfg {
No => (llvm::CodeGenOptLevel::None, llvm::CodeGenOptSizeNone),
Less => (llvm::CodeGenOptLevel::Less, llvm::CodeGenOptSizeNone),
Default => (llvm::CodeGenOptLevel::Default, llvm::CodeGenOptSizeNone),
More => (llvm::CodeGenOptLevel::Default, llvm::CodeGenOptSizeNone),
Aggressive => (llvm::CodeGenOptLevel::Aggressive, llvm::CodeGenOptSizeNone),
Size => (llvm::CodeGenOptLevel::Default, llvm::CodeGenOptSizeDefault),
SizeMin => (llvm::CodeGenOptLevel::Default, llvm::CodeGenOptSizeAggressive),
@ -153,7 +153,7 @@ fn to_pass_builder_opt_level(cfg: config::OptLevel) -> llvm::PassBuilderOptLevel
match cfg {
No => llvm::PassBuilderOptLevel::O0,
Less => llvm::PassBuilderOptLevel::O1,
Default => llvm::PassBuilderOptLevel::O2,
More => llvm::PassBuilderOptLevel::O2,
Aggressive => llvm::PassBuilderOptLevel::O3,
Size => llvm::PassBuilderOptLevel::Os,
SizeMin => llvm::PassBuilderOptLevel::Oz,

View file

@ -131,8 +131,6 @@ pub enum LlvmError<'a> {
LoadBitcode { name: CString },
#[diag(codegen_llvm_write_thinlto_key)]
WriteThinLtoKey { err: std::io::Error },
#[diag(codegen_llvm_multiple_source_dicompileunit)]
MultipleSourceDiCompileUnit,
#[diag(codegen_llvm_prepare_thin_lto_module)]
PrepareThinLtoModule,
#[diag(codegen_llvm_parse_bitcode)]
@ -155,9 +153,6 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for WithLlvmError<'_> {
PrepareThinLtoContext => fluent::codegen_llvm_prepare_thin_lto_context_with_llvm_err,
LoadBitcode { .. } => fluent::codegen_llvm_load_bitcode_with_llvm_err,
WriteThinLtoKey { .. } => fluent::codegen_llvm_write_thinlto_key_with_llvm_err,
MultipleSourceDiCompileUnit => {
fluent::codegen_llvm_multiple_source_dicompileunit_with_llvm_err
}
PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err,
ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err,
PrepareAutoDiff { .. } => fluent::codegen_llvm_prepare_autodiff_with_llvm_err,

View file

@ -410,7 +410,7 @@ impl<'a> GccLinker<'a> {
let opt_level = match self.sess.opts.optimize {
config::OptLevel::No => "O0",
config::OptLevel::Less => "O1",
config::OptLevel::Default | config::OptLevel::Size | config::OptLevel::SizeMin => "O2",
config::OptLevel::More | config::OptLevel::Size | config::OptLevel::SizeMin => "O2",
config::OptLevel::Aggressive => "O3",
};
@ -685,7 +685,7 @@ impl<'a> Linker for GccLinker<'a> {
// GNU-style linkers support optimization with -O. GNU ld doesn't
// need a numeric argument, but other linkers do.
if self.sess.opts.optimize == config::OptLevel::Default
if self.sess.opts.optimize == config::OptLevel::More
|| self.sess.opts.optimize == config::OptLevel::Aggressive
{
self.link_arg("-O1");
@ -1213,7 +1213,7 @@ impl<'a> Linker for EmLinker<'a> {
self.cc_arg(match self.sess.opts.optimize {
OptLevel::No => "-O0",
OptLevel::Less => "-O1",
OptLevel::Default => "-O2",
OptLevel::More => "-O2",
OptLevel::Aggressive => "-O3",
OptLevel::Size => "-Os",
OptLevel::SizeMin => "-Oz",
@ -1384,7 +1384,7 @@ impl<'a> Linker for WasmLd<'a> {
self.link_arg(match self.sess.opts.optimize {
OptLevel::No => "-O0",
OptLevel::Less => "-O1",
OptLevel::Default => "-O2",
OptLevel::More => "-O2",
OptLevel::Aggressive => "-O3",
// Currently LLD doesn't support `Os` and `Oz`, so pass through `O2`
// instead.
@ -1451,7 +1451,7 @@ impl<'a> WasmLd<'a> {
let opt_level = match self.sess.opts.optimize {
config::OptLevel::No => "O0",
config::OptLevel::Less => "O1",
config::OptLevel::Default => "O2",
config::OptLevel::More => "O2",
config::OptLevel::Aggressive => "O3",
// wasm-ld only handles integer LTO opt levels. Use O2
config::OptLevel::Size | config::OptLevel::SizeMin => "O2",
@ -1525,7 +1525,7 @@ impl<'a> Linker for L4Bender<'a> {
fn optimize(&mut self) {
// GNU-style linkers support optimization with -O. GNU ld doesn't
// need a numeric argument, but other linkers do.
if self.sess.opts.optimize == config::OptLevel::Default
if self.sess.opts.optimize == config::OptLevel::More
|| self.sess.opts.optimize == config::OptLevel::Aggressive
{
self.link_arg("-O1");
@ -1929,7 +1929,7 @@ impl<'a> Linker for LlbcLinker<'a> {
match self.sess.opts.optimize {
OptLevel::No => "-O0",
OptLevel::Less => "-O1",
OptLevel::Default => "-O2",
OptLevel::More => "-O2",
OptLevel::Aggressive => "-O3",
OptLevel::Size => "-Os",
OptLevel::SizeMin => "-Oz",
@ -2006,7 +2006,7 @@ impl<'a> Linker for BpfLinker<'a> {
self.link_arg(match self.sess.opts.optimize {
OptLevel::No => "-O0",
OptLevel::Less => "-O1",
OptLevel::Default => "-O2",
OptLevel::More => "-O2",
OptLevel::Aggressive => "-O3",
OptLevel::Size => "-Os",
OptLevel::SizeMin => "-Oz",

View file

@ -236,7 +236,7 @@ impl ModuleConfig {
// Copy what clang does by turning on loop vectorization at O2 and
// slp vectorization at O3.
vectorize_loop: !sess.opts.cg.no_vectorize_loops
&& (sess.opts.optimize == config::OptLevel::Default
&& (sess.opts.optimize == config::OptLevel::More
|| sess.opts.optimize == config::OptLevel::Aggressive),
vectorize_slp: !sess.opts.cg.no_vectorize_slp
&& sess.opts.optimize == config::OptLevel::Aggressive,
@ -260,7 +260,7 @@ impl ModuleConfig {
MergeFunctions::Trampolines | MergeFunctions::Aliases => {
use config::OptLevel::*;
match sess.opts.optimize {
Aggressive | Default | SizeMin | Size => true,
Aggressive | More | SizeMin | Size => true,
Less | No => false,
}
}

View file

@ -1054,12 +1054,12 @@ pub(crate) fn provide(providers: &mut Providers) {
config::OptLevel::No => return config::OptLevel::No,
// If globally optimise-speed is already specified, just use that level.
config::OptLevel::Less => return config::OptLevel::Less,
config::OptLevel::Default => return config::OptLevel::Default,
config::OptLevel::More => return config::OptLevel::More,
config::OptLevel::Aggressive => return config::OptLevel::Aggressive,
// If globally optimize-for-size has been requested, use -O2 instead (if optimize(size)
// are present).
config::OptLevel::Size => config::OptLevel::Default,
config::OptLevel::SizeMin => config::OptLevel::Default,
config::OptLevel::Size => config::OptLevel::More,
config::OptLevel::SizeMin => config::OptLevel::More,
};
let defids = tcx.collect_and_partition_mono_items(cratenum).all_mono_items;

View file

@ -49,8 +49,7 @@ impl<'tcx> crate::MirPass<'tcx> for Inline {
match sess.mir_opt_level() {
0 | 1 => false,
2 => {
(sess.opts.optimize == OptLevel::Default
|| sess.opts.optimize == OptLevel::Aggressive)
(sess.opts.optimize == OptLevel::More || sess.opts.optimize == OptLevel::Aggressive)
&& sess.opts.incremental == None
}
_ => true,

View file

@ -86,12 +86,18 @@ pub enum CFProtection {
#[derive(Clone, Copy, Debug, PartialEq, Hash, HashStable_Generic)]
pub enum OptLevel {
No, // -O0
Less, // -O1
Default, // -O2
Aggressive, // -O3
Size, // -Os
SizeMin, // -Oz
/// `-Copt-level=0`
No,
/// `-Copt-level=1`
Less,
/// `-Copt-level=2`
More,
/// `-Copt-level=3` / `-O`
Aggressive,
/// `-Copt-level=s`
Size,
/// `-Copt-level=z`
SizeMin,
}
/// This is what the `LtoCli` values get mapped to after resolving defaults and
@ -1253,7 +1259,7 @@ impl Options {
Some(setting) => setting,
None => match self.optimize {
OptLevel::No | OptLevel::Less | OptLevel::Size | OptLevel::SizeMin => true,
OptLevel::Default | OptLevel::Aggressive => false,
OptLevel::More | OptLevel::Aggressive => false,
},
}
}
@ -1572,7 +1578,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
stack-protector-strategies|link-args|deployment-target]",
),
opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""),
opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=2", ""),
opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=3", ""),
opt(Stable, Opt, "o", "", "Write output to <filename>", "FILENAME"),
opt(Stable, Opt, "", "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
opt(
@ -2127,12 +2133,12 @@ fn parse_opt_level(
})
.max();
if max_o > max_c {
OptLevel::Default
OptLevel::Aggressive
} else {
match cg.opt_level.as_ref() {
"0" => OptLevel::No,
"1" => OptLevel::Less,
"2" => OptLevel::Default,
"2" => OptLevel::More,
"3" => OptLevel::Aggressive,
"s" => OptLevel::Size,
"z" => OptLevel::SizeMin,

View file

@ -95,57 +95,23 @@ cfg_match! {
if multibyte_mask == 0 {
assert!(intra_chunk_offset == 0);
// Check if there are any control characters in the chunk. All
// control characters that we can encounter at this point have a
// byte value less than 32 or ...
let control_char_test0 = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(32)) };
let control_char_mask0 = unsafe { _mm_movemask_epi8(control_char_test0) };
// ... it's the ASCII 'DEL' character with a value of 127.
let control_char_test1 = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(127)) };
let control_char_mask1 = unsafe { _mm_movemask_epi8(control_char_test1) };
let control_char_mask = control_char_mask0 | control_char_mask1;
if control_char_mask != 0 {
// Check for newlines in the chunk
let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) };
let newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) };
let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) };
if control_char_mask == newlines_mask {
// All control characters are newlines, record them
let mut newlines_mask = 0xFFFF0000 | newlines_mask as u32;
let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1);
loop {
while newlines_mask != 0 {
let index = newlines_mask.trailing_zeros();
if index >= CHUNK_SIZE as u32 {
// We have arrived at the end of the chunk.
break;
}
lines.push(RelativeBytePos(index) + output_offset);
// Clear the bit, so we can find the next one.
newlines_mask &= (!1) << index;
}
// We are done for this chunk. All control characters were
// newlines and we took care of those.
continue;
} else {
// Some of the control characters are not newlines,
// fall through to the slow path below.
newlines_mask &= newlines_mask - 1;
}
} else {
// No control characters, nothing to record for this chunk
continue;
}
}
// The slow path.
// There are control chars in here, fallback to generic decoding.
// There are multibyte chars in here, fallback to generic decoding.
let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset;
intra_chunk_offset = analyze_source_file_generic(
&src[scan_start..],
@ -155,6 +121,7 @@ cfg_match! {
multi_byte_chars,
);
}
}
// There might still be a tail left to analyze
let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset;
@ -253,57 +220,23 @@ cfg_match! {
if multibyte_mask == 0 {
assert!(intra_chunk_offset == 0);
// Check if there are any control characters in the chunk. All
// control characters that we can encounter at this point have a
// byte value less than 32 or ...
let control_char_test0 = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(32)) };
let control_char_mask0 = unsafe { _mm_movemask_epi8(control_char_test0) };
// ... it's the ASCII 'DEL' character with a value of 127.
let control_char_test1 = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(127)) };
let control_char_mask1 = unsafe { _mm_movemask_epi8(control_char_test1) };
let control_char_mask = control_char_mask0 | control_char_mask1;
if control_char_mask != 0 {
// Check for newlines in the chunk
let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) };
let newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) };
let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) };
if control_char_mask == newlines_mask {
// All control characters are newlines, record them
let mut newlines_mask = 0xFFFF0000 | newlines_mask as u32;
let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1);
loop {
while newlines_mask != 0 {
let index = newlines_mask.trailing_zeros();
if index >= CHUNK_SIZE as u32 {
// We have arrived at the end of the chunk.
break;
}
lines.push(RelativeBytePos(index) + output_offset);
// Clear the bit, so we can find the next one.
newlines_mask &= (!1) << index;
}
// We are done for this chunk. All control characters were
// newlines and we took care of those.
continue;
} else {
// Some of the control characters are not newlines,
// fall through to the slow path below.
newlines_mask &= newlines_mask - 1;
}
} else {
// No control characters, nothing to record for this chunk
continue;
}
}
// The slow path.
// There are control chars in here, fallback to generic decoding.
// There are multibyte chars in here, fallback to generic decoding.
let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset;
intra_chunk_offset = analyze_source_file_generic(
&src[scan_start..],
@ -313,6 +246,7 @@ cfg_match! {
multi_byte_chars,
);
}
}
// There might still be a tail left to analyze
let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset;
@ -369,30 +303,19 @@ fn analyze_source_file_generic(
// string.
let mut char_len = 1;
if byte < 32 {
// This is an ASCII control character, it could be one of the cases
// that are interesting to us.
if byte == b'\n' {
let pos = RelativeBytePos::from_usize(i) + output_offset;
if let b'\n' = byte {
lines.push(pos + RelativeBytePos(1));
}
} else if byte >= 127 {
// The slow path:
// This is either ASCII control character "DEL" or the beginning of
// a multibyte char. Just decode to `char`.
} else if byte >= 128 {
// This is the beginning of a multibyte char. Just decode to `char`.
let c = src[i..].chars().next().unwrap();
char_len = c.len_utf8();
let pos = RelativeBytePos::from_usize(i) + output_offset;
if char_len > 1 {
assert!((2..=4).contains(&char_len));
let mbc = MultiByteChar { pos, bytes: char_len as u8 };
multi_byte_chars.push(mbc);
}
}
i += char_len;
}

View file

@ -47,11 +47,11 @@ pub fn expand_trait_aliases<'tcx>(
queue.extend(
tcx.explicit_super_predicates_of(trait_pred.def_id())
.iter_identity_copied()
.map(|(clause, span)| {
.map(|(super_clause, span)| {
let mut spans = spans.clone();
spans.push(span);
(
clause.instantiate_supertrait(
super_clause.instantiate_supertrait(
tcx,
clause.kind().rebind(trait_pred.trait_ref),
),

@ -1 +1 @@
Subproject commit f8cc6ac9acc4e663ecd96f9bcf1ff4542636d1b9
Subproject commit 9d2c34e7e63afe1e71c333b247065e3b7ba4d883

View file

@ -182,6 +182,8 @@ pub use self::function::{Fn, FnMut, FnOnce};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::index::{Index, IndexMut};
pub(crate) use self::index_range::IndexRange;
#[unstable(feature = "range_into_bounds", issue = "136903")]
pub use self::range::IntoBounds;
#[stable(feature = "inclusive_range", since = "1.26.0")]
pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
#[unstable(feature = "one_sided_range", issue = "69780")]

View file

@ -831,6 +831,30 @@ pub trait RangeBounds<T: ?Sized> {
}
}
/// Used to convert a range into start and end bounds, consuming the
/// range by value.
///
/// `IntoBounds` is implemented by Rusts built-in range types, produced
/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
#[unstable(feature = "range_into_bounds", issue = "136903")]
pub trait IntoBounds<T>: RangeBounds<T> {
/// Convert this range into the start and end bounds.
/// Returns `(start_bound, end_bound)`.
///
/// # Examples
///
/// ```
/// #![feature(range_into_bounds)]
///
/// use std::ops::Bound::*;
/// use std::ops::IntoBounds;
///
/// assert_eq!((0..5).into_bounds(), (Included(0), Excluded(5)));
/// assert_eq!((..=7).into_bounds(), (Unbounded, Included(7)));
/// ```
fn into_bounds(self) -> (Bound<T>, Bound<T>);
}
use self::Bound::{Excluded, Included, Unbounded};
#[stable(feature = "collections_range", since = "1.28.0")]
@ -843,6 +867,13 @@ impl<T: ?Sized> RangeBounds<T> for RangeFull {
}
}
#[unstable(feature = "range_into_bounds", issue = "136903")]
impl<T> IntoBounds<T> for RangeFull {
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
(Unbounded, Unbounded)
}
}
#[stable(feature = "collections_range", since = "1.28.0")]
impl<T> RangeBounds<T> for RangeFrom<T> {
fn start_bound(&self) -> Bound<&T> {
@ -853,6 +884,13 @@ impl<T> RangeBounds<T> for RangeFrom<T> {
}
}
#[unstable(feature = "range_into_bounds", issue = "136903")]
impl<T> IntoBounds<T> for RangeFrom<T> {
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
(Included(self.start), Unbounded)
}
}
#[stable(feature = "collections_range", since = "1.28.0")]
impl<T> RangeBounds<T> for RangeTo<T> {
fn start_bound(&self) -> Bound<&T> {
@ -863,6 +901,13 @@ impl<T> RangeBounds<T> for RangeTo<T> {
}
}
#[unstable(feature = "range_into_bounds", issue = "136903")]
impl<T> IntoBounds<T> for RangeTo<T> {
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
(Unbounded, Excluded(self.end))
}
}
#[stable(feature = "collections_range", since = "1.28.0")]
impl<T> RangeBounds<T> for Range<T> {
fn start_bound(&self) -> Bound<&T> {
@ -873,6 +918,13 @@ impl<T> RangeBounds<T> for Range<T> {
}
}
#[unstable(feature = "range_into_bounds", issue = "136903")]
impl<T> IntoBounds<T> for Range<T> {
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
(Included(self.start), Excluded(self.end))
}
}
#[stable(feature = "collections_range", since = "1.28.0")]
impl<T> RangeBounds<T> for RangeInclusive<T> {
fn start_bound(&self) -> Bound<&T> {
@ -889,6 +941,22 @@ impl<T> RangeBounds<T> for RangeInclusive<T> {
}
}
#[unstable(feature = "range_into_bounds", issue = "136903")]
impl<T> IntoBounds<T> for RangeInclusive<T> {
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
(
Included(self.start),
if self.exhausted {
// When the iterator is exhausted, we usually have start == end,
// but we want the range to appear empty, containing nothing.
Excluded(self.end)
} else {
Included(self.end)
},
)
}
}
#[stable(feature = "collections_range", since = "1.28.0")]
impl<T> RangeBounds<T> for RangeToInclusive<T> {
fn start_bound(&self) -> Bound<&T> {
@ -899,6 +967,13 @@ impl<T> RangeBounds<T> for RangeToInclusive<T> {
}
}
#[unstable(feature = "range_into_bounds", issue = "136903")]
impl<T> IntoBounds<T> for RangeToInclusive<T> {
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
(Unbounded, Included(self.end))
}
}
#[stable(feature = "collections_range", since = "1.28.0")]
impl<T> RangeBounds<T> for (Bound<T>, Bound<T>) {
fn start_bound(&self) -> Bound<&T> {
@ -918,6 +993,13 @@ impl<T> RangeBounds<T> for (Bound<T>, Bound<T>) {
}
}
#[unstable(feature = "range_into_bounds", issue = "136903")]
impl<T> IntoBounds<T> for (Bound<T>, Bound<T>) {
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
self
}
}
#[stable(feature = "collections_range", since = "1.28.0")]
impl<'a, T: ?Sized + 'a> RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) {
fn start_bound(&self) -> Bound<&T> {

View file

@ -31,7 +31,9 @@ pub use iter::{IterRange, IterRangeFrom, IterRangeInclusive};
#[doc(inline)]
pub use crate::iter::Step;
#[doc(inline)]
pub use crate::ops::{Bound, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive};
pub use crate::ops::{
Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive,
};
/// A (half-open) range bounded inclusively below and exclusively above
/// (`start..end` in a future edition).
@ -175,6 +177,14 @@ impl<T> RangeBounds<T> for Range<&T> {
}
}
// #[unstable(feature = "range_into_bounds", issue = "136903")]
#[unstable(feature = "new_range_api", issue = "125687")]
impl<T> IntoBounds<T> for Range<T> {
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
(Included(self.start), Excluded(self.end))
}
}
#[unstable(feature = "new_range_api", issue = "125687")]
impl<T> From<Range<T>> for legacy::Range<T> {
#[inline]
@ -343,6 +353,14 @@ impl<T> RangeBounds<T> for RangeInclusive<&T> {
}
}
// #[unstable(feature = "range_into_bounds", issue = "136903")]
#[unstable(feature = "new_range_api", issue = "125687")]
impl<T> IntoBounds<T> for RangeInclusive<T> {
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
(Included(self.start), Included(self.end))
}
}
#[unstable(feature = "new_range_api", issue = "125687")]
impl<T> From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
#[inline]
@ -479,6 +497,14 @@ impl<T> RangeBounds<T> for RangeFrom<&T> {
}
}
// #[unstable(feature = "range_into_bounds", issue = "136903")]
#[unstable(feature = "new_range_api", issue = "125687")]
impl<T> IntoBounds<T> for RangeFrom<T> {
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
(Included(self.start), Unbounded)
}
}
#[unstable(feature = "new_range_api", issue = "125687")]
impl<T> From<RangeFrom<T>> for legacy::RangeFrom<T> {
#[inline]

View file

@ -111,9 +111,9 @@ impl Drop for Mutex {
// `PTHREAD_MUTEX_INITIALIZER`, which is valid at all locations. Thus,
// this call always destroys a valid mutex.
let r = unsafe { libc::pthread_mutex_destroy(self.raw()) };
if cfg!(target_os = "dragonfly") {
// On DragonFly pthread_mutex_destroy() returns EINVAL if called on a
// mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER.
if cfg!(any(target_os = "aix", target_os = "dragonfly")) {
// On AIX and DragonFly pthread_mutex_destroy() returns EINVAL if called
// on a mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER.
// Once it is used (locked/unlocked) or pthread_mutex_init() is called,
// this behaviour no longer occurs.
debug_assert!(r == 0 || r == libc::EINVAL);

View file

@ -59,6 +59,7 @@ dependencies = [
"termcolor",
"toml",
"tracing",
"tracing-chrome",
"tracing-subscriber",
"tracing-tree",
"walkdir",
@ -727,6 +728,17 @@ dependencies = [
"syn",
]
[[package]]
name = "tracing-chrome"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf0a738ed5d6450a9fb96e86a23ad808de2b727fd1394585da5cdd6788ffe724"
dependencies = [
"serde_json",
"tracing-core",
"tracing-subscriber",
]
[[package]]
name = "tracing-core"
version = "0.1.33"

View file

@ -7,7 +7,7 @@ default-run = "bootstrap"
[features]
build-metrics = ["sysinfo"]
tracing = ["dep:tracing", "dep:tracing-subscriber", "dep:tracing-tree"]
tracing = ["dep:tracing", "dep:tracing-chrome", "dep:tracing-subscriber", "dep:tracing-tree"]
[lib]
path = "src/lib.rs"
@ -67,6 +67,7 @@ sysinfo = { version = "0.33.0", default-features = false, optional = true, featu
# Dependencies needed by the `tracing` feature
tracing = { version = "0.1", optional = true, features = ["attributes"] }
tracing-chrome = { version = "0.7", optional = true }
tracing-subscriber = { version = "0.3", optional = true, features = ["env-filter", "fmt", "registry", "std"] }
tracing-tree = { version = "0.4.0", optional = true }

View file

@ -21,7 +21,7 @@ use tracing::instrument;
#[cfg_attr(feature = "tracing", instrument(level = "trace", name = "main"))]
fn main() {
#[cfg(feature = "tracing")]
setup_tracing();
let _guard = setup_tracing();
let args = env::args().skip(1).collect::<Vec<_>>();
@ -210,7 +210,7 @@ fn check_version(config: &Config) -> Option<String> {
// - `tracing`'s `#[instrument(..)]` macro will need to be gated like `#![cfg_attr(feature =
// "tracing", instrument(..))]`.
#[cfg(feature = "tracing")]
fn setup_tracing() {
fn setup_tracing() -> impl Drop {
use tracing_subscriber::EnvFilter;
use tracing_subscriber::layer::SubscriberExt;
@ -218,7 +218,17 @@ fn setup_tracing() {
// cf. <https://docs.rs/tracing-tree/latest/tracing_tree/struct.HierarchicalLayer.html>.
let layer = tracing_tree::HierarchicalLayer::default().with_targets(true).with_indent_amount(2);
let registry = tracing_subscriber::registry().with(filter).with(layer);
let mut chrome_layer = tracing_chrome::ChromeLayerBuilder::new().include_args(true);
// Writes the Chrome profile to trace-<unix-timestamp>.json if enabled
if !env::var("BOOTSTRAP_PROFILE").is_ok_and(|v| v == "1") {
chrome_layer = chrome_layer.writer(io::sink());
}
let (chrome_layer, _guard) = chrome_layer.build();
let registry = tracing_subscriber::registry().with(filter).with(layer).with(chrome_layer);
tracing::subscriber::set_global_default(registry).unwrap();
_guard
}

View file

@ -2235,6 +2235,10 @@ pub fn stream_cargo(
cb: &mut dyn FnMut(CargoMessage<'_>),
) -> bool {
let mut cmd = cargo.into_cmd();
#[cfg(feature = "tracing")]
let _run_span = crate::trace_cmd!(cmd);
let cargo = cmd.as_command_mut();
// Instruct Cargo to give us json messages on stdout, critically leaving
// stderr as piped so we can get those pretty colors.

View file

@ -905,6 +905,9 @@ impl Build {
return CommandOutput::default();
}
#[cfg(feature = "tracing")]
let _run_span = trace_cmd!(command);
let created_at = command.get_created_location();
let executed_at = std::panic::Location::caller();

View file

@ -329,3 +329,25 @@ impl Default for CommandOutput {
}
}
}
/// Helper trait to format both Command and BootstrapCommand as a short execution line,
/// without all the other details (e.g. environment variables).
#[allow(unused)]
pub trait FormatShortCmd {
fn format_short_cmd(&self) -> String;
}
impl FormatShortCmd for BootstrapCommand {
fn format_short_cmd(&self) -> String {
self.command.format_short_cmd()
}
}
impl FormatShortCmd for Command {
fn format_short_cmd(&self) -> String {
let program = Path::new(self.get_program());
let mut line = vec![program.file_name().unwrap().to_str().unwrap()];
line.extend(self.get_args().map(|arg| arg.to_str().unwrap()));
line.join(" ")
}
}

View file

@ -265,6 +265,9 @@ pub fn make(host: &str) -> PathBuf {
#[track_caller]
pub fn output(cmd: &mut Command) -> String {
#[cfg(feature = "tracing")]
let _run_span = crate::trace_cmd!(cmd);
let output = match cmd.stderr(Stdio::inherit()).output() {
Ok(status) => status,
Err(e) => fail(&format!("failed to execute command: {cmd:?}\nERROR: {e}")),

View file

@ -47,3 +47,20 @@ macro_rules! error {
::tracing::error!($($tokens)*)
}
}
#[macro_export]
macro_rules! trace_cmd {
($cmd:expr) => {
{
use $crate::utils::exec::FormatShortCmd;
::tracing::span!(
target: "COMMAND",
::tracing::Level::TRACE,
"executing command",
cmd = $cmd.format_short_cmd(),
full_cmd = ?$cmd
).entered()
}
};
}

View file

@ -168,10 +168,10 @@ auto:
<<: *job-linux-4c
- name: dist-loongarch64-linux
<<: *job-linux-4c-largedisk
<<: *job-linux-4c
- name: dist-loongarch64-musl
<<: *job-linux-4c-largedisk
<<: *job-linux-4c
- name: dist-ohos
<<: *job-linux-4c

View file

@ -121,6 +121,14 @@ For `#[instrument]`, it's recommended to:
- Explicitly pick an instrumentation name via `name = ".."` to distinguish between e.g. `run` of different steps.
- Take care to not cause diverging behavior via tracing, e.g. building extra things only when tracing infra is enabled.
### Profiling bootstrap
You can use the `COMMAND` tracing target to trace execution of most commands spawned by bootstrap. If you also use the `BOOTSTRAP_PROFILE=1` environment variable, bootstrap will generate a Chrome JSON trace file, which can be visualized in Chrome's `chrome://tracing` page or on https://ui.perfetto.dev.
```bash
$ BOOTSTRAP_TRACING=COMMAND=trace BOOTSTRAP_PROFILE=1 ./x build library
```
### rust-analyzer integration?
Unfortunately, because bootstrap is a `rust-analyzer.linkedProjects`, you can't ask r-a to check/build bootstrap itself with `tracing` feature enabled to get relevant completions, due to lack of support as described in <https://github.com/rust-lang/rust-analyzer/issues/8521>.

View file

@ -368,7 +368,7 @@ This flag controls the optimization level.
* `s`: optimize for binary size.
* `z`: optimize for binary size, but also turn off loop vectorization.
Note: The [`-O` flag][option-o-optimize] is an alias for `-C opt-level=2`.
Note: The [`-O` flag][option-o-optimize] is an alias for `-C opt-level=3`.
The default is `0`.

View file

@ -308,7 +308,7 @@ A synonym for [`-C debuginfo=2`](codegen-options/index.md#debuginfo).
<a id="option-o-optimize"></a>
## `-O`: optimize your code
A synonym for [`-C opt-level=2`](codegen-options/index.md#opt-level).
A synonym for [`-C opt-level=3`](codegen-options/index.md#opt-level).
<a id="option-o-output"></a>
## `-o`: filename of the output

View file

@ -84,7 +84,7 @@ impl Rustc {
self
}
/// Specify default optimization level `-O` (alias for `-C opt-level=2`).
/// Specify default optimization level `-O` (alias for `-C opt-level=3`).
pub fn opt(&mut self) -> &mut Self {
self.cmd.arg("-O");
self

View file

@ -32,7 +32,7 @@ Options:
--print [crate-name|file-names|sysroot|target-libdir|cfg|check-cfg|calling-conventions|target-list|target-cpus|target-features|relocation-models|code-models|tls-models|target-spec-json|all-target-specs-json|native-static-libs|stack-protector-strategies|link-args|deployment-target]
Compiler information to print on stdout
-g Equivalent to -C debuginfo=2
-O Equivalent to -C opt-level=2
-O Equivalent to -C opt-level=3
-o FILENAME Write output to <filename>
--out-dir DIR Write output to compiler-chosen filename in <dir>
--explain OPT Provide a detailed explanation of an error message

View file

@ -32,7 +32,7 @@ Options:
--print [crate-name|file-names|sysroot|target-libdir|cfg|check-cfg|calling-conventions|target-list|target-cpus|target-features|relocation-models|code-models|tls-models|target-spec-json|all-target-specs-json|native-static-libs|stack-protector-strategies|link-args|deployment-target]
Compiler information to print on stdout
-g Equivalent to -C debuginfo=2
-O Equivalent to -C opt-level=2
-O Equivalent to -C opt-level=3
-o FILENAME Write output to <filename>
--out-dir DIR Write output to compiler-chosen filename in <dir>
--explain OPT Provide a detailed explanation of an error message

View file

@ -0,0 +1,18 @@
// Make sure we are using the right binder vars when expanding
// `for<'a> Foo<'a>` to `for<'a> Bar<'a>`.
//@ check-pass
#![feature(trait_alias)]
trait Bar<'a> {}
trait Foo<'a> = Bar<'a>;
fn test2(_: &(impl for<'a> Foo<'a> + ?Sized)) {}
fn test(x: &dyn for<'a> Foo<'a>) {
test2(x);
}
fn main() {}