1
Fork 0

use the correct attributes and add helper function

This commit is contained in:
Roxane 2021-05-09 10:06:24 -04:00
parent acfc708b7c
commit 564b4de626
2 changed files with 84 additions and 102 deletions

View file

@ -583,6 +583,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.infcx.predicate_may_hold(&obligation) 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<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 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 /// 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 /// captured by the closure when `capture_disjoint_fields` is enabled and auto-traits
/// differ between the root variable and the captured paths. /// 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( fn compute_2229_migrations_for_trait(
&self, &self,
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
_closure_clause: hir::CaptureBy,
var_hir_id: hir::HirId, var_hir_id: hir::HirId,
) -> Option<FxHashSet<&str>> { ) -> Option<FxHashSet<&str>> {
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 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 // Check whether catpured fields also implement the trait
let mut auto_trait_reasons = FxHashSet::default(); let mut auto_trait_reasons = FxHashSet::default();
for capture in root_var_min_capture_list.iter() { if self.need_2229_migrations_for_trait(
let ty = capture.place.ty(); min_captures,
var_hir_id,
tcx.lang_items().clone_trait(),
) {
auto_trait_reasons.insert("`Clone`");
}
let clone_obligation_holds_for_capture = tcx if self.need_2229_migrations_for_trait(
.lang_items() min_captures,
.clone_trait() var_hir_id,
.map(|clone_trait| self.ty_impls_trait(ty, &cause, clone_trait)) tcx.lang_items().sync_trait(),
.unwrap_or(false); ) {
let sync_obligation_holds_for_capture = tcx auto_trait_reasons.insert("`Sync`");
.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 !clone_obligation_holds_for_capture && clone_obligation_should_hold { if self.need_2229_migrations_for_trait(
auto_trait_reasons.insert("`Clone`"); 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 { if self.need_2229_migrations_for_trait(
auto_trait_reasons.insert("`Sync`"); 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 { if self.need_2229_migrations_for_trait(
auto_trait_reasons.insert("`Send`"); 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 { if self.need_2229_migrations_for_trait(
auto_trait_reasons.insert("`Unpin`"); min_captures,
} var_hir_id,
tcx.lang_items().ref_unwind_safe_trait(),
if !unwind_safe_obligation_holds_for_capture && unwind_safe_obligation_should_hold { ) {
auto_trait_reasons.insert("`UnwindSafe`"); auto_trait_reasons.insert("`RefUnwindSafe`");
}
if !ref_unwind_safe_obligation_holds_for_capture
&& ref_unwind_safe_obligation_should_hold
{
auto_trait_reasons.insert("`RefUnwindSafe`");
}
} }
if auto_trait_reasons.len() > 0 { 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 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 /// - One of the paths captured does not implement all the auto-traits its root variable
/// implements. /// implements.
/// ///
/// Returns a tuple containing a vector of HirIds as well as a String containing the reason /// 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. /// why root variables whose HirId is contained in the vector should be fully captured.
fn compute_2229_migrations( fn compute_2229_migrations(
@ -820,7 +802,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for (&var_hir_id, _) in upvars.iter() { for (&var_hir_id, _) in upvars.iter() {
let mut need_migration = false; let mut need_migration = false;
if let Some(trait_migration_cause) = 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; need_migration = true;
auto_trait_reasons.extend(trait_migration_cause); auto_trait_reasons.extend(trait_migration_cause);

View file

@ -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 /// [`AssertUnwindSafe`] wrapper struct can be used to force this trait to be
/// implemented for any closed over variables passed to `catch_unwind`. /// implemented for any closed over variables passed to `catch_unwind`.
#[stable(feature = "catch_unwind", since = "1.9.0")] #[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( #[rustc_on_unimplemented(
message = "the type `{Self}` may not be safely transferred across an unwind boundary", message = "the type `{Self}` may not be safely transferred across an unwind boundary",
label = "`{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 /// This is a "helper marker trait" used to provide impl blocks for the
/// [`UnwindSafe`] trait, for more information see that documentation. /// [`UnwindSafe`] trait, for more information see that documentation.
#[stable(feature = "catch_unwind", since = "1.9.0")] #[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( #[rustc_on_unimplemented(
message = "the type `{Self}` may contain interior mutability and a reference may not be safely \ message = "the type `{Self}` may contain interior mutability and a reference may not be safely \
transferrable across a catch_unwind boundary", transferrable across a catch_unwind boundary",