Remove the implicit 'static
bound on Send
.
Previously Send was defined as `trait Send: 'static {}`. As detailed in https://github.com/rust-lang/rfcs/pull/458, the `'static` bound is not actually necessary for safety, we can use lifetimes to enforce that more flexibly. `unsafe` code that was previously relying on `Send` to insert a `'static` bound now may allow incorrect patterns, and so should be audited (a quick way to ensure safety immediately and postpone the audit is to add an explicit `'static` bound to any uses of the `Send` type). cc #22251.
This commit is contained in:
parent
f9aeea7cb7
commit
cae969e2a7
3 changed files with 15 additions and 32 deletions
|
@ -32,9 +32,19 @@ use clone::Clone;
|
|||
reason = "will be overhauled with new lifetime rules; see RFC 458")]
|
||||
#[lang="send"]
|
||||
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
||||
#[cfg(stage0)] // SNAP ac134f7 remove after stage0
|
||||
pub unsafe trait Send: 'static {
|
||||
// empty.
|
||||
}
|
||||
/// Types able to be transferred across thread boundaries.
|
||||
#[unstable(feature = "core",
|
||||
reason = "will be overhauled with new lifetime rules; see RFC 458")]
|
||||
#[lang="send"]
|
||||
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
||||
#[cfg(not(stage0))]
|
||||
pub unsafe trait Send {
|
||||
// empty.
|
||||
}
|
||||
|
||||
/// Types with a constant size known at compile-time.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
|
@ -20,7 +20,7 @@ use self::EvaluationResult::*;
|
|||
use super::{DerivedObligationCause};
|
||||
use super::{project};
|
||||
use super::project::Normalized;
|
||||
use super::{PredicateObligation, Obligation, TraitObligation, ObligationCause};
|
||||
use super::{PredicateObligation, TraitObligation, ObligationCause};
|
||||
use super::{ObligationCauseCode, BuiltinDerivedObligation};
|
||||
use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
|
||||
use super::{Selection};
|
||||
|
@ -34,7 +34,7 @@ use super::{util};
|
|||
use middle::fast_reject;
|
||||
use middle::mem_categorization::Typer;
|
||||
use middle::subst::{Subst, Substs, TypeSpace, VecPerParamSpace};
|
||||
use middle::ty::{self, AsPredicate, RegionEscape, ToPolyTraitRef, Ty};
|
||||
use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
|
||||
use middle::infer;
|
||||
use middle::infer::{InferCtxt, TypeFreshener};
|
||||
use middle::ty_fold::TypeFoldable;
|
||||
|
@ -1459,22 +1459,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
ty::BoundSync |
|
||||
ty::BoundSend => {
|
||||
// Note: technically, a region pointer is only
|
||||
// sendable if it has lifetime
|
||||
// `'static`. However, we don't take regions
|
||||
// into account when doing trait matching:
|
||||
// instead, when we decide that `T : Send`, we
|
||||
// will register a separate constraint with
|
||||
// the region inferencer that `T : 'static`
|
||||
// holds as well (because the trait `Send`
|
||||
// requires it). This will ensure that there
|
||||
// is no borrowed data in `T` (or else report
|
||||
// an inference error). The reason we do it
|
||||
// this way is that we do not yet *know* what
|
||||
// lifetime the borrowed reference has, since
|
||||
// we haven't finished running inference -- in
|
||||
// other words, there's a kind of
|
||||
// chicken-and-egg problem.
|
||||
Ok(If(vec![referent_ty]))
|
||||
}
|
||||
}
|
||||
|
@ -1817,21 +1801,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
})
|
||||
}).collect::<Result<_, _>>();
|
||||
let mut obligations = match obligations {
|
||||
let obligations = match obligations {
|
||||
Ok(o) => o,
|
||||
Err(ErrorReported) => Vec::new()
|
||||
};
|
||||
|
||||
// as a special case, `Send` requires `'static`
|
||||
if bound == ty::BoundSend {
|
||||
obligations.push(Obligation {
|
||||
cause: obligation.cause.clone(),
|
||||
recursion_depth: obligation.recursion_depth+1,
|
||||
predicate: ty::Binder(ty::OutlivesPredicate(obligation.self_ty(),
|
||||
ty::ReStatic)).as_predicate(),
|
||||
});
|
||||
}
|
||||
|
||||
let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new());
|
||||
|
||||
debug!("vtable_builtin_data: obligations={}",
|
||||
|
|
|
@ -697,9 +697,8 @@ impl<'tcx> UserString<'tcx> for ty::TyTrait<'tcx> {
|
|||
}
|
||||
|
||||
// Region, if not obviously implied by builtin bounds.
|
||||
if bounds.region_bound != ty::ReStatic ||
|
||||
!bounds.builtin_bounds.contains(&ty::BoundSend)
|
||||
{ // Region bound is implied by builtin bounds:
|
||||
if bounds.region_bound != ty::ReStatic {
|
||||
// Region bound is implied by builtin bounds:
|
||||
components.push(bounds.region_bound.user_string(tcx));
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue