about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2012-09-25 15:15:42 -0700
committerNiko Matsakis <niko@alum.mit.edu>2012-09-25 15:22:38 -0700
commit12a0401d84dc033fc4e03484b334de3cb20bab30 (patch)
tree5e3bd153179dd77d34c3fd5bc97b00c0e6dcca29 /src
parenta770d86201d5b41573b6b5f5bdfe3b70df919b28 (diff)
downloadrust-12a0401d84dc033fc4e03484b334de3cb20bab30.tar.gz
rust-12a0401d84dc033fc4e03484b334de3cb20bab30.zip
Change method res to try autoref more often. Fixes #3585.
Diffstat (limited to 'src')
-rw-r--r--src/rustc/middle/typeck/check/method.rs64
-rw-r--r--src/test/run-pass/autoref-intermediate-types-issue-3585.rs20
-rw-r--r--src/test/run-pass/autoref-vec-push.rs17
3 files changed, 48 insertions, 53 deletions
diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs
index 815101a1448..085ee51eff7 100644
--- a/src/rustc/middle/typeck/check/method.rs
+++ b/src/rustc/middle/typeck/check/method.rs
@@ -48,11 +48,12 @@ candidates in the same way.
 
 If find no matching candidate at all, we proceed to auto-deref the
 receiver type and search again.  We keep doing that until we cannot
-auto-deref any longer.  At that point, we will attempt an auto-ref.
-If THAT fails, method lookup fails altogether.  Autoref itself comes
-in two varieties, autoslice and autoptr.  The former converts `~[]` to
-`&[]` and the latter converts any type `T` to `&mut T`, `&const T`, or
-`&T`.
+auto-deref any longer.  At each step, we also check for candidates
+based on "autoptr", which if the current type is `T`, checks for `&mut
+T`, `&const T`, and `&T` receivers.  Finally, at the very end, we will
+also try autoslice, which converts `~[]` to `&[]` (there is no point
+at trying autoslice earlier, because no autoderefable type is also
+sliceable).
 
 ## Why two phases?
 
@@ -159,22 +160,9 @@ impl LookupContext {
                 None => {}
             }
 
-            // some special logic around newtypes:
-            match ty::get(self_ty).sty {
-                ty_enum(*) => {
-                    // Note: in general, we prefer not to auto-ref a
-                    // partially autoderef'd type, because it
-                    // seems... crazy.  But we have to be careful
-                    // around newtype enums.  They can be further
-                    // deref'd, but they may also have intrinsic
-                    // methods hanging off of them with interior type.
-                    match self.search_for_any_autorefd_method(self_ty,
-                                                              autoderefs) {
-                        Some(move mme) => { return Some(mme); }
-                        None => {}
-                    }
-                }
-                _ => {}
+            match self.search_for_autoptrd_method(self_ty, autoderefs) {
+                Some(move mme) => { return Some(move mme); }
+                None => {}
             }
 
             match self.deref(self_ty, &enum_dids) {
@@ -186,7 +174,7 @@ impl LookupContext {
             }
         }
 
-        self.search_for_any_autorefd_method(self_ty, autoderefs)
+        self.search_for_autosliced_method(self_ty, autoderefs)
     }
 
     fn deref(ty: ty::t, enum_dids: &DVec<ast::def_id>) -> Option<ty::t> {
@@ -516,30 +504,6 @@ impl LookupContext {
         }
     }
 
-    fn search_for_any_autorefd_method(
-        &self,
-        self_ty: ty::t,
-        autoderefs: uint)
-        -> Option<method_map_entry>
-    {
-        /*!
-         *
-         * Attempts both auto-slice and auto-ptr, as appropriate.
-         */
-
-        match self.search_for_autosliced_method(self_ty, autoderefs) {
-            Some(move mme) => { return Some(move mme); }
-            None => {}
-        }
-
-        match self.search_for_autoptrd_method(self_ty, autoderefs) {
-            Some(move mme) => { return Some(move mme); }
-            None => {}
-        }
-
-        return None;
-    }
-
     fn search_for_autosliced_method(
         &self,
         self_ty: ty::t,
@@ -594,13 +558,7 @@ impl LookupContext {
 
         let tcx = self.tcx();
         match ty::get(self_ty).sty {
-            ty_box(*) | ty_uniq(*) | ty_rptr(*) => {
-                // we should be fully autoderef'd
-                self.bug(fmt!("Receiver type %s should be fully \
-                               autoderef'd by this point",
-                              self.ty_to_str(self_ty)));
-            }
-
+            ty_box(*) | ty_uniq(*) | ty_rptr(*) |
             ty_infer(IntVar(_)) | // FIXME(#3211)---should be resolved
             ty_self | ty_param(*) | ty_nil | ty_bot | ty_bool |
             ty_int(*) | ty_uint(*) |
diff --git a/src/test/run-pass/autoref-intermediate-types-issue-3585.rs b/src/test/run-pass/autoref-intermediate-types-issue-3585.rs
new file mode 100644
index 00000000000..68e172bacad
--- /dev/null
+++ b/src/test/run-pass/autoref-intermediate-types-issue-3585.rs
@@ -0,0 +1,20 @@
+trait Foo {
+    fn foo(&self) -> ~str;
+}
+
+impl<T: Foo> @T: Foo {
+    fn foo(&self) -> ~str {
+        fmt!("@%s", (**self).foo())
+    }
+}
+
+impl uint: Foo {
+    fn foo(&self) -> ~str {
+        fmt!("%u", *self)
+    }
+}
+
+fn main() {
+    let x = @3u;
+    assert x.foo() == ~"@3";
+}
\ No newline at end of file
diff --git a/src/test/run-pass/autoref-vec-push.rs b/src/test/run-pass/autoref-vec-push.rs
new file mode 100644
index 00000000000..cb70a1810b7
--- /dev/null
+++ b/src/test/run-pass/autoref-vec-push.rs
@@ -0,0 +1,17 @@
+trait VecPush<T> {
+    fn push(&mut self, +t: T);
+}
+
+impl<T> ~[T]: VecPush<T> {
+    fn push(&mut self, +t: T) {
+        vec::push(*self, t);
+    }
+}
+
+fn main() {
+    let mut x = ~[];
+    x.push(1);
+    x.push(2);
+    x.push(3);
+    assert x == ~[1, 2, 3];
+}
\ No newline at end of file