From d4031d092d0dcc3140af8fe0aa009cf98e701009 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Mon, 6 Sep 2021 23:25:38 +0200 Subject: [PATCH 01/18] String.split_terminator: Add an example when using a slice of chars --- library/core/src/str/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index ca4e2e6b7f351..495f98cfc3235 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -1354,6 +1354,9 @@ impl str { /// /// let v: Vec<&str> = "A..B..".split_terminator(".").collect(); /// assert_eq!(v, ["A", "", "B", ""]); + /// + /// let v: Vec<&str> = "A.B:C.D".split_terminator(&['.', ':'][..]).collect(); + /// assert_eq!(v, ["A", "B", "C", "D"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -1397,6 +1400,9 @@ impl str { /// /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect(); /// assert_eq!(v, ["", "B", "", "A"]); + /// + /// let v: Vec<&str> = "A.B:C.D".rsplit_terminator(&['.', ':'][..]).collect(); + /// assert_eq!(v, ["D", "C", "B", "A"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] From 6189d0a116c599804656d7befc3d4d35a49a8681 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 6 Oct 2021 09:34:39 -0700 Subject: [PATCH 02/18] Fix stabilization version for `bindings_after_at` According to the release notes and its PR milestone, it was stabilized in 1.56.0. --- compiler/rustc_feature/src/accepted.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 2ef0e0f6b1e56..55ec3703df8f8 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -288,7 +288,7 @@ declare_features! ( (accepted, member_constraints, "1.54.0", Some(61997), None), /// Allows bindings in the subpattern of a binding pattern. /// For example, you can write `x @ Some(y)`. - (accepted, bindings_after_at, "1.54.0", Some(65490), None), + (accepted, bindings_after_at, "1.56.0", Some(65490), None), /// Allows calling `transmute` in const fn (accepted, const_fn_transmute, "1.56.0", Some(53605), None), /// Allows accessing fields of unions inside `const` functions. From e7f04857efc4ebc369e588d194e5288ef57752e7 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Thu, 7 Oct 2021 09:17:57 -0700 Subject: [PATCH 03/18] rustc_driver: Enable the `WARN` log level by default This commit changes the `tracing_subscriber` initialization in `rustc_driver` so that the `WARN` verbosity level is enabled by default when the `RUSTC_LOG` env variable is empty. If the `RUSTC_LOG` env variable is set, the filter string in the environment variable is honored, instead. Fixes #76824 Closes #89623 cc @eddyb, @oli-obk --- compiler/rustc_driver/src/lib.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index ab7ee03b643f8..c658bf322e518 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1253,12 +1253,16 @@ pub fn init_rustc_env_logger() { /// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var /// other than `RUSTC_LOG`. pub fn init_env_logger(env: &str) { - // Don't register a dispatcher if there's no filter to print anything - match std::env::var(env) { - Err(_) => return, - Ok(s) if s.is_empty() => return, - Ok(_) => {} - } + use tracing_subscriber::{ + filter::{self, EnvFilter, LevelFilter}, + layer::SubscriberExt, + }; + + let filter = match std::env::var(env) { + Ok(env) => EnvFilter::from_env(env), + _ => EnvFilter::default().add_directive(filter::Directive::from(LevelFilter: WARN)), + }; + let color_logs = match std::env::var(String::from(env) + "_COLOR") { Ok(value) => match value.as_ref() { "always" => true, @@ -1278,7 +1282,7 @@ pub fn init_env_logger(env: &str) { "non-Unicode log color value: expected one of always, never, or auto", ), }; - let filter = tracing_subscriber::EnvFilter::from_env(env); + let layer = tracing_tree::HierarchicalLayer::default() .with_writer(io::stderr) .with_indent_lines(true) @@ -1288,7 +1292,6 @@ pub fn init_env_logger(env: &str) { #[cfg(parallel_compiler)] let layer = layer.with_thread_ids(true).with_thread_names(true); - use tracing_subscriber::layer::SubscriberExt; let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); tracing::subscriber::set_global_default(subscriber).unwrap(); } From eb67bf936829406ca58f9aa12169e05bdd3b2d2e Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Thu, 7 Oct 2021 09:52:51 -0700 Subject: [PATCH 04/18] Update compiler/rustc_driver/src/lib.rs Co-authored-by: Joshua Nelson --- compiler/rustc_driver/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index c658bf322e518..05c7e11cbc29a 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1260,7 +1260,7 @@ pub fn init_env_logger(env: &str) { let filter = match std::env::var(env) { Ok(env) => EnvFilter::from_env(env), - _ => EnvFilter::default().add_directive(filter::Directive::from(LevelFilter: WARN)), + _ => EnvFilter::default().add_directive(filter::Directive::from(LevelFilter::WARN)), }; let color_logs = match std::env::var(String::from(env) + "_COLOR") { From 01803025d2afd7b6869878734fa411e8c659f68b Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Thu, 7 Oct 2021 10:45:39 -0700 Subject: [PATCH 05/18] demote `rustc_peek` traces look not user-facing Signed-off-by: Eliza Weisman --- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 29ffed9934421..214d6376c7ffc 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -289,7 +289,7 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeMutBorrowedLocals<'_, 'tcx> { flow_state: &BitSet, call: PeekCall, ) { - warn!("peek_at: place={:?}", place); + info!("peek_at: place={:?}", place); let local = if let Some(l) = place.as_local() { l } else { @@ -311,7 +311,7 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeLiveLocals { flow_state: &BitSet, call: PeekCall, ) { - warn!("peek_at: place={:?}", place); + info!("peek_at: place={:?}", place); let local = if let Some(l) = place.as_local() { l } else { From 928c787fcee7a15f20da3407d479b69da601644a Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Thu, 7 Oct 2021 10:46:47 -0700 Subject: [PATCH 06/18] make them structured while i'm here Signed-off-by: Eliza Weisman --- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 214d6376c7ffc..ee8fca961f6d0 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -289,7 +289,7 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeMutBorrowedLocals<'_, 'tcx> { flow_state: &BitSet, call: PeekCall, ) { - info!("peek_at: place={:?}", place); + info!(?place, "peek_at",); let local = if let Some(l) = place.as_local() { l } else { @@ -311,7 +311,7 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeLiveLocals { flow_state: &BitSet, call: PeekCall, ) { - info!("peek_at: place={:?}", place); + info!(?place, "peek_at"); let local = if let Some(l) = place.as_local() { l } else { From e00eac8b9c4af0bd6baa4b645773fdfa86829fcb Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Thu, 7 Oct 2021 10:48:48 -0700 Subject: [PATCH 07/18] use structured fields in some existing warnings Signed-off-by: Eliza Weisman --- compiler/rustc_codegen_ssa/src/back/link.rs | 9 ++++----- compiler/rustc_errors/src/emitter.rs | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index ed15b46487240..19eff1a3a3ca4 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -844,8 +844,8 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( if out.contains(msg_segv) || out.contains(msg_bus) { warn!( "looks like the linker segfaulted when we tried to call it, \ - automatically retrying again. cmd = {:?}, out = {}.", - cmd, out, + automatically retrying again", + ?cmd, %out, ); continue; } @@ -853,9 +853,8 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( if is_illegal_instruction(&output.status) { warn!( "looks like the linker hit an illegal instruction when we \ - tried to call it, automatically retrying again. cmd = {:?}, ]\ - out = {}, status = {}.", - cmd, out, output.status, + tried to call it, automatically retrying again." + ?cmd, %out, status = %output.status, ); continue; } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 29f352ae58559..778d58eeadcf0 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2308,7 +2308,7 @@ pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool { let found = match sm.span_to_snippet(sp) { Ok(snippet) => snippet, Err(e) => { - warn!("Invalid span {:?}. Err={:?}", sp, e); + warn!(error = ?e, "Invalid span {:?}", sp); return false; } }; From b6f09a19b2345a6a898d176570496dea44b06aac Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Thu, 7 Oct 2021 11:29:47 -0700 Subject: [PATCH 08/18] comma-related changes Signed-off-by: Eliza Weisman --- compiler/rustc_codegen_ssa/src/back/link.rs | 2 +- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 19eff1a3a3ca4..b5429064324de 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -853,7 +853,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( if is_illegal_instruction(&output.status) { warn!( "looks like the linker hit an illegal instruction when we \ - tried to call it, automatically retrying again." + tried to call it, automatically retrying again.", ?cmd, %out, status = %output.status, ); continue; diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index ee8fca961f6d0..c0bf4b659aa96 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -289,7 +289,7 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeMutBorrowedLocals<'_, 'tcx> { flow_state: &BitSet, call: PeekCall, ) { - info!(?place, "peek_at",); + info!(?place, "peek_at"); let local = if let Some(l) = place.as_local() { l } else { From 0e79545c306ca173fc406b61a81ea4e14400d293 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Thu, 7 Oct 2021 12:03:15 -0700 Subject: [PATCH 09/18] lol i forgot the syntax for my own crate's macros T_____T Signed-off-by: Eliza Weisman --- compiler/rustc_codegen_ssa/src/back/link.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index b5429064324de..fd59bdca133d8 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -843,18 +843,18 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( let msg_bus = "clang: error: unable to execute command: Bus error: 10"; if out.contains(msg_segv) || out.contains(msg_bus) { warn!( + ?cmd, %out, "looks like the linker segfaulted when we tried to call it, \ automatically retrying again", - ?cmd, %out, ); continue; } if is_illegal_instruction(&output.status) { warn!( + ?cmd, %out, status = %output.status, "looks like the linker hit an illegal instruction when we \ tried to call it, automatically retrying again.", - ?cmd, %out, status = %output.status, ); continue; } From 271da7d8bc9f0f5ca98cdfeb999872a7a0b6cf74 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Thu, 7 Oct 2021 15:42:18 -0400 Subject: [PATCH 10/18] make #[target_feature] work with `asm` register classes --- compiler/rustc_ast_lowering/src/asm.rs | 64 +-------- compiler/rustc_hir/src/hir.rs | 7 + compiler/rustc_passes/src/intrinsicck.rs | 136 +++++++++++++++--- src/test/ui/asm/x86_64/bad-reg.rs | 4 - src/test/ui/asm/x86_64/bad-reg.stderr | 48 +++---- src/test/ui/asm/x86_64/target-feature-attr.rs | 40 ++++++ .../ui/asm/x86_64/target-feature-attr.stderr | 26 ++++ 7 files changed, 213 insertions(+), 112 deletions(-) create mode 100644 src/test/ui/asm/x86_64/target-feature-attr.rs create mode 100644 src/test/ui/asm/x86_64/target-feature-attr.stderr diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 7165b3bcb9fc1..957b14f348729 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -202,39 +202,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut used_input_regs = FxHashMap::default(); let mut used_output_regs = FxHashMap::default(); - let mut required_features: Vec<&str> = vec![]; + for (idx, &(ref op, op_sp)) in operands.iter().enumerate() { if let Some(reg) = op.reg() { - // Make sure we don't accidentally carry features from the - // previous iteration. - required_features.clear(); - let reg_class = reg.reg_class(); if reg_class == asm::InlineAsmRegClass::Err { continue; } - // We ignore target feature requirements for clobbers: if the - // feature is disabled then the compiler doesn't care what we - // do with the registers. - // - // Note that this is only possible for explicit register - // operands, which cannot be used in the asm string. - let is_clobber = matches!( - op, - hir::InlineAsmOperand::Out { - reg: asm::InlineAsmRegOrRegClass::Reg(_), - late: _, - expr: None - } - ); - // Some register classes can only be used as clobbers. This // means that we disallow passing a value in/out of the asm and // require that the operand name an explicit register, not a // register class. if reg_class.is_clobber_only(asm_arch.unwrap()) - && !(is_clobber && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_))) + && !(op.is_clobber() && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_))) { let msg = format!( "register class `{}` can only be used as a clobber, \ @@ -245,47 +226,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { continue; } - if !is_clobber { - // Validate register classes against currently enabled target - // features. We check that at least one type is available for - // the current target. - for &(_, feature) in reg_class.supported_types(asm_arch.unwrap()) { - if let Some(feature) = feature { - if self.sess.target_features.contains(&Symbol::intern(feature)) { - required_features.clear(); - break; - } else { - required_features.push(feature); - } - } else { - required_features.clear(); - break; - } - } - // We are sorting primitive strs here and can use unstable sort here - required_features.sort_unstable(); - required_features.dedup(); - match &required_features[..] { - [] => {} - [feature] => { - let msg = format!( - "register class `{}` requires the `{}` target feature", - reg_class.name(), - feature - ); - sess.struct_span_err(op_sp, &msg).emit(); - } - features => { - let msg = format!( - "register class `{}` requires at least one target feature: {}", - reg_class.name(), - features.join(", ") - ); - sess.struct_span_err(op_sp, &msg).emit(); - } - } - } - // Check for conflicts between explicit register operands. if let asm::InlineAsmRegOrRegClass::Reg(reg) = reg { let (input, output) = match op { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index fdd52bd74952f..5264f7cc32612 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2293,6 +2293,13 @@ impl<'hir> InlineAsmOperand<'hir> { Self::Const { .. } | Self::Sym { .. } => None, } } + + pub fn is_clobber(&self) -> bool { + matches!( + self, + InlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(_), late: _, expr: None } + ) + } } #[derive(Debug, HashStable_Generic)] diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_passes/src/intrinsicck.rs index 96e9a40df3685..008b856ebf2fa 100644 --- a/compiler/rustc_passes/src/intrinsicck.rs +++ b/compiler/rustc_passes/src/intrinsicck.rs @@ -141,6 +141,7 @@ impl ExprVisitor<'tcx> { template: &[InlineAsmTemplatePiece], is_input: bool, tied_input: Option<(&hir::Expr<'tcx>, Option)>, + target_features: &[Symbol], ) -> Option { // Check the type against the allowed types for inline asm. let ty = self.typeck_results.expr_ty_adjusted(expr); @@ -283,17 +284,20 @@ impl ExprVisitor<'tcx> { }; // Check whether the selected type requires a target feature. Note that - // this is different from the feature check we did earlier in AST - // lowering. While AST lowering checked that this register class is - // usable at all with the currently enabled features, some types may - // only be usable with a register class when a certain feature is - // enabled. We check this here since it depends on the results of typeck. + // this is different from the feature check we did earlier. While the + // previous check checked that this register class is usable at all + // with the currently enabled features, some types may only be usable + // with a register class when a certain feature is enabled. We check + // this here since it depends on the results of typeck. // // Also note that this check isn't run when the operand type is never - // (!). In that case we still need the earlier check in AST lowering to - // verify that the register class is usable at all. + // (!). In that case we still need the earlier check to verify that the + // register class is usable at all. if let Some(feature) = feature { - if !self.tcx.sess.target_features.contains(&Symbol::intern(feature)) { + let feat_sym = Symbol::intern(feature); + if !self.tcx.sess.target_features.contains(&feat_sym) + && !target_features.contains(&feat_sym) + { let msg = &format!("`{}` target feature is not enabled", feature); let mut err = self.tcx.sess.struct_span_err(expr.span, msg); err.note(&format!( @@ -349,23 +353,122 @@ impl ExprVisitor<'tcx> { Some(asm_ty) } - fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) { - for (idx, (op, _)) in asm.operands.iter().enumerate() { + fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, hir_id: hir::HirId) { + let hir = self.tcx.hir(); + let enclosing_id = hir.enclosing_body_owner(hir_id); + let enclosing_def_id = hir.local_def_id(enclosing_id).to_def_id(); + let attrs = self.tcx.codegen_fn_attrs(enclosing_def_id); + for (idx, (op, op_sp)) in asm.operands.iter().enumerate() { + // Validate register classes against currently enabled target + // features. We check that at least one type is available for + // the enabled features. + // + // We ignore target feature requirements for clobbers: if the + // feature is disabled then the compiler doesn't care what we + // do with the registers. + // + // Note that this is only possible for explicit register + // operands, which cannot be used in the asm string. + if let Some(reg) = op.reg() { + if !op.is_clobber() { + let mut missing_required_features = vec![]; + let reg_class = reg.reg_class(); + for &(_, feature) in reg_class.supported_types(self.tcx.sess.asm_arch.unwrap()) + { + match feature { + Some(feature) => { + let feat_sym = Symbol::intern(feature); + if self.tcx.sess.target_features.contains(&feat_sym) + || attrs.target_features.contains(&feat_sym) + { + missing_required_features.clear(); + break; + } else { + missing_required_features.push(feature); + } + } + None => { + missing_required_features.clear(); + break; + } + } + } + + // We are sorting primitive strs here and can use unstable sort here + missing_required_features.sort_unstable(); + missing_required_features.dedup(); + match &missing_required_features[..] { + [] => {} + [feature] => { + let msg = format!( + "register class `{}` requires the `{}` target feature", + reg_class.name(), + feature + ); + self.tcx.sess.struct_span_err(*op_sp, &msg).emit(); + // register isn't enabled, don't do more checks + continue; + } + features => { + let msg = format!( + "register class `{}` requires at least one of the following target features: {}", + reg_class.name(), + features.join(", ") + ); + self.tcx.sess.struct_span_err(*op_sp, &msg).emit(); + // register isn't enabled, don't do more checks + continue; + } + } + } + } + match *op { hir::InlineAsmOperand::In { reg, ref expr } => { - self.check_asm_operand_type(idx, reg, expr, asm.template, true, None); + self.check_asm_operand_type( + idx, + reg, + expr, + asm.template, + true, + None, + &attrs.target_features, + ); } hir::InlineAsmOperand::Out { reg, late: _, ref expr } => { if let Some(expr) = expr { - self.check_asm_operand_type(idx, reg, expr, asm.template, false, None); + self.check_asm_operand_type( + idx, + reg, + expr, + asm.template, + false, + None, + &attrs.target_features, + ); } } hir::InlineAsmOperand::InOut { reg, late: _, ref expr } => { - self.check_asm_operand_type(idx, reg, expr, asm.template, false, None); + self.check_asm_operand_type( + idx, + reg, + expr, + asm.template, + false, + None, + &attrs.target_features, + ); } hir::InlineAsmOperand::SplitInOut { reg, late: _, ref in_expr, ref out_expr } => { - let in_ty = - self.check_asm_operand_type(idx, reg, in_expr, asm.template, true, None); + let in_ty = self.check_asm_operand_type( + idx, + reg, + in_expr, + asm.template, + true, + None, + &attrs.target_features, + ); if let Some(out_expr) = out_expr { self.check_asm_operand_type( idx, @@ -374,6 +477,7 @@ impl ExprVisitor<'tcx> { asm.template, false, Some((in_expr, in_ty)), + &attrs.target_features, ); } } @@ -422,7 +526,7 @@ impl Visitor<'tcx> for ExprVisitor<'tcx> { } } - hir::ExprKind::InlineAsm(asm) => self.check_asm(asm), + hir::ExprKind::InlineAsm(asm) => self.check_asm(asm, expr.hir_id), _ => {} } diff --git a/src/test/ui/asm/x86_64/bad-reg.rs b/src/test/ui/asm/x86_64/bad-reg.rs index 06af08fab80f9..91d0f8c33f979 100644 --- a/src/test/ui/asm/x86_64/bad-reg.rs +++ b/src/test/ui/asm/x86_64/bad-reg.rs @@ -21,10 +21,6 @@ fn main() { //~^ ERROR asm template modifiers are not allowed for `const` arguments asm!("{:a}", sym main); //~^ ERROR asm template modifiers are not allowed for `sym` arguments - asm!("{}", in(zmm_reg) foo); - //~^ ERROR register class `zmm_reg` requires the `avx512f` target feature - asm!("", in("zmm0") foo); - //~^ ERROR register class `zmm_reg` requires the `avx512f` target feature asm!("", in("ebp") foo); //~^ ERROR invalid register `ebp`: the frame pointer cannot be used as an operand asm!("", in("rsp") foo); diff --git a/src/test/ui/asm/x86_64/bad-reg.stderr b/src/test/ui/asm/x86_64/bad-reg.stderr index 14740bf62f8e5..102a17e981570 100644 --- a/src/test/ui/asm/x86_64/bad-reg.stderr +++ b/src/test/ui/asm/x86_64/bad-reg.stderr @@ -46,86 +46,74 @@ LL | asm!("{:a}", sym main); | | | template modifier -error: register class `zmm_reg` requires the `avx512f` target feature - --> $DIR/bad-reg.rs:24:20 - | -LL | asm!("{}", in(zmm_reg) foo); - | ^^^^^^^^^^^^^^^ - -error: register class `zmm_reg` requires the `avx512f` target feature - --> $DIR/bad-reg.rs:26:18 - | -LL | asm!("", in("zmm0") foo); - | ^^^^^^^^^^^^^^ - error: invalid register `ebp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:24:18 | LL | asm!("", in("ebp") foo); | ^^^^^^^^^^^^^ error: invalid register `rsp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:26:18 | LL | asm!("", in("rsp") foo); | ^^^^^^^^^^^^^ error: invalid register `ip`: the instruction pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:28:18 | LL | asm!("", in("ip") foo); | ^^^^^^^^^^^^ error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:30:18 | LL | asm!("", in("k0") foo); | ^^^^^^^^^^^^ error: invalid register `ah`: high byte registers cannot be used as an operand on x86_64 - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:32:18 | LL | asm!("", in("ah") foo); | ^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:39:18 + --> $DIR/bad-reg.rs:35:18 | LL | asm!("", in("st(2)") foo); | ^^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:41:18 + --> $DIR/bad-reg.rs:37:18 | LL | asm!("", in("mm0") foo); | ^^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:45:20 + --> $DIR/bad-reg.rs:41:20 | LL | asm!("{}", in(x87_reg) foo); | ^^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:47:20 + --> $DIR/bad-reg.rs:43:20 | LL | asm!("{}", in(mmx_reg) foo); | ^^^^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:49:20 + --> $DIR/bad-reg.rs:45:20 | LL | asm!("{}", out(x87_reg) _); | ^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:51:20 + --> $DIR/bad-reg.rs:47:20 | LL | asm!("{}", out(mmx_reg) _); | ^^^^^^^^^^^^^^ error: register `al` conflicts with register `ax` - --> $DIR/bad-reg.rs:57:33 + --> $DIR/bad-reg.rs:53:33 | LL | asm!("", in("eax") foo, in("al") bar); | ------------- ^^^^^^^^^^^^ register `al` @@ -133,7 +121,7 @@ LL | asm!("", in("eax") foo, in("al") bar); | register `ax` error: register `ax` conflicts with register `ax` - --> $DIR/bad-reg.rs:59:33 + --> $DIR/bad-reg.rs:55:33 | LL | asm!("", in("rax") foo, out("rax") bar); | ------------- ^^^^^^^^^^^^^^ register `ax` @@ -141,13 +129,13 @@ LL | asm!("", in("rax") foo, out("rax") bar); | register `ax` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:59:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", in("rax") foo, out("rax") bar); | ^^^^^^^^^^^^^ error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:62:34 + --> $DIR/bad-reg.rs:58:34 | LL | asm!("", in("xmm0") foo, in("ymm0") bar); | -------------- ^^^^^^^^^^^^^^ register `ymm0` @@ -155,7 +143,7 @@ LL | asm!("", in("xmm0") foo, in("ymm0") bar); | register `xmm0` error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:64:34 + --> $DIR/bad-reg.rs:60:34 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | -------------- ^^^^^^^^^^^^^^^ register `ymm0` @@ -163,10 +151,10 @@ LL | asm!("", in("xmm0") foo, out("ymm0") bar); | register `xmm0` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:64:18 + --> $DIR/bad-reg.rs:60:18 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | ^^^^^^^^^^^^^^ -error: aborting due to 23 previous errors +error: aborting due to 21 previous errors diff --git a/src/test/ui/asm/x86_64/target-feature-attr.rs b/src/test/ui/asm/x86_64/target-feature-attr.rs new file mode 100644 index 0000000000000..4f82cd8aab9d0 --- /dev/null +++ b/src/test/ui/asm/x86_64/target-feature-attr.rs @@ -0,0 +1,40 @@ +// only-x86_64 + +#![feature(asm, avx512_target_feature)] + +#[target_feature(enable = "avx")] +unsafe fn foo() { + let mut x = 1; + let y = 2; + asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); + assert_eq!(x, 3); +} + +unsafe fn bar() { + let mut x = 1; + let y = 2; + asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); + //~^ ERROR: register class `ymm_reg` requires the `avx` target feature + //~| ERROR: register class `ymm_reg` requires the `avx` target feature + //~| ERROR: register class `ymm_reg` requires the `avx` target feature + assert_eq!(x, 3); +} + +#[target_feature(enable = "avx512bw")] +unsafe fn baz() { + let x = 1; + asm!("/* {0} */", in(kreg) x); +} + +unsafe fn baz2() { + let x = 1; + asm!("/* {0} */", in(kreg) x); + //~^ ERROR: register class `kreg` requires at least one of the following target features: avx512bw, avx512f +} + +fn main() { + unsafe { + foo(); + bar(); + } +} diff --git a/src/test/ui/asm/x86_64/target-feature-attr.stderr b/src/test/ui/asm/x86_64/target-feature-attr.stderr new file mode 100644 index 0000000000000..295c8a97ed3bc --- /dev/null +++ b/src/test/ui/asm/x86_64/target-feature-attr.stderr @@ -0,0 +1,26 @@ +error: register class `ymm_reg` requires the `avx` target feature + --> $DIR/target-feature-attr.rs:16:40 + | +LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); + | ^^^^^^^^^^^^^ + +error: register class `ymm_reg` requires the `avx` target feature + --> $DIR/target-feature-attr.rs:16:55 + | +LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); + | ^^^^^^^^^^^^^ + +error: register class `ymm_reg` requires the `avx` target feature + --> $DIR/target-feature-attr.rs:16:70 + | +LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); + | ^^^^^^^^^^^^^^^^^^ + +error: register class `kreg` requires at least one of the following target features: avx512bw, avx512f + --> $DIR/target-feature-attr.rs:31:23 + | +LL | asm!("/* {0} */", in(kreg) x); + | ^^^^^^^^^^ + +error: aborting due to 4 previous errors + From 84fc5db59b3a291090fe0cc9d1b91f463664d657 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 8 Oct 2021 10:56:08 -0700 Subject: [PATCH 11/18] bless warnings Signed-off-by: Eliza Weisman --- src/test/ui/consts/const_in_pattern/issue-73431.stderr | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/test/ui/consts/const_in_pattern/issue-73431.stderr diff --git a/src/test/ui/consts/const_in_pattern/issue-73431.stderr b/src/test/ui/consts/const_in_pattern/issue-73431.stderr new file mode 100644 index 0000000000000..c82dea4aa50df --- /dev/null +++ b/src/test/ui/consts/const_in_pattern/issue-73431.stderr @@ -0,0 +1 @@ +WARN rustc_mir_build::thir::pattern::const_to_pat MIR const-checker found novel structural match violation. See #73448. From 82c974dab5cd69862528724a36a954d9699b3d98 Mon Sep 17 00:00:00 2001 From: Marcelo Diop-Gonzalez Date: Fri, 8 Oct 2021 15:29:04 -0400 Subject: [PATCH 12/18] Fix minor std::thread documentation typo callers of spawn_unchecked() need to make sure that the thread not outlive references in the passed closure, not the other way around. --- library/std/src/thread/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 707a55b625814..7d404aff30e07 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -412,9 +412,9 @@ impl Builder { /// /// # Safety /// - /// The caller has to ensure that no references in the supplied thread closure - /// or its return type can outlive the spawned thread's lifetime. This can be - /// guaranteed in two ways: + /// The caller has to ensure that the spawned thread does not outlive any + /// references in the supplied thread closure and its return type. + /// This can be guaranteed in two ways: /// /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced /// data is dropped From 4a565e511001f8fe192a3b847a993cc7b40ccb8f Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Fri, 8 Oct 2021 16:50:35 -0400 Subject: [PATCH 13/18] Fix asm docs typo --- src/doc/unstable-book/src/library-features/asm.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md index ccaf6e8733e0c..a2afa88028fea 100644 --- a/src/doc/unstable-book/src/library-features/asm.md +++ b/src/doc/unstable-book/src/library-features/asm.md @@ -613,8 +613,8 @@ Each register class has constraints on which value types they can be used with. | x86 | `xmm_reg` | `sse` | `i32`, `f32`, `i64`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | | x86 | `ymm_reg` | `avx` | `i32`, `f32`, `i64`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2`
`i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` | | x86 | `zmm_reg` | `avx512f` | `i32`, `f32`, `i64`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2`
`i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4`
`i8x64`, `i16x32`, `i32x16`, `i64x8`, `f32x16`, `f64x8` | -| x86 | `kreg` | `axv512f` | `i8`, `i16` | -| x86 | `kreg` | `axv512bw` | `i32`, `i64` | +| x86 | `kreg` | `avx512f` | `i8`, `i16` | +| x86 | `kreg` | `avx512bw` | `i32`, `i64` | | x86 | `mmx_reg` | N/A | Only clobbers | | x86 | `x87_reg` | N/A | Only clobbers | | AArch64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | From 8a4085d370a5ca6cd97887d28871ab6aa8f7fd64 Mon Sep 17 00:00:00 2001 From: Nicholas-Baron Date: Fri, 8 Oct 2021 15:12:21 -0700 Subject: [PATCH 14/18] Move read2_abbreviated function into read2.rs --- src/tools/compiletest/src/read2.rs | 71 +++++++++++++++++++++++++++ src/tools/compiletest/src/runtest.rs | 72 +--------------------------- 2 files changed, 73 insertions(+), 70 deletions(-) diff --git a/src/tools/compiletest/src/read2.rs b/src/tools/compiletest/src/read2.rs index 30a922057eb20..897b9dd400793 100644 --- a/src/tools/compiletest/src/read2.rs +++ b/src/tools/compiletest/src/read2.rs @@ -2,6 +2,77 @@ // Consider unify the read2() in libstd, cargo and this to prevent further code duplication. pub use self::imp::read2; +use std::io; +use std::process::{Child, Output}; + +pub fn read2_abbreviated(mut child: Child) -> io::Result { + use io::Write; + use std::mem::replace; + + const HEAD_LEN: usize = 160 * 1024; + const TAIL_LEN: usize = 256 * 1024; + + enum ProcOutput { + Full(Vec), + Abbreviated { head: Vec, skipped: usize, tail: Box<[u8]> }, + } + + impl ProcOutput { + fn extend(&mut self, data: &[u8]) { + let new_self = match *self { + ProcOutput::Full(ref mut bytes) => { + bytes.extend_from_slice(data); + let new_len = bytes.len(); + if new_len <= HEAD_LEN + TAIL_LEN { + return; + } + let tail = bytes.split_off(new_len - TAIL_LEN).into_boxed_slice(); + let head = replace(bytes, Vec::new()); + let skipped = new_len - HEAD_LEN - TAIL_LEN; + ProcOutput::Abbreviated { head, skipped, tail } + } + ProcOutput::Abbreviated { ref mut skipped, ref mut tail, .. } => { + *skipped += data.len(); + if data.len() <= TAIL_LEN { + tail[..data.len()].copy_from_slice(data); + tail.rotate_left(data.len()); + } else { + tail.copy_from_slice(&data[(data.len() - TAIL_LEN)..]); + } + return; + } + }; + *self = new_self; + } + + fn into_bytes(self) -> Vec { + match self { + ProcOutput::Full(bytes) => bytes, + ProcOutput::Abbreviated { mut head, skipped, tail } => { + write!(&mut head, "\n\n<<<<<< SKIPPED {} BYTES >>>>>>\n\n", skipped).unwrap(); + head.extend_from_slice(&tail); + head + } + } + } + } + + let mut stdout = ProcOutput::Full(Vec::new()); + let mut stderr = ProcOutput::Full(Vec::new()); + + drop(child.stdin.take()); + read2( + child.stdout.take().unwrap(), + child.stderr.take().unwrap(), + &mut |is_stdout, data, _| { + if is_stdout { &mut stdout } else { &mut stderr }.extend(data); + data.clear(); + }, + )?; + let status = child.wait()?; + + Ok(Output { status, stdout: stdout.into_bytes(), stderr: stderr.into_bytes() }) +} #[cfg(not(any(unix, windows)))] mod imp { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 0821e279d2485..934839bbd605b 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -12,6 +12,7 @@ use crate::compute_diff::{write_diff, write_filtered_diff}; use crate::errors::{self, Error, ErrorKind}; use crate::header::TestProps; use crate::json; +use crate::read2::read2_abbreviated; use crate::util::get_pointer_width; use crate::util::{logv, PathBufExt}; use crate::ColorConfig; @@ -27,7 +28,7 @@ use std::hash::{Hash, Hasher}; use std::io::prelude::*; use std::io::{self, BufReader}; use std::path::{Path, PathBuf}; -use std::process::{Child, Command, ExitStatus, Output, Stdio}; +use std::process::{Command, ExitStatus, Output, Stdio}; use std::str; use glob::glob; @@ -3820,72 +3821,3 @@ enum AllowUnused { Yes, No, } - -fn read2_abbreviated(mut child: Child) -> io::Result { - use crate::read2::read2; - use std::mem::replace; - - const HEAD_LEN: usize = 160 * 1024; - const TAIL_LEN: usize = 256 * 1024; - - enum ProcOutput { - Full(Vec), - Abbreviated { head: Vec, skipped: usize, tail: Box<[u8]> }, - } - - impl ProcOutput { - fn extend(&mut self, data: &[u8]) { - let new_self = match *self { - ProcOutput::Full(ref mut bytes) => { - bytes.extend_from_slice(data); - let new_len = bytes.len(); - if new_len <= HEAD_LEN + TAIL_LEN { - return; - } - let tail = bytes.split_off(new_len - TAIL_LEN).into_boxed_slice(); - let head = replace(bytes, Vec::new()); - let skipped = new_len - HEAD_LEN - TAIL_LEN; - ProcOutput::Abbreviated { head, skipped, tail } - } - ProcOutput::Abbreviated { ref mut skipped, ref mut tail, .. } => { - *skipped += data.len(); - if data.len() <= TAIL_LEN { - tail[..data.len()].copy_from_slice(data); - tail.rotate_left(data.len()); - } else { - tail.copy_from_slice(&data[(data.len() - TAIL_LEN)..]); - } - return; - } - }; - *self = new_self; - } - - fn into_bytes(self) -> Vec { - match self { - ProcOutput::Full(bytes) => bytes, - ProcOutput::Abbreviated { mut head, skipped, tail } => { - write!(&mut head, "\n\n<<<<<< SKIPPED {} BYTES >>>>>>\n\n", skipped).unwrap(); - head.extend_from_slice(&tail); - head - } - } - } - } - - let mut stdout = ProcOutput::Full(Vec::new()); - let mut stderr = ProcOutput::Full(Vec::new()); - - drop(child.stdin.take()); - read2( - child.stdout.take().unwrap(), - child.stderr.take().unwrap(), - &mut |is_stdout, data, _| { - if is_stdout { &mut stdout } else { &mut stderr }.extend(data); - data.clear(); - }, - )?; - let status = child.wait()?; - - Ok(Output { status, stdout: stdout.into_bytes(), stderr: stderr.into_bytes() }) -} From e27bfb6e23774b61619b0d83a66e7f079c3ada37 Mon Sep 17 00:00:00 2001 From: John Kugelman Date: Fri, 8 Oct 2021 23:31:57 -0400 Subject: [PATCH 15/18] Add #[must_use] to stdin/stdout/stderr locks --- library/std/src/io/stdio.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 14a63303711fc..1ac3bbc95c66d 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -256,6 +256,7 @@ pub struct Stdin { /// Ok(()) /// } /// ``` +#[must_use = "if unused stdin will immediately unlock"] #[stable(feature = "rust1", since = "1.0.0")] pub struct StdinLock<'a> { inner: MutexGuard<'a, BufReader>, @@ -624,6 +625,7 @@ pub struct Stdout { /// When operating in a console, the Windows implementation of this stream does not support /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return /// an error. +#[must_use = "if unused stdout will immediately unlock"] #[stable(feature = "rust1", since = "1.0.0")] pub struct StdoutLock<'a> { inner: ReentrantMutexGuard<'a, RefCell>>, @@ -907,6 +909,7 @@ pub struct Stderr { /// When operating in a console, the Windows implementation of this stream does not support /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return /// an error. +#[must_use = "if unused stderr will immediately unlock"] #[stable(feature = "rust1", since = "1.0.0")] pub struct StderrLock<'a> { inner: ReentrantMutexGuard<'a, RefCell>, From 54d807cfc7f529ac1812ff1a9f4475c109f308e8 Mon Sep 17 00:00:00 2001 From: John Kugelman Date: Sat, 9 Oct 2021 01:01:40 -0400 Subject: [PATCH 16/18] Add #[must_use] to string/char transformation methods These methods could be misconstrued as modifying their arguments instead of returning new values. Where possible I made the note recommend a method that does mutate in place. --- library/alloc/src/slice.rs | 4 ++++ library/alloc/src/str.rs | 6 ++++++ library/core/src/char/methods.rs | 6 ++++++ library/core/src/num/mod.rs | 4 ++++ library/core/src/slice/ascii.rs | 2 ++ library/core/src/str/mod.rs | 16 ++++++++++++++++ library/std/src/ffi/os_str.rs | 2 ++ 7 files changed, 40 insertions(+) diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 4c8ea6902ff14..860f21085f325 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -662,6 +662,8 @@ impl [u8] { /// /// [`make_ascii_uppercase`]: slice::make_ascii_uppercase #[cfg(not(no_global_oom_handling))] + #[must_use = "this returns the uppercase bytes as a new Vec, \ + without modifying the original"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> Vec { @@ -680,6 +682,8 @@ impl [u8] { /// /// [`make_ascii_lowercase`]: slice::make_ascii_lowercase #[cfg(not(no_global_oom_handling))] + #[must_use = "this returns the lowercase bytes as a new Vec, \ + without modifying the original"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> Vec { diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index 62ba2e5765507..2900d01d9bdae 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -367,6 +367,8 @@ impl str { /// assert_eq!(new_year, new_year.to_lowercase()); /// ``` #[cfg(not(no_global_oom_handling))] + #[must_use = "this returns the lowercase string as a new String, \ + without modifying the original"] #[stable(feature = "unicode_case_mapping", since = "1.2.0")] pub fn to_lowercase(&self) -> String { let mut s = String::with_capacity(self.len()); @@ -447,6 +449,8 @@ impl str { /// assert_eq!("TSCHÜSS", s.to_uppercase()); /// ``` #[cfg(not(no_global_oom_handling))] + #[must_use = "this returns the uppercase string as a new String, \ + without modifying the original"] #[stable(feature = "unicode_case_mapping", since = "1.2.0")] pub fn to_uppercase(&self) -> String { let mut s = String::with_capacity(self.len()); @@ -534,6 +538,7 @@ impl str { /// [`make_ascii_uppercase`]: str::make_ascii_uppercase /// [`to_uppercase`]: #method.to_uppercase #[cfg(not(no_global_oom_handling))] + #[must_use = "to uppercase the value in-place, use `make_ascii_lowercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> String { @@ -565,6 +570,7 @@ impl str { /// [`make_ascii_lowercase`]: str::make_ascii_lowercase /// [`to_lowercase`]: #method.to_lowercase #[cfg(not(no_global_oom_handling))] + #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> String { diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index b1dd6aef97493..b3af1f1ffb592 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -949,6 +949,8 @@ impl char { /// // convert into themselves. /// assert_eq!('山'.to_lowercase().to_string(), "山"); /// ``` + #[must_use = "this returns the lowercase character as a new iterator, \ + without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn to_lowercase(self) -> ToLowercase { @@ -1039,6 +1041,8 @@ impl char { /// ``` /// /// holds across languages. + #[must_use = "this returns the uppercase character as a new iterator, \ + without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn to_uppercase(self) -> ToUppercase { @@ -1085,6 +1089,7 @@ impl char { /// /// [`make_ascii_uppercase()`]: #method.make_ascii_uppercase /// [`to_uppercase()`]: #method.to_uppercase + #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] #[inline] @@ -1118,6 +1123,7 @@ impl char { /// /// [`make_ascii_lowercase()`]: #method.make_ascii_lowercase /// [`to_lowercase()`]: #method.to_lowercase + #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] #[inline] diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index d5fb98eff575d..d9cac8b425931 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -282,6 +282,7 @@ impl u8 { /// ``` /// /// [`make_ascii_uppercase`]: Self::make_ascii_uppercase + #[must_use = "to uppercase the value in-place, use `make_ascii_lowercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] #[inline] @@ -306,6 +307,7 @@ impl u8 { /// ``` /// /// [`make_ascii_lowercase`]: Self::make_ascii_lowercase + #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] #[inline] @@ -769,6 +771,8 @@ impl u8 { /// assert_eq!("\\\\", b'\\'.escape_ascii().to_string()); /// assert_eq!("\\x9d", b'\x9d'.escape_ascii().to_string()); /// ``` + #[must_use = "this returns the escaped byte as an iterator, \ + without modifying the original"] #[unstable(feature = "inherent_ascii_escape", issue = "77174")] #[inline] pub fn escape_ascii(&self) -> ascii::EscapeDefault { diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index b92ab7e347555..cbb5627cef982 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -72,6 +72,8 @@ impl [u8] { /// let escaped = s.escape_ascii().to_string(); /// assert_eq!(escaped, "0\\t\\r\\n\\'\\\"\\\\\\x9d"); /// ``` + #[must_use = "this returns the escaped bytes as an iterator, \ + without modifying the original"] #[unstable(feature = "inherent_ascii_escape", issue = "77174")] pub fn escape_ascii(&self) -> EscapeAscii<'_> { EscapeAscii { inner: self.iter().flat_map(EscapeByte) } diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 607fb627605a0..993e22a5b507b 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -798,6 +798,8 @@ impl str { /// /// assert_eq!(None, iter.next()); /// ``` + #[must_use = "this returns the split string as an iterator, \ + without modifying the original"] #[stable(feature = "split_whitespace", since = "1.1.0")] #[inline] pub fn split_whitespace(&self) -> SplitWhitespace<'_> { @@ -839,6 +841,8 @@ impl str { /// /// assert_eq!(None, iter.next()); /// ``` + #[must_use = "this returns the split string as an iterator, \ + without modifying the original"] #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] #[inline] pub fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_> { @@ -914,6 +918,8 @@ impl str { /// /// assert!(utf16_len <= utf8_len); /// ``` + #[must_use = "this returns the encoded string as an iterator, \ + without modifying the original"] #[stable(feature = "encode_utf16", since = "1.8.0")] pub fn encode_utf16(&self) -> EncodeUtf16<'_> { EncodeUtf16 { chars: self.chars(), extra: 0 } @@ -1840,6 +1846,8 @@ impl str { /// let s = " עברית"; /// assert!(Some('ע') == s.trim_left().chars().next()); /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated( @@ -1882,6 +1890,8 @@ impl str { /// let s = "עברית "; /// assert!(Some('ת') == s.trim_right().chars().rev().next()); /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated( @@ -2346,6 +2356,8 @@ impl str { /// ``` /// assert_eq!("❤\n!".escape_debug().to_string(), "❤\\n!"); /// ``` + #[must_use = "this returns the escaped string as an iterator, \ + without modifying the original"] #[stable(feature = "str_escape", since = "1.34.0")] pub fn escape_debug(&self) -> EscapeDebug<'_> { let mut chars = self.chars(); @@ -2390,6 +2402,8 @@ impl str { /// ``` /// assert_eq!("❤\n!".escape_default().to_string(), "\\u{2764}\\n!"); /// ``` + #[must_use = "this returns the escaped string as an iterator, \ + without modifying the original"] #[stable(feature = "str_escape", since = "1.34.0")] pub fn escape_default(&self) -> EscapeDefault<'_> { EscapeDefault { inner: self.chars().flat_map(CharEscapeDefault) } @@ -2426,6 +2440,8 @@ impl str { /// ``` /// assert_eq!("❤\n!".escape_unicode().to_string(), "\\u{2764}\\u{a}\\u{21}"); /// ``` + #[must_use = "this returns the escaped string as an iterator, \ + without modifying the original"] #[stable(feature = "str_escape", since = "1.34.0")] pub fn escape_unicode(&self) -> EscapeUnicode<'_> { EscapeUnicode { inner: self.chars().flat_map(CharEscapeUnicode) } diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 7e70901076cda..c305519dd4461 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -777,6 +777,7 @@ impl OsStr { /// /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase()); /// ``` + #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase`"] #[stable(feature = "osstring_ascii", since = "1.53.0")] pub fn to_ascii_lowercase(&self) -> OsString { OsString::from_inner(self.inner.to_ascii_lowercase()) @@ -798,6 +799,7 @@ impl OsStr { /// /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase()); /// ``` + #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase`"] #[stable(feature = "osstring_ascii", since = "1.53.0")] pub fn to_ascii_uppercase(&self) -> OsString { OsString::from_inner(self.inner.to_ascii_uppercase()) From 2ec7588aa1a00c1f2287ee84a0d552f344746333 Mon Sep 17 00:00:00 2001 From: John Kugelman Date: Sat, 9 Oct 2021 02:05:03 -0400 Subject: [PATCH 17/18] Update library/core/src/num/mod.rs Co-authored-by: Josh Triplett --- library/core/src/num/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index d9cac8b425931..44918a711d470 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -282,7 +282,7 @@ impl u8 { /// ``` /// /// [`make_ascii_uppercase`]: Self::make_ascii_uppercase - #[must_use = "to uppercase the value in-place, use `make_ascii_lowercase()`"] + #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] #[inline] From 8683d36042d6df8c4883c3562efb22a73bd1b324 Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Sat, 9 Oct 2021 19:18:37 +1100 Subject: [PATCH 18/18] Fix min LLVM version for bpf-types test Closes #89689 --- src/test/assembly/asm/bpf-types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/assembly/asm/bpf-types.rs b/src/test/assembly/asm/bpf-types.rs index cc3863d03cd46..7271ef11287ef 100644 --- a/src/test/assembly/asm/bpf-types.rs +++ b/src/test/assembly/asm/bpf-types.rs @@ -1,4 +1,4 @@ -// min-llvm-version: 10.0.1 +// min-llvm-version: 13.0 // assembly-output: emit-asm // compile-flags: --target bpfel-unknown-none -C target_feature=+alu32 // needs-llvm-components: bpf