diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 5ce63b94b2499..ee6c5e1f9bc31 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -3894,8 +3894,31 @@ impl<'a> Resolver<'a> { self.resolve_error(trait_reference.path.span, msg.as_slice()); } Some(def) => { - debug!("(resolving trait) found trait def: {:?}", def); - self.record_def(trait_reference.ref_id, def); + match def { + (DefTrait(_), _) => { + debug!("(resolving trait) found trait def: {:?}", def); + self.record_def(trait_reference.ref_id, def); + } + (def, _) => { + self.resolve_error(trait_reference.path.span, + format!("`{}` is not a trait", + self.path_idents_to_str( + &trait_reference.path))); + + // If it's a typedef, give a note + match def { + DefTy(_) => { + self.session.span_note( + trait_reference.path.span, + format!("`type` aliases cannot \ + be used for traits") + .as_slice()); + } + _ => {} + } + } + } + } } } @@ -4021,6 +4044,9 @@ impl<'a> Resolver<'a> { 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 +4056,21 @@ impl<'a> Resolver<'a> { }); } + 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. diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 1c5cfc45afdb8..04db13feff654 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -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 `{}`", diff --git a/src/test/compile-fail/issue-3907-2.rs b/src/test/compile-fail/issue-3907-2.rs new file mode 100644 index 0000000000000..795e48cb7b005 --- /dev/null +++ b/src/test/compile-fail/issue-3907-2.rs @@ -0,0 +1,20 @@ +// Copyright 2013-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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:issue_3907.rs +extern crate issue_3907; + +type Foo = issue_3907::Foo; //~ ERROR: reference to trait + +struct S { + name: int +} + +fn main() {} diff --git a/src/test/compile-fail/issue-3907.rs b/src/test/compile-fail/issue-3907.rs index 767e674fcda17..a2faef59fd828 100644 --- a/src/test/compile-fail/issue-3907.rs +++ b/src/test/compile-fail/issue-3907.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -11,13 +11,14 @@ // aux-build:issue_3907.rs extern crate issue_3907; -type Foo = issue_3907::Foo; //~ ERROR: reference to trait +type Foo = issue_3907::Foo; struct S { name: int } impl Foo for S { //~ ERROR: `Foo` is not a trait + //~^ NOTE: `type` aliases cannot be used for traits fn bar() { } } diff --git a/src/test/compile-fail/issue-3973.rs b/src/test/compile-fail/issue-3973.rs index 7fe7778c1a59e..9b77d62a06529 100644 --- a/src/test/compile-fail/issue-3973.rs +++ b/src/test/compile-fail/issue-3973.rs @@ -8,26 +8,29 @@ // 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 failed to resolve. Use of undeclared module `Point` + println!("{}", p.a()); } diff --git a/src/test/compile-fail/issue-5035-2.rs b/src/test/compile-fail/issue-5035-2.rs new file mode 100644 index 0000000000000..8d9116da81db2 --- /dev/null +++ b/src/test/compile-fail/issue-5035-2.rs @@ -0,0 +1,14 @@ +// Copyright 2013-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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait I {} +type K = I; //~ ERROR: reference to trait + +fn main() {} diff --git a/src/test/compile-fail/issue-5035.rs b/src/test/compile-fail/issue-5035.rs index 94110f077623b..8ffe308a66939 100644 --- a/src/test/compile-fail/issue-5035.rs +++ b/src/test/compile-fail/issue-5035.rs @@ -9,6 +9,7 @@ // except according to those terms. trait I {} -type K = I; //~ ERROR: reference to trait +type K = I; impl K for int {} //~ ERROR: `K` is not a trait +//~^ NOTE: `type` aliases cannot be used for traits fn main() {}