From caecb76f08e1365fe245118c7caa4f6add0f95f5 Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Sun, 21 May 2017 14:11:08 +0300
Subject: [PATCH 1/3] Turn sufficiently old compatibility lints into hard
 errors

---
 src/librustc/lint/builtin.rs                  | 65 -----------------
 src/librustc_const_eval/pattern.rs            | 21 ++----
 src/librustc_lint/lib.rs                      | 73 ++++++++-----------
 src/librustc_passes/ast_validation.rs         | 25 ++-----
 src/librustc_resolve/lib.rs                   | 17 ++---
 src/librustc_resolve/resolve_imports.rs       | 25 ++-----
 src/librustc_typeck/collect.rs                |  9 +--
 src/libsyntax/test.rs                         |  8 --
 .../bound-lifetime-constrained.rs             |  1 -
 .../bound-lifetime-in-return-only.rs          |  1 -
 .../compile-fail/extern-crate-visibility.rs   |  6 --
 .../future-incompatible-lint-group.rs}        | 19 ++---
 .../generic-impl-less-params-with-defaults.rs |  2 +-
 .../generic-impl-more-params-with-defaults.rs |  2 +-
 src/test/compile-fail/issue-1920-1.rs         |  2 +-
 src/test/compile-fail/issue-1920-3.rs         |  2 +-
 src/test/compile-fail/issue-6804.rs           |  2 -
 src/test/compile-fail/lifetime-underscore.rs  |  4 -
 src/test/compile-fail/match-argm-statics-2.rs |  2 +
 .../restricted/struct-literal-field.rs        |  1 -
 .../compile-fail/privacy/restricted/test.rs   |  1 -
 .../compile-fail/private-in-public-lint.rs    |  2 -
 ...eexport.rs => private-variant-reexport.rs} | 11 ---
 .../pub-reexport-priv-extern-crate.rs         | 31 ++++++++
 src/test/compile-fail/resolve-self-in-impl.rs |  1 -
 src/test/compile-fail/rfc1445/feature-gate.rs |  3 +-
 .../rfc1445/match-forbidden-without-eq.rs     |  5 --
 .../match-requires-both-partialeq-and-eq.rs   |  4 -
 .../type-parameter-invalid-lint.rs            |  5 --
 .../compile-fail/use-super-global-path.rs     |  2 -
 30 files changed, 102 insertions(+), 250 deletions(-)
 rename src/test/{run-pass/issue-37020.rs => compile-fail/future-incompatible-lint-group.rs} (62%)
 rename src/test/compile-fail/{private-variant-and-crate-reexport.rs => private-variant-reexport.rs} (73%)
 create mode 100644 src/test/compile-fail/pub-reexport-priv-extern-crate.rs

diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 0bc1be70174e6..5a88731f16c38 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -130,68 +130,12 @@ declare_lint! {
     "detect private items in public interfaces not caught by the old implementation"
 }
 
-declare_lint! {
-    pub INACCESSIBLE_EXTERN_CRATE,
-    Deny,
-    "use of inaccessible extern crate erroneously allowed"
-}
-
-declare_lint! {
-    pub INVALID_TYPE_PARAM_DEFAULT,
-    Deny,
-    "type parameter default erroneously allowed in invalid location"
-}
-
-declare_lint! {
-    pub ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN,
-    Deny,
-    "floating-point constants cannot be used in patterns"
-}
-
-declare_lint! {
-    pub ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN,
-    Deny,
-    "constants of struct or enum type can only be used in a pattern if \
-     the struct or enum has `#[derive(PartialEq, Eq)]`"
-}
-
-declare_lint! {
-    pub RAW_POINTER_DERIVE,
-    Warn,
-    "uses of #[derive] with raw pointers are rarely correct"
-}
-
-declare_lint! {
-    pub HR_LIFETIME_IN_ASSOC_TYPE,
-    Deny,
-    "binding for associated type references higher-ranked lifetime \
-     that does not appear in the trait input types"
-}
-
-declare_lint! {
-    pub OVERLAPPING_INHERENT_IMPLS,
-    Deny,
-    "two overlapping inherent impls define an item with the same name were erroneously allowed"
-}
-
 declare_lint! {
     pub RENAMED_AND_REMOVED_LINTS,
     Warn,
     "lints that have been renamed or removed"
 }
 
-declare_lint! {
-    pub SUPER_OR_SELF_IN_GLOBAL_PATH,
-    Deny,
-    "detects super or self keywords at the beginning of global path"
-}
-
-declare_lint! {
-    pub LIFETIME_UNDERSCORE,
-    Deny,
-    "lifetimes or labels named `'_` were erroneously allowed"
-}
-
 declare_lint! {
     pub RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
     Warn,
@@ -280,17 +224,8 @@ impl LintPass for HardwiredLints {
             TRIVIAL_CASTS,
             TRIVIAL_NUMERIC_CASTS,
             PRIVATE_IN_PUBLIC,
-            INACCESSIBLE_EXTERN_CRATE,
-            INVALID_TYPE_PARAM_DEFAULT,
-            ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN,
-            ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN,
             CONST_ERR,
-            RAW_POINTER_DERIVE,
-            OVERLAPPING_INHERENT_IMPLS,
             RENAMED_AND_REMOVED_LINTS,
-            SUPER_OR_SELF_IN_GLOBAL_PATH,
-            HR_LIFETIME_IN_ASSOC_TYPE,
-            LIFETIME_UNDERSCORE,
             RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
             SAFE_EXTERN_STATICS,
             PATTERNS_IN_FNS_WITHOUT_BODY,
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index e15d63a63c258..a2e0bb80d23dd 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -10,7 +10,6 @@
 
 use eval;
 
-use rustc::lint;
 use rustc::middle::const_val::{ConstEvalErr, ConstVal};
 use rustc::mir::{Field, BorrowKind, Mutability};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, TypeVariants, Region};
@@ -644,11 +643,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
         debug!("expr={:?} pat_ty={:?} pat_id={}", expr, pat_ty, pat_id);
         match pat_ty.sty {
             ty::TyFloat(_) => {
-                self.tcx.sess.add_lint(
-                    lint::builtin::ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN,
-                    pat_id,
-                    span,
-                    format!("floating point constants cannot be used in patterns"));
+                self.tcx.sess.span_err(span, "floating point constants cannot be used in patterns");
             }
             ty::TyAdt(adt_def, _) if adt_def.is_union() => {
                 // Matching on union fields is unsafe, we can't hide it in constants
@@ -656,15 +651,11 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
             }
             ty::TyAdt(adt_def, _) => {
                 if !self.tcx.has_attr(adt_def.did, "structural_match") {
-                    self.tcx.sess.add_lint(
-                        lint::builtin::ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN,
-                        pat_id,
-                        span,
-                        format!("to use a constant of type `{}` \
-                                 in a pattern, \
-                                 `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
-                                self.tcx.item_path_str(adt_def.did),
-                                self.tcx.item_path_str(adt_def.did)));
+                    let msg = format!("to use a constant of type `{}` in a pattern, \
+                                       `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
+                                      self.tcx.item_path_str(adt_def.did),
+                                      self.tcx.item_path_str(adt_def.did));
+                    self.tcx.sess.span_err(span, &msg);
                 }
             }
             _ => { }
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index d8f29768ccd67..a5b1d39dd869e 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -179,7 +179,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
     // - Create a lint defaulting to warn as normal, with ideally the same error
     //   message you would normally give
     // - Add a suitable reference, typically an RFC or tracking issue. Go ahead
-    //   and include the full URL.
+    //   and include the full URL, sort items in ascending order of issue numbers.
     // - Later, change lint to error
     // - Eventually, remove lint
     store.register_future_incompatible(sess,
@@ -189,48 +189,12 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
             reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
         },
         FutureIncompatibleInfo {
-            id: LintId::of(INACCESSIBLE_EXTERN_CRATE),
-            reference: "issue #36886 <https://github.com/rust-lang/rust/issues/36886>",
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(INVALID_TYPE_PARAM_DEFAULT),
-            reference: "issue #36887 <https://github.com/rust-lang/rust/issues/36887>",
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(SUPER_OR_SELF_IN_GLOBAL_PATH),
-            reference: "issue #36888 <https://github.com/rust-lang/rust/issues/36888>",
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN),
-            reference: "issue #36890 <https://github.com/rust-lang/rust/issues/36890>",
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN),
-            reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN),
-            reference: "issue #36891 <https://github.com/rust-lang/rust/issues/36891>",
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(HR_LIFETIME_IN_ASSOC_TYPE),
-            reference: "issue #33685 <https://github.com/rust-lang/rust/issues/33685>",
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(LIFETIME_UNDERSCORE),
-            reference: "issue #36892 <https://github.com/rust-lang/rust/issues/36892>",
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(RESOLVE_TRAIT_ON_DEFAULTED_UNIT),
-            reference: "issue #39216 <https://github.com/rust-lang/rust/issues/39216>",
+            id: LintId::of(PATTERNS_IN_FNS_WITHOUT_BODY),
+            reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
         },
         FutureIncompatibleInfo {
             id: LintId::of(SAFE_EXTERN_STATICS),
-            reference: "issue #36247 <https://github.com/rust-lang/rust/issues/35112>",
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(PATTERNS_IN_FNS_WITHOUT_BODY),
-            reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
+            reference: "issue #36247 <https://github.com/rust-lang/rust/issues/36247>",
         },
         FutureIncompatibleInfo {
             id: LintId::of(EXTRA_REQUIREMENT_IN_IMPL),
@@ -248,18 +212,26 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
             id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY),
             reference: "issue #39207 <https://github.com/rust-lang/rust/issues/39207>",
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(RESOLVE_TRAIT_ON_DEFAULTED_UNIT),
+            reference: "issue #39216 <https://github.com/rust-lang/rust/issues/39216>",
+        },
         FutureIncompatibleInfo {
             id: LintId::of(MISSING_FRAGMENT_SPECIFIER),
             reference: "issue #40107 <https://github.com/rust-lang/rust/issues/40107>",
         },
         FutureIncompatibleInfo {
-            id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES),
-            reference: "issue #42238 <https://github.com/rust-lang/rust/issues/42238>",
+            id: LintId::of(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN),
+            reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
         },
         FutureIncompatibleInfo {
             id: LintId::of(ANONYMOUS_PARAMETERS),
             reference: "issue #41686 <https://github.com/rust-lang/rust/issues/41686>",
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES),
+            reference: "issue #42238 <https://github.com/rust-lang/rust/issues/42238>",
+        }
         ]);
 
     // Register renamed and removed lints
@@ -275,5 +247,20 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
     store.register_removed("drop_with_repr_extern", "drop flags have been removed");
     store.register_removed("transmute_from_fn_item_types",
         "always cast functions before transmuting them");
-    store.register_removed("overlapping_inherent_impls", "converted into hard error, see #36889");
+    store.register_removed("hr_lifetime_in_assoc_type",
+        "converted into hard error, see https://github.com/rust-lang/rust/issues/33685");
+    store.register_removed("inaccessible_extern_crate",
+        "converted into hard error, see https://github.com/rust-lang/rust/issues/36886");
+    store.register_removed("invalid_type_param_default",
+        "converted into hard error, see https://github.com/rust-lang/rust/issues/36887");
+    store.register_removed("super_or_self_in_global_path",
+        "converted into hard error, see https://github.com/rust-lang/rust/issues/36888");
+    store.register_removed("overlapping_inherent_impls",
+        "converted into hard error, see https://github.com/rust-lang/rust/issues/36889");
+    store.register_removed("illegal_floating_point_constant_pattern",
+        "converted into hard error, see https://github.com/rust-lang/rust/issues/36890");
+    store.register_removed("illegal_struct_or_enum_constant_pattern",
+        "converted into hard error, see https://github.com/rust-lang/rust/issues/36891");
+    store.register_removed("lifetime_underscore",
+        "converted into hard error, see https://github.com/rust-lang/rust/issues/36892");
 }
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 79d90210d47f7..7c443a4ac7520 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -36,16 +36,10 @@ impl<'a> AstValidator<'a> {
         &self.session.parse_sess.span_diagnostic
     }
 
-    fn check_label(&self, label: Ident, span: Span, id: NodeId) {
-        if label.name == keywords::StaticLifetime.name() {
+    fn check_label(&self, label: Ident, span: Span) {
+        if label.name == keywords::StaticLifetime.name() || label.name == "'_" {
             self.err_handler().span_err(span, &format!("invalid label name `{}`", label.name));
         }
-        if label.name == "'_" {
-            self.session.add_lint(lint::builtin::LIFETIME_UNDERSCORE,
-                                  id,
-                                  span,
-                                  format!("invalid label name `{}`", label.name));
-        }
     }
 
     fn invalid_visibility(&self, vis: &Visibility, span: Span, note: Option<&str>) {
@@ -104,10 +98,7 @@ impl<'a> AstValidator<'a> {
 impl<'a> Visitor<'a> for AstValidator<'a> {
     fn visit_lifetime(&mut self, lt: &'a Lifetime) {
         if lt.ident.name == "'_" {
-            self.session.add_lint(lint::builtin::LIFETIME_UNDERSCORE,
-                                  lt.id,
-                                  lt.span,
-                                  format!("invalid lifetime name `{}`", lt.ident));
+            self.err_handler().span_err(lt.span, &format!("invalid lifetime name `{}`", lt.ident));
         }
 
         visit::walk_lifetime(self, lt)
@@ -121,7 +112,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             ExprKind::ForLoop(.., Some(ident)) |
             ExprKind::Break(Some(ident), _) |
             ExprKind::Continue(Some(ident)) => {
-                self.check_label(ident.node, ident.span, expr.id);
+                self.check_label(ident.node, ident.span);
             }
             _ => {}
         }
@@ -169,14 +160,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         visit::walk_ty(self, ty)
     }
 
-    fn visit_path(&mut self, path: &'a Path, id: NodeId) {
+    fn visit_path(&mut self, path: &'a Path, _: NodeId) {
         if path.segments.len() >= 2 && path.is_global() {
             let ident = path.segments[1].identifier;
             if token::Ident(ident).is_path_segment_keyword() {
-                self.session.add_lint(lint::builtin::SUPER_OR_SELF_IN_GLOBAL_PATH,
-                                      id,
-                                      path.span,
-                                      format!("global paths cannot start with `{}`", ident));
+                self.err_handler()
+                    .span_err(path.span, &format!("global paths cannot start with `{}`", ident));
             }
         }
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index f1be821d526e1..a40c191f7bd29 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1069,6 +1069,10 @@ impl<'a> NameBinding<'a> {
             _ => false,
         }
     }
+
+    fn descr(&self) -> &'static str {
+        if self.is_extern_crate() { "extern crate" } else { self.def().kind_name() }
+    }
 }
 
 /// Interns the names of the primitive types.
@@ -3424,18 +3428,7 @@ impl<'a> Resolver<'a> {
 
         for &PrivacyError(span, name, binding) in &self.privacy_errors {
             if !reported_spans.insert(span) { continue }
-            if binding.is_extern_crate() {
-                // Warn when using an inaccessible extern crate.
-                let node_id = match binding.kind {
-                    NameBindingKind::Import { directive, .. } => directive.id,
-                    _ => unreachable!(),
-                };
-                let msg = format!("extern crate `{}` is private", name);
-                self.session.add_lint(lint::builtin::INACCESSIBLE_EXTERN_CRATE, node_id, span, msg);
-            } else {
-                let def = binding.def();
-                self.session.span_err(span, &format!("{} `{}` is private", def.kind_name(), name));
-            }
+            self.session.span_err(span, &format!("{} `{}` is private", binding.descr(), name));
         }
     }
 
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index c077f507932c6..8745e51f5b45a 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -18,7 +18,6 @@ use {names_to_string, module_to_string};
 use {resolve_error, ResolutionError};
 
 use rustc::ty;
-use rustc::lint::builtin::PRIVATE_IN_PUBLIC;
 use rustc::hir::def_id::DefId;
 use rustc::hir::def::*;
 use rustc::util::nodemap::FxHashMap;
@@ -295,8 +294,7 @@ impl<'a> Resolver<'a> {
     // return the corresponding binding defined by the import directive.
     pub fn import(&self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
                   -> &'a NameBinding<'a> {
-        let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) ||
-                     !directive.is_glob() && binding.is_extern_crate() { // c.f. `PRIVATE_IN_PUBLIC`
+        let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) {
             directive.vis.get()
         } else {
             binding.pseudo_vis()
@@ -720,13 +718,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
 
         // All namespaces must be re-exported with extra visibility for an error to occur.
         if !any_successful_reexport {
-            let (ns, binding) = reexport_error.unwrap();
-            if ns == TypeNS && binding.is_extern_crate() {
-                let msg = format!("extern crate `{}` is private, and cannot be reexported \
-                                   (error E0364), consider declaring with `pub`",
-                                   ident);
-                self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
-            } else if ns == TypeNS {
+            if reexport_error.unwrap().0 == TypeNS {
                 struct_span_err!(self.session, directive.span, E0365,
                                  "`{}` is private, and cannot be reexported", ident)
                     .span_label(directive.span, format!("reexport of private `{}`", ident))
@@ -792,8 +784,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         self.record_def(directive.id, PathResolution::new(module.def().unwrap()));
     }
 
-    // Miscellaneous post-processing, including recording reexports, reporting conflicts,
-    // reporting the PRIVATE_IN_PUBLIC lint, and reporting unresolved imports.
+    // Miscellaneous post-processing, including recording reexports,
+    // reporting conflicts, and reporting unresolved imports.
     fn finalize_resolutions_in(&mut self, module: Module<'b>) {
         // Since import resolution is finished, globs will not define any more names.
         *module.globs.borrow_mut() = Vec::new();
@@ -838,13 +830,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
             }
 
             match binding.kind {
-                NameBindingKind::Import { binding: orig_binding, directive, .. } => {
+                NameBindingKind::Import { binding: orig_binding, .. } => {
                     if ns == TypeNS && orig_binding.is_variant() &&
                        !orig_binding.vis.is_at_least(binding.vis, &*self) {
-                        let msg = format!("variant `{}` is private, and cannot be reexported \
-                                           (error E0364), consider declaring its enum as `pub`",
-                                          ident);
-                        self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, binding.span, msg);
+                        let msg = format!("variant `{}` is private, and cannot be reexported, \
+                                           consider declaring its enum as `pub`", ident);
+                        self.session.span_err(binding.span, &msg);
                     }
                 }
                 NameBindingKind::Ambiguity { b1, b2, .. }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index fb3bcd31e21fc..d7813efdd2fba 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -54,7 +54,6 @@ There are some shortcomings in this design:
 */
 
 use astconv::{AstConv, Bounds};
-use lint;
 use constrained_type_params as ctp;
 use middle::lang_items::SizedTraitLangItem;
 use middle::const_val::ConstVal;
@@ -897,12 +896,8 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         if !allow_defaults && p.default.is_some() {
             if !tcx.sess.features.borrow().default_type_parameter_fallback {
-                tcx.sess.add_lint(
-                    lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
-                    p.id,
-                    p.span,
-                    format!("defaults for type parameters are only allowed in `struct`, \
-                             `enum`, `type`, or `trait` definitions."));
+                tcx.sess.span_err(p.span, "defaults for type parameters are only allowed in \
+                                           `struct`, `enum`, `type`, or `trait` definitions.");
             }
         }
 
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index 837c3eb0100c6..a0d1785c6ff14 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -231,20 +231,12 @@ fn mk_reexport_mod(cx: &mut TestCtxt,
                    -> (P<ast::Item>, Ident) {
     let super_ = Ident::from_str("super");
 
-    // Generate imports with `#[allow(private_in_public)]` to work around issue #36768.
-    let allow_private_in_public = cx.ext_cx.attribute(DUMMY_SP, cx.ext_cx.meta_list(
-        DUMMY_SP,
-        Symbol::intern("allow"),
-        vec![cx.ext_cx.meta_list_item_word(DUMMY_SP, Symbol::intern("private_in_public"))],
-    ));
     let items = tests.into_iter().map(|r| {
         cx.ext_cx.item_use_simple(DUMMY_SP, ast::Visibility::Public,
                                   cx.ext_cx.path(DUMMY_SP, vec![super_, r]))
-            .map_attrs(|_| vec![allow_private_in_public.clone()])
     }).chain(tested_submods.into_iter().map(|(r, sym)| {
         let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]);
         cx.ext_cx.item_use_simple_(DUMMY_SP, ast::Visibility::Public, r, path)
-            .map_attrs(|_| vec![allow_private_in_public.clone()])
     })).collect();
 
     let reexport_mod = ast::Mod {
diff --git a/src/test/compile-fail/associated-types/bound-lifetime-constrained.rs b/src/test/compile-fail/associated-types/bound-lifetime-constrained.rs
index 7d04372088b76..9ba5045f2a053 100644
--- a/src/test/compile-fail/associated-types/bound-lifetime-constrained.rs
+++ b/src/test/compile-fail/associated-types/bound-lifetime-constrained.rs
@@ -12,7 +12,6 @@
 
 #![allow(dead_code)]
 #![feature(rustc_attrs)]
-#![allow(hr_lifetime_in_assoc_type)]
 
 trait Foo<'a> {
     type Item;
diff --git a/src/test/compile-fail/associated-types/bound-lifetime-in-return-only.rs b/src/test/compile-fail/associated-types/bound-lifetime-in-return-only.rs
index 7c1fbfa53d965..b9b1317cef50f 100644
--- a/src/test/compile-fail/associated-types/bound-lifetime-in-return-only.rs
+++ b/src/test/compile-fail/associated-types/bound-lifetime-in-return-only.rs
@@ -13,7 +13,6 @@
 #![allow(dead_code)]
 #![feature(rustc_attrs)]
 #![feature(unboxed_closures)]
-#![deny(hr_lifetime_in_assoc_type)]
 
 trait Foo {
     type Item;
diff --git a/src/test/compile-fail/extern-crate-visibility.rs b/src/test/compile-fail/extern-crate-visibility.rs
index 81e0cb249f382..6bb88e409105a 100644
--- a/src/test/compile-fail/extern-crate-visibility.rs
+++ b/src/test/compile-fail/extern-crate-visibility.rs
@@ -8,21 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(unused)]
-
 mod foo {
     extern crate core;
 }
 
 // Check that private crates can be used from outside their modules, albeit with warnings
-use foo::core; //~ WARN extern crate `core` is private
-//~^ WARN this was previously accepted by the compiler but is being phased out
 use foo::core::cell; //~ ERROR extern crate `core` is private
-//~^ WARN this was previously accepted by the compiler but is being phased out
 
 fn f() {
     foo::core::cell::Cell::new(0); //~ ERROR extern crate `core` is private
-    //~^ WARN this was previously accepted by the compiler but is being phased out
 
     use foo::*;
     mod core {} // Check that private crates are not glob imported
diff --git a/src/test/run-pass/issue-37020.rs b/src/test/compile-fail/future-incompatible-lint-group.rs
similarity index 62%
rename from src/test/run-pass/issue-37020.rs
rename to src/test/compile-fail/future-incompatible-lint-group.rs
index 7d0d20269aba7..e6a39f95e660d 100644
--- a/src/test/run-pass/issue-37020.rs
+++ b/src/test/compile-fail/future-incompatible-lint-group.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,18 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(private_in_public)]
+#![deny(future_incompatible)]
 
-mod foo {
-    pub mod bar {
-        extern crate core;
-    }
+trait Tr {
+    fn f(u8) {} //~ ERROR use of deprecated anonymous parameter
+                //~^ WARN this was previously accepted
 }
 
-mod baz {
-    pub use foo::bar::core;
-}
-
-fn main() {
-    baz::core::cell::Cell::new(0u32);
-}
+fn main() {}
diff --git a/src/test/compile-fail/generic-impl-less-params-with-defaults.rs b/src/test/compile-fail/generic-impl-less-params-with-defaults.rs
index 5fa429445a35e..3f5f7bb3a53ea 100644
--- a/src/test/compile-fail/generic-impl-less-params-with-defaults.rs
+++ b/src/test/compile-fail/generic-impl-less-params-with-defaults.rs
@@ -13,7 +13,7 @@ use std::marker;
 struct Foo<A, B, C = (A, B)>(
     marker::PhantomData<(A,B,C)>);
 
-impl<A, B, C = (A, B)> Foo<A, B, C> {
+impl<A, B, C> Foo<A, B, C> {
     fn new() -> Foo<A, B, C> {Foo(marker::PhantomData)}
 }
 
diff --git a/src/test/compile-fail/generic-impl-more-params-with-defaults.rs b/src/test/compile-fail/generic-impl-more-params-with-defaults.rs
index d3babb8982ddc..3141199208965 100644
--- a/src/test/compile-fail/generic-impl-more-params-with-defaults.rs
+++ b/src/test/compile-fail/generic-impl-more-params-with-defaults.rs
@@ -15,7 +15,7 @@ struct Heap;
 struct Vec<T, A = Heap>(
     marker::PhantomData<(T,A)>);
 
-impl<T, A = Heap> Vec<T, A> {
+impl<T, A> Vec<T, A> {
     fn new() -> Vec<T, A> {Vec(marker::PhantomData)}
 }
 
diff --git a/src/test/compile-fail/issue-1920-1.rs b/src/test/compile-fail/issue-1920-1.rs
index 8fbe4432204a4..f829d4645a089 100644
--- a/src/test/compile-fail/issue-1920-1.rs
+++ b/src/test/compile-fail/issue-1920-1.rs
@@ -11,7 +11,7 @@
 //! Test that absolute path names are correct when a crate is not linked into the root namespace
 
 mod foo {
-    extern crate core;
+    pub extern crate core;
 }
 
 fn assert_clone<T>() where T : Clone { }
diff --git a/src/test/compile-fail/issue-1920-3.rs b/src/test/compile-fail/issue-1920-3.rs
index dfec48e0a83c1..2f5da907b95f6 100644
--- a/src/test/compile-fail/issue-1920-3.rs
+++ b/src/test/compile-fail/issue-1920-3.rs
@@ -11,7 +11,7 @@
 //! Test that when a crate is linked multiple times that the shortest absolute path name is used
 
 mod foo {
-    extern crate core;
+    pub extern crate core;
 }
 
 extern crate core;
diff --git a/src/test/compile-fail/issue-6804.rs b/src/test/compile-fail/issue-6804.rs
index f7d3ce60c66cc..2a97945f26648 100644
--- a/src/test/compile-fail/issue-6804.rs
+++ b/src/test/compile-fail/issue-6804.rs
@@ -19,13 +19,11 @@ fn main() {
     let x = NAN;
     match x {
         NAN => {}, //~ ERROR floating point constants cannot be used
-                   //~| WARNING hard error
         _ => {},
     };
 
     match [x, 1.0] {
         [NAN, _] => {}, //~ ERROR floating point constants cannot be used
-                        //~| WARNING hard error
         _ => {},
     };
 }
diff --git a/src/test/compile-fail/lifetime-underscore.rs b/src/test/compile-fail/lifetime-underscore.rs
index b768009132ca9..5b518a4931da8 100644
--- a/src/test/compile-fail/lifetime-underscore.rs
+++ b/src/test/compile-fail/lifetime-underscore.rs
@@ -9,17 +9,13 @@
 // except according to those terms.
 
 fn _f<'_>() //~ ERROR invalid lifetime name `'_`
-//~^ WARN this was previously accepted
     -> &'_ u8 //~ ERROR invalid lifetime name `'_`
-    //~^ WARN this was previously accepted
 {
     panic!();
 }
 
 fn main() {
     '_: loop { //~ ERROR invalid label name `'_`
-    //~^ WARN this was previously accepted
         break '_ //~ ERROR invalid label name `'_`
-        //~^ WARN this was previously accepted
     }
 }
diff --git a/src/test/compile-fail/match-argm-statics-2.rs b/src/test/compile-fail/match-argm-statics-2.rs
index 40dcf3d0f12cc..70e148627c47e 100644
--- a/src/test/compile-fail/match-argm-statics-2.rs
+++ b/src/test/compile-fail/match-argm-statics-2.rs
@@ -10,8 +10,10 @@
 
 use self::Direction::{North, East, South, West};
 
+#[derive(PartialEq, Eq)]
 struct NewBool(bool);
 
+#[derive(PartialEq, Eq)]
 enum Direction {
     North,
     East,
diff --git a/src/test/compile-fail/privacy/restricted/struct-literal-field.rs b/src/test/compile-fail/privacy/restricted/struct-literal-field.rs
index 68458fe3f04ba..21d90dfea4b6c 100644
--- a/src/test/compile-fail/privacy/restricted/struct-literal-field.rs
+++ b/src/test/compile-fail/privacy/restricted/struct-literal-field.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(private_in_public)]
 #![allow(warnings)]
 
 mod foo {
diff --git a/src/test/compile-fail/privacy/restricted/test.rs b/src/test/compile-fail/privacy/restricted/test.rs
index 12697d51042ed..2e065ac051b20 100644
--- a/src/test/compile-fail/privacy/restricted/test.rs
+++ b/src/test/compile-fail/privacy/restricted/test.rs
@@ -10,7 +10,6 @@
 
 // aux-build:pub_restricted.rs
 
-#![deny(private_in_public)]
 #![allow(warnings)]
 extern crate pub_restricted;
 
diff --git a/src/test/compile-fail/private-in-public-lint.rs b/src/test/compile-fail/private-in-public-lint.rs
index 030fbfc491449..fd92300cd1526 100644
--- a/src/test/compile-fail/private-in-public-lint.rs
+++ b/src/test/compile-fail/private-in-public-lint.rs
@@ -18,8 +18,6 @@ mod m1 {
 }
 
 mod m2 {
-    #![deny(future_incompatible)]
-
     pub struct Pub;
     struct Priv;
 
diff --git a/src/test/compile-fail/private-variant-and-crate-reexport.rs b/src/test/compile-fail/private-variant-reexport.rs
similarity index 73%
rename from src/test/compile-fail/private-variant-and-crate-reexport.rs
rename to src/test/compile-fail/private-variant-reexport.rs
index dce533e73feea..c77a7532e34a2 100644
--- a/src/test/compile-fail/private-variant-and-crate-reexport.rs
+++ b/src/test/compile-fail/private-variant-reexport.rs
@@ -8,31 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(private_in_public)]
-#![allow(dead_code)]
-
-extern crate core;
-pub use core as reexported_core; //~ ERROR extern crate `core` is private, and cannot be reexported
-//~^ WARNING hard error
-
 mod m1 {
     pub use ::E::V; //~ ERROR variant `V` is private, and cannot be reexported
-    //~^ WARNING hard error
 }
 
 mod m2 {
     pub use ::E::{V}; //~ ERROR variant `V` is private, and cannot be reexported
-    //~^ WARNING hard error
 }
 
 mod m3 {
     pub use ::E::V::{self}; //~ ERROR variant `V` is private, and cannot be reexported
-    //~^ WARNING hard error
 }
 
 mod m4 {
     pub use ::E::*; //~ ERROR variant `V` is private, and cannot be reexported
-    //~^ WARNING hard error
 }
 
 enum E { V }
diff --git a/src/test/compile-fail/pub-reexport-priv-extern-crate.rs b/src/test/compile-fail/pub-reexport-priv-extern-crate.rs
new file mode 100644
index 0000000000000..1249ba774a8ba
--- /dev/null
+++ b/src/test/compile-fail/pub-reexport-priv-extern-crate.rs
@@ -0,0 +1,31 @@
+// Copyright 2017 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.
+
+#![allow(unused)]
+
+extern crate core;
+pub use core as reexported_core; //~ ERROR `core` is private, and cannot be reexported
+
+mod foo1 {
+    extern crate core;
+}
+
+mod foo2 {
+    use foo1::core; //~ ERROR `core` is private, and cannot be reexported
+    pub mod bar {
+        extern crate core;
+    }
+}
+
+mod baz {
+    pub use foo2::bar::core; //~ ERROR `core` is private, and cannot be reexported
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/resolve-self-in-impl.rs b/src/test/compile-fail/resolve-self-in-impl.rs
index 710d8e11ff034..55ae37404a9fa 100644
--- a/src/test/compile-fail/resolve-self-in-impl.rs
+++ b/src/test/compile-fail/resolve-self-in-impl.rs
@@ -17,7 +17,6 @@ trait Tr<T = u8> {
 
 impl Tr<Self> for S {} // OK
 impl<T: Tr<Self>> Tr<T> for S {} // OK
-impl<T = Self> Tr<T> for S {} // OK
 impl Tr for S where Self: Copy {} // OK
 impl Tr for S where S<Self>: Copy {} // OK
 impl Tr for S where Self::A: Copy {} // OK
diff --git a/src/test/compile-fail/rfc1445/feature-gate.rs b/src/test/compile-fail/rfc1445/feature-gate.rs
index b51ee3d8b5ed8..f729220eabbc3 100644
--- a/src/test/compile-fail/rfc1445/feature-gate.rs
+++ b/src/test/compile-fail/rfc1445/feature-gate.rs
@@ -16,8 +16,7 @@
 
 // gate-test-structural_match
 
-#![allow(dead_code)]
-#![deny(future_incompatible)]
+#![allow(unused)]
 #![feature(rustc_attrs)]
 #![cfg_attr(with_gate, feature(structural_match))]
 
diff --git a/src/test/compile-fail/rfc1445/match-forbidden-without-eq.rs b/src/test/compile-fail/rfc1445/match-forbidden-without-eq.rs
index c573e3e8e28b2..679be9ce219fe 100644
--- a/src/test/compile-fail/rfc1445/match-forbidden-without-eq.rs
+++ b/src/test/compile-fail/rfc1445/match-forbidden-without-eq.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(dead_code)]
-#![deny(future_incompatible)]
-
 use std::f32;
 
 #[derive(PartialEq)]
@@ -25,7 +22,6 @@ fn main() {
     match y {
         FOO => { }
         //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
-        //~| WARNING will become a hard error
         _ => { }
     }
 
@@ -33,7 +29,6 @@ fn main() {
     match x {
         f32::INFINITY => { }
         //~^ ERROR floating point constants cannot be used in patterns
-        //~| WARNING will become a hard error
         _ => { }
     }
 }
diff --git a/src/test/compile-fail/rfc1445/match-requires-both-partialeq-and-eq.rs b/src/test/compile-fail/rfc1445/match-requires-both-partialeq-and-eq.rs
index 029df08ebc37a..e02f9153e7ead 100644
--- a/src/test/compile-fail/rfc1445/match-requires-both-partialeq-and-eq.rs
+++ b/src/test/compile-fail/rfc1445/match-requires-both-partialeq-and-eq.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(dead_code)]
-#![deny(future_incompatible)]
-
 #[derive(Eq)]
 struct Foo {
     x: u32
@@ -29,7 +26,6 @@ fn main() {
     match y {
         FOO => { }
         //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
-        //~| WARNING will become a hard error
         _ => { }
     }
 }
diff --git a/src/test/compile-fail/type-parameter-invalid-lint.rs b/src/test/compile-fail/type-parameter-invalid-lint.rs
index a2c8116c9ba1c..eea6f22644b69 100644
--- a/src/test/compile-fail/type-parameter-invalid-lint.rs
+++ b/src/test/compile-fail/type-parameter-invalid-lint.rs
@@ -10,16 +10,11 @@
 
 // gate-test-default_type_parameter_fallback
 
-#![deny(future_incompatible)]
-#![allow(dead_code)]
-
 fn avg<T=i32>(_: T) {}
 //~^ ERROR defaults for type parameters are only allowed
-//~| WARNING hard error
 
 struct S<T>(T);
 impl<T=i32> S<T> {}
 //~^ ERROR defaults for type parameters are only allowed
-//~| WARNING hard error
 
 fn main() {}
diff --git a/src/test/compile-fail/use-super-global-path.rs b/src/test/compile-fail/use-super-global-path.rs
index 3fa0712fb4ca3..4162e037cf32e 100644
--- a/src/test/compile-fail/use-super-global-path.rs
+++ b/src/test/compile-fail/use-super-global-path.rs
@@ -15,11 +15,9 @@ struct Z;
 
 mod foo {
     use ::super::{S, Z}; //~ ERROR global paths cannot start with `super`
-    //~^ WARN this was previously accepted by the compiler but is being phased out
 
     pub fn g() {
         use ::super::main; //~ ERROR global paths cannot start with `super`
-        //~^ WARN this was previously accepted by the compiler but is being phased out
         main();
     }
 }

From d73a0fef381f5c6f4720c152bb7235fe02e502fd Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Sun, 21 May 2017 15:50:38 +0300
Subject: [PATCH 2/3] Turn public reexporting of private extern crates into a
 lint again

---
 src/librustc_resolve/resolve_imports.rs              | 12 ++++++++++--
 .../compile-fail/pub-reexport-priv-extern-crate.rs   |  4 ++++
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 8745e51f5b45a..a892f9df6a646 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -18,6 +18,7 @@ use {names_to_string, module_to_string};
 use {resolve_error, ResolutionError};
 
 use rustc::ty;
+use rustc::lint::builtin::PRIVATE_IN_PUBLIC;
 use rustc::hir::def_id::DefId;
 use rustc::hir::def::*;
 use rustc::util::nodemap::FxHashMap;
@@ -294,7 +295,8 @@ impl<'a> Resolver<'a> {
     // return the corresponding binding defined by the import directive.
     pub fn import(&self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
                   -> &'a NameBinding<'a> {
-        let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) {
+        let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) ||
+                     !directive.is_glob() && binding.is_extern_crate() { // c.f. `PRIVATE_IN_PUBLIC`
             directive.vis.get()
         } else {
             binding.pseudo_vis()
@@ -718,7 +720,13 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
 
         // All namespaces must be re-exported with extra visibility for an error to occur.
         if !any_successful_reexport {
-            if reexport_error.unwrap().0 == TypeNS {
+            let (ns, binding) = reexport_error.unwrap();
+            if ns == TypeNS && binding.is_extern_crate() {
+                let msg = format!("extern crate `{}` is private, and cannot be reexported \
+                                   (error E0365), consider declaring with `pub`",
+                                   ident);
+                self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
+            } else if ns == TypeNS {
                 struct_span_err!(self.session, directive.span, E0365,
                                  "`{}` is private, and cannot be reexported", ident)
                     .span_label(directive.span, format!("reexport of private `{}`", ident))
diff --git a/src/test/compile-fail/pub-reexport-priv-extern-crate.rs b/src/test/compile-fail/pub-reexport-priv-extern-crate.rs
index 1249ba774a8ba..185da379694bc 100644
--- a/src/test/compile-fail/pub-reexport-priv-extern-crate.rs
+++ b/src/test/compile-fail/pub-reexport-priv-extern-crate.rs
@@ -9,9 +9,11 @@
 // except according to those terms.
 
 #![allow(unused)]
+#![deny(private_in_public)]
 
 extern crate core;
 pub use core as reexported_core; //~ ERROR `core` is private, and cannot be reexported
+                                 //~^ WARN this was previously accepted
 
 mod foo1 {
     extern crate core;
@@ -19,6 +21,7 @@ mod foo1 {
 
 mod foo2 {
     use foo1::core; //~ ERROR `core` is private, and cannot be reexported
+                    //~^ WARN this was previously accepted
     pub mod bar {
         extern crate core;
     }
@@ -26,6 +29,7 @@ mod foo2 {
 
 mod baz {
     pub use foo2::bar::core; //~ ERROR `core` is private, and cannot be reexported
+                             //~^ WARN this was previously accepted
 }
 
 fn main() {}

From 26d5c0e20cbdd27af12a756ddfb1758d0888aad3 Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Sat, 27 May 2017 01:52:25 +0300
Subject: [PATCH 3/3] Turn `invalid_type_param_default` into a lint again

---
 src/librustc/lint/builtin.rs                         | 7 +++++++
 src/librustc_lint/lib.rs                             | 6 ++++--
 src/librustc_typeck/collect.rs                       | 9 +++++++--
 src/test/compile-fail/type-parameter-invalid-lint.rs | 5 +++++
 4 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 5a88731f16c38..736c3b289e198 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -130,6 +130,12 @@ declare_lint! {
     "detect private items in public interfaces not caught by the old implementation"
 }
 
+declare_lint! {
+    pub INVALID_TYPE_PARAM_DEFAULT,
+    Deny,
+    "type parameter default erroneously allowed in invalid location"
+}
+
 declare_lint! {
     pub RENAMED_AND_REMOVED_LINTS,
     Warn,
@@ -224,6 +230,7 @@ impl LintPass for HardwiredLints {
             TRIVIAL_CASTS,
             TRIVIAL_NUMERIC_CASTS,
             PRIVATE_IN_PUBLIC,
+            INVALID_TYPE_PARAM_DEFAULT,
             CONST_ERR,
             RENAMED_AND_REMOVED_LINTS,
             RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index a5b1d39dd869e..9870842a28e38 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -196,6 +196,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
             id: LintId::of(SAFE_EXTERN_STATICS),
             reference: "issue #36247 <https://github.com/rust-lang/rust/issues/36247>",
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(INVALID_TYPE_PARAM_DEFAULT),
+            reference: "issue #36887 <https://github.com/rust-lang/rust/issues/36887>",
+        },
         FutureIncompatibleInfo {
             id: LintId::of(EXTRA_REQUIREMENT_IN_IMPL),
             reference: "issue #37166 <https://github.com/rust-lang/rust/issues/37166>",
@@ -251,8 +255,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
         "converted into hard error, see https://github.com/rust-lang/rust/issues/33685");
     store.register_removed("inaccessible_extern_crate",
         "converted into hard error, see https://github.com/rust-lang/rust/issues/36886");
-    store.register_removed("invalid_type_param_default",
-        "converted into hard error, see https://github.com/rust-lang/rust/issues/36887");
     store.register_removed("super_or_self_in_global_path",
         "converted into hard error, see https://github.com/rust-lang/rust/issues/36888");
     store.register_removed("overlapping_inherent_impls",
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index d7813efdd2fba..fb3bcd31e21fc 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -54,6 +54,7 @@ There are some shortcomings in this design:
 */
 
 use astconv::{AstConv, Bounds};
+use lint;
 use constrained_type_params as ctp;
 use middle::lang_items::SizedTraitLangItem;
 use middle::const_val::ConstVal;
@@ -896,8 +897,12 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         if !allow_defaults && p.default.is_some() {
             if !tcx.sess.features.borrow().default_type_parameter_fallback {
-                tcx.sess.span_err(p.span, "defaults for type parameters are only allowed in \
-                                           `struct`, `enum`, `type`, or `trait` definitions.");
+                tcx.sess.add_lint(
+                    lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
+                    p.id,
+                    p.span,
+                    format!("defaults for type parameters are only allowed in `struct`, \
+                             `enum`, `type`, or `trait` definitions."));
             }
         }
 
diff --git a/src/test/compile-fail/type-parameter-invalid-lint.rs b/src/test/compile-fail/type-parameter-invalid-lint.rs
index eea6f22644b69..c7a1197372dee 100644
--- a/src/test/compile-fail/type-parameter-invalid-lint.rs
+++ b/src/test/compile-fail/type-parameter-invalid-lint.rs
@@ -10,11 +10,16 @@
 
 // gate-test-default_type_parameter_fallback
 
+#![deny(invalid_type_param_default)]
+#![allow(unused)]
+
 fn avg<T=i32>(_: T) {}
 //~^ ERROR defaults for type parameters are only allowed
+//~| WARN this was previously accepted
 
 struct S<T>(T);
 impl<T=i32> S<T> {}
 //~^ ERROR defaults for type parameters are only allowed
+//~| WARN this was previously accepted
 
 fn main() {}