diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index f543826fe0187..c4f53d744673f 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -166,7 +166,7 @@ impl<T: Send + Sync + Clone> Arc<T> { // additional reference of either kind. if self.inner().strong.load(atomic::SeqCst) != 1 || self.inner().weak.load(atomic::SeqCst) != 1 { - *self = Arc::new(self.deref().clone()) + *self = Arc::new((**self).clone()) } // This unsafety is ok because we're guaranteed that the pointer // returned is the *only* pointer that will ever be returned to T. Our diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index ac735492be4a5..2631d0d442368 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -805,6 +805,16 @@ pub trait Deref<Sized? Result> { fn deref<'a>(&'a self) -> &'a Result; } +#[cfg(not(stage0))] +impl<'a, Sized? T> Deref<T> for &'a T { + fn deref(&self) -> &T { *self } +} + +#[cfg(not(stage0))] +impl<'a, Sized? T> Deref<T> for &'a mut T { + fn deref(&self) -> &T { *self } +} + /** * * The `DerefMut` trait is used to specify the functionality of dereferencing @@ -845,6 +855,11 @@ pub trait DerefMut<Sized? Result>: Deref<Result> { fn deref_mut<'a>(&'a mut self) -> &'a mut Result; } +#[cfg(not(stage0))] +impl<'a, Sized? T> DerefMut<T> for &'a mut T { + fn deref_mut(&mut self) -> &mut T { *self } +} + /// A version of the call operator that takes an immutable receiver. #[lang="fn"] pub trait Fn<Args,Result> { diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index f854bc52acd7b..ecc42f09a59e1 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -1702,13 +1702,18 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> { PreferMutLvalue); } ast::ExprUnary(ast::UnDeref, ref base_expr) => { - check::try_overloaded_deref( - self.fcx, - expr.span, - Some(MethodCall::expr(expr.id)), - Some(&**base_expr), - self.fcx.expr_ty(&**base_expr), - PreferMutLvalue); + // if this is an overloaded deref, then re-evaluate with + // a preference for mut + let method_call = MethodCall::expr(expr.id); + if self.fcx.inh.method_map.borrow().contains_key(&method_call) { + check::try_overloaded_deref( + self.fcx, + expr.span, + Some(method_call), + Some(&**base_expr), + self.fcx.expr_ty(&**base_expr), + PreferMutLvalue); + } } _ => {} } diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 4d73029b7b06b..fd964cdf02c53 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -166,18 +166,22 @@ impl<K, V> RawBucket<K, V> { } // For parameterizing over mutability. + +#[cfg(stage0)] impl<'t, K, V> Deref<RawTable<K, V>> for &'t RawTable<K, V> { fn deref(&self) -> &RawTable<K, V> { &**self } } +#[cfg(stage0)] impl<'t, K, V> Deref<RawTable<K, V>> for &'t mut RawTable<K, V> { fn deref(&self) -> &RawTable<K,V> { &**self } } +#[cfg(stage0)] impl<'t, K, V> DerefMut<RawTable<K, V>> for &'t mut RawTable<K, V> { fn deref_mut(&mut self) -> &mut RawTable<K,V> { &mut **self diff --git a/src/test/run-pass/deref-mut-on-ref.rs b/src/test/run-pass/deref-mut-on-ref.rs new file mode 100644 index 0000000000000..dcf7c483b2cdc --- /dev/null +++ b/src/test/run-pass/deref-mut-on-ref.rs @@ -0,0 +1,21 @@ +// Copyright 2014 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. + +// Test that `&mut T` implements `DerefMut<T>` + +fn inc<T:DerefMut<int>>(mut t: T) { + *t += 1; +} + +fn main() { + let mut x: int = 5; + inc(&mut x); + assert_eq!(x, 6); +} diff --git a/src/test/run-pass/deref-on-ref.rs b/src/test/run-pass/deref-on-ref.rs new file mode 100644 index 0000000000000..27e7d8f3ba2a4 --- /dev/null +++ b/src/test/run-pass/deref-on-ref.rs @@ -0,0 +1,25 @@ +// Copyright 2014 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. + +// Test that `&T` and `&mut T` implement `Deref<T>` + +fn deref<U:Copy,T:Deref<U>>(t: T) -> U { + *t +} + +fn main() { + let x: int = 3; + let y = deref(&x); + assert_eq!(y, 3); + + let mut x: int = 4; + let y = deref(&mut x); + assert_eq!(y, 4); +}