]> git.lizzy.rs Git - rust.git/commitdiff
libs: add Deref, DerefMut impls for references, fixing a bug in compiler in the proce...
authorNiko Matsakis <niko@alum.mit.edu>
Thu, 6 Nov 2014 22:34:33 +0000 (17:34 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Fri, 7 Nov 2014 02:51:40 +0000 (21:51 -0500)
Fixes #18621.

src/liballoc/arc.rs
src/libcore/ops.rs
src/librustc/middle/typeck/check/method.rs
src/libstd/collections/hash/table.rs
src/test/run-pass/deref-mut-on-ref.rs [new file with mode: 0644]
src/test/run-pass/deref-on-ref.rs [new file with mode: 0644]

index f543826fe01878a2ff58ab70dfccb4a20523bc4b..c4f53d744673ffe0eaeed138350244e3b58e8287 100644 (file)
@@ -166,7 +166,7 @@ pub fn make_unique(&mut self) -> &mut 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
index ac735492be4a5408a2afdc3b79b56ca4c9737604..2631d0d44236828c461d5ae95ffcfa96c37adedc 100644 (file)
@@ -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> {
index f854bc52acd7b3a009c4f230f58ff527f8b5483b..ecc42f09a59e1cdc569ca05fc300ab509137b02f 100644 (file)
@@ -1702,13 +1702,18 @@ fn fixup_derefs_on_method_receiver_if_necessary(&self,
                             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);
+                        }
                     }
                     _ => {}
                 }
index 4d73029b7b06b50e3101c238d521d35c81bb0e27..fd964cdf02c5363fe8c15b12b7694dd6cfd78539 100644 (file)
@@ -166,18 +166,22 @@ unsafe fn offset(self, count: int) -> 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 (file)
index 0000000..dcf7c48
--- /dev/null
@@ -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 (file)
index 0000000..27e7d8f
--- /dev/null
@@ -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);
+}