From 7ebb6eedca28995ab12ac9e87a2785474ca226c6 Mon Sep 17 00:00:00 2001 From: Behnam Esfahbod Date: Fri, 30 Jun 2017 17:23:55 -0600 Subject: [PATCH 01/56] [libstd_unicode] Change UNICODE_VERSION to use u32 Use `u32` for version components, as `u64` is just an overkill, and `u32` is the default type for integers and the default type used for regular internal numbers. There's no expectation for Unicode Versions to even reach one thousand in the next hundered years. This is different from *package versions*, which may become something auto-generated and exceed human-friendly range of integer values. --- src/libstd_unicode/tables.rs | 2 +- src/libstd_unicode/unicode.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd_unicode/tables.rs b/src/libstd_unicode/tables.rs index 0938738b52cb..63ed53988726 100644 --- a/src/libstd_unicode/tables.rs +++ b/src/libstd_unicode/tables.rs @@ -14,7 +14,7 @@ /// The version of [Unicode](http://www.unicode.org/) /// that the unicode parts of `CharExt` and `UnicodeStrPrelude` traits are based on. -pub const UNICODE_VERSION: (u64, u64, u64) = (10, 0, 0); +pub const UNICODE_VERSION: (u32, u32, u32) = (10, 0, 0); // BoolTrie is a trie for representing a set of Unicode codepoints. It is diff --git a/src/libstd_unicode/unicode.py b/src/libstd_unicode/unicode.py index 5f9def02c7d1..5b921a946d1b 100755 --- a/src/libstd_unicode/unicode.py +++ b/src/libstd_unicode/unicode.py @@ -562,7 +562,7 @@ if __name__ == "__main__": rf.write(""" /// The version of [Unicode](http://www.unicode.org/) /// that the unicode parts of `CharExt` and `UnicodeStrPrelude` traits are based on. -pub const UNICODE_VERSION: (u64, u64, u64) = (%s, %s, %s); +pub const UNICODE_VERSION: (u32, u32, u32) = (%s, %s, %s); """ % unicode_version) (canon_decomp, compat_decomp, gencats, combines, to_upper, to_lower, to_title) = load_unicode_data("UnicodeData.txt") From 42f886110afd8c944c9a94d82d65e17bf704f03f Mon Sep 17 00:00:00 2001 From: Behnam Esfahbod Date: Fri, 30 Jun 2017 17:23:55 -0600 Subject: [PATCH 02/56] [libstd_unicode] Create UnicodeVersion type Create named struct `UnicodeVersion` to use instead of tuple type for `UNICODE_VERSION` value. This allows user to access the fields with meaningful field names: `major`, `minor`, and `micro`. Per request, an empty private field is added to the struct, so it can be extended in the future without API breakage. --- src/libstd_unicode/tables.rs | 29 ++++++++++++++++++++++++++--- src/libstd_unicode/unicode.py | 29 ++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/libstd_unicode/tables.rs b/src/libstd_unicode/tables.rs index 63ed53988726..1e8a0be80966 100644 --- a/src/libstd_unicode/tables.rs +++ b/src/libstd_unicode/tables.rs @@ -12,9 +12,32 @@ #![allow(missing_docs, non_upper_case_globals, non_snake_case)] -/// The version of [Unicode](http://www.unicode.org/) -/// that the unicode parts of `CharExt` and `UnicodeStrPrelude` traits are based on. -pub const UNICODE_VERSION: (u32, u32, u32) = (10, 0, 0); +/// Represents a Unicode Version. +/// +/// See also: +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub struct UnicodeVersion { + /// Major version. + pub major: u32, + + /// Minor version. + pub minor: u32, + + /// Micro (or Update) version. + pub micro: u32, + + // Private field to keep struct expandable. + _priv: (), +} + +/// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of +/// `CharExt` and `UnicodeStrPrelude` traits are based on. +pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion { + major: 10, + minor: 0, + micro: 0, + _priv: (), +}; // BoolTrie is a trie for representing a set of Unicode codepoints. It is diff --git a/src/libstd_unicode/unicode.py b/src/libstd_unicode/unicode.py index 5b921a946d1b..1fac859242ea 100755 --- a/src/libstd_unicode/unicode.py +++ b/src/libstd_unicode/unicode.py @@ -560,9 +560,32 @@ if __name__ == "__main__": pattern = "for Version (\d+)\.(\d+)\.(\d+) of the Unicode" unicode_version = re.search(pattern, readme.read()).groups() rf.write(""" -/// The version of [Unicode](http://www.unicode.org/) -/// that the unicode parts of `CharExt` and `UnicodeStrPrelude` traits are based on. -pub const UNICODE_VERSION: (u32, u32, u32) = (%s, %s, %s); +/// Represents a Unicode Version. +/// +/// See also: +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub struct UnicodeVersion { + /// Major version. + pub major: u32, + + /// Minor version. + pub minor: u32, + + /// Micro (or Update) version. + pub micro: u32, + + // Private field to keep struct expandable. + _priv: (), +} + +/// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of +/// `CharExt` and `UnicodeStrPrelude` traits are based on. +pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion { + major: %s, + minor: %s, + micro: %s, + _priv: (), +}; """ % unicode_version) (canon_decomp, compat_decomp, gencats, combines, to_upper, to_lower, to_title) = load_unicode_data("UnicodeData.txt") From d96f9d47ac35b637906edb1d5d112549164e096c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 25 Jul 2017 22:01:31 -0700 Subject: [PATCH 03/56] Point at return type always when type mismatch against it Before this, the diagnostic errors would only point at the return type when changing it would be a possible solution to a type error. Add a label to the return type without a suggestion to change in order to make the source of the expected type obvious. Follow up to #42850, fixes #25133, fixes #41897. --- src/librustc/hir/map/mod.rs | 2 +- src/librustc/ty/mod.rs | 1 + src/librustc_typeck/check/mod.rs | 53 ++++++++++++------- .../struct-path-self-type-mismatch.rs | 12 ++--- .../block-must-not-have-result-res.stderr | 2 + src/test/ui/block-result/issue-13624.stderr | 2 + src/test/ui/block-result/issue-22645.stderr | 3 ++ src/test/ui/block-result/issue-5500.stderr | 2 + src/test/ui/impl-trait/equality.stderr | 3 ++ src/test/ui/mismatched_types/abridged.stderr | 14 +++++ 10 files changed, 68 insertions(+), 26 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 3fdd9c34f46d..5cec697c6bbd 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -664,7 +664,7 @@ impl<'hir> Map<'hir> { match *node { NodeExpr(ref expr) => { match expr.node { - ExprWhile(..) | ExprLoop(..) => true, + ExprWhile(..) | ExprLoop(..) | ExprIf(..) => true, _ => false, } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2a11b19f8556..0f152d999df5 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -488,6 +488,7 @@ impl<'tcx> TyS<'tcx> { TypeVariants::TyFnPtr(..) | TypeVariants::TyDynamic(..) | TypeVariants::TyClosure(..) | + TypeVariants::TyInfer(..) | TypeVariants::TyProjection(..) => false, _ => true, } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3c570d85147f..73aa5ac5a0f0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4187,8 +4187,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty } - /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether it is - /// `fn main` if it is a method, `None` otherwise. + /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether a + /// suggetion can be made, `None` otherwise. pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> { // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or // `while` before reaching it, as block tail returns are not available in them. @@ -4199,14 +4199,23 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { name, node: hir::ItemFn(ref decl, ..), .. }) = parent { decl.clone().and_then(|decl| { - // This is less than ideal, it will not present the return type span on any - // method called `main`, regardless of whether it is actually the entry point. - Some((decl, name == Symbol::intern("main"))) + // This is less than ideal, it will not suggest a return type span on any + // method called `main`, regardless of whether it is actually the entry point, + // but it will still present it as the reason for the expected type. + Some((decl, name != Symbol::intern("main"))) }) } else if let Node::NodeTraitItem(&hir::TraitItem { node: hir::TraitItemKind::Method(hir::MethodSig { ref decl, .. }, ..), .. + }) = parent { + decl.clone().and_then(|decl| { + Some((decl, true)) + }) + } else if let Node::NodeImplItem(&hir::ImplItem { + node: hir::ImplItemKind::Method(hir::MethodSig { + ref decl, .. + }, ..), .. }) = parent { decl.clone().and_then(|decl| { Some((decl, false)) @@ -4233,11 +4242,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { blk_id: ast::NodeId) { self.suggest_missing_semicolon(err, expression, expected, cause_span); - if let Some((fn_decl, is_main)) = self.get_fn_decl(blk_id) { - // `fn main()` must return `()`, do not suggest changing return type - if !is_main { - self.suggest_missing_return_type(err, &fn_decl, found); - } + if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) { + self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest); } } @@ -4293,20 +4299,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn suggest_missing_return_type(&self, err: &mut DiagnosticBuilder<'tcx>, fn_decl: &hir::FnDecl, - ty: Ty<'tcx>) { + expected: Ty<'tcx>, + found: Ty<'tcx>, + can_suggest: bool) { - // Only recommend changing the return type for methods that + // Only suggest changing the return type for methods that // haven't set a return type at all (and aren't `fn main()` or an impl). - if let &hir::FnDecl { - output: hir::FunctionRetTy::DefaultReturn(span), .. - } = fn_decl { - if ty.is_suggestable() { + match (&fn_decl.output, found.is_suggestable(), can_suggest) { + (&hir::FunctionRetTy::DefaultReturn(span), true, true) => { err.span_suggestion(span, "try adding a return type", - format!("-> {} ", ty)); - } else { + format!("-> {} ", found)); + } + (&hir::FunctionRetTy::DefaultReturn(span), false, true) => { err.span_label(span, "possibly return type missing here?"); } + (&hir::FunctionRetTy::DefaultReturn(span), _, _) => { + // `fn main()` must return `()`, do not suggest changing return type + err.span_label(span, "expected `()` because of default return type"); + } + (&hir::FunctionRetTy::Return(ref ty), _, _) => { + // Only point to return type if the expected type is the return type, as if they + // are not, the expectation must have been caused by something else. + err.span_label(ty.span, + format!("expected `{}` because of return type", expected)); + } } } diff --git a/src/test/compile-fail/struct-path-self-type-mismatch.rs b/src/test/compile-fail/struct-path-self-type-mismatch.rs index f694e7d277c7..ad568b41fcbf 100644 --- a/src/test/compile-fail/struct-path-self-type-mismatch.rs +++ b/src/test/compile-fail/struct-path-self-type-mismatch.rs @@ -20,17 +20,15 @@ impl Bar for Foo { } impl Foo { - fn new(u: U) -> Foo { + fn new(u: U) -> Foo { //~ NOTE expected `Foo` because of return type Self { //~^ ERROR mismatched types - //~| expected type parameter, found a different type parameter - //~| expected type `Foo` - //~| found type `Foo` + //~| NOTE expected type parameter, found a different type parameter + //~| NOTE expected type `Foo` inner: u //~^ ERROR mismatched types - //~| expected type parameter, found a different type parameter - //~| expected type `T` - //~| found type `U` + //~| NOTE expected type parameter, found a different type parameter + //~| NOTE expected type `T` } } } diff --git a/src/test/ui/block-result/block-must-not-have-result-res.stderr b/src/test/ui/block-result/block-must-not-have-result-res.stderr index f60a0c2e5f6e..20c7dc416f3b 100644 --- a/src/test/ui/block-result/block-must-not-have-result-res.stderr +++ b/src/test/ui/block-result/block-must-not-have-result-res.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/block-must-not-have-result-res.rs:15:9 | +14 | fn drop(&mut self) { + | - expected `()` because of default return type 15 | true //~ ERROR mismatched types | ^^^^ expected (), found bool | diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr index 41113eb7a573..cd8c28cd2cfa 100644 --- a/src/test/ui/block-result/issue-13624.stderr +++ b/src/test/ui/block-result/issue-13624.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-13624.rs:17:5 | +16 | pub fn get_enum_struct_variant() -> () { + | -- expected `()` because of return type 17 | Enum::EnumStructVariant { x: 1, y: 2, z: 3 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` | diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr index a9bcc8bea94c..c6113ae0c9f6 100644 --- a/src/test/ui/block-result/issue-22645.stderr +++ b/src/test/ui/block-result/issue-22645.stderr @@ -11,6 +11,9 @@ error[E0277]: the trait bound `{integer}: Scalar` is not satisfied error[E0308]: mismatched types --> $DIR/issue-22645.rs:25:3 | +23 | fn main() { + | - expected `()` because of default return type +24 | let b = Bob + 3.5; 25 | b + 3 //~ ERROR E0277 | ^^^^^ expected (), found struct `Bob` | diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr index bd670a14f247..29dbd5a8cf59 100644 --- a/src/test/ui/block-result/issue-5500.stderr +++ b/src/test/ui/block-result/issue-5500.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-5500.rs:12:5 | +11 | fn main() { + | - expected `()` because of default return type 12 | &panic!() | ^^^^^^^^^ expected (), found reference | diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 3fc08a0900fb..791ce4860d0c 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/equality.rs:25:5 | +21 | fn two(x: bool) -> impl Foo { + | -------- expected `_` because of return type +... 25 | 0_u32 | ^^^^^ expected i32, found u32 | diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index d40bc3b33390..8c63d7d6f91c 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/abridged.rs:26:5 | +25 | fn a() -> Foo { + | --- expected `Foo` because of return type 26 | Some(Foo { bar: 1 }) | ^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::option::Option` | @@ -10,6 +12,8 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:30:5 | +29 | fn a2() -> Foo { + | --- expected `Foo` because of return type 30 | Ok(Foo { bar: 1}) | ^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::result::Result` | @@ -19,6 +23,8 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:34:5 | +33 | fn b() -> Option { + | ----------- expected `std::option::Option` because of return type 34 | Foo { bar: 1 } | ^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `Foo` | @@ -28,6 +34,8 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:38:5 | +37 | fn c() -> Result { + | ---------------- expected `std::result::Result` because of return type 38 | Foo { bar: 1 } | ^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `Foo` | @@ -37,6 +45,9 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:49:5 | +41 | fn d() -> X, String> { + | ---------------------------- expected `X, std::string::String>` because of return type +... 49 | x | ^ expected struct `std::string::String`, found integral variable | @@ -46,6 +57,9 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:60:5 | +52 | fn e() -> X, String> { + | ---------------------------- expected `X, std::string::String>` because of return type +... 60 | x | ^ expected struct `std::string::String`, found integral variable | From 4bb9a8b4ac27b48fb7989ef2900ec12a0face475 Mon Sep 17 00:00:00 2001 From: oyvindln Date: Tue, 1 Aug 2017 19:17:33 +0200 Subject: [PATCH 04/56] Add an overflow check in the Iter::next() impl for Range<_> This helps with vectorization in some cases, such as (0..u16::MAX).collect::>(), as LLVM is able to change the loop condition to use equality instead of less than --- src/libcore/iter/range.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 32c32e327eb2..73d518b570a1 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -214,9 +214,16 @@ impl Iterator for ops::Range { #[inline] fn next(&mut self) -> Option { if self.start < self.end { - let mut n = self.start.add_one(); - mem::swap(&mut n, &mut self.start); - Some(n) + // We check for overflow here, even though it can't actually + // happen. Adding this check does however help llvm vectorize loops + // for some ranges that don't get vectorized otherwise, + // and this won't actually result in an extra check in an optimized build. + if let Some(mut n) = self.start.add_usize(1) { + mem::swap(&mut n, &mut self.start); + Some(n) + } else { + None + } } else { None } From 35b9bd0559746196fe0bc9f39b86c47d8c3afb8c Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Mon, 31 Jul 2017 19:38:20 +0100 Subject: [PATCH 05/56] Fixed refs being marked used mutably on mut deref Boxes are the exception - since a Box is as mutable as its contents. --- src/librustc_borrowck/borrowck/gather_loans/mod.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 7dcb6ce76a40..ba865e125336 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -441,6 +441,19 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { LpUpvar(ty::UpvarId{ var_id: local_id, closure_expr_id: _ }) => { self.tcx().used_mut_nodes.borrow_mut().insert(local_id); } + LpExtend(ref base, mc::McInherited, LpDeref(pointer_kind)) | + LpExtend(ref base, mc::McDeclared, LpDeref(pointer_kind)) => { + match base.kind { + LpVar(_) if pointer_kind != mc::Unique => { + // If you mutate the inside of a ref var, the var itself + // is not used mutably [Issue #25049] + // Unless it's a Box! (mc::Unique) + } + _ => { + self.mark_loan_path_as_mutated(&base); + } + } + } LpDowncast(ref base, _) | LpExtend(ref base, mc::McInherited, _) | LpExtend(ref base, mc::McDeclared, _) => { From 400075d9d9b6410c9f7952ca52c35806b46b3177 Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Tue, 1 Aug 2017 13:03:03 +0100 Subject: [PATCH 06/56] Fixed all unnecessary muts in language core --- src/liballoc/btree/node.rs | 4 ++-- src/liballoc/vec.rs | 2 +- src/liballoc/vec_deque.rs | 2 +- src/libcore/ops/function.rs | 2 +- src/libcore/option.rs | 2 +- src/libcore/result.rs | 2 +- src/librustc/infer/error_reporting/mod.rs | 4 ++-- src/librustc/traits/mod.rs | 2 +- src/librustc/traits/select.rs | 2 +- src/librustc/ty/inhabitedness/mod.rs | 4 ++-- src/librustc_allocator/expand.rs | 4 ++-- src/librustc_borrowck/borrowck/mod.rs | 2 +- src/librustc_data_structures/array_vec.rs | 2 +- src/librustc_data_structures/bitvec.rs | 2 +- src/librustc_data_structures/indexed_vec.rs | 2 +- src/librustc_driver/lib.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_mir/build/matches/mod.rs | 2 +- src/librustc_mir/transform/type_check.rs | 2 +- src/librustc_privacy/lib.rs | 4 ++-- src/librustc_resolve/resolve_imports.rs | 2 +- src/librustc_trans/base.rs | 2 +- src/librustc_trans/partitioning.rs | 2 +- src/librustc_typeck/check/coercion.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 4 ++-- src/librustc_typeck/check/op.rs | 2 +- src/libstd/collections/hash/map.rs | 2 +- src/libstd/sync/once.rs | 2 +- src/libstd/sys/unix/rand.rs | 4 ++-- src/libsyntax/ext/tt/macro_parser.rs | 4 ++-- src/libsyntax/ext/tt/macro_rules.rs | 2 +- 32 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/liballoc/btree/node.rs b/src/liballoc/btree/node.rs index 06d3a113b947..8cea6c482c33 100644 --- a/src/liballoc/btree/node.rs +++ b/src/liballoc/btree/node.rs @@ -1037,7 +1037,7 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType>, marker::KV> { pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) { - let (mut keys, mut vals) = self.node.into_slices_mut(); + let (keys, vals) = self.node.into_slices_mut(); unsafe { (keys.get_unchecked_mut(self.idx), vals.get_unchecked_mut(self.idx)) } @@ -1047,7 +1047,7 @@ impl<'a, K: 'a, V: 'a, NodeType> impl<'a, K, V, NodeType> Handle, K, V, NodeType>, marker::KV> { pub fn kv_mut(&mut self) -> (&mut K, &mut V) { unsafe { - let (mut keys, mut vals) = self.node.reborrow_mut().into_slices_mut(); + let (keys, vals) = self.node.reborrow_mut().into_slices_mut(); (keys.get_unchecked_mut(self.idx), vals.get_unchecked_mut(self.idx)) } } diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index da47ca509832..160c0ba2ab0e 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1751,7 +1751,7 @@ impl<'a, T> IntoIterator for &'a mut Vec { type Item = &'a mut T; type IntoIter = slice::IterMut<'a, T>; - fn into_iter(mut self) -> slice::IterMut<'a, T> { + fn into_iter(self) -> slice::IterMut<'a, T> { self.iter_mut() } } diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index fdd6c79ef2e9..055c2d4840a4 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -2394,7 +2394,7 @@ impl<'a, T> IntoIterator for &'a mut VecDeque { type Item = &'a mut T; type IntoIter = IterMut<'a, T>; - fn into_iter(mut self) -> IterMut<'a, T> { + fn into_iter(self) -> IterMut<'a, T> { self.iter_mut() } } diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs index 62bf69336a39..c5b3fbca1a6d 100644 --- a/src/libcore/ops/function.rs +++ b/src/libcore/ops/function.rs @@ -187,7 +187,7 @@ mod impls { where F : FnMut { type Output = F::Output; - extern "rust-call" fn call_once(mut self, args: A) -> F::Output { + extern "rust-call" fn call_once(self, args: A) -> F::Output { (*self).call_mut(args) } } diff --git a/src/libcore/option.rs b/src/libcore/option.rs index ef41b6794105..aecf2ee9325e 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -872,7 +872,7 @@ impl<'a, T> IntoIterator for &'a mut Option { type Item = &'a mut T; type IntoIter = IterMut<'a, T>; - fn into_iter(mut self) -> IterMut<'a, T> { + fn into_iter(self) -> IterMut<'a, T> { self.iter_mut() } } diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 88a93492de96..20cfb02afcc7 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -909,7 +909,7 @@ impl<'a, T, E> IntoIterator for &'a mut Result { type Item = &'a mut T; type IntoIter = IterMut<'a, T>; - fn into_iter(mut self) -> IterMut<'a, T> { + fn into_iter(self) -> IterMut<'a, T> { self.iter_mut() } } diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 8e8576b83e4e..9f70b4834ddc 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -415,8 +415,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// -------- this type is the same as a type argument in the other type, not highlighted /// ``` fn highlight_outer(&self, - mut value: &mut DiagnosticStyledString, - mut other_value: &mut DiagnosticStyledString, + value: &mut DiagnosticStyledString, + other_value: &mut DiagnosticStyledString, name: String, sub: &ty::subst::Substs<'tcx>, pos: usize, diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index e14203b34a18..d1938197e652 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -560,7 +560,7 @@ pub fn fully_normalize<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, { debug!("fully_normalize(value={:?})", value); - let mut selcx = &mut SelectionContext::new(infcx); + let selcx = &mut SelectionContext::new(infcx); // FIXME (@jroesch) ISSUE 26721 // I'm not sure if this is a bug or not, needs further investigation. // It appears that by reusing the fulfillment_cx here we incur more diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index c690bebed8c0..2966e6715b40 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -494,7 +494,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { never_obligation.predicate = never_obligation.predicate.map_bound(|mut trait_pred| { // Swap out () with ! so we can check if the trait is impld for ! { - let mut trait_ref = &mut trait_pred.trait_ref; + let trait_ref = &mut trait_pred.trait_ref; let unit_substs = trait_ref.substs; let mut never_substs = Vec::with_capacity(unit_substs.len()); never_substs.push(From::from(tcx.types.never)); diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 77c863a01231..900197f3dbd1 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -171,7 +171,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { match self.sty { TyAdt(def, substs) => { { - let mut substs_set = visited.entry(def.did).or_insert(FxHashSet::default()); + let substs_set = visited.entry(def.did).or_insert(FxHashSet::default()); if !substs_set.insert(substs) { // We are already calculating the inhabitedness of this type. // The type must contain a reference to itself. Break the @@ -193,7 +193,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } let ret = def.uninhabited_from(visited, tcx, substs); - let mut substs_set = visited.get_mut(&def.did).unwrap(); + let substs_set = visited.get_mut(&def.did).unwrap(); substs_set.remove(substs); ret }, diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs index e942b7264c58..676c3c51ea2a 100644 --- a/src/librustc_allocator/expand.rs +++ b/src/librustc_allocator/expand.rs @@ -188,7 +188,7 @@ impl<'a> AllocFnFactory<'a> { fn arg_ty(&self, ty: &AllocatorTy, args: &mut Vec, - mut ident: &mut FnMut() -> Ident) -> P { + ident: &mut FnMut() -> Ident) -> P { match *ty { AllocatorTy::Layout => { let usize = self.cx.path_ident(self.span, Ident::from_str("usize")); @@ -263,7 +263,7 @@ impl<'a> AllocFnFactory<'a> { fn ret_ty(&self, ty: &AllocatorTy, args: &mut Vec, - mut ident: &mut FnMut() -> Ident, + ident: &mut FnMut() -> Ident, expr: P) -> (P, P) { match *ty { diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 76c4ac57a149..6b31535c5a52 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -98,7 +98,7 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) { let body_id = tcx.hir.body_owned_by(owner_id); let tables = tcx.typeck_tables_of(owner_def_id); let region_maps = tcx.region_maps(owner_def_id); - let mut bccx = &mut BorrowckCtxt { tcx, tables, region_maps, owner_def_id }; + let bccx = &mut BorrowckCtxt { tcx, tables, region_maps, owner_def_id }; let body = bccx.tcx.hir.body(body_id); diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs index ced73e9e4262..df660d08603a 100644 --- a/src/librustc_data_structures/array_vec.rs +++ b/src/librustc_data_structures/array_vec.rs @@ -260,7 +260,7 @@ impl<'a, A: Array> Drop for Drain<'a, A> { let start = source_array_vec.len(); let tail = self.tail_start; { - let mut arr = &mut source_array_vec.values as &mut [ManuallyDrop<_>]; + let arr = &mut source_array_vec.values as &mut [ManuallyDrop<_>]; let src = arr.as_ptr().offset(tail as isize); let dst = arr.as_mut_ptr().offset(start as isize); ptr::copy(src, dst, self.tail_len); diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs index ffcd25a4cdd3..7fc59be780f6 100644 --- a/src/librustc_data_structures/bitvec.rs +++ b/src/librustc_data_structures/bitvec.rs @@ -166,7 +166,7 @@ impl BitMatrix { pub fn add(&mut self, source: usize, target: usize) -> bool { let (start, _) = self.range(source); let (word, mask) = word_mask(target); - let mut vector = &mut self.vector[..]; + let vector = &mut self.vector[..]; let v1 = vector[start + word]; let v2 = v1 | mask; vector[start + word] = v2; diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 29ac650aa705..1f44378c9e64 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -259,7 +259,7 @@ impl<'a, I: Idx, T> IntoIterator for &'a mut IndexVec { type IntoIter = slice::IterMut<'a, T>; #[inline] - fn into_iter(mut self) -> slice::IterMut<'a, T> { + fn into_iter(self) -> slice::IterMut<'a, T> { self.raw.iter_mut() } } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index d6b1eb86937b..31f41b38060c 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -422,7 +422,7 @@ fn show_content_with_pager(content: &String) { match Command::new(pager_name).stdin(Stdio::piped()).spawn() { Ok(mut pager) => { - if let Some(mut pipe) = pager.stdin.as_mut() { + if let Some(pipe) = pager.stdin.as_mut() { if pipe.write_all(content.as_bytes()).is_err() { fallback_to_println = true; } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index e8b0dea1e8ac..d2ab9b2fbced 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -479,7 +479,7 @@ impl CrateStore for cstore::CStore { _ => {}, } - let mut bfs_queue = &mut VecDeque::new(); + let bfs_queue = &mut VecDeque::new(); let mut add_child = |bfs_queue: &mut VecDeque<_>, child: def::Export, parent: DefId| { let child = child.def.def_id(); diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 54f285480ab5..c0b54ce2a84d 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -206,7 +206,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { self.schedule_drop(span, extent, &Lvalue::Local(local_id), var_ty); } - pub fn visit_bindings(&mut self, pattern: &Pattern<'tcx>, mut f: &mut F) + pub fn visit_bindings(&mut self, pattern: &Pattern<'tcx>, f: &mut F) where F: FnMut(&mut Self, Mutability, Name, NodeId, Span, Ty<'tcx>) { match *pattern.kind { diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 7e6fccf30192..eb4a017c17b1 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -720,7 +720,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { value, obligations); - let mut fulfill_cx = &mut self.fulfillment_cx; + let fulfill_cx = &mut self.fulfillment_cx; for obligation in obligations { fulfill_cx.register_predicate_obligation(self.infcx, obligation); } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 64af24d92eec..3caa9ad34d30 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -781,7 +781,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { hir::ItemTrait(.., ref trait_item_refs) => { self.check_item(item.id).generics().predicates(); for trait_item_ref in trait_item_refs { - let mut check = self.check_item(trait_item_ref.id.node_id); + let check = self.check_item(trait_item_ref.id.node_id); check.generics().predicates(); if trait_item_ref.kind != hir::AssociatedItemKind::Type || trait_item_ref.defaultness.has_value() { @@ -814,7 +814,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } hir::ItemImpl(.., ref trait_ref, _, ref impl_item_refs) => { { - let mut check = self.check_item(item.id); + let check = self.check_item(item.id); check.ty().generics().predicates(); if trait_ref.is_some() { check.impl_trait_ref(); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 5e799b14f209..41f1f5877d8c 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -379,7 +379,7 @@ impl<'a> Resolver<'a> { // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, // during which the resolution might end up getting re-defined via a glob cycle. let (binding, t) = { - let mut resolution = &mut *self.resolution(module, ident, ns).borrow_mut(); + let resolution = &mut *self.resolution(module, ident, ns).borrow_mut(); let old_binding = resolution.binding(); let t = f(self, resolution); diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 14c73de64bc7..99a48c4221b3 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1465,7 +1465,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a let mut output = i.to_string(scx.tcx()); output.push_str(" @@"); let mut empty = Vec::new(); - let mut cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty); + let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty); cgus.as_mut_slice().sort_by_key(|&(ref name, _)| name.clone()); cgus.dedup(); for &(ref cgu_name, (linkage, _)) in cgus.iter() { diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 904cfb2acd74..3ea23be7712f 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -348,7 +348,7 @@ fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>, CodegenUnit::empty(codegen_unit_name.clone()) }; - let mut codegen_unit = codegen_units.entry(codegen_unit_name.clone()) + let codegen_unit = codegen_units.entry(codegen_unit_name.clone()) .or_insert_with(make_codegen_unit); let (linkage, visibility) = match trans_item.explicit_linkage(tcx) { diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 968e893b9a00..9ee425dab8fa 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1204,7 +1204,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> } } - if let Some(mut augment_error) = augment_error { + if let Some(augment_error) = augment_error { augment_error(&mut db); } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index dfc5cd00b6ea..a398d12a5bfd 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -538,7 +538,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // We can't use normalize_associated_types_in as it will pollute the // fcx's fulfillment context after this probe is over. let cause = traits::ObligationCause::misc(self.span, self.body_id); - let mut selcx = &mut traits::SelectionContext::new(self.fcx); + let selcx = &mut traits::SelectionContext::new(self.fcx); let traits::Normalized { value: xform_self_ty, obligations } = traits::normalize(selcx, self.param_env, cause, &xform_self_ty); debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}", @@ -749,7 +749,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // as it will pollute the fcx's fulfillment context after this probe // is over. let cause = traits::ObligationCause::misc(self.span, self.body_id); - let mut selcx = &mut traits::SelectionContext::new(self.fcx); + let selcx = &mut traits::SelectionContext::new(self.fcx); let traits::Normalized { value: xform_self_ty, obligations } = traits::normalize(selcx, self.param_env, cause, &xform_self_ty); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 17aae7dc04f2..197d5b86db87 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4147,8 +4147,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected)); let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); - let mut ctxt = enclosing_breakables.find_breakable(blk.id); - let mut coerce = ctxt.coerce.as_mut().unwrap(); + let ctxt = enclosing_breakables.find_breakable(blk.id); + let coerce = ctxt.coerce.as_mut().unwrap(); if let Some(tail_expr_ty) = tail_expr_ty { let tail_expr = tail_expr.unwrap(); let cause = self.cause(tail_expr.span, diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 032e37a34a88..c1711491ee48 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -300,7 +300,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { lhs_expr: &'gcx hir::Expr, lhs_ty: Ty<'tcx>, rhs_ty: Ty<'tcx>, - mut err: &mut errors::DiagnosticBuilder) -> bool { + err: &mut errors::DiagnosticBuilder) -> bool { // If this function returns true it means a note was printed, so we don't need // to print the normal "implementation of `std::ops::Add` might be missing" note let mut is_string_addition = false; diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 12241b3f8818..7e2229a8f84a 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1618,7 +1618,7 @@ impl<'a, K, V, S> IntoIterator for &'a mut HashMap type Item = (&'a K, &'a mut V); type IntoIter = IterMut<'a, K, V>; - fn into_iter(mut self) -> IterMut<'a, K, V> { + fn into_iter(self) -> IterMut<'a, K, V> { self.iter_mut() } } diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index d9edf5d12548..bb18fe95a9db 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -267,7 +267,7 @@ impl Once { #[cold] fn call_inner(&'static self, ignore_poisoning: bool, - mut init: &mut FnMut(bool)) { + init: &mut FnMut(bool)) { let mut state = self.state.load(Ordering::SeqCst); 'outer: loop { diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index 77ebad4e344c..1f56a299407e 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -12,13 +12,13 @@ pub use self::imp::OsRng; use mem; -fn next_u32(mut fill_buf: &mut FnMut(&mut [u8])) -> u32 { +fn next_u32(fill_buf: &mut FnMut(&mut [u8])) -> u32 { let mut buf: [u8; 4] = [0; 4]; fill_buf(&mut buf); unsafe { mem::transmute::<[u8; 4], u32>(buf) } } -fn next_u64(mut fill_buf: &mut FnMut(&mut [u8])) -> u64 { +fn next_u64(fill_buf: &mut FnMut(&mut [u8])) -> u64 { let mut buf: [u8; 8] = [0; 8]; fill_buf(&mut buf); unsafe { mem::transmute::<[u8; 8], u64>(buf) } diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 60833c75a159..146bd5d98569 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -211,7 +211,7 @@ pub enum NamedMatch { fn nameize>(sess: &ParseSess, ms: &[TokenTree], mut res: I) -> NamedParseResult { - fn n_rec>(sess: &ParseSess, m: &TokenTree, mut res: &mut I, + fn n_rec>(sess: &ParseSess, m: &TokenTree, res: &mut I, ret_val: &mut HashMap>) -> Result<(), (syntax_pos::Span, String)> { match *m { @@ -445,7 +445,7 @@ pub fn parse(sess: &ParseSess, /* error messages here could be improved with links to orig. rules */ if token_name_eq(&parser.token, &token::Eof) { if eof_items.len() == 1 { - let matches = eof_items[0].matches.iter_mut().map(|mut dv| { + let matches = eof_items[0].matches.iter_mut().map(|dv| { Rc::make_mut(dv).pop().unwrap() }); return nameize(sess, ms, matches); diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 8e746676ecd9..80b6794d1e3c 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -86,7 +86,7 @@ impl TTMacroExpander for MacroRulesMacroExpander { fn trace_macros_note(cx: &mut ExtCtxt, sp: Span, message: String) { let sp = sp.macro_backtrace().last().map(|trace| trace.call_site).unwrap_or(sp); - let mut values: &mut Vec = cx.expansions.entry(sp).or_insert_with(Vec::new); + let values: &mut Vec = cx.expansions.entry(sp).or_insert_with(Vec::new); values.push(message); } From 8e4c9e4e9de5d5b052f3e043df889e74f27e635f Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Tue, 1 Aug 2017 15:06:14 +0100 Subject: [PATCH 07/56] Fixed interior mutable references causing a mark The mutability system now checks where derefs go through borrows in the loan chain, and can correctly detect mutable borrows inside structs and tuples. --- .../borrowck/gather_loans/mod.rs | 57 +++++++++++-------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index ba865e125336..a992cf13b510 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -431,38 +431,45 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { // } // } } - + pub fn mark_loan_path_as_mutated(&self, loan_path: &LoanPath) { //! For mutable loans of content whose mutability derives //! from a local variable, mark the mutability decl as necessary. - match loan_path.kind { - LpVar(local_id) | - LpUpvar(ty::UpvarId{ var_id: local_id, closure_expr_id: _ }) => { - self.tcx().used_mut_nodes.borrow_mut().insert(local_id); - } - LpExtend(ref base, mc::McInherited, LpDeref(pointer_kind)) | - LpExtend(ref base, mc::McDeclared, LpDeref(pointer_kind)) => { - match base.kind { - LpVar(_) if pointer_kind != mc::Unique => { - // If you mutate the inside of a ref var, the var itself - // is not used mutably [Issue #25049] - // Unless it's a Box! (mc::Unique) - } - _ => { - self.mark_loan_path_as_mutated(&base); + let mut wrapped_path = Some(loan_path); + let mut through_borrow = false; + + while let Some(current_path) = wrapped_path { + wrapped_path = match current_path.kind { + LpVar(local_id) => { + if !through_borrow { + self.tcx().used_mut_nodes.borrow_mut().insert(local_id); } + None } - } - LpDowncast(ref base, _) | - LpExtend(ref base, mc::McInherited, _) | - LpExtend(ref base, mc::McDeclared, _) => { - self.mark_loan_path_as_mutated(&base); - } - LpExtend(_, mc::McImmutable, _) => { - // Nothing to do. - } + LpUpvar(ty::UpvarId{ var_id: local_id, closure_expr_id: _ }) => { + self.tcx().used_mut_nodes.borrow_mut().insert(local_id); + None + } + LpExtend(ref base, mc::McInherited, LpDeref(pointer_kind)) | + LpExtend(ref base, mc::McDeclared, LpDeref(pointer_kind)) => { + if pointer_kind != mc::Unique { + through_borrow = true; + } + Some(base) + } + LpDowncast(ref base, _) | + LpExtend(ref base, mc::McInherited, _) | + LpExtend(ref base, mc::McDeclared, _) => { + Some(base) + } + LpExtend(_, mc::McImmutable, _) => { + // Nothing to do. + None + } + } } + } pub fn compute_gen_scope(&self, From c62337532688be5223797943f830b098fe711a5a Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Tue, 1 Aug 2017 18:32:32 +0100 Subject: [PATCH 08/56] Fixed extra cases found in better checking. --- src/liballoc/vec_deque.rs | 4 ++-- src/libstd/collections/hash/table.rs | 2 +- src/libsyntax_ext/format.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index 055c2d4840a4..2068c2c9c5fb 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -2558,7 +2558,7 @@ impl<'a, T> Place for PlaceBack<'a, T> { impl<'a, T> InPlace for PlaceBack<'a, T> { type Owner = &'a mut T; - unsafe fn finalize(mut self) -> &'a mut T { + unsafe fn finalize(self) -> &'a mut T { let head = self.vec_deque.head; self.vec_deque.head = self.vec_deque.wrap_add(head, 1); &mut *(self.vec_deque.ptr().offset(head as isize)) @@ -2605,7 +2605,7 @@ impl<'a, T> Place for PlaceFront<'a, T> { impl<'a, T> InPlace for PlaceFront<'a, T> { type Owner = &'a mut T; - unsafe fn finalize(mut self) -> &'a mut T { + unsafe fn finalize(self) -> &'a mut T { self.vec_deque.tail = self.vec_deque.wrap_sub(self.vec_deque.tail, 1); &mut *(self.vec_deque.ptr().offset(self.vec_deque.tail as isize)) } diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 3844690860b5..6f7c5a5de42b 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -563,7 +563,7 @@ impl<'t, K, V> FullBucket> { /// /// This works similarly to `put`, building an `EmptyBucket` out of the /// taken bucket. - pub fn take(mut self) -> (EmptyBucket>, K, V) { + pub fn take(self) -> (EmptyBucket>, K, V) { self.table.size -= 1; unsafe { diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 9734bb867f1d..16b06424c92f 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -529,7 +529,7 @@ impl<'a, 'b> Context<'a, 'b> { /// Actually builds the expression which the format_args! block will be /// expanded to - fn into_expr(mut self) -> P { + fn into_expr(self) -> P { let mut locals = Vec::new(); let mut counts = Vec::new(); let mut pats = Vec::new(); From d817d58fe433da78c8ff942f3fdee4003c3e595d Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Tue, 1 Aug 2017 22:06:08 +0100 Subject: [PATCH 09/56] Fixed formatting. --- src/librustc_borrowck/borrowck/gather_loans/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index a992cf13b510..3d669aa81df6 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -431,7 +431,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { // } // } } - + pub fn mark_loan_path_as_mutated(&self, loan_path: &LoanPath) { //! For mutable loans of content whose mutability derives //! from a local variable, mark the mutability decl as necessary. @@ -467,7 +467,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { // Nothing to do. None } - } + } } } From bb578b6e1214e3b8efea96f6c97f8743fb33b613 Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Tue, 1 Aug 2017 22:06:26 +0100 Subject: [PATCH 10/56] Added tests for bugs fixed. --- src/test/compile-fail/lint-unused-mut-variables.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test/compile-fail/lint-unused-mut-variables.rs b/src/test/compile-fail/lint-unused-mut-variables.rs index 21cfadb9c799..49ba9421d65f 100644 --- a/src/test/compile-fail/lint-unused-mut-variables.rs +++ b/src/test/compile-fail/lint-unused-mut-variables.rs @@ -47,6 +47,20 @@ fn main() { let x = |mut y: isize| 10; //~ ERROR: variable does not need to be mutable fn what(mut foo: isize) {} //~ ERROR: variable does not need to be mutable + let mut a = &mut 5; //~ ERROR: variable does not need to be mutable + *a = 4; + + let mut a = 5; + let mut b = (&mut a,); + *b.0 = 4; //~^ ERROR: variable does not need to be mutable + + fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { + &mut arg[..] //~^ ERROR: variable does not need to be mutable + } + + let mut v : &mut Vec<()> = &mut vec![]; //~ ERROR: variable does not need to be mutable + v.push(()); + // positive cases let mut a = 2; a = 3; From d3236a85ffb17a8cce396156965047807648abd7 Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Wed, 2 Aug 2017 00:55:05 +0100 Subject: [PATCH 11/56] Fixed another problem. --- src/librustc_trans/time_graph.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_trans/time_graph.rs b/src/librustc_trans/time_graph.rs index e0ebe8a0933f..ead6e4325612 100644 --- a/src/librustc_trans/time_graph.rs +++ b/src/librustc_trans/time_graph.rs @@ -70,7 +70,7 @@ impl TimeGraph { { let mut table = self.data.lock().unwrap(); - let mut data = table.entry(timeline).or_insert(PerThread { + let data = table.entry(timeline).or_insert(PerThread { timings: Vec::new(), open_work_package: None, }); @@ -90,7 +90,7 @@ impl TimeGraph { let end = Instant::now(); let mut table = self.data.lock().unwrap(); - let mut data = table.get_mut(&timeline).unwrap(); + let data = table.get_mut(&timeline).unwrap(); if let Some((start, work_package_kind)) = data.open_work_package { data.timings.push(Timing { From 9c854db82b767ddd228dbff1e51bb3eed87464b4 Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Wed, 2 Aug 2017 15:16:20 +0100 Subject: [PATCH 12/56] Fixed errors in libstd. --- src/libcore/tests/slice.rs | 12 ++++++------ src/libstd/error.rs | 2 +- src/libstd/io/cursor.rs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index e5d6b53b5706..8c31d2e83d35 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -105,27 +105,27 @@ fn test_chunks_last() { #[test] fn test_chunks_mut_count() { - let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; + let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; let c = v.chunks_mut(3); assert_eq!(c.count(), 2); - let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4]; + let v2: &mut [i32] = &mut [0, 1, 2, 3, 4]; let c2 = v2.chunks_mut(2); assert_eq!(c2.count(), 3); - let mut v3: &mut [i32] = &mut []; + let v3: &mut [i32] = &mut []; let c3 = v3.chunks_mut(2); assert_eq!(c3.count(), 0); } #[test] fn test_chunks_mut_nth() { - let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; + let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; let mut c = v.chunks_mut(2); assert_eq!(c.nth(1).unwrap()[1], 3); assert_eq!(c.next().unwrap()[0], 4); - let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4]; + let v2: &mut [i32] = &mut [0, 1, 2, 3, 4]; let mut c2 = v2.chunks_mut(3); assert_eq!(c2.nth(1).unwrap()[1], 4); assert_eq!(c2.next(), None); @@ -194,7 +194,7 @@ fn get_range() { #[test] fn get_mut_range() { - let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; + let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; assert_eq!(v.get_mut(..), Some(&mut [0, 1, 2, 3, 4, 5][..])); assert_eq!(v.get_mut(..2), Some(&mut [0, 1][..])); assert_eq!(v.get_mut(2..), Some(&mut [2, 3, 4, 5][..])); diff --git a/src/libstd/error.rs b/src/libstd/error.rs index d1c2bfb96b33..401552a6ec41 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -514,7 +514,7 @@ mod tests { #[test] fn downcasting() { let mut a = A; - let mut a = &mut a as &mut (Error + 'static); + let a = &mut a as &mut (Error + 'static); assert_eq!(a.downcast_ref::(), Some(&A)); assert_eq!(a.downcast_ref::(), None); assert_eq!(a.downcast_mut::(), Some(&mut A)); diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 616b4f47ed3e..d986021a18bb 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -456,7 +456,7 @@ mod tests { #[test] fn test_slice_reader() { let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; - let mut reader = &mut &in_buf[..]; + let reader = &mut &in_buf[..]; let mut buf = []; assert_eq!(reader.read(&mut buf).unwrap(), 0); let mut buf = [0]; From 553ac5279ec8ff1eb77fe78d3e8f94b499aae306 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Thu, 3 Aug 2017 14:56:25 +0100 Subject: [PATCH 13/56] Updated release notes for 1.20 --- RELEASES.md | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 137 insertions(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 5bb23149f2a7..d42d879f3d81 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,139 @@ +Version 1.20.0 (2017-08-31) +=========================== + +Language +-------- +- [Associated constants in traits is now stabilised.][42809] +- [A lot of macro bugs are now fixed.][42913] + +Compiler +-------- + +- [Struct fields are now properly to the expected field type.][42807] +- [Enabled wasm LLVM backend][42571] WASM can now be built with the + `wasm32-experimental-emscripten` target. +- [Changed some of the error messages to be more helpful.][42033] +- [Add support for RELRO(RELocation Read-Only) for platforms that support + it.][43170] +- [rustc now reports the total number of errors on compilation failure][43015] + previously this was only the number of errors in the pass that failed. +- [Expansion in rustc has been sped up 29x.][42533] +- [added `msp430-none-elf` target.][43099] +- [rustc will now suggest one-argument enum variant to fix type mismatch when + applicable][43178] +- [Fixes backtraces on Redox][43228] +- [rustc now identifies different versions of same crate when absolute paths of + different types match in an error message.][42826] + +Libraries +--------- + +- [`Ref`, `RefMut`, `MutexGuard`, `RwLockReadGuard`, `RwLockWriteGuard` + now impl `fmt::Display` & `fmt::Debug`.][42822] +- [Relaxed Debug constraints on {HashMap,BTreeMap}::{Keys,Values}.][42854] +- [Implement `PartialEq`, `Eq`, `PartialOrd`, `Ord`, `Debug`, `Hash` for unsized + tuples.][43011] +- [Impl `Clone` for `DefaultHasher`.][42799] +- [Implement `Sync` for `SyncSender`.][42397] +- [Fixed how `{f32, f64}::{is_sign_negative, is_sign_positive}` handles + NaN.][42431] +- [allow messages in the `unimplemented!()` macro.][42155] + ie. `unimplemented!("Waiting for 1.21 to be stable")` +- [`char`now impls `FromStr`.][42271] +- [support pub(restricted) in thread_local! (round 2)][43185] +- [Upgrade to Unicode 10.0.0][42999] +- [Reimplemented `{f32, f64}::{min, max}` in Rust instead of using CMath.][42430] +- [Skip the main thread's manual stack guard on Linux][43072] +- [Iterator::nth for `ops::{Range, RangeFrom}` is now done in O(1) time][43077] +- [`#cfg[align(N)]` attribute max number is now 2^31 - 1.][43097] This was + previously 2^15. +- [`{OsStr, Path}::Display` now avoids allocations where possible][42613] + +Stabilized APIs +--------------- + +- [`Chain::get_mut`] +- [`Chain::get_ref`] +- [`Chain::into_inner`] +- [`Take::get_mut`] +- [`Take::get_ref`] +- [`f32::from_bits`] +- [`f32::to_bits`] +- [`f64::from_bits`] +- [`f64::to_bits`] +- [`slice::sort_unstable`] +- [`slice::sort_unstable_by`] +- [`slice::sort_unstable_by_key`] + +Cargo +----- +- [Cargo API token location moved from `~/.cargo/config` to + `~/cargo/credentials`.][cargo/3978] +- [Cargo will now build multiple `main.rs` binaries in different + directories.][cargo/4214] ie. Having `src/server/main.rs` and + `src/client/main.rs` generates `target/debug/server` and `target/debug/client` +- [You can now specify version of a binary when installed through + `cargo install` using `--vers`.][cargo/4229] +- [Added `--no-fail-fast` flag to cargo to run all benchmarks regardless of + failure.][cargo/4248] +- [Changed the convention around which file is the crate root.][cargo/4259] +- [The `include`/`exclude` property in `Cargo.toml` now accepts gitignore paths + instead of glob patterns][cargo/4270]. Glob patterns are now deprecated. + +Compatibility Notes +------------------- + +- [Functions with `'static` in their return types will now not be as usable as + if they were using lifetime parameters instead.][42417] + +[42033]: https://github.com/rust-lang/rust/pull/42033 +[42155]: https://github.com/rust-lang/rust/pull/42155 +[42271]: https://github.com/rust-lang/rust/pull/42271 +[42397]: https://github.com/rust-lang/rust/pull/42397 +[42417]: https://github.com/rust-lang/rust/pull/42417 +[42430]: https://github.com/rust-lang/rust/pull/42430 +[42431]: https://github.com/rust-lang/rust/pull/42431 +[42533]: https://github.com/rust-lang/rust/pull/42533 +[42571]: https://github.com/rust-lang/rust/pull/42571 +[42613]: https://github.com/rust-lang/rust/pull/42613 +[42799]: https://github.com/rust-lang/rust/pull/42799 +[42807]: https://github.com/rust-lang/rust/pull/42807 +[42809]: https://github.com/rust-lang/rust/pull/42809 +[42822]: https://github.com/rust-lang/rust/pull/42822 +[42826]: https://github.com/rust-lang/rust/pull/42826 +[42854]: https://github.com/rust-lang/rust/pull/42854 +[42913]: https://github.com/rust-lang/rust/pull/42913 +[42999]: https://github.com/rust-lang/rust/pull/42999 +[43011]: https://github.com/rust-lang/rust/pull/43011 +[43015]: https://github.com/rust-lang/rust/pull/43015 +[43072]: https://github.com/rust-lang/rust/pull/43072 +[43077]: https://github.com/rust-lang/rust/pull/43077 +[43097]: https://github.com/rust-lang/rust/pull/43097 +[43099]: https://github.com/rust-lang/rust/pull/43099 +[43170]: https://github.com/rust-lang/rust/pull/43170 +[43178]: https://github.com/rust-lang/rust/pull/43178 +[43185]: https://github.com/rust-lang/rust/pull/43185 +[43228]: https://github.com/rust-lang/rust/pull/43228 +[cargo/3978]: https://github.com/rust-lang/cargo/pull/3978 +[cargo/4214]: https://github.com/rust-lang/cargo/pull/4214 +[cargo/4229]: https://github.com/rust-lang/cargo/pull/4229 +[cargo/4248]: https://github.com/rust-lang/cargo/pull/4248 +[cargo/4259]: https://github.com/rust-lang/cargo/pull/4259 +[cargo/4270]: https://github.com/rust-lang/cargo/pull/4270 +[`Chain::get_mut`]: https://doc.rust-lang.org/std/io/struct.Chain.html#method.get_mut +[`Chain::get_ref`]: https://doc.rust-lang.org/std/io/struct.Chain.html#method.get_ref +[`Chain::into_inner`]: https://doc.rust-lang.org/std/io/struct.Chain.html#method.into_inner +[`Take::get_mut`]: https://doc.rust-lang.org/std/io/struct.Take.html#method.get_mut +[`Take::get_ref`]: https://doc.rust-lang.org/std/io/struct.Take.html#method.get_ref +[`f32::from_bits`]: https://doc.rust-lang.org/std/primitive.f32.html#method.from_bits +[`f32::to_bits`]: https://doc.rust-lang.org/std/primitive.f32.html#method.to_bits +[`f64::from_bits`]: https://doc.rust-lang.org/std/primitive.f64.html#method.from_bits +[`f64::to_bits`]: https://doc.rust-lang.org/std/primitive.f64.html#method.to_bits +[`slice::sort_unstable_by_key`]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort_unstable_by_key +[`slice::sort_unstable_by`]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort_unstable_by +[`slice::sort_unstable`]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort_unstable + + Version 1.19.0 (2017-07-20) =========================== @@ -1679,7 +1815,7 @@ Tooling * [Test binaries now support a `--test-threads` argument to specify the number of threads used to run tests, and which acts the same as the - `RUST_TEST_THREADS` environment variable](https://github.com/rust-lang/rust/pull/35414) + `RUST_TEST_THREADS` environment variable](https://github.com/rust-lang/rust/pull/35414) * [The test runner now emits a warning when tests run over 60 seconds](https://github.com/rust-lang/rust/pull/35405) * [rustdoc: Fix methods in search results](https://github.com/rust-lang/rust/pull/34752) * [`rust-lldb` warns about unsupported versions of LLDB](https://github.com/rust-lang/rust/pull/34646) From 6200aeff6132c660fde70c6d51f88d823e08b6b7 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Thu, 3 Aug 2017 15:07:41 +0100 Subject: [PATCH 14/56] fixed some formatting --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index d42d879f3d81..fa0c8a5f2061 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -30,7 +30,7 @@ Libraries - [`Ref`, `RefMut`, `MutexGuard`, `RwLockReadGuard`, `RwLockWriteGuard` now impl `fmt::Display` & `fmt::Debug`.][42822] -- [Relaxed Debug constraints on {HashMap,BTreeMap}::{Keys,Values}.][42854] +- [Relaxed Debug constraints on `{HashMap,BTreeMap}::{Keys,Values}`.][42854] - [Implement `PartialEq`, `Eq`, `PartialOrd`, `Ord`, `Debug`, `Hash` for unsized tuples.][43011] - [Impl `Clone` for `DefaultHasher`.][42799] From c88ec60e5f5f67f4657bd1d8efbc67cf40202104 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Thu, 3 Aug 2017 15:16:49 +0100 Subject: [PATCH 15/56] Update RELEASES.md --- RELEASES.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index fa0c8a5f2061..bcdadf7baae7 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -28,18 +28,19 @@ Compiler Libraries --------- -- [`Ref`, `RefMut`, `MutexGuard`, `RwLockReadGuard`, `RwLockWriteGuard` - now impl `fmt::Display` & `fmt::Debug`.][42822] + - [Relaxed Debug constraints on `{HashMap,BTreeMap}::{Keys,Values}`.][42854] -- [Implement `PartialEq`, `Eq`, `PartialOrd`, `Ord`, `Debug`, `Hash` for unsized +- [Impl `PartialEq`, `Eq`, `PartialOrd`, `Ord`, `Debug`, `Hash` for unsized tuples.][43011] +- [Impl `fmt::{Display, Debug}` for `Ref`, `RefMut`, `MutexGuard`, + `RwLockReadGuard`, `RwLockWriteGuard`][42822] - [Impl `Clone` for `DefaultHasher`.][42799] -- [Implement `Sync` for `SyncSender`.][42397] +- [Impl `Sync` for `SyncSender`.][42397] +- [Impl `FromStr` for `char`][42271] - [Fixed how `{f32, f64}::{is_sign_negative, is_sign_positive}` handles NaN.][42431] - [allow messages in the `unimplemented!()` macro.][42155] ie. `unimplemented!("Waiting for 1.21 to be stable")` -- [`char`now impls `FromStr`.][42271] - [support pub(restricted) in thread_local! (round 2)][43185] - [Upgrade to Unicode 10.0.0][42999] - [Reimplemented `{f32, f64}::{min, max}` in Rust instead of using CMath.][42430] From b07a0596439532d78142c92e1f1a9ae14e8ae9f5 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 4 Aug 2017 00:16:22 +0000 Subject: [PATCH 16/56] Add support for Vector Subtract Saturated on PowerPC --- src/etc/platform-intrinsics/powerpc.json | 7 +++++ src/librustc_platform_intrinsics/powerpc.rs | 30 +++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/etc/platform-intrinsics/powerpc.json b/src/etc/platform-intrinsics/powerpc.json index 7f01aaa3ac11..cf9b7a167326 100644 --- a/src/etc/platform-intrinsics/powerpc.json +++ b/src/etc/platform-intrinsics/powerpc.json @@ -72,6 +72,13 @@ "llvm": "vmin{0.kind}{0.data_type_short}", "ret": "i(8-32)", "args": ["0", "0"] + }, + { + "intrinsic": "sub{0.kind}{0.data_type_short}s", + "width": [128], + "llvm": "vsub{0.kind}{0.data_type_short}s", + "ret": "i(8-32)", + "args": ["0", "0"] } ] } diff --git a/src/librustc_platform_intrinsics/powerpc.rs b/src/librustc_platform_intrinsics/powerpc.rs index 60074cce2b9a..4825a736e72b 100644 --- a/src/librustc_platform_intrinsics/powerpc.rs +++ b/src/librustc_platform_intrinsics/powerpc.rs @@ -142,6 +142,36 @@ pub fn find(name: &str) -> Option { output: &::U32x4, definition: Named("llvm.ppc.altivec.vminuw") }, + "_vec_subsbs" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, + output: &::I8x16, + definition: Named("llvm.ppc.altivec.vsubsbs") + }, + "_vec_sububs" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, + output: &::U8x16, + definition: Named("llvm.ppc.altivec.vsububs") + }, + "_vec_subshs" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, + output: &::I16x8, + definition: Named("llvm.ppc.altivec.vsubshs") + }, + "_vec_subuhs" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, + output: &::U16x8, + definition: Named("llvm.ppc.altivec.vsubuhs") + }, + "_vec_subsws" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, + output: &::I32x4, + definition: Named("llvm.ppc.altivec.vsubsws") + }, + "_vec_subuws" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, + output: &::U32x4, + definition: Named("llvm.ppc.altivec.vsubuws") + }, _ => return None, }) } From 844e9adf25efd251749d5833710a03e5ba1a2449 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 4 Aug 2017 00:19:58 +0000 Subject: [PATCH 17/56] Add support for Vector Subtract Carryout on PowerPC --- src/etc/platform-intrinsics/powerpc.json | 7 +++++++ src/librustc_platform_intrinsics/powerpc.rs | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/src/etc/platform-intrinsics/powerpc.json b/src/etc/platform-intrinsics/powerpc.json index cf9b7a167326..e7810109f3ff 100644 --- a/src/etc/platform-intrinsics/powerpc.json +++ b/src/etc/platform-intrinsics/powerpc.json @@ -79,6 +79,13 @@ "llvm": "vsub{0.kind}{0.data_type_short}s", "ret": "i(8-32)", "args": ["0", "0"] + }, + { + "intrinsic": "subc", + "width": [128], + "llvm": "vsubcuw", + "ret": "u32", + "args": ["0", "0"] } ] } diff --git a/src/librustc_platform_intrinsics/powerpc.rs b/src/librustc_platform_intrinsics/powerpc.rs index 4825a736e72b..eb47595f4b06 100644 --- a/src/librustc_platform_intrinsics/powerpc.rs +++ b/src/librustc_platform_intrinsics/powerpc.rs @@ -172,6 +172,11 @@ pub fn find(name: &str) -> Option { output: &::U32x4, definition: Named("llvm.ppc.altivec.vsubuws") }, + "_vec_subc" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, + output: &::U32x4, + definition: Named("llvm.ppc.altivec.vsubcuw") + }, _ => return None, }) } From 1618664a736cb9f4b9a5d9e3cd8670da302eea75 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Fri, 4 Aug 2017 13:35:30 +0100 Subject: [PATCH 18/56] Update RELEASES.md --- RELEASES.md | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index bcdadf7baae7..ec24d663050e 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -9,7 +9,7 @@ Language Compiler -------- -- [Struct fields are now properly to the expected field type.][42807] +- [Struct fields are now properly coerced to the expected field type.][42807] - [Enabled wasm LLVM backend][42571] WASM can now be built with the `wasm32-experimental-emscripten` target. - [Changed some of the error messages to be more helpful.][42033] @@ -53,18 +53,41 @@ Libraries Stabilized APIs --------------- +- [`CStr::into_c_string`] +- [`CString::as_c_str`] +- [`CString::into_boxed_c_str`] - [`Chain::get_mut`] - [`Chain::get_ref`] - [`Chain::into_inner`] +- [`Option::get_or_insert_with`] +- [`Option::get_or_insert`] +- [`OsStr::into_os_string`] +- [`OsString::into_boxed_os_str`] - [`Take::get_mut`] - [`Take::get_ref`] +- [`Utf8Error::error_len`] +- [`char::EscapeDebug`] +- [`char::escape_debug`] +- [`compile_error!`] - [`f32::from_bits`] - [`f32::to_bits`] - [`f64::from_bits`] - [`f64::to_bits`] -- [`slice::sort_unstable`] -- [`slice::sort_unstable_by`] +- [`mem::ManuallyDrop`] - [`slice::sort_unstable_by_key`] +- [`slice::sort_unstable_by`] +- [`slice::sort_unstable`] +- [`ste::from_boxed_utf8_unchecked`] +- [`str::as_bytes_mut`] +- [`str::as_bytes_mut`] +- [`str::from_utf8_mut`] +- [`str::from_utf8_unchecked_mut`] +- [`str::get_mut`] +- [`str::get_unchecked_mut`] +- [`str::get_unchecked`] +- [`str::get`] +- [`str::into_boxed_bytes`] + Cargo ----- @@ -121,18 +144,40 @@ Compatibility Notes [cargo/4248]: https://github.com/rust-lang/cargo/pull/4248 [cargo/4259]: https://github.com/rust-lang/cargo/pull/4259 [cargo/4270]: https://github.com/rust-lang/cargo/pull/4270 +[`CStr::into_c_string`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html#method.into_c_string +[`CString::as_c_str`]: https://doc.rust-lang.org/std/ffi/struct.CString.html#method.as_c_str +[`CString::into_boxed_c_str`]: https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str [`Chain::get_mut`]: https://doc.rust-lang.org/std/io/struct.Chain.html#method.get_mut [`Chain::get_ref`]: https://doc.rust-lang.org/std/io/struct.Chain.html#method.get_ref [`Chain::into_inner`]: https://doc.rust-lang.org/std/io/struct.Chain.html#method.into_inner +[`Option::get_or_insert_with`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.get_or_insert_with +[`Option::get_or_insert`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.get_or_insert +[`OsStr::into_os_string`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.into_os_string +[`OsString::into_boxed_os_str`]: https://doc.rust-lang.org/std/ffi/struct.OsString.html#method.into_boxed_os_str [`Take::get_mut`]: https://doc.rust-lang.org/std/io/struct.Take.html#method.get_mut [`Take::get_ref`]: https://doc.rust-lang.org/std/io/struct.Take.html#method.get_ref +[`Utf8Error::error_len`]: https://doc.rust-lang.org/std/str/struct.Utf8Error.html#method.error_len +[`char::EscapeDebug`]: https://doc.rust-lang.org/std/char/struct.EscapeDebug.html +[`char::escape_debug`]: https://doc.rust-lang.org/std/primitive.char.html#method.escape_debug +[`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html [`f32::from_bits`]: https://doc.rust-lang.org/std/primitive.f32.html#method.from_bits [`f32::to_bits`]: https://doc.rust-lang.org/std/primitive.f32.html#method.to_bits [`f64::from_bits`]: https://doc.rust-lang.org/std/primitive.f64.html#method.from_bits [`f64::to_bits`]: https://doc.rust-lang.org/std/primitive.f64.html#method.to_bits +[`mem::ManuallyDrop`]: https://doc.rust-lang.org/std/mem/union.ManuallyDrop.html [`slice::sort_unstable_by_key`]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort_unstable_by_key [`slice::sort_unstable_by`]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort_unstable_by [`slice::sort_unstable`]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort_unstable +[`ste::from_boxed_utf8_unchecked`]: https://doc.rust-lang.org/std/str/fn.from_boxed_utf8_unchecked.html +[`str::as_bytes_mut`]: https://doc.rust-lang.org/std/primitive.str.html#method.as_bytes_mut +[`str::as_bytes_mut`]: https://doc.rust-lang.org/std/primitive.str.html#method.as_bytes_mut +[`str::from_utf8_mut`]: https://doc.rust-lang.org/std/str/fn.from_utf8_mut.html +[`str::from_utf8_unchecked_mut`]: https://doc.rust-lang.org/std/str/fn.from_utf8_unchecked_mut.html +[`str::get_mut`]: https://doc.rust-lang.org/std/primitive.str.html#method.get_mut +[`str::get_unchecked_mut`]: https://doc.rust-lang.org/std/primitive.str.html#method.get_unchecked_mut +[`str::get_unchecked`]: https://doc.rust-lang.org/std/primitive.str.html#method.get_unchecked +[`str::get`]: https://doc.rust-lang.org/std/primitive.str.html#method.get +[`str::into_boxed_bytes`]: https://doc.rust-lang.org/std/primitive.str.html#method.into_boxed_bytes Version 1.19.0 (2017-07-20) From 09c1b7486189196e51bcf4878def561c9f5b2736 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Fri, 4 Aug 2017 13:40:05 +0100 Subject: [PATCH 19/56] Update RELEASES.md --- RELEASES.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index ec24d663050e..e62e218c6c35 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -41,12 +41,12 @@ Libraries NaN.][42431] - [allow messages in the `unimplemented!()` macro.][42155] ie. `unimplemented!("Waiting for 1.21 to be stable")` -- [support pub(restricted) in thread_local! (round 2)][43185] +- [`pub(restricted)` is now supported in the `thread_local!` macro.][43185] - [Upgrade to Unicode 10.0.0][42999] - [Reimplemented `{f32, f64}::{min, max}` in Rust instead of using CMath.][42430] - [Skip the main thread's manual stack guard on Linux][43072] - [Iterator::nth for `ops::{Range, RangeFrom}` is now done in O(1) time][43077] -- [`#cfg[align(N)]` attribute max number is now 2^31 - 1.][43097] This was +- [`#[repr(align(N))]` attribute max number is now 2^31 - 1.][43097] This was previously 2^15. - [`{OsStr, Path}::Display` now avoids allocations where possible][42613] @@ -109,6 +109,8 @@ Compatibility Notes - [Functions with `'static` in their return types will now not be as usable as if they were using lifetime parameters instead.][42417] +- [The reimplementation of `{f32, f64}::is_sign_{negative, positive}` now + takes the sign of NaN into account where previously didn't.][42430] [42033]: https://github.com/rust-lang/rust/pull/42033 [42155]: https://github.com/rust-lang/rust/pull/42155 From 381cbe499483f73ec4eecc0345c156e8bdf951ae Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 4 Aug 2017 00:19:58 +0000 Subject: [PATCH 20/56] Add support for Vector Add Saturated on PowerPC --- src/etc/platform-intrinsics/powerpc.json | 7 +++++ src/librustc_platform_intrinsics/powerpc.rs | 30 +++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/etc/platform-intrinsics/powerpc.json b/src/etc/platform-intrinsics/powerpc.json index e7810109f3ff..7805bb1057d3 100644 --- a/src/etc/platform-intrinsics/powerpc.json +++ b/src/etc/platform-intrinsics/powerpc.json @@ -86,6 +86,13 @@ "llvm": "vsubcuw", "ret": "u32", "args": ["0", "0"] + }, + { + "intrinsic": "add{0.kind}{0.data_type_short}s", + "width": [128], + "llvm": "vadd{0.kind}{0.data_type_short}s", + "ret": "i(8-32)", + "args": ["0", "0"] } ] } diff --git a/src/librustc_platform_intrinsics/powerpc.rs b/src/librustc_platform_intrinsics/powerpc.rs index eb47595f4b06..0c686997eda4 100644 --- a/src/librustc_platform_intrinsics/powerpc.rs +++ b/src/librustc_platform_intrinsics/powerpc.rs @@ -177,6 +177,36 @@ pub fn find(name: &str) -> Option { output: &::U32x4, definition: Named("llvm.ppc.altivec.vsubcuw") }, + "_vec_addsbs" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, + output: &::I8x16, + definition: Named("llvm.ppc.altivec.vaddsbs") + }, + "_vec_addubs" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, + output: &::U8x16, + definition: Named("llvm.ppc.altivec.vaddubs") + }, + "_vec_addshs" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, + output: &::I16x8, + definition: Named("llvm.ppc.altivec.vaddshs") + }, + "_vec_adduhs" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, + output: &::U16x8, + definition: Named("llvm.ppc.altivec.vadduhs") + }, + "_vec_addsws" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, + output: &::I32x4, + definition: Named("llvm.ppc.altivec.vaddsws") + }, + "_vec_adduws" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, + output: &::U32x4, + definition: Named("llvm.ppc.altivec.vadduws") + }, _ => return None, }) } From bb47972d4c02f1731792e76488e1d2bc266de080 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 4 Aug 2017 00:19:58 +0000 Subject: [PATCH 21/56] Add support for Vector Add Carryout on PowerPC --- src/etc/platform-intrinsics/powerpc.json | 7 +++++++ src/librustc_platform_intrinsics/powerpc.rs | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/src/etc/platform-intrinsics/powerpc.json b/src/etc/platform-intrinsics/powerpc.json index 7805bb1057d3..7dde0fd4d087 100644 --- a/src/etc/platform-intrinsics/powerpc.json +++ b/src/etc/platform-intrinsics/powerpc.json @@ -93,6 +93,13 @@ "llvm": "vadd{0.kind}{0.data_type_short}s", "ret": "i(8-32)", "args": ["0", "0"] + }, + { + "intrinsic": "addc", + "width": [128], + "llvm": "vaddcuw", + "ret": "u32", + "args": ["0", "0"] } ] } diff --git a/src/librustc_platform_intrinsics/powerpc.rs b/src/librustc_platform_intrinsics/powerpc.rs index 0c686997eda4..0ec6a7e66d85 100644 --- a/src/librustc_platform_intrinsics/powerpc.rs +++ b/src/librustc_platform_intrinsics/powerpc.rs @@ -207,6 +207,11 @@ pub fn find(name: &str) -> Option { output: &::U32x4, definition: Named("llvm.ppc.altivec.vadduws") }, + "_vec_addc" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, + output: &::U32x4, + definition: Named("llvm.ppc.altivec.vaddcuw") + }, _ => return None, }) } From 4e2ddcb879d225e7d22fbf4af0536c06203b8d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malo=20Jaffr=C3=A9?= Date: Sun, 6 Aug 2017 17:36:50 +0200 Subject: [PATCH 22/56] Update the list of confusable characters Also reorder and space the list to make it clearer for futures updates and to come closer to the original list. Thanks @est31 for the instructions. Fixes #43629. r? @est31 --- src/libsyntax/parse/lexer/unicode_chars.rs | 144 ++++++++++++++++++--- 1 file changed, 125 insertions(+), 19 deletions(-) diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs index 83a164bdb969..cc38021b7aa1 100644 --- a/src/libsyntax/parse/lexer/unicode_chars.rs +++ b/src/libsyntax/parse/lexer/unicode_chars.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -9,15 +9,16 @@ // except according to those terms. // Characters and their corresponding confusables were collected from -// http://www.unicode.org/Public/security/revision-06/confusables.txt +// http://www.unicode.org/Public/security/10.0.0/confusables.txt use syntax_pos::{Span, NO_EXPANSION}; use errors::DiagnosticBuilder; use super::StringReader; const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[ - (' ', "No-Break Space", ' '), - (' ', "Ogham Space Mark", ' '), + ('
', "Line Separator", ' '), + ('
', "Paragraph Separator", ' '), + (' ', "Ogham Space mark", ' '), (' ', "En Quad", ' '), (' ', "Em Quad", ' '), (' ', "En Space", ' '), @@ -25,39 +26,63 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[ (' ', "Three-Per-Em Space", ' '), (' ', "Four-Per-Em Space", ' '), (' ', "Six-Per-Em Space", ' '), - (' ', "Figure Space", ' '), (' ', "Punctuation Space", ' '), (' ', "Thin Space", ' '), (' ', "Hair Space", ' '), - (' ', "Narrow No-Break Space", ' '), (' ', "Medium Mathematical Space", ' '), + (' ', "No-Break Space", ' '), + (' ', "Figure Space", ' '), + (' ', "Narrow No-Break Space", ' '), (' ', "Ideographic Space", ' '), + ('ߺ', "Nko Lajanyalan", '_'), ('﹍', "Dashed Low Line", '_'), ('﹎', "Centreline Low Line", '_'), ('﹏', "Wavy Low Line", '_'), + ('_', "Fullwidth Low Line", '-'), + ('‐', "Hyphen", '-'), ('‑', "Non-Breaking Hyphen", '-'), ('‒', "Figure Dash", '-'), ('–', "En Dash", '-'), ('—', "Em Dash", '-'), ('﹘', "Small Em Dash", '-'), + ('۔', "Arabic Full Stop", '-'), ('⁃', "Hyphen Bullet", '-'), ('˗', "Modifier Letter Minus Sign", '-'), ('−', "Minus Sign", '-'), + ('➖', "Heavy Minus Sign", '-'), + ('Ⲻ', "Coptic Letter Dialect-P Ni", '-'), ('ー', "Katakana-Hiragana Prolonged Sound Mark", '-'), + ('-', "Fullwidth Hyphen-Minus", '-'), + ('―', "Horizontal Bar", '-'), + ('─', "Box Drawings Light Horizontal", '-'), + ('━', "Box Drawings Heavy Horizontal", '-'), + ('㇐', "CJK Stroke H", '-'), + ('ꟷ', "Latin Epigraphic Letter Dideways", '-'), + ('ᅳ', "Hangul Jungseong Eu", '-'), + ('ㅡ', "Hangul Letter Eu", '-'), + ('一', "CJK Unified Ideograph-4E00", '-'), + ('⼀', "Kangxi Radical One", '-'), + + ('؍', "Arabic Date Separator", ','), ('٫', "Arabic Decimal Separator", ','), ('‚', "Single Low-9 Quotation Mark", ','), + ('¸', "Cedilla", ','), ('ꓹ', "Lisu Letter Tone Na Po", ','), (',', "Fullwidth Comma", ','), + (';', "Greek Question Mark", ';'), (';', "Fullwidth Semicolon", ';'), + ('︔', "Presentation Form For Vertical Semicolon", ';'), + ('ः', "Devanagari Sign Visarga", ':'), ('ઃ', "Gujarati Sign Visarga", ':'), (':', "Fullwidth Colon", ':'), ('։', "Armenian Full Stop", ':'), ('܃', "Syriac Supralinear Colon", ':'), ('܄', "Syriac Sublinear Colon", ':'), + ('᛬', "Runic Multiple Ponctuation", ':'), ('︰', "Presentation Form For Vertical Two Dot Leader", ':'), ('᠃', "Mongolian Full Stop", ':'), ('᠉', "Mongolian Manchu Full Stop", ':'), @@ -68,25 +93,48 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[ ('∶', "Ratio", ':'), ('ː', "Modifier Letter Triangular Colon", ':'), ('ꓽ', "Lisu Letter Tone Mya Jeu", ':'), + ('︓', "Presentation Form For Vertical Colon", ':'), + ('!', "Fullwidth Exclamation Mark", '!'), ('ǃ', "Latin Letter Retroflex Click", '!'), + ('ⵑ', "Tifinagh Letter Tuareg Yang", '!'), + ('︕', "Presentation Form For Vertical Exclamation Mark", '!'), + ('ʔ', "Latin Letter Glottal Stop", '?'), + ('Ɂ', "Latin Capital Letter Glottal Stop", '?'), ('ॽ', "Devanagari Letter Glottal Stop", '?'), ('Ꭾ', "Cherokee Letter He", '?'), + ('ꛫ', "Bamum Letter Ntuu", '?'), ('?', "Fullwidth Question Mark", '?'), + ('︖', "Presentation Form For Vertical Question Mark", '?'), + ('𝅭', "Musical Symbol Combining Augmentation Dot", '.'), ('․', "One Dot Leader", '.'), - ('۔', "Arabic Full Stop", '.'), ('܁', "Syriac Supralinear Full Stop", '.'), ('܂', "Syriac Sublinear Full Stop", '.'), ('꘎', "Vai Full Stop", '.'), ('𐩐', "Kharoshthi Punctuation Dot", '.'), - ('·', "Middle Dot", '.'), ('٠', "Arabic-Indic Digit Zero", '.'), ('۰', "Extended Arabic-Indic Digit Zero", '.'), ('ꓸ', "Lisu Letter Tone Mya Ti", '.'), - ('。', "Ideographic Full Stop", '.'), + ('·', "Middle Dot", '.'), ('・', "Katakana Middle Dot", '.'), + ('・', "Halfwidth Katakana Middle Dot", '.'), + ('᛫', "Runic Single Punctuation", '.'), + ('·', "Greek Ano Teleia", '.'), + ('⸱', "Word Separator Middle Dot", '.'), + ('𐄁', "Aegean Word Separator Dot", '.'), + ('•', "Bullet", '.'), + ('‧', "Hyphenation Point", '.'), + ('∙', "Bullet Operator", '.'), + ('⋅', "Dot Operator", '.'), + ('ꞏ', "Latin Letter Sinological Dot", '.'), + ('ᐧ', "Canadian Syllabics Final Middle Dot", '.'), + ('ᐧ', "Canadian Syllabics Final Middle Dot", '.'), + ('.', "Fullwidth Full Stop", '.'), + ('。', "Ideographic Full Stop", '.'), + ('︒', "Presentation Form For Vertical Ideographic Full Stop", '.'), + ('՝', "Armenian Comma", '\''), (''', "Fullwidth Apostrophe", '\''), ('‘', "Left Single Quotation Mark", '\''), @@ -96,8 +144,10 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[ ('‵', "Reversed Prime", '\''), ('՚', "Armenian Apostrophe", '\''), ('׳', "Hebrew Punctuation Geresh", '\''), + ('`', "Greek Accent", '\''), ('`', "Greek Varia", '\''), ('`', "Fullwidth Grave Accent", '\''), + ('´', "Acute Accent", '\''), ('΄', "Greek Tonos", '\''), ('´', "Greek Oxia", '\''), ('᾽', "Greek Koronis", '\''), @@ -105,6 +155,7 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[ ('῾', "Greek Dasia", '\''), ('ʹ', "Modifier Letter Prime", '\''), ('ʹ', "Greek Numeral Sign", '\''), + ('ˈ', "Modifier Letter Vertical Line", '\''), ('ˊ', "Modifier Letter Acute Accent", '\''), ('ˋ', "Modifier Letter Grave Accent", '\''), ('˴', "Modifier Letter Middle Grave Accent", '\''), @@ -116,6 +167,12 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[ ('י', "Hebrew Letter Yod", '\''), ('ߴ', "Nko High Tone Apostrophe", '\''), ('ߵ', "Nko Low Tone Apostrophe", '\''), + ('ᑊ', "Canadian Syllabics West-Cree P", '\''), + ('ᛌ', "Runic Letter Short-Twig-Sol S", '\''), + ('𖽑', "Miao Sign Aspiration", '\''), + ('𖽒', "Miao Sign Reformed Voicing", '\''), + + ('᳓', "Vedic Sign Nihshvasa", '"'), ('"', "Fullwidth Quotation Mark", '"'), ('“', "Left Double Quotation Mark", '"'), ('”', "Right Double Quotation Mark", '"'), @@ -132,12 +189,15 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[ ('ײ', "Hebrew Ligature Yiddish Double Yod", '"'), ('❞', "Heavy Double Comma Quotation Mark Ornament", '"'), ('❝', "Heavy Double Turned Comma Quotation Mark Ornament", '"'), + + ('(', "Fullwidth Left Parenthesis", '('), ('❨', "Medium Left Parenthesis Ornament", '('), ('﴾', "Ornate Left Parenthesis", '('), - ('(', "Fullwidth Left Parenthesis", '('), + + (')', "Fullwidth Right Parenthesis", ')'), ('❩', "Medium Right Parenthesis Ornament", ')'), ('﴿', "Ornate Right Parenthesis", ')'), - (')', "Fullwidth Right Parenthesis", ')'), + ('[', "Fullwidth Left Square Bracket", '['), ('❲', "Light Left Tortoise Shell Bracket Ornament", '['), ('「', "Left Corner Bracket", '['), @@ -147,6 +207,7 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[ ('〖', "Left White Lenticular Bracket", '['), ('〘', "Left White Tortoise Shell Bracket", '['), ('〚', "Left White Square Bracket", '['), + (']', "Fullwidth Right Square Bracket", ']'), ('❳', "Light Right Tortoise Shell Bracket Ornament", ']'), ('」', "Right Corner Bracket", ']'), @@ -156,11 +217,20 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[ ('〗', "Right White Lenticular Bracket", ']'), ('〙', "Right White Tortoise Shell Bracket", ']'), ('〛', "Right White Square Bracket", ']'), + ('❴', "Medium Left Curly Bracket Ornament", '{'), + ('𝄔', "Musical Symbol Brace", '{'), + ('{', "Fullwidth Left Curly Bracket", '{'), + ('❵', "Medium Right Curly Bracket Ornament", '}'), + ('}', "Fullwidth Right Curly Bracket", '}'), + ('⁎', "Low Asterisk", '*'), ('٭', "Arabic Five Pointed Star", '*'), ('∗', "Asterisk Operator", '*'), + ('𐌟', "Old Italic Letter Ess", '*'), + ('*', "Fullwidth Asterisk", '*'), + ('᜵', "Philippine Single Punctuation", '/'), ('⁁', "Caret Insertion Point", '/'), ('∕', "Division Slash", '/'), @@ -168,37 +238,73 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[ ('╱', "Box Drawings Light Diagonal Upper Right To Lower Left", '/'), ('⟋', "Mathematical Rising Diagonal", '/'), ('⧸', "Big Solidus", '/'), - ('㇓', "Cjk Stroke Sp", '/'), + ('𝈺', "Greek Instrumental Notation Symbol-47", '/'), + ('㇓', "CJK Stroke Sp", '/'), ('〳', "Vertical Kana Repeat Mark Upper Half", '/'), - ('丿', "Cjk Unified Ideograph-4E3F", '/'), + ('Ⳇ', "Coptic Capital Letter Old Coptic Esh", '/'), + ('ノ', "Katakana Letter No", '/'), + ('丿', "CJK Unified Ideograph-4E3F", '/'), ('⼃', "Kangxi Radical Slash", '/'), + ('/', "Fullwidth Solidus", '/'), + ('\', "Fullwidth Reverse Solidus", '\\'), ('﹨', "Small Reverse Solidus", '\\'), ('∖', "Set Minus", '\\'), ('⟍', "Mathematical Falling Diagonal", '\\'), ('⧵', "Reverse Solidus Operator", '\\'), ('⧹', "Big Reverse Solidus", '\\'), + ('⧹', "Greek Vocal Notation Symbol-16", '\\'), + ('⧹', "Greek Instrumental Symbol-48", '\\'), + ('㇔', "CJK Stroke D", '\\'), + ('丶', "CJK Unified Ideograph-4E36", '\\'), + ('⼂', "Kangxi Radical Dot", '\\'), ('、', "Ideographic Comma", '\\'), ('ヽ', "Katakana Iteration Mark", '\\'), - ('㇔', "Cjk Stroke D", '\\'), - ('丶', "Cjk Unified Ideograph-4E36", '\\'), - ('⼂', "Kangxi Radical Dot", '\\'), + ('ꝸ', "Latin Small Letter Um", '&'), + ('&', "Fullwidth Ampersand", '&'), + + ('᛭', "Runic Cros Punctuation", '+'), + ('➕', "Heavy Plus Sign", '+'), + ('𐊛', "Lycian Letter H", '+'), ('﬩', "Hebrew Letter Alternative Plus Sign", '+'), + ('+', "Fullwidth Plus Sign", '+'), + ('‹', "Single Left-Pointing Angle Quotation Mark", '<'), ('❮', "Heavy Left-Pointing Angle Quotation Mark Ornament", '<'), ('˂', "Modifier Letter Left Arrowhead", '<'), + ('𝈶', "Greek Instrumental Symbol-40", '<'), + ('ᐸ', "Canadian Syllabics Pa", '<'), + ('ᚲ', "Runic Letter Kauna", '<'), + ('❬', "Medium Left-Pointing Angle Bracket Ornament", '<'), + ('⟨', "Mathematical Left Angle Bracket", '<'), + ('〈', "Left-Pointing Angle Bracket", '<'), ('〈', "Left Angle Bracket", '<'), + ('㇛', "CJK Stroke Pd", '<'), + ('く', "Hiragana Letter Ku", '<'), + ('𡿨', "CJK Unified Ideograph-21FE8", '<'), ('《', "Left Double Angle Bracket", '<'), + ('<', "Fullwidth Less-Than Sign", '<'), + + ('᐀', "Canadian Syllabics Hyphen", '='), + ('⹀', "Double Hyphen", '='), + ('゠', "Katakana-Hiragana Double Hyphen", '='), ('꓿', "Lisu Punctuation Full Stop", '='), + ('=', "Fullwidth Equals Sign", '='), + ('›', "Single Right-Pointing Angle Quotation Mark", '>'), ('❯', "Heavy Right-Pointing Angle Quotation Mark Ornament", '>'), ('˃', "Modifier Letter Right Arrowhead", '>'), + ('𝈷', "Greek Instrumental Symbol-42", '>'), + ('ᐳ', "Canadian Syllabics Po", '>'), + ('𖼿', "Miao Letter Archaic Zza", '>'), + ('❭', "Medium Right-Pointing Angle Bracket Ornament", '>'), + ('⟩', "Mathematical Right Angle Bracket", '>'), + ('〉', "Right-Pointing Angle Bracket", '>'), ('〉', "Right Angle Bracket", '>'), ('》', "Right Double Angle Bracket", '>'), - ('Ⲻ', "Coptic Capital Letter Dialect-P Ni", '-'), - ('Ɂ', "Latin Capital Letter Glottal Stop", '?'), - ('Ⳇ', "Coptic Capital Letter Old Coptic Esh", '/'), ]; + ('>', "Fullwidth Greater-Than Sign", '>'), ]; + const ASCII_ARRAY: &'static [(char, &'static str)] = &[ (' ', "Space"), From 5e29bb91b0865bdc54864d0491fa6324aafb6fad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malo=20Jaffr=C3=A9?= Date: Sun, 6 Aug 2017 18:34:36 +0200 Subject: [PATCH 23/56] Fix typo in unicode_chars.rs --- src/libsyntax/parse/lexer/unicode_chars.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs index cc38021b7aa1..85df4eee9134 100644 --- a/src/libsyntax/parse/lexer/unicode_chars.rs +++ b/src/libsyntax/parse/lexer/unicode_chars.rs @@ -39,7 +39,7 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[ ('﹍', "Dashed Low Line", '_'), ('﹎', "Centreline Low Line", '_'), ('﹏', "Wavy Low Line", '_'), - ('_', "Fullwidth Low Line", '-'), + ('_', "Fullwidth Low Line", '_'), ('‐', "Hyphen", '-'), ('‑', "Non-Breaking Hyphen", '-'), From d1fffd8685748357a079711dde1ae22560c6cd70 Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Sun, 6 Aug 2017 18:25:31 +0100 Subject: [PATCH 24/56] Added closure test case. --- src/test/compile-fail/lint-unused-mut-variables.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/test/compile-fail/lint-unused-mut-variables.rs b/src/test/compile-fail/lint-unused-mut-variables.rs index 49ba9421d65f..26d00755da33 100644 --- a/src/test/compile-fail/lint-unused-mut-variables.rs +++ b/src/test/compile-fail/lint-unused-mut-variables.rs @@ -54,6 +54,12 @@ fn main() { let mut b = (&mut a,); *b.0 = 4; //~^ ERROR: variable does not need to be mutable + let mut x = &mut 1; //~ ERROR: variable does not need to be mutable + let mut f = || { + *x += 1; + }; + f(); + fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { &mut arg[..] //~^ ERROR: variable does not need to be mutable } From 26dd77f4f3ec4adfa22cb6dfd25fafc5b55b7466 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 5 Aug 2017 23:54:48 +0200 Subject: [PATCH 25/56] Fix hoedown error in rustdoc --- src/librustdoc/html/markdown.rs | 15 +++++++-------- src/test/rustdoc/nul-error.rs | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 src/test/rustdoc/nul-error.rs diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 03da451fd9a0..cd58ff3109f5 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -32,7 +32,6 @@ use std::ascii::AsciiExt; use std::cell::RefCell; use std::collections::{HashMap, VecDeque}; use std::default::Default; -use std::ffi::CString; use std::fmt::{self, Write}; use std::str; use syntax::feature_gate::UnstableFeatures; @@ -531,6 +530,7 @@ extern { fn hoedown_buffer_new(unit: libc::size_t) -> *mut hoedown_buffer; fn hoedown_buffer_puts(b: *mut hoedown_buffer, c: *const libc::c_char); fn hoedown_buffer_free(b: *mut hoedown_buffer); + fn hoedown_buffer_put(b: *mut hoedown_buffer, c: *const libc::c_char, len: libc::size_t); } impl hoedown_buffer { @@ -620,8 +620,7 @@ pub fn render(w: &mut fmt::Formatter, Some("rust-example-rendered"), None, playground_button.as_ref().map(String::as_str))); - let output = CString::new(s).unwrap(); - hoedown_buffer_puts(ob, output.as_ptr()); + hoedown_buffer_put(ob, s.as_ptr() as *const libc::c_char, s.len()); }) } } @@ -681,8 +680,7 @@ pub fn render(w: &mut fmt::Formatter, {sec}{}", s, lvl = level, id = id, sec = sec); - let text = CString::new(text).unwrap(); - unsafe { hoedown_buffer_puts(ob, text.as_ptr()) } + unsafe { hoedown_buffer_put(ob, text.as_ptr() as *const libc::c_char, text.len()); } } extern fn codespan( @@ -699,9 +697,10 @@ pub fn render(w: &mut fmt::Formatter, collapse_whitespace(s) }; - let content = format!("{}", Escape(&content)); - let element = CString::new(content).unwrap(); - unsafe { hoedown_buffer_puts(ob, element.as_ptr()); } + let content = format!("{}", Escape(&content)).replace("\0", "\\0"); + unsafe { + hoedown_buffer_put(ob, content.as_ptr() as *const libc::c_char, content.len()); + } // Return anything except 0, which would mean "also print the code span verbatim". 1 } diff --git a/src/test/rustdoc/nul-error.rs b/src/test/rustdoc/nul-error.rs new file mode 100644 index 000000000000..f20d19d0e59c --- /dev/null +++ b/src/test/rustdoc/nul-error.rs @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// build-aux-docs +// ignore-cross-compile + +#![crate_name = "foo"] + +// @has foo/fn.foo.html '//code' '0' +#[doc = "Attempted to pass a string containing `\0`"] +pub fn foo() {} From 380b81853ed64b58f8cccd66c2d30726387df9ab Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 7 Aug 2017 07:25:59 +0000 Subject: [PATCH 26/56] Narrow or widen the vector element without changing the vector size --- src/etc/platform-intrinsics/generator.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/etc/platform-intrinsics/generator.py b/src/etc/platform-intrinsics/generator.py index e3c08bb35e07..e9cf71c32fe9 100644 --- a/src/etc/platform-intrinsics/generator.py +++ b/src/etc/platform-intrinsics/generator.py @@ -19,7 +19,7 @@ import itertools SPEC = re.compile( r'^(?:(?PV)|(?P[iusfIUSF])(?:\((?P\d+)-(?P\d+)\)|' r'(?P\d+)(:?/(?P\d+))?)' - r'|(?P\d+))(?P\.\d+)?(?P[vShdnwusfDMC]*)(?Px\d+)?' + r'|(?P\d+))(?P\.\d+)?(?P[vShdnwusfDMCNW]*)(?Px\d+)?' r'(?:(?PPm|Pc)(?P/.*)?|(?P->.*))?$' ) @@ -246,6 +246,12 @@ class Vector(Type): return Vector(self._elem, self._length // 2) elif spec == 'd': return Vector(self._elem, self._length * 2) + elif spec == 'N': + elem = self._elem.__class__(self._elem.bitwidth() // 2) + return Vector(elem, self._length * 2) + elif spec == 'W': + elem = self._elem.__class__(self._elem.bitwidth() * 2) + return Vector(elem, self._length // 2) elif spec.startswith('x'): new_bitwidth = int(spec[1:]) return Vector(self._elem, new_bitwidth // self._elem.bitwidth()) @@ -714,6 +720,8 @@ def parse_args(): - 'd': double the length of the vector (u32x2 -> u32x4) - 'n': narrow the element of the vector (u32x4 -> u16x4) - 'w': widen the element of the vector (u16x4 -> u32x4) + - 'N': half the length of the vector element (u32x4 -> u16x8) + - 'W': double the length of the vector element (u16x8 -> u32x4) - 'u': force a number (vector or scalar) to be unsigned int (f32x4 -> u32x4) - 's': force a number (vector or scalar) to be signed int (u32x4 -> i32x4) - 'f': force a number (vector or scalar) to be float (u32x4 -> f32x4) From 9c6ab920ab8136074cb24c3b708e718584b34b9d Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 4 Aug 2017 00:19:58 +0000 Subject: [PATCH 27/56] Add support for Vector Multiply Even on PowerPC --- src/etc/platform-intrinsics/powerpc.json | 7 +++++++ src/librustc_platform_intrinsics/powerpc.rs | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/etc/platform-intrinsics/powerpc.json b/src/etc/platform-intrinsics/powerpc.json index 7dde0fd4d087..fe33908ec39f 100644 --- a/src/etc/platform-intrinsics/powerpc.json +++ b/src/etc/platform-intrinsics/powerpc.json @@ -100,6 +100,13 @@ "llvm": "vaddcuw", "ret": "u32", "args": ["0", "0"] + }, + { + "intrinsic": "mule{1.kind}{1.data_type_short}", + "width": [128], + "llvm": "vmule{0.kind}{1.data_type_short}", + "ret": "i(16-32)", + "args": ["0N", "1"] } ] } diff --git a/src/librustc_platform_intrinsics/powerpc.rs b/src/librustc_platform_intrinsics/powerpc.rs index 0ec6a7e66d85..4251d4ab25ae 100644 --- a/src/librustc_platform_intrinsics/powerpc.rs +++ b/src/librustc_platform_intrinsics/powerpc.rs @@ -212,6 +212,26 @@ pub fn find(name: &str) -> Option { output: &::U32x4, definition: Named("llvm.ppc.altivec.vaddcuw") }, + "_vec_mulesb" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, + output: &::I16x8, + definition: Named("llvm.ppc.altivec.vmulesb") + }, + "_vec_muleub" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, + output: &::U16x8, + definition: Named("llvm.ppc.altivec.vmuleub") + }, + "_vec_mulesh" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, + output: &::I32x4, + definition: Named("llvm.ppc.altivec.vmulesh") + }, + "_vec_muleuh" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, + output: &::U32x4, + definition: Named("llvm.ppc.altivec.vmuleuh") + }, _ => return None, }) } From 19c4bdb4e12ada030e64a731a3b588867c58025e Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 4 Aug 2017 00:19:58 +0000 Subject: [PATCH 28/56] Add support for Vector Multiply Odd on PowerPC --- src/etc/platform-intrinsics/powerpc.json | 7 +++++++ src/librustc_platform_intrinsics/powerpc.rs | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/etc/platform-intrinsics/powerpc.json b/src/etc/platform-intrinsics/powerpc.json index fe33908ec39f..abccc8747e46 100644 --- a/src/etc/platform-intrinsics/powerpc.json +++ b/src/etc/platform-intrinsics/powerpc.json @@ -107,6 +107,13 @@ "llvm": "vmule{0.kind}{1.data_type_short}", "ret": "i(16-32)", "args": ["0N", "1"] + }, + { + "intrinsic": "mulo{1.kind}{1.data_type_short}", + "width": [128], + "llvm": "vmulo{0.kind}{1.data_type_short}", + "ret": "i(16-32)", + "args": ["0N", "1"] } ] } diff --git a/src/librustc_platform_intrinsics/powerpc.rs b/src/librustc_platform_intrinsics/powerpc.rs index 4251d4ab25ae..d9c00a8e6270 100644 --- a/src/librustc_platform_intrinsics/powerpc.rs +++ b/src/librustc_platform_intrinsics/powerpc.rs @@ -232,6 +232,26 @@ pub fn find(name: &str) -> Option { output: &::U32x4, definition: Named("llvm.ppc.altivec.vmuleuh") }, + "_vec_mulosb" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, + output: &::I16x8, + definition: Named("llvm.ppc.altivec.vmulosb") + }, + "_vec_muloub" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, + output: &::U16x8, + definition: Named("llvm.ppc.altivec.vmuloub") + }, + "_vec_mulosh" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, + output: &::I32x4, + definition: Named("llvm.ppc.altivec.vmulosh") + }, + "_vec_mulouh" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, + output: &::U32x4, + definition: Named("llvm.ppc.altivec.vmulouh") + }, _ => return None, }) } From 8b78ea5b84cd528bce291bd8196bc83cd96c9819 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 4 Aug 2017 00:19:58 +0000 Subject: [PATCH 29/56] Add support for Vector Average on PowerPC --- src/etc/platform-intrinsics/powerpc.json | 7 +++++ src/librustc_platform_intrinsics/powerpc.rs | 30 +++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/etc/platform-intrinsics/powerpc.json b/src/etc/platform-intrinsics/powerpc.json index abccc8747e46..c70791be030f 100644 --- a/src/etc/platform-intrinsics/powerpc.json +++ b/src/etc/platform-intrinsics/powerpc.json @@ -114,6 +114,13 @@ "llvm": "vmulo{0.kind}{1.data_type_short}", "ret": "i(16-32)", "args": ["0N", "1"] + }, + { + "intrinsic": "avg{0.kind}{0.data_type_short}", + "width": [128], + "llvm": "vavg{0.kind}{0.data_type_short}", + "ret": "i(8-32)", + "args": ["0", "0"] } ] } diff --git a/src/librustc_platform_intrinsics/powerpc.rs b/src/librustc_platform_intrinsics/powerpc.rs index d9c00a8e6270..b38369665f89 100644 --- a/src/librustc_platform_intrinsics/powerpc.rs +++ b/src/librustc_platform_intrinsics/powerpc.rs @@ -252,6 +252,36 @@ pub fn find(name: &str) -> Option { output: &::U32x4, definition: Named("llvm.ppc.altivec.vmulouh") }, + "_vec_avgsb" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, + output: &::I8x16, + definition: Named("llvm.ppc.altivec.vavgsb") + }, + "_vec_avgub" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, + output: &::U8x16, + definition: Named("llvm.ppc.altivec.vavgub") + }, + "_vec_avgsh" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, + output: &::I16x8, + definition: Named("llvm.ppc.altivec.vavgsh") + }, + "_vec_avguh" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, + output: &::U16x8, + definition: Named("llvm.ppc.altivec.vavguh") + }, + "_vec_avgsw" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, + output: &::I32x4, + definition: Named("llvm.ppc.altivec.vavgsw") + }, + "_vec_avguw" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, + output: &::U32x4, + definition: Named("llvm.ppc.altivec.vavguw") + }, _ => return None, }) } From ff0513c6973523b65f59b8b508ca85dc2944c988 Mon Sep 17 00:00:00 2001 From: Kornel Date: Mon, 7 Aug 2017 18:23:15 +0100 Subject: [PATCH 30/56] Hint correct extern constant syntax --- src/libsyntax/parse/parser.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ca362ec93683..c34317e649d8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6007,7 +6007,9 @@ impl<'a> Parser<'a> { } if self.check_keyword(keywords::Const) { - return Err(self.span_fatal(self.span, "extern items cannot be `const`")); + let mut err = self.span_fatal(self.span, "extern items cannot be `const`"); + err.help("use `static` instead"); + return Err(err); } // FIXME #5668: this will occur for a macro invocation: From d0916c57ca480cb1a7672c02cda00ec008a50c3c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 7 Aug 2017 20:17:45 +0200 Subject: [PATCH 31/56] Remove \0 printing --- src/librustdoc/html/markdown.rs | 10 +++++----- src/test/rustdoc/nul-error.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index cd58ff3109f5..35d0f0a116d0 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -530,7 +530,7 @@ extern { fn hoedown_buffer_new(unit: libc::size_t) -> *mut hoedown_buffer; fn hoedown_buffer_puts(b: *mut hoedown_buffer, c: *const libc::c_char); fn hoedown_buffer_free(b: *mut hoedown_buffer); - fn hoedown_buffer_put(b: *mut hoedown_buffer, c: *const libc::c_char, len: libc::size_t); + fn hoedown_buffer_put(b: *mut hoedown_buffer, c: *const u8, len: libc::size_t); } impl hoedown_buffer { @@ -620,7 +620,7 @@ pub fn render(w: &mut fmt::Formatter, Some("rust-example-rendered"), None, playground_button.as_ref().map(String::as_str))); - hoedown_buffer_put(ob, s.as_ptr() as *const libc::c_char, s.len()); + hoedown_buffer_put(ob, s.as_ptr(), s.len()); }) } } @@ -680,7 +680,7 @@ pub fn render(w: &mut fmt::Formatter, {sec}{}", s, lvl = level, id = id, sec = sec); - unsafe { hoedown_buffer_put(ob, text.as_ptr() as *const libc::c_char, text.len()); } + unsafe { hoedown_buffer_put(ob, text.as_ptr(), text.len()); } } extern fn codespan( @@ -697,9 +697,9 @@ pub fn render(w: &mut fmt::Formatter, collapse_whitespace(s) }; - let content = format!("{}", Escape(&content)).replace("\0", "\\0"); + let content = format!("{}", Escape(&content)); unsafe { - hoedown_buffer_put(ob, content.as_ptr() as *const libc::c_char, content.len()); + hoedown_buffer_put(ob, content.as_ptr(), content.len()); } // Return anything except 0, which would mean "also print the code span verbatim". 1 diff --git a/src/test/rustdoc/nul-error.rs b/src/test/rustdoc/nul-error.rs index f20d19d0e59c..2c9d07f190d2 100644 --- a/src/test/rustdoc/nul-error.rs +++ b/src/test/rustdoc/nul-error.rs @@ -13,6 +13,6 @@ #![crate_name = "foo"] -// @has foo/fn.foo.html '//code' '0' +// @has foo/fn.foo.html '//code' '' #[doc = "Attempted to pass a string containing `\0`"] pub fn foo() {} From 9c5397d033842af39185be4608bea2b25beb75ce Mon Sep 17 00:00:00 2001 From: Danek Duvall Date: Mon, 7 Aug 2017 15:42:30 -0700 Subject: [PATCH 32/56] Update libc to 0.2.29 Cargo pulls in libc from crates.io for a number of dependencies, but 0.2.27 is too old to work properly with Solaris. In particular, it needs the change to make Solaris' PTHREAD_PROCESS_PRIVATE a 16-bit integer. --- src/Cargo.lock | 72 +++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 398b23061ead..38897993d435 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -75,7 +75,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -88,7 +88,7 @@ dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -99,7 +99,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -135,7 +135,7 @@ dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -200,7 +200,7 @@ dependencies = [ "ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -234,7 +234,7 @@ dependencies = [ "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -302,7 +302,7 @@ dependencies = [ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -341,7 +341,7 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", "socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -354,7 +354,7 @@ version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -456,7 +456,7 @@ name = "filetime" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -472,7 +472,7 @@ name = "flate2" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -496,7 +496,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -521,7 +521,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -662,7 +662,7 @@ name = "jobserver" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -714,7 +714,7 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.27" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -725,7 +725,7 @@ dependencies = [ "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -738,7 +738,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -750,7 +750,7 @@ version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -771,7 +771,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -801,7 +801,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -809,7 +809,7 @@ name = "memchr" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -818,7 +818,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -843,7 +843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -919,7 +919,7 @@ name = "num_cpus" version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -935,7 +935,7 @@ dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -950,7 +950,7 @@ version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1072,7 +1072,7 @@ name = "rand" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1604,7 +1604,7 @@ dependencies = [ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1709,7 +1709,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1828,7 +1828,7 @@ name = "syntex_errors" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1850,7 +1850,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1865,7 +1865,7 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1896,7 +1896,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1931,7 +1931,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2120,7 +2120,7 @@ name = "xattr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2189,7 +2189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d52e477b23bf52cd3ca0f9fc6c5d14be954eec97e3b9cdfbd962d911bd533caf" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" -"checksum libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)" = "719aa0af4c241fa71d396ffdfe584aa758f08f35b4680ec3f03ecc2c3fe69b76" +"checksum libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "8a014d9226c2cc402676fbe9ea2e15dd5222cd1dd57f576b5b283178c944a264" "checksum libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "df18a822100352d9863b302faf6f8f25c0e77f0e60feb40e5dbe1238b7f13b1d" "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75" "checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8" From 8d8876c0b75ea6ee5ee5eac6abf78fb92c9ac9f3 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 8 Aug 2017 16:32:47 +1200 Subject: [PATCH 33/56] driver: factor out a helper and make another helper public --- src/librustc_driver/lib.rs | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 4c337993468e..b4b7446f753d 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -518,7 +518,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { -> CompileController<'a> { let mut control = CompileController::basic(); - control.keep_ast = sess.opts.debugging_opts.keep_ast || save_analysis(sess); + control.keep_ast = sess.opts.debugging_opts.keep_ast; if let Some((ppm, opt_uii)) = parse_pretty(sess, matches) { if ppm.needs_ast_map(&opt_uii) { @@ -574,19 +574,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { } if save_analysis(sess) { - control.after_analysis.callback = box |state| { - time(state.session.time_passes(), "save analysis", || { - save::process_crate(state.tcx.unwrap(), - state.expanded_crate.unwrap(), - state.analysis.unwrap(), - state.crate_name.unwrap(), - None, - DumpHandler::new(state.out_dir, - state.crate_name.unwrap())) - }); - }; - control.after_analysis.run_callback_on_error = true; - control.make_glob_map = resolve::MakeGlobMap::Yes; + enable_save_analysis(&mut control); } if sess.print_fuel_crate.is_some() { @@ -603,6 +591,23 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { } } +pub fn enable_save_analysis(control: &mut CompileController) { + control.keep_ast = true; + control.after_analysis.callback = box |state| { + time(state.session.time_passes(), "save analysis", || { + save::process_crate(state.tcx.unwrap(), + state.expanded_crate.unwrap(), + state.analysis.unwrap(), + state.crate_name.unwrap(), + None, + DumpHandler::new(state.out_dir, + state.crate_name.unwrap())) + }); + }; + control.after_analysis.run_callback_on_error = true; + control.make_glob_map = resolve::MakeGlobMap::Yes; +} + fn save_analysis(sess: &Session) -> bool { sess.opts.debugging_opts.save_analysis } @@ -1215,7 +1220,7 @@ pub fn diagnostics_registry() -> errors::registry::Registry { Registry::new(&all_errors) } -fn get_args() -> Vec { +pub fn get_args() -> Vec { env::args_os().enumerate() .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| { early_error(ErrorOutputType::default(), From c982d6a6eb231db2230126d92525aca17ff75917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Tue, 8 Aug 2017 06:37:31 +0200 Subject: [PATCH 34/56] pass rustc_libdir instead of sysroot_libdir() for running rustdoc from rustbuild suggestion from Mark-Simulacrum --- src/bootstrap/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 811c7df5d997..d7f795e40553 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -427,7 +427,7 @@ impl<'a> Builder<'a> { } else { self.sysroot(compiler) }) - .env("RUSTC_LIBDIR", self.sysroot_libdir(compiler, self.build.build)) + .env("RUSTC_LIBDIR", self.rustc_libdir(compiler)) .env("CFG_RELEASE_CHANNEL", &self.build.config.channel) .env("RUSTDOC_REAL", self.rustdoc(compiler)); cmd From 15e8b0fd3decd6c3ceca1986a422ac5a8fc640f2 Mon Sep 17 00:00:00 2001 From: kennytm Date: Tue, 8 Aug 2017 16:17:33 +0800 Subject: [PATCH 35/56] Fix covered-switch-default warnings in PassWrapper (See #39063 for explanation) --- src/rustllvm/PassWrapper.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index bca0881c08c5..ba0c4fbe173b 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -278,10 +278,12 @@ static Optional fromRust(LLVMRustRelocMode RustReloc) { return Reloc::RWPI; case LLVMRustRelocMode::ROPIRWPI: return Reloc::ROPI_RWPI; -#endif +#else default: - llvm_unreachable("Bad RelocModel."); + break; +#endif } + llvm_unreachable("Bad RelocModel."); } #if LLVM_RUSTLLVM From 453ad8122c975dc82f6090f0c755d38932ccefc5 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Mon, 7 Aug 2017 20:50:34 +0000 Subject: [PATCH 36/56] make `for_all_relevant_impls` O(1) again A change in #41911 had made `for_all_relevant_impls` do a linear scan over all impls, instead of using an HashMap. Use an HashMap again to avoid quadratic blowup when there is a large number of structs with impls. I think this fixes #43141 completely, but I want better measurements in order to be sure. As a perf patch, please don't roll this up. --- src/librustc/traits/error_reporting.rs | 9 +- src/librustc/traits/select.rs | 6 +- src/librustc/traits/specialize/mod.rs | 3 +- src/librustc/ty/maps.rs | 15 +- src/librustc/ty/mod.rs | 2 - src/librustc/ty/trait_def.rs | 168 +++++++------------ src/librustc/ty/util.rs | 2 +- src/librustc_lint/builtin.rs | 3 +- src/librustc_mir/transform/qualify_consts.rs | 3 +- src/librustc_typeck/check/method/probe.rs | 4 +- 10 files changed, 77 insertions(+), 138 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index c02d1394f6bb..65c0a9f8ffd5 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -278,8 +278,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let mut self_match_impls = vec![]; let mut fuzzy_match_impls = vec![]; - self.tcx.trait_def(trait_ref.def_id) - .for_each_relevant_impl(self.tcx, trait_self_ty, |def_id| { + self.tcx.for_each_relevant_impl( + trait_ref.def_id, trait_self_ty, |def_id| { let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id); let impl_trait_ref = tcx .impl_trait_ref(def_id) @@ -396,10 +396,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { trait_ref.skip_binder().self_ty(), true); let mut impl_candidates = Vec::new(); - let trait_def = self.tcx.trait_def(trait_ref.def_id()); match simp { - Some(simp) => trait_def.for_each_impl(self.tcx, |def_id| { + Some(simp) => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| { let imp = self.tcx.impl_trait_ref(def_id).unwrap(); let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), @@ -411,7 +410,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } impl_candidates.push(imp); }), - None => trait_def.for_each_impl(self.tcx, |def_id| { + None => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| { impl_candidates.push( self.tcx.impl_trait_ref(def_id).unwrap()); }) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index c690bebed8c0..c2feb54c4dbe 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1576,10 +1576,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { debug!("assemble_candidates_from_impls(obligation={:?})", obligation); - let def = self.tcx().trait_def(obligation.predicate.def_id()); - - def.for_each_relevant_impl( - self.tcx(), + self.tcx().for_each_relevant_impl( + obligation.predicate.def_id(), obligation.predicate.0.trait_ref.self_ty(), |impl_def_id| { self.probe(|this, snapshot| { /* [1] */ diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 46e551029665..7c916e162a4f 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -300,7 +300,8 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx -> Rc { let mut sg = specialization_graph::Graph::new(); - let mut trait_impls: Vec = tcx.trait_impls_of(trait_id).iter().collect(); + let mut trait_impls = Vec::new(); + tcx.for_each_impl(trait_id, |impl_did| trait_impls.push(impl_did)); // The coherence checking implementation seems to rely on impls being // iterated over (roughly) in definition order, so we are sorting by diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index a2e335c00b26..5d25ce2fbeca 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -470,12 +470,6 @@ impl<'tcx> QueryDescription for queries::trait_impls_of<'tcx> { } } -impl<'tcx> QueryDescription for queries::relevant_trait_impls_for<'tcx> { - fn describe(tcx: TyCtxt, (def_id, ty): (DefId, SimplifiedType)) -> String { - format!("relevant impls for: `({}, {:?})`", tcx.item_path_str(def_id), ty) - } -} - impl<'tcx> QueryDescription for queries::is_object_safe<'tcx> { fn describe(tcx: TyCtxt, def_id: DefId) -> String { format!("determine object safety of trait `{}`", tcx.item_path_str(def_id)) @@ -966,10 +960,7 @@ define_maps! { <'tcx> [] const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool, [] is_mir_available: IsMirAvailable(DefId) -> bool, - [] trait_impls_of: TraitImpls(DefId) -> ty::trait_def::TraitImpls, - // Note that TraitDef::for_each_relevant_impl() will do type simplication for you. - [] relevant_trait_impls_for: relevant_trait_impls_for((DefId, SimplifiedType)) - -> ty::trait_def::TraitImpls, + [] trait_impls_of: TraitImpls(DefId) -> Rc, [] specialization_graph_of: SpecializationGraph(DefId) -> Rc, [] is_object_safe: ObjectSafety(DefId) -> bool, @@ -1049,10 +1040,6 @@ fn crate_variances<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { DepConstructor::CrateVariances } -fn relevant_trait_impls_for<'tcx>((def_id, t): (DefId, SimplifiedType)) -> DepConstructor<'tcx> { - DepConstructor::RelevantTraitImpls(def_id, t) -} - fn is_copy_dep_node<'tcx>(_: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> { DepConstructor::IsCopy } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index eef0bcc37535..7f4aedb5f14b 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2507,7 +2507,6 @@ pub fn provide(providers: &mut ty::maps::Providers) { param_env, trait_of_item, trait_impls_of: trait_def::trait_impls_of_provider, - relevant_trait_impls_for: trait_def::relevant_trait_impls_provider, ..*providers }; } @@ -2517,7 +2516,6 @@ pub fn provide_extern(providers: &mut ty::maps::Providers) { adt_sized_constraint, adt_dtorck_constraint, trait_impls_of: trait_def::trait_impls_of_provider, - relevant_trait_impls_for: trait_def::relevant_trait_impls_provider, param_env, ..*providers }; diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index ef6bce8a3d9d..9990472c6b4c 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -8,14 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use hir; use hir::def_id::DefId; use hir::map::DefPathHash; use traits::specialization_graph; use ty::fast_reject; use ty::fold::TypeFoldable; use ty::{Ty, TyCtxt}; + +use rustc_data_structures::fx::FxHashMap; + use std::rc::Rc; -use hir; /// A trait's definition with type information. pub struct TraitDef { @@ -36,60 +39,12 @@ pub struct TraitDef { pub def_path_hash: DefPathHash, } -// We don't store the list of impls in a flat list because each cached list of -// `relevant_impls_for` we would then duplicate all blanket impls. By keeping -// blanket and non-blanket impls separate, we can share the list of blanket -// impls. -#[derive(Clone)] pub struct TraitImpls { - blanket_impls: Rc>, - non_blanket_impls: Rc>, + blanket_impls: Vec, + /// Impls indexed by their simplified self-type, for fast lookup. + non_blanket_impls: FxHashMap>, } -impl TraitImpls { - pub fn iter(&self) -> TraitImplsIter { - TraitImplsIter { - blanket_impls: self.blanket_impls.clone(), - non_blanket_impls: self.non_blanket_impls.clone(), - index: 0 - } - } -} - -#[derive(Clone)] -pub struct TraitImplsIter { - blanket_impls: Rc>, - non_blanket_impls: Rc>, - index: usize, -} - -impl Iterator for TraitImplsIter { - type Item = DefId; - - fn next(&mut self) -> Option { - if self.index < self.blanket_impls.len() { - let bi_index = self.index; - self.index += 1; - Some(self.blanket_impls[bi_index]) - } else { - let nbi_index = self.index - self.blanket_impls.len(); - if nbi_index < self.non_blanket_impls.len() { - self.index += 1; - Some(self.non_blanket_impls[nbi_index]) - } else { - None - } - } - } - - fn size_hint(&self) -> (usize, Option) { - let items_left = (self.blanket_impls.len() + self.non_blanket_impls.len()) - self.index; - (items_left, Some(items_left)) - } -} - -impl ExactSizeIterator for TraitImplsIter {} - impl<'a, 'gcx, 'tcx> TraitDef { pub fn new(def_id: DefId, unsafety: hir::Unsafety, @@ -111,20 +66,36 @@ impl<'a, 'gcx, 'tcx> TraitDef { -> specialization_graph::Ancestors { specialization_graph::ancestors(tcx, self.def_id, of_impl) } +} - pub fn for_each_impl(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, mut f: F) { - for impl_def_id in tcx.trait_impls_of(self.def_id).iter() { +impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { + pub fn for_each_impl(self, def_id: DefId, mut f: F) { + let impls = self.trait_impls_of(def_id); + + for &impl_def_id in impls.blanket_impls.iter() { f(impl_def_id); } + + for v in impls.non_blanket_impls.values() { + for &impl_def_id in v { + f(impl_def_id); + } + } } /// Iterate over every impl that could possibly match the /// self-type `self_ty`. - pub fn for_each_relevant_impl(&self, - tcx: TyCtxt<'a, 'gcx, 'tcx>, + pub fn for_each_relevant_impl(self, + def_id: DefId, self_ty: Ty<'tcx>, mut f: F) { + let impls = self.trait_impls_of(def_id); + + for &impl_def_id in impls.blanket_impls.iter() { + f(impl_def_id); + } + // simplify_type(.., false) basically replaces type parameters and // projections with infer-variables. This is, of course, done on // the impl trait-ref when it is instantiated, but not on the @@ -137,15 +108,31 @@ impl<'a, 'gcx, 'tcx> TraitDef { // replace `S` with anything - this impl of course can't be // selected, and as there are hundreds of similar impls, // considering them would significantly harm performance. - let relevant_impls = if let Some(simplified_self_ty) = - fast_reject::simplify_type(tcx, self_ty, true) { - tcx.relevant_trait_impls_for((self.def_id, simplified_self_ty)) - } else { - tcx.trait_impls_of(self.def_id) - }; - for impl_def_id in relevant_impls.iter() { - f(impl_def_id); + // This depends on the set of all impls for the trait. That is + // unfortunate. When we get red-green recompilation, we would like + // to have a way of knowing whether the set of relevant impls + // changed. The most naive + // way would be to compute the Vec of relevant impls and see whether + // it differs between compilations. That shouldn't be too slow by + // itself - we do quite a bit of work for each relevant impl anyway. + // + // If we want to be faster, we could have separate queries for + // blanket and non-blanket impls, and compare them separately. + // + // I think we'll cross that bridge when we get to it. + if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) { + if let Some(impls) = impls.non_blanket_impls.get(&simp) { + for &impl_def_id in impls { + f(impl_def_id); + } + } + } else { + for v in impls.non_blanket_impls.values() { + for &impl_def_id in v { + f(impl_def_id); + } + } } } } @@ -153,7 +140,7 @@ impl<'a, 'gcx, 'tcx> TraitDef { // Query provider for `trait_impls_of`. pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_id: DefId) - -> TraitImpls { + -> Rc { let remote_impls = if trait_id.is_local() { // Traits defined in the current crate can't have impls in upstream // crates, so we don't bother querying the cstore. @@ -163,7 +150,7 @@ pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; let mut blanket_impls = Vec::new(); - let mut non_blanket_impls = Vec::new(); + let mut non_blanket_impls = FxHashMap(); let local_impls = tcx.hir .trait_impls(trait_id) @@ -176,47 +163,20 @@ pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, continue } - if fast_reject::simplify_type(tcx, impl_self_ty, false).is_some() { - non_blanket_impls.push(impl_def_id); + if let Some(simplified_self_ty) = + fast_reject::simplify_type(tcx, impl_self_ty, false) + { + non_blanket_impls + .entry(simplified_self_ty) + .or_insert(vec![]) + .push(impl_def_id); } else { blanket_impls.push(impl_def_id); } } - TraitImpls { - blanket_impls: Rc::new(blanket_impls), - non_blanket_impls: Rc::new(non_blanket_impls), - } -} - -// Query provider for `relevant_trait_impls_for`. -pub(super) fn relevant_trait_impls_provider<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - (trait_id, self_ty): (DefId, fast_reject::SimplifiedType)) - -> TraitImpls -{ - let all_trait_impls = tcx.trait_impls_of(trait_id); - - let relevant: Vec = all_trait_impls - .non_blanket_impls - .iter() - .cloned() - .filter(|&impl_def_id| { - let impl_self_ty = tcx.type_of(impl_def_id); - let impl_simple_self_ty = fast_reject::simplify_type(tcx, - impl_self_ty, - false).unwrap(); - impl_simple_self_ty == self_ty - }) - .collect(); - - if all_trait_impls.non_blanket_impls.len() == relevant.len() { - // If we didn't filter anything out, re-use the existing vec. - all_trait_impls - } else { - TraitImpls { - blanket_impls: all_trait_impls.blanket_impls.clone(), - non_blanket_impls: Rc::new(relevant), - } - } + Rc::new(TraitImpls { + blanket_impls: blanket_impls, + non_blanket_impls: non_blanket_impls, + }) } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index df4bbad3859f..d1c738315454 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -422,7 +422,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let mut dtor_did = None; let ty = self.type_of(adt_did); - self.trait_def(drop_trait).for_each_relevant_impl(self, ty, |impl_did| { + self.for_each_relevant_impl(drop_trait, ty, |impl_did| { if let Some(item) = self.associated_items(impl_did).next() { if let Ok(()) = validate(self, impl_did) { dtor_did = Some(item.def_id); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ca30ed4a536e..db27fa874f4e 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -542,9 +542,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations { }; if self.impling_types.is_none() { - let debug_def = cx.tcx.trait_def(debug); let mut impls = NodeSet(); - debug_def.for_each_impl(cx.tcx, |d| { + cx.tcx.for_each_impl(debug, |d| { if let Some(ty_def) = cx.tcx.type_of(d).ty_to_def_id() { if let Some(node_id) = cx.tcx.hir.as_local_node_id(ty_def) { impls.insert(node_id); diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 9d01f8294e4f..8321d9b99ae8 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -244,8 +244,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { let mut span = None; self.tcx - .trait_def(drop_trait_id) - .for_each_relevant_impl(self.tcx, self.mir.return_ty, |impl_did| { + .for_each_relevant_impl(drop_trait_id, self.mir.return_ty, |impl_did| { self.tcx.hir .as_local_node_id(impl_did) .and_then(|impl_node_id| self.tcx.hir.find(impl_node_id)) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 3195b10404d1..881fc7a13709 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -736,10 +736,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { import_id: Option, trait_def_id: DefId, item: ty::AssociatedItem) { - let trait_def = self.tcx.trait_def(trait_def_id); - // FIXME(arielb1): can we use for_each_relevant_impl here? - trait_def.for_each_impl(self.tcx, |impl_def_id| { + self.tcx.for_each_impl(trait_def_id, |impl_def_id| { debug!("assemble_extension_candidates_for_trait_impl: trait_def_id={:?} \ impl_def_id={:?}", trait_def_id, From b6ac9c0d302b361ae1747c496f1bd88f04e556d8 Mon Sep 17 00:00:00 2001 From: est31 Date: Tue, 8 Aug 2017 11:24:30 +0200 Subject: [PATCH 37/56] Avoid calling the column!() macro in panic --- src/libcore/macros.rs | 14 ++++++++++++-- src/libstd/macros.rs | 16 ++++++++++++++-- src/libsyntax_ext/lib.rs | 1 + src/test/run-pass/issue-43057.rs | 23 +++++++++++++++++++++++ 4 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 src/test/run-pass/issue-43057.rs diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 2edf8e1fa886..684b81a27f82 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -8,6 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[macro_export] +// This stability attribute is totally useless. +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(stage0)] +macro_rules! __rust_unstable_column { + () => { + column!() + } +} + /// Entry point of thread panic, for details, see std::macros #[macro_export] #[allow_internal_unstable] @@ -18,7 +28,7 @@ macro_rules! panic { ); ($msg:expr) => ({ static _MSG_FILE_LINE_COL: (&'static str, &'static str, u32, u32) = - ($msg, file!(), line!(), column!()); + ($msg, file!(), line!(), __rust_unstable_column!()); $crate::panicking::panic(&_MSG_FILE_LINE_COL) }); ($fmt:expr, $($arg:tt)*) => ({ @@ -27,7 +37,7 @@ macro_rules! panic { // insufficient, since the user may have // `#[forbid(dead_code)]` and which cannot be overridden. static _MSG_FILE_LINE_COL: (&'static str, u32, u32) = - (file!(), line!(), column!()); + (file!(), line!(), __rust_unstable_column!()); $crate::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_MSG_FILE_LINE_COL) }); } diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 03db1e4f01c6..5e88a46ecc34 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -14,6 +14,16 @@ //! library. Each macro is available for use when linking against the standard //! library. +#[macro_export] +// This stability attribute is totally useless. +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(stage0)] +macro_rules! __rust_unstable_column { + () => { + column!() + } +} + /// The entry point for panic of Rust threads. /// /// This macro is used to inject panic into a Rust thread, causing the thread to @@ -48,7 +58,8 @@ macro_rules! panic { ($msg:expr) => ({ $crate::rt::begin_panic($msg, { // static requires less code at runtime, more constant data - static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), column!()); + static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), + __rust_unstable_column!()); &_FILE_LINE_COL }) }); @@ -58,7 +69,8 @@ macro_rules! panic { // used inside a dead function. Just `#[allow(dead_code)]` is // insufficient, since the user may have // `#[forbid(dead_code)]` and which cannot be overridden. - static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), column!()); + static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), + __rust_unstable_column!()); &_FILE_LINE_COL }) }); diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 8ba07c35b054..558d2e90310f 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -89,6 +89,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, use syntax::ext::source_util::*; register! { line: expand_line, + __rust_unstable_column: expand_column, column: expand_column, file: expand_file, stringify: expand_stringify, diff --git a/src/test/run-pass/issue-43057.rs b/src/test/run-pass/issue-43057.rs new file mode 100644 index 000000000000..152ddfb193fc --- /dev/null +++ b/src/test/run-pass/issue-43057.rs @@ -0,0 +1,23 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(unused)] + +macro_rules! column { + ($i:ident) => { + $i + }; +} + +fn foo() -> ! { + panic!(); +} + +fn main() {} From 3645b0626c89ed098c121ff2215ad3ec50f44836 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Mon, 7 Aug 2017 17:20:19 -0700 Subject: [PATCH 38/56] #[must_use] for functions (RFC 1940) The return value of a function annotated with `must_use`, must be used. This is in the matter of #43302. --- src/librustc_lint/unused.rs | 34 +++++++++++++++++++++-------- src/test/ui/lint/fn_must_use.rs | 33 ++++++++++++++++++++++++++++ src/test/ui/lint/fn_must_use.stderr | 14 ++++++++++++ 3 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/lint/fn_must_use.rs create mode 100644 src/test/ui/lint/fn_must_use.stderr diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index d7d0dc7cb352..ba17df4cdca4 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -145,22 +145,38 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { } let t = cx.tables.expr_ty(&expr); - let warned = match t.sty { - ty::TyTuple(ref tys, _) if tys.is_empty() => return, - ty::TyNever => return, - ty::TyBool => return, - ty::TyAdt(def, _) => check_must_use(cx, def.did, s.span), + let ty_warned = match t.sty { + ty::TyAdt(def, _) => check_must_use(cx, def.did, s.span, ""), _ => false, }; - if !warned { + + let mut fn_warned = false; + let maybe_def = match expr.node { + hir::ExprCall(ref callee, _) => { + match callee.node { + hir::ExprPath(ref qpath) => Some(cx.tables.qpath_def(qpath, callee.id)), + _ => None + } + }, + hir::ExprMethodCall(..) => { + cx.tables.type_dependent_defs.get(&expr.id).cloned() + }, + _ => { None } + }; + if let Some(def) = maybe_def { + let def_id = def.def_id(); + fn_warned = check_must_use(cx, def_id, s.span, "return value of "); + } + + if !(ty_warned || fn_warned) { cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); } - fn check_must_use(cx: &LateContext, def_id: DefId, sp: Span) -> bool { + fn check_must_use(cx: &LateContext, def_id: DefId, sp: Span, describe_path: &str) -> bool { for attr in cx.tcx.get_attrs(def_id).iter() { if attr.check_name("must_use") { - let mut msg = format!("unused `{}` which must be used", - cx.tcx.item_path_str(def_id)); + let mut msg = format!("unused {}`{}` which must be used", + describe_path, cx.tcx.item_path_str(def_id)); // check for #[must_use="..."] if let Some(s) = attr.value_str() { msg.push_str(": "); diff --git a/src/test/ui/lint/fn_must_use.rs b/src/test/ui/lint/fn_must_use.rs new file mode 100644 index 000000000000..ea2197f3fd1a --- /dev/null +++ b/src/test/ui/lint/fn_must_use.rs @@ -0,0 +1,33 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +struct MyStruct { + n: usize +} + +impl MyStruct { + #[must_use] + fn need_to_use_this_method_value(&self) -> usize { + self.n + } +} + +#[must_use="it's important"] +fn need_to_use_this_value() -> bool { + false +} + +fn main() { + need_to_use_this_value(); + + let m = MyStruct { n: 2 }; + m.need_to_use_this_method_value(); +} diff --git a/src/test/ui/lint/fn_must_use.stderr b/src/test/ui/lint/fn_must_use.stderr new file mode 100644 index 000000000000..7057c8e9aaad --- /dev/null +++ b/src/test/ui/lint/fn_must_use.stderr @@ -0,0 +1,14 @@ +warning: unused return value of `need_to_use_this_value` which must be used: it's important + --> $DIR/fn_must_use.rs:29:5 + | +29 | need_to_use_this_value(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: #[warn(unused_must_use)] on by default + +warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used + --> $DIR/fn_must_use.rs:32:5 + | +32 | m.need_to_use_this_method_value(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + From f5ac228b366b96892fb2c950fa1269d437df8360 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Mon, 7 Aug 2017 21:23:58 -0700 Subject: [PATCH 39/56] mark comparison trait methods as #[must_use] Note that this doesn't actually give us warnings on `a == b;` and the like, as some observers may have hoped. This is in the matter of #43302. --- src/libcore/cmp.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index a9f55dc27880..ec6525485f7a 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -110,11 +110,13 @@ use self::Ordering::*; pub trait PartialEq { /// This method tests for `self` and `other` values to be equal, and is used /// by `==`. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn eq(&self, other: &Rhs) -> bool; /// This method tests for `!=`. #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn ne(&self, other: &Rhs) -> bool { !self.eq(other) } } @@ -625,6 +627,7 @@ pub trait PartialOrd: PartialEq { /// let result = std::f64::NAN.partial_cmp(&1.0); /// assert_eq!(result, None); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn partial_cmp(&self, other: &Rhs) -> Option; @@ -640,6 +643,7 @@ pub trait PartialOrd: PartialEq { /// assert_eq!(result, false); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn lt(&self, other: &Rhs) -> bool { match self.partial_cmp(other) { @@ -661,6 +665,7 @@ pub trait PartialOrd: PartialEq { /// assert_eq!(result, true); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn le(&self, other: &Rhs) -> bool { match self.partial_cmp(other) { @@ -681,6 +686,7 @@ pub trait PartialOrd: PartialEq { /// assert_eq!(result, false); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn gt(&self, other: &Rhs) -> bool { match self.partial_cmp(other) { @@ -702,6 +708,7 @@ pub trait PartialOrd: PartialEq { /// assert_eq!(result, true); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn ge(&self, other: &Rhs) -> bool { match self.partial_cmp(other) { From aaa14d1d20f3cc1104bb619f66c78a49762182ff Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 8 Aug 2017 14:12:06 +0200 Subject: [PATCH 40/56] Improve error message when duplicate names for type and trait method --- src/librustc_typeck/check/method/mod.rs | 5 ++-- src/librustc_typeck/check/method/probe.rs | 2 +- src/librustc_typeck/check/method/suggest.rs | 32 ++++++++++++++------- src/librustc_typeck/check/mod.rs | 2 +- src/test/ui/trait-method-private.rs | 30 +++++++++++++++++++ src/test/ui/trait-method-private.stderr | 12 ++++++++ 6 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/trait-method-private.rs create mode 100644 src/test/ui/trait-method-private.stderr diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index dd5b0cdda424..1ccb1e64a98e 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -58,8 +58,9 @@ pub enum MethodError<'tcx> { ClosureAmbiguity(// DefId of fn trait DefId), - // Found an applicable method, but it is not visible. - PrivateMatch(Def), + // Found an applicable method, but it is not visible. The second argument contains a list of + // not-in-scope traits which may work. + PrivateMatch(Def, Vec), // Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have // forgotten to import a trait. diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 3195b10404d1..f771fc11b5a2 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1015,7 +1015,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { }; if let Some(def) = private_candidate { - return Err(MethodError::PrivateMatch(def)); + return Err(MethodError::PrivateMatch(def, out_of_scope_traits)); } Err(MethodError::NoMatch(NoMatchData::new(static_candidates, diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 53da9e19ee0c..56eacc3194d1 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -311,9 +311,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.sess().span_err(span, &msg); } - MethodError::PrivateMatch(def) => { - struct_span_err!(self.tcx.sess, span, E0624, - "{} `{}` is private", def.kind_name(), item_name).emit(); + MethodError::PrivateMatch(def, out_of_scope_traits) => { + let mut err = struct_span_err!(self.tcx.sess, span, E0624, + "{} `{}` is private", def.kind_name(), item_name); + self.suggest_valid_traits(&mut err, out_of_scope_traits); + err.emit(); } MethodError::IllegalSizedBound(candidates) => { @@ -353,13 +355,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err.note(&msg[..]); } - fn suggest_traits_to_import(&self, - err: &mut DiagnosticBuilder, - span: Span, - rcvr_ty: Ty<'tcx>, - item_name: ast::Name, - rcvr_expr: Option<&hir::Expr>, - valid_out_of_scope_traits: Vec) { + fn suggest_valid_traits(&self, + err: &mut DiagnosticBuilder, + valid_out_of_scope_traits: Vec) -> bool { if !valid_out_of_scope_traits.is_empty() { let mut candidates = valid_out_of_scope_traits; candidates.sort(); @@ -379,6 +377,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }); self.suggest_use_candidates(err, msg, candidates); + true + } else { + false + } + } + + fn suggest_traits_to_import(&self, + err: &mut DiagnosticBuilder, + span: Span, + rcvr_ty: Ty<'tcx>, + item_name: ast::Name, + rcvr_expr: Option<&hir::Expr>, + valid_out_of_scope_traits: Vec) { + if self.suggest_valid_traits(err, valid_out_of_scope_traits) { return; } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e53e5e7b08c9..73e8bf305af4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4016,7 +4016,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Ok(def) => def, Err(error) => { let def = match error { - method::MethodError::PrivateMatch(def) => def, + method::MethodError::PrivateMatch(def, _) => def, _ => Def::Err, }; if item_name != keywords::Invalid.name() { diff --git a/src/test/ui/trait-method-private.rs b/src/test/ui/trait-method-private.rs new file mode 100644 index 000000000000..5c1bd668ac64 --- /dev/null +++ b/src/test/ui/trait-method-private.rs @@ -0,0 +1,30 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod inner { + pub trait Bar { + fn method(&self); + } + + pub struct Foo; + + impl Foo { + fn method(&self) {} + } + + impl Bar for Foo { + fn method(&self) {} + } +} + +fn main() { + let foo = inner::Foo; + foo.method(); +} diff --git a/src/test/ui/trait-method-private.stderr b/src/test/ui/trait-method-private.stderr new file mode 100644 index 000000000000..c7a7b689edc5 --- /dev/null +++ b/src/test/ui/trait-method-private.stderr @@ -0,0 +1,12 @@ +error[E0624]: method `method` is private + --> $DIR/trait-method-private.rs:29:9 + | +29 | foo.method(); + | ^^^^^^ + | + = help: items from traits can only be used if the trait is in scope + = note: the following trait is implemented but not in scope, perhaps add a `use` for it: + candidate #1: `use inner::Bar;` + +error: aborting due to previous error + From ec0ca3a7c64c08dab44eb30f11b2b0870c4583ea Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 8 Aug 2017 21:25:39 +0200 Subject: [PATCH 41/56] Remove all usage of hoedown_buffer_puts --- src/librustdoc/html/markdown.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 35d0f0a116d0..735c9d8af7a8 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -528,7 +528,6 @@ extern { fn hoedown_document_free(md: *mut hoedown_document); fn hoedown_buffer_new(unit: libc::size_t) -> *mut hoedown_buffer; - fn hoedown_buffer_puts(b: *mut hoedown_buffer, c: *const libc::c_char); fn hoedown_buffer_free(b: *mut hoedown_buffer); fn hoedown_buffer_put(b: *mut hoedown_buffer, c: *const u8, len: libc::size_t); } @@ -629,7 +628,7 @@ pub fn render(w: &mut fmt::Formatter, level: libc::c_int, data: *const hoedown_renderer_data, _: libc::size_t) { // hoedown does this, we may as well too - unsafe { hoedown_buffer_puts(ob, "\n\0".as_ptr() as *const _); } + unsafe { hoedown_buffer_put(ob, "\n".as_ptr(), 1); } // Extract the text provided let s = if text.is_null() { From 702750c538c56905f58b60520dd1e9814ba03a8e Mon Sep 17 00:00:00 2001 From: Stefan Schindler Date: Tue, 1 Aug 2017 16:25:36 +0200 Subject: [PATCH 42/56] Use explicit wrapping_add to prevent potential unexpected behavior on debug builds --- src/libstd/sync/barrier.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index a7b01e49d2bb..273c7c1c54a2 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -152,7 +152,7 @@ impl Barrier { BarrierWaitResult(false) } else { lock.count = 0; - lock.generation_id += 1; + lock.generation_id = lock.generation_id.wrapping_add(1); self.cvar.notify_all(); BarrierWaitResult(true) } From 3fcdb8ba723a46a1c036c99c6a503f39a0667156 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 8 Aug 2017 18:20:36 -0700 Subject: [PATCH 43/56] Only refer to return type when it matches --- src/librustc/hir/map/mod.rs | 2 +- src/librustc_typeck/check/mod.rs | 27 +++++++++++++++---- .../block-must-not-have-result-res.stderr | 2 +- src/test/ui/block-result/issue-13624.stderr | 2 +- src/test/ui/block-result/issue-22645.stderr | 2 +- src/test/ui/block-result/issue-5500.stderr | 2 +- src/test/ui/impl-trait/equality.stderr | 3 --- 7 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 5cec697c6bbd..3fdd9c34f46d 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -664,7 +664,7 @@ impl<'hir> Map<'hir> { match *node { NodeExpr(ref expr) => { match expr.node { - ExprWhile(..) | ExprLoop(..) | ExprIf(..) => true, + ExprWhile(..) | ExprLoop(..) => true, _ => false, } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 73aa5ac5a0f0..7c8eb77380f0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -95,7 +95,7 @@ use rustc::middle::region::CodeExtent; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode}; use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue}; -use rustc::ty::{self, Ty, TyCtxt, Visibility}; +use rustc::ty::{self, Ty, TyCtxt, Visibility, TypeVariants}; use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; use rustc::ty::maps::Providers; @@ -4302,7 +4302,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, can_suggest: bool) { - // Only suggest changing the return type for methods that // haven't set a return type at all (and aren't `fn main()` or an impl). match (&fn_decl.output, found.is_suggestable(), can_suggest) { @@ -4316,13 +4315,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } (&hir::FunctionRetTy::DefaultReturn(span), _, _) => { // `fn main()` must return `()`, do not suggest changing return type - err.span_label(span, "expected `()` because of default return type"); + err.span_label(span, "expected () because of default return type"); } (&hir::FunctionRetTy::Return(ref ty), _, _) => { // Only point to return type if the expected type is the return type, as if they // are not, the expectation must have been caused by something else. - err.span_label(ty.span, - format!("expected `{}` because of return type", expected)); + debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.node); + let sp = ty.span; + let ty = AstConv::ast_ty_to_ty(self, ty); + debug!("suggest_missing_return_type: return type sty {:?}", ty.sty); + debug!("suggest_missing_return_type: expected type sty {:?}", ty.sty); + if ty.sty == expected.sty { + let quote = if let TypeVariants::TyTuple(ref slice, _) = expected.sty { + if slice.len() == 0 { // don't use backtics for () + "" + } else { + "`" + } + } else { + "`" + }; + err.span_label(sp, format!("expected {}{}{} because of return type", + quote, + expected, + quote)); + } } } } diff --git a/src/test/ui/block-result/block-must-not-have-result-res.stderr b/src/test/ui/block-result/block-must-not-have-result-res.stderr index 20c7dc416f3b..6432375fe709 100644 --- a/src/test/ui/block-result/block-must-not-have-result-res.stderr +++ b/src/test/ui/block-result/block-must-not-have-result-res.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/block-must-not-have-result-res.rs:15:9 | 14 | fn drop(&mut self) { - | - expected `()` because of default return type + | - expected () because of default return type 15 | true //~ ERROR mismatched types | ^^^^ expected (), found bool | diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr index cd8c28cd2cfa..8fe4a5125741 100644 --- a/src/test/ui/block-result/issue-13624.stderr +++ b/src/test/ui/block-result/issue-13624.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-13624.rs:17:5 | 16 | pub fn get_enum_struct_variant() -> () { - | -- expected `()` because of return type + | -- expected () because of return type 17 | Enum::EnumStructVariant { x: 1, y: 2, z: 3 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` | diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr index c6113ae0c9f6..ad39e38cab63 100644 --- a/src/test/ui/block-result/issue-22645.stderr +++ b/src/test/ui/block-result/issue-22645.stderr @@ -12,7 +12,7 @@ error[E0308]: mismatched types --> $DIR/issue-22645.rs:25:3 | 23 | fn main() { - | - expected `()` because of default return type + | - expected () because of default return type 24 | let b = Bob + 3.5; 25 | b + 3 //~ ERROR E0277 | ^^^^^ expected (), found struct `Bob` diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr index 29dbd5a8cf59..944391c1719c 100644 --- a/src/test/ui/block-result/issue-5500.stderr +++ b/src/test/ui/block-result/issue-5500.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-5500.rs:12:5 | 11 | fn main() { - | - expected `()` because of default return type + | - expected () because of default return type 12 | &panic!() | ^^^^^^^^^ expected (), found reference | diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 791ce4860d0c..3fc08a0900fb 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -1,9 +1,6 @@ error[E0308]: mismatched types --> $DIR/equality.rs:25:5 | -21 | fn two(x: bool) -> impl Foo { - | -------- expected `_` because of return type -... 25 | 0_u32 | ^^^^^ expected i32, found u32 | From 78d1442808fa318c782e7f8249dab27126254930 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Mon, 7 Aug 2017 10:38:16 -0700 Subject: [PATCH 44/56] extended information for E0571 break with value in non-`loop` loop --- src/librustc_passes/diagnostics.rs | 35 +++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs index 907a258a12dc..1bfa5943ee90 100644 --- a/src/librustc_passes/diagnostics.rs +++ b/src/librustc_passes/diagnostics.rs @@ -223,6 +223,40 @@ To fix this, add a label specifying which loop is being broken out of: ``` 'foo: while break 'foo {} ``` +"##, + +E0571: r##" +A `break` statement with an argument appeared in a non-`loop` loop. + +Example of erroneous code: + +```compile_fail,E0571 +# let mut i = 1; +# fn satisfied(n: usize) -> bool { n % 23 == 0 } +let result = while true { + if satisfied(i) { + break 2*i; // error: `break` with value from a `while` loop + } + i += 1; +}; +``` + +The `break` statement can take an argument (which will be the value of the loop +expression if the `break` statement is executed) in `loop` loops, but not +`for`, `while`, or `while let` loops. + +Make sure `break value;` statements only occur in `loop` loops: + +``` +# let mut i = 1; +# fn satisfied(n: usize) -> bool { n % 23 == 0 } +let result = loop { // ok! + if satisfied(i) { + break 2*i; + } + i += 1; +}; +``` "## } @@ -230,5 +264,4 @@ register_diagnostics! { E0226, // only a single explicit lifetime bound is permitted E0472, // asm! is unsupported on this target E0561, // patterns aren't allowed in function pointer types - E0571, // `break` with a value in a non-`loop`-loop } From 6fa140b86994d216b2bd425f69048a3a6c3067fc Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Mon, 7 Aug 2017 10:57:08 -0700 Subject: [PATCH 45/56] extended information for E0554 feature attributes only work on nightlies It's more pleasing to use the inner-attribute syntax (`#!` rather than `#`) in the error message, as that is how `feature` attributes in particular will be declared (as they apply to the entire crate). --- src/libsyntax/diagnostic_list.rs | 16 +++++++++++++++- src/libsyntax/feature_gate.rs | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index 6598ecb94448..33dbc02d8691 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -162,6 +162,21 @@ For more information about the cfg attribute, read: https://doc.rust-lang.org/reference.html#conditional-compilation "##, +E0554: r##" +Feature attributes are only allowed on the nightly release channel. Stable or +beta compilers will not comply. + +Example of erroneous code (on a stable compiler): + +```ignore (depends on release channel) +#![feature(non_ascii_idents)] // error: #![feature] may not be used on the + // stable release channel +``` + +If you need the feature, make sure to use a nightly release of the compiler +(but be warned that the feature may be removed or altered in the future). +"##, + E0558: r##" The `export_name` attribute was malformed. @@ -301,7 +316,6 @@ register_diagnostics! { E0550, // multiple deprecated attributes E0551, // incorrect meta item E0552, // unrecognized representation hint - E0554, // #[feature] may not be used on the [] release channel E0555, // malformed feature attribute, expected #![feature(...)] E0556, // malformed feature, expected just one word E0557, // feature has been removed diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index e8de8cf41c97..aeb574bc3af3 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1602,7 +1602,7 @@ fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, if attr.check_name("feature") { let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)"); span_err!(span_handler, attr.span, E0554, - "#[feature] may not be used on the {} release channel", + "#![feature] may not be used on the {} release channel", release_channel); } } From 93bc599d65d0f946944b3c97be3556658cc01eab Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Mon, 7 Aug 2017 15:09:53 -0700 Subject: [PATCH 46/56] extended information for E0552 unrecognized representation hint --- src/libsyntax/diagnostic_list.rs | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index 33dbc02d8691..7c6db17a352e 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -162,6 +162,36 @@ For more information about the cfg attribute, read: https://doc.rust-lang.org/reference.html#conditional-compilation "##, +E0552: r##" +A unrecognized representation attribute was used. + +Erroneous code example: + +```compile_fail,E0552 +#[repr(D)] // error: unrecognized representation hint +struct MyStruct { + my_field: usize +} +``` + +You can use a `repr` attribute to tell the compiler how you want a struct or +enum to be laid out in memory. + +Make sure you're using one of the supported options: + +``` +#[repr(C)] // ok! +struct MyStruct { + my_field: usize +} +``` + +For more information about specifying representations, see the ["Alternative +Representations" section] of the Rustonomicon. + +["Alternative Representations" section]: https://doc.rust-lang.org/nomicon/other-reprs.html +"##, + E0554: r##" Feature attributes are only allowed on the nightly release channel. Stable or beta compilers will not comply. @@ -315,7 +345,6 @@ register_diagnostics! { E0549, // rustc_deprecated attribute must be paired with either stable or unstable attribute E0550, // multiple deprecated attributes E0551, // incorrect meta item - E0552, // unrecognized representation hint E0555, // malformed feature attribute, expected #![feature(...)] E0556, // malformed feature, expected just one word E0557, // feature has been removed From 116bf07c3224301a234a3a9f4b9c137013f6164f Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Mon, 7 Aug 2017 15:37:13 -0700 Subject: [PATCH 47/56] extended information for E0557 feature has been removed --- src/libsyntax/diagnostic_list.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index 7c6db17a352e..2ea3fe51d30b 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -207,6 +207,18 @@ If you need the feature, make sure to use a nightly release of the compiler (but be warned that the feature may be removed or altered in the future). "##, +E0557: r##" +A feature attribute named a feature that has been removed. + +Erroneous code example: + +```compile_fail,E0557 +#![feature(managed_boxes)] // error: feature has been removed +``` + +Delete the offending feature attribute. +"##, + E0558: r##" The `export_name` attribute was malformed. @@ -347,7 +359,6 @@ register_diagnostics! { E0551, // incorrect meta item E0555, // malformed feature attribute, expected #![feature(...)] E0556, // malformed feature, expected just one word - E0557, // feature has been removed E0584, // file for module `..` found at both .. and .. E0589, // invalid `repr(align)` attribute } From 3b0ff0d7e2055eed4acdc125f21f6b4a58e69a45 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Wed, 9 Aug 2017 09:31:10 +0000 Subject: [PATCH 48/56] Fix errors on Windows --- src/libstd/sys/windows/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 7f3291cf3047..f2487c1b0bd0 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -768,8 +768,8 @@ fn symlink_junction_inner(target: &Path, junction: &Path) -> io::Result<()> { unsafe { let mut data = [0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - let mut db = data.as_mut_ptr() - as *mut c::REPARSE_MOUNTPOINT_DATA_BUFFER; + let db = data.as_mut_ptr() + as *mut c::REPARSE_MOUNTPOINT_DATA_BUFFER; let buf = &mut (*db).ReparseTarget as *mut _; let mut i = 0; // FIXME: this conversion is very hacky From 89087183fc98e672bb21487c50cc39d1b6af35f1 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Wed, 9 Aug 2017 16:19:54 +0100 Subject: [PATCH 49/56] Update RELEASES.md --- RELEASES.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index e62e218c6c35..7bf0bcab6406 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -93,9 +93,9 @@ Cargo ----- - [Cargo API token location moved from `~/.cargo/config` to `~/cargo/credentials`.][cargo/3978] -- [Cargo will now build multiple `main.rs` binaries in different - directories.][cargo/4214] ie. Having `src/server/main.rs` and - `src/client/main.rs` generates `target/debug/server` and `target/debug/client` +- [Cargo will now build `main.rs` binaries that are in sub-directories of + `src/bin`.][cargo/4214] ie. Having `src/bin/server/main.rs` and + `src/bin/client/main.rs` generates `target/debug/server` and `target/debug/client` - [You can now specify version of a binary when installed through `cargo install` using `--vers`.][cargo/4229] - [Added `--no-fail-fast` flag to cargo to run all benchmarks regardless of From 0374e6aab7ef60b523872556ae4aca33c59fbfc9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 26 Jul 2017 21:51:09 -0700 Subject: [PATCH 50/56] rustc: Rearchitect lints to be emitted more eagerly In preparation for incremental compilation this commit refactors the lint handling infrastructure in the compiler to be more "eager" and overall more incremental-friendly. Many passes of the compiler can emit lints at various points but before this commit all lints were buffered in a table to be emitted at the very end of compilation. This commit changes these lints to be emitted immediately during compilation using pre-calculated lint level-related data structures. Linting today is split into two phases, one set of "early" lints run on the `syntax::ast` and a "late" set of lints run on the HIR. This commit moves the "early" lints to running as late as possible in compilation, just before HIR lowering. This notably means that we're catching resolve-related lints just before HIR lowering. The early linting remains a pass very similar to how it was before, maintaining context of the current lint level as it walks the tree. Post-HIR, however, linting is structured as a method on the `TyCtxt` which transitively executes a query to calculate lint levels. Each request to lint on a `TyCtxt` will query the entire crate's 'lint level data structure' and then go from there about whether the lint should be emitted or not. The query depends on the entire HIR crate but should be very quick to calculate (just a quick walk of the HIR) and the red-green system should notice that the lint level data structure rarely changes, and should hopefully preserve incrementality. Overall this resulted in a pretty big change to the test suite now that lints are emitted much earlier in compilation (on-demand vs only at the end). This in turn necessitated the addition of many `#![allow(warnings)]` directives throughout the compile-fail test suite and a number of updates to the UI test suite. --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/ich/impls_ty.rs | 2 - src/librustc/lint/context.rs | 779 +++++------------- src/librustc/lint/levels.rs | 343 ++++++++ src/librustc/lint/mod.rs | 236 +++++- src/librustc/lint/table.rs | 71 -- src/librustc/middle/dead.rs | 52 +- src/librustc/middle/effect.rs | 10 +- src/librustc/middle/liveness.rs | 18 +- src/librustc/middle/stability.rs | 14 +- src/librustc/session/mod.rs | 29 +- src/librustc/traits/error_reporting.rs | 27 +- src/librustc/traits/select.rs | 10 +- src/librustc/ty/context.rs | 61 +- src/librustc/ty/maps.rs | 13 + src/librustc_const_eval/check_match.rs | 26 +- src/librustc_driver/driver.rs | 22 +- src/librustc_lint/builtin.rs | 15 +- src/librustc_passes/ast_validation.rs | 11 +- src/librustc_passes/consts.rs | 20 +- src/librustc_privacy/lib.rs | 20 +- src/librustc_resolve/check_unused.rs | 13 +- src/librustc_resolve/lib.rs | 13 +- src/librustc_resolve/macros.rs | 4 +- src/librustc_resolve/resolve_imports.rs | 6 +- src/librustc_typeck/astconv.rs | 6 +- src/librustc_typeck/check/cast.rs | 24 +- src/librustc_typeck/check/mod.rs | 8 +- src/librustc_typeck/check/writeback.rs | 5 - src/librustc_typeck/check_unused.rs | 2 +- src/librustc_typeck/collect.rs | 6 +- .../proc-macro/attributes-included.rs | 1 + src/test/compile-fail/E0010.rs | 1 + src/test/compile-fail/E0394.rs | 2 + src/test/compile-fail/bad-lint-cap2.rs | 1 + src/test/compile-fail/bad-lint-cap3.rs | 1 + .../check-static-values-constraints.rs | 1 + .../compile-fail/const-eval-overflow-2.rs | 2 +- .../compile-fail/const-match-pattern-arm.rs | 2 + .../compile-fail/feature-gate-dropck-ugeh.rs | 1 - src/test/compile-fail/issue-14227.rs | 2 + src/test/compile-fail/issue-16538.rs | 2 + src/test/compile-fail/issue-17450.rs | 2 +- .../compile-fail/issue-17718-const-naming.rs | 1 + .../compile-fail/issue-17718-references.rs | 2 + src/test/compile-fail/issue-18937.rs | 2 +- src/test/compile-fail/issue-28075.rs | 2 +- src/test/compile-fail/issue-28113.rs | 2 + src/test/compile-fail/issue-28324.rs | 2 + src/test/compile-fail/issue-30730.rs | 1 + src/test/compile-fail/issue-37515.rs | 1 + src/test/compile-fail/issue-7364.rs | 1 + src/test/compile-fail/lint-removed-allow.rs | 3 +- src/test/compile-fail/lint-removed-cmdline.rs | 2 + src/test/compile-fail/lint-renamed-allow.rs | 3 +- .../compile-fail/lint-stability-deprecated.rs | 214 ++--- src/test/compile-fail/lint-type-overflow2.rs | 20 +- .../compile-fail/lint-uppercase-variables.rs | 1 + src/test/compile-fail/liveness-unused.rs | 1 + .../compile-fail/never-assign-dead-code.rs | 14 +- .../compile-fail/private-inferred-type.rs | 1 + .../compile-fail/private-type-in-interface.rs | 1 + .../compile-fail/static-mut-not-constant.rs | 3 +- .../compile-fail/unreachable-try-pattern.rs | 15 +- .../ui-fulldeps/lint-plugin-cmdline-allow.rs | 1 + .../lint-plugin-cmdline-allow.stderr | 11 +- src/test/ui/check_match/issue-43253.rs | 3 +- src/test/ui/check_match/issue-43253.stderr | 18 +- .../proj-outlives-region.stderr | 2 +- .../ui/compare-method/region-unrelated.stderr | 2 +- src/test/ui/lint/fn_must_use.rs | 1 + src/test/ui/lint/fn_must_use.stderr | 14 +- src/test/ui/lint/outer-forbid.rs | 8 +- src/test/ui/lint/outer-forbid.stderr | 24 +- src/test/ui/path-lookahead.rs | 2 + src/test/ui/path-lookahead.stderr | 27 +- src/test/ui/reachable/expr_unary.stderr | 14 +- src/test/ui/span/issue-24690.rs | 9 +- src/test/ui/span/issue-24690.stderr | 53 +- src/test/ui/span/macro-span-replacement.rs | 2 + .../ui/span/macro-span-replacement.stderr | 13 +- src/test/ui/span/multispan-import-lint.rs | 2 + src/test/ui/span/multispan-import-lint.stderr | 11 +- src/tools/compiletest/src/runtest.rs | 18 +- 84 files changed, 1345 insertions(+), 1067 deletions(-) create mode 100644 src/librustc/lint/levels.rs delete mode 100644 src/librustc/lint/table.rs diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index c6f9cb2fcead..5b609f192e1c 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -521,6 +521,7 @@ define_dep_nodes!( <'tcx> [] IsAllocator(DefId), [] IsPanicRuntime(DefId), [] ExternCrate(DefId), + [] LintLevels, ); trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug { diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 5269ec90def5..cd64348044fc 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -625,8 +625,6 @@ for ty::TypeckTables<'tcx> { ref cast_kinds, - // FIXME(#41184): This is still ignored at the moment. - lints: _, ref used_trait_imports, tainted_by_errors, ref free_region_map, diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index d67bca1df302..6ee06dc0a816 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -23,29 +23,25 @@ //! previous lint state is pushed onto a stack and the ast is then recursed //! upon. As the ast is traversed, this keeps track of the current lint level //! for all lint attributes. + use self::TargetLint::*; +use rustc_back::slice; +use lint::{EarlyLintPassObject, LateLintPassObject}; +use lint::{Level, Lint, LintId, LintPass, LintBuffer}; +use lint::levels::{LintLevelSets, LintLevelsBuilder}; use middle::privacy::AccessLevels; +use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; +use session::{config, early_error, Session}; use traits::Reveal; use ty::{self, TyCtxt}; -use session::{config, early_error, Session}; -use lint::{Level, LevelSource, Lint, LintId, LintPass, LintSource}; -use lint::{EarlyLintPassObject, LateLintPassObject}; -use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid}; -use lint::builtin; -use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use util::nodemap::FxHashMap; -use std::cmp; use std::default::Default as StdDefault; -use std::mem; -use std::fmt; use std::cell::{Ref, RefCell}; -use syntax::attr; use syntax::ast; -use syntax::symbol::Symbol; use syntax_pos::{MultiSpan, Span}; -use errors::{self, Diagnostic, DiagnosticBuilder}; +use errors::DiagnosticBuilder; use hir; use hir::def_id::LOCAL_CRATE; use hir::intravisit as hir_visit; @@ -69,9 +65,6 @@ pub struct LintStore { /// Lints indexed by name. by_name: FxHashMap, - /// Current levels of each lint, and where they were set. - levels: LintLevels, - /// Map of registered lint groups to what lints they expand to. The bool /// is true if the lint group was added by a plugin. lint_groups: FxHashMap<&'static str, (Vec, bool)>, @@ -81,78 +74,23 @@ pub struct LintStore { future_incompatible: FxHashMap, } - -#[derive(Default)] -struct LintLevels { - /// Current levels of each lint, and where they were set. - levels: FxHashMap, - - /// Maximum level a lint can be - lint_cap: Option, -} - - pub struct LintSession<'a, PassObject> { /// Reference to the store of registered lints. lints: Ref<'a, LintStore>, - /// The current lint levels. - levels: LintLevels, - - /// When recursing into an attributed node of the ast which modifies lint - /// levels, this stack keeps track of the previous lint levels of whatever - /// was modified. - stack: Vec<(LintId, LevelSource)>, - /// Trait objects for each lint pass. passes: Option>, } -/// When you call `add_lint` on the session, you wind up storing one -/// of these, which records a "potential lint" at a particular point. -#[derive(PartialEq, RustcEncodable, RustcDecodable)] -pub struct EarlyLint { - /// what lint is this? (e.g., `dead_code`) - pub id: LintId, - - /// the main message - pub diagnostic: Diagnostic, -} - -impl fmt::Debug for EarlyLint { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("EarlyLint") - .field("id", &self.id) - .field("span", &self.diagnostic.span) - .field("diagnostic", &self.diagnostic) - .finish() - } -} - -pub trait IntoEarlyLint { - fn into_early_lint(self, id: LintId) -> EarlyLint; -} - -impl<'a, S: Into> IntoEarlyLint for (S, &'a str) { - fn into_early_lint(self, id: LintId) -> EarlyLint { - let (span, msg) = self; - let mut diagnostic = Diagnostic::new(errors::Level::Warning, msg); - diagnostic.set_span(span); - EarlyLint { - id, - diagnostic, - } - } -} - -impl IntoEarlyLint for Diagnostic { - fn into_early_lint(self, id: LintId) -> EarlyLint { - EarlyLint { - id, - diagnostic: self, - } - } +/// Lints that are buffered up early on in the `Session` before the +/// `LintLevels` is calculated +#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] +pub struct BufferedEarlyLint { + pub lint_id: LintId, + pub ast_id: ast::NodeId, + pub span: MultiSpan, + pub msg: String, } /// Extra information for a future incompatibility lint. See the call @@ -176,11 +114,20 @@ enum TargetLint { Removed(String), } -enum FindLintError { +pub enum FindLintError { NotFound, Removed, } +pub enum CheckLintNameResult<'a> { + Ok(&'a [LintId]), + // Lint doesn't exist + NoLint, + // The lint is either renamed or removed. This is the warning + // message. + Warning(String), +} + impl LintStore { pub fn new() -> LintStore { LintStore { @@ -188,7 +135,6 @@ impl LintStore { early_passes: Some(vec![]), late_passes: Some(vec![]), by_name: FxHashMap(), - levels: LintLevels::default(), future_incompatible: FxHashMap(), lint_groups: FxHashMap(), } @@ -241,8 +187,6 @@ impl LintStore { (Some(sess), true) => sess.err(&msg[..]), } } - - self.levels.set(id, (lint.default_level, Default)); } } @@ -291,96 +235,93 @@ impl LintStore { self.by_name.insert(name.into(), Removed(reason.into())); } - fn find_lint(&self, lint_name: &str) -> Result { + pub fn find_lints(&self, lint_name: &str) -> Result, FindLintError> { match self.by_name.get(lint_name) { - Some(&Id(lint_id)) => Ok(lint_id), + Some(&Id(lint_id)) => Ok(vec![lint_id]), Some(&Renamed(_, lint_id)) => { - Ok(lint_id) + Ok(vec![lint_id]) }, Some(&Removed(_)) => { Err(FindLintError::Removed) }, - None => Err(FindLintError::NotFound) - } - } - - pub fn process_command_line(&mut self, sess: &Session) { - for &(ref lint_name, level) in &sess.opts.lint_opts { - check_lint_name_cmdline(sess, self, - &lint_name[..], level); - - let lint_flag_val = Symbol::intern(&lint_name); - match self.find_lint(&lint_name[..]) { - Ok(lint_id) => self.levels.set(lint_id, (level, CommandLine(lint_flag_val))), - Err(FindLintError::Removed) => { } - Err(_) => { - match self.lint_groups.iter().map(|(&x, pair)| (x, pair.0.clone())) - .collect::>>() - .get(&lint_name[..]) { - Some(v) => { - for lint_id in v { - self.levels.set(*lint_id, (level, CommandLine(lint_flag_val))); - } - } - None => { - // The lint or lint group doesn't exist. - // This is an error, but it was handled - // by check_lint_name_cmdline. - } - } + None => { + match self.lint_groups.get(lint_name) { + Some(v) => Ok(v.0.clone()), + None => Err(FindLintError::Removed) } } } - - self.levels.set_lint_cap(sess.opts.lint_cap); - } -} - - -impl LintLevels { - fn get_source(&self, lint: LintId) -> LevelSource { - match self.levels.get(&lint) { - Some(&s) => s, - None => (Allow, Default), - } } - fn set(&mut self, lint: LintId, mut lvlsrc: LevelSource) { - if let Some(cap) = self.lint_cap { - lvlsrc.0 = cmp::min(lvlsrc.0, cap); - } - if lvlsrc.0 == Allow { - self.levels.remove(&lint); - } else { - self.levels.insert(lint, lvlsrc); - } - } - - fn set_lint_cap(&mut self, lint_cap: Option) { - self.lint_cap = lint_cap; - if let Some(cap) = lint_cap { - for (_, level) in &mut self.levels { - level.0 = cmp::min(level.0, cap); + // Checks the validity of lint names derived from the command line + pub fn check_lint_name_cmdline(&self, + sess: &Session, + lint_name: &str, + level: Level) { + let db = match self.check_lint_name(lint_name) { + CheckLintNameResult::Ok(_) => None, + CheckLintNameResult::Warning(ref msg) => { + Some(sess.struct_warn(msg)) + }, + CheckLintNameResult::NoLint => { + Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name)) } + }; + + if let Some(mut db) = db { + let msg = format!("requested on the command line with `{} {}`", + match level { + Level::Allow => "-A", + Level::Warn => "-W", + Level::Deny => "-D", + Level::Forbid => "-F", + }, + lint_name); + db.note(&msg); + db.emit(); + } + } + + /// Checks the name of a lint for its existence, and whether it was + /// renamed or removed. Generates a DiagnosticBuilder containing a + /// warning for renamed and removed lints. This is over both lint + /// names from attributes and those passed on the command line. Since + /// it emits non-fatal warnings and there are *two* lint passes that + /// inspect attributes, this is only run from the late pass to avoid + /// printing duplicate warnings. + pub fn check_lint_name(&self, lint_name: &str) -> CheckLintNameResult { + match self.by_name.get(lint_name) { + Some(&Renamed(ref new_name, _)) => { + CheckLintNameResult::Warning( + format!("lint {} has been renamed to {}", lint_name, new_name) + ) + }, + Some(&Removed(ref reason)) => { + CheckLintNameResult::Warning( + format!("lint {} has been removed: {}", lint_name, reason) + ) + }, + None => { + match self.lint_groups.get(lint_name) { + None => CheckLintNameResult::NoLint, + Some(ids) => CheckLintNameResult::Ok(&ids.0), + } + } + Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::ref_slice(id)), } } } - impl<'a, PassObject: LintPassObject> LintSession<'a, PassObject> { /// Creates a new `LintSession`, by moving out the `LintStore`'s initial /// lint levels and pass objects. These can be restored using the `restore` /// method. fn new(store: &'a RefCell) -> LintSession<'a, PassObject> { let mut s = store.borrow_mut(); - let levels = mem::replace(&mut s.levels, LintLevels::default()); let passes = PassObject::take_passes(&mut *s); drop(s); LintSession { lints: store.borrow(), - stack: Vec::new(), - levels, passes, } } @@ -389,17 +330,10 @@ impl<'a, PassObject: LintPassObject> LintSession<'a, PassObject> { fn restore(self, store: &RefCell) { drop(self.lints); let mut s = store.borrow_mut(); - s.levels = self.levels; PassObject::restore_passes(&mut *s, self.passes); } - - fn get_source(&self, lint_id: LintId) -> LevelSource { - self.levels.get_source(lint_id) - } } - - /// Context for lint checking after type checking. pub struct LateContext<'a, 'tcx: 'a> { /// Type context we're checking in. @@ -416,6 +350,8 @@ pub struct LateContext<'a, 'tcx: 'a> { /// The store of registered lints and the lint levels. lint_sess: LintSession<'tcx, LateLintPassObject>, + + last_ast_node_with_lint_attrs: ast::NodeId, } /// Context for lint checking of the AST, after expansion, before lowering to @@ -427,8 +363,12 @@ pub struct EarlyContext<'a> { /// The crate being checked. pub krate: &'a ast::Crate, + builder: LintLevelsBuilder<'a>, + /// The store of registered lints and the lint levels. lint_sess: LintSession<'a, EarlyLintPassObject>, + + buffered: LintBuffer, } /// Convenience macro for calling a `LintPass` method on every pass in the context. @@ -442,135 +382,6 @@ macro_rules! run_lints { ($cx:expr, $f:ident, $ps:ident, $($args:expr),*) => ({ $cx.lint_sess_mut().passes = Some(passes); }) } -/// Parse the lint attributes into a vector, with `Err`s for malformed lint -/// attributes. Writing this as an iterator is an enormous mess. -// See also the hir version just below. -pub fn gather_attrs(attrs: &[ast::Attribute]) -> Vec> { - let mut out = vec![]; - for attr in attrs { - let r = gather_attr(attr); - out.extend(r.into_iter()); - } - out -} - -pub fn gather_attr(attr: &ast::Attribute) -> Vec> { - let mut out = vec![]; - - let level = match attr.name().and_then(|name| Level::from_str(&name.as_str())) { - None => return out, - Some(lvl) => lvl, - }; - - let meta = unwrap_or!(attr.meta(), return out); - attr::mark_used(attr); - - let metas = if let Some(metas) = meta.meta_item_list() { - metas - } else { - out.push(Err(meta.span)); - return out; - }; - - for li in metas { - out.push(li.word().map_or(Err(li.span), |word| Ok((word.name(), level, word.span)))); - } - - out -} - -/// Emit a lint as a warning or an error (or not at all) -/// according to `level`. -/// -/// This lives outside of `Context` so it can be used by checks -/// in trans that run after the main lint pass is finished. Most -/// 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, - msg: &str) { - raw_struct_lint(sess, lints, lint, lvlsrc, span, msg).emit(); -} - -pub fn raw_struct_lint<'a, S>(sess: &'a Session, - lints: &LintStore, - lint: &'static Lint, - lvlsrc: LevelSource, - span: Option, - msg: &str) - -> DiagnosticBuilder<'a> - where S: Into -{ - let (level, source) = lvlsrc; - if level == Allow { - return sess.diagnostic().struct_dummy(); - } - - let name = lint.name_lower(); - - // Except for possible note details, forbid behaves like deny. - let effective_level = if level == Forbid { Deny } else { level }; - - let mut err = match (effective_level, span) { - (Warn, Some(sp)) => sess.struct_span_warn(sp, &msg[..]), - (Warn, None) => sess.struct_warn(&msg[..]), - (Deny, Some(sp)) => sess.struct_span_err(sp, &msg[..]), - (Deny, None) => sess.struct_err(&msg[..]), - _ => bug!("impossible level in raw_emit_lint"), - }; - - match source { - Default => { - sess.diag_note_once(&mut err, lint, - &format!("#[{}({})] on by default", level.as_str(), name)); - }, - CommandLine(lint_flag_val) => { - let flag = match level { - Warn => "-W", Deny => "-D", Forbid => "-F", - Allow => bug!("earlier conditional return should handle Allow case") - }; - let hyphen_case_lint_name = name.replace("_", "-"); - if lint_flag_val.as_str() == name { - sess.diag_note_once(&mut err, lint, - &format!("requested on the command line with `{} {}`", - flag, hyphen_case_lint_name)); - } else { - let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); - sess.diag_note_once(&mut err, lint, - &format!("`{} {}` implied by `{} {}`", - flag, hyphen_case_lint_name, flag, - hyphen_case_flag_val)); - } - }, - Node(lint_attr_name, src) => { - sess.diag_span_note_once(&mut err, lint, src, "lint level defined here"); - if lint_attr_name.as_str() != name { - let level_str = level.as_str(); - sess.diag_note_once(&mut err, lint, - &format!("#[{}({})] implied by #[{}({})]", - level_str, name, level_str, lint_attr_name)); - } - } - } - - // Check for future incompatibility lints and issue a stronger warning. - if let Some(future_incompatible) = lints.future_incompatible(LintId::of(lint)) { - let explanation = format!("this was previously accepted by the compiler \ - but is being phased out; \ - it will become a hard error in a future release!"); - let citation = format!("for more information, see {}", - future_incompatible.reference); - err.warn(&explanation); - err.note(&citation); - } - - err -} - - pub trait LintPassObject: Sized { fn take_passes(store: &mut LintStore) -> Option>; fn restore_passes(store: &mut LintStore, passes: Option>); @@ -607,67 +418,24 @@ pub trait LintContext<'tcx>: Sized { fn enter_attrs(&mut self, attrs: &'tcx [ast::Attribute]); fn exit_attrs(&mut self, attrs: &'tcx [ast::Attribute]); - /// Get the level of `lint` at the current position of the lint - /// traversal. - fn current_level(&self, lint: &'static Lint) -> Level { - self.lint_sess().get_source(LintId::of(lint)).0 - } - - fn level_src(&self, lint: &'static Lint) -> Option { - let ref levels = self.lint_sess().levels; - levels.levels.get(&LintId::of(lint)).map(|ls| match ls { - &(Warn, _) => { - let lint_id = LintId::of(builtin::WARNINGS); - let warn_src = levels.get_source(lint_id); - if warn_src.0 != Warn { - warn_src - } else { - *ls - } - } - _ => *ls - }) - } - fn lookup_and_emit>(&self, lint: &'static Lint, span: Option, msg: &str) { - let (level, src) = match self.level_src(lint) { - None => return, - Some(pair) => pair, - }; - - raw_emit_lint(&self.sess(), self.lints(), lint, (level, src), span, msg); + self.lookup(lint, span, msg).emit(); } fn lookup>(&self, lint: &'static Lint, span: Option, msg: &str) - -> DiagnosticBuilder { - let (level, src) = match self.level_src(lint) { - None => return self.sess().diagnostic().struct_dummy(), - Some(pair) => pair, - }; - - raw_struct_lint(&self.sess(), self.lints(), lint, (level, src), span, msg) - } + -> DiagnosticBuilder; /// Emit a lint at the appropriate level, for a particular span. fn span_lint>(&self, lint: &'static Lint, span: S, msg: &str) { self.lookup_and_emit(lint, Some(span), msg); } - fn early_lint(&self, early_lint: &EarlyLint) { - let span = early_lint.diagnostic.span.primary_span().expect("early lint w/o primary span"); - let mut err = self.struct_span_lint(early_lint.id.lint, - span, - &early_lint.diagnostic.message()); - err.copy_details_not_message(&early_lint.diagnostic); - err.emit(); - } - fn struct_span_lint>(&self, lint: &'static Lint, span: S, @@ -680,12 +448,10 @@ pub trait LintContext<'tcx>: Sized { fn span_lint_note(&self, lint: &'static Lint, span: Span, msg: &str, note_span: Span, note: &str) { let mut err = self.lookup(lint, Some(span), msg); - if self.current_level(lint) != Level::Allow { - if note_span == span { - err.note(note); - } else { - err.span_note(note_span, note); - } + if note_span == span { + err.note(note); + } else { + err.span_note(note_span, note); } err.emit(); } @@ -695,9 +461,7 @@ pub trait LintContext<'tcx>: Sized { msg: &str, help: &str) { let mut err = self.lookup(lint, Some(span), msg); self.span_lint(lint, span, msg); - if self.current_level(lint) != Level::Allow { - err.span_help(span, help); - } + err.span_help(span, help); err.emit(); } @@ -710,94 +474,10 @@ pub trait LintContext<'tcx>: Sized { /// current lint context, call the provided function, then reset the /// lints in effect to their previous state. fn with_lint_attrs(&mut self, + id: ast::NodeId, attrs: &'tcx [ast::Attribute], f: F) - where F: FnOnce(&mut Self), - { - // Parse all of the lint attributes, and then add them all to the - // current dictionary of lint information. Along the way, keep a history - // of what we changed so we can roll everything back after invoking the - // specified closure - let mut pushed = 0; - - for result in gather_attrs(attrs) { - let (is_group, lint_level_spans) = match result { - Err(span) => { - span_err!(self.sess(), span, E0452, - "malformed lint attribute"); - continue; - } - Ok((lint_name, level, span)) => { - match self.lints().find_lint(&lint_name.as_str()) { - Ok(lint_id) => (false, vec![(lint_id, level, span)]), - Err(FindLintError::NotFound) => { - match self.lints().lint_groups.get(&*lint_name.as_str()) { - Some(&(ref v, _)) => (true, - v.iter() - .map(|lint_id: &LintId| - (*lint_id, level, span)) - .collect()), - None => { - // The lint or lint group doesn't exist. - // This is an error, but it was handled - // by check_lint_name_attribute. - continue; - } - } - } - Err(FindLintError::Removed) => continue, - } - } - }; - - let lint_attr_name = result.expect("lint attribute should be well-formed").0; - - for (lint_id, level, span) in lint_level_spans { - let (now, now_source) = self.lint_sess().get_source(lint_id); - if now == Forbid && level != Forbid { - let forbidden_lint_name = match now_source { - LintSource::Default => lint_id.to_string(), - LintSource::Node(name, _) => name.to_string(), - LintSource::CommandLine(name) => name.to_string(), - }; - let mut diag_builder = struct_span_err!(self.sess(), span, E0453, - "{}({}) overruled by outer forbid({})", - level.as_str(), lint_attr_name, - forbidden_lint_name); - diag_builder.span_label(span, "overruled by previous forbid"); - match now_source { - LintSource::Default => &mut diag_builder, - LintSource::Node(_, forbid_source_span) => { - diag_builder.span_label(forbid_source_span, - "`forbid` level set here") - }, - LintSource::CommandLine(_) => { - diag_builder.note("`forbid` lint level was set on command line") - } - }.emit(); - if is_group { // don't set a separate error for every lint in the group - break; - } - } else if now != level { - let cx = self.lint_sess_mut(); - cx.stack.push((lint_id, (now, now_source))); - pushed += 1; - cx.levels.set(lint_id, (level, Node(lint_attr_name, span))); - } - } - } - - self.enter_attrs(attrs); - f(self); - self.exit_attrs(attrs); - - // rollback - let cx = self.lint_sess_mut(); - for _ in 0..pushed { - let (lint, lvlsrc) = cx.stack.pop().unwrap(); - cx.levels.set(lint, lvlsrc); - } - } + where F: FnOnce(&mut Self); } @@ -808,6 +488,16 @@ impl<'a> EarlyContext<'a> { sess, krate, lint_sess: LintSession::new(&sess.lint_store), + builder: LintLevelSets::builder(sess), + buffered: sess.buffered_lints.borrow_mut().take().unwrap(), + } + } + + fn check_id(&mut self, id: ast::NodeId) { + for early_lint in self.buffered.take(id) { + self.lookup_and_emit(early_lint.lint_id.lint, + Some(early_lint.span.clone()), + &early_lint.msg); } } } @@ -841,6 +531,32 @@ impl<'a, 'tcx> LintContext<'tcx> for LateContext<'a, 'tcx> { debug!("late context: exit_attrs({:?})", attrs); run_lints!(self, exit_lint_attrs, late_passes, attrs); } + + fn lookup>(&self, + lint: &'static Lint, + span: Option, + msg: &str) + -> DiagnosticBuilder { + let id = self.last_ast_node_with_lint_attrs; + match span { + Some(s) => self.tcx.struct_span_lint_node(lint, id, s, msg), + None => self.tcx.struct_lint_node(lint, id, msg), + } + } + + fn with_lint_attrs(&mut self, + id: ast::NodeId, + attrs: &'tcx [ast::Attribute], + f: F) + where F: FnOnce(&mut Self) + { + let prev = self.last_ast_node_with_lint_attrs; + self.last_ast_node_with_lint_attrs = id; + self.enter_attrs(attrs); + f(self); + self.exit_attrs(attrs); + self.last_ast_node_with_lint_attrs = prev; + } } impl<'a> LintContext<'a> for EarlyContext<'a> { @@ -872,6 +588,28 @@ impl<'a> LintContext<'a> for EarlyContext<'a> { debug!("early context: exit_attrs({:?})", attrs); run_lints!(self, exit_lint_attrs, early_passes, attrs); } + + fn lookup>(&self, + lint: &'static Lint, + span: Option, + msg: &str) + -> DiagnosticBuilder { + self.builder.struct_lint(lint, span.map(|s| s.into()), msg) + } + + fn with_lint_attrs(&mut self, + id: ast::NodeId, + attrs: &'a [ast::Attribute], + f: F) + where F: FnOnce(&mut Self) + { + let push = self.builder.push(attrs); + self.check_id(id); + self.enter_attrs(attrs); + f(self); + self.exit_attrs(attrs); + self.builder.pop(push); + } } impl<'a, 'tcx> LateContext<'a, 'tcx> { @@ -893,15 +631,6 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { hir_visit::NestedVisitorMap::All(&self.tcx.hir) } - // Output any lints that were previously added to the session. - fn visit_id(&mut self, id: ast::NodeId) { - let lints = self.sess().lints.borrow_mut().take(id); - for early_lint in lints.iter().chain(self.tables.lints.get(id)) { - debug!("LateContext::visit_id: id={:?} early_lint={:?}", id, early_lint); - self.early_lint(early_lint); - } - } - fn visit_nested_body(&mut self, body: hir::BodyId) { let old_tables = self.tables; self.tables = self.tcx.body_tables(body); @@ -917,7 +646,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { } fn visit_item(&mut self, it: &'tcx hir::Item) { - self.with_lint_attrs(&it.attrs, |cx| { + self.with_lint_attrs(it.id, &it.attrs, |cx| { cx.with_param_env(it.id, |cx| { run_lints!(cx, check_item, late_passes, it); hir_visit::walk_item(cx, it); @@ -927,7 +656,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { } fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem) { - self.with_lint_attrs(&it.attrs, |cx| { + self.with_lint_attrs(it.id, &it.attrs, |cx| { cx.with_param_env(it.id, |cx| { run_lints!(cx, check_foreign_item, late_passes, it); hir_visit::walk_foreign_item(cx, it); @@ -942,7 +671,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { } fn visit_expr(&mut self, e: &'tcx hir::Expr) { - self.with_lint_attrs(&e.attrs, |cx| { + self.with_lint_attrs(e.id, &e.attrs, |cx| { run_lints!(cx, check_expr, late_passes, e); hir_visit::walk_expr(cx, e); run_lints!(cx, check_expr_post, late_passes, e); @@ -984,7 +713,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { } fn visit_struct_field(&mut self, s: &'tcx hir::StructField) { - self.with_lint_attrs(&s.attrs, |cx| { + self.with_lint_attrs(s.id, &s.attrs, |cx| { run_lints!(cx, check_struct_field, late_passes, s); hir_visit::walk_struct_field(cx, s); }) @@ -994,7 +723,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { v: &'tcx hir::Variant, g: &'tcx hir::Generics, item_id: ast::NodeId) { - self.with_lint_attrs(&v.node.attrs, |cx| { + self.with_lint_attrs(v.node.data.id(), &v.node.attrs, |cx| { run_lints!(cx, check_variant, late_passes, v, g); hir_visit::walk_variant(cx, v, g, item_id); run_lints!(cx, check_variant_post, late_passes, v, g); @@ -1017,7 +746,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { } fn visit_local(&mut self, l: &'tcx hir::Local) { - self.with_lint_attrs(&l.attrs, |cx| { + self.with_lint_attrs(l.id, &l.attrs, |cx| { run_lints!(cx, check_local, late_passes, l); hir_visit::walk_local(cx, l); }) @@ -1045,7 +774,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { } fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { - self.with_lint_attrs(&trait_item.attrs, |cx| { + self.with_lint_attrs(trait_item.id, &trait_item.attrs, |cx| { cx.with_param_env(trait_item.id, |cx| { run_lints!(cx, check_trait_item, late_passes, trait_item); hir_visit::walk_trait_item(cx, trait_item); @@ -1055,7 +784,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { } fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { - self.with_lint_attrs(&impl_item.attrs, |cx| { + self.with_lint_attrs(impl_item.id, &impl_item.attrs, |cx| { cx.with_param_env(impl_item.id, |cx| { run_lints!(cx, check_impl_item, late_passes, impl_item); hir_visit::walk_impl_item(cx, impl_item); @@ -1080,14 +809,13 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { } fn visit_attribute(&mut self, attr: &'tcx ast::Attribute) { - check_lint_name_attribute(self, attr); run_lints!(self, check_attribute, late_passes, attr); } } impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { fn visit_item(&mut self, it: &'a ast::Item) { - self.with_lint_attrs(&it.attrs, |cx| { + self.with_lint_attrs(it.id, &it.attrs, |cx| { run_lints!(cx, check_item, early_passes, it); ast_visit::walk_item(cx, it); run_lints!(cx, check_item_post, early_passes, it); @@ -1095,7 +823,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { } fn visit_foreign_item(&mut self, it: &'a ast::ForeignItem) { - self.with_lint_attrs(&it.attrs, |cx| { + self.with_lint_attrs(it.id, &it.attrs, |cx| { run_lints!(cx, check_foreign_item, early_passes, it); ast_visit::walk_foreign_item(cx, it); run_lints!(cx, check_foreign_item_post, early_passes, it); @@ -1104,11 +832,12 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { fn visit_pat(&mut self, p: &'a ast::Pat) { run_lints!(self, check_pat, early_passes, p); + self.check_id(p.id); ast_visit::walk_pat(self, p); } fn visit_expr(&mut self, e: &'a ast::Expr) { - self.with_lint_attrs(&e.attrs, |cx| { + self.with_lint_attrs(e.id, &e.attrs, |cx| { run_lints!(cx, check_expr, early_passes, e); ast_visit::walk_expr(cx, e); }) @@ -1116,12 +845,14 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { fn visit_stmt(&mut self, s: &'a ast::Stmt) { run_lints!(self, check_stmt, early_passes, s); + self.check_id(s.id); ast_visit::walk_stmt(self, s); } fn visit_fn(&mut self, fk: ast_visit::FnKind<'a>, decl: &'a ast::FnDecl, span: Span, id: ast::NodeId) { run_lints!(self, check_fn, early_passes, fk, decl, span, id); + self.check_id(id); ast_visit::walk_fn(self, fk, decl, span); run_lints!(self, check_fn_post, early_passes, fk, decl, span, id); } @@ -1133,19 +864,20 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { item_id: ast::NodeId, _: Span) { run_lints!(self, check_struct_def, early_passes, s, ident, g, item_id); + self.check_id(s.id()); ast_visit::walk_struct_def(self, s); run_lints!(self, check_struct_def_post, early_passes, s, ident, g, item_id); } fn visit_struct_field(&mut self, s: &'a ast::StructField) { - self.with_lint_attrs(&s.attrs, |cx| { + self.with_lint_attrs(s.id, &s.attrs, |cx| { run_lints!(cx, check_struct_field, early_passes, s); ast_visit::walk_struct_field(cx, s); }) } fn visit_variant(&mut self, v: &'a ast::Variant, g: &'a ast::Generics, item_id: ast::NodeId) { - self.with_lint_attrs(&v.node.attrs, |cx| { + self.with_lint_attrs(item_id, &v.node.attrs, |cx| { run_lints!(cx, check_variant, early_passes, v, g); ast_visit::walk_variant(cx, v, g, item_id); run_lints!(cx, check_variant_post, early_passes, v, g); @@ -1154,6 +886,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { fn visit_ty(&mut self, t: &'a ast::Ty) { run_lints!(self, check_ty, early_passes, t); + self.check_id(t.id); ast_visit::walk_ty(self, t); } @@ -1163,12 +896,13 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { fn visit_mod(&mut self, m: &'a ast::Mod, s: Span, _a: &[ast::Attribute], n: ast::NodeId) { run_lints!(self, check_mod, early_passes, m, s, n); + self.check_id(n); ast_visit::walk_mod(self, m); run_lints!(self, check_mod_post, early_passes, m, s, n); } fn visit_local(&mut self, l: &'a ast::Local) { - self.with_lint_attrs(&l.attrs, |cx| { + self.with_lint_attrs(l.id, &l.attrs, |cx| { run_lints!(cx, check_local, early_passes, l); ast_visit::walk_local(cx, l); }) @@ -1176,6 +910,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { fn visit_block(&mut self, b: &'a ast::Block) { run_lints!(self, check_block, early_passes, b); + self.check_id(b.id); ast_visit::walk_block(self, b); run_lints!(self, check_block_post, early_passes, b); } @@ -1195,7 +930,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { } fn visit_trait_item(&mut self, trait_item: &'a ast::TraitItem) { - self.with_lint_attrs(&trait_item.attrs, |cx| { + self.with_lint_attrs(trait_item.id, &trait_item.attrs, |cx| { run_lints!(cx, check_trait_item, early_passes, trait_item); ast_visit::walk_trait_item(cx, trait_item); run_lints!(cx, check_trait_item_post, early_passes, trait_item); @@ -1203,7 +938,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { } fn visit_impl_item(&mut self, impl_item: &'a ast::ImplItem) { - self.with_lint_attrs(&impl_item.attrs, |cx| { + self.with_lint_attrs(impl_item.id, &impl_item.attrs, |cx| { run_lints!(cx, check_impl_item, early_passes, impl_item); ast_visit::walk_impl_item(cx, impl_item); run_lints!(cx, check_impl_item_post, early_passes, impl_item); @@ -1212,6 +947,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) { run_lints!(self, check_lifetime, early_passes, lt); + self.check_id(lt.id); } fn visit_lifetime_def(&mut self, lt: &'a ast::LifetimeDef) { @@ -1220,11 +956,13 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { fn visit_path(&mut self, p: &'a ast::Path, id: ast::NodeId) { run_lints!(self, check_path, early_passes, p, id); + self.check_id(id); ast_visit::walk_path(self, p); } fn visit_path_list_item(&mut self, prefix: &'a ast::Path, item: &'a ast::PathListItem) { run_lints!(self, check_path_list_item, early_passes, item); + self.check_id(item.node.id); ast_visit::walk_path_list_item(self, prefix, item); } @@ -1233,110 +971,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { } fn visit_mac_def(&mut self, _mac: &'a ast::MacroDef, id: ast::NodeId) { - let lints = self.sess.lints.borrow_mut().take(id); - for early_lint in lints { - self.early_lint(&early_lint); - } - } -} - -enum CheckLintNameResult { - Ok, - // Lint doesn't exist - NoLint, - // The lint is either renamed or removed. This is the warning - // message. - Warning(String), -} - -/// Checks the name of a lint for its existence, and whether it was -/// renamed or removed. Generates a DiagnosticBuilder containing a -/// warning for renamed and removed lints. This is over both lint -/// names from attributes and those passed on the command line. Since -/// it emits non-fatal warnings and there are *two* lint passes that -/// inspect attributes, this is only run from the late pass to avoid -/// printing duplicate warnings. -fn check_lint_name(lint_cx: &LintStore, - lint_name: &str) -> CheckLintNameResult { - match lint_cx.by_name.get(lint_name) { - Some(&Renamed(ref new_name, _)) => { - CheckLintNameResult::Warning( - format!("lint {} has been renamed to {}", lint_name, new_name) - ) - }, - Some(&Removed(ref reason)) => { - CheckLintNameResult::Warning( - format!("lint {} has been removed: {}", lint_name, reason) - ) - }, - None => { - match lint_cx.lint_groups.get(lint_name) { - None => { - CheckLintNameResult::NoLint - } - Some(_) => { - /* lint group exists */ - CheckLintNameResult::Ok - } - } - } - Some(_) => { - /* lint exists */ - CheckLintNameResult::Ok - } - } -} - -// Checks the validity of lint names derived from attributes -fn check_lint_name_attribute(cx: &LateContext, attr: &ast::Attribute) { - for result in gather_attr(attr) { - match result { - Err(_) => { - // Malformed lint attr. Reported by with_lint_attrs - continue; - } - Ok((lint_name, _, span)) => { - match check_lint_name(&cx.lint_sess.lints, &lint_name.as_str()) { - CheckLintNameResult::Ok => (), - CheckLintNameResult::Warning(ref msg) => { - cx.span_lint(builtin::RENAMED_AND_REMOVED_LINTS, - span, msg); - } - CheckLintNameResult::NoLint => { - cx.span_lint(builtin::UNKNOWN_LINTS, span, - &format!("unknown lint: `{}`", - lint_name)); - } - } - } - } - } -} - -// Checks the validity of lint names derived from the command line -fn check_lint_name_cmdline(sess: &Session, lint_cx: &LintStore, - lint_name: &str, level: Level) { - let db = match check_lint_name(lint_cx, lint_name) { - CheckLintNameResult::Ok => None, - CheckLintNameResult::Warning(ref msg) => { - Some(sess.struct_warn(msg)) - }, - CheckLintNameResult::NoLint => { - Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name)) - } - }; - - if let Some(mut db) = db { - let msg = format!("requested on the command line with `{} {}`", - match level { - Level::Allow => "-A", - Level::Warn => "-W", - Level::Deny => "-D", - Level::Forbid => "-F", - }, - lint_name); - db.note(&msg); - db.emit(); + self.check_id(id); } } @@ -1355,10 +990,11 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { param_env: ty::ParamEnv::empty(Reveal::UserFacing), access_levels, lint_sess: LintSession::new(&tcx.sess.lint_store), + last_ast_node_with_lint_attrs: ast::CRATE_NODE_ID, }; // Visit the whole crate. - cx.with_lint_attrs(&krate.attrs, |cx| { + cx.with_lint_attrs(ast::CRATE_NODE_ID, &krate.attrs, |cx| { // since the root module isn't visited as an item (because it isn't an // item), warn for it here. run_lints!(cx, check_crate, late_passes, krate); @@ -1368,16 +1004,6 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { run_lints!(cx, check_crate_post, late_passes, krate); }); - // If we missed any lints added to the session, then there's a bug somewhere - // in the iteration code. - if let Some((id, v)) = tcx.sess.lints.borrow().get_any() { - for early_lint in v { - span_bug!(early_lint.diagnostic.span.clone(), - "unprocessed lint {:?} at {}", - early_lint, tcx.hir.node_to_string(*id)); - } - } - // Put the lint store levels and passes back in the session. cx.lint_sess.restore(&tcx.sess.lint_store); } @@ -1386,13 +1012,7 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) { let mut cx = EarlyContext::new(sess, krate); // Visit the whole crate. - cx.with_lint_attrs(&krate.attrs, |cx| { - // Lints may be assigned to the whole crate. - let lints = cx.sess.lints.borrow_mut().take(ast::CRATE_NODE_ID); - for early_lint in lints { - cx.early_lint(&early_lint); - } - + cx.with_lint_attrs(ast::CRATE_NODE_ID, &krate.attrs, |cx| { // since the root module isn't visited as an item (because it isn't an // item), warn for it here. run_lints!(cx, check_crate, early_passes, krate); @@ -1405,11 +1025,11 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) { // Put the lint store levels and passes back in the session. cx.lint_sess.restore(&sess.lint_store); - // If we missed any lints added to the session, then there's a bug somewhere - // in the iteration code. - for (_, v) in sess.lints.borrow().get_any() { - for early_lint in v { - span_bug!(early_lint.diagnostic.span.clone(), "unprocessed lint {:?}", early_lint); + // Emit all buffered lints from early on in the session now that we've + // calculated the lint levels for all AST nodes. + for (_id, lints) in cx.buffered.map { + for early_lint in lints { + span_bug!(early_lint.span, "failed to process bufferd lint here"); } } } @@ -1425,8 +1045,13 @@ impl Decodable for LintId { fn decode(d: &mut D) -> Result { let s = d.read_str()?; ty::tls::with(|tcx| { - match tcx.sess.lint_store.borrow().find_lint(&s) { - Ok(id) => Ok(id), + match tcx.sess.lint_store.borrow().find_lints(&s) { + Ok(ids) => { + if ids.len() != 0 { + panic!("invalid lint-id `{}`", s); + } + Ok(ids[0]) + } Err(_) => panic!("invalid lint-id `{}`", s), } }) diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs new file mode 100644 index 000000000000..ab9d4f75597b --- /dev/null +++ b/src/librustc/lint/levels.rs @@ -0,0 +1,343 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::cmp; + +use errors::DiagnosticBuilder; +use hir::HirId; +use lint::builtin; +use lint::context::CheckLintNameResult; +use lint::{self, Lint, LintId, Level, LintSource}; +use session::Session; +use syntax::ast; +use syntax::attr; +use syntax::codemap::MultiSpan; +use syntax::symbol::Symbol; +use util::nodemap::FxHashMap; + +pub struct LintLevelSets { + list: Vec, + lint_cap: Level, +} + +enum LintSet { + CommandLine { + // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which + // flag. + specs: FxHashMap, + }, + + Node { + specs: FxHashMap, + parent: u32, + }, +} + +impl LintLevelSets { + pub fn new(sess: &Session) -> LintLevelSets { + let mut me = LintLevelSets { + list: Vec::new(), + lint_cap: Level::Forbid, + }; + me.process_command_line(sess); + return me + } + + pub fn builder(sess: &Session) -> LintLevelsBuilder { + LintLevelsBuilder::new(sess, LintLevelSets::new(sess)) + } + + fn process_command_line(&mut self, sess: &Session) { + let store = sess.lint_store.borrow(); + let mut specs = FxHashMap(); + self.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid); + + for &(ref lint_name, level) in &sess.opts.lint_opts { + store.check_lint_name_cmdline(sess, &lint_name, level); + + // If the cap is less than this specified level, e.g. if we've got + // `--cap-lints allow` but we've also got `-D foo` then we ignore + // this specification as the lint cap will set it to allow anyway. + let level = cmp::min(level, self.lint_cap); + + let lint_flag_val = Symbol::intern(lint_name); + let ids = match store.find_lints(&lint_name) { + Ok(ids) => ids, + Err(_) => continue, // errors handled in check_lint_name_cmdline above + }; + for id in ids { + let src = LintSource::CommandLine(lint_flag_val); + specs.insert(id, (level, src)); + } + } + + self.list.push(LintSet::CommandLine { + specs: specs, + }); + } + + fn get_lint_level(&self, lint: &'static Lint, idx: u32) + -> (Level, LintSource) + { + let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx); + + // If `level` is none then we actually assume the default level for this + // lint. + let mut level = level.unwrap_or(lint.default_level); + + // If we're about to issue a warning, check at the last minute for any + // directives against the warnings "lint". If, for example, there's an + // `allow(warnings)` in scope then we want to respect that instead. + if level == Level::Warn { + let (warnings_level, warnings_src) = + self.get_lint_id_level(LintId::of(lint::builtin::WARNINGS), idx); + if let Some(configured_warning_level) = warnings_level { + if configured_warning_level != Level::Warn { + level = configured_warning_level; + src = warnings_src; + } + } + } + + // Ensure that we never exceed the `--cap-lints` argument. + level = cmp::min(level, self.lint_cap); + + return (level, src) + } + + fn get_lint_id_level(&self, id: LintId, mut idx: u32) + -> (Option, LintSource) + { + loop { + match self.list[idx as usize] { + LintSet::CommandLine { ref specs } => { + if let Some(&(level, src)) = specs.get(&id) { + return (Some(level), src) + } + return (None, LintSource::Default) + } + LintSet::Node { ref specs, parent } => { + if let Some(&(level, src)) = specs.get(&id) { + return (Some(level), src) + } + idx = parent; + } + } + } + } +} + +pub struct LintLevelsBuilder<'a> { + sess: &'a Session, + sets: LintLevelSets, + id_to_set: FxHashMap, + cur: u32, + warn_about_weird_lints: bool, +} + +pub struct BuilderPush { + prev: u32, +} + +impl<'a> LintLevelsBuilder<'a> { + pub fn new(sess: &'a Session, sets: LintLevelSets) -> LintLevelsBuilder<'a> { + assert_eq!(sets.list.len(), 1); + LintLevelsBuilder { + sess, + sets, + cur: 0, + id_to_set: FxHashMap(), + warn_about_weird_lints: sess.buffered_lints.borrow().is_some(), + } + } + + /// Pushes a list of AST lint attributes onto this context. + /// + /// This function will return a `BuilderPush` object which should be be + /// passed to `pop` when this scope for the attributes provided is exited. + /// + /// This function will perform a number of tasks: + /// + /// * It'll validate all lint-related attributes in `attrs` + /// * It'll mark all lint-related attriutes as used + /// * Lint levels will be updated based on the attributes provided + /// * Lint attributes are validated, e.g. a #[forbid] can't be switched to + /// #[allow] + /// + /// Don't forget to call `pop`! + pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush { + let mut specs = FxHashMap(); + let store = self.sess.lint_store.borrow(); + let sess = self.sess; + let bad_attr = |span| { + span_err!(sess, span, E0452, + "malformed lint attribute"); + }; + for attr in attrs { + let level = match attr.name().and_then(|name| Level::from_str(&name.as_str())) { + None => continue, + Some(lvl) => lvl, + }; + + let meta = unwrap_or!(attr.meta(), continue); + attr::mark_used(attr); + + let metas = if let Some(metas) = meta.meta_item_list() { + metas + } else { + bad_attr(meta.span); + continue + }; + + for li in metas { + let word = match li.word() { + Some(word) => word, + None => { + bad_attr(li.span); + continue + } + }; + let name = word.name(); + match store.check_lint_name(&name.as_str()) { + CheckLintNameResult::Ok(ids) => { + let src = LintSource::Node(name, li.span); + for id in ids { + specs.insert(*id, (level, src)); + } + } + CheckLintNameResult::Warning(ref msg) => { + if self.warn_about_weird_lints { + self.struct_lint(builtin::RENAMED_AND_REMOVED_LINTS, + Some(li.span.into()), + msg) + .emit(); + } + } + CheckLintNameResult::NoLint => { + if self.warn_about_weird_lints { + self.struct_lint(builtin::UNKNOWN_LINTS, + Some(li.span.into()), + &format!("unknown lint: `{}`", name)) + .emit(); + } + } + } + } + } + + for (id, &(level, ref src)) in specs.iter() { + if level == Level::Forbid { + continue + } + let forbid_src = match self.sets.get_lint_id_level(*id, self.cur) { + (Some(Level::Forbid), src) => src, + _ => continue, + }; + let forbidden_lint_name = match forbid_src { + LintSource::Default => id.to_string(), + LintSource::Node(name, _) => name.to_string(), + LintSource::CommandLine(name) => name.to_string(), + }; + let (lint_attr_name, lint_attr_span) = match *src { + LintSource::Node(name, span) => (name, span), + _ => continue, + }; + let mut diag_builder = struct_span_err!(self.sess, + lint_attr_span, + E0453, + "{}({}) overruled by outer forbid({})", + level.as_str(), + lint_attr_name, + forbidden_lint_name); + diag_builder.span_label(lint_attr_span, "overruled by previous forbid"); + match forbid_src { + LintSource::Default => &mut diag_builder, + LintSource::Node(_, forbid_source_span) => { + diag_builder.span_label(forbid_source_span, + "`forbid` level set here") + }, + LintSource::CommandLine(_) => { + diag_builder.note("`forbid` lint level was set on command line") + } + }.emit(); + // don't set a separate error for every lint in the group + break + } + + let prev = self.cur; + if specs.len() > 0 { + self.cur = self.sets.list.len() as u32; + self.sets.list.push(LintSet::Node { + specs: specs, + parent: prev, + }); + } + + BuilderPush { + prev: prev, + } + } + + /// Called after `push` when the scope of a set of attributes are exited. + pub fn pop(&mut self, push: BuilderPush) { + self.cur = push.prev; + } + + /// Used to emit a lint-related diagnostic based on the current state of + /// this lint context. + pub fn struct_lint(&self, + lint: &'static Lint, + span: Option, + msg: &str) + -> DiagnosticBuilder<'a> + { + let (level, src) = self.sets.get_lint_level(lint, self.cur); + lint::struct_lint_level(self.sess, lint, level, src, span, msg) + } + + /// Registers the ID provided with the current set of lints stored in + /// this context. + pub fn register_id(&mut self, id: HirId) { + self.id_to_set.insert(id, self.cur); + } + + pub fn build(self) -> LintLevelSets { + self.sets + } + + pub fn build_map(self) -> LintLevelMap { + LintLevelMap { + sets: self.sets, + id_to_set: self.id_to_set, + } + } +} + +pub struct LintLevelMap { + sets: LintLevelSets, + id_to_set: FxHashMap, +} + +impl LintLevelMap { + /// If the `id` was previously registered with `register_id` when building + /// this `LintLevelMap` this returns the corresponding lint level and source + /// of the lint level for the lint provided. + /// + /// If the `id` was not previously registered, returns `None`. If `None` is + /// returned then the parent of `id` should be acquired and this function + /// should be called again. + pub fn level_and_source(&self, lint: &'static Lint, id: HirId) + -> Option<(Level, LintSource)> + { + self.id_to_set.get(&id).map(|idx| { + self.sets.get_lint_level(lint, *idx) + }) + } +} diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index f9222ac9400a..c64e1c08082a 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -31,20 +31,27 @@ pub use self::Level::*; pub use self::LintSource::*; +use std::rc::Rc; + +use errors::DiagnosticBuilder; +use hir::def_id::{CrateNum, LOCAL_CRATE}; +use hir::intravisit::{self, FnKind}; use hir; -use hir::intravisit::FnKind; -use std::hash; +use session::Session; use std::ascii::AsciiExt; -use syntax_pos::Span; -use syntax::visit as ast_visit; +use std::hash; use syntax::ast; +use syntax::codemap::MultiSpan; use syntax::symbol::Symbol; +use syntax::visit as ast_visit; +use syntax_pos::Span; +use ty::TyCtxt; +use ty::maps::Providers; +use util::nodemap::NodeMap; pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore, - raw_emit_lint, check_crate, check_ast_crate, gather_attrs, - raw_struct_lint, FutureIncompatibleInfo, EarlyLint, IntoEarlyLint}; - -pub use lint::table::LintTable; + check_crate, check_ast_crate, + FutureIncompatibleInfo, BufferedEarlyLint}; /// Specification of a single lint. #[derive(Copy, Clone, Debug)] @@ -351,4 +358,215 @@ pub type LevelSource = (Level, LintSource); pub mod builtin; mod context; -mod table; +mod levels; + +pub use self::levels::{LintLevelSets, LintLevelMap}; + +pub struct LintBuffer { + map: NodeMap>, +} + +impl LintBuffer { + pub fn new() -> LintBuffer { + LintBuffer { map: NodeMap() } + } + + pub fn add_lint(&mut self, + lint: &'static Lint, + id: ast::NodeId, + sp: MultiSpan, + msg: &str) { + let early_lint = BufferedEarlyLint { + lint_id: LintId::of(lint), + ast_id: id, + span: sp, + msg: msg.to_string(), + }; + let arr = self.map.entry(id).or_insert(Vec::new()); + if !arr.contains(&early_lint) { + arr.push(early_lint); + } + } + + pub fn take(&mut self, id: ast::NodeId) -> Vec { + self.map.remove(&id).unwrap_or(Vec::new()) + } + + pub fn get_any(&self) -> Option<&[BufferedEarlyLint]> { + let key = self.map.keys().next().map(|k| *k); + key.map(|k| &self.map[&k][..]) + } +} + +pub fn struct_lint_level<'a>(sess: &'a Session, + lint: &'static Lint, + level: Level, + src: LintSource, + span: Option, + msg: &str) + -> DiagnosticBuilder<'a> +{ + let mut err = match (level, span) { + (Level::Allow, _) => return sess.diagnostic().struct_dummy(), + (Level::Warn, Some(span)) => sess.struct_span_warn(span, msg), + (Level::Warn, None) => sess.struct_warn(msg), + (Level::Deny, Some(span)) | + (Level::Forbid, Some(span)) => sess.struct_span_err(span, msg), + (Level::Deny, None) | + (Level::Forbid, None) => sess.struct_err(msg), + }; + + let name = lint.name_lower(); + match src { + LintSource::Default => { + sess.diag_note_once( + &mut err, + lint, + &format!("#[{}({})] on by default", level.as_str(), name)); + } + LintSource::CommandLine(lint_flag_val) => { + let flag = match level { + Level::Warn => "-W", + Level::Deny => "-D", + Level::Forbid => "-F", + Level::Allow => panic!(), + }; + let hyphen_case_lint_name = name.replace("_", "-"); + if lint_flag_val.as_str() == name { + sess.diag_note_once( + &mut err, + lint, + &format!("requested on the command line with `{} {}`", + flag, hyphen_case_lint_name)); + } else { + let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); + sess.diag_note_once( + &mut err, + lint, + &format!("`{} {}` implied by `{} {}`", + flag, hyphen_case_lint_name, flag, + hyphen_case_flag_val)); + } + } + LintSource::Node(lint_attr_name, src) => { + sess.diag_span_note_once(&mut err, lint, src, "lint level defined here"); + if lint_attr_name.as_str() != name { + let level_str = level.as_str(); + sess.diag_note_once(&mut err, lint, + &format!("#[{}({})] implied by #[{}({})]", + level_str, name, level_str, lint_attr_name)); + } + } + } + + // Check for future incompatibility lints and issue a stronger warning. + let lints = sess.lint_store.borrow(); + if let Some(future_incompatible) = lints.future_incompatible(LintId::of(lint)) { + let explanation = format!("this was previously accepted by the compiler \ + but is being phased out; \ + it will become a hard error in a future release!"); + let citation = format!("for more information, see {}", + future_incompatible.reference); + err.warn(&explanation); + err.note(&citation); + } + + return err +} + +fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum) + -> Rc +{ + assert_eq!(cnum, LOCAL_CRATE); + let mut builder = LintLevelMapBuilder { + levels: LintLevelSets::builder(tcx.sess), + tcx: tcx, + }; + let krate = tcx.hir.krate(); + + builder.with_lint_attrs(ast::CRATE_NODE_ID, &krate.attrs, |builder| { + intravisit::walk_crate(builder, krate); + }); + + Rc::new(builder.levels.build_map()) +} + +struct LintLevelMapBuilder<'a, 'tcx: 'a> { + levels: levels::LintLevelsBuilder<'tcx>, + tcx: TyCtxt<'a, 'tcx, 'tcx>, +} + +impl<'a, 'tcx> LintLevelMapBuilder<'a, 'tcx> { + fn with_lint_attrs(&mut self, + id: ast::NodeId, + attrs: &[ast::Attribute], + f: F) + where F: FnOnce(&mut Self) + { + let push = self.levels.push(attrs); + self.levels.register_id(self.tcx.hir.definitions().node_to_hir_id(id)); + f(self); + self.levels.pop(push); + } +} + +impl<'a, 'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'a, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> { + intravisit::NestedVisitorMap::All(&self.tcx.hir) + } + + fn visit_item(&mut self, it: &'tcx hir::Item) { + self.with_lint_attrs(it.id, &it.attrs, |builder| { + intravisit::walk_item(builder, it); + }); + } + + fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem) { + self.with_lint_attrs(it.id, &it.attrs, |builder| { + intravisit::walk_foreign_item(builder, it); + }) + } + + fn visit_expr(&mut self, e: &'tcx hir::Expr) { + self.with_lint_attrs(e.id, &e.attrs, |builder| { + intravisit::walk_expr(builder, e); + }) + } + + fn visit_struct_field(&mut self, s: &'tcx hir::StructField) { + self.with_lint_attrs(s.id, &s.attrs, |builder| { + intravisit::walk_struct_field(builder, s); + }) + } + + fn visit_variant(&mut self, + v: &'tcx hir::Variant, + g: &'tcx hir::Generics, + item_id: ast::NodeId) { + self.with_lint_attrs(v.node.data.id(), &v.node.attrs, |builder| { + intravisit::walk_variant(builder, v, g, item_id); + }) + } + + fn visit_local(&mut self, l: &'tcx hir::Local) { + self.with_lint_attrs(l.id, &l.attrs, |builder| { + intravisit::walk_local(builder, l); + }) + } + + fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { + self.with_lint_attrs(trait_item.id, &trait_item.attrs, |builder| { + intravisit::walk_trait_item(builder, trait_item); + }); + } + + fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { + self.with_lint_attrs(impl_item.id, &impl_item.attrs, |builder| { + intravisit::walk_impl_item(builder, impl_item); + }); + } +} + +pub fn provide(providers: &mut Providers) { + providers.lint_levels = lint_levels; +} diff --git a/src/librustc/lint/table.rs b/src/librustc/lint/table.rs deleted file mode 100644 index f2dab25229ae..000000000000 --- a/src/librustc/lint/table.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2012-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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use syntax::ast; -use syntax_pos::MultiSpan; -use util::nodemap::NodeMap; - -use super::{Lint, LintId, EarlyLint, IntoEarlyLint}; - -#[derive(RustcEncodable, RustcDecodable)] -pub struct LintTable { - map: NodeMap> -} - -impl LintTable { - pub fn new() -> Self { - LintTable { map: NodeMap() } - } - - pub fn add_lint>(&mut self, - lint: &'static Lint, - id: ast::NodeId, - sp: S, - msg: String) - { - self.add_lint_diagnostic(lint, id, (sp, &msg[..])) - } - - pub fn add_lint_diagnostic(&mut self, - lint: &'static Lint, - id: ast::NodeId, - msg: M) - where M: IntoEarlyLint, - { - let lint_id = LintId::of(lint); - let early_lint = msg.into_early_lint(lint_id); - let arr = self.map.entry(id).or_insert(vec![]); - if !arr.contains(&early_lint) { - arr.push(early_lint); - } - } - - pub fn get(&self, id: ast::NodeId) -> &[EarlyLint] { - self.map.get(&id).map(|v| &v[..]).unwrap_or(&[]) - } - - pub fn take(&mut self, id: ast::NodeId) -> Vec { - self.map.remove(&id).unwrap_or(vec![]) - } - - pub fn transfer(&mut self, into: &mut LintTable) { - into.map.extend(self.map.drain()); - } - - /// Returns the first (id, lint) pair that is non-empty. Used to - /// implement a sanity check in lints that all node-ids are - /// visited. - pub fn get_any(&self) -> Option<(&ast::NodeId, &Vec)> { - self.map.iter() - .filter(|&(_, v)| !v.is_empty()) - .next() - } -} - diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index a525b4e13b78..4e08bc90c7c3 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -17,11 +17,11 @@ use hir::{self, Item_, PatKind}; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use hir::itemlikevisit::ItemLikeVisitor; -use middle::privacy; -use ty::{self, TyCtxt}; use hir::def::Def; use hir::def_id::{DefId, LOCAL_CRATE}; use lint; +use middle::privacy; +use ty::{self, TyCtxt}; use util::nodemap::FxHashSet; use syntax::{ast, codemap}; @@ -299,7 +299,9 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { } } -fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool { +fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt, + id: ast::NodeId, + attrs: &[ast::Attribute]) -> bool { if attr::contains_name(attrs, "lang") { return true; } @@ -315,14 +317,7 @@ fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool { return true; } - let dead_code = lint::builtin::DEAD_CODE.name_lower(); - for attr in lint::gather_attrs(attrs) { - match attr { - Ok((name, lint::Allow, _)) if name == &*dead_code => return true, - _ => (), - } - } - false + tcx.lint_level_at_node(lint::builtin::DEAD_CODE, id).0 == lint::Allow } // This visitor seeds items that @@ -338,14 +333,17 @@ fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool { // or // 2) We are not sure to be live or not // * Implementation of a trait method -struct LifeSeeder<'k> { +struct LifeSeeder<'k, 'tcx: 'k> { worklist: Vec, krate: &'k hir::Crate, + tcx: TyCtxt<'k, 'tcx, 'tcx>, } -impl<'v, 'k> ItemLikeVisitor<'v> for LifeSeeder<'k> { +impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { - let allow_dead_code = has_allow_dead_code_or_lang_attr(&item.attrs); + let allow_dead_code = has_allow_dead_code_or_lang_attr(self.tcx, + item.id, + &item.attrs); if allow_dead_code { self.worklist.push(item.id); } @@ -360,7 +358,9 @@ impl<'v, 'k> ItemLikeVisitor<'v> for LifeSeeder<'k> { match trait_item.node { hir::TraitItemKind::Const(_, Some(_)) | hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => { - if has_allow_dead_code_or_lang_attr(&trait_item.attrs) { + if has_allow_dead_code_or_lang_attr(self.tcx, + trait_item.id, + &trait_item.attrs) { self.worklist.push(trait_item.id); } } @@ -372,7 +372,9 @@ impl<'v, 'k> ItemLikeVisitor<'v> for LifeSeeder<'k> { for impl_item_ref in impl_item_refs { let impl_item = self.krate.impl_item(impl_item_ref.id); if opt_trait.is_some() || - has_allow_dead_code_or_lang_attr(&impl_item.attrs) { + has_allow_dead_code_or_lang_attr(self.tcx, + impl_item.id, + &impl_item.attrs) { self.worklist.push(impl_item_ref.id.node_id); } } @@ -408,6 +410,7 @@ fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut life_seeder = LifeSeeder { worklist, krate, + tcx, }; krate.visit_all_item_likes(&mut life_seeder); @@ -472,17 +475,19 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { !field.is_positional() && !self.symbol_is_live(field.id, None) && !is_marker_field - && !has_allow_dead_code_or_lang_attr(&field.attrs) + && !has_allow_dead_code_or_lang_attr(self.tcx, field.id, &field.attrs) } fn should_warn_about_variant(&mut self, variant: &hir::Variant_) -> bool { !self.symbol_is_live(variant.data.id(), None) - && !has_allow_dead_code_or_lang_attr(&variant.attrs) + && !has_allow_dead_code_or_lang_attr(self.tcx, + variant.data.id(), + &variant.attrs) } fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem) -> bool { !self.symbol_is_live(fi.id, None) - && !has_allow_dead_code_or_lang_attr(&fi.attrs) + && !has_allow_dead_code_or_lang_attr(self.tcx, fi.id, &fi.attrs) } // id := node id of an item's definition. @@ -528,11 +533,10 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { node_type: &str) { if !name.as_str().starts_with("_") { self.tcx - .sess - .add_lint(lint::builtin::DEAD_CODE, - id, - span, - format!("{} is never used: `{}`", node_type, name)); + .lint_node(lint::builtin::DEAD_CODE, + id, + span, + &format!("{} is never used: `{}`", node_type, name)); } } } diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index abd5cbcb89e3..fcf366788b22 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -56,11 +56,11 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> { match self.unsafe_context.root { SafeContext => { if is_lint { - self.tcx.sess.add_lint(lint::builtin::SAFE_EXTERN_STATICS, - node_id, - span, - format!("{} requires unsafe function or \ - block (error E0133)", description)); + self.tcx.lint_node(lint::builtin::SAFE_EXTERN_STATICS, + node_id, + span, + &format!("{} requires unsafe function or \ + block (error E0133)", description)); } else { // Report an error. struct_span_err!( diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 551a550442b3..070ad5159086 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1482,12 +1482,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { }; if is_assigned { - self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_VARIABLES, id, sp, - format!("variable `{}` is assigned to, but never used", - name)); + self.ir.tcx.lint_node(lint::builtin::UNUSED_VARIABLES, id, sp, + &format!("variable `{}` is assigned to, but never used", + name)); } else if name != "self" { - self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_VARIABLES, id, sp, - format!("unused variable: `{}`", name)); + self.ir.tcx.lint_node(lint::builtin::UNUSED_VARIABLES, id, sp, + &format!("unused variable: `{}`", name)); } } true @@ -1509,11 +1509,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn report_dead_assign(&self, id: NodeId, sp: Span, var: Variable, is_argument: bool) { if let Some(name) = self.should_warn(var) { if is_argument { - self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_ASSIGNMENTS, id, sp, - format!("value passed to `{}` is never read", name)); + self.ir.tcx.lint_node(lint::builtin::UNUSED_ASSIGNMENTS, id, sp, + &format!("value passed to `{}` is never read", name)); } else { - self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_ASSIGNMENTS, id, sp, - format!("value assigned to `{}` is never read", name)); + self.ir.tcx.lint_node(lint::builtin::UNUSED_ASSIGNMENTS, id, sp, + &format!("value assigned to `{}` is never read", name)); } } } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 68c01db544a6..5158c7e94af4 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -493,7 +493,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { format!("use of deprecated item") }; - self.sess.add_lint(lint::builtin::DEPRECATED, id, span, msg); + self.lint_node(lint::builtin::DEPRECATED, id, span, &msg); }; // Deprecated attributes apply in-crate and cross-crate. @@ -737,10 +737,10 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { for &(ref stable_lang_feature, span) in &sess.features.borrow().declared_stable_lang_features { let version = find_lang_feature_accepted_version(&stable_lang_feature.as_str()) .expect("unexpectedly couldn't find version feature was stabilized"); - sess.add_lint(lint::builtin::STABLE_FEATURES, + tcx.lint_node(lint::builtin::STABLE_FEATURES, ast::CRATE_NODE_ID, span, - format_stable_since_msg(version)); + &format_stable_since_msg(version)); } let index = tcx.stability.borrow(); @@ -748,10 +748,10 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { match remaining_lib_features.remove(used_lib_feature) { Some(span) => { if let &attr::StabilityLevel::Stable { since: ref version } = level { - sess.add_lint(lint::builtin::STABLE_FEATURES, + tcx.lint_node(lint::builtin::STABLE_FEATURES, ast::CRATE_NODE_ID, span, - format_stable_since_msg(&version.as_str())); + &format_stable_since_msg(&version.as_str())); } } None => ( /* used but undeclared, handled during the previous ast visit */ ) @@ -759,9 +759,9 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { } for &span in remaining_lib_features.values() { - sess.add_lint(lint::builtin::UNUSED_FEATURES, + tcx.lint_node(lint::builtin::UNUSED_FEATURES, ast::CRATE_NODE_ID, span, - "unused or unknown feature".to_string()); + "unused or unknown feature"); } } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index fe6b24f3e1f2..be39f95b9889 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -79,7 +79,7 @@ pub struct Session { // if the value stored here has been affected by path remapping. pub working_dir: (String, bool), pub lint_store: RefCell, - pub lints: RefCell, + pub buffered_lints: RefCell>, /// Set of (LintId, Option, message) tuples tracking lint /// (sub)diagnostics that have been set once, but should not be set again, /// in order to avoid redundantly verbose output (Issue #24690). @@ -307,22 +307,15 @@ impl Session { self.diagnostic().unimpl(msg) } - pub fn add_lint>(&self, - lint: &'static lint::Lint, - id: ast::NodeId, - sp: S, - msg: String) - { - self.lints.borrow_mut().add_lint(lint, id, sp, msg); - } - - pub fn add_lint_diagnostic(&self, - lint: &'static lint::Lint, - id: ast::NodeId, - msg: M) - where M: lint::IntoEarlyLint, - { - self.lints.borrow_mut().add_lint_diagnostic(lint, id, msg); + pub fn buffer_lint>(&self, + lint: &'static lint::Lint, + id: ast::NodeId, + sp: S, + msg: &str) { + match *self.buffered_lints.borrow_mut() { + Some(ref mut buffer) => buffer.add_lint(lint, id, sp.into(), msg), + None => bug!("can't buffer lints after HIR lowering"), + } } pub fn reserve_node_ids(&self, count: usize) -> ast::NodeId { @@ -708,7 +701,7 @@ pub fn build_session_(sopts: config::Options, local_crate_source_file, working_dir, lint_store: RefCell::new(lint::LintStore::new()), - lints: RefCell::new(lint::LintTable::new()), + buffered_lints: RefCell::new(Some(lint::LintBuffer::new())), one_time_diagnostics: RefCell::new(FxHashSet()), plugin_llvm_passes: RefCell::new(Vec::new()), plugin_attributes: RefCell::new(Vec::new()), diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 65c0a9f8ffd5..f0fc6998c9e5 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -499,11 +499,21 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // weird effect -- the diagnostic is reported as a lint, and // the builder which is returned is marked as canceled. - let mut err = - struct_span_err!(self.tcx.sess, - error_span, - E0276, - "impl has stricter requirements than trait"); + let msg = "impl has stricter requirements than trait"; + let mut err = match lint_id { + Some(node_id) => { + self.tcx.struct_span_lint_node(EXTRA_REQUIREMENT_IN_IMPL, + node_id, + error_span, + msg) + } + None => { + struct_span_err!(self.tcx.sess, + error_span, + E0276, + "{}", msg) + } + }; if let Some(trait_item_span) = self.tcx.hir.span_if_local(trait_item_def_id) { let span = self.tcx.sess.codemap().def_span(trait_item_span); @@ -514,13 +524,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { error_span, format!("impl has extra requirement {}", requirement)); - if let Some(node_id) = lint_id { - self.tcx.sess.add_lint_diagnostic(EXTRA_REQUIREMENT_IN_IMPL, - node_id, - (*err).clone()); - err.cancel(); - } - err } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index c2feb54c4dbe..e843ba35ce52 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -512,11 +512,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } if raise_warning { - tcx.sess.add_lint(lint::builtin::RESOLVE_TRAIT_ON_DEFAULTED_UNIT, - obligation.cause.body_id, - obligation.cause.span, - format!("code relies on type inference rules which are likely \ - to change")); + tcx.lint_node(lint::builtin::RESOLVE_TRAIT_ON_DEFAULTED_UNIT, + obligation.cause.body_id, + obligation.cause.span, + &format!("code relies on type inference rules which are likely \ + to change")); } } Ok(ret) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index be3cd99426d4..6b9cbabf20e9 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -11,14 +11,15 @@ //! type context book-keeping use dep_graph::DepGraph; +use errors::DiagnosticBuilder; use session::Session; -use lint; use middle; use hir::TraitMap; use hir::def::{Def, ExportMap}; use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use hir::map as hir_map; use hir::map::DefPathHash; +use lint::{self, Lint}; use middle::free_region::FreeRegionMap; use middle::lang_items; use middle::resolve_lifetime; @@ -58,6 +59,7 @@ use std::rc::Rc; use syntax::abi; use syntax::ast::{self, Name, NodeId}; use syntax::attr; +use syntax::codemap::MultiSpan; use syntax::symbol::{Symbol, keywords}; use syntax_pos::Span; @@ -254,9 +256,6 @@ pub struct TypeckTables<'tcx> { /// *from* expression of the cast, not the cast itself. pub cast_kinds: NodeMap, - /// Lints for the body of this fn generated by typeck. - pub lints: lint::LintTable, - /// Set of trait imports actually used in the method resolution. /// This is used for warning unused imports. pub used_trait_imports: DefIdSet, @@ -285,7 +284,6 @@ impl<'tcx> TypeckTables<'tcx> { liberated_fn_sigs: NodeMap(), fru_field_types: NodeMap(), cast_kinds: NodeMap(), - lints: lint::LintTable::new(), used_trait_imports: DefIdSet(), tainted_by_errors: false, free_region_map: FreeRegionMap::new(), @@ -1515,6 +1513,59 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { { self.mk_substs(iter::once(s).chain(t.into_iter().cloned()).map(Kind::from)) } + + pub fn lint_node>(self, + lint: &'static Lint, + id: NodeId, + span: S, + msg: &str) { + self.struct_span_lint_node(lint, id, span.into(), msg).emit() + } + + pub fn lint_level_at_node(self, lint: &'static Lint, mut id: NodeId) + -> (lint::Level, lint::LintSource) + { + // Right now we insert a `with_ignore` node in the dep graph here to + // ignore the fact that `lint_levels` below depends on the entire crate. + // For now this'll prevent false positives of recompiling too much when + // anything changes. + // + // Once red/green incremental compilation lands we should be able to + // remove this because while the crate changes often the lint level map + // will change rarely. + self.dep_graph.with_ignore(|| { + let sets = self.lint_levels(LOCAL_CRATE); + loop { + let hir_id = self.hir.definitions().node_to_hir_id(id); + if let Some(pair) = sets.level_and_source(lint, hir_id) { + return pair + } + let next = self.hir.get_parent_node(id); + if next == id { + bug!("lint traversal reached the root of the crate"); + } + id = next; + } + }) + } + + pub fn struct_span_lint_node>(self, + lint: &'static Lint, + id: NodeId, + span: S, + msg: &str) + -> DiagnosticBuilder<'tcx> + { + let (level, src) = self.lint_level_at_node(lint, id); + lint::struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg) + } + + pub fn struct_lint_node(self, lint: &'static Lint, id: NodeId, msg: &str) + -> DiagnosticBuilder<'tcx> + { + let (level, src) = self.lint_level_at_node(lint, id); + lint::struct_lint_level(self.sess, lint, level, src, None, msg) + } } pub trait InternAs { diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 5d25ce2fbeca..b871b36c9485 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -12,6 +12,7 @@ use dep_graph::{DepConstructor, DepNode, DepNodeIndex}; use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use hir::def::Def; use hir; +use lint; use middle::const_val; use middle::cstore::{ExternCrate, LinkagePreference}; use middle::privacy::AccessLevels; @@ -506,6 +507,12 @@ impl<'tcx> QueryDescription for queries::extern_crate<'tcx> { } } +impl<'tcx> QueryDescription for queries::lint_levels<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("computing the lint levels for items in this crate") + } +} + macro_rules! define_maps { (<$tcx:tt> $($(#[$attr:meta])* @@ -988,6 +995,8 @@ define_maps! { <'tcx> [] is_panic_runtime: IsPanicRuntime(DefId) -> bool, [] extern_crate: ExternCrate(DefId) -> Rc>, + + [] lint_levels: lint_levels(CrateNum) -> Rc, } fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> { @@ -1059,3 +1068,7 @@ fn needs_drop_dep_node<'tcx>(_: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstruct fn layout_dep_node<'tcx>(_: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> { DepConstructor::Layout } + +fn lint_levels<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::LintLevels +} diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 060ff503d4e5..a3f8aae472ca 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -23,7 +23,7 @@ use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; use rustc::lint; -use rustc_errors::{Diagnostic, Level, DiagnosticBuilder}; +use rustc_errors::DiagnosticBuilder; use rustc::hir::def::*; use rustc::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; @@ -351,12 +351,10 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, match arm_index { // The arm with the user-specified pattern. 0 => { - let mut diagnostic = Diagnostic::new(Level::Warning, - "unreachable pattern"); - diagnostic.set_span(pat.span); - cx.tcx.sess.add_lint_diagnostic( + cx.tcx.lint_node( lint::builtin::UNREACHABLE_PATTERNS, - hir_pat.id, diagnostic); + hir_pat.id, pat.span, + "unreachable pattern"); }, // The arm with the wildcard pattern. 1 => { @@ -371,16 +369,18 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => { - let mut diagnostic = Diagnostic::new(Level::Warning, - "unreachable pattern"); - diagnostic.set_span(pat.span); + let mut err = cx.tcx.struct_span_lint_node( + lint::builtin::UNREACHABLE_PATTERNS, + hir_pat.id, + pat.span, + "unreachable pattern", + ); // if we had a catchall pattern, hint at that if let Some(catchall) = catchall { - diagnostic.span_label(pat.span, "this is an unreachable pattern"); - diagnostic.span_note(catchall, "this pattern matches any value"); + err.span_label(pat.span, "this is an unreachable pattern"); + err.span_note(catchall, "this pattern matches any value"); } - cx.tcx.sess.add_lint_diagnostic(lint::builtin::UNREACHABLE_PATTERNS, - hir_pat.id, diagnostic); + err.emit(); }, // Unreachable patterns in try expressions occur when one of the arms diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 12cb556afdab..3c01d4bafab2 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -638,7 +638,6 @@ pub fn phase_2_configure_and_expand(sess: &Session, super::describe_lints(&sess.lint_store.borrow(), true); return Err(CompileIncomplete::Stopped); } - sess.track_errors(|| sess.lint_store.borrow_mut().process_command_line(sess))?; // Currently, we ignore the name resolution data structures for the purposes of dependency // tracking. Instead we will run name resolution and include its output in the hash of each @@ -708,8 +707,8 @@ pub fn phase_2_configure_and_expand(sess: &Session, missing_fragment_specifiers.sort(); for span in missing_fragment_specifiers { let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER; - let msg = "missing fragment specifier".to_string(); - sess.add_lint(lint, ast::CRATE_NODE_ID, span, msg); + let msg = "missing fragment specifier"; + sess.buffer_lint(lint, ast::CRATE_NODE_ID, span, msg); } if ecx.parse_sess.span_diagnostic.err_count() - ecx.resolve_err_count > err_count { ecx.parse_sess.span_diagnostic.abort_if_errors(); @@ -772,10 +771,6 @@ pub fn phase_2_configure_and_expand(sess: &Session, "checking for inline asm in case the target doesn't support it", || no_asm::check_crate(sess, &krate)); - time(time_passes, - "early lint checks", - || lint::check_ast_crate(sess, &krate)); - time(time_passes, "AST validation", || ast_validation::check_crate(sess, &krate)); @@ -800,6 +795,10 @@ pub fn phase_2_configure_and_expand(sess: &Session, }) })?; + time(time_passes, + "early lint checks", + || lint::check_ast_crate(sess, &krate)); + // Lower ast -> hir. let hir_forest = time(time_passes, "lowering ast -> hir", || { let hir_crate = lower_crate(sess, &krate, &mut resolver); @@ -908,6 +907,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, rustc_const_eval::provide(&mut local_providers); middle::region::provide(&mut local_providers); cstore::provide_local(&mut local_providers); + lint::provide(&mut local_providers); let mut extern_providers = ty::maps::Providers::default(); cstore::provide(&mut extern_providers); @@ -1194,10 +1194,10 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec Some(config::CrateTypeExecutable), Some(_) => { - session.add_lint(lint::builtin::UNKNOWN_CRATE_TYPES, - ast::CRATE_NODE_ID, - a.span, - "invalid `crate_type` value".to_string()); + session.buffer_lint(lint::builtin::UNKNOWN_CRATE_TYPES, + ast::CRATE_NODE_ID, + a.span, + "invalid `crate_type` value"); None } _ => { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index db27fa874f4e..88432e642903 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -36,7 +36,7 @@ use rustc::ty::{self, Ty}; use rustc::traits::{self, Reveal}; use rustc::hir::map as hir_map; use util::nodemap::NodeSet; -use lint::{Level, LateContext, LintContext, LintArray}; +use lint::{LateContext, LintContext, LintArray}; use lint::{LintPass, LateLintPass, EarlyLintPass, EarlyContext}; use std::collections::HashSet; @@ -876,16 +876,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION, sp, "function cannot return without recurring"); - // FIXME #19668: these could be span_lint_note's instead of this manual guard. - if cx.current_level(UNCONDITIONAL_RECURSION) != Level::Allow { - // offer some help to the programmer. - for call in &self_call_spans { - db.span_note(*call, "recursive call site"); - } - db.help("a `loop` may express intention \ - better if this is on purpose"); + // offer some help to the programmer. + for call in &self_call_spans { + db.span_note(*call, "recursive call site"); } + db.help("a `loop` may express intention \ + better if this is on purpose"); db.emit(); } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 38d8555334c3..2643ed2a3c07 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -237,10 +237,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_trait_fn_not_const(sig.constness); if block.is_none() { self.check_decl_no_pat(&sig.decl, |span, _| { - self.session.add_lint(lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY, - trait_item.id, span, - "patterns aren't allowed in methods \ - without bodies".to_string()); + self.session.buffer_lint( + lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY, + trait_item.id, span, + "patterns aren't allowed in methods \ + without bodies"); }); } } @@ -252,7 +253,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if item.attrs.iter().any(|attr| attr.check_name("warn_directory_ownership")) { let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP; let msg = "cannot declare a new module at this location"; - self.session.add_lint(lint, item.id, item.span, msg.to_string()); + self.session.buffer_lint(lint, item.id, item.span, msg); } } ItemKind::Union(ref vdata, _) => { diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index a881bf9eac7b..8443cc8267d1 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -76,12 +76,12 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { ErroneousReferencedConstant(_) => {} TypeckError => {} _ => { - self.tcx.sess.add_lint(CONST_ERR, - expr.id, - expr.span, - format!("constant evaluation error: {}. This will \ - become a HARD ERROR in the future", - err.description().into_oneline())) + self.tcx.lint_node(CONST_ERR, + expr.id, + expr.span, + &format!("constant evaluation error: {}. This will \ + become a HARD ERROR in the future", + err.description().into_oneline())); } } } @@ -260,10 +260,10 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { kind: LayoutError(ty::layout::LayoutError::Unknown(_)), .. }) => {} Err(msg) => { - self.tcx.sess.add_lint(CONST_ERR, - ex.id, - msg.span, - msg.description().into_oneline().into_owned()) + self.tcx.lint_node(CONST_ERR, + ex.id, + msg.span, + &msg.description().into_oneline().into_owned()); } } } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 64af24d92eec..180d3dedf4b9 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1345,11 +1345,11 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { "private trait can't be public")) .emit(); } else { - self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC, - node_id, - self.span, - format!("private trait `{}` in public \ - interface (error E0445)", trait_ref)); + self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC, + node_id, + self.span, + &format!("private trait `{}` in public \ + interface (error E0445)", trait_ref)); } } } @@ -1393,11 +1393,11 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<' err.span_label(self.span, "can't leak private type"); err.emit(); } else { - self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC, - node_id, - self.span, - format!("private type `{}` in public \ - interface (error E0446)", ty)); + self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC, + node_id, + self.span, + &format!("private type `{}` in public \ + interface (error E0446)", ty)); } } } diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index d150ff1ff81f..a8bb6619bbdd 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -122,13 +122,13 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) { directive.span.source_equal(&DUMMY_SP) => {} ImportDirectiveSubclass::ExternCrate => { let lint = lint::builtin::UNUSED_EXTERN_CRATES; - let msg = "unused extern crate".to_string(); - resolver.session.add_lint(lint, directive.id, directive.span, msg); + let msg = "unused extern crate"; + ; resolver.session.buffer_lint(lint, directive.id, directive.span, msg) } ImportDirectiveSubclass::MacroUse => { let lint = lint::builtin::UNUSED_IMPORTS; - let msg = "unused `#[macro_use]` import".to_string(); - resolver.session.add_lint(lint, directive.id, directive.span, msg); + let msg = "unused `#[macro_use]` import"; + resolver.session.buffer_lint(lint, directive.id, directive.span, msg); } _ => {} } @@ -160,9 +160,6 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) { } else { String::new() }); - visitor.session.add_lint(lint::builtin::UNUSED_IMPORTS, - *id, - ms, - msg); + visitor.session.buffer_lint(lint::builtin::UNUSED_IMPORTS, *id, ms, &msg); } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2317e36a0ab8..b4f9ba4e8f78 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2552,9 +2552,10 @@ impl<'a> Resolver<'a> { = self.struct_constructors.get(&def_id).cloned() { if is_expected(ctor_def) && self.is_accessible(ctor_vis) { let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY; - self.session.add_lint(lint, id, span, + self.session.buffer_lint(lint, id, span, "private struct constructors are not usable through \ - reexports in outer modules".to_string()); + reexports in outer modules", + ); res = Some(PathResolution::new(ctor_def)); } } @@ -2748,7 +2749,7 @@ impl<'a> Resolver<'a> { }; if result.base_def() == unqualified_result { let lint = lint::builtin::UNUSED_QUALIFICATIONS; - self.session.add_lint(lint, id, span, "unnecessary qualification".to_string()); + self.session.buffer_lint(lint, id, span, "unnecessary qualification") } } @@ -3486,7 +3487,7 @@ impl<'a> Resolver<'a> { span.push_span_label(b1.span, msg1); span.push_span_label(b2.span, msg2); let msg = format!("`{}` is ambiguous", name); - self.session.add_lint(lint::builtin::LEGACY_IMPORTS, id, span, msg); + self.session.buffer_lint(lint::builtin::LEGACY_IMPORTS, id, span, &msg); } else { let mut err = self.session.struct_span_err(span, &format!("`{}` is ambiguous", name)); @@ -3607,8 +3608,8 @@ impl<'a> Resolver<'a> { fn warn_legacy_self_import(&self, directive: &'a ImportDirective<'a>) { let (id, span) = (directive.id, directive.span); - let msg = "`self` no longer imports values".to_string(); - self.session.add_lint(lint::builtin::LEGACY_IMPORTS, id, span, msg); + let msg = "`self` no longer imports values"; + self.session.buffer_lint(lint::builtin::LEGACY_IMPORTS, id, span, msg); } fn check_proc_macro_attrs(&mut self, attrs: &[ast::Attribute]) { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 4d4f6aadce4d..98eaa056177e 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -319,8 +319,8 @@ impl<'a> base::Resolver for Resolver<'a> { }; if let Some((id, span)) = id_span { let lint = lint::builtin::UNUSED_MACROS; - let msg = "unused macro definition".to_string(); - self.session.add_lint(lint, id, span, msg); + let msg = "unused macro definition"; + self.session.buffer_lint(lint, id, span, msg); } else { bug!("attempted to create unused macro error, but span not available"); } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 5e799b14f209..984ef3a44e1a 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -745,8 +745,10 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let msg = format!("extern crate `{}` is private, and cannot be reexported \ (error E0365), consider declaring with `pub`", ident); - self.session.add_lint(PUB_USE_OF_PRIVATE_EXTERN_CRATE, - directive.id, directive.span, msg); + self.session.buffer_lint(PUB_USE_OF_PRIVATE_EXTERN_CRATE, + directive.id, + directive.span, + &msg); } else if ns == TypeNS { struct_span_err!(self.session, directive.span, E0365, "`{}` is private, and cannot be reexported", ident) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 1ec850ad7f34..2910d25486ed 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -985,9 +985,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { .span_label(data.span, "only traits may use parentheses") .emit(); } else { - let msg = "parenthesized parameters may only be used with a trait".to_string(); - self.tcx().sess.add_lint(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, - ast::CRATE_NODE_ID, data.span, msg); + let msg = "parenthesized parameters may only be used with a trait"; + self.tcx().lint_node(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, + ast::CRATE_NODE_ID, data.span, msg); } } } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index b3f62de5b570..5f256eab9a9c 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -291,25 +291,25 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { let t_cast = self.cast_ty; let t_expr = self.expr_ty; if t_cast.is_numeric() && t_expr.is_numeric() { - fcx.tables.borrow_mut().lints.add_lint( + fcx.tcx.lint_node( lint::builtin::TRIVIAL_NUMERIC_CASTS, self.expr.id, self.span, - format!("trivial numeric cast: `{}` as `{}`. Cast can be \ - replaced by coercion, this might require type \ - ascription or a temporary variable", - fcx.ty_to_string(t_expr), - fcx.ty_to_string(t_cast))); + &format!("trivial numeric cast: `{}` as `{}`. Cast can be \ + replaced by coercion, this might require type \ + ascription or a temporary variable", + fcx.ty_to_string(t_expr), + fcx.ty_to_string(t_cast))); } else { - fcx.tables.borrow_mut().lints.add_lint( + fcx.tcx.lint_node( lint::builtin::TRIVIAL_CASTS, self.expr.id, self.span, - format!("trivial cast: `{}` as `{}`. Cast can be \ - replaced by coercion, this might require type \ - ascription or a temporary variable", - fcx.ty_to_string(t_expr), - fcx.ty_to_string(t_cast))); + &format!("trivial cast: `{}` as `{}`. Cast can be \ + replaced by coercion, this might require type \ + ascription or a temporary variable", + fcx.ty_to_string(t_expr), + fcx.ty_to_string(t_cast))); } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e53e5e7b08c9..6c9a6524d678 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1713,10 +1713,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind); - self.tables.borrow_mut().lints.add_lint( + self.tcx().lint_node( lint::builtin::UNREACHABLE_CODE, id, span, - format!("unreachable {}", kind)); + &format!("unreachable {}", kind)); } } @@ -4746,8 +4746,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { let mut multispan = MultiSpan::from_span(lifetimes[0].span); multispan.push_span_label(span_late, note_msg.to_string()); - self.tcx.sess.add_lint(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, - lifetimes[0].id, multispan, primary_msg.to_string()); + self.tcx.lint_node(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, + lifetimes[0].id, multispan, primary_msg); } return; } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 0a323efabec1..9e5cf5137c21 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -43,7 +43,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { wbcx.visit_fru_field_types(); wbcx.visit_anon_types(); wbcx.visit_cast_types(); - wbcx.visit_lints(); wbcx.visit_free_region_map(); let used_trait_imports = mem::replace(&mut self.tables.borrow_mut().used_trait_imports, @@ -234,10 +233,6 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { self.fcx.tables.borrow().cast_kinds.iter().map(|(&key, &value)| (key, value))); } - fn visit_lints(&mut self) { - self.fcx.tables.borrow_mut().lints.transfer(&mut self.tables.lints); - } - fn visit_free_region_map(&mut self) { let free_region_map = self.tcx().lift_to_global(&self.fcx.tables.borrow().free_region_map); let free_region_map = free_region_map.expect("all regions in free-region-map are global"); diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 1af55d4d840d..e95d49f00bf7 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -39,7 +39,7 @@ impl<'a, 'tcx> CheckVisitor<'a, 'tcx> { } else { "unused import".to_string() }; - self.tcx.sess.add_lint(lint::builtin::UNUSED_IMPORTS, id, span, msg); + self.tcx.lint_node(lint::builtin::UNUSED_IMPORTS, id, span, &msg); } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index f25a6cf58a79..fba32dbb889d 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -999,12 +999,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.add_lint( + tcx.lint_node( 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.")); + &format!("defaults for type parameters are only allowed in `struct`, \ + `enum`, `type`, or `trait` definitions.")); } } diff --git a/src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs b/src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs index 508f8dac5711..f42d1006bf5c 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs @@ -11,6 +11,7 @@ // aux-build:attributes-included.rs #![feature(proc_macro, rustc_attrs)] +#![warn(unused)] extern crate attributes_included; diff --git a/src/test/compile-fail/E0010.rs b/src/test/compile-fail/E0010.rs index 8a666168c86f..ccaf01932d46 100644 --- a/src/test/compile-fail/E0010.rs +++ b/src/test/compile-fail/E0010.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(box_syntax)] +#![allow(warnings)] const CON : Box = box 0; //~ ERROR E0010 //~| NOTE allocation not allowed in diff --git a/src/test/compile-fail/E0394.rs b/src/test/compile-fail/E0394.rs index e35d038248c8..c7d5665cd2c5 100644 --- a/src/test/compile-fail/E0394.rs +++ b/src/test/compile-fail/E0394.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(warnings)] + static A: u32 = 0; static B: u32 = A; //~^ ERROR E0394 diff --git a/src/test/compile-fail/bad-lint-cap2.rs b/src/test/compile-fail/bad-lint-cap2.rs index 5a97d7b1a79a..cb9fb973a019 100644 --- a/src/test/compile-fail/bad-lint-cap2.rs +++ b/src/test/compile-fail/bad-lint-cap2.rs @@ -10,6 +10,7 @@ // compile-flags: --cap-lints deny +#![warn(unused)] #![deny(warnings)] use std::option; //~ ERROR diff --git a/src/test/compile-fail/bad-lint-cap3.rs b/src/test/compile-fail/bad-lint-cap3.rs index e03ba6ecb644..c9394954c5fb 100644 --- a/src/test/compile-fail/bad-lint-cap3.rs +++ b/src/test/compile-fail/bad-lint-cap3.rs @@ -10,6 +10,7 @@ // compile-flags: --cap-lints warn +#![warn(unused)] #![deny(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/compile-fail/check-static-values-constraints.rs b/src/test/compile-fail/check-static-values-constraints.rs index f65968e0e119..3642add32597 100644 --- a/src/test/compile-fail/check-static-values-constraints.rs +++ b/src/test/compile-fail/check-static-values-constraints.rs @@ -12,6 +12,7 @@ // gate-test-drop_types_in_const +#![allow(warnings)] #![feature(box_syntax)] use std::marker; diff --git a/src/test/compile-fail/const-eval-overflow-2.rs b/src/test/compile-fail/const-eval-overflow-2.rs index 9b045ed1d02c..0fd41a17b2c9 100644 --- a/src/test/compile-fail/const-eval-overflow-2.rs +++ b/src/test/compile-fail/const-eval-overflow-2.rs @@ -11,7 +11,7 @@ // Evaluation of constants in refutable patterns goes through // different compiler control-flow paths. -#![allow(unused_imports)] +#![allow(unused_imports, warnings)] use std::fmt; use std::{i8, i16, i32, i64, isize}; diff --git a/src/test/compile-fail/const-match-pattern-arm.rs b/src/test/compile-fail/const-match-pattern-arm.rs index 452aa87d6ba5..bc944948f3d8 100644 --- a/src/test/compile-fail/const-match-pattern-arm.rs +++ b/src/test/compile-fail/const-match-pattern-arm.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(warnings)] + const x: bool = match Some(true) { Some(value) => true, //~^ ERROR: constant contains unimplemented expression type [E0019] diff --git a/src/test/compile-fail/feature-gate-dropck-ugeh.rs b/src/test/compile-fail/feature-gate-dropck-ugeh.rs index d9664fda2b33..360895d30b0b 100644 --- a/src/test/compile-fail/feature-gate-dropck-ugeh.rs +++ b/src/test/compile-fail/feature-gate-dropck-ugeh.rs @@ -28,7 +28,6 @@ struct Foo { data: Vec } impl Drop for Foo { #[unsafe_destructor_blind_to_params] // This is the UGEH attribute //~^ ERROR unsafe_destructor_blind_to_params has been replaced - //~^^ WARN: use of deprecated attribute fn drop(&mut self) { } } diff --git a/src/test/compile-fail/issue-14227.rs b/src/test/compile-fail/issue-14227.rs index c4846a64f29b..d8f9f5543e43 100644 --- a/src/test/compile-fail/issue-14227.rs +++ b/src/test/compile-fail/issue-14227.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(safe_extern_statics, warnings)] + extern { pub static symbol: (); } diff --git a/src/test/compile-fail/issue-16538.rs b/src/test/compile-fail/issue-16538.rs index 6c41450796c7..08c3f7a7c154 100644 --- a/src/test/compile-fail/issue-16538.rs +++ b/src/test/compile-fail/issue-16538.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(safe_extern_statics)] + mod Y { pub type X = usize; extern { diff --git a/src/test/compile-fail/issue-17450.rs b/src/test/compile-fail/issue-17450.rs index 5471d8522dff..cde1bbbe4927 100644 --- a/src/test/compile-fail/issue-17450.rs +++ b/src/test/compile-fail/issue-17450.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(dead_code)] +#![allow(dead_code, warnings)] static mut x: isize = 3; static mut y: isize = unsafe { diff --git a/src/test/compile-fail/issue-17718-const-naming.rs b/src/test/compile-fail/issue-17718-const-naming.rs index 06719e2756b1..4857c2fb446b 100644 --- a/src/test/compile-fail/issue-17718-const-naming.rs +++ b/src/test/compile-fail/issue-17718-const-naming.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![warn(unused)] #[deny(warnings)] const foo: isize = 3; diff --git a/src/test/compile-fail/issue-17718-references.rs b/src/test/compile-fail/issue-17718-references.rs index c159168030b8..8e0df283cdbe 100644 --- a/src/test/compile-fail/issue-17718-references.rs +++ b/src/test/compile-fail/issue-17718-references.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(warnings)] + struct Struct { a: usize } const C: usize = 1; diff --git a/src/test/compile-fail/issue-18937.rs b/src/test/compile-fail/issue-18937.rs index f57f3477a8a8..5996c8e54387 100644 --- a/src/test/compile-fail/issue-18937.rs +++ b/src/test/compile-fail/issue-18937.rs @@ -26,7 +26,7 @@ trait A<'a> { } impl<'a> A<'a> for B { - fn foo(&mut self, f: F) //~ ERROR E0276 + fn foo(&mut self, f: F) //~ ERROR impl has stricter //~^ WARNING future release where F: fmt::Debug + 'static, { diff --git a/src/test/compile-fail/issue-28075.rs b/src/test/compile-fail/issue-28075.rs index cd73a4564111..057c99f93051 100644 --- a/src/test/compile-fail/issue-28075.rs +++ b/src/test/compile-fail/issue-28075.rs @@ -12,7 +12,7 @@ // aux-build:lint_stability.rs -#![allow(unused_imports)] +#![allow(warnings)] extern crate lint_stability; diff --git a/src/test/compile-fail/issue-28113.rs b/src/test/compile-fail/issue-28113.rs index 5c697b69c80b..7d2541966a48 100644 --- a/src/test/compile-fail/issue-28113.rs +++ b/src/test/compile-fail/issue-28113.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(warnings)] + const X: u8 = || -> u8 { 5 }() //~^ ERROR calls in constants are limited to constant functions diff --git a/src/test/compile-fail/issue-28324.rs b/src/test/compile-fail/issue-28324.rs index 13ce41f4dcc5..3c4d6b42b503 100644 --- a/src/test/compile-fail/issue-28324.rs +++ b/src/test/compile-fail/issue-28324.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(safe_extern_statics)] + extern { static error_message_count: u32; } diff --git a/src/test/compile-fail/issue-30730.rs b/src/test/compile-fail/issue-30730.rs index 086938334c78..d1af39a6c187 100644 --- a/src/test/compile-fail/issue-30730.rs +++ b/src/test/compile-fail/issue-30730.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![warn(unused)] #![deny(warnings)] //~ NOTE: lint level defined here use std::thread; //~^ ERROR: unused import diff --git a/src/test/compile-fail/issue-37515.rs b/src/test/compile-fail/issue-37515.rs index fa452d6e74a0..d5733f981938 100644 --- a/src/test/compile-fail/issue-37515.rs +++ b/src/test/compile-fail/issue-37515.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(rustc_attrs)] +#![warn(unused)] type Z = for<'x> Send; //~^ WARN type alias is never used diff --git a/src/test/compile-fail/issue-7364.rs b/src/test/compile-fail/issue-7364.rs index 16b407baad17..bd32317ae780 100644 --- a/src/test/compile-fail/issue-7364.rs +++ b/src/test/compile-fail/issue-7364.rs @@ -10,6 +10,7 @@ #![feature(box_syntax)] #![feature(const_fn)] +#![allow(warnings)] use std::cell::RefCell; diff --git a/src/test/compile-fail/lint-removed-allow.rs b/src/test/compile-fail/lint-removed-allow.rs index 1498ed4d17ed..9f84190ea18a 100644 --- a/src/test/compile-fail/lint-removed-allow.rs +++ b/src/test/compile-fail/lint-removed-allow.rs @@ -11,7 +11,8 @@ // No warnings about removed lint when // allow(renamed_and_removed_lints) +#![allow(renamed_and_removed_lints)] + #[deny(raw_pointer_derive)] -#[allow(renamed_and_removed_lints)] #[deny(unused_variables)] fn main() { let unused = (); } //~ ERROR unused diff --git a/src/test/compile-fail/lint-removed-cmdline.rs b/src/test/compile-fail/lint-removed-cmdline.rs index d6bfd1eec39a..e1da5086612f 100644 --- a/src/test/compile-fail/lint-removed-cmdline.rs +++ b/src/test/compile-fail/lint-removed-cmdline.rs @@ -16,5 +16,7 @@ // error-pattern:lint raw_pointer_derive has been removed // error-pattern:requested on the command line with `-D raw_pointer_derive` +#![warn(unused)] + #[deny(warnings)] fn main() { let unused = (); } diff --git a/src/test/compile-fail/lint-renamed-allow.rs b/src/test/compile-fail/lint-renamed-allow.rs index ea26c3656e69..ae010b64bfdf 100644 --- a/src/test/compile-fail/lint-renamed-allow.rs +++ b/src/test/compile-fail/lint-renamed-allow.rs @@ -11,7 +11,8 @@ // No warnings about renamed lint when // allow(renamed_and_removed_lints) +#![allow(renamed_and_removed_lints)] + #[deny(unknown_features)] -#[allow(renamed_and_removed_lints)] #[deny(unused)] fn main() { let unused = (); } //~ ERROR unused diff --git a/src/test/compile-fail/lint-stability-deprecated.rs b/src/test/compile-fail/lint-stability-deprecated.rs index d8813b6a6101..8443518b3f56 100644 --- a/src/test/compile-fail/lint-stability-deprecated.rs +++ b/src/test/compile-fail/lint-stability-deprecated.rs @@ -13,9 +13,9 @@ // aux-build:stability_cfg1.rs // aux-build:stability_cfg2.rs -#![deny(deprecated)] +#![warn(deprecated)] #![allow(dead_code)] -#![feature(staged_api, test_feature)] +#![feature(staged_api, test_feature, rustc_attrs)] #![stable(feature = "rust1", since = "1.0.0")] @@ -32,41 +32,41 @@ mod cross_crate { type Foo = MethodTester; let foo = MethodTester; - deprecated(); //~ ERROR use of deprecated item - foo.method_deprecated(); //~ ERROR use of deprecated item - Foo::method_deprecated(&foo); //~ ERROR use of deprecated item - ::method_deprecated(&foo); //~ ERROR use of deprecated item - foo.trait_deprecated(); //~ ERROR use of deprecated item - Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item - ::trait_deprecated(&foo); //~ ERROR use of deprecated item - ::trait_deprecated(&foo); //~ ERROR use of deprecated item + deprecated(); //~ WARN use of deprecated item + foo.method_deprecated(); //~ WARN use of deprecated item + Foo::method_deprecated(&foo); //~ WARN use of deprecated item + ::method_deprecated(&foo); //~ WARN use of deprecated item + foo.trait_deprecated(); //~ WARN use of deprecated item + Trait::trait_deprecated(&foo); //~ WARN use of deprecated item + ::trait_deprecated(&foo); //~ WARN use of deprecated item + ::trait_deprecated(&foo); //~ WARN use of deprecated item - deprecated_text(); //~ ERROR use of deprecated item: text - foo.method_deprecated_text(); //~ ERROR use of deprecated item: text - Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text - ::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text - foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text - Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text - ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text - ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + deprecated_text(); //~ WARN use of deprecated item: text + foo.method_deprecated_text(); //~ WARN use of deprecated item: text + Foo::method_deprecated_text(&foo); //~ WARN use of deprecated item: text + ::method_deprecated_text(&foo); //~ WARN use of deprecated item: text + foo.trait_deprecated_text(); //~ WARN use of deprecated item: text + Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text - deprecated_unstable(); //~ ERROR use of deprecated item - foo.method_deprecated_unstable(); //~ ERROR use of deprecated item - Foo::method_deprecated_unstable(&foo); //~ ERROR use of deprecated item - ::method_deprecated_unstable(&foo); //~ ERROR use of deprecated item - foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item - Trait::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item - ::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item - ::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item + deprecated_unstable(); //~ WARN use of deprecated item + foo.method_deprecated_unstable(); //~ WARN use of deprecated item + Foo::method_deprecated_unstable(&foo); //~ WARN use of deprecated item + ::method_deprecated_unstable(&foo); //~ WARN use of deprecated item + foo.trait_deprecated_unstable(); //~ WARN use of deprecated item + Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item + ::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item + ::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item - deprecated_unstable_text(); //~ ERROR use of deprecated item: text - foo.method_deprecated_unstable_text(); //~ ERROR use of deprecated item: text - Foo::method_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text - ::method_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text - foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text - Trait::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text - ::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text - ::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + deprecated_unstable_text(); //~ WARN use of deprecated item: text + foo.method_deprecated_unstable_text(); //~ WARN use of deprecated item: text + Foo::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text + ::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text + foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item: text + Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text + ::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text + ::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text unstable(); foo.method_unstable(); @@ -106,30 +106,30 @@ mod cross_crate { struct S1(T::TypeUnstable); struct S2(T::TypeDeprecated); - //~^ ERROR use of deprecated item + //~^ WARN use of deprecated item - let _ = DeprecatedStruct { //~ ERROR use of deprecated item - i: 0 //~ ERROR use of deprecated item + let _ = DeprecatedStruct { //~ WARN use of deprecated item + i: 0 //~ WARN use of deprecated item }; let _ = DeprecatedUnstableStruct { - //~^ ERROR use of deprecated item - i: 0 //~ ERROR use of deprecated item + //~^ WARN use of deprecated item + i: 0 //~ WARN use of deprecated item }; let _ = UnstableStruct { i: 0 }; let _ = StableStruct { i: 0 }; - let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item - let _ = DeprecatedUnstableUnitStruct; //~ ERROR use of deprecated item + let _ = DeprecatedUnitStruct; //~ WARN use of deprecated item + let _ = DeprecatedUnstableUnitStruct; //~ WARN use of deprecated item let _ = UnstableUnitStruct; let _ = StableUnitStruct; - let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item - let _ = Enum::DeprecatedUnstableVariant; //~ ERROR use of deprecated item + let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated item + let _ = Enum::DeprecatedUnstableVariant; //~ WARN use of deprecated item let _ = Enum::UnstableVariant; let _ = Enum::StableVariant; - let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item - let _ = DeprecatedUnstableTupleStruct (1); //~ ERROR use of deprecated item + let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated item + let _ = DeprecatedUnstableTupleStruct (1); //~ WARN use of deprecated item let _ = UnstableTupleStruct (1); let _ = StableTupleStruct (1); @@ -138,28 +138,28 @@ mod cross_crate { // Eventually, we will want to lint the contents of the // macro in the module *defining* it. Also, stability levels // on macros themselves are not yet linted. - macro_test_arg!(deprecated_text()); //~ ERROR use of deprecated item: text - macro_test_arg!(deprecated_unstable_text()); //~ ERROR use of deprecated item: text - macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated item: text + macro_test_arg!(deprecated_text()); //~ WARN use of deprecated item: text + macro_test_arg!(deprecated_unstable_text()); //~ WARN use of deprecated item: text + macro_test_arg!(macro_test_arg!(deprecated_text())); //~ WARN use of deprecated item: text } fn test_method_param(foo: Foo) { - foo.trait_deprecated(); //~ ERROR use of deprecated item - Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item - ::trait_deprecated(&foo); //~ ERROR use of deprecated item - ::trait_deprecated(&foo); //~ ERROR use of deprecated item - foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text - Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text - ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text - ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text - foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item - Trait::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item - ::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item - ::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item - foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text - Trait::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text - ::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text - ::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + foo.trait_deprecated(); //~ WARN use of deprecated item + Trait::trait_deprecated(&foo); //~ WARN use of deprecated item + ::trait_deprecated(&foo); //~ WARN use of deprecated item + ::trait_deprecated(&foo); //~ WARN use of deprecated item + foo.trait_deprecated_text(); //~ WARN use of deprecated item: text + Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text + foo.trait_deprecated_unstable(); //~ WARN use of deprecated item + Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item + ::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item + ::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item + foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item: text + Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text + ::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text + ::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text foo.trait_unstable(); Trait::trait_unstable(&foo); ::trait_unstable(&foo); @@ -175,10 +175,10 @@ mod cross_crate { } fn test_method_object(foo: &Trait) { - foo.trait_deprecated(); //~ ERROR use of deprecated item - foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text - foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item - foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text + foo.trait_deprecated(); //~ WARN use of deprecated item + foo.trait_deprecated_text(); //~ WARN use of deprecated item: text + foo.trait_deprecated_unstable(); //~ WARN use of deprecated item + foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item: text foo.trait_unstable(); foo.trait_unstable_text(); foo.trait_stable(); @@ -187,9 +187,9 @@ mod cross_crate { struct S; impl UnstableTrait for S { } - impl DeprecatedTrait for S {} //~ ERROR use of deprecated item: text + impl DeprecatedTrait for S {} //~ WARN use of deprecated item: text trait LocalTrait : UnstableTrait { } - trait LocalTrait2 : DeprecatedTrait { } //~ ERROR use of deprecated item: text + trait LocalTrait2 : DeprecatedTrait { } //~ WARN use of deprecated item: text impl Trait for S { fn trait_stable(&self) {} @@ -208,7 +208,7 @@ mod inheritance { stable_mod::unstable(); stable_mod::stable(); - unstable_mod::deprecated(); //~ ERROR use of deprecated item + unstable_mod::deprecated(); //~ WARN use of deprecated item unstable_mod::unstable(); let _ = Unstable::UnstableVariant; @@ -330,23 +330,23 @@ mod this_crate { type Foo = MethodTester; let foo = MethodTester; - deprecated(); //~ ERROR use of deprecated item - foo.method_deprecated(); //~ ERROR use of deprecated item - Foo::method_deprecated(&foo); //~ ERROR use of deprecated item - ::method_deprecated(&foo); //~ ERROR use of deprecated item - foo.trait_deprecated(); //~ ERROR use of deprecated item - Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item - ::trait_deprecated(&foo); //~ ERROR use of deprecated item - ::trait_deprecated(&foo); //~ ERROR use of deprecated item + deprecated(); //~ WARN use of deprecated item + foo.method_deprecated(); //~ WARN use of deprecated item + Foo::method_deprecated(&foo); //~ WARN use of deprecated item + ::method_deprecated(&foo); //~ WARN use of deprecated item + foo.trait_deprecated(); //~ WARN use of deprecated item + Trait::trait_deprecated(&foo); //~ WARN use of deprecated item + ::trait_deprecated(&foo); //~ WARN use of deprecated item + ::trait_deprecated(&foo); //~ WARN use of deprecated item - deprecated_text(); //~ ERROR use of deprecated item: text - foo.method_deprecated_text(); //~ ERROR use of deprecated item: text - Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text - ::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text - foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text - Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text - ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text - ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + deprecated_text(); //~ WARN use of deprecated item: text + foo.method_deprecated_text(); //~ WARN use of deprecated item: text + Foo::method_deprecated_text(&foo); //~ WARN use of deprecated item: text + ::method_deprecated_text(&foo); //~ WARN use of deprecated item: text + foo.trait_deprecated_text(); //~ WARN use of deprecated item: text + Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text unstable(); foo.method_unstable(); @@ -385,34 +385,34 @@ mod this_crate { ::trait_stable_text(&foo); let _ = DeprecatedStruct { - //~^ ERROR use of deprecated item - i: 0 //~ ERROR use of deprecated item + //~^ WARN use of deprecated item + i: 0 //~ WARN use of deprecated item }; let _ = UnstableStruct { i: 0 }; let _ = StableStruct { i: 0 }; - let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item + let _ = DeprecatedUnitStruct; //~ WARN use of deprecated item let _ = UnstableUnitStruct; let _ = StableUnitStruct; - let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item + let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated item let _ = Enum::UnstableVariant; let _ = Enum::StableVariant; - let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item + let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated item let _ = UnstableTupleStruct (1); let _ = StableTupleStruct (1); } fn test_method_param(foo: Foo) { - foo.trait_deprecated(); //~ ERROR use of deprecated item - Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item - ::trait_deprecated(&foo); //~ ERROR use of deprecated item - ::trait_deprecated(&foo); //~ ERROR use of deprecated item - foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text - Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text - ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text - ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + foo.trait_deprecated(); //~ WARN use of deprecated item + Trait::trait_deprecated(&foo); //~ WARN use of deprecated item + ::trait_deprecated(&foo); //~ WARN use of deprecated item + ::trait_deprecated(&foo); //~ WARN use of deprecated item + foo.trait_deprecated_text(); //~ WARN use of deprecated item: text + Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text foo.trait_unstable(); Trait::trait_unstable(&foo); ::trait_unstable(&foo); @@ -428,8 +428,8 @@ mod this_crate { } fn test_method_object(foo: &Trait) { - foo.trait_deprecated(); //~ ERROR use of deprecated item - foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text + foo.trait_deprecated(); //~ WARN use of deprecated item + foo.trait_deprecated_text(); //~ WARN use of deprecated item: text foo.trait_unstable(); foo.trait_unstable_text(); foo.trait_stable(); @@ -439,7 +439,7 @@ mod this_crate { #[rustc_deprecated(since = "1.0.0", reason = "text")] fn test_fn_body() { fn fn_in_body() {} - fn_in_body(); //~ ERROR use of deprecated item: text + fn_in_body(); //~ WARN use of deprecated item: text } impl MethodTester { @@ -447,7 +447,7 @@ mod this_crate { #[rustc_deprecated(since = "1.0.0", reason = "text")] fn test_method_body(&self) { fn fn_in_body() {} - fn_in_body(); //~ ERROR use of deprecated item: text + fn_in_body(); //~ WARN use of deprecated item: text } } @@ -459,9 +459,9 @@ mod this_crate { struct S; - impl DeprecatedTrait for S { } //~ ERROR use of deprecated item + impl DeprecatedTrait for S { } //~ WARN use of deprecated item - trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated item + trait LocalTrait : DeprecatedTrait { } //~ WARN use of deprecated item } -fn main() {} +#[rustc_error] fn main() {} //~ ERROR: compilation successful diff --git a/src/test/compile-fail/lint-type-overflow2.rs b/src/test/compile-fail/lint-type-overflow2.rs index d399fda32862..559349975834 100644 --- a/src/test/compile-fail/lint-type-overflow2.rs +++ b/src/test/compile-fail/lint-type-overflow2.rs @@ -9,16 +9,18 @@ // except according to those terms. // -#![deny(overflowing_literals)] -#![deny(const_err)] +#![warn(overflowing_literals)] +#![warn(const_err)] +#![feature(rustc_attrs)] #[allow(unused_variables)] -fn main() { - let x2: i8 = --128; //~ error: literal out of range for i8 - //~^ error: attempt to negate with overflow +#[rustc_error] +fn main() { //~ ERROR: compilation successful + let x2: i8 = --128; //~ warn: literal out of range for i8 + //~^ warn: attempt to negate with overflow - let x = -3.40282357e+38_f32; //~ error: literal out of range for f32 - let x = 3.40282357e+38_f32; //~ error: literal out of range for f32 - let x = -1.7976931348623159e+308_f64; //~ error: literal out of range for f64 - let x = 1.7976931348623159e+308_f64; //~ error: literal out of range for f64 + let x = -3.40282357e+38_f32; //~ warn: literal out of range for f32 + let x = 3.40282357e+38_f32; //~ warn: literal out of range for f32 + let x = -1.7976931348623159e+308_f64; //~ warn: literal out of range for f64 + let x = 1.7976931348623159e+308_f64; //~ warn: literal out of range for f64 } diff --git a/src/test/compile-fail/lint-uppercase-variables.rs b/src/test/compile-fail/lint-uppercase-variables.rs index 1615af400713..1d947684792d 100644 --- a/src/test/compile-fail/lint-uppercase-variables.rs +++ b/src/test/compile-fail/lint-uppercase-variables.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![warn(unused)] #![allow(dead_code)] #![deny(non_snake_case)] diff --git a/src/test/compile-fail/liveness-unused.rs b/src/test/compile-fail/liveness-unused.rs index 3aab953eb794..d056d6be806f 100644 --- a/src/test/compile-fail/liveness-unused.rs +++ b/src/test/compile-fail/liveness-unused.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![warn(unused)] #![deny(unused_variables)] #![deny(unused_assignments)] #![allow(dead_code, non_camel_case_types, trivial_numeric_casts)] diff --git a/src/test/compile-fail/never-assign-dead-code.rs b/src/test/compile-fail/never-assign-dead-code.rs index d8752e1c050f..1e0cc0f5357f 100644 --- a/src/test/compile-fail/never-assign-dead-code.rs +++ b/src/test/compile-fail/never-assign-dead-code.rs @@ -10,12 +10,12 @@ // Test that an assignment of type ! makes the rest of the block dead code. -#![feature(never_type)] -#![deny(unused, unreachable_code)] +#![feature(never_type, rustc_attrs)] +#![warn(unused)] -fn main() { - let x: ! = panic!("aah"); //~ ERROR unused - drop(x); //~ ERROR unreachable - //~^ ERROR unreachable +#[rustc_error] +fn main() { //~ ERROR: compilation successful + let x: ! = panic!("aah"); //~ WARN unused + drop(x); //~ WARN unreachable + //~^ WARN unreachable } - diff --git a/src/test/compile-fail/private-inferred-type.rs b/src/test/compile-fail/private-inferred-type.rs index 140891027d5f..4d41f8ba47d0 100644 --- a/src/test/compile-fail/private-inferred-type.rs +++ b/src/test/compile-fail/private-inferred-type.rs @@ -11,6 +11,7 @@ #![feature(associated_consts)] #![feature(conservative_impl_trait)] #![feature(decl_macro)] +#![allow(warnings)] mod m { fn priv_fn() {} diff --git a/src/test/compile-fail/private-type-in-interface.rs b/src/test/compile-fail/private-type-in-interface.rs index 925d692f8ae6..a5581664f741 100644 --- a/src/test/compile-fail/private-type-in-interface.rs +++ b/src/test/compile-fail/private-type-in-interface.rs @@ -11,6 +11,7 @@ // aux-build:private-inferred-type.rs #![feature(conservative_impl_trait)] +#![allow(warnings)] extern crate private_inferred_type as ext; diff --git a/src/test/compile-fail/static-mut-not-constant.rs b/src/test/compile-fail/static-mut-not-constant.rs index 7c37abf76576..a855b08f0669 100644 --- a/src/test/compile-fail/static-mut-not-constant.rs +++ b/src/test/compile-fail/static-mut-not-constant.rs @@ -14,6 +14,7 @@ static mut a: Box = box 3; //~^ ERROR allocations are not allowed in statics -//~^^ ERROR destructors in statics are an unstable feature +//~| ERROR destructors in statics are an unstable feature +//~| WARN: constant evaluation error fn main() {} diff --git a/src/test/compile-fail/unreachable-try-pattern.rs b/src/test/compile-fail/unreachable-try-pattern.rs index f4817ba33b51..46ea4a06a3bd 100644 --- a/src/test/compile-fail/unreachable-try-pattern.rs +++ b/src/test/compile-fail/unreachable-try-pattern.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(never_type)] -#![deny(unreachable_code)] -#![deny(unreachable_patterns)] +#![feature(never_type, rustc_attrs)] +#![warn(unreachable_code)] +#![warn(unreachable_patterns)] enum Void {} @@ -26,8 +26,8 @@ fn bar(x: Result) -> Result { fn foo(x: Result) -> Result { let y = (match x { Ok(n) => Ok(n as u32), Err(e) => Err(e) })?; - //~^ ERROR unreachable pattern - //~| ERROR unreachable expression + //~^ WARN unreachable pattern + //~| WARN unreachable expression Ok(y) } @@ -37,11 +37,12 @@ fn qux(x: Result) -> Result { fn vom(x: Result) -> Result { let y = (match x { Ok(n) => Ok(n), Err(e) => Err(e) })?; - //~^ ERROR unreachable pattern + //~^ WARN unreachable pattern Ok(y) } -fn main() { +#[rustc_error] +fn main() { //~ ERROR: compilation successful let _ = bar(Err(123)); let _ = foo(Err(123)); let _ = qux(Ok(123)); diff --git a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.rs b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.rs index 1e428629cc2f..19ce23621345 100644 --- a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.rs +++ b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.rs @@ -14,6 +14,7 @@ // compile-flags: -A test-lint #![feature(plugin)] +#![warn(unused)] #![plugin(lint_plugin_test)] fn lintme() { } diff --git a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr index b8513b95d36c..7c9c4e990390 100644 --- a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr +++ b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr @@ -1,8 +1,13 @@ warning: function is never used: `lintme` - --> $DIR/lint-plugin-cmdline-allow.rs:19:1 + --> $DIR/lint-plugin-cmdline-allow.rs:20:1 | -19 | fn lintme() { } +20 | fn lintme() { } | ^^^^^^^^^^^^^^^ | - = note: #[warn(dead_code)] on by default +note: lint level defined here + --> $DIR/lint-plugin-cmdline-allow.rs:17:9 + | +17 | #![warn(unused)] + | ^^^^^^ + = note: #[warn(dead_code)] implied by #[warn(unused)] diff --git a/src/test/ui/check_match/issue-43253.rs b/src/test/ui/check_match/issue-43253.rs index c77fa74f6e0e..108d7e1ea22a 100644 --- a/src/test/ui/check_match/issue-43253.rs +++ b/src/test/ui/check_match/issue-43253.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(exclusive_range_pattern)] +#![warn(unreachable_patterns)] fn main() { // These cases should generate no warning. @@ -48,4 +49,4 @@ fn main() { 9...9 => {}, _ => {}, } -} \ No newline at end of file +} diff --git a/src/test/ui/check_match/issue-43253.stderr b/src/test/ui/check_match/issue-43253.stderr index 0d4a2ecf512d..a1cb3963914c 100644 --- a/src/test/ui/check_match/issue-43253.stderr +++ b/src/test/ui/check_match/issue-43253.stderr @@ -1,20 +1,24 @@ warning: unreachable pattern - --> $DIR/issue-43253.rs:36:9 + --> $DIR/issue-43253.rs:37:9 | -36 | 9 => {}, +37 | 9 => {}, | ^ | - = note: #[warn(unreachable_patterns)] on by default +note: lint level defined here + --> $DIR/issue-43253.rs:12:9 + | +12 | #![warn(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ warning: unreachable pattern - --> $DIR/issue-43253.rs:42:9 + --> $DIR/issue-43253.rs:43:9 | -42 | 8...9 => {}, +43 | 8...9 => {}, | ^^^^^ warning: unreachable pattern - --> $DIR/issue-43253.rs:48:9 + --> $DIR/issue-43253.rs:49:9 | -48 | 9...9 => {}, +49 | 9...9 => {}, | ^^^^^ diff --git a/src/test/ui/compare-method/proj-outlives-region.stderr b/src/test/ui/compare-method/proj-outlives-region.stderr index b1b5aedea70d..e58251c846f8 100644 --- a/src/test/ui/compare-method/proj-outlives-region.stderr +++ b/src/test/ui/compare-method/proj-outlives-region.stderr @@ -1,4 +1,4 @@ -error[E0276]: impl has stricter requirements than trait +error: impl has stricter requirements than trait --> $DIR/proj-outlives-region.rs:19:5 | 14 | fn foo() where T: 'a; diff --git a/src/test/ui/compare-method/region-unrelated.stderr b/src/test/ui/compare-method/region-unrelated.stderr index b02aa5eeb2f5..95db68fea5cf 100644 --- a/src/test/ui/compare-method/region-unrelated.stderr +++ b/src/test/ui/compare-method/region-unrelated.stderr @@ -1,4 +1,4 @@ -error[E0276]: impl has stricter requirements than trait +error: impl has stricter requirements than trait --> $DIR/region-unrelated.rs:19:5 | 14 | fn foo() where T: 'a; diff --git a/src/test/ui/lint/fn_must_use.rs b/src/test/ui/lint/fn_must_use.rs index ea2197f3fd1a..5aea5f2ca064 100644 --- a/src/test/ui/lint/fn_must_use.rs +++ b/src/test/ui/lint/fn_must_use.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![warn(unused_must_use)] struct MyStruct { n: usize diff --git a/src/test/ui/lint/fn_must_use.stderr b/src/test/ui/lint/fn_must_use.stderr index 7057c8e9aaad..20eb7452aea7 100644 --- a/src/test/ui/lint/fn_must_use.stderr +++ b/src/test/ui/lint/fn_must_use.stderr @@ -1,14 +1,18 @@ warning: unused return value of `need_to_use_this_value` which must be used: it's important - --> $DIR/fn_must_use.rs:29:5 + --> $DIR/fn_must_use.rs:30:5 | -29 | need_to_use_this_value(); +30 | need_to_use_this_value(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[warn(unused_must_use)] on by default +note: lint level defined here + --> $DIR/fn_must_use.rs:11:9 + | +11 | #![warn(unused_must_use)] + | ^^^^^^^^^^^^^^^ warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used - --> $DIR/fn_must_use.rs:32:5 + --> $DIR/fn_must_use.rs:33:5 | -32 | m.need_to_use_this_method_value(); +33 | m.need_to_use_this_method_value(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/lint/outer-forbid.rs b/src/test/ui/lint/outer-forbid.rs index d71da58829a7..a79dacbc1c95 100644 --- a/src/test/ui/lint/outer-forbid.rs +++ b/src/test/ui/lint/outer-forbid.rs @@ -16,7 +16,13 @@ #![forbid(unused, non_snake_case)] -#[allow(unused, unused_variables, bad_style)] +#[allow(unused_variables)] +fn foo() {} + +#[allow(unused)] +fn bar() {} + +#[allow(bad_style)] fn main() { println!("hello forbidden world") } diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr index df62f5acc007..67a1f4f88adc 100644 --- a/src/test/ui/lint/outer-forbid.stderr +++ b/src/test/ui/lint/outer-forbid.stderr @@ -1,29 +1,29 @@ -error[E0453]: allow(unused) overruled by outer forbid(unused) +error[E0453]: allow(unused_variables) overruled by outer forbid(unused) --> $DIR/outer-forbid.rs:19:9 | 17 | #![forbid(unused, non_snake_case)] | ------ `forbid` level set here 18 | -19 | #[allow(unused, unused_variables, bad_style)] - | ^^^^^^ overruled by previous forbid +19 | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid -error[E0453]: allow(unused_variables) overruled by outer forbid(unused) - --> $DIR/outer-forbid.rs:19:17 +error[E0453]: allow(unused) overruled by outer forbid(unused) + --> $DIR/outer-forbid.rs:22:9 | 17 | #![forbid(unused, non_snake_case)] | ------ `forbid` level set here -18 | -19 | #[allow(unused, unused_variables, bad_style)] - | ^^^^^^^^^^^^^^^^ overruled by previous forbid +... +22 | #[allow(unused)] + | ^^^^^^ overruled by previous forbid error[E0453]: allow(bad_style) overruled by outer forbid(non_snake_case) - --> $DIR/outer-forbid.rs:19:35 + --> $DIR/outer-forbid.rs:25:9 | 17 | #![forbid(unused, non_snake_case)] | -------------- `forbid` level set here -18 | -19 | #[allow(unused, unused_variables, bad_style)] - | ^^^^^^^^^ overruled by previous forbid +... +25 | #[allow(bad_style)] + | ^^^^^^^^^ overruled by previous forbid error: aborting due to 3 previous errors diff --git a/src/test/ui/path-lookahead.rs b/src/test/ui/path-lookahead.rs index c43f2229cdc3..367a25601555 100644 --- a/src/test/ui/path-lookahead.rs +++ b/src/test/ui/path-lookahead.rs @@ -10,6 +10,8 @@ // run-pass +#![warn(unused)] + // Parser test for #37765 fn with_parens(arg: T) -> String { //~WARN function is never used: `with_parens` diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr index 8fd1b8de6878..9936a1eb81e2 100644 --- a/src/test/ui/path-lookahead.stderr +++ b/src/test/ui/path-lookahead.stderr @@ -1,26 +1,31 @@ warning: unnecessary parentheses around `return` value - --> $DIR/path-lookahead.rs:16:10 + --> $DIR/path-lookahead.rs:18:10 | -16 | return (::to_string(&arg)); //~WARN unnecessary parentheses around `return` value +18 | return (::to_string(&arg)); //~WARN unnecessary parentheses around `return` value | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: #[warn(unused_parens)] on by default warning: function is never used: `with_parens` - --> $DIR/path-lookahead.rs:15:1 + --> $DIR/path-lookahead.rs:17:1 | -15 | / fn with_parens(arg: T) -> String { //~WARN function is never used: `with_parens` -16 | | return (::to_string(&arg)); //~WARN unnecessary parentheses around `return` value -17 | | } +17 | / fn with_parens(arg: T) -> String { //~WARN function is never used: `with_parens` +18 | | return (::to_string(&arg)); //~WARN unnecessary parentheses around `return` value +19 | | } | |_^ | - = note: #[warn(dead_code)] on by default +note: lint level defined here + --> $DIR/path-lookahead.rs:13:9 + | +13 | #![warn(unused)] + | ^^^^^^ + = note: #[warn(dead_code)] implied by #[warn(unused)] warning: function is never used: `no_parens` - --> $DIR/path-lookahead.rs:19:1 + --> $DIR/path-lookahead.rs:21:1 | -19 | / fn no_parens(arg: T) -> String { //~WARN function is never used: `no_parens` -20 | | return ::to_string(&arg); -21 | | } +21 | / fn no_parens(arg: T) -> String { //~WARN function is never used: `no_parens` +22 | | return ::to_string(&arg); +23 | | } | |_^ diff --git a/src/test/ui/reachable/expr_unary.stderr b/src/test/ui/reachable/expr_unary.stderr index 328b75fd236b..9f4562fe2971 100644 --- a/src/test/ui/reachable/expr_unary.stderr +++ b/src/test/ui/reachable/expr_unary.stderr @@ -1,8 +1,20 @@ +error: unreachable expression + --> $DIR/expr_unary.rs:18:28 + | +18 | let x: ! = ! { return; 22 }; + | ^^ + | +note: lint level defined here + --> $DIR/expr_unary.rs:14:9 + | +14 | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + error[E0600]: cannot apply unary operator `!` to type `!` --> $DIR/expr_unary.rs:18:16 | 18 | let x: ! = ! { return; 22 }; | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-24690.rs b/src/test/ui/span/issue-24690.rs index def0d9aced3c..f59d2845108f 100644 --- a/src/test/ui/span/issue-24690.rs +++ b/src/test/ui/span/issue-24690.rs @@ -11,10 +11,13 @@ //! A test to ensure that helpful `note` messages aren't emitted more often //! than necessary. -// Although there are three errors, we should only get two "lint level defined -// here" notes pointing at the `warnings` span, one for each error type. -#![deny(warnings)] +#![feature(rustc_attrs)] +// Although there are three warnings, we should only get two "lint level defined +// here" notes pointing at the `warnings` span, one for each error type. +#![warn(unused)] + +#[rustc_error] fn main() { let theTwo = 2; let theOtherTwo = 2; diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr index 8332ba50a73d..4f1c870d8745 100644 --- a/src/test/ui/span/issue-24690.stderr +++ b/src/test/ui/span/issue-24690.stderr @@ -1,34 +1,37 @@ -error: variable `theTwo` should have a snake case name such as `the_two` - --> $DIR/issue-24690.rs:19:9 +warning: unused variable: `theOtherTwo` + --> $DIR/issue-24690.rs:23:9 | -19 | let theTwo = 2; +23 | let theOtherTwo = 2; + | ^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/issue-24690.rs:18:9 + | +18 | #![warn(unused)] + | ^^^^^^ + = note: #[warn(unused_variables)] implied by #[warn(unused)] + +warning: variable `theTwo` should have a snake case name such as `the_two` + --> $DIR/issue-24690.rs:22:9 + | +22 | let theTwo = 2; | ^^^^^^ | -note: lint level defined here - --> $DIR/issue-24690.rs:16:9 - | -16 | #![deny(warnings)] - | ^^^^^^^^ - = note: #[deny(non_snake_case)] implied by #[deny(warnings)] + = note: #[warn(non_snake_case)] on by default -error: variable `theOtherTwo` should have a snake case name such as `the_other_two` - --> $DIR/issue-24690.rs:20:9 +warning: variable `theOtherTwo` should have a snake case name such as `the_other_two` + --> $DIR/issue-24690.rs:23:9 | -20 | let theOtherTwo = 2; +23 | let theOtherTwo = 2; | ^^^^^^^^^^^ -error: unused variable: `theOtherTwo` - --> $DIR/issue-24690.rs:20:9 +error: compilation successful + --> $DIR/issue-24690.rs:21:1 | -20 | let theOtherTwo = 2; - | ^^^^^^^^^^^ - | -note: lint level defined here - --> $DIR/issue-24690.rs:16:9 - | -16 | #![deny(warnings)] - | ^^^^^^^^ - = note: #[deny(unused_variables)] implied by #[deny(warnings)] - -error: aborting due to 3 previous errors +21 | / fn main() { +22 | | let theTwo = 2; +23 | | let theOtherTwo = 2; +24 | | println!("{}", theTwo); +25 | | } + | |_^ diff --git a/src/test/ui/span/macro-span-replacement.rs b/src/test/ui/span/macro-span-replacement.rs index d779bec4ace5..b7aae39c4692 100644 --- a/src/test/ui/span/macro-span-replacement.rs +++ b/src/test/ui/span/macro-span-replacement.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![warn(unused)] + macro_rules! m { ($a:tt $b:tt) => { $b $a; diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr index e7336697f48e..af03aa6a3690 100644 --- a/src/test/ui/span/macro-span-replacement.stderr +++ b/src/test/ui/span/macro-span-replacement.stderr @@ -1,11 +1,16 @@ warning: struct is never used: `S` - --> $DIR/macro-span-replacement.rs:13:9 + --> $DIR/macro-span-replacement.rs:15:9 | -13 | $b $a; +15 | $b $a; | ^^^^^^ ... -18 | m!(S struct); +20 | m!(S struct); | ------------- in this macro invocation | - = note: #[warn(dead_code)] on by default +note: lint level defined here + --> $DIR/macro-span-replacement.rs:11:9 + | +11 | #![warn(unused)] + | ^^^^^^ + = note: #[warn(dead_code)] implied by #[warn(unused)] diff --git a/src/test/ui/span/multispan-import-lint.rs b/src/test/ui/span/multispan-import-lint.rs index 43b6cd8f85f8..66536b29c029 100644 --- a/src/test/ui/span/multispan-import-lint.rs +++ b/src/test/ui/span/multispan-import-lint.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![warn(unused)] + use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd}; fn main() { diff --git a/src/test/ui/span/multispan-import-lint.stderr b/src/test/ui/span/multispan-import-lint.stderr index 4b1ca7f98bbf..1fecdea7d0d0 100644 --- a/src/test/ui/span/multispan-import-lint.stderr +++ b/src/test/ui/span/multispan-import-lint.stderr @@ -1,8 +1,13 @@ warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd` - --> $DIR/multispan-import-lint.rs:11:16 + --> $DIR/multispan-import-lint.rs:13:16 | -11 | use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd}; +13 | use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd}; | ^^ ^^^ ^^^^^^^^^ ^^^^^^^^^^ | - = note: #[warn(unused_imports)] on by default +note: lint level defined here + --> $DIR/multispan-import-lint.rs:11:9 + | +11 | #![warn(unused)] + | ^^^^^^ + = note: #[warn(unused_imports)] implied by #[warn(unused)] diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 936965617087..769748c63c02 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1156,9 +1156,21 @@ actual:\n\ fn compile_test(&self) -> ProcRes { let aux_dir = self.aux_output_dir_name(); // FIXME (#9639): This needs to handle non-utf8 paths - let link_args = vec!["-L".to_owned(), - aux_dir.to_str().unwrap().to_owned()]; - let args = self.make_compile_args(link_args, + let mut extra_args = vec!["-L".to_owned(), + aux_dir.to_str().unwrap().to_owned()]; + match self.config.mode { + CompileFail | Ui => { + // compile-fail and ui tests tend to have tons of unused code as + // it's just testing various pieces of the compile, but we don't + // want to actually assert warnings about all this code. Instead + // let's just ignore unused code warnings by defaults and tests + // can turn it back on if needed. + extra_args.push("-A".to_owned()); + extra_args.push("unused".to_owned()); + } + _ => {} + } + let args = self.make_compile_args(extra_args, &self.testpaths.file, TargetLocation::ThisFile(self.make_exe_name())); self.compose_and_run_compiler(args, None) From 9bd62a4691346a30f7aa26cf3b6d726695cf7eee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 9 Aug 2017 09:57:28 -0700 Subject: [PATCH 51/56] Readd backticks around () --- src/librustc_typeck/check/mod.rs | 19 ++++--------------- .../block-must-not-have-result-res.stderr | 2 +- src/test/ui/block-result/issue-13624.stderr | 2 +- src/test/ui/block-result/issue-22645.stderr | 2 +- src/test/ui/block-result/issue-5500.stderr | 2 +- 5 files changed, 8 insertions(+), 19 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7c8eb77380f0..8e363eee24d4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -95,7 +95,7 @@ use rustc::middle::region::CodeExtent; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode}; use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue}; -use rustc::ty::{self, Ty, TyCtxt, Visibility, TypeVariants}; +use rustc::ty::{self, Ty, TyCtxt, Visibility}; use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; use rustc::ty::maps::Providers; @@ -4315,7 +4315,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } (&hir::FunctionRetTy::DefaultReturn(span), _, _) => { // `fn main()` must return `()`, do not suggest changing return type - err.span_label(span, "expected () because of default return type"); + err.span_label(span, "expected `()` because of default return type"); } (&hir::FunctionRetTy::Return(ref ty), _, _) => { // Only point to return type if the expected type is the return type, as if they @@ -4326,19 +4326,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!("suggest_missing_return_type: return type sty {:?}", ty.sty); debug!("suggest_missing_return_type: expected type sty {:?}", ty.sty); if ty.sty == expected.sty { - let quote = if let TypeVariants::TyTuple(ref slice, _) = expected.sty { - if slice.len() == 0 { // don't use backtics for () - "" - } else { - "`" - } - } else { - "`" - }; - err.span_label(sp, format!("expected {}{}{} because of return type", - quote, - expected, - quote)); + err.span_label(sp, format!("expected `{}` because of return type", + expected)); } } } diff --git a/src/test/ui/block-result/block-must-not-have-result-res.stderr b/src/test/ui/block-result/block-must-not-have-result-res.stderr index 6432375fe709..20c7dc416f3b 100644 --- a/src/test/ui/block-result/block-must-not-have-result-res.stderr +++ b/src/test/ui/block-result/block-must-not-have-result-res.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/block-must-not-have-result-res.rs:15:9 | 14 | fn drop(&mut self) { - | - expected () because of default return type + | - expected `()` because of default return type 15 | true //~ ERROR mismatched types | ^^^^ expected (), found bool | diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr index 8fe4a5125741..cd8c28cd2cfa 100644 --- a/src/test/ui/block-result/issue-13624.stderr +++ b/src/test/ui/block-result/issue-13624.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-13624.rs:17:5 | 16 | pub fn get_enum_struct_variant() -> () { - | -- expected () because of return type + | -- expected `()` because of return type 17 | Enum::EnumStructVariant { x: 1, y: 2, z: 3 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` | diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr index ad39e38cab63..c6113ae0c9f6 100644 --- a/src/test/ui/block-result/issue-22645.stderr +++ b/src/test/ui/block-result/issue-22645.stderr @@ -12,7 +12,7 @@ error[E0308]: mismatched types --> $DIR/issue-22645.rs:25:3 | 23 | fn main() { - | - expected () because of default return type + | - expected `()` because of default return type 24 | let b = Bob + 3.5; 25 | b + 3 //~ ERROR E0277 | ^^^^^ expected (), found struct `Bob` diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr index 944391c1719c..29dbd5a8cf59 100644 --- a/src/test/ui/block-result/issue-5500.stderr +++ b/src/test/ui/block-result/issue-5500.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-5500.rs:12:5 | 11 | fn main() { - | - expected () because of default return type + | - expected `()` because of default return type 12 | &panic!() | ^^^^^^^^^ expected (), found reference | From a9a181d4dcac6d5e347ef7157e91877fac648c56 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 8 Aug 2017 17:10:08 +1200 Subject: [PATCH 52/56] driver: factor out `continue_parse_after_error` so it can be controlled via driver API --- src/librustc_driver/driver.rs | 23 +++++++++++++++-------- src/librustc_driver/lib.rs | 1 + src/librustc_driver/test.rs | 4 +++- src/librustdoc/core.rs | 4 +++- src/librustdoc/test.rs | 4 +++- 5 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 12cb556afdab..22f98454f6c4 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -89,7 +89,7 @@ pub fn compile_input(sess: &Session, // large chunks of memory alive and we want to free them as soon as // possible to keep the peak memory usage low let (outputs, trans) = { - let krate = match phase_1_parse_input(sess, input) { + let krate = match phase_1_parse_input(control, sess, input) { Ok(krate) => krate, Err(mut parse_error) => { parse_error.emit(); @@ -296,9 +296,13 @@ pub struct CompileController<'a> { pub after_llvm: PhaseController<'a>, pub compilation_done: PhaseController<'a>, + // FIXME we probably want to group the below options together and offer a + // better API, rather than this ad-hoc approach. pub make_glob_map: MakeGlobMap, // Whether the compiler should keep the ast beyond parsing. pub keep_ast: bool, + // -Zcontinue-parse-after-error + pub continue_parse_after_error: bool, } impl<'a> CompileController<'a> { @@ -312,6 +316,7 @@ impl<'a> CompileController<'a> { compilation_done: PhaseController::basic(), make_glob_map: MakeGlobMap::No, keep_ast: false, + continue_parse_after_error: false, } } } @@ -484,10 +489,10 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { } fn state_when_compilation_done(input: &'a Input, - session: &'tcx Session, - out_dir: &'a Option, - out_file: &'a Option) - -> Self { + session: &'tcx Session, + out_dir: &'a Option, + out_file: &'a Option) + -> Self { CompileState { out_file: out_file.as_ref().map(|s| &**s), ..CompileState::empty(input, session, out_dir) @@ -495,9 +500,11 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { } } -pub fn phase_1_parse_input<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> { - let continue_after_error = sess.opts.debugging_opts.continue_parse_after_error; - sess.diagnostic().set_continue_after_error(continue_after_error); +pub fn phase_1_parse_input<'a>(control: &CompileController, + sess: &'a Session, + input: &Input) + -> PResult<'a, ast::Crate> { + sess.diagnostic().set_continue_after_error(control.continue_parse_after_error); let krate = time(sess.time_passes(), "parsing", || { match *input { diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index b4b7446f753d..a3c2957ff90d 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -519,6 +519,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { let mut control = CompileController::basic(); control.keep_ast = sess.opts.debugging_opts.keep_ast; + control.continue_parse_after_error = sess.opts.debugging_opts.continue_parse_after_error; if let Some((ppm, opt_uii)) = parse_pretty(sess, matches) { if ppm.needs_ast_map(&opt_uii) { diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 62e20a90f8a0..8668ab301543 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -119,7 +119,9 @@ fn test_env(source_string: &str, name: driver::anon_src(), input: source_string.to_string(), }; - let krate = driver::phase_1_parse_input(&sess, &input).unwrap(); + let krate = driver::phase_1_parse_input(&driver::CompileController::basic(), + &sess, + &input).unwrap(); let driver::ExpansionResult { defs, resolutions, mut hir_forest, .. } = { driver::phase_2_configure_and_expand(&sess, &cstore, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 62b91feb09d0..e101e29fc6fb 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -155,7 +155,9 @@ pub fn run_core(search_paths: SearchPaths, target_features::add_configuration(&mut cfg, &sess); sess.parse_sess.config = cfg; - let krate = panictry!(driver::phase_1_parse_input(&sess, &input)); + let krate = panictry!(driver::phase_1_parse_input(&driver::CompileController::basic(), + &sess, + &input)); let name = link::find_crate_name(Some(&sess), &krate.attrs, &input); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index f012fd974b57..b1e92b5190f3 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -91,7 +91,9 @@ pub fn run(input: &str, sess.parse_sess.config = config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone())); - let krate = panictry!(driver::phase_1_parse_input(&sess, &input)); + let krate = panictry!(driver::phase_1_parse_input(&driver::CompileController::basic(), + &sess, + &input)); let driver::ExpansionResult { defs, mut hir_forest, .. } = { phase_2_configure_and_expand( &sess, &cstore, krate, None, "rustdoc-test", None, MakeGlobMap::No, |_| Ok(()) From a965beef8f362e1db47eadd0ff701ec57cc23cfe Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 10 Aug 2017 01:43:06 +0300 Subject: [PATCH 53/56] Better diagnostics and recovery for `const` in extern blocks --- src/libsyntax/parse/parser.rs | 24 ++++++++++++------------ src/test/ui/extern-const.rs | 19 +++++++++++++++++++ src/test/ui/extern-const.stderr | 8 ++++++++ 3 files changed, 39 insertions(+), 12 deletions(-) create mode 100644 src/test/ui/extern-const.rs create mode 100644 src/test/ui/extern-const.stderr diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c34317e649d8..cb28f356fe6f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5518,12 +5518,11 @@ impl<'a> Parser<'a> { }) } - /// Parse a static item from a foreign module + /// Parse a static item from a foreign module. + /// Assumes that the `static` keyword is already parsed. fn parse_item_foreign_static(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec) -> PResult<'a, ForeignItem> { - self.expect_keyword(keywords::Static)?; let mutbl = self.eat_keyword(keywords::Mut); - let ident = self.parse_ident()?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; @@ -5997,21 +5996,22 @@ impl<'a> Parser<'a> { let lo = self.span; let visibility = self.parse_visibility(false)?; - if self.check_keyword(keywords::Static) { - // FOREIGN STATIC ITEM + // FOREIGN STATIC ITEM + // Treat `const` as `static` for error recovery, but don't add it to expected tokens. + if self.check_keyword(keywords::Static) || self.token.is_keyword(keywords::Const) { + if self.token.is_keyword(keywords::Const) { + self.diagnostic() + .struct_span_err(self.span, "extern items cannot be `const`") + .span_label(self.span, "use `static` instead").emit(); + } + self.bump(); // `static` or `const` return Ok(Some(self.parse_item_foreign_static(visibility, lo, attrs)?)); } + // FOREIGN FUNCTION ITEM if self.check_keyword(keywords::Fn) { - // FOREIGN FUNCTION ITEM return Ok(Some(self.parse_item_foreign_fn(visibility, lo, attrs)?)); } - if self.check_keyword(keywords::Const) { - let mut err = self.span_fatal(self.span, "extern items cannot be `const`"); - err.help("use `static` instead"); - return Err(err); - } - // FIXME #5668: this will occur for a macro invocation: match self.parse_macro_use_or_failure(attrs, true, false, lo, visibility)? { Some(item) => { diff --git a/src/test/ui/extern-const.rs b/src/test/ui/extern-const.rs new file mode 100644 index 000000000000..a77d7b118956 --- /dev/null +++ b/src/test/ui/extern-const.rs @@ -0,0 +1,19 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z continue-parse-after-error + +extern "C" { + const C: u8; //~ ERROR extern items cannot be `const` +} + +fn main() { + let x = C; +} diff --git a/src/test/ui/extern-const.stderr b/src/test/ui/extern-const.stderr new file mode 100644 index 000000000000..e6c41a05594e --- /dev/null +++ b/src/test/ui/extern-const.stderr @@ -0,0 +1,8 @@ +error: extern items cannot be `const` + --> $DIR/extern-const.rs:14:5 + | +14 | const C: u8; //~ ERROR extern items cannot be `const` + | ^^^^^ use `static` instead + +error: aborting due to previous error + From 5cf9f6330a02a0e86f08223289c74b36fba784db Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 10 Aug 2017 01:42:36 +0200 Subject: [PATCH 54/56] Add a feature gate @alexcrichton figured out a way how to do it :) --- src/libsyntax/ext/source_util.rs | 10 ++++++++++ src/libsyntax_ext/lib.rs | 2 +- .../compile-fail/rust-unstable-column-gated.rs | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/rust-unstable-column-gated.rs diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 3cdd3a4b2c31..b293aa8de38b 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -52,6 +52,16 @@ pub fn expand_column(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree]) base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32)) } +/* __rust_unstable_column!(): expands to the current column number */ +pub fn expand_column_gated(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree]) + -> Box { + if sp.allows_unstable() { + expand_column(cx, sp, tts) + } else { + cx.span_fatal(sp, "the __rust_unstable_column macro is unstable"); + } +} + /// file!(): expands to the current filename */ /// The filemap (`loc.file`) contains a bunch more information we could spit /// out if we wanted. diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 558d2e90310f..5eab81dd28fc 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -89,7 +89,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, use syntax::ext::source_util::*; register! { line: expand_line, - __rust_unstable_column: expand_column, + __rust_unstable_column: expand_column_gated, column: expand_column, file: expand_file, stringify: expand_stringify, diff --git a/src/test/compile-fail/rust-unstable-column-gated.rs b/src/test/compile-fail/rust-unstable-column-gated.rs new file mode 100644 index 000000000000..abc92c86eec6 --- /dev/null +++ b/src/test/compile-fail/rust-unstable-column-gated.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + println!("{}", __rust_unstable_column!()); + //~^ERROR the __rust_unstable_column macro is unstable +} From 8f78d453ded152e95d66f113d24287f12c680a15 Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Thu, 10 Aug 2017 02:00:48 +0100 Subject: [PATCH 55/56] Updated cargo submodule to fix compile error --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 305bc25d5e10..7704f7b1fd52 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 305bc25d5e105e84ffe261655b46cf74570f6e5b +Subproject commit 7704f7b1fd52607104cc7fdc435d636c9de1fe90 From cabc9be9e2057c5197db273ba0c750aad5ff3366 Mon Sep 17 00:00:00 2001 From: Kornel Date: Thu, 10 Aug 2017 12:16:01 +0100 Subject: [PATCH 56/56] Reword error hint --- src/libsyntax/parse/parser.rs | 3 ++- src/test/ui/extern-const.stderr | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index cb28f356fe6f..7bf4c6799b3c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6002,7 +6002,8 @@ impl<'a> Parser<'a> { if self.token.is_keyword(keywords::Const) { self.diagnostic() .struct_span_err(self.span, "extern items cannot be `const`") - .span_label(self.span, "use `static` instead").emit(); + .span_suggestion(self.span, "instead try using", "static".to_owned()) + .emit(); } self.bump(); // `static` or `const` return Ok(Some(self.parse_item_foreign_static(visibility, lo, attrs)?)); diff --git a/src/test/ui/extern-const.stderr b/src/test/ui/extern-const.stderr index e6c41a05594e..c5a3149e85a7 100644 --- a/src/test/ui/extern-const.stderr +++ b/src/test/ui/extern-const.stderr @@ -2,7 +2,7 @@ error: extern items cannot be `const` --> $DIR/extern-const.rs:14:5 | 14 | const C: u8; //~ ERROR extern items cannot be `const` - | ^^^^^ use `static` instead + | ^^^^^ help: instead try using: `static` error: aborting due to previous error