Skip to content

Commit f2aaed8

Browse files
committed
libs: add Deref, DerefMut impls for references, fixing a bug in compiler in the process that was blocking this.
Fixes #18621.
1 parent e84e7a0 commit f2aaed8

File tree

6 files changed

+78
-8
lines changed

6 files changed

+78
-8
lines changed

src/liballoc/arc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ impl<T: Send + Sync + Clone> Arc<T> {
166166
// additional reference of either kind.
167167
if self.inner().strong.load(atomic::SeqCst) != 1 ||
168168
self.inner().weak.load(atomic::SeqCst) != 1 {
169-
*self = Arc::new(self.deref().clone())
169+
*self = Arc::new((**self).clone())
170170
}
171171
// This unsafety is ok because we're guaranteed that the pointer
172172
// returned is the *only* pointer that will ever be returned to T. Our

src/libcore/ops.rs

+15
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,16 @@ pub trait Deref<Sized? Result> {
805805
fn deref<'a>(&'a self) -> &'a Result;
806806
}
807807

808+
#[cfg(not(stage0))]
809+
impl<'a, Sized? T> Deref<T> for &'a T {
810+
fn deref(&self) -> &T { *self }
811+
}
812+
813+
#[cfg(not(stage0))]
814+
impl<'a, Sized? T> Deref<T> for &'a mut T {
815+
fn deref(&self) -> &T { *self }
816+
}
817+
808818
/**
809819
*
810820
* The `DerefMut` trait is used to specify the functionality of dereferencing
@@ -845,6 +855,11 @@ pub trait DerefMut<Sized? Result>: Deref<Result> {
845855
fn deref_mut<'a>(&'a mut self) -> &'a mut Result;
846856
}
847857

858+
#[cfg(not(stage0))]
859+
impl<'a, Sized? T> DerefMut<T> for &'a mut T {
860+
fn deref_mut(&mut self) -> &mut T { *self }
861+
}
862+
848863
/// A version of the call operator that takes an immutable receiver.
849864
#[lang="fn"]
850865
pub trait Fn<Args,Result> {

src/librustc/middle/typeck/check/method.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -1702,13 +1702,18 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
17021702
PreferMutLvalue);
17031703
}
17041704
ast::ExprUnary(ast::UnDeref, ref base_expr) => {
1705-
check::try_overloaded_deref(
1706-
self.fcx,
1707-
expr.span,
1708-
Some(MethodCall::expr(expr.id)),
1709-
Some(&**base_expr),
1710-
self.fcx.expr_ty(&**base_expr),
1711-
PreferMutLvalue);
1705+
// if this is an overloaded deref, then re-evaluate with
1706+
// a preference for mut
1707+
let method_call = MethodCall::expr(expr.id);
1708+
if self.fcx.inh.method_map.borrow().contains_key(&method_call) {
1709+
check::try_overloaded_deref(
1710+
self.fcx,
1711+
expr.span,
1712+
Some(method_call),
1713+
Some(&**base_expr),
1714+
self.fcx.expr_ty(&**base_expr),
1715+
PreferMutLvalue);
1716+
}
17121717
}
17131718
_ => {}
17141719
}

src/libstd/collections/hash/table.rs

+4
Original file line numberDiff line numberDiff line change
@@ -166,18 +166,22 @@ impl<K, V> RawBucket<K, V> {
166166
}
167167

168168
// For parameterizing over mutability.
169+
170+
#[cfg(stage0)]
169171
impl<'t, K, V> Deref<RawTable<K, V>> for &'t RawTable<K, V> {
170172
fn deref(&self) -> &RawTable<K, V> {
171173
&**self
172174
}
173175
}
174176

177+
#[cfg(stage0)]
175178
impl<'t, K, V> Deref<RawTable<K, V>> for &'t mut RawTable<K, V> {
176179
fn deref(&self) -> &RawTable<K,V> {
177180
&**self
178181
}
179182
}
180183

184+
#[cfg(stage0)]
181185
impl<'t, K, V> DerefMut<RawTable<K, V>> for &'t mut RawTable<K, V> {
182186
fn deref_mut(&mut self) -> &mut RawTable<K,V> {
183187
&mut **self

src/test/run-pass/deref-mut-on-ref.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that `&mut T` implements `DerefMut<T>`
12+
13+
fn inc<T:DerefMut<int>>(mut t: T) {
14+
*t += 1;
15+
}
16+
17+
fn main() {
18+
let mut x: int = 5;
19+
inc(&mut x);
20+
assert_eq!(x, 6);
21+
}

src/test/run-pass/deref-on-ref.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that `&T` and `&mut T` implement `Deref<T>`
12+
13+
fn deref<U:Copy,T:Deref<U>>(t: T) -> U {
14+
*t
15+
}
16+
17+
fn main() {
18+
let x: int = 3;
19+
let y = deref(&x);
20+
assert_eq!(y, 3);
21+
22+
let mut x: int = 4;
23+
let y = deref(&mut x);
24+
assert_eq!(y, 4);
25+
}

0 commit comments

Comments
 (0)