about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/check/upvar.rs174
-rw-r--r--library/std/src/panic.rs4
2 files changed, 80 insertions, 98 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,129 +583,111 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.infcx.predicate_may_hold(&obligation)
     }
 
-    /// 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.
-    ///
-    /// The output list would include a root variable if:
-    /// - It would have been captured into the closure when `capture_disjoint_fields` wasn't
-    ///   enabled, **and**
-    /// - It wasn't completely captured by the closure, **and**
-    /// - One of the paths captured does not implement all the auto-traits its root variable
-    ///   implements.
-    fn compute_2229_migrations_for_trait(
+    /// 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>>,
-        _closure_clause: hir::CaptureBy,
         var_hir_id: hir::HirId,
-    ) -> Option<FxHashSet<&str>> {
+        check_trait: Option<DefId>,
+    ) -> 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 None;
+            return false;
         };
 
         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))
+        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
-        let mut auto_trait_reasons = FxHashSet::default();
 
         for capture in root_var_min_capture_list.iter() {
             let ty = capture.place.ty();
 
-            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))
+            let obligation_holds_for_capture = check_trait
+                .map(|check_trait| self.ty_impls_trait(ty, &cause, check_trait))
                 .unwrap_or(false);
 
-            if !clone_obligation_holds_for_capture && clone_obligation_should_hold {
-                auto_trait_reasons.insert("`Clone`");
+            if !obligation_holds_for_capture && obligation_should_hold {
+                return true;
             }
+        }
+        false
+    }
 
-            if !sync_obligation_holds_for_capture && sync_obligation_should_hold {
-                auto_trait_reasons.insert("`Sync`");
-            }
+    /// 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.
+    ///
+    /// The output list would include a root variable if:
+    /// - It would have been captured into the closure when `capture_disjoint_fields` wasn't
+    ///   enabled, **and**
+    /// - It wasn't completely captured by the closure, **and**
+    /// - One of the paths captured does not implement all the auto-traits its root variable
+    ///   implements.
+    fn compute_2229_migrations_for_trait(
+        &self,
+        min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
+        var_hir_id: hir::HirId,
+    ) -> Option<FxHashSet<&str>> {
+        let tcx = self.infcx.tcx;
 
-            if !send_obligation_holds_for_capture && send_obligation_should_hold {
-                auto_trait_reasons.insert("`Send`");
-            }
+        // Check whether catpured fields also implement the trait
+        let mut auto_trait_reasons = FxHashSet::default();
 
-            if !unpin_obligation_holds_for_capture && unpin_obligation_should_hold {
-                auto_trait_reasons.insert("`Unpin`");
-            }
+        if self.need_2229_migrations_for_trait(
+            min_captures,
+            var_hir_id,
+            tcx.lang_items().clone_trait(),
+        ) {
+            auto_trait_reasons.insert("`Clone`");
+        }
 
-            if !unwind_safe_obligation_holds_for_capture && unwind_safe_obligation_should_hold {
-                auto_trait_reasons.insert("`UnwindSafe`");
-            }
+        if self.need_2229_migrations_for_trait(
+            min_captures,
+            var_hir_id,
+            tcx.lang_items().sync_trait(),
+        ) {
+            auto_trait_reasons.insert("`Sync`");
+        }
 
-            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().send_trait(),
+        ) {
+            auto_trait_reasons.insert("`Send`");
+        }
+
+        if self.need_2229_migrations_for_trait(
+            min_captures,
+            var_hir_id,
+            tcx.lang_items().unpin_trait(),
+        ) {
+            auto_trait_reasons.insert("`Unpin`");
+        }
+
+        if self.need_2229_migrations_for_trait(
+            min_captures,
+            var_hir_id,
+            tcx.lang_items().unwind_safe_trait(),
+        ) {
+            auto_trait_reasons.insert("`UnwindSafe`");
+        }
+
+        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<M: 'static + Any + Send>(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",