Skip to content

Commit

Permalink
Remove the implicit 'static bound on Send.
Browse files Browse the repository at this point in the history
Previously Send was defined as `trait Send: 'static {}`. As detailed in
rust-lang/rfcs#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.
  • Loading branch information
huonw committed Feb 17, 2015
1 parent f9aeea7 commit cae969e
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 32 deletions.
10 changes: 10 additions & 0 deletions src/libcore/marker.rs
Expand Up @@ -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")]
Expand Down
32 changes: 3 additions & 29 deletions src/librustc/middle/traits/select.rs
Expand Up @@ -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};
Expand All @@ -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;
Expand Down Expand Up @@ -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]))
}
}
Expand Down Expand Up @@ -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={}",
Expand Down
5 changes: 2 additions & 3 deletions src/librustc/util/ppaux.rs
Expand Up @@ -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));
}

Expand Down

0 comments on commit cae969e

Please sign in to comment.