From 564b4de626d9fa68ce10a0e792c1d329d3225d08 Mon Sep 17 00:00:00 2001 From: Roxane Date: Sun, 9 May 2021 10:06:24 -0400 Subject: [PATCH] use the correct attributes and add helper function --- compiler/rustc_typeck/src/check/upvar.rs | 182 ++++++++++------------- library/std/src/panic.rs | 4 +- 2 files changed, 84 insertions(+), 102 deletions(-) diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index a92b9b28887..7a2b5b26ef4 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -583,6 +583,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.infcx.predicate_may_hold(&obligation) } + /// Returns true if migration is needed for trait for the provided var_hir_id + fn need_2229_migrations_for_trait( + &self, + min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, + var_hir_id: hir::HirId, + check_trait: Option, + ) -> bool { + let root_var_min_capture_list = if let Some(root_var_min_capture_list) = + min_captures.and_then(|m| m.get(&var_hir_id)) + { + root_var_min_capture_list + } else { + return false; + }; + + let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id)); + + let cause = ObligationCause::misc(self.tcx.hir().span(var_hir_id), self.body_id); + + let obligation_should_hold = check_trait + .map(|check_trait| self.ty_impls_trait(ty, &cause, check_trait)) + .unwrap_or(false); + + // Check whether catpured fields also implement the trait + + for capture in root_var_min_capture_list.iter() { + let ty = capture.place.ty(); + + let obligation_holds_for_capture = check_trait + .map(|check_trait| self.ty_impls_trait(ty, &cause, check_trait)) + .unwrap_or(false); + + if !obligation_holds_for_capture && obligation_should_hold { + return true; + } + } + false + } + /// Figures out the list of root variables (and their types) that aren't completely /// captured by the closure when `capture_disjoint_fields` is enabled and auto-traits /// differ between the root variable and the captured paths. @@ -596,116 +635,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn compute_2229_migrations_for_trait( &self, min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, - _closure_clause: hir::CaptureBy, var_hir_id: hir::HirId, ) -> Option> { - let root_var_min_capture_list = if let Some(root_var_min_capture_list) = - min_captures.and_then(|m| m.get(&var_hir_id)) - { - root_var_min_capture_list - } else { - return None; - }; - - let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id)); - let tcx = self.infcx.tcx; - let cause = ObligationCause::misc(self.tcx.hir().span(var_hir_id), self.body_id); - - let clone_obligation_should_hold = tcx - .lang_items() - .clone_trait() - .map(|clone_trait| self.ty_impls_trait(ty, &cause, clone_trait)) - .unwrap_or(false); - let sync_obligation_should_hold = tcx - .lang_items() - .sync_trait() - .map(|sync_trait| self.ty_impls_trait(ty, &cause, sync_trait)) - .unwrap_or(false); - let send_obligation_should_hold = tcx - .lang_items() - .send_trait() - .map(|send_trait| self.ty_impls_trait(ty, &cause, send_trait)) - .unwrap_or(false); - let unpin_obligation_should_hold = tcx - .lang_items() - .unpin_trait() - .map(|unpin_trait| self.ty_impls_trait(ty, &cause, unpin_trait)) - .unwrap_or(false); - let unwind_safe_obligation_should_hold = tcx - .lang_items() - .unwind_safe_trait() - .map(|unwind_safe_trait| self.ty_impls_trait(ty, &cause, unwind_safe_trait)) - .unwrap_or(false); - let ref_unwind_safe_obligation_should_hold = tcx - .lang_items() - .ref_unwind_safe_trait() - .map(|ref_unwind_safe_trait| self.ty_impls_trait(ty, &cause, ref_unwind_safe_trait)) - .unwrap_or(false); - // Check whether catpured fields also implement the trait let mut auto_trait_reasons = FxHashSet::default(); - for capture in root_var_min_capture_list.iter() { - let ty = capture.place.ty(); + if self.need_2229_migrations_for_trait( + min_captures, + var_hir_id, + tcx.lang_items().clone_trait(), + ) { + auto_trait_reasons.insert("`Clone`"); + } - let clone_obligation_holds_for_capture = tcx - .lang_items() - .clone_trait() - .map(|clone_trait| self.ty_impls_trait(ty, &cause, clone_trait)) - .unwrap_or(false); - let sync_obligation_holds_for_capture = tcx - .lang_items() - .sync_trait() - .map(|sync_trait| self.ty_impls_trait(ty, &cause, sync_trait)) - .unwrap_or(false); - let send_obligation_holds_for_capture = tcx - .lang_items() - .send_trait() - .map(|send_trait| self.ty_impls_trait(ty, &cause, send_trait)) - .unwrap_or(false); - let unpin_obligation_holds_for_capture = tcx - .lang_items() - .unpin_trait() - .map(|unpin_trait| self.ty_impls_trait(ty, &cause, unpin_trait)) - .unwrap_or(false); - let unwind_safe_obligation_holds_for_capture = tcx - .lang_items() - .unwind_safe_trait() - .map(|unwind_safe| self.ty_impls_trait(ty, &cause, unwind_safe)) - .unwrap_or(false); - let ref_unwind_safe_obligation_holds_for_capture = tcx - .lang_items() - .ref_unwind_safe_trait() - .map(|ref_unwind_safe_trait| self.ty_impls_trait(ty, &cause, ref_unwind_safe_trait)) - .unwrap_or(false); + if self.need_2229_migrations_for_trait( + min_captures, + var_hir_id, + tcx.lang_items().sync_trait(), + ) { + auto_trait_reasons.insert("`Sync`"); + } - if !clone_obligation_holds_for_capture && clone_obligation_should_hold { - auto_trait_reasons.insert("`Clone`"); - } + if self.need_2229_migrations_for_trait( + min_captures, + var_hir_id, + tcx.lang_items().send_trait(), + ) { + auto_trait_reasons.insert("`Send`"); + } - if !sync_obligation_holds_for_capture && sync_obligation_should_hold { - auto_trait_reasons.insert("`Sync`"); - } + if self.need_2229_migrations_for_trait( + min_captures, + var_hir_id, + tcx.lang_items().unpin_trait(), + ) { + auto_trait_reasons.insert("`Unpin`"); + } - if !send_obligation_holds_for_capture && send_obligation_should_hold { - auto_trait_reasons.insert("`Send`"); - } + if self.need_2229_migrations_for_trait( + min_captures, + var_hir_id, + tcx.lang_items().unwind_safe_trait(), + ) { + auto_trait_reasons.insert("`UnwindSafe`"); + } - if !unpin_obligation_holds_for_capture && unpin_obligation_should_hold { - auto_trait_reasons.insert("`Unpin`"); - } - - if !unwind_safe_obligation_holds_for_capture && unwind_safe_obligation_should_hold { - auto_trait_reasons.insert("`UnwindSafe`"); - } - - if !ref_unwind_safe_obligation_holds_for_capture - && ref_unwind_safe_obligation_should_hold - { - auto_trait_reasons.insert("`RefUnwindSafe`"); - } + if self.need_2229_migrations_for_trait( + min_captures, + var_hir_id, + tcx.lang_items().ref_unwind_safe_trait(), + ) { + auto_trait_reasons.insert("`RefUnwindSafe`"); } if auto_trait_reasons.len() > 0 { @@ -796,7 +778,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// - One of the paths starting at this root variable, that is not captured needs Drop **or** /// - One of the paths captured does not implement all the auto-traits its root variable /// implements. - /// + /// /// Returns a tuple containing a vector of HirIds as well as a String containing the reason /// why root variables whose HirId is contained in the vector should be fully captured. fn compute_2229_migrations( @@ -820,7 +802,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (&var_hir_id, _) in upvars.iter() { let mut need_migration = false; if let Some(trait_migration_cause) = - self.compute_2229_migrations_for_trait(min_captures, closure_clause, var_hir_id) + self.compute_2229_migrations_for_trait(min_captures, var_hir_id) { need_migration = true; auto_trait_reasons.extend(trait_migration_cause); diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 0442f70aa65..7114552745a 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -132,7 +132,7 @@ pub fn panic_any(msg: M) -> ! { /// [`AssertUnwindSafe`] wrapper struct can be used to force this trait to be /// implemented for any closed over variables passed to `catch_unwind`. #[stable(feature = "catch_unwind", since = "1.9.0")] -#[cfg_attr(not(bootstrap), lang = "unwind_safe")] +#[cfg_attr(all(not(bootstrap), not(test)), lang = "unwind_safe")] #[rustc_on_unimplemented( message = "the type `{Self}` may not be safely transferred across an unwind boundary", label = "`{Self}` may not be safely transferred across an unwind boundary" @@ -148,7 +148,7 @@ pub auto trait UnwindSafe {} /// This is a "helper marker trait" used to provide impl blocks for the /// [`UnwindSafe`] trait, for more information see that documentation. #[stable(feature = "catch_unwind", since = "1.9.0")] -#[cfg_attr(not(bootstrap), lang = "ref_unwind_safe")] +#[cfg_attr(all(not(bootstrap), not(test)), lang = "ref_unwind_safe")] #[rustc_on_unimplemented( message = "the type `{Self}` may contain interior mutability and a reference may not be safely \ transferrable across a catch_unwind boundary",