]> git.lizzy.rs Git - rust.git/commitdiff
rustc: catch non-trait methods before typeck.
authorKevin Butler <haqkrs@gmail.com>
Wed, 18 Jun 2014 13:16:45 +0000 (14:16 +0100)
committerKevin Butler <haqkrs@gmail.com>
Mon, 23 Jun 2014 16:38:32 +0000 (17:38 +0100)
Closes #3973.

src/librustc/middle/resolve.rs
src/librustc/middle/typeck/check/mod.rs
src/test/compile-fail/issue-3973.rs

index 5ce63b94b2499b6f9cf4fdb06c502c0f4e1184f9..6c916272593dc9f0ff9188c9a65212eaa34f9e40 100644 (file)
@@ -4021,6 +4021,9 @@ fn resolve_implementation(&mut self,
 
                 this.with_current_self_type(self_type, |this| {
                     for method in methods.iter() {
+                        // If this is a trait impl, ensure the method exists in trait
+                        this.check_trait_method(&**method);
+
                         // We also need a new scope for the method-specific type parameters.
                         this.resolve_method(MethodRibKind(id, Provided(method.id)),
                                             &**method);
@@ -4030,6 +4033,21 @@ fn resolve_implementation(&mut self,
         });
     }
 
+    fn check_trait_method(&self, method: &Method) {
+        // If there is a TraitRef in scope for an impl, then the method must be in the trait.
+        for &(did, ref trait_ref) in self.current_trait_ref.iter() {
+            let method_name = method.ident.name;
+
+            if self.method_map.borrow().find(&(method_name, did)).is_none() {
+                let path_str = self.path_idents_to_str(&trait_ref.path);
+                self.resolve_error(method.span,
+                                    format!("method `{}` is not a member of trait `{}`",
+                                            token::get_name(method_name),
+                                            path_str).as_slice());
+            }
+        }
+    }
+
     fn resolve_module(&mut self, module: &Mod, _span: Span,
                       _name: Ident, id: NodeId) {
         // Write the implementations in scope into the module metadata.
index 1c5cfc45afdb80061d77729245512533794b4ad2..04db13feff65489ea77c69ca0fba4a4289631f99 100644 (file)
@@ -784,7 +784,8 @@ fn check_impl_methods_against_trait(ccx: &CrateCtxt,
                                     &impl_trait_ref.substs);
             }
             None => {
-                tcx.sess.span_err(
+                // This is span_bug as it should have already been caught in resolve.
+                tcx.sess.span_bug(
                     impl_method.span,
                     format!(
                         "method `{}` is not a member of trait `{}`",
index 7fe7778c1a59e981aeb2fa5a4c72697c9ce6082f..d2d7625842a07b9d94fb2c070ee21c7aa1806148 100644 (file)
@@ -8,26 +8,30 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test
-
-use std::io;
-
 struct Point {
     x: f64,
     y: f64,
 }
 
-impl ToStr for Point { //~ ERROR implements a method not defined in the trait
+trait NewTrait {
+    fn a(&self) -> String;
+}
+
+impl NewTrait for Point {
     fn new(x: f64, y: f64) -> Point {
+    //~^ ERROR method `new` is not a member of trait `NewTrait`
         Point { x: x, y: y }
     }
 
-    fn to_str(&self) -> String {
+    fn a(&self) -> String {
         format!("({}, {})", self.x, self.y)
     }
 }
 
 fn main() {
     let p = Point::new(0.0, 0.0);
-    println!("{}", p.to_str());
+    //~^ ERROR unresolved name `Point::new`
+    //~^^ ERROR unresolved name
+    //~^^^ ERROR use of undeclared module `Point`
+    println!("{}", p.a());
 }