diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index dca9c1f04d3c0..bedd3523d899e 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -1,7 +1,6 @@ use crate::builder::Builder; use crate::context::CodegenCx; use crate::llvm::{self, AttributePlace}; -use crate::llvm_util; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; @@ -53,15 +52,10 @@ pub trait ArgAttributesExt { } fn should_use_mutable_noalias(cx: &CodegenCx<'_, '_>) -> bool { - // LLVM prior to version 12 has known miscompiles in the presence of - // noalias attributes (see #54878). Only enable mutable noalias by - // default for versions we believe to be safe. - cx.tcx - .sess - .opts - .debugging_opts - .mutable_noalias - .unwrap_or_else(|| llvm_util::get_version() >= (12, 0, 0)) + // LLVM prior to version 12 had known miscompiles in the presence of + // noalias attributes (see #54878), but we don't support earlier + // versions at all anymore. We now enable mutable noalias by default. + cx.tcx.sess.opts.debugging_opts.mutable_noalias.unwrap_or(true) } impl ArgAttributesExt for ArgAttributes { diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 0707faf610cf3..6c74163fb496c 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -731,7 +731,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> { - if llvm_util::get_version() >= (12, 0, 0) && !self.fptoint_sat_broken_in_llvm() { + if !self.fptoint_sat_broken_in_llvm() { let src_ty = self.cx.val_ty(val); let float_width = self.cx.float_width(src_ty); let int_width = self.cx.int_width(dest_ty); @@ -743,7 +743,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn fptosi_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> { - if llvm_util::get_version() >= (12, 0, 0) && !self.fptoint_sat_broken_in_llvm() { + if !self.fptoint_sat_broken_in_llvm() { let src_ty = self.cx.val_ty(val); let float_width = self.cx.float_width(src_ty); let int_width = self.cx.int_width(dest_ty); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index cda766039c167..1dba264a9614a 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -134,9 +134,6 @@ pub unsafe fn create_module( let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx); let mut target_data_layout = sess.target.data_layout.clone(); - if llvm_util::get_version() < (12, 0, 0) && sess.target.arch == "powerpc64" { - target_data_layout = target_data_layout.replace("-v256:256:256-v512:512:512", ""); - } if llvm_util::get_version() < (13, 0, 0) { if sess.target.arch == "powerpc64" { target_data_layout = target_data_layout.replace("-S128", ""); diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 246bb88885d85..3e0ea92ab81ed 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -406,11 +406,6 @@ pub fn llvm_global_features(sess: &Session) -> Vec { // -Ctarget-features features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter)); - // FIXME: Move outline-atomics to target definition when earliest supported LLVM is 12. - if get_version() >= (12, 0, 0) && sess.target.llvm_target.contains("aarch64-unknown-linux") { - features.push("+outline-atomics".to_string()); - } - features } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index b83d04f3dc2e7..c1a53c34b7a24 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3054,6 +3054,7 @@ declare_lint_pass! { BREAK_WITH_LABEL_AND_LOOP, UNUSED_ATTRIBUTES, NON_EXHAUSTIVE_OMITTED_PATTERNS, + TEXT_DIRECTION_CODEPOINT_IN_COMMENT, DEREF_INTO_DYN_SUPERTRAIT, ] } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 8ec5f4c79781f..b87e23af72b70 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -3060,9 +3060,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // LLVM's definition of `noalias` is based solely on memory // dependencies rather than pointer equality // - // Due to miscompiles in LLVM < 12, we apply a separate NoAliasMutRef attribute - // for UniqueBorrowed arguments, so that the codegen backend can decide - // whether or not to actually emit the attribute. + // Due to past miscompiles in LLVM, we apply a separate NoAliasMutRef attribute + // for UniqueBorrowed arguments, so that the codegen backend can decide whether + // or not to actually emit the attribute. It can also be controlled with the + // `-Zmutable-noalias` debugging option. let no_alias = match kind { PointerKind::Shared | PointerKind::UniqueBorrowed => false, PointerKind::UniqueOwned => true, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index e894e46a30142..3add3e861484e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1193,7 +1193,7 @@ options! { move_size_limit: Option = (None, parse_opt_number, [TRACKED], "the size at which the `large_assignments` lint starts to be emitted"), mutable_noalias: Option = (None, parse_opt_bool, [TRACKED], - "emit noalias metadata for mutable references (default: yes for LLVM >= 12, otherwise no)"), + "emit noalias metadata for mutable references (default: yes)"), new_llvm_pass_manager: Option = (None, parse_opt_bool, [TRACKED], "use new LLVM pass manager (default: no)"), nll_facts: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index d9eb299e2fd35..4768c9e2db5e1 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -68,8 +68,10 @@ mod attr_impl { const NonNull = 1 << 3; const ReadOnly = 1 << 4; const InReg = 1 << 5; - // NoAlias on &mut arguments can only be used with LLVM >= 12 due to miscompiles - // in earlier versions. FIXME: Remove this distinction once possible. + // Due to past miscompiles in LLVM, we use a separate attribute for + // &mut arguments, so that the codegen backend can decide whether + // or not to actually emit the attribute. It can also be controlled + // with the `-Zmutable-noalias` debugging option. const NoAliasMutRef = 1 << 6; } } diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs index 71ee6deb07f90..a393858879bfe 100644 --- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs @@ -8,6 +8,7 @@ pub fn target() -> Target { data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), options: TargetOptions { + features: "+outline-atomics".to_string(), max_atomic_width: Some(128), mcount: "\u{1}_mcount".to_string(), endian: Endian::Big, diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs index e05360ea45c6c..e75100f143511 100644 --- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs +++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs @@ -12,6 +12,7 @@ pub fn target() -> Target { arch: "aarch64".to_string(), options: TargetOptions { abi: "ilp32".to_string(), + features: "+outline-atomics".to_string(), mcount: "\u{1}_mcount".to_string(), endian: Endian::Big, ..base diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs index c8d46adbfd92b..850381f7fb073 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs @@ -7,6 +7,7 @@ pub fn target() -> Target { data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), options: TargetOptions { + features: "+outline-atomics".to_string(), mcount: "\u{1}_mcount".to_string(), max_atomic_width: Some(128), supported_sanitizers: SanitizerSet::ADDRESS diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs index 8522405f61feb..1c931d5a705f0 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs @@ -8,6 +8,7 @@ pub fn target() -> Target { arch: "aarch64".to_string(), options: TargetOptions { abi: "ilp32".to_string(), + features: "+outline-atomics".to_string(), max_atomic_width: Some(128), mcount: "\u{1}_mcount".to_string(), ..super::linux_gnu_base::opts() diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs index 6a16b4ce41964..0770f3496c279 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs @@ -9,6 +9,10 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), - options: TargetOptions { mcount: "\u{1}_mcount".to_string(), ..base }, + options: TargetOptions { + features: "+outline-atomics".to_string(), + mcount: "\u{1}_mcount".to_string(), + ..base + }, } } diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 9c7b0b2cacb06..774d8078e52ca 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -86,18 +86,55 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Intermediate format to store the hir_id pointing to the use that resulted in the /// corresponding place being captured and a String which contains the captured value's /// name (i.e: a.b.c) -type CapturesInfo = (Option, String); +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +enum UpvarMigrationInfo { + /// We previously captured all of `x`, but now we capture some sub-path. + CapturingPrecise { source_expr: Option, var_name: String }, + CapturingNothing { + // where the variable appears in the closure (but is not captured) + use_span: Span, + }, +} + +/// Reasons that we might issue a migration warning. +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +struct MigrationWarningReason { + /// When we used to capture `x` in its entirety, we implemented the auto-trait(s) + /// in this vec, but now we don't. + auto_traits: Vec<&'static str>, + + /// When we used to capture `x` in its entirety, we would execute some destructors + /// at a different time. + drop_order: bool, +} + +impl MigrationWarningReason { + fn migration_message(&self) -> String { + let base = "changes to closure capture in Rust 2021 will affect"; + if !self.auto_traits.is_empty() && self.drop_order { + format!("{} drop order and which traits the closure implements", base) + } else if self.drop_order { + format!("{} drop order", base) + } else { + format!("{} which traits the closure implements", base) + } + } +} -/// Intermediate format to store information needed to generate migration lint. The tuple -/// contains the hir_id pointing to the use that resulted in the -/// corresponding place being captured, a String which contains the captured value's -/// name (i.e: a.b.c) and a String which contains the reason why migration is needed for that -/// capture -type MigrationNeededForCapture = (Option, String, String); +/// Intermediate format to store information needed to generate a note in the migration lint. +struct MigrationLintNote { + captures_info: UpvarMigrationInfo, + + /// reasons why migration is needed for this capture + reason: MigrationWarningReason, +} /// Intermediate format to store the hir id of the root variable and a HashSet containing /// information on why the root variable should be fully captured -type MigrationDiagnosticInfo = (hir::HirId, Vec); +struct NeededMigration { + var_hir_id: hir::HirId, + diagnostics_info: Vec, +} struct InferBorrowKindVisitor<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, @@ -707,47 +744,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { closure_head_span, |lint| { let mut diagnostics_builder = lint.build( - format!( - "changes to closure capture in Rust 2021 will affect {}", - reasons - ) - .as_str(), + &reasons.migration_message(), ); - for (var_hir_id, diagnostics_info) in need_migrations.iter() { + for NeededMigration { var_hir_id, diagnostics_info } in &need_migrations { // Labels all the usage of the captured variable and why they are responsible // for migration being needed - for (captured_hir_id, captured_name, reasons) in diagnostics_info.iter() { - if let Some(captured_hir_id) = captured_hir_id { - let cause_span = self.tcx.hir().span(*captured_hir_id); - diagnostics_builder.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`", - self.tcx.hir().name(*var_hir_id), - captured_name, - )); + for lint_note in diagnostics_info.iter() { + match &lint_note.captures_info { + UpvarMigrationInfo::CapturingPrecise { source_expr: Some(capture_expr_id), var_name: captured_name } => { + let cause_span = self.tcx.hir().span(*capture_expr_id); + diagnostics_builder.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`", + self.tcx.hir().name(*var_hir_id), + captured_name, + )); + } + UpvarMigrationInfo::CapturingNothing { use_span } => { + diagnostics_builder.span_label(*use_span, format!("in Rust 2018, this causes the closure to capture `{}`, but in Rust 2021, it has no effect", + self.tcx.hir().name(*var_hir_id), + )); + } + + _ => { } } // Add a label pointing to where a captured variable affected by drop order // is dropped - if reasons.contains("drop order") { + if lint_note.reason.drop_order { let drop_location_span = drop_location_span(self.tcx, &closure_hir_id); - diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure", - self.tcx.hir().name(*var_hir_id), - captured_name, - )); + match &lint_note.captures_info { + UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => { + diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure", + self.tcx.hir().name(*var_hir_id), + captured_name, + )); + } + UpvarMigrationInfo::CapturingNothing { use_span: _ } => { + diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{v}` is dropped here along with the closure, but in Rust 2021 `{v}` is not part of the closure", + v = self.tcx.hir().name(*var_hir_id), + )); + } + } } // Add a label explaining why a closure no longer implements a trait - if reasons.contains("trait implementation") { - let missing_trait = &reasons[..reasons.find("trait implementation").unwrap() - 1]; - - diagnostics_builder.span_label(closure_head_span, format!("in Rust 2018, this closure implements {} as `{}` implements {}, but in Rust 2021, this closure will no longer implement {} as `{}` does not implement {}", - missing_trait, - self.tcx.hir().name(*var_hir_id), - missing_trait, - missing_trait, - captured_name, - missing_trait, - )); + for &missing_trait in &lint_note.reason.auto_traits { + // not capturing something anymore cannot cause a trait to fail to be implemented: + match &lint_note.captures_info { + UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => { + let var_name = self.tcx.hir().name(*var_hir_id); + diagnostics_builder.span_label(closure_head_span, format!("\ + in Rust 2018, this closure implements {missing_trait} \ + as `{var_name}` implements {missing_trait}, but in Rust 2021, \ + this closure will no longer implement {missing_trait} \ + because `{var_name}` is not fully captured \ + and `{captured_name}` does not implement {missing_trait}")); + } + + // Cannot happen: if we don't capture a variable, we impl strictly more traits + UpvarMigrationInfo::CapturingNothing { use_span } => span_bug!(*use_span, "missing trait from not capturing something"), + } } } } @@ -840,25 +896,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Combines all the reasons for 2229 migrations fn compute_2229_migrations_reasons( &self, - auto_trait_reasons: FxHashSet<&str>, - drop_reason: bool, - ) -> String { - let mut reasons = String::new(); - - if !auto_trait_reasons.is_empty() { - reasons = format!( - "{} trait implementation for closure", - auto_trait_reasons.clone().into_iter().collect::>().join(", ") - ); - } + auto_trait_reasons: FxHashSet<&'static str>, + drop_order: bool, + ) -> MigrationWarningReason { + let mut reasons = MigrationWarningReason::default(); - if !auto_trait_reasons.is_empty() && drop_reason { - reasons = format!("{} and ", reasons); + for auto_trait in auto_trait_reasons { + reasons.auto_traits.push(auto_trait); } - if drop_reason { - reasons = format!("{}drop order", reasons); - } + reasons.drop_order = drop_order; reasons } @@ -874,7 +921,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, var_hir_id: hir::HirId, closure_clause: hir::CaptureBy, - ) -> Option>> { + ) -> Option>> { let auto_traits_def_id = vec![ self.tcx.lang_items().clone_trait(), self.tcx.lang_items().sync_trait(), @@ -963,7 +1010,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !capture_problems.is_empty() { problematic_captures.insert( - (capture.info.path_expr_id, capture.to_string(self.tcx)), + UpvarMigrationInfo::CapturingPrecise { + source_expr: capture.info.path_expr_id, + var_name: capture.to_string(self.tcx), + }, capture_problems, ); } @@ -986,6 +1036,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// This function only returns a HashSet of CapturesInfo for significant drops. If there /// are no significant drops than None is returned + #[instrument(level = "debug", skip(self))] fn compute_2229_migrations_for_drop( &self, closure_def_id: DefId, @@ -993,25 +1044,41 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, closure_clause: hir::CaptureBy, var_hir_id: hir::HirId, - ) -> Option> { + ) -> Option> { let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id)); if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) { + debug!("does not have significant drop"); return None; } let Some(root_var_min_capture_list) = min_captures.and_then(|m| m.get(&var_hir_id)) else { // The upvar is mentioned within the closure but no path starting from it is - // used. + // used. This occurs when you have (e.g.) + // + // ``` + // let x = move || { + // let _ = y; + // }); + // ``` + debug!("no path starting from it is used"); + match closure_clause { // Only migrate if closure is a move closure - hir::CaptureBy::Value => return Some(FxHashSet::default()), + hir::CaptureBy::Value => { + let mut diagnostics_info = FxHashSet::default(); + let upvars = self.tcx.upvars_mentioned(closure_def_id).expect("must be an upvar"); + let upvar = upvars[&var_hir_id]; + diagnostics_info.insert(UpvarMigrationInfo::CapturingNothing { use_span: upvar.span }); + return Some(diagnostics_info); + } hir::CaptureBy::Ref => {} } return None; }; + debug!(?root_var_min_capture_list); let mut projections_list = Vec::new(); let mut diagnostics_info = FxHashSet::default(); @@ -1021,19 +1088,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Only care about captures that are moved into the closure ty::UpvarCapture::ByValue(..) => { projections_list.push(captured_place.place.projections.as_slice()); - diagnostics_info.insert(( - captured_place.info.path_expr_id, - captured_place.to_string(self.tcx), - )); + diagnostics_info.insert(UpvarMigrationInfo::CapturingPrecise { + source_expr: captured_place.info.path_expr_id, + var_name: captured_place.to_string(self.tcx), + }); } ty::UpvarCapture::ByRef(..) => {} } } + debug!(?projections_list); + debug!(?diagnostics_info); + let is_moved = !projections_list.is_empty(); + debug!(?is_moved); let is_not_completely_captured = root_var_min_capture_list.iter().any(|capture| !capture.place.projections.is_empty()); + debug!(?is_not_completely_captured); if is_moved && is_not_completely_captured @@ -1066,15 +1138,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Returns a tuple containing a vector of MigrationDiagnosticInfo, as well as a String /// containing the reason why root variables whose HirId is contained in the vector should /// be captured + #[instrument(level = "debug", skip(self))] fn compute_2229_migrations( &self, closure_def_id: DefId, closure_span: Span, closure_clause: hir::CaptureBy, min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, - ) -> (Vec, String) { + ) -> (Vec, MigrationWarningReason) { let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) else { - return (Vec::new(), String::new()); + return (Vec::new(), MigrationWarningReason::default()); }; let mut need_migrations = Vec::new(); @@ -1083,7 +1156,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Perform auto-trait analysis for (&var_hir_id, _) in upvars.iter() { - let mut responsible_captured_hir_ids = Vec::new(); + let mut diagnostics_info = Vec::new(); let auto_trait_diagnostic = if let Some(diagnostics_info) = self.compute_2229_migrations_for_trait(min_captures, var_hir_id, closure_clause) @@ -1115,34 +1188,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut capture_diagnostic = capture_diagnostic.into_iter().collect::>(); capture_diagnostic.sort(); - for captured_info in capture_diagnostic.iter() { + for captures_info in capture_diagnostic { // Get the auto trait reasons of why migration is needed because of that capture, if there are any let capture_trait_reasons = - if let Some(reasons) = auto_trait_diagnostic.get(captured_info) { + if let Some(reasons) = auto_trait_diagnostic.get(&captures_info) { reasons.clone() } else { FxHashSet::default() }; // Check if migration is needed because of drop reorder as a result of that capture - let capture_drop_reorder_reason = drop_reorder_diagnostic.contains(captured_info); + let capture_drop_reorder_reason = drop_reorder_diagnostic.contains(&captures_info); // Combine all the reasons of why the root variable should be captured as a result of // auto trait implementation issues auto_trait_migration_reasons.extend(capture_trait_reasons.clone()); - responsible_captured_hir_ids.push(( - captured_info.0, - captured_info.1.clone(), - self.compute_2229_migrations_reasons( + diagnostics_info.push(MigrationLintNote { + captures_info, + reason: self.compute_2229_migrations_reasons( capture_trait_reasons, capture_drop_reorder_reason, ), - )); + }); } - if !capture_diagnostic.is_empty() { - need_migrations.push((var_hir_id, responsible_captured_hir_ids)); + if !diagnostics_info.is_empty() { + need_migrations.push(NeededMigration { var_hir_id, diagnostics_info }); } } ( @@ -2087,6 +2159,7 @@ fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol { tcx.hir().name(var_hir_id) } +#[instrument(level = "debug", skip(tcx))] fn should_do_rust_2021_incompatible_closure_captures_analysis( tcx: TyCtxt<'_>, closure_id: hir::HirId, @@ -2102,10 +2175,12 @@ fn should_do_rust_2021_incompatible_closure_captures_analysis( /// - s2: Comma separated names of the variables being migrated. fn migration_suggestion_for_2229( tcx: TyCtxt<'_>, - need_migrations: &Vec, + need_migrations: &Vec, ) -> (String, String) { - let need_migrations_variables = - need_migrations.iter().map(|(v, _)| var_name(tcx, *v)).collect::>(); + let need_migrations_variables = need_migrations + .iter() + .map(|NeededMigration { var_hir_id: v, .. }| var_name(tcx, *v)) + .collect::>(); let migration_ref_concat = need_migrations_variables.iter().map(|v| format!("&{}", v)).collect::>().join(", "); diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 9861530c19443..0c00db5fdf37a 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -201,33 +201,33 @@ macro_rules! widening_impl { #[lang = "i8"] impl i8 { - widening_impl! { i8, i16, 8, signed } int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } + widening_impl! { i8, i16, 8, signed } } #[lang = "i16"] impl i16 { - widening_impl! { i16, i32, 16, signed } int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } + widening_impl! { i16, i32, 16, signed } } #[lang = "i32"] impl i32 { - widening_impl! { i32, i64, 32, signed } int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } + widening_impl! { i32, i64, 32, signed } } #[lang = "i64"] impl i64 { - widening_impl! { i64, i128, 64, signed } int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" } + widening_impl! { i64, i128, 64, signed } } #[lang = "i128"] @@ -245,31 +245,31 @@ impl i128 { #[cfg(target_pointer_width = "16")] #[lang = "isize"] impl isize { - widening_impl! { isize, i32, 16, signed } int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + widening_impl! { isize, i32, 16, signed } } #[cfg(target_pointer_width = "32")] #[lang = "isize"] impl isize { - widening_impl! { isize, i64, 32, signed } int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + widening_impl! { isize, i64, 32, signed } } #[cfg(target_pointer_width = "64")] #[lang = "isize"] impl isize { - widening_impl! { isize, i128, 64, signed } int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", - "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", - usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + widening_impl! { isize, i128, 64, signed } } /// If 6th bit set ascii is upper case. @@ -277,9 +277,9 @@ const ASCII_CASE_MASK: u8 = 0b0010_0000; #[lang = "u8"] impl u8 { - widening_impl! { u8, u16, 8, unsigned } uint_impl! { u8, u8, i8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } + widening_impl! { u8, u16, 8, unsigned } /// Checks if the value is within the ASCII range. /// @@ -826,26 +826,26 @@ impl u8 { #[lang = "u16"] impl u16 { - widening_impl! { u16, u32, 16, unsigned } uint_impl! { u16, u16, i16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } + widening_impl! { u16, u32, 16, unsigned } } #[lang = "u32"] impl u32 { - widening_impl! { u32, u64, 32, unsigned } uint_impl! { u32, u32, i32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } + widening_impl! { u32, u64, 32, unsigned } } #[lang = "u64"] impl u64 { - widening_impl! { u64, u128, 64, unsigned } uint_impl! { u64, u64, i64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", ""} + widening_impl! { u64, u128, 64, unsigned } } #[lang = "u128"] @@ -863,29 +863,29 @@ impl u128 { #[cfg(target_pointer_width = "16")] #[lang = "usize"] impl usize { - widening_impl! { usize, u32, 16, unsigned } uint_impl! { usize, u16, isize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + widening_impl! { usize, u32, 16, unsigned } } #[cfg(target_pointer_width = "32")] #[lang = "usize"] impl usize { - widening_impl! { usize, u64, 32, unsigned } uint_impl! { usize, u32, isize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + widening_impl! { usize, u64, 32, unsigned } } #[cfg(target_pointer_width = "64")] #[lang = "usize"] impl usize { - widening_impl! { usize, u128, 64, unsigned } uint_impl! { usize, u64, isize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + widening_impl! { usize, u128, 64, unsigned } } /// A classification of floating point numbers. diff --git a/src/test/ui/closures/2229_closure_analysis/issue-90465.fixed b/src/test/ui/closures/2229_closure_analysis/issue-90465.fixed new file mode 100644 index 0000000000000..4e0b18e72338a --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-90465.fixed @@ -0,0 +1,35 @@ +// run-rustfix + +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE lint level is defined here + +fn main() { + struct Foo(u32); + impl Drop for Foo { + fn drop(&mut self) { + println!("dropped {}", self.0); + } + } + + let f0 = Foo(0); + let f1 = Foo(1); + + let c0 = move || { + let _ = &f0; + //~^ ERROR changes to closure capture in Rust 2021 will affect drop order + //~| NOTE for more information + let _ = f0; + //~^ NOTE in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect + }; + + let c1 = move || { + let _ = &f1; + }; + + println!("dropping 0"); + drop(c0); + println!("dropping 1"); + drop(c1); + println!("dropped all"); +} +//~^ NOTE in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure diff --git a/src/test/ui/closures/2229_closure_analysis/issue-90465.rs b/src/test/ui/closures/2229_closure_analysis/issue-90465.rs new file mode 100644 index 0000000000000..466e6dbabc502 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-90465.rs @@ -0,0 +1,34 @@ +// run-rustfix + +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE lint level is defined here + +fn main() { + struct Foo(u32); + impl Drop for Foo { + fn drop(&mut self) { + println!("dropped {}", self.0); + } + } + + let f0 = Foo(0); + let f1 = Foo(1); + + let c0 = move || { + //~^ ERROR changes to closure capture in Rust 2021 will affect drop order + //~| NOTE for more information + let _ = f0; + //~^ NOTE in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect + }; + + let c1 = move || { + let _ = &f1; + }; + + println!("dropping 0"); + drop(c0); + println!("dropping 1"); + drop(c1); + println!("dropped all"); +} +//~^ NOTE in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure diff --git a/src/test/ui/closures/2229_closure_analysis/issue-90465.stderr b/src/test/ui/closures/2229_closure_analysis/issue-90465.stderr new file mode 100644 index 0000000000000..3e921dc0f8a66 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-90465.stderr @@ -0,0 +1,26 @@ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/issue-90465.rs:17:14 + | +LL | let c0 = move || { + | ^^^^^^^ +... +LL | let _ = f0; + | -- in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect +... +LL | } + | - in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure + | +note: the lint level is defined here + --> $DIR/issue-90465.rs:3:9 + | +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see +help: add a dummy let to cause `f0` to be fully captured + | +LL ~ let c0 = move || { +LL + let _ = &f0; + | + +error: aborting due to previous error + diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed index b0fc5120f08f2..26703fbf81193 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed @@ -20,8 +20,8 @@ fn test_send_trait() { let mut f = 10; let fptr = SendPointer(&mut f as *mut i32); thread::spawn(move || { let _ = &fptr; unsafe { - //~^ ERROR: `Send` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send` + //~^ ERROR: changes to closure capture + //~| NOTE: in Rust 2018, this closure implements `Send` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0 = 20; @@ -40,8 +40,9 @@ fn test_sync_trait() { let f = CustomInt(&mut f as *mut i32); let fptr = SyncPointer(f); thread::spawn(move || { let _ = &fptr; unsafe { - //~^ ERROR: `Sync`, `Send` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send` + //~^ ERROR: changes to closure capture + //~| NOTE: in Rust 2018, this closure implements `Sync` + //~| NOTE: in Rust 2018, this closure implements `Send` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0.0 = 20; @@ -65,8 +66,8 @@ fn test_clone_trait() { let f = U(S(Foo(0)), T(0)); let c = || { let _ = &f; - //~^ ERROR: `Clone` trait implementation for closure and drop order - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + //~| NOTE: in Rust 2018, this closure implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured let f_1 = f.1; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs index 2bcf9a795edbd..932db51d43713 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs @@ -20,8 +20,8 @@ fn test_send_trait() { let mut f = 10; let fptr = SendPointer(&mut f as *mut i32); thread::spawn(move || unsafe { - //~^ ERROR: `Send` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send` + //~^ ERROR: changes to closure capture + //~| NOTE: in Rust 2018, this closure implements `Send` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0 = 20; @@ -40,8 +40,9 @@ fn test_sync_trait() { let f = CustomInt(&mut f as *mut i32); let fptr = SyncPointer(f); thread::spawn(move || unsafe { - //~^ ERROR: `Sync`, `Send` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send` + //~^ ERROR: changes to closure capture + //~| NOTE: in Rust 2018, this closure implements `Sync` + //~| NOTE: in Rust 2018, this closure implements `Send` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0.0 = 20; @@ -64,8 +65,8 @@ impl Clone for U { fn test_clone_trait() { let f = U(S(Foo(0)), T(0)); let c = || { - //~^ ERROR: `Clone` trait implementation for closure and drop order - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + //~| NOTE: in Rust 2018, this closure implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured let f_1 = f.1; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr index 8d2d3553d4040..ee4907bb755cc 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr @@ -1,8 +1,8 @@ -error: changes to closure capture in Rust 2021 will affect `Send` trait implementation for closure +error: changes to closure capture in Rust 2021 will affect which traits the closure implements --> $DIR/auto_traits.rs:22:19 | LL | thread::spawn(move || unsafe { - | ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send` + | ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0` does not implement `Send` ... LL | *fptr.0 = 20; | ------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0` @@ -23,11 +23,14 @@ LL | LL | *fptr.0 = 20; ... -error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure +error: changes to closure capture in Rust 2021 will affect which traits the closure implements --> $DIR/auto_traits.rs:42:19 | LL | thread::spawn(move || unsafe { - | ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send` + | ^^^^^^^^^^^^^^ + | | + | in Rust 2018, this closure implements `Sync` as `fptr` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr` is not fully captured and `fptr.0.0` does not implement `Sync` + | in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0.0` does not implement `Send` ... LL | *fptr.0.0 = 20; | --------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0` @@ -40,14 +43,14 @@ LL | LL | LL | LL | -LL | *fptr.0.0 = 20; +LL | ... -error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order - --> $DIR/auto_traits.rs:66:13 +error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + --> $DIR/auto_traits.rs:67:13 | LL | let c = || { - | ^^ in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone` + | ^^ in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f` is not fully captured and `f.1` does not implement `Clone` ... LL | let f_1 = f.1; | --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.1` diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed index a5652154682c5..7df0dd76b4456 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed @@ -19,8 +19,9 @@ where let f = panic::AssertUnwindSafe(f); let result = panic::catch_unwind(move || { let _ = &f; - //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe` + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `UnwindSafe` + //~| NOTE: in Rust 2018, this closure implements `RefUnwindSafe` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured f.0() diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs index d9acde073fc3d..d02fac7c66952 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs @@ -18,8 +18,9 @@ where { let f = panic::AssertUnwindSafe(f); let result = panic::catch_unwind(move || { - //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe` + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `UnwindSafe` + //~| NOTE: in Rust 2018, this closure implements `RefUnwindSafe` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured f.0() diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr index 10816b7bc3adf..74f85b6ebaac5 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr @@ -1,8 +1,11 @@ -error: changes to closure capture in Rust 2021 will affect `UnwindSafe`, `RefUnwindSafe` trait implementation for closure +error: changes to closure capture in Rust 2021 will affect which traits the closure implements --> $DIR/mir_calls_to_shims.rs:20:38 | LL | let result = panic::catch_unwind(move || { - | ^^^^^^^ in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe` + | ^^^^^^^ + | | + | in Rust 2018, this closure implements `UnwindSafe` as `f` implements `UnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe` because `f` is not fully captured and `f.0` does not implement `UnwindSafe` + | in Rust 2018, this closure implements `RefUnwindSafe` as `f` implements `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `RefUnwindSafe` because `f` is not fully captured and `f.0` does not implement `RefUnwindSafe` ... LL | f.0() | --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0` diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed index 11218eff1337f..2b86b0ddade23 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed @@ -18,7 +18,6 @@ impl Foo { } } - struct S(Foo); #[derive(Clone)] @@ -37,8 +36,8 @@ fn test_multi_issues() { let f2 = U(S(Foo::from("bar")), T(0)); let c = || { let _ = (&f1, &f2); - //~^ ERROR: `Clone` trait implementation for closure and drop order - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured let _f_1 = f1.0; @@ -57,8 +56,8 @@ fn test_capturing_all_disjoint_fields_individually() { let f1 = U(S(Foo::from("foo")), T(0)); let c = || { let _ = &f1; - //~^ ERROR: `Clone` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1` to be fully captured let _f_1 = f1.0; @@ -83,9 +82,9 @@ fn test_capturing_several_disjoint_fields_individually_1() { let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar"))); let c = || { let _ = &f1; - //~^ ERROR: `Clone` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1` to be fully captured let _f_0 = f1.0; @@ -103,8 +102,8 @@ fn test_capturing_several_disjoint_fields_individually_2() { let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar"))); let c = || { let _ = &f1; - //~^ ERROR: `Clone` trait implementation for closure and drop order - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1` to be fully captured let _f_0 = f1.0; @@ -136,9 +135,10 @@ fn test_multi_traits_issues() { let mut f2 = 10; let fptr2 = SendPointer(&mut f2 as *mut i32); thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe { - //~^ ERROR: `Sync`, `Send` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send` - //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send` + //~^ ERROR: changes to closure capture in Rust 2021 + //~| NOTE: in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync` + //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr1` implements `Send` + //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured *fptr1.0.0 = 20; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs index 02f2faa2e8741..3cac4abfad7c2 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs @@ -18,7 +18,6 @@ impl Foo { } } - struct S(Foo); #[derive(Clone)] @@ -36,8 +35,8 @@ fn test_multi_issues() { let f1 = U(S(Foo::from("foo")), T(0)); let f2 = U(S(Foo::from("bar")), T(0)); let c = || { - //~^ ERROR: `Clone` trait implementation for closure and drop order - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured let _f_1 = f1.0; @@ -55,8 +54,8 @@ fn test_multi_issues() { fn test_capturing_all_disjoint_fields_individually() { let f1 = U(S(Foo::from("foo")), T(0)); let c = || { - //~^ ERROR: `Clone` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1` to be fully captured let _f_1 = f1.0; @@ -80,9 +79,9 @@ impl Clone for U1 { fn test_capturing_several_disjoint_fields_individually_1() { let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar"))); let c = || { - //~^ ERROR: `Clone` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1` to be fully captured let _f_0 = f1.0; @@ -99,8 +98,8 @@ fn test_capturing_several_disjoint_fields_individually_1() { fn test_capturing_several_disjoint_fields_individually_2() { let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar"))); let c = || { - //~^ ERROR: `Clone` trait implementation for closure and drop order - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1` to be fully captured let _f_0 = f1.0; @@ -132,9 +131,10 @@ fn test_multi_traits_issues() { let mut f2 = 10; let fptr2 = SendPointer(&mut f2 as *mut i32); thread::spawn(move || unsafe { - //~^ ERROR: `Sync`, `Send` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send` - //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send` + //~^ ERROR: changes to closure capture in Rust 2021 + //~| NOTE: in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync` + //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr1` implements `Send` + //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured *fptr1.0.0 = 20; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr index d425db5aa998c..0008f1b2c07ed 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr @@ -1,8 +1,8 @@ -error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order - --> $DIR/multi_diagnostics.rs:38:13 +error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + --> $DIR/multi_diagnostics.rs:37:13 | LL | let c = || { - | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone` ... LL | let _f_1 = f1.0; | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` @@ -25,11 +25,11 @@ LL ~ let c = || { LL + let _ = (&f1, &f2); | -error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure - --> $DIR/multi_diagnostics.rs:57:13 +error: changes to closure capture in Rust 2021 will affect which traits the closure implements + --> $DIR/multi_diagnostics.rs:56:13 | LL | let c = || { - | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone` ... LL | let _f_1 = f1.0; | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` @@ -41,14 +41,14 @@ LL ~ let c = || { LL + let _ = &f1; | -error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure - --> $DIR/multi_diagnostics.rs:82:13 +error: changes to closure capture in Rust 2021 will affect which traits the closure implements + --> $DIR/multi_diagnostics.rs:81:13 | LL | let c = || { | ^^ | | - | in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` - | in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone` + | in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone` + | in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.2` does not implement `Clone` ... LL | let _f_0 = f1.0; | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` @@ -63,11 +63,11 @@ LL ~ let c = || { LL + let _ = &f1; | -error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order - --> $DIR/multi_diagnostics.rs:101:13 +error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + --> $DIR/multi_diagnostics.rs:100:13 | LL | let c = || { - | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone` ... LL | let _f_0 = f1.0; | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` @@ -88,14 +88,15 @@ LL ~ let c = || { LL + let _ = &f1; | -error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure - --> $DIR/multi_diagnostics.rs:134:19 +error: changes to closure capture in Rust 2021 will affect which traits the closure implements + --> $DIR/multi_diagnostics.rs:133:19 | LL | thread::spawn(move || unsafe { | ^^^^^^^^^^^^^^ | | - | in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send` - | in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send` + | in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Sync` + | in Rust 2018, this closure implements `Send` as `fptr1` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Send` + | in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr2` is not fully captured and `fptr2.0` does not implement `Send` ... LL | *fptr1.0.0 = 20; | ---------- in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0` diff --git a/src/test/ui/extern/extern-methods.rs b/src/test/ui/extern/extern-methods.rs index 3909b5301ade5..22792c11366ba 100644 --- a/src/test/ui/extern/extern-methods.rs +++ b/src/test/ui/extern/extern-methods.rs @@ -1,5 +1,5 @@ // run-pass -// only-i686 +// only-x86 trait A { extern "fastcall" fn test1(i: i32); diff --git a/src/test/ui/extern/extern-thiscall.rs b/src/test/ui/extern/extern-thiscall.rs index 8ce94aa71aae6..717df57ec4848 100644 --- a/src/test/ui/extern/extern-thiscall.rs +++ b/src/test/ui/extern/extern-thiscall.rs @@ -1,5 +1,5 @@ // run-pass -// only-i686 +// only-x86 #![feature(abi_thiscall)] diff --git a/src/test/ui/extern/extern-vectorcall.rs b/src/test/ui/extern/extern-vectorcall.rs index f625eb0890f05..a283573c9fbd1 100644 --- a/src/test/ui/extern/extern-vectorcall.rs +++ b/src/test/ui/extern/extern-vectorcall.rs @@ -1,7 +1,7 @@ // run-pass // revisions: x64 x32 // [x64]only-x86_64 -// [x32]only-i686 +// [x32]only-x86 #![feature(abi_vectorcall)] diff --git a/src/test/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs b/src/test/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs new file mode 100644 index 0000000000000..425e2703c94c4 --- /dev/null +++ b/src/test/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs @@ -0,0 +1,9 @@ +// check-pass +// Allowing the code lint should work without warning and +// the text flow char in the comment should be ignored. + +#![allow(text_direction_codepoint_in_comment)] + +fn main() { + // U+2066 LEFT-TO-RIGHT ISOLATE follows:⁦⁦ +} diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 2485dbadab5bf..157b42e2d17f5 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -168,7 +168,7 @@ fn only_target() { let mut config = config(); config.target = "x86_64-pc-windows-gnu".to_owned(); - assert!(check_ignore(&config, "// only-i686")); + assert!(check_ignore(&config, "// only-x86")); assert!(check_ignore(&config, "// only-linux")); assert!(check_ignore(&config, "// only-msvc")); assert!(check_ignore(&config, "// only-32bit"));