Skip to content

Commit cae969e

Browse files
committed
Remove the implicit 'static bound on Send.
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.
1 parent f9aeea7 commit cae969e

File tree

3 files changed

+15
-32
lines changed

3 files changed

+15
-32
lines changed

src/libcore/marker.rs

+10
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,19 @@ use clone::Clone;
3232
reason = "will be overhauled with new lifetime rules; see RFC 458")]
3333
#[lang="send"]
3434
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
35+
#[cfg(stage0)] // SNAP ac134f7 remove after stage0
3536
pub unsafe trait Send: 'static {
3637
// empty.
3738
}
39+
/// Types able to be transferred across thread boundaries.
40+
#[unstable(feature = "core",
41+
reason = "will be overhauled with new lifetime rules; see RFC 458")]
42+
#[lang="send"]
43+
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
44+
#[cfg(not(stage0))]
45+
pub unsafe trait Send {
46+
// empty.
47+
}
3848

3949
/// Types with a constant size known at compile-time.
4050
#[stable(feature = "rust1", since = "1.0.0")]

src/librustc/middle/traits/select.rs

+3-29
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use self::EvaluationResult::*;
2020
use super::{DerivedObligationCause};
2121
use super::{project};
2222
use super::project::Normalized;
23-
use super::{PredicateObligation, Obligation, TraitObligation, ObligationCause};
23+
use super::{PredicateObligation, TraitObligation, ObligationCause};
2424
use super::{ObligationCauseCode, BuiltinDerivedObligation};
2525
use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
2626
use super::{Selection};
@@ -34,7 +34,7 @@ use super::{util};
3434
use middle::fast_reject;
3535
use middle::mem_categorization::Typer;
3636
use middle::subst::{Subst, Substs, TypeSpace, VecPerParamSpace};
37-
use middle::ty::{self, AsPredicate, RegionEscape, ToPolyTraitRef, Ty};
37+
use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
3838
use middle::infer;
3939
use middle::infer::{InferCtxt, TypeFreshener};
4040
use middle::ty_fold::TypeFoldable;
@@ -1459,22 +1459,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14591459

14601460
ty::BoundSync |
14611461
ty::BoundSend => {
1462-
// Note: technically, a region pointer is only
1463-
// sendable if it has lifetime
1464-
// `'static`. However, we don't take regions
1465-
// into account when doing trait matching:
1466-
// instead, when we decide that `T : Send`, we
1467-
// will register a separate constraint with
1468-
// the region inferencer that `T : 'static`
1469-
// holds as well (because the trait `Send`
1470-
// requires it). This will ensure that there
1471-
// is no borrowed data in `T` (or else report
1472-
// an inference error). The reason we do it
1473-
// this way is that we do not yet *know* what
1474-
// lifetime the borrowed reference has, since
1475-
// we haven't finished running inference -- in
1476-
// other words, there's a kind of
1477-
// chicken-and-egg problem.
14781462
Ok(If(vec![referent_ty]))
14791463
}
14801464
}
@@ -1817,21 +1801,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
18171801
}
18181802
})
18191803
}).collect::<Result<_, _>>();
1820-
let mut obligations = match obligations {
1804+
let obligations = match obligations {
18211805
Ok(o) => o,
18221806
Err(ErrorReported) => Vec::new()
18231807
};
18241808

1825-
// as a special case, `Send` requires `'static`
1826-
if bound == ty::BoundSend {
1827-
obligations.push(Obligation {
1828-
cause: obligation.cause.clone(),
1829-
recursion_depth: obligation.recursion_depth+1,
1830-
predicate: ty::Binder(ty::OutlivesPredicate(obligation.self_ty(),
1831-
ty::ReStatic)).as_predicate(),
1832-
});
1833-
}
1834-
18351809
let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new());
18361810

18371811
debug!("vtable_builtin_data: obligations={}",

src/librustc/util/ppaux.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -697,9 +697,8 @@ impl<'tcx> UserString<'tcx> for ty::TyTrait<'tcx> {
697697
}
698698

699699
// Region, if not obviously implied by builtin bounds.
700-
if bounds.region_bound != ty::ReStatic ||
701-
!bounds.builtin_bounds.contains(&ty::BoundSend)
702-
{ // Region bound is implied by builtin bounds:
700+
if bounds.region_bound != ty::ReStatic {
701+
// Region bound is implied by builtin bounds:
703702
components.push(bounds.region_bound.user_string(tcx));
704703
}
705704

0 commit comments

Comments
 (0)