about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-01-07 06:32:56 +0000
committerbors <bors@rust-lang.org>2016-01-07 06:32:56 +0000
commit91b27ec9beb8455426da3efd26dfc9155058f5bd (patch)
tree07d71c78a97c65aeda0f6ad440c9b966b1472150
parent440671751e818dfb20525a16a00011b8227eeaa7 (diff)
parent6dd3f6143e384927a15b165b1c64e1d7c06faa0a (diff)
downloadrust-91b27ec9beb8455426da3efd26dfc9155058f5bd.tar.gz
rust-91b27ec9beb8455426da3efd26dfc9155058f5bd.zip
Auto merge of #30724 - nikomatsakis:feature-gate-defaulted-type-parameters, r=pnkfelix
It was recently realized that we accept defaulted type parameters everywhere, without feature gate, even though the only place that we really *intended* to accept them were on types. This PR adds a lint warning unless the "type-parameter-defaults" feature is enabled. This should eventually become a hard error.

This is a [breaking-change] in that new feature gates are required (or simply removing the defaults, which is probably a better choice as they have little effect at this time). Results of a [crater run][crater] suggest that approximately 5-15 crates are affected. I didn't do the measurement quite right so that run cannot distinguish "true" regressions from "non-root" regressions, but even the upper bound of 15 affected crates seems relatively minimal.

[crater]: https://gist.github.com/nikomatsakis/760c6a67698bd24253bf

cc @rust-lang/lang
r? @pnkfelix
-rw-r--r--src/libcollections/btree/map.rs16
-rw-r--r--src/libcollections/btree/set.rs8
-rw-r--r--src/libcore/iter.rs4
-rw-r--r--src/librustc/lint/builtin.rs10
-rw-r--r--src/librustc/lint/context.rs20
-rw-r--r--src/librustc_lint/lib.rs4
-rw-r--r--src/librustc_trans/trans/base.rs1
-rw-r--r--src/librustc_typeck/collect.rs12
-rw-r--r--src/test/auxiliary/default_ty_param_cross_crate_crate.rs1
-rw-r--r--src/test/compile-fail/issue-26812.rs2
-rw-r--r--src/test/compile-fail/type-parameter-invalid-lint.rs17
11 files changed, 76 insertions, 19 deletions
diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs
index de9c8a2feaf..f87f5e6c2e6 100644
--- a/src/libcollections/btree/map.rs
+++ b/src/libcollections/btree/map.rs
@@ -1591,10 +1591,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
     #[unstable(feature = "btree_range",
                reason = "matches collection reform specification, waiting for dust to settle",
                issue = "27787")]
-    pub fn range<Min: ?Sized + Ord = K, Max: ?Sized + Ord = K>(&self,
-                                                               min: Bound<&Min>,
-                                                               max: Bound<&Max>)
-                                                               -> Range<K, V>
+    pub fn range<Min: ?Sized + Ord, Max: ?Sized + Ord>(&self,
+                                                       min: Bound<&Min>,
+                                                       max: Bound<&Max>)
+                                                       -> Range<K, V>
         where K: Borrow<Min> + Borrow<Max>
     {
         range_impl!(&self.root,
@@ -1633,10 +1633,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
     #[unstable(feature = "btree_range",
                reason = "matches collection reform specification, waiting for dust to settle",
                issue = "27787")]
-    pub fn range_mut<Min: ?Sized + Ord = K, Max: ?Sized + Ord = K>(&mut self,
-                                                                   min: Bound<&Min>,
-                                                                   max: Bound<&Max>)
-                                                                   -> RangeMut<K, V>
+    pub fn range_mut<Min: ?Sized + Ord, Max: ?Sized + Ord>(&mut self,
+                                                           min: Bound<&Min>,
+                                                           max: Bound<&Max>)
+                                                           -> RangeMut<K, V>
         where K: Borrow<Min> + Borrow<Max>
     {
         range_impl!(&mut self.root,
diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs
index 12d3465e518..55e9e3a1c34 100644
--- a/src/libcollections/btree/set.rs
+++ b/src/libcollections/btree/set.rs
@@ -154,10 +154,10 @@ impl<T: Ord> BTreeSet<T> {
     #[unstable(feature = "btree_range",
                reason = "matches collection reform specification, waiting for dust to settle",
                issue = "27787")]
-    pub fn range<'a, Min: ?Sized + Ord = T, Max: ?Sized + Ord = T>(&'a self,
-                                                                   min: Bound<&Min>,
-                                                                   max: Bound<&Max>)
-                                                                   -> Range<'a, T>
+    pub fn range<'a, Min: ?Sized + Ord, Max: ?Sized + Ord>(&'a self,
+                                                           min: Bound<&Min>,
+                                                           max: Bound<&Max>)
+                                                           -> Range<'a, T>
         where T: Borrow<Min> + Borrow<Max>
     {
         fn first<A, B>((a, _): (A, B)) -> A {
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 6f052f964c6..a30e5b1372a 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -2132,7 +2132,7 @@ pub trait Iterator {
     /// ```
     #[unstable(feature = "iter_arith", reason = "bounds recently changed",
                issue = "27739")]
-    fn sum<S=<Self as Iterator>::Item>(self) -> S where
+    fn sum<S>(self) -> S where
         S: Add<Self::Item, Output=S> + Zero,
         Self: Sized,
     {
@@ -2157,7 +2157,7 @@ pub trait Iterator {
     /// ```
     #[unstable(feature="iter_arith", reason = "bounds recently changed",
                issue = "27739")]
-    fn product<P=<Self as Iterator>::Item>(self) -> P where
+    fn product<P>(self) -> P where
         P: Mul<Self::Item, Output=P> + One,
         Self: Sized,
     {
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 2c5c664566a..aff925d1082 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -16,6 +16,9 @@
 
 use lint::{LintPass, LateLintPass, LintArray};
 
+// name of the future-incompatible group
+pub const FUTURE_INCOMPATIBLE: &'static str = "future_incompatible";
+
 declare_lint! {
     pub CONST_ERR,
     Warn,
@@ -124,6 +127,12 @@ declare_lint! {
     "detect private items in public interfaces not caught by the old implementation"
 }
 
+declare_lint! {
+    pub INVALID_TYPE_PARAM_DEFAULT,
+    Warn,
+    "type parameter default erroneously allowed in invalid location"
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy, Clone)]
@@ -149,6 +158,7 @@ impl LintPass for HardwiredLints {
             TRIVIAL_CASTS,
             TRIVIAL_NUMERIC_CASTS,
             PRIVATE_IN_PUBLIC,
+            INVALID_TYPE_PARAM_DEFAULT,
             CONST_ERR
         )
     }
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 0ac5160c29e..08fba2dc56f 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -365,14 +365,16 @@ pub fn gather_attrs(attrs: &[ast::Attribute])
 /// lints elsewhere in the compiler should call
 /// `Session::add_lint()` instead.
 pub fn raw_emit_lint(sess: &Session,
+                     lints: &LintStore,
                      lint: &'static Lint,
                      lvlsrc: LevelSource,
                      span: Option<Span>,
                      msg: &str) {
-    raw_struct_lint(sess, lint, lvlsrc, span, msg).emit();
+    raw_struct_lint(sess, lints, lint, lvlsrc, span, msg).emit();
 }
 
 pub fn raw_struct_lint<'a>(sess: &'a Session,
+                           lints: &LintStore,
                            lint: &'static Lint,
                            lvlsrc: LevelSource,
                            span: Option<Span>,
@@ -414,6 +416,18 @@ pub fn raw_struct_lint<'a>(sess: &'a Session,
         _ => sess.bug("impossible level in raw_emit_lint"),
     };
 
+    // Check for future incompatibility lints and issue a stronger warning.
+    let future_incompat_lints = &lints.lint_groups[builtin::FUTURE_INCOMPATIBLE];
+    let this_id = LintId::of(lint);
+    if future_incompat_lints.0.iter().any(|&id| id == this_id) {
+        let msg = "this lint will become a HARD ERROR in a future release!";
+        if let Some(sp) = span {
+            err.span_note(sp, msg);
+        } else {
+            err.note(msg);
+        }
+    }
+
     if let Some(span) = def {
         err.span_note(span, "lint level defined here");
     }
@@ -451,7 +465,7 @@ pub trait LintContext: Sized {
             Some(pair) => pair,
         };
 
-        raw_emit_lint(&self.sess(), lint, (level, src), span, msg);
+        raw_emit_lint(&self.sess(), self.lints(), lint, (level, src), span, msg);
     }
 
     fn lookup(&self,
@@ -464,7 +478,7 @@ pub trait LintContext: Sized {
             Some(pair) => pair,
         };
 
-        raw_struct_lint(&self.sess(), lint, (level, src), span, msg)
+        raw_struct_lint(&self.sess(), self.lints(), lint, (level, src), span, msg)
     }
 
     /// Emit a lint at the appropriate level, for a particular span.
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 80ef334fe18..f2e75960406 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -143,8 +143,8 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
                     UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE,
                     UNUSED_UNSAFE, PATH_STATEMENTS, UNUSED_ATTRIBUTES);
 
-    add_lint_group!(sess, "future_incompatible",
-                    PRIVATE_IN_PUBLIC);
+    add_lint_group!(sess, FUTURE_INCOMPATIBLE,
+                    PRIVATE_IN_PUBLIC, INVALID_TYPE_PARAM_DEFAULT);
 
     // We have one lint pass defined specially
     store.register_late_pass(sess, false, box lint::GatherNodeLevels);
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 5a40ff76252..1c3732d3ce4 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -2216,6 +2216,7 @@ fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &hir::EnumDef, sp: Span,
         // Use lint::raw_emit_lint rather than sess.add_lint because the lint-printing
         // pass for the latter already ran.
         lint::raw_struct_lint(&ccx.tcx().sess,
+                              &ccx.tcx().sess.lint_store.borrow(),
                               lint::builtin::VARIANT_SIZE_DIFFERENCES,
                               *lvlsrc.unwrap(),
                               Some(sp),
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 5a9b8991758..fbbd2f02908 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -59,6 +59,7 @@ There are some shortcomings in this design:
 */
 
 use astconv::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region};
+use lint;
 use middle::def;
 use middle::def_id::DefId;
 use constrained_type_params as ctp;
@@ -1910,6 +1911,17 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 
     let parent = tcx.map.get_parent(param.id);
 
+    if space != TypeSpace && default.is_some() {
+        if !tcx.sess.features.borrow().default_type_parameter_fallback {
+            tcx.sess.add_lint(
+                lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
+                param.id,
+                param.span,
+                format!("defaults for type parameters are only allowed \
+                         on `struct` or `enum` definitions (see issue #27336)"));
+        }
+    }
+
     let def = ty::TypeParameterDef {
         space: space,
         index: index,
diff --git a/src/test/auxiliary/default_ty_param_cross_crate_crate.rs b/src/test/auxiliary/default_ty_param_cross_crate_crate.rs
index 270cfdcb7f6..4bd8ecacb96 100644
--- a/src/test/auxiliary/default_ty_param_cross_crate_crate.rs
+++ b/src/test/auxiliary/default_ty_param_cross_crate_crate.rs
@@ -10,6 +10,7 @@
 
 #![crate_type = "lib"]
 #![crate_name = "default_param_test"]
+#![feature(default_type_parameter_fallback)]
 
 use std::marker::PhantomData;
 
diff --git a/src/test/compile-fail/issue-26812.rs b/src/test/compile-fail/issue-26812.rs
index c1ccfe269cd..060a66846d3 100644
--- a/src/test/compile-fail/issue-26812.rs
+++ b/src/test/compile-fail/issue-26812.rs
@@ -8,5 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(default_type_parameter_fallback)]
+
 fn avg<T=T::Item>(_: T) {} //~ ERROR associated type `Item` not found for `T`
 fn main() {}
diff --git a/src/test/compile-fail/type-parameter-invalid-lint.rs b/src/test/compile-fail/type-parameter-invalid-lint.rs
new file mode 100644
index 00000000000..a3ecbfa84f0
--- /dev/null
+++ b/src/test/compile-fail/type-parameter-invalid-lint.rs
@@ -0,0 +1,17 @@
+// 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.
+
+#![deny(future_incompatible)]
+#![allow(dead_code)]
+
+fn avg<T=i32>(_: T) {}
+//~^ ERROR defaults for type parameters are only allowed
+//~| NOTE HARD ERROR
+fn main() {}