Skip to content

Backport of PRs to Beta #25192

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 7, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions src/libcollections/string.rs
Original file line number Diff line number Diff line change
@@ -742,8 +742,7 @@ impl<'a> FromIterator<&'a str> for String {
}
}

#[unstable(feature = "collections",
reason = "waiting on Extend stabilization")]
#[stable(feature = "rust1", since = "1.0.0")]
impl Extend<char> for String {
fn extend<I: IntoIterator<Item=char>>(&mut self, iterable: I) {
let iterator = iterable.into_iter();
@@ -755,8 +754,7 @@ impl Extend<char> for String {
}
}

#[unstable(feature = "collections",
reason = "waiting on Extend stabilization")]
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Extend<&'a str> for String {
fn extend<I: IntoIterator<Item=&'a str>>(&mut self, iterable: I) {
let iterator = iterable.into_iter();
@@ -871,8 +869,7 @@ impl hash::Hash for String {
}
}

#[unstable(feature = "collections",
reason = "recent addition, needs more experience")]
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Add<&'a str> for String {
type Output = String;

@@ -965,11 +962,17 @@ pub fn as_string<'a>(x: &'a str) -> DerefString<'a> {
DerefString { x: as_vec(x.as_bytes()) }
}

#[unstable(feature = "collections", reason = "associated error type may change")]
/// Error returned from `String::from_str`
#[unstable(feature = "str_parse_error", reason = "may want to be replaced with \
Void if it ever exists")]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct ParseError(());

#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for String {
type Err = ();
type Err = ParseError;
#[inline]
fn from_str(s: &str) -> Result<String, ()> {
fn from_str(s: &str) -> Result<String, ParseError> {
Ok(String::from_str(s))
}
}
20 changes: 4 additions & 16 deletions src/libcollections/vec.rs
Original file line number Diff line number Diff line change
@@ -59,7 +59,7 @@ use core::intrinsics::assume;
use core::iter::{repeat, FromIterator};
use core::marker::PhantomData;
use core::mem;
use core::ops::{Index, IndexMut, Deref, Add};
use core::ops::{Index, IndexMut, Deref};
use core::ops;
use core::ptr;
use core::ptr::Unique;
@@ -1276,7 +1276,7 @@ pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {
// Common trait implementations for Vec
////////////////////////////////////////////////////////////////////////////////

#[unstable(feature = "collections")]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T:Clone> Clone for Vec<T> {
#[cfg(not(test))]
fn clone(&self) -> Vec<T> { <[T]>::to_vec(&**self) }
@@ -1531,7 +1531,7 @@ impl<'a, T> IntoIterator for &'a mut Vec<T> {
}
}

#[unstable(feature = "collections", reason = "waiting on Extend stability")]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Extend<T> for Vec<T> {
#[inline]
fn extend<I: IntoIterator<Item=T>>(&mut self, iterable: I) {
@@ -1591,18 +1591,6 @@ impl<T: Ord> Ord for Vec<T> {
}
}

#[unstable(feature = "collections",
reason = "recent addition, needs more experience")]
impl<'a, T: Clone> Add<&'a [T]> for Vec<T> {
type Output = Vec<T>;

#[inline]
fn add(mut self, rhs: &[T]) -> Vec<T> {
self.push_all(rhs);
self
}
}

#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Vec<T> {
@@ -1672,7 +1660,7 @@ impl<'a> From<&'a str> for Vec<u8> {
// Clone-on-write
////////////////////////////////////////////////////////////////////////////////

#[unstable(feature = "collections")]
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> FromIterator<T> for Cow<'a, [T]> where T: Clone {
fn from_iter<I: IntoIterator<Item=T>>(it: I) -> Cow<'a, [T]> {
Cow::Owned(FromIterator::from_iter(it))
13 changes: 4 additions & 9 deletions src/libcore/iter.rs
Original file line number Diff line number Diff line change
@@ -626,12 +626,10 @@ pub trait Iterator {
/// # Examples
///
/// ```
/// # #![feature(core)]
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter();
/// assert!(it.any(|x| *x == 3));
/// assert_eq!(&it[..], [4, 5]);
///
/// assert_eq!(it.collect::<Vec<_>>(), [&4, &5]);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -654,11 +652,10 @@ pub trait Iterator {
/// # Examples
///
/// ```
/// # #![feature(core)]
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter();
/// assert_eq!(it.find(|&x| *x == 3).unwrap(), &3);
/// assert_eq!(&it[..], [4, 5]);
/// assert_eq!(it.collect::<Vec<_>>(), [&4, &5]);
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
@@ -678,11 +675,10 @@ pub trait Iterator {
/// # Examples
///
/// ```
/// # #![feature(core)]
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter();
/// assert_eq!(it.position(|x| *x == 3).unwrap(), 2);
/// assert_eq!(&it[..], [4, 5]);
/// assert_eq!(it.collect::<Vec<_>>(), [&4, &5]);
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
@@ -708,11 +704,10 @@ pub trait Iterator {
/// # Examples
///
/// ```
/// # #![feature(core)]
/// let a = [1, 2, 2, 4, 5];
/// let mut it = a.iter();
/// assert_eq!(it.rposition(|x| *x == 2).unwrap(), 2);
/// assert_eq!(&it[..], [1, 2]);
/// assert_eq!(it.collect::<Vec<_>>(), [&1, &2]);
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
110 changes: 0 additions & 110 deletions src/libcore/slice.rs
Original file line number Diff line number Diff line change
@@ -736,46 +736,6 @@ pub struct Iter<'a, T: 'a> {
unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {}
unsafe impl<'a, T: Sync> Send for Iter<'a, T> {}

#[unstable(feature = "core")]
impl<'a, T> ops::Index<ops::Range<usize>> for Iter<'a, T> {
type Output = [T];

#[inline]
fn index(&self, index: ops::Range<usize>) -> &[T] {
self.as_slice().index(index)
}
}

#[unstable(feature = "core")]
impl<'a, T> ops::Index<ops::RangeTo<usize>> for Iter<'a, T> {
type Output = [T];

#[inline]
fn index(&self, index: ops::RangeTo<usize>) -> &[T] {
self.as_slice().index(index)
}
}

#[unstable(feature = "core")]
impl<'a, T> ops::Index<ops::RangeFrom<usize>> for Iter<'a, T> {
type Output = [T];

#[inline]
fn index(&self, index: ops::RangeFrom<usize>) -> &[T] {
self.as_slice().index(index)
}
}

#[unstable(feature = "core")]
impl<'a, T> ops::Index<RangeFull> for Iter<'a, T> {
type Output = [T];

#[inline]
fn index(&self, _index: RangeFull) -> &[T] {
self.as_slice()
}
}

impl<'a, T> Iter<'a, T> {
/// View the underlying data as a subslice of the original data.
///
@@ -833,76 +793,6 @@ pub struct IterMut<'a, T: 'a> {
unsafe impl<'a, T: Sync> Sync for IterMut<'a, T> {}
unsafe impl<'a, T: Send> Send for IterMut<'a, T> {}

#[unstable(feature = "core")]
impl<'a, T> ops::Index<ops::Range<usize>> for IterMut<'a, T> {
type Output = [T];

#[inline]
fn index(&self, index: ops::Range<usize>) -> &[T] {
self.index(RangeFull).index(index)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::Index<ops::RangeTo<usize>> for IterMut<'a, T> {
type Output = [T];

#[inline]
fn index(&self, index: ops::RangeTo<usize>) -> &[T] {
self.index(RangeFull).index(index)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::Index<ops::RangeFrom<usize>> for IterMut<'a, T> {
type Output = [T];

#[inline]
fn index(&self, index: ops::RangeFrom<usize>) -> &[T] {
self.index(RangeFull).index(index)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::Index<RangeFull> for IterMut<'a, T> {
type Output = [T];

#[inline]
fn index(&self, _index: RangeFull) -> &[T] {
make_slice!(T => &[T]: self.ptr, self.end)
}
}

#[unstable(feature = "core")]
impl<'a, T> ops::IndexMut<ops::Range<usize>> for IterMut<'a, T> {
#[inline]
fn index_mut(&mut self, index: ops::Range<usize>) -> &mut [T] {
self.index_mut(RangeFull).index_mut(index)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::IndexMut<ops::RangeTo<usize>> for IterMut<'a, T> {

#[inline]
fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut [T] {
self.index_mut(RangeFull).index_mut(index)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::IndexMut<ops::RangeFrom<usize>> for IterMut<'a, T> {

#[inline]
fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut [T] {
self.index_mut(RangeFull).index_mut(index)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::IndexMut<RangeFull> for IterMut<'a, T> {

#[inline]
fn index_mut(&mut self, _index: RangeFull) -> &mut [T] {
make_mut_slice!(T => &mut [T]: self.ptr, self.end)
}
}


impl<'a, T> IterMut<'a, T> {
/// View the underlying data as a subslice of the original data.
///
46 changes: 0 additions & 46 deletions src/libcoretest/slice.rs
Original file line number Diff line number Diff line change
@@ -35,50 +35,4 @@ fn binary_search_not_found() {
}

#[test]
fn iterator_to_slice() {
macro_rules! test {
($data: expr) => {{
let data: &mut [_] = &mut $data;
let other_data: &mut [_] = &mut $data;

{
let mut iter = data.iter();
assert_eq!(&iter[..], &other_data[..]);

iter.next();
assert_eq!(&iter[..], &other_data[1..]);

iter.next_back();
assert_eq!(&iter[..], &other_data[1..2]);

let s = iter.as_slice();
iter.next();
assert_eq!(s, &other_data[1..2]);
}
{
let mut iter = data.iter_mut();
assert_eq!(&iter[..], &other_data[..]);
// mutability:
assert!(&mut iter[..] == other_data);

iter.next();
assert_eq!(&iter[..], &other_data[1..]);
assert!(&mut iter[..] == &mut other_data[1..]);

iter.next_back();

assert_eq!(&iter[..], &other_data[1..2]);
assert!(&mut iter[..] == &mut other_data[1..2]);

let s = iter.into_slice();
assert!(s == &mut other_data[1..2]);
}
}}
}

// try types of a variety of sizes
test!([(1u64, 1u64, 1u8), (2, 2, 2), (3, 3, 3)]);
test!([1u64,2,3]);
test!([1u8,2,3]);
test!([(),(),()]);
}
8 changes: 4 additions & 4 deletions src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
@@ -855,10 +855,10 @@ pub fn monitor<F:FnOnce()+Send+'static>(f: F) {
pub fn diagnostics_registry() -> diagnostics::registry::Registry {
use syntax::diagnostics::registry::Registry;

let all_errors = Vec::new() +
&rustc::diagnostics::DIAGNOSTICS[..] +
&rustc_typeck::diagnostics::DIAGNOSTICS[..] +
&rustc_resolve::diagnostics::DIAGNOSTICS[..];
let mut all_errors = Vec::new();
all_errors.push_all(&rustc::diagnostics::DIAGNOSTICS);
all_errors.push_all(&rustc_typeck::diagnostics::DIAGNOSTICS);
all_errors.push_all(&rustc_resolve::diagnostics::DIAGNOSTICS);

Registry::new(&*all_errors)
}
66 changes: 66 additions & 0 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
@@ -2087,6 +2087,72 @@ impl LintPass for InvalidNoMangleItems {
}
}

#[derive(Clone, Copy)]
pub struct MutableTransmutes;

declare_lint! {
MUTABLE_TRANSMUTES,
Deny,
"mutating transmuted &mut T from &T may cause undefined behavior"
}

impl LintPass for MutableTransmutes {
fn get_lints(&self) -> LintArray {
lint_array!(MUTABLE_TRANSMUTES)
}

fn check_expr(&mut self, cx: &Context, expr: &ast::Expr) {
use syntax::ast::DefId;
use syntax::abi::RustIntrinsic;
let msg = "mutating transmuted &mut T from &T may cause undefined behavior,\
consider instead using an UnsafeCell";
match get_transmute_from_to(cx, expr) {
Some((&ty::ty_rptr(_, from_mt), &ty::ty_rptr(_, to_mt))) => {
if to_mt.mutbl == ast::Mutability::MutMutable
&& from_mt.mutbl == ast::Mutability::MutImmutable {
cx.span_lint(MUTABLE_TRANSMUTES, expr.span, msg);
}
}
_ => ()
}

fn get_transmute_from_to<'a, 'tcx>(cx: &Context<'a, 'tcx>, expr: &ast::Expr)
-> Option<(&'tcx ty::sty<'tcx>, &'tcx ty::sty<'tcx>)> {
match expr.node {
ast::ExprPath(..) => (),
_ => return None
}
if let DefFn(did, _) = ty::resolve_expr(cx.tcx, expr) {
if !def_id_is_transmute(cx, did) {
return None;
}
let typ = ty::node_id_to_type(cx.tcx, expr.id);
match typ.sty {
ty::ty_bare_fn(_, ref bare_fn) if bare_fn.abi == RustIntrinsic => {
if let ty::FnConverging(to) = bare_fn.sig.0.output {
let from = bare_fn.sig.0.inputs[0];
return Some((&from.sty, &to.sty));
}
},
_ => ()
}
}
None
}

fn def_id_is_transmute(cx: &Context, def_id: DefId) -> bool {
match ty::lookup_item_type(cx.tcx, def_id).ty.sty {
ty::ty_bare_fn(_, ref bfty) if bfty.abi == RustIntrinsic => (),
_ => return false
}
ty::with_path(cx.tcx, def_id, |path| match path.last() {
Some(ref last) => last.name().as_str() == "transmute",
_ => false
})
}
}
}

/// Forbids using the `#[feature(...)]` attribute
#[derive(Copy, Clone)]
pub struct UnstableFeatures;
1 change: 1 addition & 0 deletions src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
@@ -110,6 +110,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
InvalidNoMangleItems,
PluginAsLibrary,
DropWithReprExtern,
MutableTransmutes,
);

add_builtin_with_new!(sess,
3 changes: 1 addition & 2 deletions src/libstd/collections/hash/map.rs
Original file line number Diff line number Diff line change
@@ -1607,8 +1607,7 @@ impl HashState for RandomState {
}
}

#[unstable(feature = "std_misc",
reason = "hashing an hash maps may be altered")]
#[stable(feature = "rust1", since = "1.0.0")]
impl Default for RandomState {
#[inline]
fn default() -> RandomState {
34 changes: 21 additions & 13 deletions src/libstd/io/buffered.rs
Original file line number Diff line number Diff line change
@@ -120,7 +120,7 @@ impl<R> fmt::Debug for BufReader<R> where R: fmt::Debug {
}
}

#[unstable(feature = "buf_seek", reason = "recently added")]
#[stable(feature = "rust1", since = "1.0.0")]
impl<R: Seek> Seek for BufReader<R> {
/// Seek to an offset, in bytes, in the underlying reader.
///
@@ -284,8 +284,8 @@ impl<W: Write> fmt::Debug for BufWriter<W> where W: fmt::Debug {
}
}

#[unstable(feature = "buf_seek", reason = "recently added")]
impl<W: Write+Seek> Seek for BufWriter<W> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write + Seek> Seek for BufWriter<W> {
/// Seek to the offset, in bytes, in the underlying writer.
///
/// Seeking always writes out the internal buffer before seeking.
@@ -435,15 +435,19 @@ impl<W: Read + Write> Read for InternalBufWriter<W> {
/// infrequent calls to `read` and `write` on the underlying `Read+Write`.
///
/// The output buffer will be written out when this stream is dropped.
#[stable(feature = "rust1", since = "1.0.0")]
#[unstable(feature = "buf_stream",
reason = "unsure about semantics of buffering two directions, \
leading to issues like #17136")]
pub struct BufStream<S: Write> {
inner: BufReader<InternalBufWriter<S>>
}

#[unstable(feature = "buf_stream",
reason = "unsure about semantics of buffering two directions, \
leading to issues like #17136")]
impl<S: Read + Write> BufStream<S> {
/// Creates a new buffered stream with explicitly listed capacities for the
/// reader/writer buffer.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacities(reader_cap: usize, writer_cap: usize, inner: S)
-> BufStream<S> {
let writer = BufWriter::with_capacity(writer_cap, inner);
@@ -454,13 +458,11 @@ impl<S: Read + Write> BufStream<S> {

/// Creates a new buffered stream with the default reader/writer buffer
/// capacities.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: S) -> BufStream<S> {
BufStream::with_capacities(DEFAULT_BUF_SIZE, DEFAULT_BUF_SIZE, inner)
}

/// Gets a reference to the underlying stream.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &S {
let InternalBufWriter(ref w) = self.inner.inner;
w.get_ref()
@@ -472,7 +474,6 @@ impl<S: Read + Write> BufStream<S> {
///
/// It is inadvisable to read directly from or write directly to the
/// underlying stream.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut S {
let InternalBufWriter(ref mut w) = self.inner.inner;
w.get_mut()
@@ -482,7 +483,6 @@ impl<S: Read + Write> BufStream<S> {
///
/// The internal write buffer is written out before returning the stream.
/// Any leftover data in the read buffer is lost.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> Result<S, IntoInnerError<BufStream<S>>> {
let BufReader { inner: InternalBufWriter(w), buf, pos, cap } = self.inner;
w.into_inner().map_err(|IntoInnerError(w, e)| {
@@ -493,20 +493,26 @@ impl<S: Read + Write> BufStream<S> {
}
}

#[stable(feature = "rust1", since = "1.0.0")]
#[unstable(feature = "buf_stream",
reason = "unsure about semantics of buffering two directions, \
leading to issues like #17136")]
impl<S: Read + Write> BufRead for BufStream<S> {
fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() }
fn consume(&mut self, amt: usize) { self.inner.consume(amt) }
}

#[stable(feature = "rust1", since = "1.0.0")]
#[unstable(feature = "buf_stream",
reason = "unsure about semantics of buffering two directions, \
leading to issues like #17136")]
impl<S: Read + Write> Read for BufStream<S> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
#[unstable(feature = "buf_stream",
reason = "unsure about semantics of buffering two directions, \
leading to issues like #17136")]
impl<S: Read + Write> Write for BufStream<S> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.inner.get_mut().write(buf)
@@ -516,7 +522,9 @@ impl<S: Read + Write> Write for BufStream<S> {
}
}

#[stable(feature = "rust1", since = "1.0.0")]
#[unstable(feature = "buf_stream",
reason = "unsure about semantics of buffering two directions, \
leading to issues like #17136")]
impl<S: Write> fmt::Debug for BufStream<S> where S: fmt::Debug {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let reader = &self.inner;
2 changes: 1 addition & 1 deletion src/libstd/net/parser.rs
Original file line number Diff line number Diff line change
@@ -291,7 +291,7 @@ impl<'a> Parser<'a> {
}
}

#[unstable(feature = "ip_addr", reason = "recent addition")]
#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for IpAddr {
type Err = AddrParseError;
fn from_str(s: &str) -> Result<IpAddr, AddrParseError> {
30 changes: 19 additions & 11 deletions src/libstd/sync/mpsc/select.rs
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@

use core::prelude::*;

use core::cell::Cell;
use core::cell::{Cell, UnsafeCell};
use core::marker;
use core::mem;
use core::ptr;
@@ -70,9 +70,13 @@ use sync::mpsc::blocking::{self, SignalToken};
/// The "receiver set" of the select interface. This structure is used to manage
/// a set of receivers which are being selected over.
pub struct Select {
inner: UnsafeCell<SelectInner>,
next_id: Cell<usize>,
}

struct SelectInner {
head: *mut Handle<'static, ()>,
tail: *mut Handle<'static, ()>,
next_id: Cell<usize>,
}

impl !marker::Send for Select {}
@@ -84,7 +88,7 @@ pub struct Handle<'rx, T:Send+'rx> {
/// The ID of this handle, used to compare against the return value of
/// `Select::wait()`
id: usize,
selector: &'rx Select,
selector: *mut SelectInner,
next: *mut Handle<'static, ()>,
prev: *mut Handle<'static, ()>,
added: bool,
@@ -127,8 +131,10 @@ impl Select {
/// ```
pub fn new() -> Select {
Select {
head: ptr::null_mut(),
tail: ptr::null_mut(),
inner: UnsafeCell::new(SelectInner {
head: ptr::null_mut(),
tail: ptr::null_mut(),
}),
next_id: Cell::new(1),
}
}
@@ -141,7 +147,7 @@ impl Select {
self.next_id.set(id + 1);
Handle {
id: id,
selector: self,
selector: self.inner.get(),
next: ptr::null_mut(),
prev: ptr::null_mut(),
added: false,
@@ -250,7 +256,7 @@ impl Select {
}
}

fn iter(&self) -> Packets { Packets { cur: self.head } }
fn iter(&self) -> Packets { Packets { cur: unsafe { &*self.inner.get() }.head } }
}

impl<'rx, T: Send> Handle<'rx, T> {
@@ -271,7 +277,7 @@ impl<'rx, T: Send> Handle<'rx, T> {
/// while it is added to the `Select` set.
pub unsafe fn add(&mut self) {
if self.added { return }
let selector: &mut Select = mem::transmute(&*self.selector);
let selector = &mut *self.selector;
let me: *mut Handle<'static, ()> = mem::transmute(&*self);

if selector.head.is_null() {
@@ -292,7 +298,7 @@ impl<'rx, T: Send> Handle<'rx, T> {
pub unsafe fn remove(&mut self) {
if !self.added { return }

let selector: &mut Select = mem::transmute(&*self.selector);
let selector = &mut *self.selector;
let me: *mut Handle<'static, ()> = mem::transmute(&*self);

if self.prev.is_null() {
@@ -318,8 +324,10 @@ impl<'rx, T: Send> Handle<'rx, T> {
#[unsafe_destructor]
impl Drop for Select {
fn drop(&mut self) {
assert!(self.head.is_null());
assert!(self.tail.is_null());
unsafe {
assert!((&*self.inner.get()).head.is_null());
assert!((&*self.inner.get()).tail.is_null());
}
}
}

21 changes: 19 additions & 2 deletions src/libstd/sync/rwlock.rs
Original file line number Diff line number Diff line change
@@ -230,7 +230,7 @@ impl<T> RwLock<T> {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> {
if unsafe { self.inner.lock.try_read() } {
if unsafe { self.inner.lock.try_write() } {
Ok(try!(RwLockWriteGuard::new(&*self.inner, &self.data)))
} else {
Err(TryLockError::WouldBlock)
@@ -413,7 +413,7 @@ mod tests {
use rand::{self, Rng};
use sync::mpsc::channel;
use thread;
use sync::{Arc, RwLock, StaticRwLock, RW_LOCK_INIT};
use sync::{Arc, RwLock, StaticRwLock, TryLockError, RW_LOCK_INIT};

#[test]
fn smoke() {
@@ -565,4 +565,21 @@ mod tests {
let lock = arc.read().unwrap();
assert_eq!(*lock, 2);
}

#[test]
fn test_rwlock_try_write() {
use mem::drop;

let lock = RwLock::new(0isize);
let read_guard = lock.read().unwrap();

let write_result = lock.try_write();
match write_result {
Err(TryLockError::WouldBlock) => (),
Ok(_) => assert!(false, "try_write should not succeed while read_guard is in scope"),
Err(_) => assert!(false, "unexpected error"),
}

drop(read_guard);
}
}
4 changes: 2 additions & 2 deletions src/test/auxiliary/issue_8401.rs
Original file line number Diff line number Diff line change
@@ -21,6 +21,6 @@ impl A for B {}
fn bar<T>(_: &mut A, _: &T) {}

fn foo<T>(t: &T) {
let b = B;
bar(unsafe { mem::transmute(&b as &A) }, t)
let mut b = B;
bar(&mut b as &mut A, t)
}
20 changes: 20 additions & 0 deletions src/test/compile-fail/transmute-imut-to-mut.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Tests that transmuting from &T to &mut T is Undefined Behavior.

use std::mem::transmute;

fn main() {
let _a: &mut u8 = unsafe { transmute(&1u8) };
//~^ ERROR mutating transmuted &mut T from &T may cause undefined behavior
}


4 changes: 2 additions & 2 deletions src/test/run-pass/issue-2718.rs
Original file line number Diff line number Diff line change
@@ -172,7 +172,7 @@ pub mod pipes {
unsafe {
if self.p != None {
let self_p: &mut Option<*const packet<T>> =
mem::transmute(&self.p);
mem::transmute(&mut self.p);
let p = replace(self_p, None);
sender_terminate(p.unwrap())
}
@@ -202,7 +202,7 @@ pub mod pipes {
unsafe {
if self.p != None {
let self_p: &mut Option<*const packet<T>> =
mem::transmute(&self.p);
mem::transmute(&mut self.p);
let p = replace(self_p, None);
receiver_terminate(p.unwrap())
}