diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index 74f685a6de20e..3f4ff7c2f437e 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -103,7 +103,7 @@ pub trait Sized {
 /// `Unsize` is implemented for:
 ///
 /// - `[T; N]` is `Unsize<[T]>`
-/// - `T` is `Unsize<Trait>` when `T: Trait`
+/// - `T` is `Unsize<dyn Trait>` when `T: Trait`
 /// - `Foo<..., T, ...>` is `Unsize<Foo<..., U, ...>>` if:
 ///   - `T: Unsize<U>`
 ///   - Foo is a struct
diff --git a/src/librustc/hir/itemlikevisit.rs b/src/librustc/hir/itemlikevisit.rs
index bfc9e8f06e235..35b181245837f 100644
--- a/src/librustc/hir/itemlikevisit.rs
+++ b/src/librustc/hir/itemlikevisit.rs
@@ -51,7 +51,7 @@ pub trait ItemLikeVisitor<'hir> {
     fn visit_impl_item(&mut self, impl_item: &'hir ImplItem);
 }
 
-pub struct DeepVisitor<'v, V: 'v> {
+pub struct DeepVisitor<'v, V> {
     visitor: &'v mut V,
 }
 
diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs
index 21489965b1bf6..a1a93eb552138 100644
--- a/src/librustc/infer/nll_relate/mod.rs
+++ b/src/librustc/infer/nll_relate/mod.rs
@@ -800,7 +800,7 @@ impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> {
 /// [blog post]: https://is.gd/0hKvIr
 struct TypeGeneralizer<'me, 'tcx, D>
 where
-    D: TypeRelatingDelegate<'tcx> + 'me,
+    D: TypeRelatingDelegate<'tcx>,
 {
     infcx: &'me InferCtxt<'me, 'tcx>,
 
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index e2f2799d9634d..257d5159f1131 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -31,7 +31,6 @@
 #![deny(rust_2018_idioms)]
 #![deny(internal)]
 #![deny(unused_lifetimes)]
-#![allow(explicit_outlives_requirements)]
 
 #![feature(arbitrary_self_types)]
 #![feature(box_patterns)]
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index ce785f9a0246b..28399ed5439f7 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -231,7 +231,7 @@ pub struct CommonConsts<'tcx> {
     pub err: &'tcx Const<'tcx>,
 }
 
-pub struct LocalTableInContext<'a, V: 'a> {
+pub struct LocalTableInContext<'a, V> {
     local_id_root: Option<DefId>,
     data: &'a ItemLocalMap<V>
 }
@@ -294,7 +294,7 @@ impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
     }
 }
 
-pub struct LocalTableInContextMut<'a, V: 'a> {
+pub struct LocalTableInContextMut<'a, V> {
     local_id_root: Option<DefId>,
     data: &'a mut ItemLocalMap<V>
 }
@@ -2171,7 +2171,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
 
 /// An entry in an interner.
-struct Interned<'tcx, T: 'tcx+?Sized>(&'tcx T);
+struct Interned<'tcx, T: ?Sized>(&'tcx T);
 
 impl<'tcx, T: 'tcx+?Sized> Clone for Interned<'tcx, T> {
     fn clone(&self) -> Self {
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 0f158d2982a20..7d5f984c1b6f2 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -89,7 +89,7 @@ macro_rules! profq_query_msg {
 
 /// A type representing the responsibility to execute the job in the `job` field.
 /// This will poison the relevant query if dropped.
-pub(super) struct JobOwner<'a, 'tcx, Q: QueryDescription<'tcx> + 'a> {
+pub(super) struct JobOwner<'a, 'tcx, Q: QueryDescription<'tcx>> {
     cache: &'a Lock<QueryCache<'tcx, Q>>,
     key: Q::Key,
     job: Lrc<QueryJob<'tcx>>,
@@ -230,7 +230,7 @@ pub struct CycleError<'tcx> {
 }
 
 /// The result of `try_get_lock`
-pub(super) enum TryGetJob<'a, 'tcx, D: QueryDescription<'tcx> + 'a> {
+pub(super) enum TryGetJob<'a, 'tcx, D: QueryDescription<'tcx>> {
     /// The query is not yet started. Contains a guard to the cache eventually used to start it.
     NotYetStarted(JobOwner<'a, 'tcx, D>),
 
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 1eb6e9a5283bd..7283aa95b3027 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -24,7 +24,6 @@
 #![deny(rust_2018_idioms)]
 #![deny(internal)]
 #![deny(unused_lifetimes)]
-#![allow(explicit_outlives_requirements)]
 
 use back::write::{create_target_machine, create_informational_target_machine};
 use syntax_pos::symbol::Symbol;
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index 71393e224e42d..b76f098773f0b 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -15,7 +15,6 @@
 #![deny(rust_2018_idioms)]
 #![deny(internal)]
 #![deny(unused_lifetimes)]
-#![allow(explicit_outlives_requirements)]
 
 #![recursion_limit="256"]
 
diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs
index f62ad2fbef71f..7896592eea685 100644
--- a/src/librustc_mir/dataflow/graphviz.rs
+++ b/src/librustc_mir/dataflow/graphviz.rs
@@ -30,7 +30,7 @@ impl<'a, 'tcx, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD>
     fn flow_state(&self) -> &DataflowState<'tcx, Self::BD> { &self.flow_state.flow_state }
 }
 
-struct Graph<'a, 'tcx, MWF:'a, P> where
+struct Graph<'a, 'tcx, MWF, P> where
     MWF: MirWithFlowState<'tcx>
 {
     mbcx: &'a MWF,
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index 0728d5b21bbd1..89b952e9f8b5a 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -181,7 +181,7 @@ where
 
 struct PropagationContext<'b, 'a, 'tcx, O>
 where
-    O: 'b + BitDenotation<'tcx>,
+    O: BitDenotation<'tcx>,
 {
     builder: &'b mut DataflowAnalysis<'a, 'tcx, O>,
 }
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index d998f40c86ecc..416b66daa0594 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -21,7 +21,7 @@ use super::{
 };
 use crate::const_eval::{CompileTimeInterpreter, CompileTimeEvalContext};
 
-struct InternVisitor<'rt, 'mir: 'rt, 'tcx: 'rt + 'mir> {
+struct InternVisitor<'rt, 'mir, 'tcx> {
     /// previously encountered safe references
     ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>,
     ecx: &'rt mut CompileTimeEvalContext<'mir, 'tcx>,
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index a7cbe84330d89..cb02e1a778c93 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -30,7 +30,6 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![deny(rust_2018_idioms)]
 #![deny(internal)]
 #![deny(unused_lifetimes)]
-#![allow(explicit_outlives_requirements)]
 
 #[macro_use] extern crate log;
 #[macro_use]
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 815d210d36ea4..91fc19b71d8ba 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -92,7 +92,7 @@ pub trait DropElaborator<'a, 'tcx>: fmt::Debug {
 #[derive(Debug)]
 struct DropCtxt<'l, 'b, 'tcx, D>
 where
-    D: DropElaborator<'b, 'tcx> + 'l,
+    D: DropElaborator<'b, 'tcx>,
 {
     elaborator: &'l mut D,
 
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index cc6f7a07d9621..ec0f431d9b25e 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -75,7 +75,6 @@ This API is completely unstable and subject to change.
 #![deny(rust_2018_idioms)]
 #![deny(internal)]
 #![deny(unused_lifetimes)]
-#![allow(explicit_outlives_requirements)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index 3b42e1de61497..1ab367f73c1b3 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -91,10 +91,10 @@ impl<'a> StripUnconfigured<'a> {
     /// is in the original source file. Gives a compiler error if the syntax of
     /// the attribute is incorrect.
     fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec<ast::Attribute> {
-        if !attr.check_name(sym::cfg_attr) {
+        if attr.path != sym::cfg_attr {
             return vec![attr];
         }
-        if attr.tokens.len() == 0 {
+        if attr.tokens.is_empty() {
             self.sess.span_diagnostic
                 .struct_span_err(
                     attr.span,
@@ -108,7 +108,7 @@ impl<'a> StripUnconfigured<'a> {
                        <https://doc.rust-lang.org/reference/conditional-compilation.html\
                        #the-cfg_attr-attribute>")
                 .emit();
-            return Vec::new();
+            return vec![];
         }
 
         let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |parser| {
@@ -133,17 +133,18 @@ impl<'a> StripUnconfigured<'a> {
             Ok(result) => result,
             Err(mut e) => {
                 e.emit();
-                return Vec::new();
+                return vec![];
             }
         };
 
-        // Check feature gate and lint on zero attributes in source. Even if the feature is gated,
-        // we still compute as if it wasn't, since the emitted error will stop compilation further
-        // along the compilation.
-        if expanded_attrs.len() == 0 {
-            // FIXME: Emit unused attribute lint here.
+        // Lint on zero attributes in source.
+        if expanded_attrs.is_empty() {
+            return vec![attr];
         }
 
+        // At this point we know the attribute is considered used.
+        attr::mark_used(&attr);
+
         if attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
             // We call `process_cfg_attr` recursively in case there's a
             // `cfg_attr` inside of another `cfg_attr`. E.g.
@@ -159,7 +160,7 @@ impl<'a> StripUnconfigured<'a> {
             }))
             .collect()
         } else {
-            Vec::new()
+            vec![]
         }
     }
 
diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs
index abc451c96ae0e..3b4243ed24f7c 100644
--- a/src/libsyntax/ext/derive.rs
+++ b/src/libsyntax/ext/derive.rs
@@ -30,10 +30,6 @@ pub fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>) ->
 
         match attr.parse_list(cx.parse_sess,
                               |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) {
-            Ok(ref traits) if traits.is_empty() => {
-                cx.span_warn(attr.span, "empty trait list in `derive`");
-                false
-            }
             Ok(traits) => {
                 result.extend(traits);
                 true
diff --git a/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.rs b/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.rs
new file mode 100644
index 0000000000000..4c96d6e7ca17d
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.rs
@@ -0,0 +1,13 @@
+// Check that `#[cfg_attr($PREDICATE,)]` triggers the `unused_attribute` lint.
+
+// compile-flags: --cfg TRUE
+
+#![deny(unused)]
+
+#[cfg_attr(FALSE,)] //~ ERROR unused attribute
+fn _f() {}
+
+#[cfg_attr(TRUE,)] //~ ERROR unused attribute
+fn _g() {}
+
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr b/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr
new file mode 100644
index 0000000000000..cd3563e66c720
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr
@@ -0,0 +1,21 @@
+error: unused attribute
+  --> $DIR/cfg-attr-empty-is-unused.rs:7:1
+   |
+LL | #[cfg_attr(FALSE,)]
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/cfg-attr-empty-is-unused.rs:5:9
+   |
+LL | #![deny(unused)]
+   |         ^^^^^^
+   = note: #[deny(unused_attributes)] implied by #[deny(unused)]
+
+error: unused attribute
+  --> $DIR/cfg-attr-empty-is-unused.rs:10:1
+   |
+LL | #[cfg_attr(TRUE,)]
+   | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/derives/deriving-meta-empty-trait-list.rs b/src/test/ui/derives/deriving-meta-empty-trait-list.rs
index 882484146152d..4f2e31e8efb15 100644
--- a/src/test/ui/derives/deriving-meta-empty-trait-list.rs
+++ b/src/test/ui/derives/deriving-meta-empty-trait-list.rs
@@ -1,6 +1,6 @@
-// compile-pass
+#![deny(unused)]
 
-#[derive()] //~ WARNING empty trait list in `derive`
-struct Bar;
+#[derive()] //~ ERROR unused attribute
+struct _Bar;
 
 pub fn main() {}
diff --git a/src/test/ui/derives/deriving-meta-empty-trait-list.stderr b/src/test/ui/derives/deriving-meta-empty-trait-list.stderr
index f8414b6e65e62..95c94ded3eaf1 100644
--- a/src/test/ui/derives/deriving-meta-empty-trait-list.stderr
+++ b/src/test/ui/derives/deriving-meta-empty-trait-list.stderr
@@ -1,6 +1,15 @@
-warning: empty trait list in `derive`
+error: unused attribute
   --> $DIR/deriving-meta-empty-trait-list.rs:3:1
    |
 LL | #[derive()]
    | ^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/deriving-meta-empty-trait-list.rs:1:9
+   |
+LL | #![deny(unused)]
+   |         ^^^^^^
+   = note: #[deny(unused_attributes)] implied by #[deny(unused)]
+
+error: aborting due to previous error
 
diff --git a/src/test/ui/malformed/malformed-derive-entry.rs b/src/test/ui/malformed/malformed-derive-entry.rs
index 3e53e15601b0b..a6d886318e820 100644
--- a/src/test/ui/malformed/malformed-derive-entry.rs
+++ b/src/test/ui/malformed/malformed-derive-entry.rs
@@ -4,9 +4,6 @@ struct Test1;
 #[derive(Copy="bad")] //~ ERROR expected one of `)`, `,`, or `::`, found `=`
 struct Test2;
 
-#[derive()] //~ WARNING empty trait list
-struct Test3;
-
 #[derive] //~ ERROR malformed `derive` attribute input
 struct Test4;
 
diff --git a/src/test/ui/malformed/malformed-derive-entry.stderr b/src/test/ui/malformed/malformed-derive-entry.stderr
index dfbc5faedac59..f7500febe9719 100644
--- a/src/test/ui/malformed/malformed-derive-entry.stderr
+++ b/src/test/ui/malformed/malformed-derive-entry.stderr
@@ -10,14 +10,8 @@ error: expected one of `)`, `,`, or `::`, found `=`
 LL | #[derive(Copy="bad")]
    |              ^ expected one of `)`, `,`, or `::` here
 
-warning: empty trait list in `derive`
-  --> $DIR/malformed-derive-entry.rs:7:1
-   |
-LL | #[derive()]
-   | ^^^^^^^^^^^
-
 error: malformed `derive` attribute input
-  --> $DIR/malformed-derive-entry.rs:10:1
+  --> $DIR/malformed-derive-entry.rs:7:1
    |
 LL | #[derive]
    | ^^^^^^^^^ help: missing traits to be derived: `#[derive(Trait1, Trait2, ...)]`