Skip to content

Rollup of 9 pull requests #137010

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Feb 14, 2025
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3c7c38a
Simplify SSE2 implementation
real-eren Feb 2, 2025
d6ca7ad
Remove dead control char logic
real-eren Feb 3, 2025
4b086d4
expect EINVAL for pthread_mutex_destroy for aix
mustartt Feb 12, 2025
88193aa
Use the right binder for rebinding PolyTraitRef
compiler-errors Feb 12, 2025
9c03369
add `IntoBounds` trait
pitaj Feb 12, 2025
d7eca8a
Trace execution of bootstrap commands
Kobzol Feb 12, 2025
447a6a0
Add export of bootstrap tracing to Chrome events
Kobzol Feb 12, 2025
521cbd3
Document bootstrap profiling
Kobzol Feb 12, 2025
fc5ff7f
ci: switch loongarch jobs to free runners
marcoieni Feb 13, 2025
2966256
Make `-O` mean `-C opt-level=3`
clubby789 Jan 13, 2025
06524b5
Update backtrace
ehuss Feb 13, 2025
bfdc961
[cg_llvm] Remove dead error message
dpaoliello Feb 13, 2025
e7d9cb3
Rollup merge of #135439 - clubby789:O3, r=Noratrieb
workingjubilee Feb 14, 2025
8f4b766
Rollup merge of #136460 - real-eren:simplify-rustc_span-analyze, r=No…
workingjubilee Feb 14, 2025
a82d7d6
Rollup merge of #136904 - pitaj:range-into_bounds, r=tgross35
workingjubilee Feb 14, 2025
dfc235f
Rollup merge of #136908 - mustartt:aix-mutex-destory-einval, r=joboet
workingjubilee Feb 14, 2025
6c1768e
Rollup merge of #136924 - Kobzol:bootstrap-tracing, r=jieyouxu
workingjubilee Feb 14, 2025
3957eaa
Rollup merge of #136951 - compiler-errors:clause-binder, r=lqd
workingjubilee Feb 14, 2025
07c2bd9
Rollup merge of #136981 - marcoieni:no-largedisk-loongarch, r=Kobzol
workingjubilee Feb 14, 2025
e961aac
Rollup merge of #136992 - ehuss:update-backtrace, r=workingjubilee
workingjubilee Feb 14, 2025
e8d0d00
Rollup merge of #136993 - dpaoliello:cleanllvm4, r=workingjubilee
workingjubilee Feb 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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 => {
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_gcc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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,
},
3 changes: 0 additions & 3 deletions compiler/rustc_codegen_llvm/messages.ftl
Original file line number Diff line number Diff line change
@@ -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}
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_llvm/src/back/write.rs
Original file line number Diff line number Diff line change
@@ -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,
5 changes: 0 additions & 5 deletions compiler/rustc_codegen_llvm/src/errors.rs
Original file line number Diff line number Diff line change
@@ -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,
16 changes: 8 additions & 8 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
@@ -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",
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
@@ -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,
}
}
6 changes: 3 additions & 3 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
@@ -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;
3 changes: 1 addition & 2 deletions compiler/rustc_mir_transform/src/inline.rs
Original file line number Diff line number Diff line change
@@ -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,
26 changes: 16 additions & 10 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
@@ -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,
187 changes: 55 additions & 132 deletions compiler/rustc_span/src/analyze_source_file.rs
Original file line number Diff line number Diff line change
@@ -95,65 +95,32 @@ 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) };

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 {
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.
}
} else {
// No control characters, nothing to record for this chunk
continue;
// Check for newlines in the chunk
let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) };
let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) };

let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1);

while newlines_mask != 0 {
let index = newlines_mask.trailing_zeros();

lines.push(RelativeBytePos(index) + output_offset);

// Clear the bit, so we can find the next one.
newlines_mask &= newlines_mask - 1;
}
} else {
// The slow path.
// 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..],
CHUNK_SIZE - intra_chunk_offset,
RelativeBytePos::from_usize(scan_start),
lines,
multi_byte_chars,
);
}

// The slow path.
// There are control 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..],
CHUNK_SIZE - intra_chunk_offset,
RelativeBytePos::from_usize(scan_start),
lines,
multi_byte_chars,
);
}

// There might still be a tail left to analyze
@@ -253,65 +220,32 @@ 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) };

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 {
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.
}
} else {
// No control characters, nothing to record for this chunk
continue;
// Check for newlines in the chunk
let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) };
let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) };

let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1);

while newlines_mask != 0 {
let index = newlines_mask.trailing_zeros();

lines.push(RelativeBytePos(index) + output_offset);

// Clear the bit, so we can find the next one.
newlines_mask &= newlines_mask - 1;
}
} else {
// The slow path.
// 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..],
CHUNK_SIZE - intra_chunk_offset,
RelativeBytePos::from_usize(scan_start),
lines,
multi_byte_chars,
);
}

// The slow path.
// There are control 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..],
CHUNK_SIZE - intra_chunk_offset,
RelativeBytePos::from_usize(scan_start),
lines,
multi_byte_chars,
);
}

// There might still be a tail left to analyze
@@ -369,29 +303,18 @@ 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`.
lines.push(pos + RelativeBytePos(1));
} 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);
}
assert!((2..=4).contains(&char_len));
let mbc = MultiByteChar { pos, bytes: char_len as u8 };
multi_byte_chars.push(mbc);
}

i += char_len;
4 changes: 2 additions & 2 deletions compiler/rustc_trait_selection/src/traits/util.rs
Original file line number Diff line number Diff line change
@@ -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),
),
2 changes: 2 additions & 0 deletions library/core/src/ops/mod.rs
Original file line number Diff line number Diff line change
@@ -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")]
82 changes: 82 additions & 0 deletions library/core/src/ops/range.rs
Original file line number Diff line number Diff line change
@@ -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 Rust’s 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> {
28 changes: 27 additions & 1 deletion library/core/src/range.rs
Original file line number Diff line number Diff line change
@@ -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]
6 changes: 3 additions & 3 deletions library/std/src/sys/pal/unix/sync/mutex.rs
Original file line number Diff line number Diff line change
@@ -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);
12 changes: 12 additions & 0 deletions src/bootstrap/Cargo.lock
3 changes: 2 additions & 1 deletion src/bootstrap/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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 }

16 changes: 13 additions & 3 deletions src/bootstrap/src/bin/main.rs
Original file line number Diff line number Diff line change
@@ -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,15 +210,25 @@ 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;

let filter = EnvFilter::from_env("BOOTSTRAP_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
}
4 changes: 4 additions & 0 deletions src/bootstrap/src/core/build_steps/compile.rs
Original file line number Diff line number Diff line change
@@ -2234,6 +2234,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.
3 changes: 3 additions & 0 deletions src/bootstrap/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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();

22 changes: 22 additions & 0 deletions src/bootstrap/src/utils/exec.rs
Original file line number Diff line number Diff line change
@@ -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(" ")
}
}
3 changes: 3 additions & 0 deletions src/bootstrap/src/utils/helpers.rs
Original file line number Diff line number Diff line change
@@ -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}")),
17 changes: 17 additions & 0 deletions src/bootstrap/src/utils/tracing.rs
Original file line number Diff line number Diff line change
@@ -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()
}
};
}
4 changes: 2 additions & 2 deletions src/ci/github-actions/jobs.yml
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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>.
2 changes: 1 addition & 1 deletion src/doc/rustc/src/codegen-options/index.md
Original file line number Diff line number Diff line change
@@ -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`.

2 changes: 1 addition & 1 deletion src/doc/rustc/src/command-line-arguments.md
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion src/tools/run-make-support/src/external_deps/rustc.rs
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion tests/run-make/rustc-help/help-v.stdout
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion tests/run-make/rustc-help/help.stdout
Original file line number Diff line number Diff line change
@@ -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
18 changes: 18 additions & 0 deletions tests/ui/traits/alias/expand-higher-ranked-alias.rs
Original file line number Diff line number Diff line change
@@ -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() {}