Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit bb918d0

Browse files
committedOct 9, 2021
Auto merge of #89698 - matthiaskrgr:rollup-gna54x6, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #88707 (String.split_terminator: Add an example when using a slice of chars) - #89605 (Fix stabilization version for `bindings_after_at`) - #89634 (rustc_driver: Enable the `WARN` log level by default) - #89641 (make #[target_feature] work with `asm` register classes) - #89678 (Fix minor std::thread documentation typo) - #89684 (Fix asm docs typo) - #89687 (Move `read2_abbreviated` function into read2.rs) - #89693 (Add #[must_use] to stdin/stdout/stderr locks) - #89694 (Add #[must_use] to string/char transformation methods) - #89697 (Fix min LLVM version for bpf-types test) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 910692d + 2e5a5e2 commit bb918d0

File tree

26 files changed

+361
-205
lines changed

26 files changed

+361
-205
lines changed
 

‎compiler/rustc_ast_lowering/src/asm.rs

Lines changed: 2 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -202,39 +202,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
202202

203203
let mut used_input_regs = FxHashMap::default();
204204
let mut used_output_regs = FxHashMap::default();
205-
let mut required_features: Vec<&str> = vec![];
205+
206206
for (idx, &(ref op, op_sp)) in operands.iter().enumerate() {
207207
if let Some(reg) = op.reg() {
208-
// Make sure we don't accidentally carry features from the
209-
// previous iteration.
210-
required_features.clear();
211-
212208
let reg_class = reg.reg_class();
213209
if reg_class == asm::InlineAsmRegClass::Err {
214210
continue;
215211
}
216212

217-
// We ignore target feature requirements for clobbers: if the
218-
// feature is disabled then the compiler doesn't care what we
219-
// do with the registers.
220-
//
221-
// Note that this is only possible for explicit register
222-
// operands, which cannot be used in the asm string.
223-
let is_clobber = matches!(
224-
op,
225-
hir::InlineAsmOperand::Out {
226-
reg: asm::InlineAsmRegOrRegClass::Reg(_),
227-
late: _,
228-
expr: None
229-
}
230-
);
231-
232213
// Some register classes can only be used as clobbers. This
233214
// means that we disallow passing a value in/out of the asm and
234215
// require that the operand name an explicit register, not a
235216
// register class.
236217
if reg_class.is_clobber_only(asm_arch.unwrap())
237-
&& !(is_clobber && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_)))
218+
&& !(op.is_clobber() && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_)))
238219
{
239220
let msg = format!(
240221
"register class `{}` can only be used as a clobber, \
@@ -245,47 +226,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
245226
continue;
246227
}
247228

248-
if !is_clobber {
249-
// Validate register classes against currently enabled target
250-
// features. We check that at least one type is available for
251-
// the current target.
252-
for &(_, feature) in reg_class.supported_types(asm_arch.unwrap()) {
253-
if let Some(feature) = feature {
254-
if self.sess.target_features.contains(&Symbol::intern(feature)) {
255-
required_features.clear();
256-
break;
257-
} else {
258-
required_features.push(feature);
259-
}
260-
} else {
261-
required_features.clear();
262-
break;
263-
}
264-
}
265-
// We are sorting primitive strs here and can use unstable sort here
266-
required_features.sort_unstable();
267-
required_features.dedup();
268-
match &required_features[..] {
269-
[] => {}
270-
[feature] => {
271-
let msg = format!(
272-
"register class `{}` requires the `{}` target feature",
273-
reg_class.name(),
274-
feature
275-
);
276-
sess.struct_span_err(op_sp, &msg).emit();
277-
}
278-
features => {
279-
let msg = format!(
280-
"register class `{}` requires at least one target feature: {}",
281-
reg_class.name(),
282-
features.join(", ")
283-
);
284-
sess.struct_span_err(op_sp, &msg).emit();
285-
}
286-
}
287-
}
288-
289229
// Check for conflicts between explicit register operands.
290230
if let asm::InlineAsmRegOrRegClass::Reg(reg) = reg {
291231
let (input, output) = match op {

‎compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -843,19 +843,18 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
843843
let msg_bus = "clang: error: unable to execute command: Bus error: 10";
844844
if out.contains(msg_segv) || out.contains(msg_bus) {
845845
warn!(
846+
?cmd, %out,
846847
"looks like the linker segfaulted when we tried to call it, \
847-
automatically retrying again. cmd = {:?}, out = {}.",
848-
cmd, out,
848+
automatically retrying again",
849849
);
850850
continue;
851851
}
852852

853853
if is_illegal_instruction(&output.status) {
854854
warn!(
855+
?cmd, %out, status = %output.status,
855856
"looks like the linker hit an illegal instruction when we \
856-
tried to call it, automatically retrying again. cmd = {:?}, ]\
857-
out = {}, status = {}.",
858-
cmd, out, output.status,
857+
tried to call it, automatically retrying again.",
859858
);
860859
continue;
861860
}

‎compiler/rustc_driver/src/lib.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,12 +1253,16 @@ pub fn init_rustc_env_logger() {
12531253
/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var
12541254
/// other than `RUSTC_LOG`.
12551255
pub fn init_env_logger(env: &str) {
1256-
// Don't register a dispatcher if there's no filter to print anything
1257-
match std::env::var(env) {
1258-
Err(_) => return,
1259-
Ok(s) if s.is_empty() => return,
1260-
Ok(_) => {}
1261-
}
1256+
use tracing_subscriber::{
1257+
filter::{self, EnvFilter, LevelFilter},
1258+
layer::SubscriberExt,
1259+
};
1260+
1261+
let filter = match std::env::var(env) {
1262+
Ok(env) => EnvFilter::from_env(env),
1263+
_ => EnvFilter::default().add_directive(filter::Directive::from(LevelFilter::WARN)),
1264+
};
1265+
12621266
let color_logs = match std::env::var(String::from(env) + "_COLOR") {
12631267
Ok(value) => match value.as_ref() {
12641268
"always" => true,
@@ -1278,7 +1282,7 @@ pub fn init_env_logger(env: &str) {
12781282
"non-Unicode log color value: expected one of always, never, or auto",
12791283
),
12801284
};
1281-
let filter = tracing_subscriber::EnvFilter::from_env(env);
1285+
12821286
let layer = tracing_tree::HierarchicalLayer::default()
12831287
.with_writer(io::stderr)
12841288
.with_indent_lines(true)
@@ -1288,7 +1292,6 @@ pub fn init_env_logger(env: &str) {
12881292
#[cfg(parallel_compiler)]
12891293
let layer = layer.with_thread_ids(true).with_thread_names(true);
12901294

1291-
use tracing_subscriber::layer::SubscriberExt;
12921295
let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer);
12931296
tracing::subscriber::set_global_default(subscriber).unwrap();
12941297
}

‎compiler/rustc_errors/src/emitter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2308,7 +2308,7 @@ pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool {
23082308
let found = match sm.span_to_snippet(sp) {
23092309
Ok(snippet) => snippet,
23102310
Err(e) => {
2311-
warn!("Invalid span {:?}. Err={:?}", sp, e);
2311+
warn!(error = ?e, "Invalid span {:?}", sp);
23122312
return false;
23132313
}
23142314
};

‎compiler/rustc_feature/src/accepted.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ declare_features! (
288288
(accepted, member_constraints, "1.54.0", Some(61997), None),
289289
/// Allows bindings in the subpattern of a binding pattern.
290290
/// For example, you can write `x @ Some(y)`.
291-
(accepted, bindings_after_at, "1.54.0", Some(65490), None),
291+
(accepted, bindings_after_at, "1.56.0", Some(65490), None),
292292
/// Allows calling `transmute` in const fn
293293
(accepted, const_fn_transmute, "1.56.0", Some(53605), None),
294294
/// Allows accessing fields of unions inside `const` functions.

‎compiler/rustc_hir/src/hir.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2293,6 +2293,13 @@ impl<'hir> InlineAsmOperand<'hir> {
22932293
Self::Const { .. } | Self::Sym { .. } => None,
22942294
}
22952295
}
2296+
2297+
pub fn is_clobber(&self) -> bool {
2298+
matches!(
2299+
self,
2300+
InlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(_), late: _, expr: None }
2301+
)
2302+
}
22962303
}
22972304

22982305
#[derive(Debug, HashStable_Generic)]

‎compiler/rustc_mir_dataflow/src/rustc_peek.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeMutBorrowedLocals<'_, 'tcx> {
289289
flow_state: &BitSet<Local>,
290290
call: PeekCall,
291291
) {
292-
warn!("peek_at: place={:?}", place);
292+
info!(?place, "peek_at");
293293
let local = if let Some(l) = place.as_local() {
294294
l
295295
} else {
@@ -311,7 +311,7 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeLiveLocals {
311311
flow_state: &BitSet<Local>,
312312
call: PeekCall,
313313
) {
314-
warn!("peek_at: place={:?}", place);
314+
info!(?place, "peek_at");
315315
let local = if let Some(l) = place.as_local() {
316316
l
317317
} else {

‎compiler/rustc_passes/src/intrinsicck.rs

Lines changed: 120 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ impl ExprVisitor<'tcx> {
141141
template: &[InlineAsmTemplatePiece],
142142
is_input: bool,
143143
tied_input: Option<(&hir::Expr<'tcx>, Option<InlineAsmType>)>,
144+
target_features: &[Symbol],
144145
) -> Option<InlineAsmType> {
145146
// Check the type against the allowed types for inline asm.
146147
let ty = self.typeck_results.expr_ty_adjusted(expr);
@@ -283,17 +284,20 @@ impl ExprVisitor<'tcx> {
283284
};
284285

285286
// Check whether the selected type requires a target feature. Note that
286-
// this is different from the feature check we did earlier in AST
287-
// lowering. While AST lowering checked that this register class is
288-
// usable at all with the currently enabled features, some types may
289-
// only be usable with a register class when a certain feature is
290-
// enabled. We check this here since it depends on the results of typeck.
287+
// this is different from the feature check we did earlier. While the
288+
// previous check checked that this register class is usable at all
289+
// with the currently enabled features, some types may only be usable
290+
// with a register class when a certain feature is enabled. We check
291+
// this here since it depends on the results of typeck.
291292
//
292293
// Also note that this check isn't run when the operand type is never
293-
// (!). In that case we still need the earlier check in AST lowering to
294-
// verify that the register class is usable at all.
294+
// (!). In that case we still need the earlier check to verify that the
295+
// register class is usable at all.
295296
if let Some(feature) = feature {
296-
if !self.tcx.sess.target_features.contains(&Symbol::intern(feature)) {
297+
let feat_sym = Symbol::intern(feature);
298+
if !self.tcx.sess.target_features.contains(&feat_sym)
299+
&& !target_features.contains(&feat_sym)
300+
{
297301
let msg = &format!("`{}` target feature is not enabled", feature);
298302
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
299303
err.note(&format!(
@@ -349,23 +353,122 @@ impl ExprVisitor<'tcx> {
349353
Some(asm_ty)
350354
}
351355

352-
fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) {
353-
for (idx, (op, _)) in asm.operands.iter().enumerate() {
356+
fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, hir_id: hir::HirId) {
357+
let hir = self.tcx.hir();
358+
let enclosing_id = hir.enclosing_body_owner(hir_id);
359+
let enclosing_def_id = hir.local_def_id(enclosing_id).to_def_id();
360+
let attrs = self.tcx.codegen_fn_attrs(enclosing_def_id);
361+
for (idx, (op, op_sp)) in asm.operands.iter().enumerate() {
362+
// Validate register classes against currently enabled target
363+
// features. We check that at least one type is available for
364+
// the enabled features.
365+
//
366+
// We ignore target feature requirements for clobbers: if the
367+
// feature is disabled then the compiler doesn't care what we
368+
// do with the registers.
369+
//
370+
// Note that this is only possible for explicit register
371+
// operands, which cannot be used in the asm string.
372+
if let Some(reg) = op.reg() {
373+
if !op.is_clobber() {
374+
let mut missing_required_features = vec![];
375+
let reg_class = reg.reg_class();
376+
for &(_, feature) in reg_class.supported_types(self.tcx.sess.asm_arch.unwrap())
377+
{
378+
match feature {
379+
Some(feature) => {
380+
let feat_sym = Symbol::intern(feature);
381+
if self.tcx.sess.target_features.contains(&feat_sym)
382+
|| attrs.target_features.contains(&feat_sym)
383+
{
384+
missing_required_features.clear();
385+
break;
386+
} else {
387+
missing_required_features.push(feature);
388+
}
389+
}
390+
None => {
391+
missing_required_features.clear();
392+
break;
393+
}
394+
}
395+
}
396+
397+
// We are sorting primitive strs here and can use unstable sort here
398+
missing_required_features.sort_unstable();
399+
missing_required_features.dedup();
400+
match &missing_required_features[..] {
401+
[] => {}
402+
[feature] => {
403+
let msg = format!(
404+
"register class `{}` requires the `{}` target feature",
405+
reg_class.name(),
406+
feature
407+
);
408+
self.tcx.sess.struct_span_err(*op_sp, &msg).emit();
409+
// register isn't enabled, don't do more checks
410+
continue;
411+
}
412+
features => {
413+
let msg = format!(
414+
"register class `{}` requires at least one of the following target features: {}",
415+
reg_class.name(),
416+
features.join(", ")
417+
);
418+
self.tcx.sess.struct_span_err(*op_sp, &msg).emit();
419+
// register isn't enabled, don't do more checks
420+
continue;
421+
}
422+
}
423+
}
424+
}
425+
354426
match *op {
355427
hir::InlineAsmOperand::In { reg, ref expr } => {
356-
self.check_asm_operand_type(idx, reg, expr, asm.template, true, None);
428+
self.check_asm_operand_type(
429+
idx,
430+
reg,
431+
expr,
432+
asm.template,
433+
true,
434+
None,
435+
&attrs.target_features,
436+
);
357437
}
358438
hir::InlineAsmOperand::Out { reg, late: _, ref expr } => {
359439
if let Some(expr) = expr {
360-
self.check_asm_operand_type(idx, reg, expr, asm.template, false, None);
440+
self.check_asm_operand_type(
441+
idx,
442+
reg,
443+
expr,
444+
asm.template,
445+
false,
446+
None,
447+
&attrs.target_features,
448+
);
361449
}
362450
}
363451
hir::InlineAsmOperand::InOut { reg, late: _, ref expr } => {
364-
self.check_asm_operand_type(idx, reg, expr, asm.template, false, None);
452+
self.check_asm_operand_type(
453+
idx,
454+
reg,
455+
expr,
456+
asm.template,
457+
false,
458+
None,
459+
&attrs.target_features,
460+
);
365461
}
366462
hir::InlineAsmOperand::SplitInOut { reg, late: _, ref in_expr, ref out_expr } => {
367-
let in_ty =
368-
self.check_asm_operand_type(idx, reg, in_expr, asm.template, true, None);
463+
let in_ty = self.check_asm_operand_type(
464+
idx,
465+
reg,
466+
in_expr,
467+
asm.template,
468+
true,
469+
None,
470+
&attrs.target_features,
471+
);
369472
if let Some(out_expr) = out_expr {
370473
self.check_asm_operand_type(
371474
idx,
@@ -374,6 +477,7 @@ impl ExprVisitor<'tcx> {
374477
asm.template,
375478
false,
376479
Some((in_expr, in_ty)),
480+
&attrs.target_features,
377481
);
378482
}
379483
}
@@ -422,7 +526,7 @@ impl Visitor<'tcx> for ExprVisitor<'tcx> {
422526
}
423527
}
424528

425-
hir::ExprKind::InlineAsm(asm) => self.check_asm(asm),
529+
hir::ExprKind::InlineAsm(asm) => self.check_asm(asm, expr.hir_id),
426530

427531
_ => {}
428532
}

‎library/alloc/src/slice.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,8 @@ impl [u8] {
662662
///
663663
/// [`make_ascii_uppercase`]: slice::make_ascii_uppercase
664664
#[cfg(not(no_global_oom_handling))]
665+
#[must_use = "this returns the uppercase bytes as a new Vec, \
666+
without modifying the original"]
665667
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
666668
#[inline]
667669
pub fn to_ascii_uppercase(&self) -> Vec<u8> {
@@ -680,6 +682,8 @@ impl [u8] {
680682
///
681683
/// [`make_ascii_lowercase`]: slice::make_ascii_lowercase
682684
#[cfg(not(no_global_oom_handling))]
685+
#[must_use = "this returns the lowercase bytes as a new Vec, \
686+
without modifying the original"]
683687
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
684688
#[inline]
685689
pub fn to_ascii_lowercase(&self) -> Vec<u8> {

‎library/alloc/src/str.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ impl str {
367367
/// assert_eq!(new_year, new_year.to_lowercase());
368368
/// ```
369369
#[cfg(not(no_global_oom_handling))]
370+
#[must_use = "this returns the lowercase string as a new String, \
371+
without modifying the original"]
370372
#[stable(feature = "unicode_case_mapping", since = "1.2.0")]
371373
pub fn to_lowercase(&self) -> String {
372374
let mut s = String::with_capacity(self.len());
@@ -447,6 +449,8 @@ impl str {
447449
/// assert_eq!("TSCHÜSS", s.to_uppercase());
448450
/// ```
449451
#[cfg(not(no_global_oom_handling))]
452+
#[must_use = "this returns the uppercase string as a new String, \
453+
without modifying the original"]
450454
#[stable(feature = "unicode_case_mapping", since = "1.2.0")]
451455
pub fn to_uppercase(&self) -> String {
452456
let mut s = String::with_capacity(self.len());
@@ -534,6 +538,7 @@ impl str {
534538
/// [`make_ascii_uppercase`]: str::make_ascii_uppercase
535539
/// [`to_uppercase`]: #method.to_uppercase
536540
#[cfg(not(no_global_oom_handling))]
541+
#[must_use = "to uppercase the value in-place, use `make_ascii_lowercase()`"]
537542
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
538543
#[inline]
539544
pub fn to_ascii_uppercase(&self) -> String {
@@ -565,6 +570,7 @@ impl str {
565570
/// [`make_ascii_lowercase`]: str::make_ascii_lowercase
566571
/// [`to_lowercase`]: #method.to_lowercase
567572
#[cfg(not(no_global_oom_handling))]
573+
#[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"]
568574
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
569575
#[inline]
570576
pub fn to_ascii_lowercase(&self) -> String {

‎library/core/src/char/methods.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,8 @@ impl char {
949949
/// // convert into themselves.
950950
/// assert_eq!('山'.to_lowercase().to_string(), "山");
951951
/// ```
952+
#[must_use = "this returns the lowercase character as a new iterator, \
953+
without modifying the original"]
952954
#[stable(feature = "rust1", since = "1.0.0")]
953955
#[inline]
954956
pub fn to_lowercase(self) -> ToLowercase {
@@ -1039,6 +1041,8 @@ impl char {
10391041
/// ```
10401042
///
10411043
/// holds across languages.
1044+
#[must_use = "this returns the uppercase character as a new iterator, \
1045+
without modifying the original"]
10421046
#[stable(feature = "rust1", since = "1.0.0")]
10431047
#[inline]
10441048
pub fn to_uppercase(self) -> ToUppercase {
@@ -1085,6 +1089,7 @@ impl char {
10851089
///
10861090
/// [`make_ascii_uppercase()`]: #method.make_ascii_uppercase
10871091
/// [`to_uppercase()`]: #method.to_uppercase
1092+
#[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"]
10881093
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
10891094
#[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
10901095
#[inline]
@@ -1118,6 +1123,7 @@ impl char {
11181123
///
11191124
/// [`make_ascii_lowercase()`]: #method.make_ascii_lowercase
11201125
/// [`to_lowercase()`]: #method.to_lowercase
1126+
#[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"]
11211127
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
11221128
#[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
11231129
#[inline]

‎library/core/src/num/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ impl u8 {
282282
/// ```
283283
///
284284
/// [`make_ascii_uppercase`]: Self::make_ascii_uppercase
285+
#[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"]
285286
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
286287
#[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
287288
#[inline]
@@ -306,6 +307,7 @@ impl u8 {
306307
/// ```
307308
///
308309
/// [`make_ascii_lowercase`]: Self::make_ascii_lowercase
310+
#[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"]
309311
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
310312
#[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
311313
#[inline]
@@ -769,6 +771,8 @@ impl u8 {
769771
/// assert_eq!("\\\\", b'\\'.escape_ascii().to_string());
770772
/// assert_eq!("\\x9d", b'\x9d'.escape_ascii().to_string());
771773
/// ```
774+
#[must_use = "this returns the escaped byte as an iterator, \
775+
without modifying the original"]
772776
#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
773777
#[inline]
774778
pub fn escape_ascii(&self) -> ascii::EscapeDefault {

‎library/core/src/slice/ascii.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ impl [u8] {
7272
/// let escaped = s.escape_ascii().to_string();
7373
/// assert_eq!(escaped, "0\\t\\r\\n\\'\\\"\\\\\\x9d");
7474
/// ```
75+
#[must_use = "this returns the escaped bytes as an iterator, \
76+
without modifying the original"]
7577
#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
7678
pub fn escape_ascii(&self) -> EscapeAscii<'_> {
7779
EscapeAscii { inner: self.iter().flat_map(EscapeByte) }

‎library/core/src/str/mod.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,8 @@ impl str {
798798
///
799799
/// assert_eq!(None, iter.next());
800800
/// ```
801+
#[must_use = "this returns the split string as an iterator, \
802+
without modifying the original"]
801803
#[stable(feature = "split_whitespace", since = "1.1.0")]
802804
#[inline]
803805
pub fn split_whitespace(&self) -> SplitWhitespace<'_> {
@@ -839,6 +841,8 @@ impl str {
839841
///
840842
/// assert_eq!(None, iter.next());
841843
/// ```
844+
#[must_use = "this returns the split string as an iterator, \
845+
without modifying the original"]
842846
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
843847
#[inline]
844848
pub fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_> {
@@ -914,6 +918,8 @@ impl str {
914918
///
915919
/// assert!(utf16_len <= utf8_len);
916920
/// ```
921+
#[must_use = "this returns the encoded string as an iterator, \
922+
without modifying the original"]
917923
#[stable(feature = "encode_utf16", since = "1.8.0")]
918924
pub fn encode_utf16(&self) -> EncodeUtf16<'_> {
919925
EncodeUtf16 { chars: self.chars(), extra: 0 }
@@ -1353,6 +1359,9 @@ impl str {
13531359
///
13541360
/// let v: Vec<&str> = "A..B..".split_terminator(".").collect();
13551361
/// assert_eq!(v, ["A", "", "B", ""]);
1362+
///
1363+
/// let v: Vec<&str> = "A.B:C.D".split_terminator(&['.', ':'][..]).collect();
1364+
/// assert_eq!(v, ["A", "B", "C", "D"]);
13561365
/// ```
13571366
#[stable(feature = "rust1", since = "1.0.0")]
13581367
#[inline]
@@ -1396,6 +1405,9 @@ impl str {
13961405
///
13971406
/// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect();
13981407
/// assert_eq!(v, ["", "B", "", "A"]);
1408+
///
1409+
/// let v: Vec<&str> = "A.B:C.D".rsplit_terminator(&['.', ':'][..]).collect();
1410+
/// assert_eq!(v, ["D", "C", "B", "A"]);
13991411
/// ```
14001412
#[stable(feature = "rust1", since = "1.0.0")]
14011413
#[inline]
@@ -1840,6 +1852,8 @@ impl str {
18401852
/// let s = " עברית";
18411853
/// assert!(Some('ע') == s.trim_left().chars().next());
18421854
/// ```
1855+
#[must_use = "this returns the trimmed string as a new slice, \
1856+
without modifying the original"]
18431857
#[inline]
18441858
#[stable(feature = "rust1", since = "1.0.0")]
18451859
#[rustc_deprecated(
@@ -1882,6 +1896,8 @@ impl str {
18821896
/// let s = "עברית ";
18831897
/// assert!(Some('ת') == s.trim_right().chars().rev().next());
18841898
/// ```
1899+
#[must_use = "this returns the trimmed string as a new slice, \
1900+
without modifying the original"]
18851901
#[inline]
18861902
#[stable(feature = "rust1", since = "1.0.0")]
18871903
#[rustc_deprecated(
@@ -2346,6 +2362,8 @@ impl str {
23462362
/// ```
23472363
/// assert_eq!("❤\n!".escape_debug().to_string(), "❤\\n!");
23482364
/// ```
2365+
#[must_use = "this returns the escaped string as an iterator, \
2366+
without modifying the original"]
23492367
#[stable(feature = "str_escape", since = "1.34.0")]
23502368
pub fn escape_debug(&self) -> EscapeDebug<'_> {
23512369
let mut chars = self.chars();
@@ -2390,6 +2408,8 @@ impl str {
23902408
/// ```
23912409
/// assert_eq!("❤\n!".escape_default().to_string(), "\\u{2764}\\n!");
23922410
/// ```
2411+
#[must_use = "this returns the escaped string as an iterator, \
2412+
without modifying the original"]
23932413
#[stable(feature = "str_escape", since = "1.34.0")]
23942414
pub fn escape_default(&self) -> EscapeDefault<'_> {
23952415
EscapeDefault { inner: self.chars().flat_map(CharEscapeDefault) }
@@ -2426,6 +2446,8 @@ impl str {
24262446
/// ```
24272447
/// assert_eq!("❤\n!".escape_unicode().to_string(), "\\u{2764}\\u{a}\\u{21}");
24282448
/// ```
2449+
#[must_use = "this returns the escaped string as an iterator, \
2450+
without modifying the original"]
24292451
#[stable(feature = "str_escape", since = "1.34.0")]
24302452
pub fn escape_unicode(&self) -> EscapeUnicode<'_> {
24312453
EscapeUnicode { inner: self.chars().flat_map(CharEscapeUnicode) }

‎library/std/src/ffi/os_str.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,7 @@ impl OsStr {
777777
///
778778
/// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase());
779779
/// ```
780+
#[must_use = "to lowercase the value in-place, use `make_ascii_lowercase`"]
780781
#[stable(feature = "osstring_ascii", since = "1.53.0")]
781782
pub fn to_ascii_lowercase(&self) -> OsString {
782783
OsString::from_inner(self.inner.to_ascii_lowercase())
@@ -798,6 +799,7 @@ impl OsStr {
798799
///
799800
/// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase());
800801
/// ```
802+
#[must_use = "to uppercase the value in-place, use `make_ascii_uppercase`"]
801803
#[stable(feature = "osstring_ascii", since = "1.53.0")]
802804
pub fn to_ascii_uppercase(&self) -> OsString {
803805
OsString::from_inner(self.inner.to_ascii_uppercase())

‎library/std/src/io/stdio.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ pub struct Stdin {
256256
/// Ok(())
257257
/// }
258258
/// ```
259+
#[must_use = "if unused stdin will immediately unlock"]
259260
#[stable(feature = "rust1", since = "1.0.0")]
260261
pub struct StdinLock<'a> {
261262
inner: MutexGuard<'a, BufReader<StdinRaw>>,
@@ -624,6 +625,7 @@ pub struct Stdout {
624625
/// When operating in a console, the Windows implementation of this stream does not support
625626
/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
626627
/// an error.
628+
#[must_use = "if unused stdout will immediately unlock"]
627629
#[stable(feature = "rust1", since = "1.0.0")]
628630
pub struct StdoutLock<'a> {
629631
inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
@@ -907,6 +909,7 @@ pub struct Stderr {
907909
/// When operating in a console, the Windows implementation of this stream does not support
908910
/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
909911
/// an error.
912+
#[must_use = "if unused stderr will immediately unlock"]
910913
#[stable(feature = "rust1", since = "1.0.0")]
911914
pub struct StderrLock<'a> {
912915
inner: ReentrantMutexGuard<'a, RefCell<StderrRaw>>,

‎library/std/src/thread/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -412,9 +412,9 @@ impl Builder {
412412
///
413413
/// # Safety
414414
///
415-
/// The caller has to ensure that no references in the supplied thread closure
416-
/// or its return type can outlive the spawned thread's lifetime. This can be
417-
/// guaranteed in two ways:
415+
/// The caller has to ensure that the spawned thread does not outlive any
416+
/// references in the supplied thread closure and its return type.
417+
/// This can be guaranteed in two ways:
418418
///
419419
/// - ensure that [`join`][`JoinHandle::join`] is called before any referenced
420420
/// data is dropped

‎src/doc/unstable-book/src/library-features/asm.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -613,8 +613,8 @@ Each register class has constraints on which value types they can be used with.
613613
| x86 | `xmm_reg` | `sse` | `i32`, `f32`, `i64`, `f64`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
614614
| x86 | `ymm_reg` | `avx` | `i32`, `f32`, `i64`, `f64`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` <br> `i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` |
615615
| x86 | `zmm_reg` | `avx512f` | `i32`, `f32`, `i64`, `f64`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` <br> `i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` <br> `i8x64`, `i16x32`, `i32x16`, `i64x8`, `f32x16`, `f64x8` |
616-
| x86 | `kreg` | `axv512f` | `i8`, `i16` |
617-
| x86 | `kreg` | `axv512bw` | `i32`, `i64` |
616+
| x86 | `kreg` | `avx512f` | `i8`, `i16` |
617+
| x86 | `kreg` | `avx512bw` | `i32`, `i64` |
618618
| x86 | `mmx_reg` | N/A | Only clobbers |
619619
| x86 | `x87_reg` | N/A | Only clobbers |
620620
| AArch64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |

‎src/test/assembly/asm/bpf-types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// min-llvm-version: 10.0.1
1+
// min-llvm-version: 13.0
22
// assembly-output: emit-asm
33
// compile-flags: --target bpfel-unknown-none -C target_feature=+alu32
44
// needs-llvm-components: bpf

‎src/test/ui/asm/x86_64/bad-reg.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@ fn main() {
2121
//~^ ERROR asm template modifiers are not allowed for `const` arguments
2222
asm!("{:a}", sym main);
2323
//~^ ERROR asm template modifiers are not allowed for `sym` arguments
24-
asm!("{}", in(zmm_reg) foo);
25-
//~^ ERROR register class `zmm_reg` requires the `avx512f` target feature
26-
asm!("", in("zmm0") foo);
27-
//~^ ERROR register class `zmm_reg` requires the `avx512f` target feature
2824
asm!("", in("ebp") foo);
2925
//~^ ERROR invalid register `ebp`: the frame pointer cannot be used as an operand
3026
asm!("", in("rsp") foo);

‎src/test/ui/asm/x86_64/bad-reg.stderr

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -46,127 +46,115 @@ LL | asm!("{:a}", sym main);
4646
| |
4747
| template modifier
4848

49-
error: register class `zmm_reg` requires the `avx512f` target feature
50-
--> $DIR/bad-reg.rs:24:20
51-
|
52-
LL | asm!("{}", in(zmm_reg) foo);
53-
| ^^^^^^^^^^^^^^^
54-
55-
error: register class `zmm_reg` requires the `avx512f` target feature
56-
--> $DIR/bad-reg.rs:26:18
57-
|
58-
LL | asm!("", in("zmm0") foo);
59-
| ^^^^^^^^^^^^^^
60-
6149
error: invalid register `ebp`: the frame pointer cannot be used as an operand for inline asm
62-
--> $DIR/bad-reg.rs:28:18
50+
--> $DIR/bad-reg.rs:24:18
6351
|
6452
LL | asm!("", in("ebp") foo);
6553
| ^^^^^^^^^^^^^
6654

6755
error: invalid register `rsp`: the stack pointer cannot be used as an operand for inline asm
68-
--> $DIR/bad-reg.rs:30:18
56+
--> $DIR/bad-reg.rs:26:18
6957
|
7058
LL | asm!("", in("rsp") foo);
7159
| ^^^^^^^^^^^^^
7260

7361
error: invalid register `ip`: the instruction pointer cannot be used as an operand for inline asm
74-
--> $DIR/bad-reg.rs:32:18
62+
--> $DIR/bad-reg.rs:28:18
7563
|
7664
LL | asm!("", in("ip") foo);
7765
| ^^^^^^^^^^^^
7866

7967
error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm
80-
--> $DIR/bad-reg.rs:34:18
68+
--> $DIR/bad-reg.rs:30:18
8169
|
8270
LL | asm!("", in("k0") foo);
8371
| ^^^^^^^^^^^^
8472

8573
error: invalid register `ah`: high byte registers cannot be used as an operand on x86_64
86-
--> $DIR/bad-reg.rs:36:18
74+
--> $DIR/bad-reg.rs:32:18
8775
|
8876
LL | asm!("", in("ah") foo);
8977
| ^^^^^^^^^^^^
9078

9179
error: register class `x87_reg` can only be used as a clobber, not as an input or output
92-
--> $DIR/bad-reg.rs:39:18
80+
--> $DIR/bad-reg.rs:35:18
9381
|
9482
LL | asm!("", in("st(2)") foo);
9583
| ^^^^^^^^^^^^^^^
9684

9785
error: register class `mmx_reg` can only be used as a clobber, not as an input or output
98-
--> $DIR/bad-reg.rs:41:18
86+
--> $DIR/bad-reg.rs:37:18
9987
|
10088
LL | asm!("", in("mm0") foo);
10189
| ^^^^^^^^^^^^^
10290

10391
error: register class `x87_reg` can only be used as a clobber, not as an input or output
104-
--> $DIR/bad-reg.rs:45:20
92+
--> $DIR/bad-reg.rs:41:20
10593
|
10694
LL | asm!("{}", in(x87_reg) foo);
10795
| ^^^^^^^^^^^^^^^
10896

10997
error: register class `mmx_reg` can only be used as a clobber, not as an input or output
110-
--> $DIR/bad-reg.rs:47:20
98+
--> $DIR/bad-reg.rs:43:20
11199
|
112100
LL | asm!("{}", in(mmx_reg) foo);
113101
| ^^^^^^^^^^^^^^^
114102

115103
error: register class `x87_reg` can only be used as a clobber, not as an input or output
116-
--> $DIR/bad-reg.rs:49:20
104+
--> $DIR/bad-reg.rs:45:20
117105
|
118106
LL | asm!("{}", out(x87_reg) _);
119107
| ^^^^^^^^^^^^^^
120108

121109
error: register class `mmx_reg` can only be used as a clobber, not as an input or output
122-
--> $DIR/bad-reg.rs:51:20
110+
--> $DIR/bad-reg.rs:47:20
123111
|
124112
LL | asm!("{}", out(mmx_reg) _);
125113
| ^^^^^^^^^^^^^^
126114

127115
error: register `al` conflicts with register `ax`
128-
--> $DIR/bad-reg.rs:57:33
116+
--> $DIR/bad-reg.rs:53:33
129117
|
130118
LL | asm!("", in("eax") foo, in("al") bar);
131119
| ------------- ^^^^^^^^^^^^ register `al`
132120
| |
133121
| register `ax`
134122

135123
error: register `ax` conflicts with register `ax`
136-
--> $DIR/bad-reg.rs:59:33
124+
--> $DIR/bad-reg.rs:55:33
137125
|
138126
LL | asm!("", in("rax") foo, out("rax") bar);
139127
| ------------- ^^^^^^^^^^^^^^ register `ax`
140128
| |
141129
| register `ax`
142130
|
143131
help: use `lateout` instead of `out` to avoid conflict
144-
--> $DIR/bad-reg.rs:59:18
132+
--> $DIR/bad-reg.rs:55:18
145133
|
146134
LL | asm!("", in("rax") foo, out("rax") bar);
147135
| ^^^^^^^^^^^^^
148136

149137
error: register `ymm0` conflicts with register `xmm0`
150-
--> $DIR/bad-reg.rs:62:34
138+
--> $DIR/bad-reg.rs:58:34
151139
|
152140
LL | asm!("", in("xmm0") foo, in("ymm0") bar);
153141
| -------------- ^^^^^^^^^^^^^^ register `ymm0`
154142
| |
155143
| register `xmm0`
156144

157145
error: register `ymm0` conflicts with register `xmm0`
158-
--> $DIR/bad-reg.rs:64:34
146+
--> $DIR/bad-reg.rs:60:34
159147
|
160148
LL | asm!("", in("xmm0") foo, out("ymm0") bar);
161149
| -------------- ^^^^^^^^^^^^^^^ register `ymm0`
162150
| |
163151
| register `xmm0`
164152
|
165153
help: use `lateout` instead of `out` to avoid conflict
166-
--> $DIR/bad-reg.rs:64:18
154+
--> $DIR/bad-reg.rs:60:18
167155
|
168156
LL | asm!("", in("xmm0") foo, out("ymm0") bar);
169157
| ^^^^^^^^^^^^^^
170158

171-
error: aborting due to 23 previous errors
159+
error: aborting due to 21 previous errors
172160

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// only-x86_64
2+
3+
#![feature(asm, avx512_target_feature)]
4+
5+
#[target_feature(enable = "avx")]
6+
unsafe fn foo() {
7+
let mut x = 1;
8+
let y = 2;
9+
asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
10+
assert_eq!(x, 3);
11+
}
12+
13+
unsafe fn bar() {
14+
let mut x = 1;
15+
let y = 2;
16+
asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
17+
//~^ ERROR: register class `ymm_reg` requires the `avx` target feature
18+
//~| ERROR: register class `ymm_reg` requires the `avx` target feature
19+
//~| ERROR: register class `ymm_reg` requires the `avx` target feature
20+
assert_eq!(x, 3);
21+
}
22+
23+
#[target_feature(enable = "avx512bw")]
24+
unsafe fn baz() {
25+
let x = 1;
26+
asm!("/* {0} */", in(kreg) x);
27+
}
28+
29+
unsafe fn baz2() {
30+
let x = 1;
31+
asm!("/* {0} */", in(kreg) x);
32+
//~^ ERROR: register class `kreg` requires at least one of the following target features: avx512bw, avx512f
33+
}
34+
35+
fn main() {
36+
unsafe {
37+
foo();
38+
bar();
39+
}
40+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: register class `ymm_reg` requires the `avx` target feature
2+
--> $DIR/target-feature-attr.rs:16:40
3+
|
4+
LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
5+
| ^^^^^^^^^^^^^
6+
7+
error: register class `ymm_reg` requires the `avx` target feature
8+
--> $DIR/target-feature-attr.rs:16:55
9+
|
10+
LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
11+
| ^^^^^^^^^^^^^
12+
13+
error: register class `ymm_reg` requires the `avx` target feature
14+
--> $DIR/target-feature-attr.rs:16:70
15+
|
16+
LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
17+
| ^^^^^^^^^^^^^^^^^^
18+
19+
error: register class `kreg` requires at least one of the following target features: avx512bw, avx512f
20+
--> $DIR/target-feature-attr.rs:31:23
21+
|
22+
LL | asm!("/* {0} */", in(kreg) x);
23+
| ^^^^^^^^^^
24+
25+
error: aborting due to 4 previous errors
26+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
WARN rustc_mir_build::thir::pattern::const_to_pat MIR const-checker found novel structural match violation. See #73448.

‎src/tools/compiletest/src/read2.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,77 @@
22
// Consider unify the read2() in libstd, cargo and this to prevent further code duplication.
33

44
pub use self::imp::read2;
5+
use std::io;
6+
use std::process::{Child, Output};
7+
8+
pub fn read2_abbreviated(mut child: Child) -> io::Result<Output> {
9+
use io::Write;
10+
use std::mem::replace;
11+
12+
const HEAD_LEN: usize = 160 * 1024;
13+
const TAIL_LEN: usize = 256 * 1024;
14+
15+
enum ProcOutput {
16+
Full(Vec<u8>),
17+
Abbreviated { head: Vec<u8>, skipped: usize, tail: Box<[u8]> },
18+
}
19+
20+
impl ProcOutput {
21+
fn extend(&mut self, data: &[u8]) {
22+
let new_self = match *self {
23+
ProcOutput::Full(ref mut bytes) => {
24+
bytes.extend_from_slice(data);
25+
let new_len = bytes.len();
26+
if new_len <= HEAD_LEN + TAIL_LEN {
27+
return;
28+
}
29+
let tail = bytes.split_off(new_len - TAIL_LEN).into_boxed_slice();
30+
let head = replace(bytes, Vec::new());
31+
let skipped = new_len - HEAD_LEN - TAIL_LEN;
32+
ProcOutput::Abbreviated { head, skipped, tail }
33+
}
34+
ProcOutput::Abbreviated { ref mut skipped, ref mut tail, .. } => {
35+
*skipped += data.len();
36+
if data.len() <= TAIL_LEN {
37+
tail[..data.len()].copy_from_slice(data);
38+
tail.rotate_left(data.len());
39+
} else {
40+
tail.copy_from_slice(&data[(data.len() - TAIL_LEN)..]);
41+
}
42+
return;
43+
}
44+
};
45+
*self = new_self;
46+
}
47+
48+
fn into_bytes(self) -> Vec<u8> {
49+
match self {
50+
ProcOutput::Full(bytes) => bytes,
51+
ProcOutput::Abbreviated { mut head, skipped, tail } => {
52+
write!(&mut head, "\n\n<<<<<< SKIPPED {} BYTES >>>>>>\n\n", skipped).unwrap();
53+
head.extend_from_slice(&tail);
54+
head
55+
}
56+
}
57+
}
58+
}
59+
60+
let mut stdout = ProcOutput::Full(Vec::new());
61+
let mut stderr = ProcOutput::Full(Vec::new());
62+
63+
drop(child.stdin.take());
64+
read2(
65+
child.stdout.take().unwrap(),
66+
child.stderr.take().unwrap(),
67+
&mut |is_stdout, data, _| {
68+
if is_stdout { &mut stdout } else { &mut stderr }.extend(data);
69+
data.clear();
70+
},
71+
)?;
72+
let status = child.wait()?;
73+
74+
Ok(Output { status, stdout: stdout.into_bytes(), stderr: stderr.into_bytes() })
75+
}
576

677
#[cfg(not(any(unix, windows)))]
778
mod imp {

‎src/tools/compiletest/src/runtest.rs

Lines changed: 2 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::compute_diff::{write_diff, write_filtered_diff};
1212
use crate::errors::{self, Error, ErrorKind};
1313
use crate::header::TestProps;
1414
use crate::json;
15+
use crate::read2::read2_abbreviated;
1516
use crate::util::get_pointer_width;
1617
use crate::util::{logv, PathBufExt};
1718
use crate::ColorConfig;
@@ -27,7 +28,7 @@ use std::hash::{Hash, Hasher};
2728
use std::io::prelude::*;
2829
use std::io::{self, BufReader};
2930
use std::path::{Path, PathBuf};
30-
use std::process::{Child, Command, ExitStatus, Output, Stdio};
31+
use std::process::{Command, ExitStatus, Output, Stdio};
3132
use std::str;
3233

3334
use glob::glob;
@@ -3820,72 +3821,3 @@ enum AllowUnused {
38203821
Yes,
38213822
No,
38223823
}
3823-
3824-
fn read2_abbreviated(mut child: Child) -> io::Result<Output> {
3825-
use crate::read2::read2;
3826-
use std::mem::replace;
3827-
3828-
const HEAD_LEN: usize = 160 * 1024;
3829-
const TAIL_LEN: usize = 256 * 1024;
3830-
3831-
enum ProcOutput {
3832-
Full(Vec<u8>),
3833-
Abbreviated { head: Vec<u8>, skipped: usize, tail: Box<[u8]> },
3834-
}
3835-
3836-
impl ProcOutput {
3837-
fn extend(&mut self, data: &[u8]) {
3838-
let new_self = match *self {
3839-
ProcOutput::Full(ref mut bytes) => {
3840-
bytes.extend_from_slice(data);
3841-
let new_len = bytes.len();
3842-
if new_len <= HEAD_LEN + TAIL_LEN {
3843-
return;
3844-
}
3845-
let tail = bytes.split_off(new_len - TAIL_LEN).into_boxed_slice();
3846-
let head = replace(bytes, Vec::new());
3847-
let skipped = new_len - HEAD_LEN - TAIL_LEN;
3848-
ProcOutput::Abbreviated { head, skipped, tail }
3849-
}
3850-
ProcOutput::Abbreviated { ref mut skipped, ref mut tail, .. } => {
3851-
*skipped += data.len();
3852-
if data.len() <= TAIL_LEN {
3853-
tail[..data.len()].copy_from_slice(data);
3854-
tail.rotate_left(data.len());
3855-
} else {
3856-
tail.copy_from_slice(&data[(data.len() - TAIL_LEN)..]);
3857-
}
3858-
return;
3859-
}
3860-
};
3861-
*self = new_self;
3862-
}
3863-
3864-
fn into_bytes(self) -> Vec<u8> {
3865-
match self {
3866-
ProcOutput::Full(bytes) => bytes,
3867-
ProcOutput::Abbreviated { mut head, skipped, tail } => {
3868-
write!(&mut head, "\n\n<<<<<< SKIPPED {} BYTES >>>>>>\n\n", skipped).unwrap();
3869-
head.extend_from_slice(&tail);
3870-
head
3871-
}
3872-
}
3873-
}
3874-
}
3875-
3876-
let mut stdout = ProcOutput::Full(Vec::new());
3877-
let mut stderr = ProcOutput::Full(Vec::new());
3878-
3879-
drop(child.stdin.take());
3880-
read2(
3881-
child.stdout.take().unwrap(),
3882-
child.stderr.take().unwrap(),
3883-
&mut |is_stdout, data, _| {
3884-
if is_stdout { &mut stdout } else { &mut stderr }.extend(data);
3885-
data.clear();
3886-
},
3887-
)?;
3888-
let status = child.wait()?;
3889-
3890-
Ok(Output { status, stdout: stdout.into_bytes(), stderr: stderr.into_bytes() })
3891-
}

0 commit comments

Comments
 (0)
Please sign in to comment.