diff options
| author | bors <bors@rust-lang.org> | 2016-01-07 06:32:56 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2016-01-07 06:32:56 +0000 |
| commit | 91b27ec9beb8455426da3efd26dfc9155058f5bd (patch) | |
| tree | 07d71c78a97c65aeda0f6ad440c9b966b1472150 | |
| parent | 440671751e818dfb20525a16a00011b8227eeaa7 (diff) | |
| parent | 6dd3f6143e384927a15b165b1c64e1d7c06faa0a (diff) | |
| download | rust-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.rs | 16 | ||||
| -rw-r--r-- | src/libcollections/btree/set.rs | 8 | ||||
| -rw-r--r-- | src/libcore/iter.rs | 4 | ||||
| -rw-r--r-- | src/librustc/lint/builtin.rs | 10 | ||||
| -rw-r--r-- | src/librustc/lint/context.rs | 20 | ||||
| -rw-r--r-- | src/librustc_lint/lib.rs | 4 | ||||
| -rw-r--r-- | src/librustc_trans/trans/base.rs | 1 | ||||
| -rw-r--r-- | src/librustc_typeck/collect.rs | 12 | ||||
| -rw-r--r-- | src/test/auxiliary/default_ty_param_cross_crate_crate.rs | 1 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-26812.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/type-parameter-invalid-lint.rs | 17 |
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() {} |
