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:
commit
905b1bf1cc
33 changed files with 307 additions and 179 deletions
|
@ -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 => {
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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")]
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 }
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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(" ")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}")),
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>.
|
||||
|
|
|
@ -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`.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
tests/ui/traits/alias/expand-higher-ranked-alias.rs
Normal file
18
tests/ui/traits/alias/expand-higher-ranked-alias.rs
Normal 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() {}
|
Loading…
Add table
Add a link
Reference in a new issue