diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index 1cc13ac7878be..3b42e1de61497 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -240,6 +240,10 @@ impl<'a> StripUnconfigured<'a> {
         items.flat_map_in_place(|item| self.configure(item));
     }
 
+    pub fn configure_generic_params(&mut self, params: &mut Vec<ast::GenericParam>) {
+        params.flat_map_in_place(|param| self.configure(param));
+    }
+
     fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) {
         match vdata {
             ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) =>
@@ -301,22 +305,6 @@ impl<'a> StripUnconfigured<'a> {
     pub fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) {
         fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg));
     }
-
-    /// Denies `#[cfg]` on generic parameters until we decide what to do with it.
-    /// See issue #51279.
-    pub fn disallow_cfg_on_generic_param(&mut self, param: &ast::GenericParam) {
-        for attr in param.attrs() {
-            let offending_attr = if attr.check_name(sym::cfg) {
-                "cfg"
-            } else if attr.check_name(sym::cfg_attr) {
-                "cfg_attr"
-            } else {
-                continue;
-            };
-            let msg = format!("#[{}] cannot be applied on a generic parameter", offending_attr);
-            self.sess.span_diagnostic.span_err(attr.span, &msg);
-        }
-    }
 }
 
 impl<'a> MutVisitor for StripUnconfigured<'a> {
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index d433e6c5a896f..a71d1d503cabc 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -1439,9 +1439,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         }
     }
 
-    fn visit_generic_param(&mut self, param: &mut ast::GenericParam) {
-        self.cfg.disallow_cfg_on_generic_param(&param);
-        noop_visit_generic_param(param, self)
+    fn visit_generic_params(&mut self, params: &mut Vec<ast::GenericParam>) {
+        self.cfg.configure_generic_params(params);
+        noop_visit_generic_params(params, self);
     }
 
     fn visit_attribute(&mut self, at: &mut ast::Attribute) {
diff --git a/src/test/ui/conditional-compilation/cfg-generic-params.rs b/src/test/ui/conditional-compilation/cfg-generic-params.rs
new file mode 100644
index 0000000000000..d80d3ea7b7fe9
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-generic-params.rs
@@ -0,0 +1,38 @@
+// compile-flags:--cfg yes
+
+fn f_lt<#[cfg(yes)] 'a: 'a, #[cfg(no)] T>() {}
+fn f_ty<#[cfg(no)] 'a: 'a, #[cfg(yes)] T>() {}
+
+type FnGood = for<#[cfg(yes)] 'a, #[cfg(no)] T> fn(); // OK
+type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
+//~^ ERROR only lifetime parameters can be used in this context
+
+type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(no)] T> Copy; // OK
+type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
+//~^ ERROR only lifetime parameters can be used in this context
+
+struct WhereGood where for<#[cfg(yes)] 'a, #[cfg(no)] T> u8: Copy; // OK
+struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
+//~^ ERROR only lifetime parameters can be used in this context
+
+fn f_lt_no<#[cfg_attr(no, unknown)] 'a>() {} // OK
+fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {} //~ ERROR attribute `unknown` is currently unknown
+fn f_ty_no<#[cfg_attr(no, unknown)] T>() {} // OK
+fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {} //~ ERROR attribute `unknown` is currently unknown
+
+type FnNo = for<#[cfg_attr(no, unknown)] 'a> fn(); // OK
+type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
+//~^ ERROR attribute `unknown` is currently unknown
+
+type PolyNo = dyn for<#[cfg_attr(no, unknown)] 'a> Copy; // OK
+type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
+//~^ ERROR attribute `unknown` is currently unknown
+
+struct WhereNo where for<#[cfg_attr(no, unknown)] 'a> u8: Copy; // OK
+struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
+//~^ ERROR attribute `unknown` is currently unknown
+
+fn main() {
+    f_lt::<'static>();
+    f_ty::<u8>();
+}
diff --git a/src/test/ui/conditional-compilation/cfg-generic-params.stderr b/src/test/ui/conditional-compilation/cfg-generic-params.stderr
new file mode 100644
index 0000000000000..40ca44d9db59c
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-generic-params.stderr
@@ -0,0 +1,66 @@
+error: only lifetime parameters can be used in this context
+  --> $DIR/cfg-generic-params.rs:7:45
+   |
+LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
+   |                                             ^
+
+error: only lifetime parameters can be used in this context
+  --> $DIR/cfg-generic-params.rs:11:51
+   |
+LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
+   |                                                   ^
+
+error: only lifetime parameters can be used in this context
+  --> $DIR/cfg-generic-params.rs:15:54
+   |
+LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
+   |                                                      ^
+
+error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future
+  --> $DIR/cfg-generic-params.rs:19:29
+   |
+LL | fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {}
+   |                             ^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future
+  --> $DIR/cfg-generic-params.rs:21:29
+   |
+LL | fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {}
+   |                             ^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future
+  --> $DIR/cfg-generic-params.rs:24:34
+   |
+LL | type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
+   |                                  ^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future
+  --> $DIR/cfg-generic-params.rs:28:40
+   |
+LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
+   |                                        ^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future
+  --> $DIR/cfg-generic-params.rs:32:43
+   |
+LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
+   |                                           ^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-51279.rs b/src/test/ui/issues/issue-51279.rs
deleted file mode 100644
index f8f3626caabe7..0000000000000
--- a/src/test/ui/issues/issue-51279.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-pub struct X<#[cfg(none)] 'a, #[cfg(none)] T>(&'a T);
-//~^ ERROR #[cfg] cannot be applied on a generic parameter
-//~^^ ERROR #[cfg] cannot be applied on a generic parameter
-
-impl<#[cfg(none)] 'a, #[cfg(none)] T> X<'a, T> {}
-//~^ ERROR #[cfg] cannot be applied on a generic parameter
-//~^^ ERROR #[cfg] cannot be applied on a generic parameter
-
-pub fn f<#[cfg(none)] 'a, #[cfg(none)] T>(_: &'a T) {}
-//~^ ERROR #[cfg] cannot be applied on a generic parameter
-//~^^ ERROR #[cfg] cannot be applied on a generic parameter
-
-#[cfg(none)]
-pub struct Y<#[cfg(none)] T>(T); // shouldn't care when the entire item is stripped out
-
-struct M<T>(*const T);
-
-impl<#[cfg_attr(none, may_dangle)] T> Drop for M<T> {
-    //~^ ERROR #[cfg_attr] cannot be applied on a generic parameter
-    fn drop(&mut self) {}
-}
-
-type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
-//~^ ERROR #[cfg] cannot be applied on a generic parameter
-//~| ERROR attribute `ignored` is currently unknown to the compiler
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-51279.stderr b/src/test/ui/issues/issue-51279.stderr
deleted file mode 100644
index 9dd4a9f23814c..0000000000000
--- a/src/test/ui/issues/issue-51279.stderr
+++ /dev/null
@@ -1,60 +0,0 @@
-error: #[cfg] cannot be applied on a generic parameter
-  --> $DIR/issue-51279.rs:1:14
-   |
-LL | pub struct X<#[cfg(none)] 'a, #[cfg(none)] T>(&'a T);
-   |              ^^^^^^^^^^^^
-
-error: #[cfg] cannot be applied on a generic parameter
-  --> $DIR/issue-51279.rs:1:31
-   |
-LL | pub struct X<#[cfg(none)] 'a, #[cfg(none)] T>(&'a T);
-   |                               ^^^^^^^^^^^^
-
-error: #[cfg] cannot be applied on a generic parameter
-  --> $DIR/issue-51279.rs:5:6
-   |
-LL | impl<#[cfg(none)] 'a, #[cfg(none)] T> X<'a, T> {}
-   |      ^^^^^^^^^^^^
-
-error: #[cfg] cannot be applied on a generic parameter
-  --> $DIR/issue-51279.rs:5:23
-   |
-LL | impl<#[cfg(none)] 'a, #[cfg(none)] T> X<'a, T> {}
-   |                       ^^^^^^^^^^^^
-
-error: #[cfg] cannot be applied on a generic parameter
-  --> $DIR/issue-51279.rs:9:10
-   |
-LL | pub fn f<#[cfg(none)] 'a, #[cfg(none)] T>(_: &'a T) {}
-   |          ^^^^^^^^^^^^
-
-error: #[cfg] cannot be applied on a generic parameter
-  --> $DIR/issue-51279.rs:9:27
-   |
-LL | pub fn f<#[cfg(none)] 'a, #[cfg(none)] T>(_: &'a T) {}
-   |                           ^^^^^^^^^^^^
-
-error: #[cfg_attr] cannot be applied on a generic parameter
-  --> $DIR/issue-51279.rs:18:6
-   |
-LL | impl<#[cfg_attr(none, may_dangle)] T> Drop for M<T> {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: #[cfg] cannot be applied on a generic parameter
-  --> $DIR/issue-51279.rs:23:23
-   |
-LL | type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
-   |                       ^^^^^^^^^^^^
-
-error[E0658]: The attribute `ignored` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/issue-51279.rs:23:8
-   |
-LL | type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
-   |        ^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add #![feature(custom_attribute)] to the crate attributes to enable
-
-error: aborting due to 9 previous errors
-
-For more information about this error, try `rustc --explain E0658`.