diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 27acc39c77863..8a7c7b38287ec 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -174,6 +174,9 @@ impl Session {
     pub fn fileline_note(&self, sp: Span, msg: &str) {
         self.diagnostic().fileline_note(sp, msg)
     }
+    pub fn fileline_help(&self, sp: Span, msg: &str) {
+        self.diagnostic().fileline_help(sp, msg)
+    }
     pub fn note(&self, msg: &str) {
         self.diagnostic().handler().note(msg)
     }
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 0c53a16a8118b..345bc5fd2aa60 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -12,7 +12,6 @@
 
 use astconv::AstConv;
 use check::{FnCtxt};
-use check::{impl_self_ty};
 use check::vtable;
 use check::vtable::select_new_fcx_obligations;
 use middle::subst;
@@ -20,7 +19,7 @@ use middle::traits;
 use middle::ty::*;
 use middle::ty;
 use middle::infer;
-use util::ppaux::{Repr, UserString};
+use util::ppaux::Repr;
 
 use std::rc::Rc;
 use syntax::ast::{DefId};
@@ -30,14 +29,18 @@ use syntax::codemap::Span;
 pub use self::MethodError::*;
 pub use self::CandidateSource::*;
 
+pub use self::suggest::{report_error, AllTraitsVec};
+
 mod confirm;
 mod doc;
 mod probe;
+mod suggest;
 
 pub enum MethodError {
     // Did not find an applicable method, but we did find various
-    // static methods that may apply.
-    NoMatch(Vec<CandidateSource>),
+    // static methods that may apply, as well as a list of
+    // not-in-scope traits which may work.
+    NoMatch(Vec<CandidateSource>, Vec<ast::DefId>),
 
     // Multiple methods might apply.
     Ambiguity(Vec<CandidateSource>),
@@ -63,7 +66,7 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 {
     match probe::probe(fcx, span, method_name, self_ty, call_expr_id) {
         Ok(_) => true,
-        Err(NoMatch(_)) => false,
+        Err(NoMatch(_, _)) => false,
         Err(Ambiguity(_)) => true,
     }
 }
@@ -294,105 +297,6 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     Some(callee)
 }
 
-pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                              span: Span,
-                              rcvr_ty: Ty<'tcx>,
-                              method_name: ast::Name,
-                              error: MethodError)
-{
-    match error {
-        NoMatch(static_sources) => {
-            let cx = fcx.tcx();
-            let method_ustring = method_name.user_string(cx);
-
-            // True if the type is a struct and contains a field with
-            // the same name as the not-found method
-            let is_field = match rcvr_ty.sty {
-                ty_struct(did, _) =>
-                    ty::lookup_struct_fields(cx, did)
-                        .iter()
-                        .any(|f| f.name.user_string(cx) == method_ustring),
-                _ => false
-            };
-
-            fcx.type_error_message(
-                span,
-                |actual| {
-                    format!("type `{}` does not implement any \
-                             method in scope named `{}`",
-                            actual,
-                            method_ustring)
-                },
-                rcvr_ty,
-                None);
-
-            // If the method has the name of a field, give a help note
-            if is_field {
-                cx.sess.span_note(span,
-                    &format!("use `(s.{0})(...)` if you meant to call the \
-                            function stored in the `{0}` field", method_ustring)[]);
-            }
-
-            if static_sources.len() > 0 {
-                fcx.tcx().sess.fileline_note(
-                    span,
-                    "found defined static methods, maybe a `self` is missing?");
-
-                report_candidates(fcx, span, method_name, static_sources);
-            }
-        }
-
-        Ambiguity(sources) => {
-            span_err!(fcx.sess(), span, E0034,
-                      "multiple applicable methods in scope");
-
-            report_candidates(fcx, span, method_name, sources);
-        }
-    }
-
-    fn report_candidates(fcx: &FnCtxt,
-                         span: Span,
-                         method_name: ast::Name,
-                         mut sources: Vec<CandidateSource>) {
-        sources.sort();
-        sources.dedup();
-
-        for (idx, source) in sources.iter().enumerate() {
-            match *source {
-                ImplSource(impl_did) => {
-                    // Provide the best span we can. Use the method, if local to crate, else
-                    // the impl, if local to crate (method may be defaulted), else the call site.
-                    let method = impl_method(fcx.tcx(), impl_did, method_name).unwrap();
-                    let impl_span = fcx.tcx().map.def_id_span(impl_did, span);
-                    let method_span = fcx.tcx().map.def_id_span(method.def_id, impl_span);
-
-                    let impl_ty = impl_self_ty(fcx, span, impl_did).ty;
-
-                    let insertion = match impl_trait_ref(fcx.tcx(), impl_did) {
-                        None => format!(""),
-                        Some(trait_ref) => format!(" of the trait `{}`",
-                                                   ty::item_path_str(fcx.tcx(),
-                                                                     trait_ref.def_id)),
-                    };
-
-                    span_note!(fcx.sess(), method_span,
-                               "candidate #{} is defined in an impl{} for the type `{}`",
-                               idx + 1u,
-                               insertion,
-                               impl_ty.user_string(fcx.tcx()));
-                }
-                TraitSource(trait_did) => {
-                    let (_, method) = trait_method(fcx.tcx(), trait_did, method_name).unwrap();
-                    let method_span = fcx.tcx().map.def_id_span(method.def_id, span);
-                    span_note!(fcx.sess(), method_span,
-                               "candidate #{} is defined in the trait `{}`",
-                               idx + 1u,
-                               ty::item_path_str(fcx.tcx(), trait_did));
-                }
-            }
-        }
-    }
-}
 
 /// Find method with name `method_name` defined in `trait_def_id` and return it, along with its
 /// index (or `None`, if no such method).
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index dc4d6c9a826c9..9df8875152e3b 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -11,6 +11,7 @@
 use super::{MethodError,Ambiguity,NoMatch};
 use super::MethodIndex;
 use super::{CandidateSource,ImplSource,TraitSource};
+use super::suggest;
 
 use check;
 use check::{FnCtxt, NoPreference};
@@ -25,6 +26,7 @@ use middle::infer::InferCtxt;
 use syntax::ast;
 use syntax::codemap::{Span, DUMMY_SP};
 use std::collections::HashSet;
+use std::mem;
 use std::rc::Rc;
 use util::ppaux::Repr;
 
@@ -42,6 +44,7 @@ struct ProbeContext<'a, 'tcx:'a> {
     extension_candidates: Vec<Candidate<'tcx>>,
     impl_dups: HashSet<ast::DefId>,
     static_candidates: Vec<CandidateSource>,
+    all_traits_search: bool,
 }
 
 struct CandidateStep<'tcx> {
@@ -127,7 +130,7 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // take place in the `fcx.infcx().probe` below.
     let steps = match create_steps(fcx, span, self_ty) {
         Some(steps) => steps,
-        None => return Err(NoMatch(Vec::new())),
+        None => return Err(NoMatch(Vec::new(), Vec::new())),
     };
 
     // Create a list of simplified self types, if we can.
@@ -208,9 +211,17 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             steps: Rc::new(steps),
             opt_simplified_steps: opt_simplified_steps,
             static_candidates: Vec::new(),
+            all_traits_search: false,
         }
     }
 
+    fn reset(&mut self) {
+        self.inherent_candidates.clear();
+        self.extension_candidates.clear();
+        self.impl_dups.clear();
+        self.static_candidates.clear();
+    }
+
     fn tcx(&self) -> &'a ty::ctxt<'tcx> {
         self.fcx.tcx()
     }
@@ -446,6 +457,15 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         }
     }
 
+    fn assemble_extension_candidates_for_all_traits(&mut self) {
+        let mut duplicates = HashSet::new();
+        for trait_info in suggest::all_traits(self.fcx.ccx) {
+            if duplicates.insert(trait_info.def_id) {
+                self.assemble_extension_candidates_for_trait(trait_info.def_id)
+            }
+        }
+    }
+
     fn assemble_extension_candidates_for_trait(&mut self,
                                                trait_def_id: ast::DefId) {
         debug!("assemble_extension_candidates_for_trait(trait_def_id={})",
@@ -715,7 +735,47 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             }
         }
 
-        Err(NoMatch(self.static_candidates))
+        let static_candidates = mem::replace(&mut self.static_candidates, vec![]);
+
+        let out_of_scope_traits = if !self.all_traits_search {
+            // things failed, and we haven't yet looked through all
+            // traits, so lets do that now:
+            self.reset();
+            self.all_traits_search = true;
+
+            let span = self.span;
+            let tcx = self.tcx();
+
+            self.assemble_extension_candidates_for_all_traits();
+
+            match self.pick() {
+                Ok(p) => vec![p.method_ty.container.id()],
+                Err(Ambiguity(v)) => v.into_iter().map(|source| {
+                    match source {
+                        TraitSource(id) => id,
+                        ImplSource(impl_id) => {
+                            match ty::trait_id_of_impl(tcx, impl_id) {
+                                Some(id) => id,
+                                None => tcx.sess.span_bug(span,
+                                                          "found inherent method when looking \
+                                                           at traits")
+                            }
+                        }
+                    }
+                }).collect(),
+                // it'd be really weird for this assertion to trigger,
+                // given the `vec![]` in the else branch below
+                Err(NoMatch(_, others)) => {
+                    assert!(others.is_empty());
+                    vec![]
+                }
+            }
+        } else {
+            // we've just looked through all traits and didn't find
+            // anything at all.
+            vec![]
+        };
+        Err(NoMatch(static_candidates, out_of_scope_traits))
     }
 
     fn pick_step(&mut self, step: &CandidateStep<'tcx>) -> Option<PickResult<'tcx>> {
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
new file mode 100644
index 0000000000000..013c6e2f953a0
--- /dev/null
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -0,0 +1,306 @@
+// 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.
+
+//! Give useful errors and suggestions to users when a method can't be
+//! found or is otherwise invalid.
+
+use CrateCtxt;
+
+use astconv::AstConv;
+use check::{self, FnCtxt};
+use middle::ty::{self, Ty};
+use middle::def;
+use metadata::{csearch, cstore, decoder};
+use util::ppaux::UserString;
+
+use syntax::{ast, ast_util};
+use syntax::codemap::Span;
+
+use std::cell;
+use std::cmp::Ordering;
+
+use super::{MethodError, CandidateSource, impl_method, trait_method};
+
+pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                              span: Span,
+                              rcvr_ty: Ty<'tcx>,
+                              method_name: ast::Name,
+                              error: MethodError)
+{
+    match error {
+        MethodError::NoMatch(static_sources, out_of_scope_traits) => {
+            let cx = fcx.tcx();
+            let method_ustring = method_name.user_string(cx);
+
+            // True if the type is a struct and contains a field with
+            // the same name as the not-found method
+            let is_field = match rcvr_ty.sty {
+                ty::ty_struct(did, _) =>
+                    ty::lookup_struct_fields(cx, did)
+                        .iter()
+                        .any(|f| f.name.user_string(cx) == method_ustring),
+                _ => false
+            };
+
+            fcx.type_error_message(
+                span,
+                |actual| {
+                    format!("type `{}` does not implement any \
+                             method in scope named `{}`",
+                            actual,
+                            method_ustring)
+                },
+                rcvr_ty,
+                None);
+
+            // If the method has the name of a field, give a help note
+            if is_field {
+                cx.sess.span_note(span,
+                    &format!("use `(s.{0})(...)` if you meant to call the \
+                            function stored in the `{0}` field", method_ustring)[]);
+            }
+
+            if static_sources.len() > 0 {
+                fcx.tcx().sess.fileline_note(
+                    span,
+                    "found defined static methods, maybe a `self` is missing?");
+
+                report_candidates(fcx, span, method_name, static_sources);
+            }
+
+            suggest_traits_to_import(fcx, span, rcvr_ty, method_name, out_of_scope_traits)
+        }
+
+        MethodError::Ambiguity(sources) => {
+            span_err!(fcx.sess(), span, E0034,
+                      "multiple applicable methods in scope");
+
+            report_candidates(fcx, span, method_name, sources);
+        }
+    }
+
+    fn report_candidates(fcx: &FnCtxt,
+                         span: Span,
+                         method_name: ast::Name,
+                         mut sources: Vec<CandidateSource>) {
+        sources.sort();
+        sources.dedup();
+
+        for (idx, source) in sources.iter().enumerate() {
+            match *source {
+                CandidateSource::ImplSource(impl_did) => {
+                    // Provide the best span we can. Use the method, if local to crate, else
+                    // the impl, if local to crate (method may be defaulted), else the call site.
+                    let method = impl_method(fcx.tcx(), impl_did, method_name).unwrap();
+                    let impl_span = fcx.tcx().map.def_id_span(impl_did, span);
+                    let method_span = fcx.tcx().map.def_id_span(method.def_id, impl_span);
+
+                    let impl_ty = check::impl_self_ty(fcx, span, impl_did).ty;
+
+                    let insertion = match ty::impl_trait_ref(fcx.tcx(), impl_did) {
+                        None => format!(""),
+                        Some(trait_ref) => format!(" of the trait `{}`",
+                                                   ty::item_path_str(fcx.tcx(),
+                                                                     trait_ref.def_id)),
+                    };
+
+                    span_note!(fcx.sess(), method_span,
+                               "candidate #{} is defined in an impl{} for the type `{}`",
+                               idx + 1u,
+                               insertion,
+                               impl_ty.user_string(fcx.tcx()));
+                }
+                CandidateSource::TraitSource(trait_did) => {
+                    let (_, method) = trait_method(fcx.tcx(), trait_did, method_name).unwrap();
+                    let method_span = fcx.tcx().map.def_id_span(method.def_id, span);
+                    span_note!(fcx.sess(), method_span,
+                               "candidate #{} is defined in the trait `{}`",
+                               idx + 1u,
+                               ty::item_path_str(fcx.tcx(), trait_did));
+                }
+            }
+        }
+    }
+}
+
+
+pub type AllTraitsVec = Vec<TraitInfo>;
+
+fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                      span: Span,
+                                      _rcvr_ty: Ty<'tcx>,
+                                      method_name: ast::Name,
+                                      valid_out_of_scope_traits: Vec<ast::DefId>)
+{
+    let tcx = fcx.tcx();
+    let method_ustring = method_name.user_string(tcx);
+
+    if !valid_out_of_scope_traits.is_empty() {
+        let mut candidates = valid_out_of_scope_traits;
+        candidates.sort();
+        let msg = format!(
+            "methods from traits can only be called if the trait is in scope; \
+             the following {traits_are} implemented and {define} a method `{name}`:",
+            traits_are = if candidates.len() == 1 {"trait is"} else {"traits are"},
+            define = if candidates.len() == 1 {"defines"} else {"define"},
+            name = method_ustring);
+
+        fcx.sess().fileline_help(span, &msg[]);
+
+        for (i, trait_did) in candidates.iter().enumerate() {
+            fcx.sess().fileline_help(span,
+                                     &*format!("candidate #{}: `{}`",
+                                               i + 1,
+                                               ty::item_path_str(fcx.tcx(), *trait_did)))
+
+        }
+        return
+    }
+
+    // there's no implemented traits, so lets suggest some traits to implement
+    let mut candidates = all_traits(fcx.ccx)
+        .filter(|info| trait_method(tcx, info.def_id, method_name).is_some())
+        .collect::<Vec<_>>();
+
+    if candidates.len() > 0 {
+        // sort from most relevant to least relevant
+        candidates.sort_by(|a, b| a.cmp(b).reverse());
+
+        let msg = format!(
+            "methods from traits can only be called if the trait is implemented and \
+             in scope; no such traits are but the following {traits_define} a method `{name}`:",
+            traits_define = if candidates.len() == 1 {"trait defines"} else {"traits define"},
+            name = method_ustring);
+
+        fcx.sess().fileline_help(span, &msg[]);
+
+        for (i, trait_info) in candidates.iter().enumerate() {
+            fcx.sess().fileline_help(span,
+                                     &*format!("candidate #{}: `{}`",
+                                               i + 1,
+                                               ty::item_path_str(fcx.tcx(), trait_info.def_id)))
+        }
+    }
+}
+
+#[derive(Copy)]
+pub struct TraitInfo {
+    pub def_id: ast::DefId,
+}
+
+impl TraitInfo {
+    fn new(def_id: ast::DefId) -> TraitInfo {
+        TraitInfo {
+            def_id: def_id,
+        }
+    }
+}
+impl PartialEq for TraitInfo {
+    fn eq(&self, other: &TraitInfo) -> bool {
+        self.cmp(other) == Ordering::Equal
+    }
+}
+impl Eq for TraitInfo {}
+impl PartialOrd for TraitInfo {
+    fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> { Some(self.cmp(other)) }
+}
+impl Ord for TraitInfo {
+    fn cmp(&self, other: &TraitInfo) -> Ordering {
+        // accessible traits are more important/relevant than
+        // inaccessible ones, local crates are more important than
+        // remote ones (local: cnum == 0), and NodeIds just for
+        // totality.
+
+        let lhs = (other.def_id.krate, other.def_id.node);
+        let rhs = (self.def_id.krate, self.def_id.node);
+        lhs.cmp(&rhs)
+    }
+}
+
+/// Retrieve all traits in this crate and any dependent crates.
+pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
+    if ccx.all_traits.borrow().is_none() {
+        use syntax::visit;
+
+        let mut traits = vec![];
+
+        // Crate-local:
+        //
+        // meh.
+        struct Visitor<'a, 'b: 'a, 'tcx: 'a + 'b> {
+            traits: &'a mut AllTraitsVec,
+        }
+        impl<'v,'a, 'b, 'tcx> visit::Visitor<'v> for Visitor<'a, 'b, 'tcx> {
+            fn visit_item(&mut self, i: &'v ast::Item) {
+                match i.node {
+                    ast::ItemTrait(..) => {
+                        self.traits.push(TraitInfo::new(ast_util::local_def(i.id)));
+                    }
+                    _ => {}
+                }
+                visit::walk_item(self, i)
+            }
+        }
+        visit::walk_crate(&mut Visitor {
+            traits: &mut traits
+        }, ccx.tcx.map.krate());
+
+        // Cross-crate:
+        fn handle_external_def(traits: &mut AllTraitsVec,
+                               ccx: &CrateCtxt,
+                               cstore: &cstore::CStore,
+                               dl: decoder::DefLike) {
+            match dl {
+                decoder::DlDef(def::DefTrait(did)) => {
+                    traits.push(TraitInfo::new(did));
+                }
+                decoder::DlDef(def::DefMod(did)) => {
+                    csearch::each_child_of_item(cstore, did, |dl, _, _| {
+                        handle_external_def(traits, ccx, cstore, dl)
+                    })
+                }
+                _ => {}
+            }
+        }
+        let cstore = &ccx.tcx.sess.cstore;
+        cstore.iter_crate_data(|&mut: cnum, _| {
+            csearch::each_top_level_item_of_crate(cstore, cnum, |dl, _, _| {
+                handle_external_def(&mut traits, ccx, cstore, dl)
+            })
+        });
+
+        *ccx.all_traits.borrow_mut() = Some(traits);
+    }
+
+    let borrow = ccx.all_traits.borrow();
+    assert!(borrow.is_some());
+    AllTraits {
+        borrow: borrow,
+        idx: 0
+    }
+}
+
+pub struct AllTraits<'a> {
+    borrow: cell::Ref<'a Option<AllTraitsVec>>,
+    idx: usize
+}
+
+impl<'a> Iterator for AllTraits<'a> {
+    type Item = TraitInfo;
+
+    fn next(&mut self) -> Option<TraitInfo> {
+        let AllTraits { ref borrow, ref mut idx } = *self;
+        // ugh.
+        borrow.as_ref().unwrap().get(*idx).map(|info| {
+            *idx += 1;
+            *info
+        })
+    }
+}
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 68b152dee233b..88fe88bf26540 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -108,6 +108,8 @@ use syntax::print::pprust::*;
 use syntax::{ast, ast_map, abi};
 use syntax::ast_util::local_def;
 
+use std::cell::RefCell;
+
 mod check;
 mod rscope;
 mod astconv;
@@ -123,6 +125,11 @@ struct TypeAndSubsts<'tcx> {
 struct CrateCtxt<'a, 'tcx: 'a> {
     // A mapping from method call sites to traits that have that method.
     trait_map: ty::TraitMap,
+    /// A vector of every trait accessible in the whole crate
+    /// (i.e. including those from subcrates). This is used only for
+    /// error reporting, and so is lazily initialised and generally
+    /// shouldn't taint the common path (hence the RefCell).
+    all_traits: RefCell<Option<check::method::AllTraitsVec>>,
     tcx: &'a ty::ctxt<'tcx>,
 }
 
@@ -320,6 +327,7 @@ pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
     let time_passes = tcx.sess.time_passes();
     let ccx = CrateCtxt {
         trait_map: trait_map,
+        all_traits: RefCell::new(None),
         tcx: tcx
     };
 
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index 3f81dac2b0d62..36058b694eac4 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -118,6 +118,9 @@ impl SpanHandler {
     pub fn fileline_note(&self, sp: Span, msg: &str) {
         self.handler.custom_emit(&self.cm, FileLine(sp), msg, Note);
     }
+    pub fn fileline_help(&self, sp: Span, msg: &str) {
+        self.handler.custom_emit(&self.cm, FileLine(sp), msg, Help);
+    }
     pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
         self.handler.emit(Some((&self.cm, sp)), msg, Bug);
         panic!(ExplicitBug);
diff --git a/src/test/auxiliary/no_method_suggested_traits.rs b/src/test/auxiliary/no_method_suggested_traits.rs
new file mode 100644
index 0000000000000..328561495eef0
--- /dev/null
+++ b/src/test/auxiliary/no_method_suggested_traits.rs
@@ -0,0 +1,43 @@
+// Copyright 2015 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.
+
+pub use reexport::Reexported;
+
+pub mod foo {
+    pub trait PubPub {
+        fn method(&self) {}
+
+        fn method3(&self) {}
+    }
+
+    impl PubPub for u32 {}
+    impl PubPub for i32 {}
+}
+pub mod bar {
+    trait PubPriv {
+        fn method(&self);
+    }
+}
+mod qux {
+    pub trait PrivPub {
+        fn method(&self);
+    }
+}
+mod quz {
+    trait PrivPriv {
+        fn method(&self);
+    }
+}
+
+mod reexport {
+    pub trait Reexported {
+        fn method(&self);
+    }
+}
diff --git a/src/test/compile-fail/no-method-suggested-traits.rs b/src/test/compile-fail/no-method-suggested-traits.rs
new file mode 100644
index 0000000000000..277800778a87e
--- /dev/null
+++ b/src/test/compile-fail/no-method-suggested-traits.rs
@@ -0,0 +1,62 @@
+// Copyright 2015 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.
+
+// aux-build:no_method_suggested_traits.rs
+
+extern crate no_method_suggested_traits;
+
+mod foo {
+    trait Bar {
+        fn method(&self) {}
+
+        fn method2(&self) {}
+    }
+
+    impl Bar for u32 {}
+
+    impl Bar for char {}
+}
+
+fn main() {
+    1u32.method();
+    //~^ ERROR does not implement
+    //~^^ HELP the following traits are implemented and define a method `method`
+    //~^^^ HELP `foo::Bar`
+    //~^^^^ HELP `no_method_suggested_traits::foo::PubPub`
+
+    'a'.method();
+    //~^ ERROR does not implement
+    //~^^ HELP the following trait is implemented and defines a method `method`
+    //~^^^ HELP `foo::Bar`
+
+    1i32.method();
+    //~^ ERROR does not implement
+    //~^^ HELP the following trait is implemented and defines a method `method`
+    //~^^^ HELP `no_method_suggested_traits::foo::PubPub`
+
+    1u64.method();
+    //~^ ERROR does not implement
+    //~^^ HELP the following traits define a method `method`
+    //~^^^ HELP `foo::Bar`
+    //~^^^^ HELP `no_method_suggested_traits::foo::PubPub`
+    //~^^^^^ HELP `no_method_suggested_traits::reexport::Reexported`
+    //~^^^^^^ HELP `no_method_suggested_traits::bar::PubPriv`
+    //~^^^^^^^ HELP `no_method_suggested_traits::qux::PrivPub`
+    //~^^^^^^^^ HELP `no_method_suggested_traits::quz::PrivPriv`
+
+    1u64.method2();
+    //~^ ERROR does not implement
+    //~^^ HELP the following trait defines a method `method2`
+    //~^^^ HELP `foo::Bar`
+    1u64.method3();
+    //~^ ERROR does not implement
+    //~^^ HELP the following trait defines a method `method3`
+    //~^^^ HELP `no_method_suggested_traits::foo::PubPub`
+}