diff --git a/src/lifetimes.rs b/src/lifetimes.rs
index 660d68535bd..bff0db14f7b 100644
--- a/src/lifetimes.rs
+++ b/src/lifetimes.rs
@@ -20,21 +20,21 @@ impl LintPass for LifetimePass {
 
     fn check_item(&mut self, cx: &Context, item: &Item) {
         if let ItemFn(ref decl, _, _, _, ref generics, _) = item.node {
-            check_fn_inner(cx, decl, None, &generics.lifetimes, item.span);
+            check_fn_inner(cx, decl, None, &generics, item.span);
         }
     }
 
     fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) {
         if let MethodImplItem(ref sig, _) = item.node {
             check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self),
-                           &sig.generics.lifetimes, item.span);
+                           &sig.generics, item.span);
         }
     }
 
     fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) {
         if let MethodTraitItem(ref sig, _) = item.node {
             check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self),
-                           &sig.generics.lifetimes, item.span);
+                           &sig.generics, item.span);
         }
     }
 }
@@ -49,11 +49,11 @@ enum RefLt {
 use self::RefLt::*;
 
 fn check_fn_inner(cx: &Context, decl: &FnDecl, slf: Option<&ExplicitSelf>,
-                  named_lts: &[LifetimeDef], span: Span) {
-    if in_external_macro(cx, span) {
+                  generics: &Generics, span: Span) {
+    if in_external_macro(cx, span) || has_where_lifetimes(&generics.where_clause) {
         return;
     }
-    if could_use_elision(decl, slf, named_lts) {
+    if could_use_elision(decl, slf, &generics.lifetimes) {
         span_lint(cx, NEEDLESS_LIFETIMES, span,
                   "explicit lifetimes given in parameter types where they could be elided");
     }
@@ -182,3 +182,21 @@ impl<'v> Visitor<'v> for RefVisitor {
     // for lifetime bounds; the default impl calls visit_lifetime_ref
     fn visit_lifetime_bound(&mut self, _: &'v Lifetime) { }
 }
+
+/// Are any lifetimes mentioned in the `where` clause? If yes, we don't try to
+/// reason about elision.
+fn has_where_lifetimes(where_clause: &WhereClause) -> bool {
+    let mut where_visitor = RefVisitor(Vec::new());
+    for predicate in &where_clause.predicates {
+        match *predicate {
+            WherePredicate::RegionPredicate(..) => return true,
+            WherePredicate::BoundPredicate(ref pred) => {
+                walk_ty(&mut where_visitor, &pred.bounded_ty);
+            }
+            WherePredicate::EqPredicate(ref pred) => {
+                walk_ty(&mut where_visitor, &pred.ty);
+            }
+        }
+    }
+    !where_visitor.into_vec().is_empty()
+}
diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs
index a5597e6478f..ae115efec04 100755
--- a/tests/compile-fail/lifetimes.rs
+++ b/tests/compile-fail/lifetimes.rs
@@ -31,6 +31,10 @@ fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 { x.unwrap() } // n
 fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { Ok(x) }
 //~^ERROR explicit lifetimes given
 
+// where clause, but without lifetimes
+fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> where T: Copy { Ok(x) }
+//~^ERROR explicit lifetimes given
+
 type Ref<'r> = &'r u8;
 
 fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) { } // no error, same lifetime on two params
@@ -40,6 +44,8 @@ fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) { }
 
 fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) { } // no error, bounded lifetime
 
+fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8) where 'b: 'a { } // no error, bounded lifetime
+
 struct X {
     x: u8,
 }