about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/resolve.rs57
-rw-r--r--src/test/compile-fail/issue-14254.rs113
-rw-r--r--src/test/run-pass/issue-14254.rs100
3 files changed, 252 insertions, 18 deletions
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 87919c8a4f4..cd3375799a3 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -4891,6 +4891,25 @@ impl<'a> Resolver<'a> {
     }
 
     fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion {
+        #[deriving(Eq)]
+        enum FallbackChecks {
+            Everything,
+            OnlyTraitAndStatics
+        }
+
+        fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks)
+                                                    -> Option<(Path, NodeId, FallbackChecks)> {
+            match t.node {
+                TyPath(ref path, _, node_id) => Some((path.clone(), node_id, allow)),
+                TyPtr(mut_ty) => extract_path_and_node_id(mut_ty.ty, OnlyTraitAndStatics),
+                TyRptr(_, mut_ty) => extract_path_and_node_id(mut_ty.ty, allow),
+                // This doesn't handle the remaining `Ty` variants as they are not
+                // that commonly the self_type, it might be interesting to provide
+                // support for those in future.
+                _ => None,
+            }
+        }
+
         fn get_module(this: &mut Resolver, span: Span, ident_path: &[ast::Ident])
                             -> Option<Rc<Module>> {
             let root = this.current_module.clone();
@@ -4918,27 +4937,29 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        let (path, node_id) = match self.current_self_type {
-            Some(ref ty) => match ty.node {
-                TyPath(ref path, _, node_id) => (path.clone(), node_id),
-                _ => unreachable!(),
+        let (path, node_id, allowed) = match self.current_self_type {
+            Some(ref ty) => match extract_path_and_node_id(ty, Everything) {
+                Some(x) => x,
+                None => return NoSuggestion,
             },
             None => return NoSuggestion,
         };
 
-        // Look for a field with the same name in the current self_type.
-        match self.def_map.borrow().find(&node_id) {
-             Some(&DefTy(did))
-            | Some(&DefStruct(did))
-            | Some(&DefVariant(_, did, _)) => match self.structs.find(&did) {
-                None => {}
-                Some(fields) => {
-                    if fields.iter().any(|&field_name| name == field_name) {
-                        return Field;
+        if allowed == Everything {
+            // Look for a field with the same name in the current self_type.
+            match self.def_map.borrow().find(&node_id) {
+                 Some(&DefTy(did))
+                | Some(&DefStruct(did))
+                | Some(&DefVariant(_, did, _)) => match self.structs.find(&did) {
+                    None => {}
+                    Some(fields) => {
+                        if fields.iter().any(|&field_name| name == field_name) {
+                            return Field;
+                        }
                     }
-                }
-            },
-            _ => {} // Self type didn't resolve properly
+                },
+                _ => {} // Self type didn't resolve properly
+            }
         }
 
         let ident_path = path.segments.iter().map(|seg| seg.identifier).collect::<Vec<_>>();
@@ -4955,8 +4976,8 @@ impl<'a> Resolver<'a> {
                                 FromTrait(_) => unreachable!()
                             }
                         }
-                        Some(DefMethod(_, None)) => return Method,
-                        Some(DefMethod(_, _)) => return TraitMethod,
+                        Some(DefMethod(_, None)) if allowed == Everything => return Method,
+                        Some(DefMethod(_, Some(_))) => return TraitMethod,
                         _ => ()
                     }
                 }
diff --git a/src/test/compile-fail/issue-14254.rs b/src/test/compile-fail/issue-14254.rs
new file mode 100644
index 00000000000..8b7267ab776
--- /dev/null
+++ b/src/test/compile-fail/issue-14254.rs
@@ -0,0 +1,113 @@
+// 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.
+
+trait Foo {
+    fn bar(&self);
+    fn baz(&self) { }
+    fn bah(_: Option<Self>) { }
+}
+
+struct BarTy {
+    x : int,
+    y : f64,
+}
+
+impl BarTy {
+    fn a() {}
+    fn b(&self) {}
+}
+
+impl Foo for *BarTy {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+        a;
+        //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
+    }
+}
+
+impl<'a> Foo for &'a BarTy {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+        x;
+        //~^ ERROR: unresolved name `x`. Did you mean `self.x`?
+        y;
+        //~^ ERROR: unresolved name `y`. Did you mean `self.y`?
+        a;
+        //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
+        bah;
+        //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
+        b;
+        //~^ ERROR: unresolved name `b`. Did you mean to call `self.b`?
+    }
+}
+
+impl<'a> Foo for &'a mut BarTy {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+        x;
+        //~^ ERROR: unresolved name `x`. Did you mean `self.x`?
+        y;
+        //~^ ERROR: unresolved name `y`. Did you mean `self.y`?
+        a;
+        //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
+        bah;
+        //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
+        b;
+        //~^ ERROR: unresolved name `b`. Did you mean to call `self.b`?
+    }
+}
+
+impl Foo for Box<BarTy> {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+        bah;
+        //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
+    }
+}
+
+impl Foo for *int {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+        bah;
+        //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
+    }
+}
+
+impl<'a> Foo for &'a int {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+        bah;
+        //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
+    }
+}
+
+impl<'a> Foo for &'a mut int {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+        bah;
+        //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
+    }
+}
+
+impl Foo for Box<int> {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+        bah;
+        //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
+    }
+}
diff --git a/src/test/run-pass/issue-14254.rs b/src/test/run-pass/issue-14254.rs
new file mode 100644
index 00000000000..a3ead0a6685
--- /dev/null
+++ b/src/test/run-pass/issue-14254.rs
@@ -0,0 +1,100 @@
+// 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.
+
+trait Foo {
+    fn bar(&self);
+    fn baz(&self) { }
+    fn bah(_: Option<Self>) { }
+}
+
+struct BarTy {
+    x : int,
+    y : f64,
+}
+
+impl BarTy {
+    fn a() {}
+    fn b(&self) {}
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl Foo for *BarTy {
+    fn bar(&self) {
+        self.baz();
+        BarTy::a();
+        Foo::bah(None::<*BarTy>);
+    }
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl<'a> Foo for &'a BarTy {
+    fn bar(&self) {
+        self.baz();
+        self.x;
+        self.y;
+        BarTy::a();
+        Foo::bah(None::<&BarTy>);
+        self.b();
+    }
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl<'a> Foo for &'a mut BarTy {
+    fn bar(&self) {
+        self.baz();
+        self.x;
+        self.y;
+        BarTy::a();
+        Foo::bah(None::<&mut BarTy>);
+        self.b();
+    }
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl Foo for Box<BarTy> {
+    fn bar(&self) {
+        self.baz();
+        Foo::bah(None::<Box<BarTy>>);
+    }
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl Foo for *int {
+    fn bar(&self) {
+        self.baz();
+        Foo::bah(None::<*int>);
+    }
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl<'a> Foo for &'a int {
+    fn bar(&self) {
+        self.baz();
+        Foo::bah(None::<&int>);
+    }
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl<'a> Foo for &'a mut int {
+    fn bar(&self) {
+        self.baz();
+        Foo::bah(None::<&mut int>);
+    }
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl Foo for Box<int> {
+    fn bar(&self) {
+        self.baz();
+        Foo::bah(None::<Box<int>>);
+    }
+}
+
+fn main() {}