diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 377863b016d85..d469191dc273b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -576,7 +576,9 @@ impl<'a, 'v> Visitor<'v> for Resolver<'a> { self.visit_generics(&sig.generics); MethodRibKind(!sig.decl.has_self()) } - FnKind::Closure => ClosureRibKind(node_id), + FnKind::Closure => { + ClosureRibKind(node_id) + } }; self.resolve_function(rib_kind, declaration, block); } @@ -1617,6 +1619,8 @@ impl<'a> Resolver<'a> { this.visit_generics(generics); walk_list!(this, visit_ty_param_bound, bounds); + let mut types = Vec::new(); + let mut methods = Vec::new(); for trait_item in trait_items { match trait_item.node { TraitItemKind::Const(_, ref default) => { @@ -1631,6 +1635,12 @@ impl<'a> Resolver<'a> { visit::walk_trait_item(this, trait_item) } } + TraitItemKind::Type(..) => { + this.with_type_parameter_rib(NoTypeParameters, |this| { + visit::walk_trait_item(this, trait_item) + }); + types.push(format!("{}", trait_item.ident)); + } TraitItemKind::Method(ref sig, _) => { let type_parameters = HasTypeParameters(&sig.generics, @@ -1639,14 +1649,38 @@ impl<'a> Resolver<'a> { this.with_type_parameter_rib(type_parameters, |this| { visit::walk_trait_item(this, trait_item) }); - } - TraitItemKind::Type(..) => { - this.with_type_parameter_rib(NoTypeParameters, |this| { - visit::walk_trait_item(this, trait_item) - }); + methods.push(sig.clone()); } }; } + if types.len() > 0 { + for method in methods { + for arg in method.decl.inputs.iter() { + if let Some(paths) = arg.ty.get_path() { + for path in paths { + if path.segments.len() == 2 && + &format!("{}", + path.segments[0].identifier) == "Self" { + let name = format!("{}", + path.segments[1].identifier); + let mut found = false; + for ty in types.iter() { + if ty == &name { + found = true; + break; + } + } + if found == false { + let error_variant = + ResolutionError::UndeclaredAssociatedType; + resolve_error(this, arg.ty.span, error_variant); + } + } + } + } + } + } + } }); }); } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 8537fcc221c95..c3138ea6b5a3b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1578,6 +1578,32 @@ impl fmt::Debug for Ty { } } +impl Ty { + pub fn get_path(&self) -> Option<Vec<Path>> { + match self.node { + TyKind::Vec(ref p) | TyKind::FixedLengthVec(ref p, _) => p.get_path(), + TyKind::Ptr(ref p) | TyKind::Rptr(_, ref p) => p.ty.get_path(), + TyKind::Tup(ref v) => { + let mut res = Vec::new(); + for path in v { + if let Some(p) = path.get_path() { + for path in p { + res.push(path); + } + } + } + if res.len() > 0 { + Some(res) + } else { + None + } + } + TyKind::Path(_, ref p) => Some(vec!(p.clone())), + _ => None, + } + } +} + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct BareFnTy { pub unsafety: Unsafety, diff --git a/src/test/compile-fail/E0406.rs b/src/test/compile-fail/E0406.rs new file mode 100644 index 0000000000000..66f82f2c1a821 --- /dev/null +++ b/src/test/compile-fail/E0406.rs @@ -0,0 +1,23 @@ +// Copyright 2016 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 { + type Bar; + type Bar2; + + fn return_bool(&self, &Self::Bar, &Self::Baz) -> bool; + //~^ ERROR E0406 + //~| ERROR E0220 + fn return_bool2(&self, &(u32, Self::Babar)) -> bool; + //~^ ERROR E0406 + //~| ERROR E0220 +} + +fn main() {}