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:
Huon Wilson 2015-02-13 15:15:05 +11:00
parent f9aeea7cb7
commit cae969e2a7
3 changed files with 15 additions and 32 deletions

View file

@ -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")]

View file

@ -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={}",

View file

@ -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));
}