Skip to content

Commit

Permalink
rustc: catch non-trait methods before typeck.
Browse files Browse the repository at this point in the history
Closes #3973.
  • Loading branch information
Ryman committed Jun 23, 2014
1 parent d77cb22 commit 579a139
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 8 deletions.
18 changes: 18 additions & 0 deletions src/librustc/middle/resolve.rs
Expand Up @@ -4021,6 +4021,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);
Expand All @@ -4030,6 +4033,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.
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/middle/typeck/check/mod.rs
Expand Up @@ -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 `{}`",
Expand Down
18 changes: 11 additions & 7 deletions src/test/compile-fail/issue-3973.rs
Expand Up @@ -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());
}

0 comments on commit 579a139

Please sign in to comment.