about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2014-09-22 17:38:49 -0700
committerPatrick Walton <pcwalton@mimiga.net>2014-09-26 13:02:47 -0700
commit21df9c805f6e0101cff7a04391c6c5fcff8056df (patch)
tree5242f7c1eae334e68e7709667a0f63b850e9beaf
parent5d653c17a656e8fe1572c7a695e33b188eda0597 (diff)
downloadrust-21df9c805f6e0101cff7a04391c6c5fcff8056df.tar.gz
rust-21df9c805f6e0101cff7a04391c6c5fcff8056df.zip
librustc: Give trait methods accessible via fewer autoderefs priority
over inherent methods accessible via more autoderefs.

This simplifies the trait matching algorithm. It breaks code like:

    impl Foo {
        fn foo(self) {
            // before this change, this will be called
        }
    }

    impl<'a,'b,'c> Trait for &'a &'b &'c Foo {
        fn foo(self) {
            // after this change, this will be called
        }
    }

    fn main() {
        let x = &(&(&Foo));
        x.foo();
    }

To explicitly indicate that you wish to call the inherent method, perform
explicit dereferences. For example:

    fn main() {
        let x = &(&(&Foo));
        (***x).foo();
    }

Part of #17282.

[breaking-change]
-rw-r--r--src/librustc/middle/typeck/check/method.rs11
-rw-r--r--src/librustc/util/ppaux.rs3
-rw-r--r--src/libstd/io/mod.rs15
-rw-r--r--src/test/run-pass/class-cast-to-trait-cross-crate-2.rs2
-rw-r--r--src/test/run-pass/class-separate-impl.rs2
-rw-r--r--src/test/run-pass/inherent-trait-method-order.rs34
-rw-r--r--src/test/run-pass/issue-3702.rs2
7 files changed, 50 insertions, 19 deletions
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 7d28a63d935..141b03d9b9f 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -158,13 +158,7 @@ pub fn lookup<'a, 'tcx>(
 
     debug!("searching inherent candidates");
     lcx.push_inherent_candidates(self_ty);
-    let mme = lcx.search(self_ty);
-    if mme.is_some() {
-        return mme;
-    }
-
     debug!("searching extension candidates");
-    lcx.reset_candidates();
     lcx.push_bound_candidates(self_ty, None);
     lcx.push_extension_candidates(expr.id);
     lcx.search(self_ty)
@@ -425,11 +419,6 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
     // ______________________________________________________________________
     // Candidate collection (see comment at start of file)
 
-    fn reset_candidates(&mut self) {
-        self.inherent_candidates = Vec::new();
-        self.extension_candidates = Vec::new();
-    }
-
     fn push_inherent_candidates(&mut self, self_ty: ty::t) {
         /*!
          * Collect all inherent candidates into
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 0a4fd90765c..fcb613426fc 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -881,7 +881,8 @@ impl Repr for ty::Variance {
         // The first `.to_string()` returns a &'static str (it is not an implementation
         // of the ToString trait). Because of that, we need to call `.to_string()` again
         // if we want to have a `String`.
-        self.to_string().to_string()
+        let result: &'static str = (*self).to_string();
+        result.to_string()
     }
 }
 
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index ff508c802d8..81e05648567 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -946,11 +946,14 @@ pub trait Reader {
 }
 
 impl<'a> Reader for Box<Reader+'a> {
-    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.read(buf) }
+    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
+        let reader: &mut Reader = &mut **self;
+        reader.read(buf)
+    }
 }
 
 impl<'a> Reader for &'a mut Reader+'a {
-    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.read(buf) }
+    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { (*self).read(buf) }
 }
 
 /// Returns a slice of `v` between `start` and `end`.
@@ -1281,10 +1284,14 @@ pub trait Writer {
 
 impl<'a> Writer for Box<Writer+'a> {
     #[inline]
-    fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.write(buf) }
+    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
+        (&mut **self).write(buf)
+    }
 
     #[inline]
-    fn flush(&mut self) -> IoResult<()> { self.flush() }
+    fn flush(&mut self) -> IoResult<()> {
+        (&mut **self).flush()
+    }
 }
 
 impl<'a> Writer for &'a mut Writer+'a {
diff --git a/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs b/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs
index a2ae91abd13..cfee1a81231 100644
--- a/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs
+++ b/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs
@@ -15,7 +15,7 @@ use std::to_string::ToString;
 use cci_class_cast::kitty::cat;
 
 fn print_out(thing: Box<ToString>, expected: String) {
-  let actual = thing.to_string();
+  let actual = (*thing).to_string();
   println!("{}", actual);
   assert_eq!(actual.to_string(), expected);
 }
diff --git a/src/test/run-pass/class-separate-impl.rs b/src/test/run-pass/class-separate-impl.rs
index 71438882980..86d7b72f4ff 100644
--- a/src/test/run-pass/class-separate-impl.rs
+++ b/src/test/run-pass/class-separate-impl.rs
@@ -58,7 +58,7 @@ impl fmt::Show for cat {
 }
 
 fn print_out(thing: Box<ToString>, expected: String) {
-  let actual = thing.to_string();
+  let actual = (*thing).to_string();
   println!("{}", actual);
   assert_eq!(actual.to_string(), expected);
 }
diff --git a/src/test/run-pass/inherent-trait-method-order.rs b/src/test/run-pass/inherent-trait-method-order.rs
new file mode 100644
index 00000000000..416c0701804
--- /dev/null
+++ b/src/test/run-pass/inherent-trait-method-order.rs
@@ -0,0 +1,34 @@
+// 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.
+
+struct Foo;
+
+impl Foo {
+    #[allow(dead_code)]
+    fn foo(self) {
+        fail!("wrong method!")
+    }
+}
+
+trait Trait {
+    fn foo(self);
+}
+
+impl<'a,'b,'c> Trait for &'a &'b &'c Foo {
+    fn foo(self) {
+        // ok
+    }
+}
+
+fn main() {
+    let x = &(&(&Foo));
+    x.foo();
+}
+
diff --git a/src/test/run-pass/issue-3702.rs b/src/test/run-pass/issue-3702.rs
index 3f219da0a87..9c09b8cd1c7 100644
--- a/src/test/run-pass/issue-3702.rs
+++ b/src/test/run-pass/issue-3702.rs
@@ -15,7 +15,7 @@ pub fn main() {
   }
 
   fn to_string(t: Box<Text>) {
-    println!("{}", t.to_string());
+    println!("{}", (*t).to_string());
   }
 
 }