diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 4f3c12567095e..33d53892c55b2 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -16,7 +16,7 @@
 use self::wrapping::OverflowingOps;
 
 use char::CharExt;
-use cmp::{Eq, PartialOrd};
+use cmp::PartialOrd;
 use convert::From;
 use fmt;
 use intrinsics;
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index aca36d856266b..60b3ed0f6ddf3 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -146,7 +146,6 @@
 use self::Option::*;
 
 use clone::Clone;
-use cmp::{Eq, Ord};
 use default::Default;
 use iter::ExactSizeIterator;
 use iter::{Iterator, DoubleEndedIterator, FromIterator, IntoIterator};
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 7aacdbeb76879..101afa21d2742 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -19,7 +19,6 @@ use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
 
 use char::{self, CharExt};
 use clone::Clone;
-use cmp::Eq;
 use convert::AsRef;
 use default::Default;
 use fmt;
@@ -1180,7 +1179,6 @@ Section: Trait implementations
 mod traits {
     use cmp::{self, Ordering, Ord, PartialEq, PartialOrd, Eq};
     use cmp::Ordering::{Less, Greater};
-    use iter::Iterator;
     use option::Option;
     use option::Option::Some;
     use ops;
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 1ed873f0508d5..56baf9ab6d956 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -29,7 +29,7 @@ use middle::privacy::AccessLevels;
 use middle::ty::{self, Ty};
 use session::{early_error, Session};
 use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass};
-use lint::{EarlyLintPass, EarlyLintPassObject, LateLintPass, LateLintPassObject};
+use lint::{EarlyLintPassObject, LateLintPass, LateLintPassObject};
 use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid};
 use lint::builtin;
 use util::nodemap::FnvHashMap;
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index ec1b447d7111b..4afa0e301465f 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -22,7 +22,7 @@ use lint;
 
 use std::collections::HashSet;
 use syntax::{ast, codemap};
-use syntax::attr::{self, AttrMetaMethods};
+use syntax::attr;
 
 // Any local node that may call something in its body block should be
 // explored. For example, if it's a live NodeItem that is a
diff --git a/src/librustc/middle/implicator.rs b/src/librustc/middle/implicator.rs
index 9f33c4df03d41..6c24134f5a558 100644
--- a/src/librustc/middle/implicator.rs
+++ b/src/librustc/middle/implicator.rs
@@ -15,7 +15,7 @@ use middle::infer::{InferCtxt, GenericKind};
 use middle::subst::Substs;
 use middle::traits;
 use middle::ty::{self, RegionEscape, ToPredicate, Ty};
-use middle::ty::fold::{TypeFoldable, TypeFolder};
+use middle::ty::fold::TypeFoldable;
 
 use syntax::ast;
 use syntax::codemap::Span;
diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs
index 03554a59655b1..d455b1a4fa6f6 100644
--- a/src/librustc/middle/infer/combine.rs
+++ b/src/librustc/middle/infer/combine.rs
@@ -46,7 +46,7 @@ use middle::ty::{IntType, UintType};
 use middle::ty::{self, Ty};
 use middle::ty::error::TypeError;
 use middle::ty::fold::{TypeFolder, TypeFoldable};
-use middle::ty::relate::{Relate, RelateResult, TypeRelation};
+use middle::ty::relate::{RelateResult, TypeRelation};
 
 use syntax::ast;
 use syntax::codemap::Span;
diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs
index b39ddfe95c83a..25dde6739c1e9 100644
--- a/src/librustc/middle/infer/mod.rs
+++ b/src/librustc/middle/infer/mod.rs
@@ -33,7 +33,7 @@ use middle::ty::adjustment;
 use middle::ty::{TyVid, IntVid, FloatVid, RegionVid};
 use middle::ty::{self, Ty, HasTypeFlags};
 use middle::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
-use middle::ty::fold::{TypeFolder, TypeFoldable};
+use middle::ty::fold::TypeFoldable;
 use middle::ty::relate::{Relate, RelateResult, TypeRelation};
 use rustc_data_structures::unify::{self, UnificationTable};
 use std::cell::{RefCell, Ref};
diff --git a/src/librustc/middle/ty/context.rs b/src/librustc/middle/ty/context.rs
index cee651743ca86..5e0cc5131bcc0 100644
--- a/src/librustc/middle/ty/context.rs
+++ b/src/librustc/middle/ty/context.rs
@@ -271,6 +271,7 @@ pub struct ctxt<'tcx> {
 
     pub map: ast_map::Map<'tcx>,
     pub freevars: RefCell<FreevarMap>,
+    pub maybe_unused_trait_imports: NodeSet,
     pub tcache: RefCell<DefIdMap<ty::TypeScheme<'tcx>>>,
     pub rcache: RefCell<FnvHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
     pub tc_cache: RefCell<FnvHashMap<Ty<'tcx>, ty::contents::TypeContents>>,
@@ -306,6 +307,10 @@ pub struct ctxt<'tcx> {
     /// about.
     pub used_mut_nodes: RefCell<NodeSet>,
 
+    /// Set of trait imports actually used in method resolution.
+    /// This is used for warning unused imports.
+    pub used_trait_imports: RefCell<NodeSet>,
+
     /// The set of external nominal types whose implementations have been read.
     /// This is used for lazy resolution of methods.
     pub populated_external_types: RefCell<DefIdSet>,
@@ -475,6 +480,7 @@ impl<'tcx> ctxt<'tcx> {
                                  named_region_map: resolve_lifetime::NamedRegionMap,
                                  map: ast_map::Map<'tcx>,
                                  freevars: FreevarMap,
+                                 maybe_unused_trait_imports: NodeSet,
                                  region_maps: RegionMaps,
                                  lang_items: middle::lang_items::LanguageItems,
                                  stability: stability::Index<'tcx>,
@@ -508,6 +514,7 @@ impl<'tcx> ctxt<'tcx> {
             fulfilled_predicates: RefCell::new(traits::FulfilledPredicates::new()),
             map: map,
             freevars: RefCell::new(freevars),
+            maybe_unused_trait_imports: maybe_unused_trait_imports,
             tcache: RefCell::new(DefIdMap()),
             rcache: RefCell::new(FnvHashMap()),
             tc_cache: RefCell::new(FnvHashMap()),
@@ -522,6 +529,7 @@ impl<'tcx> ctxt<'tcx> {
             impl_items: RefCell::new(DefIdMap()),
             used_unsafe: RefCell::new(NodeSet()),
             used_mut_nodes: RefCell::new(NodeSet()),
+            used_trait_imports: RefCell::new(NodeSet()),
             populated_external_types: RefCell::new(DefIdSet()),
             populated_external_primitive_impls: RefCell::new(DefIdSet()),
             extern_const_statics: RefCell::new(DefIdMap()),
diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs
index 7477c4dead031..5dc539ea882c7 100644
--- a/src/librustc/middle/ty/mod.rs
+++ b/src/librustc/middle/ty/mod.rs
@@ -29,14 +29,13 @@ use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangIte
 use middle::subst::{self, ParamSpace, Subst, Substs, VecPerParamSpace};
 use middle::traits;
 use middle::ty;
-use middle::ty::fold::TypeFolder;
 use middle::ty::walk::TypeWalker;
 use util::common::memoized;
 use util::nodemap::{NodeMap, NodeSet, DefIdMap};
 use util::nodemap::FnvHashMap;
 
 use serialize::{Encodable, Encoder, Decodable, Decoder};
-use std::borrow::{Borrow, Cow};
+use std::borrow::Cow;
 use std::cell::{Cell, RefCell};
 use std::hash::{Hash, Hasher};
 use std::iter;
@@ -2752,8 +2751,13 @@ pub type FreevarMap = NodeMap<Vec<Freevar>>;
 
 pub type CaptureModeMap = NodeMap<hir::CaptureClause>;
 
+pub struct TraitCandidate {
+    pub def_id: DefId,
+    pub import_id: Option<NodeId>,
+}
+
 // Trait method resolution
-pub type TraitMap = NodeMap<Vec<DefId>>;
+pub type TraitMap = NodeMap<Vec<TraitCandidate>>;
 
 // Map from the NodeId of a glob import to a list of items which are actually
 // imported.
diff --git a/src/librustc/middle/ty/util.rs b/src/librustc/middle/ty/util.rs
index 0517769356f75..f183f3a0b6076 100644
--- a/src/librustc/middle/ty/util.rs
+++ b/src/librustc/middle/ty/util.rs
@@ -28,7 +28,7 @@ use std::cmp;
 use std::hash::{Hash, SipHasher, Hasher};
 use std::rc::Rc;
 use syntax::ast::{self, Name};
-use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
+use syntax::attr::{self, SignedInt, UnsignedInt};
 use syntax::codemap::Span;
 
 use rustc_front::hir;
diff --git a/src/librustc/session/filesearch.rs b/src/librustc/session/filesearch.rs
index 09c6b54d99cf8..7749cbd238599 100644
--- a/src/librustc/session/filesearch.rs
+++ b/src/librustc/session/filesearch.rs
@@ -15,7 +15,6 @@ pub use self::FileMatch::*;
 use std::collections::HashSet;
 use std::env;
 use std::fs;
-use std::io::prelude::*;
 use std::path::{Path, PathBuf};
 
 use session::search_paths::{SearchPaths, PathKind};
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 69e065b3e8f97..7541e752fbbaa 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -703,6 +703,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
     let resolve::CrateMap {
         def_map,
         freevars,
+        maybe_unused_trait_imports,
         export_map,
         trait_map,
         external_exports,
@@ -741,6 +742,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                named_region_map,
                                ast_map,
                                freevars,
+                               maybe_unused_trait_imports,
                                region_map,
                                lang_items,
                                stability::Index::new(krate),
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 2fb23c943c76a..124b3192d9b19 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -128,7 +128,7 @@ fn test_env<F>(source_string: &str,
 
     // run just enough stuff to build a tcx:
     let lang_items = lang_items::collect_language_items(&sess, &ast_map);
-    let resolve::CrateMap { def_map, freevars, .. } =
+    let resolve::CrateMap { def_map, freevars, maybe_unused_trait_imports, .. } =
         resolve::resolve_crate(&sess, &ast_map, resolve::MakeGlobMap::No);
     let named_region_map = resolve_lifetime::krate(&sess, krate, &def_map.borrow());
     let region_map = region::resolve_crate(&sess, krate);
@@ -138,6 +138,7 @@ fn test_env<F>(source_string: &str,
                                named_region_map,
                                ast_map,
                                freevars,
+                               maybe_unused_trait_imports,
                                region_map,
                                lang_items,
                                stability::Index::new(krate),
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index a1d029025b2fa..b963329049d9e 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -22,7 +22,7 @@ use std::cmp;
 use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
 
 use syntax::{abi, ast};
-use syntax::attr::{self, AttrMetaMethods};
+use syntax::attr;
 use syntax::codemap::{self, Span};
 use syntax::feature_gate::{emit_feature_err, GateIssue};
 use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64};
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index a627eeb688075..c9ce36ae2122b 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -43,7 +43,6 @@ use std::u32;
 use syntax::abi;
 use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum};
 use syntax::attr;
-use syntax::attr::AttrMetaMethods;
 use syntax::diagnostic::SpanHandler;
 use syntax::parse::token::special_idents;
 use syntax;
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index 7f740f9c03335..ceed90059628a 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -16,6 +16,8 @@
 // resolve data structures and because it finalises the privacy information for
 // `use` directives.
 //
+// Unused trait imports can't be checked until the method resolution. We save
+// candidates here, and do the actual check in librustc_typeck/check_unused.rs.
 
 use std::ops::{Deref, DerefMut};
 
@@ -62,13 +64,7 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
         debug!("finalizing import uses for {:?}",
                self.session.codemap().span_to_snippet(span));
 
-        if !self.used_imports.contains(&(id, TypeNS)) &&
-           !self.used_imports.contains(&(id, ValueNS)) {
-            self.session.add_lint(lint::builtin::UNUSED_IMPORTS,
-                                  id,
-                                  span,
-                                  "unused import".to_string());
-        }
+        self.check_import(id, span);
 
         let mut def_map = self.def_map.borrow_mut();
         let path_res = if let Some(r) = def_map.get_mut(&id) {
@@ -109,6 +105,24 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
             type_used: t_used,
         };
     }
+
+    fn check_import(&mut self, id: ast::NodeId, span: Span) {
+        if !self.used_imports.contains(&(id, TypeNS)) &&
+           !self.used_imports.contains(&(id, ValueNS)) {
+            if self.maybe_unused_trait_imports.contains(&id) {
+                // Check later.
+                return;
+            }
+            self.session.add_lint(lint::builtin::UNUSED_IMPORTS,
+                                  id,
+                                  span,
+                                  "unused import".to_string());
+        } else {
+            // This trait import is definitely used, in a way other than
+            // method resolution.
+            self.maybe_unused_trait_imports.remove(&id);
+        }
+    }
 }
 
 impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
@@ -144,14 +158,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
                         }
                     }
                     ViewPathGlob(_) => {
-                        if !self.used_imports.contains(&(item.id, TypeNS)) &&
-                           !self.used_imports.contains(&(item.id, ValueNS)) {
-                            self.session
-                                .add_lint(lint::builtin::UNUSED_IMPORTS,
-                                          item.id,
-                                          p.span,
-                                          "unused import".to_string());
-                        }
+                        self.check_import(item.id, p.span);
                     }
                 }
             }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index c32acb7bb269f..15ca1d51ab504 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -60,13 +60,12 @@ use rustc::middle::def_id::DefId;
 use rustc::middle::pat_util::pat_bindings;
 use rustc::middle::privacy::*;
 use rustc::middle::subst::{ParamSpace, FnSpace, TypeSpace};
-use rustc::middle::ty::{Freevar, FreevarMap, TraitMap, GlobMap};
-use rustc::util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
+use rustc::middle::ty::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
+use rustc::util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap};
 
 use syntax::ast;
 use syntax::ast::{CRATE_NODE_ID, Ident, Name, NodeId, CrateNum, TyIs, TyI8, TyI16, TyI32, TyI64};
 use syntax::ast::{TyUs, TyU8, TyU16, TyU32, TyU64, TyF64, TyF32};
-use syntax::attr::AttrMetaMethods;
 use syntax::parse::token::{self, special_names, special_idents};
 use syntax::codemap::{self, Span, Pos};
 use syntax::util::lev_distance::{lev_distance, max_suggestion_distance};
@@ -1142,6 +1141,7 @@ pub struct Resolver<'a, 'tcx: 'a> {
 
     used_imports: HashSet<(NodeId, Namespace)>,
     used_crates: HashSet<CrateNum>,
+    maybe_unused_trait_imports: NodeSet,
 
     // Callback function for intercepting walks
     callback: Option<Box<Fn(hir_map::Node, &mut bool) -> bool>>,
@@ -1193,14 +1193,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             freevars_seen: NodeMap(),
             export_map: NodeMap(),
             trait_map: NodeMap(),
-            used_imports: HashSet::new(),
-            used_crates: HashSet::new(),
             external_exports: DefIdSet(),
 
             emit_errors: true,
             make_glob_map: make_glob_map == MakeGlobMap::Yes,
             glob_map: HashMap::new(),
 
+            used_imports: HashSet::new(),
+            used_crates: HashSet::new(),
+            maybe_unused_trait_imports: NodeSet(),
+
             callback: None,
             resolved: false,
         }
@@ -3609,14 +3611,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
     }
 
-    fn get_traits_containing_item(&mut self, name: Name) -> Vec<DefId> {
+    fn get_traits_containing_item(&mut self, name: Name) -> Vec<TraitCandidate> {
         debug!("(getting traits containing item) looking for '{}'", name);
 
-        fn add_trait_info(found_traits: &mut Vec<DefId>, trait_def_id: DefId, name: Name) {
+        fn add_trait_info(found_traits: &mut Vec<TraitCandidate>,
+                          trait_def_id: DefId,
+                          import_id: Option<NodeId>,
+                          name: Name) {
             debug!("(adding trait info) found trait {:?} for method '{}'",
                    trait_def_id,
                    name);
-            found_traits.push(trait_def_id);
+            found_traits.push(TraitCandidate {
+                def_id: trait_def_id,
+                import_id: import_id,
+            });
         }
 
         let mut found_traits = Vec::new();
@@ -3626,7 +3634,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             match self.current_trait_ref {
                 Some((trait_def_id, _)) => {
                     if self.trait_item_map.contains_key(&(name, trait_def_id)) {
-                        add_trait_info(&mut found_traits, trait_def_id, name);
+                        add_trait_info(&mut found_traits, trait_def_id, None, name);
                     }
                 }
                 None => {} // Nothing to do.
@@ -3646,7 +3654,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         _ => continue,
                     };
                     if self.trait_item_map.contains_key(&(name, trait_def_id)) {
-                        add_trait_info(&mut found_traits, trait_def_id, name);
+                        add_trait_info(&mut found_traits, trait_def_id, None, name);
                     }
                 }
             }
@@ -3662,9 +3670,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     Some(..) | None => continue,
                 };
                 if self.trait_item_map.contains_key(&(name, did)) {
-                    add_trait_info(&mut found_traits, did, name);
                     let id = import.type_ns.id;
-                    self.used_imports.insert((id, TypeNS));
+                    add_trait_info(&mut found_traits, did, Some(id), name);
+                    self.maybe_unused_trait_imports.insert(id);
                     let trait_name = self.get_trait_name(did);
                     self.record_import_use(id, trait_name);
                     if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
@@ -3815,6 +3823,7 @@ fn module_to_string(module: &Module) -> String {
 pub struct CrateMap {
     pub def_map: RefCell<DefMap>,
     pub freevars: FreevarMap,
+    pub maybe_unused_trait_imports: NodeSet,
     pub export_map: ExportMap,
     pub trait_map: TraitMap,
     pub external_exports: ExternalExports,
@@ -3843,6 +3852,7 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
     CrateMap {
         def_map: resolver.def_map,
         freevars: resolver.freevars,
+        maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
         export_map: resolver.export_map,
         trait_map: resolver.trait_map,
         external_exports: resolver.external_exports,
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index fd471893acd53..4f9a70626665b 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -30,7 +30,6 @@ use rustc::middle::def_id::DefId;
 use rustc::middle::privacy::*;
 
 use syntax::ast::{NodeId, Name};
-use syntax::attr::AttrMetaMethods;
 use syntax::codemap::Span;
 
 use std::mem::replace;
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index fa500ab93552c..69b21a161766b 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -38,7 +38,7 @@ use trans::type_::Type;
 use trans::type_of;
 use middle::traits;
 use middle::ty::{self, HasTypeFlags, Ty};
-use middle::ty::fold::{TypeFolder, TypeFoldable};
+use middle::ty::fold::TypeFoldable;
 use rustc_front::hir;
 use rustc::mir::repr::Mir;
 use util::nodemap::{FnvHashMap, NodeMap};
diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs
index 9c1fcaff7c895..214a6aa612420 100644
--- a/src/librustc_trans/trans/monomorphize.rs
+++ b/src/librustc_trans/trans/monomorphize.rs
@@ -16,7 +16,7 @@ use middle::def_id::DefId;
 use middle::infer::normalize_associated_type;
 use middle::subst;
 use middle::subst::{Subst, Substs};
-use middle::ty::fold::{TypeFolder, TypeFoldable};
+use middle::ty::fold::TypeFoldable;
 use trans::attributes;
 use trans::base::{trans_enum_variant, push_ctxt, get_item_val};
 use trans::base::trans_fn;
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index b9fec44ec4030..18f1ad3d4d3dd 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -11,18 +11,15 @@
 //! Type-checking for the rust-intrinsic and platform-intrinsic
 //! intrinsics that the compiler exposes.
 
-use astconv::AstConv;
 use intrinsics;
 use middle::subst;
 use middle::ty::FnSig;
 use middle::ty::{self, Ty};
-use middle::ty::fold::TypeFolder;
 use {CrateCtxt, require_same_types};
 
 use std::collections::{HashMap};
 use syntax::abi;
 use syntax::ast;
-use syntax::attr::AttrMetaMethods;
 use syntax::codemap::Span;
 use syntax::parse::token;
 
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index e0ad51b4ea1b5..e74b013152f28 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -10,7 +10,6 @@
 
 //! Method lookup: the secret sauce of Rust. See `README.md`.
 
-use astconv::AstConv;
 use check::FnCtxt;
 use middle::def;
 use middle::def_id::DefId;
@@ -126,6 +125,11 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let mode = probe::Mode::MethodCall;
     let self_ty = fcx.infcx().resolve_type_vars_if_possible(&self_ty);
     let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, call_expr.id));
+
+    if let Some(import_id) = pick.import_id {
+        fcx.tcx().used_trait_imports.borrow_mut().insert(import_id);
+    }
+
     Ok(confirm::confirm(fcx, span, self_expr, call_expr, self_ty, pick, supplied_method_types))
 }
 
@@ -338,6 +342,11 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 {
     let mode = probe::Mode::Path;
     let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id));
+
+    if let Some(import_id) = pick.import_id {
+        fcx.tcx().used_trait_imports.borrow_mut().insert(import_id);
+    }
+
     let def_id = pick.item.def_id();
     let mut lp = LastMod(AllPublic);
     if let probe::InherentImplPick = pick.kind {
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index ed819d46041e6..1ee7c0bf97c53 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -44,6 +44,7 @@ struct ProbeContext<'a, 'tcx:'a> {
     inherent_candidates: Vec<Candidate<'tcx>>,
     extension_candidates: Vec<Candidate<'tcx>>,
     impl_dups: HashSet<DefId>,
+    import_id: Option<ast::NodeId>,
 
     /// Collects near misses when the candidate functions are missing a `self` keyword and is only
     /// used for error reporting
@@ -66,6 +67,7 @@ struct Candidate<'tcx> {
     xform_self_ty: Ty<'tcx>,
     item: ty::ImplOrTraitItem<'tcx>,
     kind: CandidateKind<'tcx>,
+    import_id: Option<ast::NodeId>,
 }
 
 #[derive(Debug)]
@@ -83,6 +85,7 @@ enum CandidateKind<'tcx> {
 pub struct Pick<'tcx> {
     pub item: ty::ImplOrTraitItem<'tcx>,
     pub kind: PickKind<'tcx>,
+    pub import_id: Option<ast::NodeId>,
 
     // Indicates that the source expression should be autoderef'd N times
     //
@@ -246,6 +249,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             inherent_candidates: Vec::new(),
             extension_candidates: Vec::new(),
             impl_dups: HashSet::new(),
+            import_id: None,
             steps: Rc::new(steps),
             opt_simplified_steps: opt_simplified_steps,
             static_candidates: Vec::new(),
@@ -427,7 +431,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         self.inherent_candidates.push(Candidate {
             xform_self_ty: xform_self_ty,
             item: item,
-            kind: InherentImplCandidate(impl_substs, obligations)
+            kind: InherentImplCandidate(impl_substs, obligations),
+            import_id: self.import_id,
         });
     }
 
@@ -455,7 +460,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             this.inherent_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
                 item: item,
-                kind: ObjectCandidate
+                kind: ObjectCandidate,
+                import_id: this.import_id,
             });
         });
     }
@@ -524,7 +530,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             this.inherent_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
                 item: item,
-                kind: WhereClauseCandidate(poly_trait_ref)
+                kind: WhereClauseCandidate(poly_trait_ref),
+                import_id: this.import_id,
             });
         });
     }
@@ -568,9 +575,13 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         let mut duplicates = HashSet::new();
         let opt_applicable_traits = self.fcx.ccx.trait_map.get(&expr_id);
         if let Some(applicable_traits) = opt_applicable_traits {
-            for &trait_did in applicable_traits {
+            for trait_candidate in applicable_traits {
+                let trait_did = trait_candidate.def_id;
                 if duplicates.insert(trait_did) {
-                    try!(self.assemble_extension_candidates_for_trait(trait_did));
+                    self.import_id = trait_candidate.import_id;
+                    let result = self.assemble_extension_candidates_for_trait(trait_did);
+                    self.import_id = None;
+                    try!(result);
                 }
             }
         }
@@ -670,7 +681,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             self.extension_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
                 item: item.clone(),
-                kind: ExtensionImplCandidate(impl_def_id, impl_substs, obligations)
+                kind: ExtensionImplCandidate(impl_def_id, impl_substs, obligations),
+                import_id: self.import_id,
             });
         });
     }
@@ -745,7 +757,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             self.inherent_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
                 item: item.clone(),
-                kind: TraitCandidate
+                kind: TraitCandidate,
+                import_id: self.import_id,
             });
         }
 
@@ -802,7 +815,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                     self.extension_candidates.push(Candidate {
                         xform_self_ty: xform_self_ty,
                         item: item.clone(),
-                        kind: TraitCandidate
+                        kind: TraitCandidate,
+                        import_id: self.import_id,
                     });
                 }
             }
@@ -833,7 +847,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             self.extension_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
                 item: item.clone(),
-                kind: WhereClauseCandidate(poly_bound)
+                kind: WhereClauseCandidate(poly_bound),
+                import_id: self.import_id,
             });
         }
     }
@@ -1126,6 +1141,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         Some(Pick {
             item: probes[0].item.clone(),
             kind: TraitPick,
+            import_id: probes[0].import_id,
             autoderefs: 0,
             autoref: None,
             unsize: None
@@ -1329,6 +1345,7 @@ impl<'tcx> Candidate<'tcx> {
                     WhereClausePick(trait_ref.clone())
                 }
             },
+            import_id: self.import_id,
             autoderefs: 0,
             autoref: None,
             unsize: None
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 955bc92a8f31e..039257d72b2ff 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -13,7 +13,6 @@
 
 use CrateCtxt;
 
-use astconv::AstConv;
 use check::{self, FnCtxt};
 use front::map as hir_map;
 use middle::ty::{self, Ty, ToPolyTraitRef, ToPredicate, HasTypeFlags};
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index a50213202b82c..91549ccd1310d 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -100,7 +100,7 @@ use middle::ty::{self, HasTypeFlags, RegionEscape, ToPolyTraitRef, Ty};
 use middle::ty::{MethodCall, MethodCallee};
 use middle::ty::adjustment;
 use middle::ty::error::TypeError;
-use middle::ty::fold::{TypeFolder, TypeFoldable};
+use middle::ty::fold::TypeFoldable;
 use middle::ty::util::Representability;
 use require_c_abi_if_variadic;
 use rscope::{ElisionFailureInfo, RegionScope};
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index f980945dbf220..d2fe174f3915e 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -82,7 +82,6 @@
 //! relation, except that a borrowed pointer never owns its
 //! contents.
 
-use astconv::AstConv;
 use check::dropck;
 use check::FnCtxt;
 use middle::free_region::FreeRegionMap;
diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs
index 3daf5003b97e0..8606f9f81c929 100644
--- a/src/librustc_typeck/check/wf.rs
+++ b/src/librustc_typeck/check/wf.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use astconv::AstConv;
 use check::{FnCtxt, Inherited, blank_fn_ctxt, regionck, wfcheck};
 use constrained_type_params::{identify_constrained_type_params, Parameter};
 use CrateCtxt;
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index a9bd0e3926811..dfc4ddee48758 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use astconv::AstConv;
 use check::{FnCtxt, Inherited, blank_fn_ctxt, regionck};
 use constrained_type_params::{identify_constrained_type_params, Parameter};
 use CrateCtxt;
@@ -16,7 +15,6 @@ use middle::def_id::DefId;
 use middle::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace};
 use middle::traits;
 use middle::ty::{self, Ty};
-use middle::ty::fold::{TypeFolder};
 
 use std::cell::RefCell;
 use std::collections::HashSet;
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 984f227cebe79..c1d4d49512c68 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -13,7 +13,6 @@
 // substitutions.
 use self::ResolveReason::*;
 
-use astconv::AstConv;
 use check::FnCtxt;
 use middle::def_id::DefId;
 use middle::pat_util;
diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs
new file mode 100644
index 0000000000000..7a66bb05090c2
--- /dev/null
+++ b/src/librustc_typeck/check_unused.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.
+
+use lint;
+use middle::ty;
+
+use syntax::ast;
+use syntax::codemap::{Span, DUMMY_SP};
+
+use rustc_front::hir;
+use rustc_front::intravisit::Visitor;
+
+struct UnusedTraitImportVisitor<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+}
+
+impl<'a, 'tcx> UnusedTraitImportVisitor<'a, 'tcx> {
+    fn check_import(&self, id: ast::NodeId, span: Span) {
+        if !self.tcx.maybe_unused_trait_imports.contains(&id) {
+            return;
+        }
+        if self.tcx.used_trait_imports.borrow().contains(&id) {
+            return;
+        }
+        self.tcx.sess.add_lint(lint::builtin::UNUSED_IMPORTS,
+                               id,
+                               span,
+                               "unused import".to_string());
+    }
+}
+
+impl<'a, 'tcx, 'v> Visitor<'v> for UnusedTraitImportVisitor<'a, 'tcx> {
+    fn visit_item(&mut self, item: &hir::Item) {
+        if item.vis == hir::Public || item.span == DUMMY_SP {
+            return;
+        }
+        if let hir::ItemUse(ref path) = item.node {
+            match path.node {
+                hir::ViewPathSimple(..) | hir::ViewPathGlob(..) => {
+                    self.check_import(item.id, path.span);
+                }
+                hir::ViewPathList(_, ref path_list) => {
+                    for path_item in path_list {
+                        self.check_import(path_item.node.id(), path_item.span);
+                    }
+                }
+            }
+        }
+    }
+}
+
+pub fn check_crate(tcx: &ty::ctxt) {
+    let mut visitor = UnusedTraitImportVisitor { tcx: tcx };
+    tcx.map.krate().visit_all_items(&mut visitor);
+}
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 86a56e718b5cf..860cbf7da1f0d 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -78,7 +78,7 @@ use middle::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerPar
 use middle::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
 use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme};
 use middle::ty::{VariantKind};
-use middle::ty::fold::{TypeFolder, TypeFoldable};
+use middle::ty::fold::TypeFoldable;
 use middle::ty::util::IntTypeExt;
 use middle::infer;
 use rscope::*;
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 495b8995ceea2..39e650b308264 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -120,6 +120,7 @@ use std::cell::RefCell;
 pub mod diagnostics;
 
 pub mod check;
+pub mod check_unused;
 mod rscope;
 mod astconv;
 pub mod collect;
@@ -361,6 +362,7 @@ pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
     time(time_passes, "wf checking (new)", ||
         check::check_wf_new(&ccx));
 
+    check_unused::check_crate(tcx);
     check_for_entry_fn(&ccx);
     tcx.sess.abort_if_errors();
 }
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 40e7146670907..ff00643923a74 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -13,7 +13,6 @@
 use std::collections::HashSet;
 
 use syntax::ast;
-use syntax::attr::AttrMetaMethods;
 use rustc_front::hir;
 
 use rustc::middle::cstore::{self, CrateStore};
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 8ea8f0c6c771b..07e49e2da97b0 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use io::prelude::*;
 use os::unix::prelude::*;
 
 use ffi::{CString, CStr, OsString, OsStr};
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index b854a2f2a0a17..3b7b5d854adac 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -289,8 +289,6 @@ pub enum Level {
 
 impl fmt::Display for Level {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        use std::fmt::Display;
-
         match *self {
             Bug => "error: internal compiler error".fmt(f),
             Fatal | Error => "error".fmt(f),
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index e9c8173a4d980..1b6f963f5751c 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -19,7 +19,6 @@ use ptr::P;
 use str::char_at;
 
 use std::cell::RefCell;
-use std::io::Read;
 use std::iter;
 use std::path::{Path, PathBuf};
 use std::rc::Rc;
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 7502a8cbc3546..566794a13612f 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -78,7 +78,6 @@ use parse::PResult;
 use diagnostic::FatalError;
 
 use std::collections::HashSet;
-use std::io::prelude::*;
 use std::mem;
 use std::path::{Path, PathBuf};
 use std::rc::Rc;
diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs
index 6e9c161293de2..8e20358027b22 100644
--- a/src/libsyntax/util/interner.rs
+++ b/src/libsyntax/util/interner.rs
@@ -115,14 +115,12 @@ impl Ord for RcStr {
 
 impl fmt::Debug for RcStr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        use std::fmt::Debug;
         self[..].fmt(f)
     }
 }
 
 impl fmt::Display for RcStr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        use std::fmt::Display;
         self[..].fmt(f)
     }
 }
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 7ffe567ac83c1..c41ac49b03474 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -58,9 +58,7 @@ use self::TestEvent::*;
 use self::NamePadding::*;
 use self::OutputLocation::*;
 
-use stats::Stats;
 use getopts::{OptGroup, optflag, optopt};
-use serialize::Encodable;
 use std::boxed::FnBox;
 use term::Terminal;
 use term::color::{Color, RED, YELLOW, GREEN, CYAN};
diff --git a/src/rustbook/main.rs b/src/rustbook/main.rs
index d23e868eeadd1..2e03ad512b5a8 100644
--- a/src/rustbook/main.rs
+++ b/src/rustbook/main.rs
@@ -19,10 +19,8 @@ extern crate rustdoc;
 extern crate rustc_back;
 
 use std::env;
-use std::error::Error;
 use std::process;
 use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
-use subcommand::Subcommand;
 use term::Term;
 
 mod term;
diff --git a/src/test/compile-fail/lint-unused-imports.rs b/src/test/compile-fail/lint-unused-imports.rs
index 1468ae64d9418..3eb0d48956b16 100644
--- a/src/test/compile-fail/lint-unused-imports.rs
+++ b/src/test/compile-fail/lint-unused-imports.rs
@@ -24,6 +24,8 @@ use test::A;       //~ ERROR unused import
 // Be sure that if we just bring some methods into scope that they're also
 // counted as being used.
 use test::B;
+// But only when actually used: do not get confused by the method with the same name.
+use test::B2; //~ ERROR unused import
 
 // Make sure this import is warned about when at least one of its imported names
 // is unused
@@ -37,6 +39,7 @@ mod test2 {
 mod test {
     pub trait A { fn a(&self) {} }
     pub trait B { fn b(&self) {} }
+    pub trait B2 { fn b(&self) {} }
     pub struct C;
     impl A for C {}
     impl B for C {}