]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #43766 - michaelwoerister:trans-scheduler-touch-up, r=alexcrichton
authorbors <bors@rust-lang.org>
Fri, 11 Aug 2017 22:23:10 +0000 (22:23 +0000)
committerbors <bors@rust-lang.org>
Fri, 11 Aug 2017 22:23:10 +0000 (22:23 +0000)
Improve LLVM/trans scheduling a bit

Currently it's possible that the main thread is waiting on LLVM threads to finish work while its implicit token is going to waste. This PR let's the main thread take over, so one of the running LLVM threads can free its token earlier.

r? @alexcrichton

223 files changed:
RELEASES.md
src/Cargo.lock
src/bootstrap/config.rs
src/bootstrap/config.toml.example
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/liballoc/arc.rs
src/liballoc/btree/node.rs
src/liballoc/string.rs
src/liballoc/vec.rs
src/liballoc/vec_deque.rs
src/libcore/intrinsics.rs
src/libcore/macros.rs
src/libcore/mem.rs
src/libcore/ops/function.rs
src/libcore/option.rs
src/libcore/result.rs
src/libcore/tests/slice.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/ich/impls_mir.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/lint/context.rs
src/librustc/lint/levels.rs [new file with mode: 0644]
src/librustc/lint/mod.rs
src/librustc/lint/table.rs [deleted file]
src/librustc/macros.rs
src/librustc/middle/dead.rs
src/librustc/middle/effect.rs
src/librustc/middle/liveness.rs
src/librustc/middle/stability.rs
src/librustc/mir/visit.rs
src/librustc/session/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/mod.rs
src/librustc/traits/select.rs
src/librustc/ty/context.rs
src/librustc/ty/inhabitedness/mod.rs
src/librustc/ty/layout.rs
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc/ty/util.rs
src/librustc_allocator/expand.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_const_eval/check_match.rs
src/librustc_data_structures/array_vec.rs
src/librustc_data_structures/bitvec.rs
src/librustc_data_structures/indexed_vec.rs
src/librustc_driver/Cargo.toml
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/test.rs
src/librustc_lint/builtin.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/encoder.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/add_call_guards.rs
src/librustc_mir/transform/nll.rs
src/librustc_mir/transform/type_check.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/consts.rs
src/librustc_passes/diagnostics.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/check_unused.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/Cargo.toml
src/librustc_trans/back/link.rs
src/librustc_trans/back/symbol_export.rs
src/librustc_trans/base.rs
src/librustc_trans/partitioning.rs
src/librustc_trans/time_graph.rs
src/librustc_trans_utils/Cargo.toml [new file with mode: 0644]
src/librustc_trans_utils/lib.rs [new file with mode: 0644]
src/librustc_trans_utils/link.rs [new file with mode: 0644]
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/op.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/check_unused.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustdoc/core.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/rustdoc.css
src/librustdoc/test.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/table.rs
src/libstd/error.rs
src/libstd/fs.rs
src/libstd/io/cursor.rs
src/libstd/io/error.rs
src/libstd/io/mod.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/net/ip.rs
src/libstd/sync/once.rs
src/libstd/sys/unix/ext/net.rs
src/libstd/sys/unix/rand.rs
src/libstd/sys/windows/fs.rs
src/libsyntax/diagnostic_list.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/source_util.rs
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/feature_gate.rs
src/libsyntax/parse/lexer/unicode_chars.rs
src/libsyntax/parse/parser.rs
src/libsyntax_ext/format.rs
src/libsyntax_ext/lib.rs
src/rustc/Cargo.toml
src/rustllvm/PassWrapper.cpp
src/test/compile-fail-fulldeps/proc-macro/attribute-with-error.rs
src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs
src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs
src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable-2.rs
src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable.rs
src/test/compile-fail-fulldeps/proc-macro/issue-38586.rs
src/test/compile-fail-fulldeps/proc-macro/item-error.rs
src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs
src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs
src/test/compile-fail/E0010.rs
src/test/compile-fail/E0394.rs
src/test/compile-fail/bad-lint-cap2.rs
src/test/compile-fail/bad-lint-cap3.rs
src/test/compile-fail/check-static-values-constraints.rs
src/test/compile-fail/const-eval-overflow-2.rs
src/test/compile-fail/const-match-pattern-arm.rs
src/test/compile-fail/feature-gate-dropck-ugeh.rs
src/test/compile-fail/issue-14227.rs
src/test/compile-fail/issue-16538.rs
src/test/compile-fail/issue-17450.rs
src/test/compile-fail/issue-17718-const-naming.rs
src/test/compile-fail/issue-17718-references.rs
src/test/compile-fail/issue-18937.rs
src/test/compile-fail/issue-28075.rs
src/test/compile-fail/issue-28113.rs
src/test/compile-fail/issue-28324.rs
src/test/compile-fail/issue-30730.rs
src/test/compile-fail/issue-37515.rs
src/test/compile-fail/issue-43162.rs [new file with mode: 0644]
src/test/compile-fail/issue-7364.rs
src/test/compile-fail/lint-removed-allow.rs
src/test/compile-fail/lint-removed-cmdline.rs
src/test/compile-fail/lint-renamed-allow.rs
src/test/compile-fail/lint-stability-deprecated.rs
src/test/compile-fail/lint-type-overflow2.rs
src/test/compile-fail/lint-unused-mut-variables.rs
src/test/compile-fail/lint-uppercase-variables.rs
src/test/compile-fail/liveness-unused.rs
src/test/compile-fail/never-assign-dead-code.rs
src/test/compile-fail/private-inferred-type.rs
src/test/compile-fail/private-type-in-interface.rs
src/test/compile-fail/rust-unstable-column-gated.rs [new file with mode: 0644]
src/test/compile-fail/static-mut-not-constant.rs
src/test/compile-fail/struct-path-self-type-mismatch.rs
src/test/compile-fail/unreachable-try-pattern.rs
src/test/mir-opt/validate_1.rs
src/test/mir-opt/validate_4.rs
src/test/mir-opt/validate_5.rs
src/test/run-make/issue-37839/Makefile
src/test/run-make/issue-37893/Makefile
src/test/run-make/issue-38237/Makefile
src/test/run-make/llvm-pass/Makefile
src/test/run-make/rustc-macro-dep-files/Makefile
src/test/run-pass-fulldeps/issue-40663.rs
src/test/run-pass-fulldeps/proc-macro/add-impl.rs
src/test/run-pass-fulldeps/proc-macro/append-impl.rs
src/test/run-pass-fulldeps/proc-macro/attr-args.rs
src/test/run-pass-fulldeps/proc-macro/bang-macro.rs
src/test/run-pass-fulldeps/proc-macro/count_compound_ops.rs
src/test/run-pass-fulldeps/proc-macro/crate-var.rs
src/test/run-pass-fulldeps/proc-macro/derive-same-struct.rs
src/test/run-pass-fulldeps/proc-macro/hygiene_example.rs
src/test/run-pass-fulldeps/proc-macro/issue-39889.rs
src/test/run-pass-fulldeps/proc-macro/issue-40001.rs
src/test/run-pass-fulldeps/proc-macro/load-two.rs
src/test/run-pass-fulldeps/proc-macro/use-reexport.rs
src/test/run-pass/issue-43057.rs [new file with mode: 0644]
src/test/run-pass/loop-break-value.rs
src/test/run-pass/type-id-higher-rank.rs
src/test/run-pass/weird-exprs.rs
src/test/ui-fulldeps/lint-plugin-cmdline-allow.rs
src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr
src/test/ui/block-result/block-must-not-have-result-res.stderr
src/test/ui/block-result/issue-13624.stderr
src/test/ui/block-result/issue-22645.stderr
src/test/ui/block-result/issue-5500.stderr
src/test/ui/check_match/issue-43253.rs
src/test/ui/check_match/issue-43253.stderr
src/test/ui/compare-method/proj-outlives-region.stderr
src/test/ui/compare-method/region-unrelated.stderr
src/test/ui/extern-const.rs [new file with mode: 0644]
src/test/ui/extern-const.stderr [new file with mode: 0644]
src/test/ui/lint/fn_must_use.rs
src/test/ui/lint/fn_must_use.stderr
src/test/ui/lint/outer-forbid.rs
src/test/ui/lint/outer-forbid.stderr
src/test/ui/mismatched_types/abridged.stderr
src/test/ui/path-lookahead.rs
src/test/ui/path-lookahead.stderr
src/test/ui/reachable/expr_unary.stderr
src/test/ui/span/issue-24690.rs
src/test/ui/span/issue-24690.stderr
src/test/ui/span/macro-span-replacement.rs
src/test/ui/span/macro-span-replacement.stderr
src/test/ui/span/multispan-import-lint.rs
src/test/ui/span/multispan-import-lint.stderr
src/test/ui/trait-method-private.rs [new file with mode: 0644]
src/test/ui/trait-method-private.stderr [new file with mode: 0644]
src/tools/cargo
src/tools/compiletest/src/runtest.rs
src/tools/tidy/src/pal.rs
src/tools/tidy/src/style.rs

index 5bb23149f2a745122c84c754f71cb16402c1a8b6..7bf0bcab64066b886d1d5677f4ce0f46fcc9173a 100644 (file)
@@ -1,3 +1,187 @@
+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 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]
+- [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
+---------
+
+
+- [Relaxed Debug constraints on `{HashMap,BTreeMap}::{Keys,Values}`.][42854]
+- [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]
+- [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")`
+- [`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]
+- [`#[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]
+
+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`]
+- [`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
+-----
+- [Cargo API token location moved from `~/.cargo/config` to
+  `~/cargo/credentials`.][cargo/3978]
+- [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
+  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]
+- [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
+[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
+[`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)
 ===========================
 
@@ -1679,7 +1863,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)
index 38897993d435de0d02c6dcc50469de7ac2b31e3c..c175198c227a54adc24d0fc04abd27072402d0ab 100644 (file)
@@ -65,6 +65,11 @@ name = "ansi_term"
 version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "ar"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "arena"
 version = "0.0.0"
@@ -1333,10 +1338,12 @@ dependencies = [
 name = "rustc_driver"
 version = "0.0.0"
 dependencies = [
+ "ar 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "arena 0.0.0",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_allocator 0.0.0",
  "rustc_back 0.0.0",
@@ -1354,6 +1361,7 @@ dependencies = [
  "rustc_resolve 0.0.0",
  "rustc_save_analysis 0.0.0",
  "rustc_trans 0.0.0",
+ "rustc_trans_utils 0.0.0",
  "rustc_typeck 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
@@ -1545,11 +1553,21 @@ dependencies = [
  "rustc_incremental 0.0.0",
  "rustc_llvm 0.0.0",
  "rustc_platform_intrinsics 0.0.0",
+ "rustc_trans_utils 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
 
+[[package]]
+name = "rustc_trans_utils"
+version = "0.0.0"
+dependencies = [
+ "rustc 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
 [[package]]
 name = "rustc_tsan"
 version = "0.0.0"
@@ -2141,6 +2159,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
 "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
 "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
+"checksum ar 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b24e4eef8e3fa7e2ca75b157e6039cdf8d9d3a68213ddc19d0fd9d576b9717c9"
 "checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
 "checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76"
 "checksum backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "afccc5772ba333abccdf60d55200fa3406f8c59dcf54d5f7998c9107d3799c7c"
index 5d898cb716dcf68d48b7426e40d9a6e957190b51..ec57bb069e0a4812719f88be8640239e3cf857e6 100644 (file)
@@ -53,6 +53,7 @@ pub struct Config {
     pub profiler: bool,
 
     // llvm codegen options
+    pub llvm_enabled: bool,
     pub llvm_assertions: bool,
     pub llvm_optimize: bool,
     pub llvm_release_debuginfo: bool,
@@ -192,6 +193,7 @@ struct Install {
 #[derive(Deserialize, Default)]
 #[serde(deny_unknown_fields, rename_all = "kebab-case")]
 struct Llvm {
+    enabled: Option<bool>,
     ccache: Option<StringOrBool>,
     ninja: Option<bool>,
     assertions: Option<bool>,
@@ -265,6 +267,7 @@ struct TomlTarget {
 impl Config {
     pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
         let mut config = Config::default();
+        config.llvm_enabled = true;
         config.llvm_optimize = true;
         config.use_jemalloc = true;
         config.backtrace = true;
@@ -345,6 +348,7 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
                 Some(StringOrBool::Bool(false)) | None => {}
             }
             set(&mut config.ninja, llvm.ninja);
+            set(&mut config.llvm_enabled, llvm.enabled);
             set(&mut config.llvm_assertions, llvm.assertions);
             set(&mut config.llvm_optimize, llvm.optimize);
             set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo);
index 9314135050f016f84b487e8405e814b3dd75affc..19678dc77937568216a7fafa88302834669bca10 100644 (file)
 # =============================================================================
 [llvm]
 
+# Indicates whether rustc will support compilation with LLVM
+# note: rustc does not compile without LLVM at the moment
+#enabled = true
+
 # Indicates whether the LLVM build is a Release or Debug build
 #optimize = true
 
index 5b5ef3f07f98e839caf20904532bc2a2e4f33f98..a8485d1d152d18703837f735a7e778e8c62dd2f8 100644 (file)
@@ -429,6 +429,9 @@ fn rustc_features(&self) -> String {
         if self.config.use_jemalloc {
             features.push_str(" jemalloc");
         }
+        if self.config.llvm_enabled {
+            features.push_str(" llvm");
+        }
         features
     }
 
index ee0eca5d482432853ba2ee66e2ff3f6bef067173..59efbd5c4d20d8d9ce7f96d355cf746e20e13fec 100644 (file)
@@ -56,6 +56,12 @@ fn make_run(run: RunConfig) {
     fn run(self, builder: &Builder) {
         let build = builder.build;
         let target = self.target;
+
+        // If we're not compiling for LLVM bail out here.
+        if !build.config.llvm_enabled {
+            return;
+        }
+
         // If we're using a custom LLVM bail out here, but we can only use a
         // custom LLVM for the build triple.
         if let Some(config) = build.config.target_config.get(&target) {
index 9e3142519341777cca7803f8e663bdca417ef00c..daf556795fa6b2b9bdb71d7b9193cc36ba769f9d 100644 (file)
@@ -95,7 +95,7 @@
 /// # Cloning references
 ///
 /// Creating a new reference from an existing reference counted pointer is done using the
-/// `Clone` trait implemented for [`Arc<T>`][`arc`] and [`Weak<T>`][`weak`].
+/// `Clone` trait implemented for [`Arc<T>`][arc] and [`Weak<T>`][weak].
 ///
 /// ```
 /// use std::sync::Arc;
index 06d3a113b947471989ad7a803cb77e490f9f5038..8cea6c482c33d0a65c7a146f43dfd21fc3098d98 100644 (file)
@@ -1037,7 +1037,7 @@ impl<'a, K: 'a, V: 'a, NodeType>
         Handle<NodeRef<marker::Mut<'a>, 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 @@ pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) {
 impl<'a, K, V, NodeType> Handle<NodeRef<marker::Mut<'a>, 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))
         }
     }
index 622cc68964bf7061cc49d3832a69bbc63186c81c..322b137e99f0e9b6856d5171384aab0b3f482a87 100644 (file)
 /// # Deref
 ///
 /// `String`s implement [`Deref`]`<Target=str>`, and so inherit all of [`str`]'s
-/// methods. In addition, this means that you can pass a `String` to any
+/// methods. In addition, this means that you can pass a `String` to a
 /// function which takes a [`&str`] by using an ampersand (`&`):
 ///
 /// ```
 ///
 /// This will create a [`&str`] from the `String` and pass it in. This
 /// conversion is very inexpensive, and so generally, functions will accept
-/// [`&str`]s as arguments unless they need a `String` for some specific reason.
+/// [`&str`]s as arguments unless they need a `String` for some specific
+/// reason.
 ///
+/// In certain cases Rust doesn't have enough information to make this
+/// conversion, known as `Deref` coercion. In the following example a string
+/// slice `&'a str` implements the trait `TraitExample`, and the function
+/// `example_func` takes anything that implements the trait. In this case Rust
+/// would need to make two implicit conversions, which Rust doesn't have the
+/// means to do. For that reason, the following example will not compile.
+///
+/// ```compile_fail,E0277
+/// trait TraitExample {}
+///
+/// impl<'a> TraitExample for &'a str {}
+///
+/// fn example_func<A: TraitExample>(example_arg: A) {}
+///
+/// fn main() {
+///     let example_string = String::from("example_string");
+///     example_func(&example_string);
+/// }
+/// ```
+///
+/// There are two options that would work instead. The first would be to
+/// change the line `example_func(&example_string);` to
+/// `example_func(example_string.as_str());`, using the method `as_str()`
+/// to explicitly extract the string slice containing the string. The second
+/// way changes `example_func(&example_string);` to
+/// `example_func(&*example_string);`. In this case we are dereferencing a
+/// `String` to a `str`, then referencing the `str` back to `&str`. The
+/// second way is more idiomatic, however both work to do the conversion
+/// explicitly rather than relying on the implicit conversion.
 ///
 /// # Representation
 ///
index da47ca509832b95e5f9236f28e033def89ee930a..160c0ba2ab0e3482f56771f1950a73a3d107bc71 100644 (file)
@@ -1751,7 +1751,7 @@ impl<'a, T> IntoIterator for &'a mut Vec<T> {
     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()
     }
 }
index fdd6c79ef2e9d74d8971033c588b7d0236cf76aa..2068c2c9c5fb56268f5ece03cd97bc06d1022dc6 100644 (file)
@@ -2394,7 +2394,7 @@ impl<'a, T> IntoIterator for &'a mut VecDeque<T> {
     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()
     }
 }
@@ -2558,7 +2558,7 @@ fn pointer(&mut self) -> *mut T {
 impl<'a, T> InPlace<T> 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 @@ fn pointer(&mut self) -> *mut T {
 impl<'a, T> InPlace<T> 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))
     }
index 65c18d6d7772b45852b493f57d6c6737083b7b4c..fdca8d00d7a75f1fc0a693765a576b7d536d893d 100644 (file)
     /// Aborts the execution of the process.
     pub fn abort() -> !;
 
-    /// Tells LLVM that this point in the code is not reachable,
-    /// enabling further optimizations.
+    /// Tells LLVM that this point in the code is not reachable, enabling
+    /// further optimizations.
     ///
-    /// NB: This is very different from the `unreachable!()` macro!
+    /// NB: This is very different from the `unreachable!()` macro: Unlike the
+    /// macro, which panics when it is executed, it is *undefined behavior* to
+    /// reach code marked with this function.
     pub fn unreachable() -> !;
 
     /// Informs the optimizer that a condition is always true.
index 2edf8e1fa886f9bde3ba843b161aad7cc3ce7e62..684b81a27f82e39291addc166bcbd503416d1a4b 100644 (file)
@@ -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)
     });
 }
index 866296a5670318c8047ea441e78e89c86256493f..6f7adbe1e7a0e9e67754ae9731582c4e209b4668 100644 (file)
@@ -942,3 +942,15 @@ fn fmt(&self, fmt: &mut ::fmt::Formatter) -> ::fmt::Result {
         }
     }
 }
+
+/// Tells LLVM that this point in the code is not reachable, enabling further
+/// optimizations.
+///
+/// NB: This is very different from the `unreachable!()` macro: Unlike the
+/// macro, which panics when it is executed, it is *undefined behavior* to
+/// reach code marked with this function.
+#[inline]
+#[unstable(feature = "unreachable", issue = "43751")]
+pub unsafe fn unreachable() -> ! {
+    intrinsics::unreachable()
+}
index 62bf69336a398ebdb6015319562fac3ccbb19f46..c5b3fbca1a6dd492e313c6782cd44b2a2e43fa2c 100644 (file)
@@ -187,7 +187,7 @@ impl<'a,A,F:?Sized> FnOnce<A> for &'a mut F
         where F : FnMut<A>
     {
         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)
         }
     }
index ef41b6794105d8b62aacf75357f51d0dce320560..aecf2ee9325eee9dde0a13cef3d65e293610c147 100644 (file)
@@ -872,7 +872,7 @@ impl<'a, T> IntoIterator for &'a mut Option<T> {
     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()
     }
 }
index 88a93492de96257276348c3f1eda3a28f6d2ff01..20cfb02afcc7707149236dd940066532ccc151c2 100644 (file)
@@ -909,7 +909,7 @@ impl<'a, T, E> IntoIterator for &'a mut Result<T, E> {
     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()
     }
 }
index e5d6b53b570628b688e8e623a0b6052f5dab1f0d..8c31d2e83d3524f797c1417cd27c0db7587028fb 100644 (file)
@@ -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][..]));
index c6f9cb2fceadd3f454121d8aecaa0fa56739cfcd..5b609f192e1c2b11d351febd6d23b72e3e99c2d6 100644 (file)
@@ -521,6 +521,7 @@ pub fn to_dep_node(self, tcx: TyCtxt, kind: DepKind) -> DepNode {
     [] IsAllocator(DefId),
     [] IsPanicRuntime(DefId),
     [] ExternCrate(DefId),
+    [] LintLevels,
 );
 
 trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
index c20864183f47a0cf774efa72fa78d875f142a83f..faf579186e5fcd7d9d9ea9f3c251efb578a54b4f 100644 (file)
@@ -33,7 +33,7 @@
 impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, is_cleanup });
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for mir::Terminator<'tcx> {
+for mir::Terminator<'gcx> {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
@@ -125,7 +125,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for mir::TerminatorKind<'tcx> {
+for mir::TerminatorKind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
@@ -186,7 +186,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for mir::AssertMessage<'tcx> {
+for mir::AssertMessage<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
@@ -207,7 +207,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 impl_stable_hash_for!(struct mir::Statement<'tcx> { source_info, kind });
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for mir::StatementKind<'tcx> {
+for mir::StatementKind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
@@ -244,7 +244,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl<'a, 'gcx, 'tcx, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-    for mir::ValidationOperand<'tcx, T>
+    for mir::ValidationOperand<'gcx, T>
     where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
@@ -260,7 +260,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 
 impl_stable_hash_for!(enum mir::ValidationOp { Acquire, Release, Suspend(extent) });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Lvalue<'tcx> {
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Lvalue<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
@@ -280,7 +280,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl<'a, 'gcx, 'tcx, B, V, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for mir::Projection<'tcx, B, V, T>
+for mir::Projection<'gcx, B, V, T>
     where B: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
           V: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
           T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
@@ -299,7 +299,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl<'a, 'gcx, 'tcx, V, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for mir::ProjectionElem<'tcx, V, T>
+for mir::ProjectionElem<'gcx, V, T>
     where V: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
           T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
 {
@@ -335,7 +335,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 
 impl_stable_hash_for!(struct mir::VisibilityScopeData { span, parent_scope });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Operand<'tcx> {
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Operand<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
@@ -352,7 +352,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Rvalue<'tcx> {
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Rvalue<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
@@ -413,7 +413,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 });
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for mir::AggregateKind<'tcx> {
+for mir::AggregateKind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
@@ -469,7 +469,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 
 impl_stable_hash_for!(struct mir::Constant<'tcx> { span, ty, literal });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Literal<'tcx> {
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Literal<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
index 5269ec90def5c015c3117dd2ef42d982b413cdb9..8a37d7bab4445c9314b23a49ce04aeb20132aa78 100644 (file)
@@ -20,7 +20,7 @@
 use ty;
 
 impl<'a, 'gcx, 'tcx, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for &'tcx ty::Slice<T>
+for &'gcx ty::Slice<T>
     where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
@@ -30,7 +30,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for ty::subst::Kind<'tcx> {
+for ty::subst::Kind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
@@ -55,6 +55,11 @@ fn hash_stable<W: StableHasherResult>(&self,
                 db.depth.hash_stable(hcx, hasher);
                 i.hash_stable(hcx, hasher);
             }
+            ty::ReLateBound(db, ty::BrNamed(def_id, name)) => {
+                db.depth.hash_stable(hcx, hasher);
+                def_id.hash_stable(hcx, hasher);
+                name.hash_stable(hcx, hasher);
+            }
             ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {
                 def_id.hash_stable(hcx, hasher);
                 index.hash_stable(hcx, hasher);
@@ -76,7 +81,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for ty::adjustment::AutoBorrow<'tcx> {
+for ty::adjustment::AutoBorrow<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
@@ -94,7 +99,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for ty::adjustment::Adjust<'tcx> {
+for ty::adjustment::Adjust<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
@@ -128,7 +133,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 });
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for ty::UpvarCapture<'tcx> {
+for ty::UpvarCapture<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
@@ -150,12 +155,13 @@ fn hash_stable<W: StableHasherResult>(&self,
 });
 
 impl<'a, 'gcx, 'tcx, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::Binder<T>
-    where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>> + ty::fold::TypeFoldable<'tcx>
+    where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
-        hcx.tcx().anonymize_late_bound_regions(self).0.hash_stable(hcx, hasher);
+        let ty::Binder(ref inner) = *self;
+        inner.hash_stable(hcx, hasher);
     }
 }
 
@@ -190,7 +196,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 impl_stable_hash_for!(struct ty::ProjectionTy<'tcx> { substs, item_def_id });
 
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::Predicate<'tcx> {
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::Predicate<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
@@ -256,7 +262,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 });
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for ::middle::const_val::ConstVal<'tcx> {
+for ::middle::const_val::ConstVal<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
@@ -483,7 +489,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 });
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for ty::TypeVariants<'tcx>
+for ty::TypeVariants<'gcx>
 {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
@@ -574,7 +580,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 });
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for ty::ExistentialPredicate<'tcx>
+for ty::ExistentialPredicate<'gcx>
 {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
@@ -607,7 +613,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for ty::TypeckTables<'tcx> {
+for ty::TypeckTables<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
@@ -625,8 +631,6 @@ fn hash_stable<W: StableHasherResult>(&self,
 
             ref cast_kinds,
 
-            // FIXME(#41184): This is still ignored at the moment.
-            lints: _,
             ref used_trait_imports,
             tainted_by_errors,
             ref free_region_map,
@@ -689,7 +693,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     substs
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::InstanceDef<'tcx> {
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::InstanceDef<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
index 8e8576b83e4ed4d238638768cbe61d012d928b0b..9f70b4834ddc5d71b0700be42671d9e584a3678f 100644 (file)
@@ -415,8 +415,8 @@ fn note_error_origin(&self,
     /// -------- 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,
index d67bca1df3022bd9535aa4df871afe4cd4756409..6ee06dc0a8163775af63b54ef02a158aa2e4091d 100644 (file)
 //! 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<String, TargetLint>,
 
-    /// 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<LintId>, bool)>,
@@ -81,78 +74,23 @@ pub struct LintStore {
     future_incompatible: FxHashMap<LintId, FutureIncompatibleInfo>,
 }
 
-
-#[derive(Default)]
-struct LintLevels {
-    /// Current levels of each lint, and where they were set.
-    levels: FxHashMap<LintId, LevelSource>,
-
-    /// Maximum level a lint can be
-    lint_cap: Option<Level>,
-}
-
-
 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<Vec<PassObject>>,
 }
 
 
-/// 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<MultiSpan>> 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 @@ pub fn new() -> 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 @@ fn push_pass<P: LintPass + ?Sized + 'static>(&mut self,
                     (Some(sess), true)  => sess.err(&msg[..]),
                 }
             }
-
-            self.levels.set(id, (lint.default_level, Default));
         }
     }
 
@@ -291,96 +235,93 @@ pub fn register_removed(&mut self, name: &str, reason: &str) {
         self.by_name.insert(name.into(), Removed(reason.into()));
     }
 
-    fn find_lint(&self, lint_name: &str) -> Result<LintId, FindLintError> {
+    pub fn find_lints(&self, lint_name: &str) -> Result<Vec<LintId>, 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::<FxHashMap<&'static str,
-                                                                      Vec<LintId>>>()
-                                                 .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),
-        }
-    }
+    // 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))
+            }
+        };
 
-    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);
+        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();
         }
     }
 
-    fn set_lint_cap(&mut self, lint_cap: Option<Level>) {
-        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 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<LintStore>) -> 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 @@ fn new(store: &'a RefCell<LintStore>) -> LintSession<'a, PassObject> {
     fn restore(self, store: &RefCell<LintStore>) {
         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<Result<(ast::Name, Level, Span), Span>> {
-    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<Result<(ast::Name, Level, Span), Span>> {
-    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<S: Into<MultiSpan>>(sess: &Session,
-                                         lints: &LintStore,
-                                         lint: &'static Lint,
-                                         lvlsrc: LevelSource,
-                                         span: Option<S>,
-                                         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<S>,
-                              msg: &str)
-                              -> DiagnosticBuilder<'a>
-    where S: Into<MultiSpan>
-{
-    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<Vec<Self>>;
     fn restore_passes(store: &mut LintStore, passes: Option<Vec<Self>>);
@@ -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<LevelSource> {
-        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<S: Into<MultiSpan>>(&self,
                                            lint: &'static Lint,
                                            span: Option<S>,
                                            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<S: Into<MultiSpan>>(&self,
                                   lint: &'static Lint,
                                   span: Option<S>,
                                   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<S: Into<MultiSpan>>(&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<S: Into<MultiSpan>>(&self,
                                             lint: &'static Lint,
                                             span: S,
@@ -680,12 +448,10 @@ fn struct_span_lint<S: Into<MultiSpan>>(&self,
     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 @@ fn span_lint_help(&self, lint: &'static Lint, span: Span,
                       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 @@ fn lint(&self, lint: &'static Lint, msg: &str) {
     /// current lint context, call the provided function, then reset the
     /// lints in effect to their previous state.
     fn with_lint_attrs<F>(&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 @@ fn new(sess: &'a Session,
             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 @@ fn exit_attrs(&mut self, attrs: &'tcx [ast::Attribute]) {
         debug!("late context: exit_attrs({:?})", attrs);
         run_lints!(self, exit_lint_attrs, late_passes, attrs);
     }
+
+    fn lookup<S: Into<MultiSpan>>(&self,
+                                  lint: &'static Lint,
+                                  span: Option<S>,
+                                  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<F>(&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 @@ fn exit_attrs(&mut self, attrs: &'a [ast::Attribute]) {
         debug!("early context: exit_attrs({:?})", attrs);
         run_lints!(self, exit_lint_attrs, early_passes, attrs);
     }
+
+    fn lookup<S: Into<MultiSpan>>(&self,
+                                  lint: &'static Lint,
+                                  span: Option<S>,
+                                  msg: &str)
+                                  -> DiagnosticBuilder {
+        self.builder.struct_lint(lint, span.map(|s| s.into()), msg)
+    }
+
+    fn with_lint_attrs<F>(&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 @@ fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this
         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 @@ fn visit_body(&mut self, body: &'tcx hir::Body) {
     }
 
     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 @@ fn visit_item(&mut self, it: &'tcx hir::Item) {
     }
 
     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 @@ fn visit_pat(&mut self, p: &'tcx hir::Pat) {
     }
 
     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 @@ fn visit_variant_data(&mut self,
     }
 
     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 @@ fn visit_variant(&mut self,
                      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 @@ fn visit_mod(&mut self, m: &'tcx hir::Mod, s: Span, n: ast::NodeId) {
     }
 
     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 @@ fn visit_generics(&mut self, g: &'tcx hir::Generics) {
     }
 
     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 @@ fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
     }
 
     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 @@ fn visit_path(&mut self, p: &'tcx hir::Path, id: ast::NodeId) {
     }
 
     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 @@ fn visit_item(&mut self, it: &'a ast::Item) {
     }
 
     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 @@ fn visit_foreign_item(&mut self, it: &'a ast::ForeignItem) {
 
     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 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
 
     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 @@ fn visit_variant_data(&mut self,
                         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 @@ fn visit_variant(&mut self, v: &'a ast::Variant, g: &'a ast::Generics, item_id:
 
     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 @@ fn visit_ident(&mut self, sp: Span, id: ast::Ident) {
 
     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 @@ fn visit_local(&mut self, l: &'a ast::Local) {
 
     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 @@ fn visit_generics(&mut self, g: &'a ast::Generics) {
     }
 
     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 @@ fn visit_trait_item(&mut self, trait_item: &'a ast::TraitItem) {
     }
 
     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 @@ fn visit_impl_item(&mut self, impl_item: &'a ast::ImplItem) {
 
     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 @@ fn visit_lifetime_def(&mut self, lt: &'a ast::LifetimeDef) {
 
     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 @@ fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
     }
 
     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: Decoder>(d: &mut D) -> Result<LintId, D::Error> {
         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 (file)
index 0000000..ab9d4f7
--- /dev/null
@@ -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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+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<LintSet>,
+    lint_cap: Level,
+}
+
+enum LintSet {
+    CommandLine {
+        // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
+        // flag.
+        specs: FxHashMap<LintId, (Level, LintSource)>,
+    },
+
+    Node {
+        specs: FxHashMap<LintId, (Level, LintSource)>,
+        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<Level>, 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<HirId, u32>,
+    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<MultiSpan>,
+                       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<HirId, u32>,
+}
+
+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)
+        })
+    }
+}
index f9222ac9400af307852ee74657b9984e33f25acd..c64e1c08082a5637fcfbecf68eba67ebafac13e5 100644 (file)
 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 enum LintSource {
 
 pub mod builtin;
 mod context;
-mod table;
+mod levels;
+
+pub use self::levels::{LintLevelSets, LintLevelMap};
+
+pub struct LintBuffer {
+    map: NodeMap<Vec<BufferedEarlyLint>>,
+}
+
+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<BufferedEarlyLint> {
+        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<MultiSpan>,
+                             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<LintLevelMap>
+{
+    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<F>(&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 (file)
index f2dab25..0000000
+++ /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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-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<Vec<EarlyLint>>
-}
-
-impl LintTable {
-    pub fn new() -> Self {
-        LintTable { map: NodeMap() }
-    }
-
-    pub fn add_lint<S: Into<MultiSpan>>(&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<M>(&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<EarlyLint> {
-        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<EarlyLint>)> {
-        self.map.iter()
-                .filter(|&(_, v)| !v.is_empty())
-                .next()
-    }
-}
-
index f814f941b06f1aed2dd35a0a18b8c3214e8c3e28..f3d66b49de5a89000c00ec4597a4e68bebd9313b 100644 (file)
@@ -73,10 +73,10 @@ macro_rules! __impl_stable_hash_field {
 #[macro_export]
 macro_rules! impl_stable_hash_for {
     (enum $enum_name:path { $( $variant:ident $( ( $($arg:ident),* ) )* ),* }) => {
-        impl<'a, 'gcx, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'gcx, 'tcx>> for $enum_name {
+        impl<'a, 'tcx, 'lcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx, 'lcx>> for $enum_name {
             #[inline]
             fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
-                                                  __ctx: &mut $crate::ich::StableHashingContext<'a, 'gcx, 'tcx>,
+                                                  __ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx, 'lcx>,
                                                   __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
                 use $enum_name::*;
                 ::std::mem::discriminant(self).hash_stable(__ctx, __hasher);
@@ -92,10 +92,10 @@ fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&s
         }
     };
     (struct $struct_name:path { $($field:ident),* }) => {
-        impl<'a, 'gcx, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'gcx, 'tcx>> for $struct_name {
+        impl<'a, 'tcx, 'lcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx, 'lcx>> for $struct_name {
             #[inline]
             fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
-                                                  __ctx: &mut $crate::ich::StableHashingContext<'a, 'gcx, 'tcx>,
+                                                  __ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx, 'lcx>,
                                                   __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
                 let $struct_name {
                     $(ref $field),*
@@ -106,10 +106,10 @@ fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&s
         }
     };
     (tuple_struct $struct_name:path { $($field:ident),* }) => {
-        impl<'a, 'gcx, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'gcx, 'tcx>> for $struct_name {
+        impl<'a, 'tcx, 'lcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx, 'lcx>> for $struct_name {
             #[inline]
             fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
-                                                  __ctx: &mut $crate::ich::StableHashingContext<'a, 'gcx, 'tcx>,
+                                                  __ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx, 'lcx>,
                                                   __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
                 let $struct_name (
                     $(ref $field),*
@@ -125,11 +125,11 @@ fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&s
 macro_rules! impl_stable_hash_for_spanned {
     ($T:path) => (
 
-        impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ::syntax::codemap::Spanned<$T>
+        impl<'a, 'tcx, 'lcx> HashStable<StableHashingContext<'a, 'tcx, 'lcx>> for ::syntax::codemap::Spanned<$T>
         {
             #[inline]
             fn hash_stable<W: StableHasherResult>(&self,
-                                                  hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                                  hcx: &mut StableHashingContext<'a, 'tcx, 'lcx>,
                                                   hasher: &mut StableHasher<W>) {
                 self.node.hash_stable(hcx, hasher);
                 self.span.hash_stable(hcx, hasher);
index a525b4e13b78dd2b1cda110cc18da2d678f02e3d..4e08bc90c7c3a5064bf80005a566bfdbc26e3bcc 100644 (file)
 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 @@ fn visit_path(&mut self, path: &'tcx hir::Path, _: ast::NodeId) {
     }
 }
 
-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<ast::NodeId>,
     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 @@ fn visit_item(&mut self, item: &hir::Item) {
                     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 @@ fn visit_item(&mut self, item: &hir::Item) {
                 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 @@ fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool {
         !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 @@ fn warn_dead_code(&mut self,
                       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));
         }
     }
 }
index abd5cbcb89e33a3af6c668724dba005e3d7d7ca2..fcf366788b22394a1901ccbc2e54bfae531076fe 100644 (file)
@@ -56,11 +56,11 @@ fn require_unsafe_ext(&mut self, node_id: ast::NodeId, span: Span,
         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!(
index 551a550442b3df983c06402f4b1f44303a114126..070ad5159086e1607f9ae63ea5798cb0965322c2 100644 (file)
@@ -1482,12 +1482,12 @@ fn warn_about_unused(&self,
                 };
 
                 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 @@ fn warn_about_dead_assign(&self,
     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));
             }
         }
     }
index 68c01db544a66bab857e147f0a3bdabc131c1f08..5158c7e94af4c3025c1626cae5e91909fff1d599 100644 (file)
@@ -493,7 +493,7 @@ pub fn check_stability(self, def_id: DefId, id: NodeId, span: Span) {
                 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 @@ fn format_stable_since_msg(version: &str) -> String {
     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 @@ fn format_stable_since_msg(version: &str) -> String {
         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 @@ fn format_stable_since_msg(version: &str) -> String {
     }
 
     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");
     }
 }
index 5e860c632852cba9c28f53ef90078596dc90e9eb..a6d115bf0391280e17c162b01ca146d9858b5674 100644 (file)
@@ -753,6 +753,7 @@ fn visit_location(&mut self, mir: & $($mutability)* Mir<'tcx>, location: Locatio
 make_mir_visitor!(Visitor,);
 make_mir_visitor!(MutVisitor,mut);
 
+#[derive(Copy, Clone, Debug)]
 pub enum Lookup {
     Loc(Location),
     Src(SourceInfo),
index fe6b24f3e1f2a8f6fdd59ac5c382a7d4dcb939bd..be39f95b98899b788a115303386b14d5d81b7746 100644 (file)
@@ -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<lint::LintStore>,
-    pub lints: RefCell<lint::LintTable>,
+    pub buffered_lints: RefCell<Option<lint::LintBuffer>>,
     /// Set of (LintId, Option<Span>, 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 @@ pub fn unimpl(&self, msg: &str) -> ! {
         self.diagnostic().unimpl(msg)
     }
 
-    pub fn add_lint<S: Into<MultiSpan>>(&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<M>(&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<S: Into<MultiSpan>>(&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()),
index 65c0a9f8ffd58383c09fea1186cc8326b70c1275..f0fc6998c9e51735931516c79069d979302ebd6e 100644 (file)
@@ -499,11 +499,21 @@ pub fn report_extra_impl_obligation(&self,
         // 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 @@ pub fn report_extra_impl_obligation(&self,
             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
     }
 
index e14203b34a18072015a084ab97186a503cb4f593..d1938197e652965dbf338ac1c233141f36c9e909 100644 (file)
@@ -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
index c2feb54c4dbe65e294c8e8358f753f61dca085ba..3e39d5921351f3c05c983e4dcb6c80ebebcd2447 100644 (file)
@@ -494,7 +494,7 @@ pub fn select(&mut self, obligation: &TraitObligation<'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));
@@ -512,11 +512,11 @@ pub fn select(&mut self, obligation: &TraitObligation<'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)
index be3cd99426d4df4867956bd343774d9abb17d0aa..6b9cbabf20e977887e59021f15c8b52f0b9775d7 100644 (file)
 //! 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 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<ty::cast::CastKind>,
 
-    /// 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 @@ pub fn empty() -> 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 @@ pub fn mk_substs_trait(self,
     {
         self.mk_substs(iter::once(s).chain(t.into_iter().cloned()).map(Kind::from))
     }
+
+    pub fn lint_node<S: Into<MultiSpan>>(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<S: Into<MultiSpan>>(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<T: ?Sized, R> {
index 77c863a012318ca161a1ebbdf6f46a6a6839a3e0..900197f3dbd17c0756ebcf3c410e921270924ff0 100644 (file)
@@ -171,7 +171,7 @@ fn uninhabited_from_inner(
         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 @@ fn uninhabited_from_inner(
                     }
                 }
                 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
             },
index e770f1d55dcfdcc08dd35bb96557c7ee84d23dbb..4ee9b2e65a782ac79c88ad3062caaeb6e7cb8df3 100644 (file)
@@ -2197,8 +2197,8 @@ pub fn field_type<C: LayoutTyper<'tcx>>(&self, cx: C, i: usize) -> Ty<'tcx> {
         let tcx = cx.tcx();
 
         let ptr_field_type = |pointee: Ty<'tcx>| {
+            assert!(i < 2);
             let slice = |element: Ty<'tcx>| {
-                assert!(i < 2);
                 if i == 0 {
                     tcx.mk_mut_ptr(element)
                 } else {
index 5d25ce2fbeca39824fd8d46f180cc2aac81a9189..b871b36c948500100ab7f118a632d7dc6fa6a71e 100644 (file)
@@ -12,6 +12,7 @@
 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 @@ fn describe(_: TyCtxt, _: DefId) -> String {
     }
 }
 
+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 @@ fn default() -> Self {
     [] is_panic_runtime: IsPanicRuntime(DefId) -> bool,
 
     [] extern_crate: ExternCrate(DefId) -> Rc<Option<ExternCrate>>,
+
+    [] lint_levels: lint_levels(CrateNum) -> Rc<lint::LintLevelMap>,
 }
 
 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
+}
index 7f4aedb5f14bb7bc0b9f88a59767222b3ed8a116..28a73f4a4d387dcbe36170619619c236cd78baa0 100644 (file)
@@ -491,13 +491,14 @@ pub fn is_suggestable(&self) -> bool {
             TypeVariants::TyFnPtr(..) |
             TypeVariants::TyDynamic(..) |
             TypeVariants::TyClosure(..) |
+            TypeVariants::TyInfer(..) |
             TypeVariants::TyProjection(..) => false,
             _ => true,
         }
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::TyS<'tcx> {
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::TyS<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
index d1c73831545416c1c8b0376dbb2e78fe7f890cec..9cd6aa2111873a69f9becbb6b011e205b25f2978 100644 (file)
@@ -214,6 +214,11 @@ pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 {
         let mut hasher = StableHasher::new();
         let mut hcx = StableHashingContext::new(self);
 
+        // We want the type_id be independent of the types free regions, so we
+        // erase them. The erase_regions() call will also anonymize bound
+        // regions, which is desirable too.
+        let ty = self.erase_regions(&ty);
+
         hcx.while_hashing_spans(false, |hcx| {
             hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
                 ty.hash_stable(hcx, &mut hasher);
index e942b7264c589ebf952988f4be92fd6cee29e2d5..676c3c51ea2a3d3aca2d09ec8599c32e48c1a646 100644 (file)
@@ -188,7 +188,7 @@ fn attrs(&self) -> Vec<Attribute> {
     fn arg_ty(&self,
               ty: &AllocatorTy,
               args: &mut Vec<Arg>,
-              mut ident: &mut FnMut() -> Ident) -> P<Expr> {
+              ident: &mut FnMut() -> Ident) -> P<Expr> {
         match *ty {
             AllocatorTy::Layout => {
                 let usize = self.cx.path_ident(self.span, Ident::from_str("usize"));
@@ -263,7 +263,7 @@ fn arg_ty(&self,
     fn ret_ty(&self,
               ty: &AllocatorTy,
               args: &mut Vec<Arg>,
-              mut ident: &mut FnMut() -> Ident,
+              ident: &mut FnMut() -> Ident,
               expr: P<Expr>) -> (P<Ty>, P<Expr>)
     {
         match *ty {
index 7dcb6ce76a401618660faaf42f0841824b5f3d61..3d669aa81df6e7bce6aa2bcdffcbe400b6613e55 100644 (file)
@@ -436,20 +436,40 @@ 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);
-            }
-            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.
+        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
+                }
+                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,
index 76c4ac57a149ee803312ac5690dee74050aa4f9f..6b31535c5a5260592066d33039388692fce50cd3 100644 (file)
@@ -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);
 
index 060ff503d4e5889cdb61984056459a23e26f0ad6..a3f8aae472cae39e1d88465f0caeac5f74d73d15 100644 (file)
@@ -23,7 +23,7 @@
 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
index ced73e9e4262767cd4f740200b8116b7ae876ccd..df660d08603adfa1cc2fb31a82d63299d1540902 100644 (file)
@@ -260,7 +260,7 @@ fn drop(&mut self) {
                 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);
index ffcd25a4cdd39ab2863054812d614dfa7765cfd9..7fc59be780f6e565983e870d3cee6a09c186d21e 100644 (file)
@@ -166,7 +166,7 @@ fn range(&self, row: usize) -> (usize, usize) {
     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;
index 29ac650aa7053110e374dfa6859919913b9cf067..1f44378c9e6466f590f1c06aec59f9ef39d3e9a0 100644 (file)
@@ -259,7 +259,7 @@ impl<'a, I: Idx, T> IntoIterator for &'a mut IndexVec<I, T> {
     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()
     }
 }
index f1bdf0b2c3d3757bb2e03e1b48ac797e09812921..d6155f53485e3a8caca6b161bb38ac83e55ce1e8 100644 (file)
@@ -12,6 +12,7 @@ crate-type = ["dylib"]
 arena = { path = "../libarena" }
 graphviz = { path = "../libgraphviz" }
 log = { version = "0.3", features = ["release_max_level_info"] }
+owning_ref = "0.3.3"
 env_logger = { version = "0.4", default-features = false }
 rustc = { path = "../librustc" }
 rustc_allocator = { path = "../librustc_allocator" }
@@ -29,9 +30,15 @@ rustc_plugin = { path = "../librustc_plugin" }
 rustc_privacy = { path = "../librustc_privacy" }
 rustc_resolve = { path = "../librustc_resolve" }
 rustc_save_analysis = { path = "../librustc_save_analysis" }
-rustc_trans = { path = "../librustc_trans" }
+rustc_trans = { path = "../librustc_trans", optional = true }
+rustc_trans_utils = { path = "../librustc_trans_utils" }
 rustc_typeck = { path = "../librustc_typeck" }
 serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_ext = { path = "../libsyntax_ext" }
 syntax_pos = { path = "../libsyntax_pos" }
+
+ar = "0.3.0"
+
+[features]
+llvm = ["rustc_trans"]
index 12cb556afdabcb20cd7366b2ffcb90545edd4488..1c03b9f69f711bc24e67f947e9fef0b09c39ff3e 100644 (file)
@@ -18,7 +18,9 @@
 use rustc::session::config::{self, Input, OutputFilenames, OutputType};
 use rustc::session::search_paths::PathKind;
 use rustc::lint;
-use rustc::middle::{self, dependency_format, stability, reachable};
+use rustc::middle::{self, stability, reachable};
+#[cfg(feature="llvm")]
+use rustc::middle::dependency_format;
 use rustc::middle::privacy::AccessLevels;
 use rustc::mir::transform::{MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED, Passes};
 use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
@@ -31,7 +33,9 @@
 use rustc_resolve::{MakeGlobMap, Resolver};
 use rustc_metadata::creader::CrateLoader;
 use rustc_metadata::cstore::{self, CStore};
+#[cfg(feature="llvm")]
 use rustc_trans::back::{link, write};
+#[cfg(feature="llvm")]
 use rustc_trans as trans;
 use rustc_typeck as typeck;
 use rustc_privacy;
@@ -69,6 +73,11 @@ pub fn compile_input(sess: &Session,
                      output: &Option<PathBuf>,
                      addl_plugins: Option<Vec<String>>,
                      control: &CompileController) -> CompileResult {
+    #[cfg(feature="llvm")]
+    use rustc_trans::back::write::OngoingCrateTranslation;
+    #[cfg(not(feature="llvm"))]
+    type OngoingCrateTranslation = ();
+
     macro_rules! controller_entry_point {
         ($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{
             let state = &mut $make_state;
@@ -88,8 +97,8 @@ macro_rules! controller_entry_point {
     // We need nested scopes here, because the intermediate results can keep
     // 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 (outputs, trans): (OutputFilenames, OngoingCrateTranslation) = {
+        let krate = match phase_1_parse_input(control, sess, input) {
             Ok(krate) => krate,
             Err(mut parse_error) => {
                 parse_error.emit();
@@ -113,7 +122,8 @@ macro_rules! controller_entry_point {
         };
 
         let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
-        let crate_name = link::find_crate_name(Some(sess), &krate.attrs, input);
+        let crate_name =
+            ::rustc_trans_utils::link::find_crate_name(Some(sess), &krate.attrs, input);
         let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = {
             phase_2_configure_and_expand(
                 sess, &cstore, krate, registry, &crate_name, addl_plugins, control.make_glob_map,
@@ -206,6 +216,8 @@ macro_rules! controller_entry_point {
                 println!("Pre-trans");
                 tcx.print_debug_stats();
             }
+
+            #[cfg(feature="llvm")]
             let trans = phase_4_translate_to_llvm(tcx, analysis, incremental_hashes_map,
                                                   &outputs);
 
@@ -221,38 +233,59 @@ macro_rules! controller_entry_point {
                 }
             }
 
+            #[cfg(not(feature="llvm"))]
+            {
+                let _ = incremental_hashes_map;
+                sess.err(&format!("LLVM is not supported by this rustc"));
+                sess.abort_if_errors();
+                unreachable!();
+            }
+
+            #[cfg(feature="llvm")]
             Ok((outputs, trans))
         })??
     };
 
-    if sess.opts.debugging_opts.print_type_sizes {
-        sess.code_stats.borrow().print_type_sizes();
+    #[cfg(not(feature="llvm"))]
+    {
+        let _ = outputs;
+        let _ = trans;
+        unreachable!();
     }
 
-    let (phase5_result, trans) = phase_5_run_llvm_passes(sess, trans);
+    #[cfg(feature="llvm")]
+    {
+        if sess.opts.debugging_opts.print_type_sizes {
+            sess.code_stats.borrow().print_type_sizes();
+        }
 
-    controller_entry_point!(after_llvm,
-                            sess,
-                            CompileState::state_after_llvm(input, sess, outdir, output, &trans),
-                            phase5_result);
-    phase5_result?;
+        let (phase5_result, trans) = phase_5_run_llvm_passes(sess, trans);
 
-    phase_6_link_output(sess, &trans, &outputs);
+        controller_entry_point!(after_llvm,
+                                sess,
+                                CompileState::state_after_llvm(input, sess, outdir, output, &trans),
+                                phase5_result);
+        phase5_result?;
 
-    // Now that we won't touch anything in the incremental compilation directory
-    // any more, we can finalize it (which involves renaming it)
-    rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
+        phase_6_link_output(sess, &trans, &outputs);
 
-    if sess.opts.debugging_opts.perf_stats {
-        sess.print_perf_stats();
-    }
+        // Now that we won't touch anything in the incremental compilation directory
+        // any more, we can finalize it (which involves renaming it)
+        rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
 
-    controller_entry_point!(compilation_done,
-                            sess,
-                            CompileState::state_when_compilation_done(input, sess, outdir, output),
-                            Ok(()));
+        if sess.opts.debugging_opts.perf_stats {
+            sess.print_perf_stats();
+        }
+
+        controller_entry_point!(
+            compilation_done,
+            sess,
+            CompileState::state_when_compilation_done(input, sess, outdir, output),
+            Ok(())
+        );
 
-    Ok(())
+        Ok(())
+    }
 }
 
 fn keep_hygiene_data(sess: &Session) -> bool {
@@ -296,9 +329,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 +349,7 @@ pub fn basic() -> CompileController<'a> {
             compilation_done: PhaseController::basic(),
             make_glob_map: MakeGlobMap::No,
             keep_ast: false,
+            continue_parse_after_error: false,
         }
     }
 }
@@ -355,6 +393,7 @@ pub struct CompileState<'a, 'tcx: 'a> {
     pub resolutions: Option<&'a Resolutions>,
     pub analysis: Option<&'a ty::CrateAnalysis>,
     pub tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
+    #[cfg(feature="llvm")]
     pub trans: Option<&'a trans::CrateTranslation>,
 }
 
@@ -381,6 +420,7 @@ fn empty(input: &'a Input,
             resolutions: None,
             analysis: None,
             tcx: None,
+            #[cfg(feature="llvm")]
             trans: None,
         }
     }
@@ -469,7 +509,7 @@ fn state_after_analysis(input: &'a Input,
         }
     }
 
-
+    #[cfg(feature="llvm")]
     fn state_after_llvm(input: &'a Input,
                         session: &'tcx Session,
                         out_dir: &'a Option<PathBuf>,
@@ -483,11 +523,12 @@ fn state_after_llvm(input: &'a Input,
         }
     }
 
+    #[cfg(feature="llvm")]
     fn state_when_compilation_done(input: &'a Input,
-                                    session: &'tcx Session,
-                                    out_dir: &'a Option<PathBuf>,
-                                    out_file: &'a Option<PathBuf>)
-                                    -> Self {
+                                   session: &'tcx Session,
+                                   out_dir: &'a Option<PathBuf>,
+                                   out_file: &'a Option<PathBuf>)
+                                   -> Self {
         CompileState {
             out_file: out_file.as_ref().map(|s| &**s),
             ..CompileState::empty(input, session, out_dir)
@@ -495,9 +536,11 @@ fn state_when_compilation_done(input: &'a Input,
     }
 }
 
-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 {
@@ -638,7 +681,6 @@ pub fn phase_2_configure_and_expand<F>(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 +750,8 @@ pub fn phase_2_configure_and_expand<F>(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 +814,6 @@ pub fn phase_2_configure_and_expand<F>(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 +838,10 @@ pub fn phase_2_configure_and_expand<F>(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);
@@ -900,6 +942,7 @@ macro_rules! try_with_f {
     mir::provide(&mut local_providers);
     reachable::provide(&mut local_providers);
     rustc_privacy::provide(&mut local_providers);
+    #[cfg(feature="llvm")]
     trans::provide(&mut local_providers);
     typeck::provide(&mut local_providers);
     ty::provide(&mut local_providers);
@@ -908,9 +951,11 @@ macro_rules! try_with_f {
     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);
+    #[cfg(feature="llvm")]
     trans::provide(&mut extern_providers);
     ty::provide_extern(&mut extern_providers);
     traits::provide_extern(&mut extern_providers);
@@ -942,15 +987,16 @@ macro_rules! try_with_f {
 
     // These next passes must be executed together
     passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AddCallGuards);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::CriticalCallEdges);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::elaborate_drops::ElaborateDrops);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
+    // AddValidation needs to run after ElaborateDrops and before EraseRegions, and it needs
+    // an AllCallEdges pass right before it.
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AllCallEdges);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_validation::AddValidation);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyCfg::new("elaborate-drops"));
     // No lifetime analysis based on borrowing can be done from here on out.
 
-    // AddValidation needs to run after ElaborateDrops and before EraseRegions.
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_validation::AddValidation);
-
     // From here on out, regions are gone.
     passes.push_pass(MIR_OPTIMIZED, mir::transform::erase_regions::EraseRegions);
 
@@ -960,7 +1006,7 @@ macro_rules! try_with_f {
     passes.push_pass(MIR_OPTIMIZED, mir::transform::deaggregator::Deaggregator);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::copy_prop::CopyPropagation);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyLocals);
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AddCallGuards);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::CriticalCallEdges);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::dump_mir::Marker("PreTrans"));
 
     TyCtxt::create_and_enter(sess,
@@ -1056,6 +1102,7 @@ macro_rules! try_with_f {
 
 /// Run the translation phase to LLVM, after which the AST and analysis can
 /// be discarded.
+#[cfg(feature="llvm")]
 pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            analysis: ty::CrateAnalysis,
                                            incremental_hashes_map: IncrementalHashesMap,
@@ -1077,6 +1124,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 /// Run LLVM itself, producing a bitcode file, assembly file or object file
 /// as a side effect.
+#[cfg(feature="llvm")]
 pub fn phase_5_run_llvm_passes(sess: &Session,
                                trans: write::OngoingCrateTranslation)
                                -> (CompileResult, trans::CrateTranslation) {
@@ -1095,6 +1143,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
 
 /// Run the linker on any artifacts that resulted from the LLVM run.
 /// This should produce either a finished executable or library.
+#[cfg(feature="llvm")]
 pub fn phase_6_link_output(sess: &Session,
                            trans: &trans::CrateTranslation,
                            outputs: &OutputFilenames) {
@@ -1116,7 +1165,12 @@ fn write_out_deps(sess: &Session, outputs: &OutputFilenames, crate_name: &str) {
         match *output_type {
             OutputType::Exe => {
                 for output in sess.crate_types.borrow().iter() {
-                    let p = link::filename_for_input(sess, *output, crate_name, outputs);
+                    let p = ::rustc_trans_utils::link::filename_for_input(
+                        sess,
+                        *output,
+                        crate_name,
+                        outputs
+                    );
                     out_filenames.push(p);
                 }
             }
@@ -1194,10 +1248,10 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
                          }
                          Some(ref n) if *n == "bin" => 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
                          }
                          _ => {
@@ -1226,7 +1280,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
     if base.is_empty() {
         base.extend(attr_types);
         if base.is_empty() {
-            base.push(link::default_output_for_target(session));
+            base.push(::rustc_trans_utils::link::default_output_for_target(session));
         }
         base.sort();
         base.dedup();
@@ -1234,7 +1288,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
 
     base.into_iter()
         .filter(|crate_type| {
-            let res = !link::invalid_output_for_target(session, *crate_type);
+            let res = !::rustc_trans_utils::link::invalid_output_for_target(session, *crate_type);
 
             if !res {
                 session.warn(&format!("dropping unsupported crate type `{}` for target `{}`",
index 4c337993468e6803eb82e1e1912254401769573a..91ba7ed1958e7c85299cf4795b54fc30ddcc486b 100644 (file)
 #![feature(rustc_diagnostic_macros)]
 #![feature(set_stdio)]
 
+#[cfg(not(feature="llvm"))]
+extern crate ar;
+
 extern crate arena;
 extern crate getopts;
 extern crate graphviz;
 extern crate env_logger;
+#[cfg(not(feature="llvm"))]
+extern crate owning_ref;
 extern crate libc;
 extern crate rustc;
 extern crate rustc_allocator;
@@ -49,7 +54,9 @@
 extern crate rustc_mir;
 extern crate rustc_resolve;
 extern crate rustc_save_analysis;
+#[cfg(feature="llvm")]
 extern crate rustc_trans;
+extern crate rustc_trans_utils;
 extern crate rustc_typeck;
 extern crate serialize;
 #[macro_use]
@@ -64,7 +71,7 @@
 use rustc_resolve as resolve;
 use rustc_save_analysis as save;
 use rustc_save_analysis::DumpHandler;
-use rustc_trans::back::link;
+#[cfg(feature="llvm")]
 use rustc_trans::back::write::{RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS};
 use rustc::dep_graph::DepGraph;
 use rustc::session::{self, config, Session, build_session, CompileResult};
 use rustc::session::{early_error, early_warn};
 use rustc::lint::Lint;
 use rustc::lint;
+#[cfg(not(feature="llvm"))]
+use rustc::middle::cstore::MetadataLoader as MetadataLoaderTrait;
 use rustc_metadata::locator;
 use rustc_metadata::cstore::CStore;
 use rustc::util::common::{time, ErrorReported};
+#[cfg(not(feature="llvm"))]
+use rustc_back::target::Target;
 
 use serialize::json::ToJson;
 
 use std::io::{self, Read, Write};
 use std::iter::repeat;
 use std::path::PathBuf;
+#[cfg(not(feature="llvm"))]
+use std::path::Path;
 use std::process::{self, Command, Stdio};
 use std::rc::Rc;
 use std::str;
 use syntax::parse::{self, PResult};
 use syntax_pos::{DUMMY_SP, MultiSpan};
 
+#[cfg(not(feature="llvm"))]
+use owning_ref::{OwningRef, ErasedBoxRef};
+
 #[cfg(test)]
 pub mod test;
 
 pub mod driver;
 pub mod pretty;
+#[cfg(feature="llvm")]
 pub mod target_features;
 mod derive_registrar;
 
@@ -151,9 +168,49 @@ pub fn run<F>(run_compiler: F) -> isize
     0
 }
 
+#[cfg(not(feature="llvm"))]
+pub struct NoLLvmMetadataLoader;
+
+#[cfg(not(feature="llvm"))]
+pub use NoLLvmMetadataLoader as MetadataLoader;
+#[cfg(feature="llvm")]
+pub use rustc_trans::LlvmMetadataLoader as MetadataLoader;
+
+#[cfg(not(feature="llvm"))]
+impl MetadataLoaderTrait for NoLLvmMetadataLoader {
+    fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
+        use std::fs::File;
+        use std::io;
+        use self::ar::Archive;
+
+        let file = File::open(filename).map_err(|e|format!("metadata file open err: {:?}", e))?;
+        let mut archive = Archive::new(file);
+
+        while let Some(entry_result) = archive.next_entry() {
+            let mut entry = entry_result.map_err(|e|format!("metadata section read err: {:?}", e))?;
+            if entry.header().identifier() == "rust.metadata.bin" {
+                let mut buf = Vec::new();
+                io::copy(&mut entry, &mut buf).unwrap();
+                let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
+                return Ok(buf.map_owner_box().erase_owner());
+            }
+        }
+
+        Err("Couldnt find metadata section".to_string())
+    }
+
+    fn get_dylib_metadata(&self,
+                          _target: &Target,
+                          _filename: &Path)
+                          -> Result<ErasedBoxRef<[u8]>, String> {
+        panic!("Dylib metadata loading not supported without LLVM")
+    }
+}
+
 // Parse args and run the compiler. This is the primary entry point for rustc.
 // See comments on CompilerCalls below for details about the callbacks argument.
 // The FileLoader provides a way to load files from sources other than the file system.
+#[cfg_attr(not(feature="llvm"), allow(unused_mut))]
 pub fn run_compiler<'a>(args: &[String],
                         callbacks: &mut CompilerCalls<'a>,
                         file_loader: Option<Box<FileLoader + 'static>>,
@@ -175,6 +232,7 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
     let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
 
     if sopts.debugging_opts.debug_llvm {
+        #[cfg(feature="llvm")]
         rustc_trans::enable_llvm_debug();
     }
 
@@ -197,17 +255,19 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
     };
 
     let dep_graph = DepGraph::new(sopts.build_dep_graph());
-    let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
+    let cstore = Rc::new(CStore::new(&dep_graph, box ::MetadataLoader));
 
     let loader = file_loader.unwrap_or(box RealFileLoader);
     let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
     let mut sess = session::build_session_with_codemap(
         sopts, &dep_graph, input_file_path, descriptions, cstore.clone(), codemap, emitter_dest,
     );
+    #[cfg(feature="llvm")]
     rustc_trans::init(&sess);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
     let mut cfg = config::build_configuration(&sess, cfg);
+    #[cfg(feature="llvm")]
     target_features::add_configuration(&mut cfg, &sess);
     sess.parse_sess.config = cfg;
 
@@ -422,7 +482,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;
                 }
@@ -460,6 +520,7 @@ fn early_callback(&mut self,
         Compilation::Continue
     }
 
+    #[cfg_attr(not(feature="llvm"), allow(unused_mut))]
     fn no_input(&mut self,
                 matches: &getopts::Matches,
                 sopts: &config::Options,
@@ -477,15 +538,17 @@ fn no_input(&mut self,
                     return None;
                 }
                 let dep_graph = DepGraph::new(sopts.build_dep_graph());
-                let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
+                let cstore = Rc::new(CStore::new(&dep_graph, box ::MetadataLoader));
                 let mut sess = build_session(sopts.clone(),
                     &dep_graph,
                     None,
                     descriptions.clone(),
                     cstore.clone());
+                #[cfg(feature="llvm")]
                 rustc_trans::init(&sess);
                 rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
                 let mut cfg = config::build_configuration(&sess, cfg.clone());
+                #[cfg(feature="llvm")]
                 target_features::add_configuration(&mut cfg, &sess);
                 sess.parse_sess.config = cfg;
                 let should_stop =
@@ -518,7 +581,8 @@ fn build_controller(&mut self,
                         -> 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;
+        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) {
@@ -574,19 +638,7 @@ fn build_controller(&mut self,
         }
 
         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 +655,23 @@ fn build_controller(&mut self,
     }
 }
 
+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
 }
@@ -672,14 +741,19 @@ fn print_crate_info(sess: &Session,
                     };
                     let attrs = attrs.as_ref().unwrap();
                     let t_outputs = driver::build_output_filenames(input, odir, ofile, attrs, sess);
-                    let id = link::find_crate_name(Some(sess), attrs, input);
+                    let id = rustc_trans_utils::link::find_crate_name(Some(sess), attrs, input);
                     if *req == PrintRequest::CrateName {
                         println!("{}", id);
                         continue;
                     }
                     let crate_types = driver::collect_crate_types(sess, attrs);
                     for &style in &crate_types {
-                        let fname = link::filename_for_input(sess, style, &id, &t_outputs);
+                        let fname = rustc_trans_utils::link::filename_for_input(
+                            sess,
+                            style,
+                            &id,
+                            &t_outputs
+                        );
                         println!("{}",
                                  fname.file_name()
                                       .unwrap()
@@ -728,6 +802,7 @@ fn print_crate_info(sess: &Session,
                 }
                 PrintRequest::RelocationModels => {
                     println!("Available relocation models:");
+                    #[cfg(feature="llvm")]
                     for &(name, _) in RELOC_MODEL_ARGS.iter() {
                         println!("    {}", name);
                     }
@@ -735,13 +810,17 @@ fn print_crate_info(sess: &Session,
                 }
                 PrintRequest::CodeModels => {
                     println!("Available code models:");
+                    #[cfg(feature="llvm")]
                     for &(name, _) in CODE_GEN_MODEL_ARGS.iter(){
                         println!("    {}", name);
                     }
                     println!("");
                 }
                 PrintRequest::TargetCPUs | PrintRequest::TargetFeatures => {
+                    #[cfg(feature="llvm")]
                     rustc_trans::print(*req, sess);
+                    #[cfg(not(feature="llvm"))]
+                    panic!("LLVM not supported by this rustc")
                 }
             }
         }
@@ -780,6 +859,7 @@ fn unw(x: Option<&str>) -> &str {
         println!("commit-date: {}", unw(commit_date_str()));
         println!("host: {}", config::host_triple());
         println!("release: {}", unw(release_str()));
+        #[cfg(feature="llvm")]
         rustc_trans::print_version();
     }
 }
@@ -1077,6 +1157,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
     }
 
     if cg_flags.contains(&"passes=list".to_string()) {
+        #[cfg(feature="llvm")]
         rustc_trans::print_passes();
         return None;
     }
@@ -1204,6 +1285,7 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
     all_errors.extend_from_slice(&rustc_borrowck::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS);
+    #[cfg(feature="llvm")]
     all_errors.extend_from_slice(&rustc_trans::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_const_eval::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS);
@@ -1215,7 +1297,7 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
     Registry::new(&all_errors)
 }
 
-fn get_args() -> Vec<String> {
+pub fn get_args() -> Vec<String> {
     env::args_os().enumerate()
         .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| {
              early_error(ErrorOutputType::default(),
index 62e20a90f8a0860e3b37543472a4e1390d062085..7f65a8b97cd669b76297f14ea01d9681151982bd 100644 (file)
@@ -14,6 +14,7 @@
 use rustc::dep_graph::DepGraph;
 use rustc_lint;
 use rustc_resolve::MakeGlobMap;
+#[cfg(feature="llvm")]
 use rustc_trans;
 use rustc::middle::lang_items;
 use rustc::middle::free_region::FreeRegionMap;
@@ -106,20 +107,23 @@ fn test_env<F>(source_string: &str,
 
     let dep_graph = DepGraph::new(false);
     let _ignore = dep_graph.in_ignore();
-    let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
+    let cstore = Rc::new(CStore::new(&dep_graph, box ::MetadataLoader));
     let sess = session::build_session_(options,
                                        &dep_graph,
                                        None,
                                        diagnostic_handler,
                                        Rc::new(CodeMap::new(FilePathMapping::empty())),
                                        cstore.clone());
+    #[cfg(feature="llvm")]
     rustc_trans::init(&sess);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
     let input = config::Input::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,
index db27fa874f4e91091b900d610845cd3acc891c58..88432e64290316a85ef0bf6b35398fcea7feda13 100644 (file)
@@ -36,7 +36,7 @@
 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 @@ fn check_fn(&mut self,
             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();
         }
 
index e8b0dea1e8ac0285d9dc9a0e99d4baf395a9a2c2..d2ab9b2fbced359c497376a5f550c7cce1de0389 100644 (file)
@@ -479,7 +479,7 @@ fn visible_parent_map<'a>(&'a self, sess: &Session) -> ::std::cell::Ref<'a, DefI
                 _ => {},
             }
 
-            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();
 
index c35d8407c9d3c4f24ee55c5da2beb13d7409bfa6..8a753a0ae4b573e1a32b53b893dd90dbe262f257 100644 (file)
@@ -563,7 +563,7 @@ fn encode_info_for_mod(&mut self,
         Entry {
             kind: EntryKind::Mod(self.lazy(&data)),
             visibility: self.lazy(&ty::Visibility::from_hir(vis, id, tcx)),
-            span: self.lazy(&md.inner),
+            span: self.lazy(&tcx.def_span(def_id)),
             attributes: self.encode_attributes(attrs),
             children: self.lazy_seq(md.item_ids.iter().map(|item_id| {
                 tcx.hir.local_def_id(item_id.id).index
index 54f285480ab5371506e6fb1d3a7b78fb35f6a5a3..c0b54ce2a84decf7947e90f58321115103895471 100644 (file)
@@ -206,7 +206,7 @@ pub fn schedule_drop_for_binding(&mut self, var: NodeId, span: Span) {
         self.schedule_drop(span, extent, &Lvalue::Local(local_id), var_ty);
     }
 
-    pub fn visit_bindings<F>(&mut self, pattern: &Pattern<'tcx>, mut f: &mut F)
+    pub fn visit_bindings<F>(&mut self, pattern: &Pattern<'tcx>, f: &mut F)
         where F: FnMut(&mut Self, Mutability, Name, NodeId, Span, Ty<'tcx>)
     {
         match *pattern.kind {
index 11ad5d1509d29bcd17b2cd0bb1c541986de4cf31..62e762be93a71938a7a3f93ccfdc40d1186a43f7 100644 (file)
@@ -105,7 +105,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
         debug!("make_shim({:?}) = untransformed {:?}", instance, result);
         no_landing_pads::no_landing_pads(tcx, &mut result);
         simplify::simplify_cfg(&mut result);
-        add_call_guards::add_call_guards(&mut result);
+        add_call_guards::CriticalCallEdges.add_call_guards(&mut result);
     debug!("make_shim({:?}) = {:?}", instance, result);
 
     tcx.alloc_mir(result)
index b7c7a1774dd356f3ab2aac43decccb7002904a36..23a9c4c57ca6a39b107b2fef139c8540e3145457 100644 (file)
 use rustc::mir::transform::{MirPass, MirSource};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 
-pub struct AddCallGuards;
+#[derive(PartialEq)]
+pub enum AddCallGuards {
+    AllCallEdges,
+    CriticalCallEdges,
+}
+pub use self::AddCallGuards::*;
 
 /**
  * Breaks outgoing critical edges for call terminators in the MIR.
@@ -40,48 +45,52 @@ fn run_pass<'a, 'tcx>(&self,
                           _tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _src: MirSource,
                           mir: &mut Mir<'tcx>) {
-        add_call_guards(mir);
+        self.add_call_guards(mir);
     }
 }
 
-pub fn add_call_guards(mir: &mut Mir) {
-    let pred_count: IndexVec<_, _> =
-        mir.predecessors().iter().map(|ps| ps.len()).collect();
+impl AddCallGuards {
+    pub fn add_call_guards(&self, mir: &mut Mir) {
+        let pred_count: IndexVec<_, _> =
+            mir.predecessors().iter().map(|ps| ps.len()).collect();
 
-    // We need a place to store the new blocks generated
-    let mut new_blocks = Vec::new();
+        // We need a place to store the new blocks generated
+        let mut new_blocks = Vec::new();
 
-    let cur_len = mir.basic_blocks().len();
+        let cur_len = mir.basic_blocks().len();
 
-    for block in mir.basic_blocks_mut() {
-        match block.terminator {
-            Some(Terminator {
-                kind: TerminatorKind::Call {
-                    destination: Some((_, ref mut destination)),
-                    cleanup: Some(_),
-                    ..
-                }, source_info
-            }) if pred_count[*destination] > 1 => {
-                // It's a critical edge, break it
-                let call_guard = BasicBlockData {
-                    statements: vec![],
-                    is_cleanup: block.is_cleanup,
-                    terminator: Some(Terminator {
-                        source_info: source_info,
-                        kind: TerminatorKind::Goto { target: *destination }
-                    })
-                };
+        for block in mir.basic_blocks_mut() {
+            match block.terminator {
+                Some(Terminator {
+                    kind: TerminatorKind::Call {
+                        destination: Some((_, ref mut destination)),
+                        cleanup,
+                        ..
+                    }, source_info
+                }) if pred_count[*destination] > 1 &&
+                      (cleanup.is_some() || self == &AllCallEdges) =>
+                {
+                    // It's a critical edge, break it
+                    let call_guard = BasicBlockData {
+                        statements: vec![],
+                        is_cleanup: block.is_cleanup,
+                        terminator: Some(Terminator {
+                            source_info: source_info,
+                            kind: TerminatorKind::Goto { target: *destination }
+                        })
+                    };
 
-                // Get the index it will be when inserted into the MIR
-                let idx = cur_len + new_blocks.len();
-                new_blocks.push(call_guard);
-                *destination = BasicBlock::new(idx);
+                    // Get the index it will be when inserted into the MIR
+                    let idx = cur_len + new_blocks.len();
+                    new_blocks.push(call_guard);
+                    *destination = BasicBlock::new(idx);
+                }
+                _ => {}
             }
-            _ => {}
         }
-    }
 
-    debug!("Broke {} N edges", new_blocks.len());
+        debug!("Broke {} N edges", new_blocks.len());
 
-    mir.basic_blocks_mut().extend(new_blocks);
+        mir.basic_blocks_mut().extend(new_blocks);
+    }
 }
index 3273b4ff347e562d224844c70954cef3f799d13d..fb4764c4962682bef62e135f33050ff536f09465 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::ty::TyCtxt;
-use rustc::mir::Mir;
-use rustc::mir::visit::MutVisitor;
+use rustc::ty::TypeFoldable;
+use rustc::ty::subst::{Kind, Substs};
+use rustc::ty::{Ty, TyCtxt, ClosureSubsts, RegionVid, RegionKind};
+use rustc::mir::{Mir, Location, Rvalue, BasicBlock, Statement, StatementKind};
+use rustc::mir::visit::{MutVisitor, Lookup};
 use rustc::mir::transform::{MirPass, MirSource};
+use rustc::infer::{self, InferCtxt};
+use syntax_pos::DUMMY_SP;
+use std::collections::HashMap;
 
 #[allow(dead_code)]
-struct NLLVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
+    lookup_map: HashMap<RegionVid, Lookup>,
+    infcx: InferCtxt<'a, 'gcx, 'tcx>,
 }
 
-impl<'a, 'tcx> NLLVisitor<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
+impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
+    pub fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self {
         NLLVisitor {
-            tcx: tcx
+            infcx: infcx,
+            lookup_map: HashMap::new(),
+        }
+    }
+
+    pub fn into_results(self) -> HashMap<RegionVid, Lookup> {
+        self.lookup_map
+    }
+
+    fn renumber_regions<T>(&self, value: &T) -> T where T: TypeFoldable<'tcx> {
+        self.infcx.tcx.fold_regions(value, &mut false, |_region, _depth| {
+            self.infcx.next_region_var(infer::MiscVariable(DUMMY_SP))
+        })
+    }
+
+    fn store_region(&mut self, region: &RegionKind, lookup: Lookup) {
+        if let RegionKind::ReVar(rid) = *region {
+            self.lookup_map.entry(rid).or_insert(lookup);
+        }
+    }
+
+    fn store_ty_regions(&mut self, ty: &Ty<'tcx>, lookup: Lookup) {
+        for region in ty.regions() {
+            self.store_region(region, lookup);
+        }
+    }
+
+    fn store_kind_regions(&mut self, kind: &'tcx Kind, lookup: Lookup) {
+        if let Some(ty) = kind.as_type() {
+            self.store_ty_regions(&ty, lookup);
+        } else if let Some(region) = kind.as_region() {
+            self.store_region(region, lookup);
         }
     }
 }
 
-impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> {
-    // FIXME: Nashenas88: implement me!
+impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
+    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, lookup: Lookup) {
+        let old_ty = *ty;
+        *ty = self.renumber_regions(&old_ty);
+        self.store_ty_regions(ty, lookup);
+    }
+
+    fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
+        *substs = self.renumber_regions(&{*substs});
+        let lookup = Lookup::Loc(location);
+        for kind in *substs {
+            self.store_kind_regions(kind, lookup);
+        }
+    }
+
+    fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
+        match *rvalue {
+            Rvalue::Ref(ref mut r, _, _) => {
+                let old_r = *r;
+                *r = self.renumber_regions(&old_r);
+                let lookup = Lookup::Loc(location);
+                self.store_region(r, lookup);
+            }
+            Rvalue::Use(..) |
+            Rvalue::Repeat(..) |
+            Rvalue::Len(..) |
+            Rvalue::Cast(..) |
+            Rvalue::BinaryOp(..) |
+            Rvalue::CheckedBinaryOp(..) |
+            Rvalue::UnaryOp(..) |
+            Rvalue::Discriminant(..) |
+            Rvalue::NullaryOp(..) |
+            Rvalue::Aggregate(..) => {
+                // These variants don't contain regions.
+            }
+        }
+        self.super_rvalue(rvalue, location);
+    }
+
+    fn visit_closure_substs(&mut self,
+                            substs: &mut ClosureSubsts<'tcx>,
+                            location: Location) {
+        *substs = self.renumber_regions(substs);
+        let lookup = Lookup::Loc(location);
+        for kind in substs.substs {
+            self.store_kind_regions(kind, lookup);
+        }
+    }
+
+    fn visit_statement(&mut self,
+                       block: BasicBlock,
+                       statement: &mut Statement<'tcx>,
+                       location: Location) {
+        if let StatementKind::EndRegion(_) = statement.kind {
+            statement.kind = StatementKind::Nop;
+        }
+        self.super_statement(block, statement, location);
+    }
 }
 
 // MIR Pass for non-lexical lifetimes
@@ -38,10 +131,16 @@ fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _: MirSource,
                           mir: &mut Mir<'tcx>) {
-        if tcx.sess.opts.debugging_opts.nll {
-            // Clone mir so we can mutate it without disturbing the rest
-            // of the compiler
-            NLLVisitor::new(tcx).visit_mir(&mut mir.clone());
+        if !tcx.sess.opts.debugging_opts.nll {
+            return;
         }
+
+        tcx.infer_ctxt().enter(|infcx| {
+            // Clone mir so we can mutate it without disturbing the rest of the compiler
+            let mut renumbered_mir = mir.clone();
+            let mut visitor = NLLVisitor::new(infcx);
+            visitor.visit_mir(&mut renumbered_mir);
+            let _results = visitor.into_results();
+        })
     }
 }
\ No newline at end of file
index 1c7899a46d1d760eb2d854a79c0ce31af6cbdd31..f3a82b54063b4710c1fd594c0f0aa093b8784505 100644 (file)
@@ -721,7 +721,7 @@ fn normalize<T>(&mut self, value: &T) -> T
                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);
         }
index 38d8555334c355192d8563f25fbe9c1ea154f94e..2643ed2a3c07459faef968f4cfbf8c3e5d1b9d0f 100644 (file)
@@ -237,10 +237,11 @@ fn visit_item(&mut self, item: &'a Item) {
                         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 @@ fn visit_item(&mut self, item: &'a Item) {
                 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, _) => {
index a881bf9eac7bf5d65909bb9303e31336bdba27d5..8443cc8267d1c87dc1fad2fe439cbd846db361ab 100644 (file)
@@ -76,12 +76,12 @@ fn check_const_eval(&self, expr: &'gcx hir::Expr) {
                 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 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
                     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());
                 }
             }
         }
index 907a258a12dc68063df770b6ab2425a0bd40635e..1bfa5943ee90a1849851be8459648cfa34b6018e 100644 (file)
@@ -223,6 +223,40 @@ fn foo() {}
 ```
 '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 @@ fn foo() {}
     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
 }
index 64af24d92eecb5f47304e5048b12f22d827b0b02..9fa5fea20d915885d4e3ab06194751fe79efa6ad 100644 (file)
@@ -781,7 +781,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             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 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             }
             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();
@@ -1345,11 +1345,11 @@ fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'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 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                         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));
                     }
                 }
             }
index d150ff1ff81f55e6eb8cb7d5624bb0679556c568..a8bb6619bbdda4b7ff9993e4bc27107df2da5b57 100644 (file)
@@ -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);
     }
 }
index 2317e36a0ab89a64a7041d944619fe79f9923e6d..b4f9ba4e8f78f29dbf961b707988156ac8192800 100644 (file)
@@ -2552,9 +2552,10 @@ fn smart_resolve_path_fragment(&mut self,
                                 = 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 @@ fn resolve_qpath(&mut self,
             };
             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 @@ fn report_errors(&mut self) {
                 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 @@ fn report_conflict(&mut self,
 
     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]) {
index 4d4f6aadce4df343bb92c9c9f327503f8df9e1c7..98eaa056177ef13c39f51fd05d9128df5dfdaa97 100644 (file)
@@ -319,8 +319,8 @@ fn check_unused_macros(&self) {
             };
             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");
             }
index 5e799b14f209c9071d06b043e8cbdfa1d1e4aa0f..26c398379dc83256c906a843b2f59639be5b8c0a 100644 (file)
@@ -379,7 +379,7 @@ fn update_resolution<T, F>(&mut self, module: Module<'a>, ident: Ident, ns: Name
         // 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);
@@ -745,8 +745,10 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
                 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)
index ed9321cc3f3a1197dd97f45703cdfd53ebd50080..4a92a5798604af01b25330400c3873acc0b0a3ea 100644 (file)
@@ -26,6 +26,7 @@ rustc_errors = { path = "../librustc_errors" }
 rustc_incremental = { path = "../librustc_incremental" }
 rustc_llvm = { path = "../librustc_llvm" }
 rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
+rustc_trans_utils = { path = "../librustc_trans_utils" }
 serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
index 5e85771217b95e0253e99c6287a2a152bea43ece..a9bd8ea90109e24316c7b4a150802d389c36a95b 100644 (file)
@@ -8,16 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+extern crate rustc_trans_utils;
+
 use super::archive::{ArchiveBuilder, ArchiveConfig};
 use super::linker::Linker;
 use super::rpath::RPathConfig;
 use super::rpath;
 use metadata::METADATA_FILENAME;
-use rustc::session::config::{self, NoDebugInfo, OutputFilenames, Input, OutputType};
+use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType};
 use rustc::session::filesearch;
 use rustc::session::search_paths::PathKind;
 use rustc::session::Session;
-use rustc::middle::cstore::{self, LinkMeta, NativeLibrary, LibSource, LinkagePreference,
+use rustc::middle::cstore::{LinkMeta, NativeLibrary, LibSource, LinkagePreference,
                             NativeLibraryKind};
 use rustc::middle::dependency_format::Linkage;
 use CrateTranslation;
@@ -44,9 +46,7 @@
 use std::str;
 use flate2::Compression;
 use flate2::write::DeflateEncoder;
-use syntax::ast;
 use syntax::attr;
-use syntax_pos::Span;
 
 /// The LLVM module name containing crate-metadata. This includes a `.` on
 /// purpose, so it cannot clash with the name of a user-defined module.
 pub const RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET: usize =
     RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET + 8;
 
-
-pub fn find_crate_name(sess: Option<&Session>,
-                       attrs: &[ast::Attribute],
-                       input: &Input) -> String {
-    let validate = |s: String, span: Option<Span>| {
-        cstore::validate_crate_name(sess, &s, span);
-        s
-    };
-
-    // Look in attributes 100% of the time to make sure the attribute is marked
-    // as used. After doing this, however, we still prioritize a crate name from
-    // the command line over one found in the #[crate_name] attribute. If we
-    // find both we ensure that they're the same later on as well.
-    let attr_crate_name = attrs.iter().find(|at| at.check_name("crate_name"))
-                               .and_then(|at| at.value_str().map(|s| (at, s)));
-
-    if let Some(sess) = sess {
-        if let Some(ref s) = sess.opts.crate_name {
-            if let Some((attr, name)) = attr_crate_name {
-                if name != &**s {
-                    let msg = format!("--crate-name and #[crate_name] are \
-                                       required to match, but `{}` != `{}`",
-                                      s, name);
-                    sess.span_err(attr.span, &msg);
-                }
-            }
-            return validate(s.clone(), None);
-        }
-    }
-
-    if let Some((attr, s)) = attr_crate_name {
-        return validate(s.to_string(), Some(attr.span));
-    }
-    if let Input::File(ref path) = *input {
-        if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
-            if s.starts_with("-") {
-                let msg = format!("crate names cannot start with a `-`, but \
-                                   `{}` has a leading hyphen", s);
-                if let Some(sess) = sess {
-                    sess.err(&msg);
-                }
-            } else {
-                return validate(s.replace("-", "_"), None);
-            }
-        }
-    }
-
-    "rust_out".to_string()
-}
+pub use self::rustc_trans_utils::link::{find_crate_name, filename_for_input,
+                                        default_output_for_target, invalid_output_for_target};
 
 pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap) -> LinkMeta {
     let krate_dep_node = &DepNode::new_no_params(DepKind::Krate);
@@ -252,37 +205,6 @@ pub fn link_binary(sess: &Session,
     out_filenames
 }
 
-
-/// Returns default crate type for target
-///
-/// Default crate type is used when crate type isn't provided neither
-/// through cmd line arguments nor through crate attributes
-///
-/// It is CrateTypeExecutable for all platforms but iOS as there is no
-/// way to run iOS binaries anyway without jailbreaking and
-/// interaction with Rust code through static library is the only
-/// option for now
-pub fn default_output_for_target(sess: &Session) -> config::CrateType {
-    if !sess.target.target.options.executables {
-        config::CrateTypeStaticlib
-    } else {
-        config::CrateTypeExecutable
-    }
-}
-
-/// Checks if target supports crate_type as output
-pub fn invalid_output_for_target(sess: &Session,
-                                 crate_type: config::CrateType) -> bool {
-    match (sess.target.target.options.dynamic_linking,
-           sess.target.target.options.executables, crate_type) {
-        (false, _, config::CrateTypeCdylib) |
-        (false, _, config::CrateTypeProcMacro) |
-        (false, _, config::CrateTypeDylib) => true,
-        (_, false, config::CrateTypeExecutable) => true,
-        _ => false
-    }
-}
-
 fn is_writeable(p: &Path) -> bool {
     match p.metadata() {
         Err(..) => true,
@@ -299,42 +221,6 @@ fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilen
     out_filename
 }
 
-pub fn filename_for_input(sess: &Session,
-                          crate_type: config::CrateType,
-                          crate_name: &str,
-                          outputs: &OutputFilenames) -> PathBuf {
-    let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
-
-    match crate_type {
-        config::CrateTypeRlib => {
-            outputs.out_directory.join(&format!("lib{}.rlib", libname))
-        }
-        config::CrateTypeCdylib |
-        config::CrateTypeProcMacro |
-        config::CrateTypeDylib => {
-            let (prefix, suffix) = (&sess.target.target.options.dll_prefix,
-                                    &sess.target.target.options.dll_suffix);
-            outputs.out_directory.join(&format!("{}{}{}", prefix, libname,
-                                                suffix))
-        }
-        config::CrateTypeStaticlib => {
-            let (prefix, suffix) = (&sess.target.target.options.staticlib_prefix,
-                                    &sess.target.target.options.staticlib_suffix);
-            outputs.out_directory.join(&format!("{}{}{}", prefix, libname,
-                                                suffix))
-        }
-        config::CrateTypeExecutable => {
-            let suffix = &sess.target.target.options.exe_suffix;
-            let out_filename = outputs.path(OutputType::Exe);
-            if suffix.is_empty() {
-                out_filename.to_path_buf()
-            } else {
-                out_filename.with_extension(&suffix[1..])
-            }
-        }
-    }
-}
-
 pub fn each_linked_rlib(sess: &Session,
                         f: &mut FnMut(CrateNum, &Path)) -> Result<(), String> {
     let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic).into_iter();
index 72071f8cec99006793a4a5df09d9c7f246fa95d7..971483e91b6f341d13743ffd901e87385775d549 100644 (file)
@@ -13,6 +13,7 @@
 use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE, INVALID_CRATE, CRATE_DEF_INDEX};
 use rustc::session::config;
 use rustc::ty::TyCtxt;
+use rustc_allocator::ALLOCATOR_METHODS;
 use syntax::attr;
 
 /// The SymbolExportLevel of a symbols specifies from which kinds of crates
@@ -83,6 +84,14 @@ pub fn compute<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               SymbolExportLevel::C));
         }
 
+        if tcx.sess.allocator_kind.get().is_some() {
+            for method in ALLOCATOR_METHODS {
+                local_crate.push((format!("__rust_{}", method.name),
+                                  INVALID_DEF_ID,
+                                  SymbolExportLevel::Rust));
+            }
+        }
+
         if let Some(id) = tcx.sess.derive_registrar_fn.get() {
             let def_id = tcx.hir.local_def_id(id);
             let idx = def_id.index;
index e8032529b1fe4c54111becf6b30ecf0a6cc49ae2..8cbc5155ddeb721e793cf1565b1e72ba8ac58153 100644 (file)
@@ -1464,7 +1464,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() {
index cff0eca02c60ee4ccaea654f6d436bc8c86721c5..63c7b18e8d29054687c954031986ca60fa15a8b0 100644 (file)
@@ -335,7 +335,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) {
index e0ebe8a0933f128407f5ae79c640d7beb8729a50..ead6e432561294f048d716aeffb7c1e248e449a3 100644 (file)
@@ -70,7 +70,7 @@ pub fn start(&self,
         {
             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 @@ fn end(&self, timeline: TimelineId) {
         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 {
diff --git a/src/librustc_trans_utils/Cargo.toml b/src/librustc_trans_utils/Cargo.toml
new file mode 100644 (file)
index 0000000..f026d4f
--- /dev/null
@@ -0,0 +1,15 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_trans_utils"
+version = "0.0.0"
+
+[lib]
+name = "rustc_trans_utils"
+path = "lib.rs"
+crate-type = ["dylib"]
+test = false
+
+[dependencies]
+rustc = { path = "../librustc" }
+syntax = { path = "../libsyntax" }
+syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs
new file mode 100644 (file)
index 0000000..81e8307
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! # Note
+//!
+//! This API is completely unstable and subject to change.
+
+#![crate_name = "rustc_trans_utils"]
+#![crate_type = "dylib"]
+#![crate_type = "rlib"]
+#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+      html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![deny(warnings)]
+
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+#![feature(const_fn)]
+#![feature(custom_attribute)]
+#![allow(unused_attributes)]
+#![feature(i128_type)]
+#![feature(quote)]
+#![feature(rustc_diagnostic_macros)]
+#![feature(slice_patterns)]
+#![feature(conservative_impl_trait)]
+
+extern crate rustc;
+extern crate syntax;
+extern crate syntax_pos;
+
+pub mod link;
diff --git a/src/librustc_trans_utils/link.rs b/src/librustc_trans_utils/link.rs
new file mode 100644 (file)
index 0000000..29bb062
--- /dev/null
@@ -0,0 +1,154 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::session::config::{self, /*NoDebugInfo,*/ OutputFilenames, Input, OutputType};
+/*use rustc::session::filesearch;
+use rustc::session::search_paths::PathKind;
+*/use rustc::session::Session;
+use rustc::middle::cstore;/*::{self, LinkMeta, NativeLibrary, LibSource, LinkagePreference,
+                            NativeLibraryKind};*/
+/*use rustc::middle::dependency_format::Linkage;
+use rustc::util::common::time;
+use rustc::util::fs::fix_windows_verbatim_for_gcc;
+use rustc::dep_graph::{DepKind, DepNode};
+use rustc::hir::def_id::CrateNum;
+use rustc::hir::svh::Svh;
+use rustc_back::tempdir::TempDir;
+use rustc_back::{PanicStrategy, RelroLevel};
+use rustc_incremental::IncrementalHashesMap;*/
+
+/*use std::ascii;
+use std::char;
+use std::env;
+use std::ffi::OsString;
+use std::fs;
+use std::io::{self, Read, Write};
+use std::mem;
+*/use std::path::PathBuf;/*{Path, PathBuf};
+use std::process::Command;
+use std::str;*/
+use syntax::ast;
+//use syntax::attr;
+use syntax_pos::Span;
+
+pub fn find_crate_name(sess: Option<&Session>,
+                       attrs: &[ast::Attribute],
+                       input: &Input) -> String {
+    let validate = |s: String, span: Option<Span>| {
+        cstore::validate_crate_name(sess, &s, span);
+        s
+    };
+
+    // Look in attributes 100% of the time to make sure the attribute is marked
+    // as used. After doing this, however, we still prioritize a crate name from
+    // the command line over one found in the #[crate_name] attribute. If we
+    // find both we ensure that they're the same later on as well.
+    let attr_crate_name = attrs.iter().find(|at| at.check_name("crate_name"))
+                               .and_then(|at| at.value_str().map(|s| (at, s)));
+
+    if let Some(sess) = sess {
+        if let Some(ref s) = sess.opts.crate_name {
+            if let Some((attr, name)) = attr_crate_name {
+                if name != &**s {
+                    let msg = format!("--crate-name and #[crate_name] are \
+                                       required to match, but `{}` != `{}`",
+                                      s, name);
+                    sess.span_err(attr.span, &msg);
+                }
+            }
+            return validate(s.clone(), None);
+        }
+    }
+
+    if let Some((attr, s)) = attr_crate_name {
+        return validate(s.to_string(), Some(attr.span));
+    }
+    if let Input::File(ref path) = *input {
+        if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
+            if s.starts_with("-") {
+                let msg = format!("crate names cannot start with a `-`, but \
+                                   `{}` has a leading hyphen", s);
+                if let Some(sess) = sess {
+                    sess.err(&msg);
+                }
+            } else {
+                return validate(s.replace("-", "_"), None);
+            }
+        }
+    }
+
+    "rust_out".to_string()
+}
+
+pub fn filename_for_input(sess: &Session,
+                          crate_type: config::CrateType,
+                          crate_name: &str,
+                          outputs: &OutputFilenames) -> PathBuf {
+    let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
+
+    match crate_type {
+        config::CrateTypeRlib => {
+            outputs.out_directory.join(&format!("lib{}.rlib", libname))
+        }
+        config::CrateTypeCdylib |
+        config::CrateTypeProcMacro |
+        config::CrateTypeDylib => {
+            let (prefix, suffix) = (&sess.target.target.options.dll_prefix,
+                                    &sess.target.target.options.dll_suffix);
+            outputs.out_directory.join(&format!("{}{}{}", prefix, libname,
+                                                suffix))
+        }
+        config::CrateTypeStaticlib => {
+            let (prefix, suffix) = (&sess.target.target.options.staticlib_prefix,
+                                    &sess.target.target.options.staticlib_suffix);
+            outputs.out_directory.join(&format!("{}{}{}", prefix, libname,
+                                                suffix))
+        }
+        config::CrateTypeExecutable => {
+            let suffix = &sess.target.target.options.exe_suffix;
+            let out_filename = outputs.path(OutputType::Exe);
+            if suffix.is_empty() {
+                out_filename.to_path_buf()
+            } else {
+                out_filename.with_extension(&suffix[1..])
+            }
+        }
+    }
+}
+
+/// Returns default crate type for target
+///
+/// Default crate type is used when crate type isn't provided neither
+/// through cmd line arguments nor through crate attributes
+///
+/// It is CrateTypeExecutable for all platforms but iOS as there is no
+/// way to run iOS binaries anyway without jailbreaking and
+/// interaction with Rust code through static library is the only
+/// option for now
+pub fn default_output_for_target(sess: &Session) -> config::CrateType {
+    if !sess.target.target.options.executables {
+        config::CrateTypeStaticlib
+    } else {
+        config::CrateTypeExecutable
+    }
+}
+
+/// Checks if target supports crate_type as output
+pub fn invalid_output_for_target(sess: &Session,
+                                 crate_type: config::CrateType) -> bool {
+    match (sess.target.target.options.dynamic_linking,
+           sess.target.target.options.executables, crate_type) {
+        (false, _, config::CrateTypeCdylib) |
+        (false, _, config::CrateTypeProcMacro) |
+        (false, _, config::CrateTypeDylib) => true,
+        (_, false, config::CrateTypeExecutable) => true,
+        _ => false
+    }
+}
index 1ec850ad7f3494ab228869167a5f0f52736f81fd..2910d25486ed5ad714cf925f9ae24feaec9f71e6 100644 (file)
@@ -985,9 +985,9 @@ pub fn prohibit_parenthesized_params(&self, segment: &hir::PathSegment, emit_err
                     .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);
             }
         }
     }
index b3f62de5b570ba3e31b12d0a4cce12f676431727..5f256eab9a9c8383a800882b1aa62a4bb9bfeca9 100644 (file)
@@ -291,25 +291,25 @@ fn trivial_cast_lint(&self, fcx: &FnCtxt<'a, 'gcx, '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)));
         }
 
     }
index e494bc15222229face5d28a98d66a7ad6c1bdb4c..934a4f9b29689775498bf585460549d951b44843 100644 (file)
@@ -1204,7 +1204,7 @@ fn coerce_inner<'a>(&mut self,
                     }
                 }
 
-                if let Some(mut augment_error) = augment_error {
+                if let Some(augment_error) = augment_error {
                     augment_error(&mut db);
                 }
 
index dd5b0cdda42447233e639ef8e535e12d48efb0e9..1ccb1e64a98e088b1292155d6562b73f6d4e895e 100644 (file)
@@ -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<DefId>),
 
     // Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have
     // forgotten to import a trait.
index 881fc7a137095b0d01a92ec2d7b024e88cb9d073..7bf671d5e9f9376de47ef543d5842d935f692457 100644 (file)
@@ -556,7 +556,7 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
             // 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 = {:?}",
@@ -765,7 +765,7 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
             // 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);
 
@@ -1013,7 +1013,7 @@ fn pick(mut self) -> PickResult<'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,
index 53da9e19ee0cdff01d7a698433242e2b80015a35..56eacc3194d1c8404c60d7c8e6dc073cc768af5c 100644 (file)
@@ -311,9 +311,11 @@ macro_rules! report_function {
                 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 @@ fn suggest_use_candidates(&self,
         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<DefId>) {
+    fn suggest_valid_traits(&self,
+                            err: &mut DiagnosticBuilder,
+                            valid_out_of_scope_traits: Vec<DefId>) -> bool {
         if !valid_out_of_scope_traits.is_empty() {
             let mut candidates = valid_out_of_scope_traits;
             candidates.sort();
@@ -379,6 +377,20 @@ fn suggest_traits_to_import(&self,
                             });
 
             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<DefId>) {
+        if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
             return;
         }
 
index e53e5e7b08c97eb46644a981b076fa97b75305ed..697d9de931a86068973df2c5358193846905d77e 100644 (file)
@@ -1713,10 +1713,10 @@ fn warn_if_unreachable(&self, id: ast::NodeId, span: Span, kind: &str) {
 
             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));
         }
     }
 
@@ -3652,6 +3652,20 @@ fn check_expr_kind(&self,
                   // inside a loop at all, which is caught by the
                   // loop-checking pass.
                   assert!(self.tcx.sess.err_count() > 0);
+
+                  // We still need to assign a type to the inner expression to
+                  // prevent the ICE in #43162.
+                  if let Some(ref e) = *expr_opt {
+                      self.check_expr_with_hint(e, tcx.types.err);
+
+                      // ... except when we try to 'break rust;'.
+                      // ICE this expression in particular (see #43162).
+                      if let hir::ExprPath(hir::QPath::Resolved(_, ref path)) = e.node {
+                          if path.segments.len() == 1 && path.segments[0].name == "rust" {
+                              fatally_break_rust(self.tcx.sess);
+                          }
+                      }
+                  }
               }
 
               // the type of a `break` is always `!`, since it diverges
@@ -4016,7 +4030,7 @@ pub fn resolve_ty_and_def_ufcs<'b>(&self,
             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() {
@@ -4183,8 +4197,8 @@ fn check_block_with_expected(&self,
             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,
@@ -4229,8 +4243,8 @@ fn check_block_with_expected(&self,
         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.
@@ -4241,14 +4255,23 @@ pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> {
                 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))
@@ -4275,11 +4298,8 @@ pub fn suggest_mismatched_types_on_tail(&self,
                                             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);
         }
     }
 
@@ -4335,20 +4355,37 @@ fn suggest_missing_semicolon(&self,
     fn suggest_missing_return_type(&self,
                                    err: &mut DiagnosticBuilder<'tcx>,
                                    fn_decl: &hir::FnDecl,
-                                   ty: Ty<'tcx>) {
-
-        // Only recommend changing the return type for methods that
+                                   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).
-        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.
+                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 {
+                    err.span_label(sp, format!("expected `{}` because of return type",
+                                               expected));
+                }
+            }
         }
     }
 
@@ -4746,8 +4783,8 @@ fn check_path_parameter_count(&self,
             } 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;
         }
@@ -4857,3 +4894,20 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     }
 }
+
+fn fatally_break_rust(sess: &Session) {
+    let handler = sess.diagnostic();
+    handler.span_bug_no_panic(
+        MultiSpan::new(),
+        "It looks like you're trying to break rust; would you like some ICE?",
+    );
+    handler.note_without_error("the compiler expectedly panicked. this is a feature.");
+    handler.note_without_error(
+        "we would appreciate a joke overview: \
+        https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675"
+    );
+    handler.note_without_error(&format!("rustc {} running on {}",
+        option_env!("CFG_VERSION").unwrap_or("unknown_version"),
+        ::session::config::host_triple(),
+    ));
+}
index 032e37a34a887f7acbfa478029100309b4d4ffc3..c1711491ee48ca2427d0dbfc4f49d3dee71d160b 100644 (file)
@@ -300,7 +300,7 @@ fn check_str_addition(&self,
                           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;
index 0a323efabec1dd6c90d5697df6320621e8838899..9e5cf5137c21f9f18c66d153c40f7e2cba5b620c 100644 (file)
@@ -43,7 +43,6 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body)
         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 @@ fn visit_cast_types(&mut self) {
             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");
index 1af55d4d840d9b0fa852923539632a75a896c1b6..e95d49f00bf76614741c1f0a349c7fc40067155a 100644 (file)
@@ -39,7 +39,7 @@ fn check_import(&self, id: ast::NodeId, span: Span) {
         } 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);
     }
 }
 
index f25a6cf58a79e6f0f3887e72f338f35bcd9ef521..fba32dbb889d9f195c5e1630019365862271ce2c 100644 (file)
@@ -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."));
             }
         }
 
index 35ca19698e8cf94e1039b2a8db103f8a8a9ed918..c74dc24ddc3406583bbaa96eb2406787508ffff8 100644 (file)
@@ -1525,9 +1525,9 @@ fn foo() -> _ { 5 } // error, explicitly write out the return type instead
 "##,
 
 E0122: r##"
-An attempt was made to add a generic constraint to a type alias. While Rust will
-allow this with a warning, it will not currently enforce the constraint.
-Consider the example below:
+An attempt was made to add a generic constraint to a type alias. This constraint
+is entirely ignored. For backwards compatibility, Rust still allows this with a
+warning. Consider the example below:
 
 ```
 trait Foo{}
index 62b91feb09d0b62926b0d9b20a7b90750d867b83..e101e29fc6fbb8d86877264ac88dbd6891cef641 100644 (file)
@@ -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);
 
index fc0adef70baa1da01307f902724ac1e8650132ba..563c5618759b721a11fa64c2975764d0acd8f194 100644 (file)
@@ -2141,8 +2141,8 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
 
     if !types.is_empty() {
         write!(w, "
-            <h2 id='associated-types' class='section-header'>
-              <a href='#associated-types'>Associated Types</a>
+            <h2 id='associated-types' class='small-section-header'>
+              Associated Types<a href='#associated-types' class='anchor'></a>
             </h2>
             <div class='methods'>
         ")?;
@@ -2154,8 +2154,8 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
 
     if !consts.is_empty() {
         write!(w, "
-            <h2 id='associated-const' class='section-header'>
-              <a href='#associated-const'>Associated Constants</a>
+            <h2 id='associated-const' class='small-section-header'>
+              Associated Constants<a href='#associated-const' class='anchor'></a>
             </h2>
             <div class='methods'>
         ")?;
@@ -2168,8 +2168,8 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
     // Output the documentation for each function individually
     if !required.is_empty() {
         write!(w, "
-            <h2 id='required-methods' class='section-header'>
-              <a href='#required-methods'>Required Methods</a>
+            <h2 id='required-methods' class='small-section-header'>
+              Required Methods<a href='#required-methods' class='anchor'></a>
             </h2>
             <div class='methods'>
         ")?;
@@ -2180,8 +2180,8 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
     }
     if !provided.is_empty() {
         write!(w, "
-            <h2 id='provided-methods' class='section-header'>
-              <a href='#provided-methods'>Provided Methods</a>
+            <h2 id='provided-methods' class='small-section-header'>
+              Provided Methods<a href='#provided-methods' class='anchor'></a>
             </h2>
             <div class='methods'>
         ")?;
@@ -2196,8 +2196,8 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
 
     let cache = cache();
     write!(w, "
-        <h2 id='implementors' class='section-header'>
-          <a href='#implementors'>Implementors</a>
+        <h2 id='implementors' class='small-section-header'>
+          Implementors<a href='#implementors' class='anchor'></a>
         </h2>
         <ul class='item-list' id='implementors-list'>
     ")?;
@@ -2436,8 +2436,8 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     }).peekable();
     if let doctree::Plain = s.struct_type {
         if fields.peek().is_some() {
-            write!(w, "<h2 id='fields' class='fields section-header'>
-                       <a href='#fields'>Fields</a></h2>")?;
+            write!(w, "<h2 id='fields' class='fields small-section-header'>
+                       Fields<a href='#fields' class='anchor'></a></h2>")?;
             for (field, ty) in fields {
                 let id = derive_id(format!("{}.{}",
                                            ItemType::StructField,
@@ -2485,8 +2485,8 @@ fn item_union(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         }
     }).peekable();
     if fields.peek().is_some() {
-        write!(w, "<h2 id='fields' class='fields section-header'>
-                   <a href='#fields'>Fields</a></h2>")?;
+        write!(w, "<h2 id='fields' class='fields small-section-header'>
+                   Fields<a href='#fields' class='anchor'></a></h2>")?;
         for (field, ty) in fields {
             write!(w, "<span id='{shortty}.{name}' class=\"{shortty}\"><code>{name}: {ty}</code>
                        </span>",
@@ -2558,8 +2558,8 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
 
     document(w, cx, it)?;
     if !e.variants.is_empty() {
-        write!(w, "<h2 id='variants' class='variants section-header'>
-                   <a href='#variants'>Variants</a></h2>\n")?;
+        write!(w, "<h2 id='variants' class='variants small-section-header'>
+                   Variants<a href='#variants' class='anchor'></a></h2>\n")?;
         for variant in &e.variants {
             let id = derive_id(format!("{}.{}",
                                        ItemType::Variant,
@@ -2831,16 +2831,16 @@ fn render_assoc_items(w: &mut fmt::Formatter,
         let render_mode = match what {
             AssocItemRender::All => {
                 write!(w, "
-                    <h2 id='methods' class='section-header'>
-                      <a href='#methods'>Methods</a>
+                    <h2 id='methods' class='small-section-header'>
+                      Methods<a href='#methods' class='anchor'></a>
                     </h2>
                 ")?;
                 RenderMode::Normal
             }
             AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
                 write!(w, "
-                    <h2 id='deref-methods' class='section-header'>
-                      <a href='#deref-methods'>Methods from {}&lt;Target = {}&gt;</a>
+                    <h2 id='deref-methods' class='small-section-header'>
+                      Methods from {}&lt;Target = {}&gt;<a href='#deref-methods' class='anchor'></a>
                     </h2>
                 ", trait_, type_)?;
                 RenderMode::ForDeref { mut_: deref_mut_ }
@@ -2865,8 +2865,8 @@ fn render_assoc_items(w: &mut fmt::Formatter,
             render_deref_methods(w, cx, impl_, containing_item, has_deref_mut)?;
         }
         write!(w, "
-            <h2 id='implementations' class='section-header'>
-              <a href='#implementations'>Trait Implementations</a>
+            <h2 id='implementations' class='small-section-header'>
+              Trait Implementations<a href='#implementations' class='anchor'></a>
             </h2>
         ")?;
         for i in &traits {
index 51465bafc42e23f10b4ab947ed366c0163e145df..ee94f0baeb9a39bdf9cf590adc1b4c88878ab00b 100644 (file)
@@ -438,6 +438,16 @@ a {
        background: transparent;
 }
 
+.small-section-header:hover > .anchor {
+       display: initial;
+}
+.anchor {
+       display: none;
+}
+.anchor:after {
+       content: '\2002\00a7\2002';
+}
+
 .docblock a:hover, .docblock-short a:hover, .stability a {
        text-decoration: underline;
 }
@@ -677,6 +687,10 @@ span.since {
        left: 0;
 }
 
+.variant + .toggle-wrapper + .docblock > p {
+       margin-top: 5px;
+}
+
 .variant + .toggle-wrapper > a {
        margin-top: 5px;
 }
@@ -695,7 +709,7 @@ span.since {
        margin-bottom: 25px;
 }
 
-.enum .variant, .struct .structfield, .union .structfield {
+#main > .variant, #main > .structfield {
        display: block;
 }
 
index f012fd974b574267d28841be6f870741872dca58..b1e92b5190f375941a9e1e0c15097f3e96733094 100644 (file)
@@ -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(())
index 12241b3f88187f17ba2c8653057c21faac58013e..7e2229a8f84a3bb014f169112c02eb40901c7e52 100644 (file)
@@ -1618,7 +1618,7 @@ impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S>
     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()
     }
 }
index 3844690860b5a7aa9e6e15658ab2352f308231eb..6f7c5a5de42b37a90f75e70fa629219398bb7594 100644 (file)
@@ -563,7 +563,7 @@ impl<'t, K, V> FullBucket<K, V, &'t mut RawTable<K, V>> {
     ///
     /// This works similarly to `put`, building an `EmptyBucket` out of the
     /// taken bucket.
-    pub fn take(mut self) -> (EmptyBucket<K, V, &'t mut RawTable<K, V>>, K, V) {
+    pub fn take(self) -> (EmptyBucket<K, V, &'t mut RawTable<K, V>>, K, V) {
         self.table.size -= 1;
 
         unsafe {
index d1c2bfb96b3366f9eb9dc79c2df18df6bb9e8d93..401552a6ec41729a0234ee455e0027ab256dd14a 100644 (file)
@@ -514,7 +514,7 @@ fn description(&self) -> &str { "A-desc" }
     #[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::<A>(), Some(&A));
         assert_eq!(a.downcast_ref::<B>(), None);
         assert_eq!(a.downcast_mut::<A>(), Some(&mut A));
index 38d3312b4e7dd6a7569cdd5381de742edc8e538e..062186ef70866fec67ef4d4676950b5bc3dc02e1 100644 (file)
@@ -28,7 +28,7 @@
 /// A reference to an open file on the filesystem.
 ///
 /// An instance of a `File` can be read and/or written depending on what options
-/// it was opened with. Files also implement `Seek` to alter the logical cursor
+/// it was opened with. Files also implement [`Seek`] to alter the logical cursor
 /// that the file contains internally.
 ///
 /// Files are automatically closed when they go out of scope.
@@ -48,7 +48,7 @@
 /// # }
 /// ```
 ///
-/// Read the contents of a file into a `String`:
+/// Read the contents of a file into a [`String`]:
 ///
 /// ```no_run
 /// use std::fs::File;
@@ -81,6 +81,8 @@
 /// # }
 /// ```
 ///
+/// [`Seek`]: ../io/trait.Seek.html
+/// [`String`]: ../string/struct.String.html
 /// [`Read`]: ../io/trait.Read.html
 /// [`BufReader<R>`]: ../io/struct.BufReader.html
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -104,19 +106,19 @@ pub struct File {
 /// Iterator over the entries in a directory.
 ///
 /// This iterator is returned from the [`read_dir`] function of this module and
-/// will yield instances of `io::Result<DirEntry>`. Through a [`DirEntry`]
+/// will yield instances of [`io::Result`]`<`[`DirEntry`]`>`. Through a [`DirEntry`]
 /// information like the entry's path and possibly other metadata can be
 /// learned.
 ///
-/// [`read_dir`]: fn.read_dir.html
-/// [`DirEntry`]: struct.DirEntry.html
-///
 /// # Errors
 ///
-/// This [`io::Result`] will be an `Err` if there's some sort of intermittent
+/// This [`io::Result`] will be an [`Err`] if there's some sort of intermittent
 /// IO error during iteration.
 ///
+/// [`read_dir`]: fn.read_dir.html
+/// [`DirEntry`]: struct.DirEntry.html
 /// [`io::Result`]: ../io/type.Result.html
+/// [`Err`]: ../result/enum.Result.html#variant.Err
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct ReadDir(fs_imp::ReadDir);
index 616b4f47ed3eaafde0345b29dec4688ae773f6c0..d986021a18bbc7676e072c4001670aa3ae119b45 100644 (file)
@@ -456,7 +456,7 @@ fn read_to_end() {
     #[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];
index 0a5804a774411c0b078d8070bc5b944283461dc2..68f55221a6c985f1fb7ee84718afcd9e9d97c52b 100644 (file)
 /// A specialized [`Result`](../result/enum.Result.html) type for I/O
 /// operations.
 ///
-/// This type is broadly used across `std::io` for any operation which may
+/// This type is broadly used across [`std::io`] for any operation which may
 /// produce an error.
 ///
-/// This typedef is generally used to avoid writing out `io::Error` directly and
-/// is otherwise a direct mapping to `Result`.
+/// This typedef is generally used to avoid writing out [`io::Error`] directly and
+/// is otherwise a direct mapping to [`Result`].
 ///
-/// While usual Rust style is to import types directly, aliases of `Result`
-/// often are not, to make it easier to distinguish between them. `Result` is
-/// generally assumed to be `std::result::Result`, and so users of this alias
+/// While usual Rust style is to import types directly, aliases of [`Result`]
+/// often are not, to make it easier to distinguish between them. [`Result`] is
+/// generally assumed to be [`std::result::Result`][`Result`], and so users of this alias
 /// will generally use `io::Result` instead of shadowing the prelude's import
-/// of `std::result::Result`.
+/// of [`std::result::Result`][`Result`].
+///
+/// [`std::io`]: ../io/index.html
+/// [`io::Error`]: ../io/struct.Error.html
+/// [`Result`]: ../result/enum.Result.html
 ///
 /// # Examples
 ///
 #[stable(feature = "rust1", since = "1.0.0")]
 pub type Result<T> = result::Result<T, Error>;
 
-/// The error type for I/O operations of the `Read`, `Write`, `Seek`, and
+/// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and
 /// associated traits.
 ///
 /// Errors mostly originate from the underlying OS, but custom instances of
 /// `Error` can be created with crafted error messages and a particular value of
 /// [`ErrorKind`].
 ///
+/// [`Read`]: ../io/trait.Read.html
+/// [`Write`]: ../io/trait.Write.html
+/// [`Seek`]: ../io/trait.Seek.html
 /// [`ErrorKind`]: enum.ErrorKind.html
 #[derive(Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
index 9a3036f753ed314e155321dea34d8acfdaea0a92..f486493f98b4c275f6ac3d37ebe612c494f703db 100644 (file)
@@ -22,7 +22,7 @@
 //! you'll see a few different types of I/O throughout the documentation in
 //! this module: [`File`]s, [`TcpStream`]s, and sometimes even [`Vec<T>`]s. For
 //! example, [`Read`] adds a [`read`][`Read::read`] method, which we can use on
-//! `File`s:
+//! [`File`]s:
 //!
 //! ```
 //! use std::io;
 //! # }
 //! ```
 //!
-//! Note that you cannot use the `?` operator in functions that do not return
-//! a `Result<T, E>` (e.g. `main`). Instead, you can call `.unwrap()` or `match`
-//! on the return value to catch any possible errors:
+//! Note that you cannot use the [`?` operator] in functions that do not return
+//! a [`Result<T, E>`][`Result`] (e.g. `main`). Instead, you can call [`.unwrap()`]
+//! or `match` on the return value to catch any possible errors:
 //!
 //! ```
 //! use std::io;
 //! [`io::Result`]: type.Result.html
 //! [`?` operator]: ../../book/first-edition/syntax-index.html
 //! [`Read::read`]: trait.Read.html#tymethod.read
+//! [`Result`]: ../result/enum.Result.html
+//! [`.unwrap()`]: ../result/enum.Result.html#method.unwrap
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index bd9c9c747848921fee9f6d089edf9670060ef4f0..f7748aa3f041f43a51a0f20002e331b00626b71e 100644 (file)
 
 #![default_lib_allocator]
 
+// Always use alloc_system during stage0 since we don't know if the alloc_*
+// crate the stage0 compiler will pick by default is enabled (e.g.
+// if the user has disabled jemalloc in `./configure`).
+// `force_alloc_system` is *only* intended as a workaround for local rebuilds
+// with a rustc without jemalloc.
+// The not(stage0+msvc) gates will only last until the next stage0 bump
+#![cfg_attr(all(
+        not(all(stage0, target_env = "msvc")),
+        any(stage0, feature = "force_alloc_system")),
+    feature(global_allocator))]
+#[cfg(all(
+    not(all(stage0, target_env = "msvc")),
+    any(stage0, feature = "force_alloc_system")))]
+#[global_allocator]
+static ALLOC: alloc_system::System = alloc_system::System;
+
 // Explicitly import the prelude. The compiler uses this same unstable attribute
 // to import the prelude implicitly when building crates that depend on std.
 #[prelude_import]
index 03db1e4f01c6c9455380ab4da49b56a25e33212f..5e88a46ecc343016b947bb896a01b0e0d00e96aa 100644 (file)
 //! 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
         })
     });
index 1e5368896af9100ff44819bb3f8d34c4ffc84920..0abf8179cc971ff1fdc9092636c87e0a72fa00e5 100644 (file)
@@ -466,7 +466,7 @@ pub fn is_link_local(&self) -> bool {
     /// - test addresses used for documentation (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24)
     /// - the unspecified address (0.0.0.0)
     ///
-    /// [ipv4-sr]: http://goo.gl/RaZ7lg
+    /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
     /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
index d9edf5d1254896c492fb5f9cc2009a77d528e76f..bb18fe95a9dbfb08cfee8456a364bc2b4f50b7c8 100644 (file)
@@ -267,7 +267,7 @@ pub fn call_once_force<F>(&'static self, f: F) where F: FnOnce(&OnceState) {
     #[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 {
index 94b87a6bff4908bbef10994688bdd9146fd52624..7701ae25b418f792bd1e124891927931c967db25 100644 (file)
@@ -655,7 +655,7 @@ fn inner(path: &Path) -> io::Result<UnixListener> {
     /// Accepts a new incoming connection to this listener.
     ///
     /// This function will block the calling thread until a new Unix connection
-    /// is established. When established, the corersponding [`UnixStream`] and
+    /// is established. When established, the corresponding [`UnixStream`] and
     /// the remote peer's address will be returned.
     ///
     /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html
index 77ebad4e344c24adbcef0ae199fee1c7a9c8168b..1f56a299407edb2fbbb20a41efbaaf4c7da2bcf7 100644 (file)
 
 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) }
index 7f3291cf30470b59054650c97efccb96a0ce8e09..f2487c1b0bd0af4e4b3032413ca4d823484b32cb 100644 (file)
@@ -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
index 6598ecb94448b7bbb15d47e56656151a050c40d2..2ea3fe51d30b201076afabec5076af93b5f7053f 100644 (file)
@@ -162,6 +162,63 @@ pub fn main() {}
 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.
+
+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).
+"##,
+
+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.
 
@@ -300,11 +357,8 @@ fn main() {
     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
-    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
     E0584, // file for module `..` found at both .. and ..
     E0589, // invalid `repr(align)` attribute
 }
index 7eeafa72c682966ce6687772389c6399e3023f7b..194d30e25d41082e9f8bf5dc12c88b694af38d68 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::SyntaxExtension::{MultiDecorator, MultiModifier, NormalTT, IdentTT};
+pub use self::SyntaxExtension::*;
 
 use ast::{self, Attribute, Name, PatKind, MetaItem};
 use attr::HasAttrs;
index 16c264e0f941028e4cb59d636d58caed8500f09b..4843a66a750fab71473d1f297eb8fb2a9bb231a4 100644 (file)
@@ -294,7 +294,7 @@ fn expand(&mut self, expansion: Expansion) -> Expansion {
                         let item = match self.cx.resolver.resolve_macro(
                                 Mark::root(), path, MacroKind::Derive, false) {
                             Ok(ext) => match *ext {
-                                SyntaxExtension::BuiltinDerive(..) => item_with_markers.clone(),
+                                BuiltinDerive(..) => item_with_markers.clone(),
                                 _ => item.clone(),
                             },
                             _ => item.clone(),
@@ -427,7 +427,7 @@ fn expand_attr_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
                 items.push(item);
                 kind.expect_from_annotatables(items)
             }
-            SyntaxExtension::AttrProcMacro(ref mac) => {
+            AttrProcMacro(ref mac) => {
                 let item_tok = TokenTree::Token(DUMMY_SP, Token::interpolated(match item {
                     Annotatable::Item(item) => token::NtItem(item),
                     Annotatable::TraitItem(item) => token::NtTraitItem(item.unwrap()),
@@ -436,7 +436,7 @@ fn expand_attr_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
                 let tok_result = mac.expand(self.cx, attr.span, attr.tokens, item_tok);
                 self.parse_expansion(tok_result, kind, &attr.path, attr.span)
             }
-            SyntaxExtension::ProcMacroDerive(..) | SyntaxExtension::BuiltinDerive(..) => {
+            ProcMacroDerive(..) | BuiltinDerive(..) => {
                 self.cx.span_err(attr.span, &format!("`{}` is a derive mode", attr.path));
                 kind.dummy(attr.span)
             }
@@ -474,7 +474,7 @@ fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
         };
 
         let opt_expanded = match *ext {
-            SyntaxExtension::DeclMacro(ref expand, def_span) => {
+            DeclMacro(ref expand, def_span) => {
                 if let Err(msg) = validate_and_set_expn_info(def_span.map(|(_, s)| s),
                                                              false) {
                     self.cx.span_err(path.span, &msg);
@@ -512,18 +512,18 @@ fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
                 kind.make_from(expander.expand(self.cx, span, ident, input))
             }
 
-            MultiDecorator(..) | MultiModifier(..) | SyntaxExtension::AttrProcMacro(..) => {
+            MultiDecorator(..) | MultiModifier(..) | AttrProcMacro(..) => {
                 self.cx.span_err(path.span,
                                  &format!("`{}` can only be used in attributes", path));
                 return kind.dummy(span);
             }
 
-            SyntaxExtension::ProcMacroDerive(..) | SyntaxExtension::BuiltinDerive(..) => {
+            ProcMacroDerive(..) | BuiltinDerive(..) => {
                 self.cx.span_err(path.span, &format!("`{}` is a derive mode", path));
                 return kind.dummy(span);
             }
 
-            SyntaxExtension::ProcMacro(ref expandfun) => {
+            ProcMacro(ref expandfun) => {
                 if ident.name != keywords::Invalid.name() {
                     let msg =
                         format!("macro {}! expects no ident argument, given '{}'", path, ident);
@@ -582,7 +582,7 @@ fn expand_derive_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -
         };
 
         match *ext {
-            SyntaxExtension::ProcMacroDerive(ref ext, _) => {
+            ProcMacroDerive(ref ext, _) => {
                 invoc.expansion_data.mark.set_expn_info(expn_info);
                 let span = Span { ctxt: self.cx.backtrace(), ..span };
                 let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
@@ -592,7 +592,7 @@ fn expand_derive_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -
                 };
                 kind.expect_from_annotatables(ext.expand(self.cx, span, &dummy, item))
             }
-            SyntaxExtension::BuiltinDerive(func) => {
+            BuiltinDerive(func) => {
                 expn_info.callee.allow_internal_unstable = true;
                 invoc.expansion_data.mark.set_expn_info(expn_info);
                 let span = Span { ctxt: self.cx.backtrace(), ..span };
index 3cdd3a4b2c31d8a313c863cde1311e5b1a5c8a17..b293aa8de38b2944bd5082da7460b3dd4b867d23 100644 (file)
@@ -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<base::MacResult+'static> {
+    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.
index 60833c75a15961ceb525d5deb1813cc8bf0d49b2..146bd5d985699fead5fc4050eadc3f426752b4ca 100644 (file)
@@ -211,7 +211,7 @@ pub enum NamedMatch {
 
 fn nameize<I: Iterator<Item=NamedMatch>>(sess: &ParseSess, ms: &[TokenTree], mut res: I)
                                              -> NamedParseResult {
-    fn n_rec<I: Iterator<Item=NamedMatch>>(sess: &ParseSess, m: &TokenTree, mut res: &mut I,
+    fn n_rec<I: Iterator<Item=NamedMatch>>(sess: &ParseSess, m: &TokenTree, res: &mut I,
              ret_val: &mut HashMap<Ident, Rc<NamedMatch>>)
              -> 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);
index 8e746676ecd9e3f4fc14fbd26ca296d19c7bed7c..80b6794d1e3cc4c01aae143a8c5d89faef7f1455 100644 (file)
@@ -86,7 +86,7 @@ fn expand<'cx>(&self,
 
 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<String> = cx.expansions.entry(sp).or_insert_with(Vec::new);
+    let values: &mut Vec<String> = cx.expansions.entry(sp).or_insert_with(Vec::new);
     values.push(message);
 }
 
index e8de8cf41c970ce5f33fad1d9d157b46a5b85f63..aeb574bc3af3cea34236dd90cb533643afc20ddc 100644 (file)
@@ -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);
             }
         }
index 85df4eee9134440c3222dcb59378fe94f1779d90..c36fdef2d4c1dd9f9117a11f560654eb2b1a1b45 100644 (file)
@@ -82,7 +82,7 @@
     ('։', "Armenian Full Stop", ':'),
     ('܃', "Syriac Supralinear Colon", ':'),
     ('܄', "Syriac Sublinear Colon", ':'),
-    ('᛬', "Runic Multiple Ponctuation", ':'),
+    ('᛬', "Runic Multiple Punctuation", ':'),
     ('︰', "Presentation Form For Vertical Two Dot Leader", ':'),
     ('᠃', "Mongolian Full Stop", ':'),
     ('᠉', "Mongolian Manchu Full Stop", ':'),
     ('ꝸ', "Latin Small Letter Um", '&'),
     ('&', "Fullwidth Ampersand", '&'),
 
-    ('᛭', "Runic Cros Punctuation", '+'),
+    ('᛭', "Runic Cross Punctuation", '+'),
     ('➕', "Heavy Plus Sign", '+'),
     ('𐊛', "Lycian Letter H", '+'),
     ('﬩', "Hebrew Letter Alternative Plus Sign", '+'),
index ca362ec93683d62c001e3f4f28ff395a6e7322e0..7bf4c6799b3cb208119bbaccb6535c643788b051 100644 (file)
@@ -5518,12 +5518,11 @@ fn parse_item_foreign_fn(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec<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<Attribute>)
                                  -> 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,19 +5996,23 @@ fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> {
         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_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)?));
         }
+        // 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) {
-            return Err(self.span_fatal(self.span, "extern items cannot be `const`"));
-        }
-
         // FIXME #5668: this will occur for a macro invocation:
         match self.parse_macro_use_or_failure(attrs, true, false, lo, visibility)? {
             Some(item) => {
index 9734bb867f1d80e0af7a8cdc6b1112d3ba2943f8..16b06424c92fc847acb0ec7b6ea2ab0f63319ca1 100644 (file)
@@ -529,7 +529,7 @@ fn static_array(ecx: &mut ExtCtxt,
 
     /// Actually builds the expression which the format_args! block will be
     /// expanded to
-    fn into_expr(mut self) -> P<ast::Expr> {
+    fn into_expr(self) -> P<ast::Expr> {
         let mut locals = Vec::new();
         let mut counts = Vec::new();
         let mut pats = Vec::new();
index 8ba07c35b0543f721185b82e6399dec8f0ebfc29..5eab81dd28fc4bc526eb41ef7fcd8ba609a8f562 100644 (file)
@@ -89,6 +89,7 @@ macro_rules! register {
     use syntax::ext::source_util::*;
     register! {
         line: expand_line,
+        __rust_unstable_column: expand_column_gated,
         column: expand_column,
         file: expand_file,
         stringify: expand_stringify,
index 4452f4a2f446bb804b1f3a82085a1ecd529d88ac..d185c061d5bd9fb6656b7240de820824447d2137 100644 (file)
@@ -15,3 +15,4 @@ rustc_driver = { path = "../librustc_driver" }
 
 [features]
 jemalloc = ["rustc_back/jemalloc"]
+llvm = ["rustc_driver/llvm"]
index bca0881c08c5a35a433f9b61dea2e17e9e8fe178..ba0c4fbe173bbb8dde137ebc5ea7d42d4f841036 100644 (file)
@@ -278,10 +278,12 @@ static Optional<Reloc::Model> 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
index 65f4b6350c4eed4f578d9d78bc61949360b66a4f..00a27818327f6692afb55eb9f74003319ecdba99 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:attribute-with-error.rs
+// ignore-stage1
 
 #![feature(proc_macro)]
 
index 508f8dac5711939f75f13bfbac6b1b0645378eba..2adbee1d3fbd5b7c23bf58667d33f00e893c1c54 100644 (file)
@@ -9,8 +9,10 @@
 // except according to those terms.
 
 // aux-build:attributes-included.rs
+// ignore-stage1
 
 #![feature(proc_macro, rustc_attrs)]
+#![warn(unused)]
 
 extern crate attributes_included;
 
index 42fad803bfa68ae345d5643ff0ae3b0e99fbdadb..b03409c9c285e69b1b34db4e5c594a86e695bec7 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:derive-bad.rs
+// ignore-stage1
 
 #[macro_use]
 extern crate derive_bad;
index e4fcbb117a5057c0dd55eb757713496102a08bad..6f254dcbdb11a361f602bbc989ac3f38e645aa03 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:derive-unstable-2.rs
+// ignore-stage1
 
 #![allow(warnings)]
 
index 836e336fc22f013e86983a5c0530a0ebac944719..ca0f0e382ed0c2af76d303ca4eef7fefb0cf7e48 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:derive-unstable.rs
+// ignore-stage1
 
 #![allow(warnings)]
 
index 42475e6de90c982178efac63a4c3cde5685f6edd..1d645a7ec510fe420509ea39d600d30c06544218 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:issue_38586.rs
+// ignore-stage1
 
 #![feature(proc_macro)]
 
index 4133e75e3a62d8f33ca7d1c80a1db23e020b544a..c0d4d71a6ec8be6356729db5b5dee4c835b7f398 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:derive-b.rs
+// ignore-stage1
 
 #![allow(warnings)]
 
index 93dead1a156851ca0a69b4861540b0f3e86f6e91..b1fb7d42d8683b064f1b88bafa85fa093fc70a5e 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:bang_proc_macro2.rs
+// ignore-stage1
 
 #![feature(proc_macro)]
 #![allow(unused_macros)]
index df881bedec1bbf5202dfd618eefe913c658c13fc..153e4dd05717a42f6ae0933ccc31ec88a938af7c 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:derive-b.rs
+// ignore-stage1
 
 #![allow(warnings)]
 
index 8a666168c86fd22207a7067c426fe0c89329dfd6..ccaf01932d46684001261207044f9f76f23c7751 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(box_syntax)]
+#![allow(warnings)]
 
 const CON : Box<i32> = box 0; //~ ERROR E0010
                               //~| NOTE allocation not allowed in
index e35d038248c8148f39b1a377be151a7fe258f8c5..c7d5665cd2c58482f12a3ff9a35cd77ddc1a3bdd 100644 (file)
@@ -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
index 5a97d7b1a79a186ad2a88f136a52f023ed2fc779..cb9fb973a01939e332b0bd3cc310be2c6312ac56 100644 (file)
@@ -10,6 +10,7 @@
 
 // compile-flags: --cap-lints deny
 
+#![warn(unused)]
 #![deny(warnings)]
 
 use std::option; //~ ERROR
index e03ba6ecb6440fd278bd82ddc9084770ab0ff3cb..c9394954c5fbd3485c99e74abf0a6e8b9f3d1ce6 100644 (file)
@@ -10,6 +10,7 @@
 
 // compile-flags: --cap-lints warn
 
+#![warn(unused)]
 #![deny(warnings)]
 #![feature(rustc_attrs)]
 
index f65968e0e1192cfb1841f2f492671abf7f5a0aac..3642add32597b781cf416664c77ff0e6a418820b 100644 (file)
@@ -12,6 +12,7 @@
 
 // gate-test-drop_types_in_const
 
+#![allow(warnings)]
 #![feature(box_syntax)]
 
 use std::marker;
index 9b045ed1d02cce60d8eeb7d203bd58557e14896e..0fd41a17b2c9c0554a141b0695196be76ff9537f 100644 (file)
@@ -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};
index 452aa87d6ba56ecc1706b92157ed7b069d1f0fae..bc944948f3d8b846eb0a6e0208921680a0d52f1a 100644 (file)
@@ -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]
index d9664fda2b339afebe9fda9ef4e82f9d6416d699..360895d30b0b7e39866ea4ba4e754299dbf1fb84 100644 (file)
@@ -28,7 +28,6 @@ struct Foo<T> { data: Vec<T> }
 impl<T> Drop for Foo<T> {
     #[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) { }
 }
 
index c4846a64f29be2b6a2c3ae2e075157f4ed8c5f70..d8f9f5543e43964f7d84cc541190849d92f1ed99 100644 (file)
@@ -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: ();
 }
index 6c41450796c749edad9e4c630bef2fa2e6526d96..08c3f7a7c15451a6d5dcc647f555bc563f386b9c 100644 (file)
@@ -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 {
index 5471d8522dffdc4f9a15e1d2da2df87bae5f5c96..cde1bbbe4927a427d1603026ce0ad771bf8a165f 100644 (file)
@@ -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 {
index 06719e2756b19f07fc142c5a9720eb90534c4a25..4857c2fb446b519e9097ea3154705d5f571c4397 100644 (file)
@@ -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;
index c159168030b8c7b1e50d4aa61406d312bdb708a5..8e0df283cdbebe839936be20c1dd597c7635ea12 100644 (file)
@@ -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;
index f57f3477a8a86fe1d195877b367df7594e4cf291..5996c8e5438783fe2defdf81e9da1e12f9821386 100644 (file)
@@ -26,7 +26,7 @@ fn foo<F>(&mut self, f: F)
 }
 
 impl<'a> A<'a> for B {
-    fn foo<F>(&mut self, f: F) //~ ERROR E0276
+    fn foo<F>(&mut self, f: F) //~ ERROR impl has stricter
         //~^ WARNING future release
         where F: fmt::Debug + 'static,
     {
index cd73a45641111c9e20260536ee83af89d873e459..057c99f930510aa9a6add482b10a499f1b550991 100644 (file)
@@ -12,7 +12,7 @@
 
 // aux-build:lint_stability.rs
 
-#![allow(unused_imports)]
+#![allow(warnings)]
 
 extern crate lint_stability;
 
index 5c697b69c80b1e3cc049291fea55262d39e34127..7d2541966a4810a3a2f6bebc0fb2b860e364e825 100644 (file)
@@ -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
index 13ce41f4dcc543f8a210d9ee948a72271c4b77fd..3c4d6b42b503dfc72956de56d5fd5346878ff5ec 100644 (file)
@@ -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;
 }
index 086938334c78aa5480dc39ffedd72f8eb883b4d4..d1af39a6c1872497cf27b4236535e6e76dcf6024 100644 (file)
@@ -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
index fa452d6e74a057461e4233f6dbf4968c9740d544..d5733f98193874735004ab2e09bfdf5dc1514176 100644 (file)
@@ -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-43162.rs b/src/test/compile-fail/issue-43162.rs
new file mode 100644 (file)
index 0000000..8f46612
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo() -> bool {
+    break true; //~ ERROR E0268
+}
+
+fn main() {
+    break {}; //~ ERROR E0268
+}
index 16b407baad178eece4faea4a35123d70b206a406..bd32317ae78086b3e709bd9a19a1859aed2f35b9 100644 (file)
@@ -10,6 +10,7 @@
 
 #![feature(box_syntax)]
 #![feature(const_fn)]
+#![allow(warnings)]
 
 use std::cell::RefCell;
 
index 1498ed4d17ed71513f9d72c0aa49292bb60dc42c..9f84190ea18a1f3e8bb598ae2a53b89e1f038aba 100644 (file)
@@ -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
index d6bfd1eec39a6f2fbc782da28cd339a416bc3e30..e1da5086612fd7d5eacb4bd77bce414550ada9e6 100644 (file)
@@ -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 = (); }
index ea26c3656e6911fa1daa742cdab1cf50bfdaa786..ae010b64bfdfc75cfe945d07385ae90293638bbd 100644 (file)
@@ -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
index d8813b6a6101a377179e2fe1da648099f5085166..8443518b3f5681c682c188f1e98905768b50bb2b 100644 (file)
@@ -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 @@ fn test() {
         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
-        <Foo>::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
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR 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
-        <Foo>::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
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR 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
-        <Foo>::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
-        <Foo>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ ERROR 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
-        <Foo>::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
-        <Foo>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        deprecated(); //~ WARN use of deprecated item
+        foo.method_deprecated(); //~ WARN use of deprecated item
+        Foo::method_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo>::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
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item
+
+        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
+        <Foo>::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
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+
+        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
+        <Foo>::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
+        <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item
+        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item
+
+        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
+        <Foo>::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
+        <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
 
         unstable();
         foo.method_unstable();
@@ -106,30 +106,30 @@ fn test() {
 
         struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
         struct S2<T: TraitWithAssociatedTypes>(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 @@ fn test() {
         // 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: Trait>(foo: Foo) {
-        foo.trait_deprecated(); //~ ERROR use of deprecated item
-        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::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
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::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
-        <Foo>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::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
-        <Foo>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::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
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo as Trait>::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
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        <Foo as Trait>::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
+        <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item
+        <Foo as Trait>::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
+        <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
         foo.trait_unstable();
         Trait::trait_unstable(&foo);
         <Foo>::trait_unstable(&foo);
@@ -175,10 +175,10 @@ fn test_method_param<Foo: Trait>(foo: Foo) {
     }
 
     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 @@ fn test_method_object(foo: &Trait) {
     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 @@ fn test_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 @@ fn test() {
         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
-        <Foo>::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
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR 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
-        <Foo>::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
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        deprecated(); //~ WARN use of deprecated item
+        foo.method_deprecated(); //~ WARN use of deprecated item
+        Foo::method_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo>::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
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item
+
+        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
+        <Foo>::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
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
 
         unstable();
         foo.method_unstable();
@@ -385,34 +385,34 @@ fn test() {
         <Foo as Trait>::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: Trait>(foo: Foo) {
-        foo.trait_deprecated(); //~ ERROR use of deprecated item
-        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::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
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::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
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo as Trait>::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
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
         foo.trait_unstable();
         Trait::trait_unstable(&foo);
         <Foo>::trait_unstable(&foo);
@@ -428,8 +428,8 @@ fn test_method_param<Foo: Trait>(foo: Foo) {
     }
 
     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 @@ fn test_method_object(foo: &Trait) {
     #[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 @@ impl MethodTester {
         #[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 @@ fn dummy(&self) { }
 
     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
index d399fda32862569119c8598a217f9e1a6d4bc077..5593499758346d37c7cd001c55e95cd0579e2716 100644 (file)
@@ -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
 }
index 21cfadb9c79925c96e9ddeb278a0f3d90174a41a..26d00755da33b0f28d45971354fff0fc0f16cfc4 100644 (file)
@@ -47,6 +47,26 @@ 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
+
+    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
+    }
+
+    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;
index 1615af400713c2a2ddaf78722ed93b65ecf309b1..1d947684792dd9a78964528e836dedbc15ab5d13 100644 (file)
@@ -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)]
 
index 3aab953eb7940bc6d2a33c3e73ce5b78d30d53aa..d056d6be806f7828b62aa20fbea8905e2155ba29 100644 (file)
@@ -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)]
index d8752e1c050fce37c2d5d7630c62915584ee3b85..1e0cc0f5357fb6f7cce36fddfb8ab5130cb32567 100644 (file)
 
 // 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
 }
-
index 140891027d5f0f7305c21141f69453d36e97b8e5..4d41f8ba47d014334ed82e4e7e3ba01024df2bb8 100644 (file)
@@ -11,6 +11,7 @@
 #![feature(associated_consts)]
 #![feature(conservative_impl_trait)]
 #![feature(decl_macro)]
+#![allow(warnings)]
 
 mod m {
     fn priv_fn() {}
index 925d692f8ae6bf3fa14ff3d7b9335e62b6142c84..a5581664f741859baa603fd7c7b140a73f850d60 100644 (file)
@@ -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/rust-unstable-column-gated.rs b/src/test/compile-fail/rust-unstable-column-gated.rs
new file mode 100644 (file)
index 0000000..abc92c8
--- /dev/null
@@ -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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    println!("{}", __rust_unstable_column!());
+    //~^ERROR the __rust_unstable_column macro is unstable
+}
index 7c37abf765769c25725f16cb9169f907418d1ad6..a855b08f06691f8603411e21c6d921ffe4b0a1fc 100644 (file)
@@ -14,6 +14,7 @@
 
 static mut a: Box<isize> = 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() {}
index f694e7d277c7fec094e70b30b191f17605845340..ad568b41fcbf3622bf8acbaf47925e2d8eed3c95 100644 (file)
@@ -20,17 +20,15 @@ fn bar() {
 }
 
 impl<T> Foo<T> {
-    fn new<U>(u: U) -> Foo<U> {
+    fn new<U>(u: U) -> Foo<U> { //~ NOTE expected `Foo<U>` because of return type
         Self {
         //~^ ERROR mismatched types
-        //~| expected type parameter, found a different type parameter
-        //~| expected type `Foo<U>`
-        //~| found type `Foo<T>`
+        //~| NOTE expected type parameter, found a different type parameter
+        //~| NOTE expected type `Foo<U>`
             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`
         }
     }
 }
index f4817ba33b518f45dd44d62b5065819f78742f1f..46ea4a06a3bd8a41a9dcf2ecbc950bedb5eda83b 100644 (file)
@@ -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<!, i32>) -> Result<u32, i32> {
 
 fn foo(x: Result<!, i32>) -> Result<u32, i32> {
     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<u32, Void>) -> Result<u32, i32> {
 
 fn vom(x: Result<u32, Void>) -> Result<u32, i32> {
     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));
index 9ac76a5f4ea614fd2af8480ff4b6ad1ffc316286..677c92ea71b7a78a64241da9c9fe7cd7afe13c39 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
-// compile-flags: -Z verbose -Z mir-emit-validate=1
+// compile-flags: -Z verbose -Z mir-emit-validate=1 -Z span_free_formats
 
 struct Test(i32);
 
@@ -20,16 +20,13 @@ fn foo(&self, _x: &mut i32) {}
 
 fn main() {
     let mut x = 0;
-    Test(0).foo(&mut x);
+    Test(0).foo(&mut x); // just making sure we do not panic when there is a tuple struct ctor
 
     // Also test closures
     let c = |x: &mut i32| { let y = &*x; *y };
     c(&mut x);
 }
 
-// FIXME: Also test code generated inside the closure, make sure it has validation.  Unfortunately,
-// the interesting lines of code also contain name of the source file, so we cannot test for it.
-
 // END RUST SOURCE
 // START rustc.node12.EraseRegions.after.mir
 //     bb0: {
@@ -57,3 +54,24 @@ fn main() {
 //     }
 // }
 // END rustc.node23.EraseRegions.after.mir
+// START rustc.node50.EraseRegions.after.mir
+// fn main::{{closure}}(_1: &ReErased [closure@NodeId(50)], _2: &ReErased mut i32) -> i32 {
+//     bb0: {
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483663) => validate_1/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483663) => validate_1/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
+//         StorageLive(_3);
+//         _3 = _2;
+//         StorageLive(_4);
+//         Validate(Suspend(ReScope(Remainder(BlockRemainder { block: NodeId(41), first_statement_index: 0 }))), [(*_3): i32]);
+//         _4 = &ReErased (*_3);
+//         Validate(Acquire, [(*_4): i32/ReScope(Remainder(BlockRemainder { block: NodeId(41), first_statement_index: 0 })) (imm)]);
+//         StorageLive(_5);
+//         _5 = (*_4);
+//         _0 = _5;
+//         StorageDead(_5);
+//         StorageDead(_4);
+//         EndRegion(ReScope(Remainder(BlockRemainder { block: NodeId(41), first_statement_index: 0 })));
+//         StorageDead(_3);
+//         return;
+//     }
+// }
+// END rustc.node50.EraseRegions.after.mir
index 591de975740f9fd572883f2156ad82ff75987706..2ee459d6809c55d771eccf02872a0631b5f5286f 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
-// compile-flags: -Z verbose -Z mir-emit-validate=1
+// compile-flags: -Z verbose -Z mir-emit-validate=1 -Z span_free_formats
 
 // Make sure unsafe fns and fns with an unsafe block only get restricted validation.
 
@@ -45,6 +45,19 @@ fn main() {
 //     }
 // }
 // END rustc.node4.EraseRegions.after.mir
+// START rustc.node22.EraseRegions.after.mir
+// fn write_42::{{closure}}(_1: &ReErased [closure@NodeId(22)], _2: *mut i32) -> () {
+//     bb0: {
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483659) => validate_4/8cd878b::write_42[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(22)], _2: *mut i32]);
+//         Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483659) => validate_4/8cd878b::write_42[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(22)], _2: *mut i32]);
+//         StorageLive(_3);
+//         _3 = _2;
+//         (*_3) = const 23i32;
+//         StorageDead(_3);
+//         return;
+//     }
+// }
+// END rustc.node22.EraseRegions.after.mir
 // START rustc.node31.EraseRegions.after.mir
 // fn test(_1: &ReErased mut i32) -> () {
 //     bb0: {
@@ -58,3 +71,13 @@ fn main() {
 //     }
 // }
 // END rustc.node31.EraseRegions.after.mir
+// START rustc.node60.EraseRegions.after.mir
+// fn main::{{closure}}(_1: &ReErased [closure@NodeId(60)], _2: &ReErased mut i32) -> bool {
+//     bb0: {
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483663) => validate_4/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483663) => validate_4/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
+//         Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483663) => validate_4/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483663) => validate_4/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
+//         StorageLive(_3);
+//         _0 = const write_42(_4) -> bb1;
+//     }
+// }
+// END rustc.node60.EraseRegions.after.mir
index e9919af9fd3a6fec243a75c3979d7002836d6073..0182e6e2964452c5627f49503ace6d7b5eff7498 100644 (file)
@@ -9,9 +9,9 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
-// compile-flags: -Z verbose -Z mir-emit-validate=2
+// compile-flags: -Z verbose -Z mir-emit-validate=2 -Z span_free_formats
 
-// Make sure unsafe fns and fns with an unsafe block only get full validation.
+// Make sure unsafe fns and fns with an unsafe block still get full validation.
 
 unsafe fn write_42(x: *mut i32) -> bool {
     *x = 42;
@@ -26,12 +26,12 @@ fn main() {
     test(&mut 0);
 
     let test_closure = unsafe { |x: &mut i32| write_42(x) };
+    // Note that validation will fail if this is executed: The closure keeps the lock on
+    // x, so the write in write_42 fails.  This test just checks code generation,
+    // so the UB doesn't matter.
     test_closure(&mut 0);
 }
 
-// FIXME: Also test code generated inside the closure, make sure it has validation.  Unfortunately,
-// the interesting lines of code also contain name of the source file, so we cannot test for it.
-
 // END RUST SOURCE
 // START rustc.node17.EraseRegions.after.mir
 // fn test(_1: &ReErased mut i32) -> () {
@@ -42,3 +42,22 @@ fn main() {
 //     }
 // }
 // END rustc.node17.EraseRegions.after.mir
+// START rustc.node46.EraseRegions.after.mir
+// fn main::{{closure}}(_1: &ReErased [closure@NodeId(46)], _2: &ReErased mut i32) -> bool {
+//     bb0: {
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483660) => validate_5/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483660) => validate_5/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
+//         StorageLive(_3);
+//         _3 = _2;
+//         StorageLive(_4);
+//         StorageLive(_5);
+//         Validate(Suspend(ReScope(Misc(NodeId(44)))), [(*_3): i32]);
+//         _5 = &ReErased mut (*_3);
+//         Validate(Acquire, [(*_5): i32/ReScope(Misc(NodeId(44)))]);
+//         _4 = _5 as *mut i32 (Misc);
+//         StorageDead(_5);
+//         EndRegion(ReScope(Misc(NodeId(44))));
+//         Validate(Release, [_0: bool, _4: *mut i32]);
+//         _0 = const write_42(_4) -> bb1;
+//     }
+// }
+// END rustc.node46.EraseRegions.after.mir
index f17ce537fb813dacf340d0cc9762262076421924..8b3355b96226aa8e5d1f9fbf550cf00f9c365b81 100644 (file)
@@ -1,6 +1,12 @@
 -include ../tools.mk
 
+ifeq ($(findstring stage1,$(RUST_BUILD_STAGE)),stage1)
+# ignore stage1
+all:
+
+else
 all:
        $(RUSTC) a.rs && $(RUSTC) b.rs
        $(BARE_RUSTC) c.rs -L dependency=$(TMPDIR) --extern b=$(TMPDIR)/libb.rlib \
                --out-dir=$(TMPDIR)
+endif
index 27b69baf97787b794b246d27c0df5c4e4db99f50..c7732cc2682b1a044ee1cdd247f1aeb08b85e59f 100644 (file)
@@ -1,4 +1,10 @@
 -include ../tools.mk
 
+ifeq ($(findstring stage1,$(RUST_BUILD_STAGE)),stage1)
+# ignore stage1
+all:
+
+else
 all:
        $(RUSTC) a.rs && $(RUSTC) b.rs && $(RUSTC) c.rs
+endif
index 0a681401b1afbdd4eff22b4e5968c25e22d84832..855d958b344a9531a3aa998ff1e89a04bd869e0a 100644 (file)
@@ -1,5 +1,11 @@
 -include ../tools.mk
 
+ifeq ($(findstring stage1,$(RUST_BUILD_STAGE)),stage1)
+# ignore stage1
+all:
+
+else
 all:
        $(RUSTC) foo.rs; $(RUSTC) bar.rs
        $(RUSTDOC) baz.rs -L $(TMPDIR) -o $(TMPDIR)
+endif
index aab6e895f22609fb87dd8951c46b0d191a259b97..0d31d2c823500ab64d6d9412b77de4300d71db1d 100644 (file)
@@ -1,5 +1,10 @@
 -include ../tools.mk
 
+ifeq ($(findstring stage1,$(RUST_BUILD_STAGE)),stage1)
+# ignore stage1
+all:
+
+else
 # Windows doesn't correctly handle include statements with escaping paths,
 # so this test will not get run on Windows.
 ifdef IS_WINDOWS
@@ -15,3 +20,5 @@ $(TMPDIR)/libllvm-function-pass.o:
 $(TMPDIR)/libllvm-module-pass.o:
        $(CXX) $(CFLAGS) $(LLVM_CXXFLAGS) -c llvm-module-pass.so.cc -o $(TMPDIR)/libllvm-module-pass.o
 endif
+
+endif
index e3a6776c8080b5426e1af2ffb476e8c4a34a11cd..1ab27397e3146bbafa134862eca203a4763c2a35 100644 (file)
@@ -1,6 +1,12 @@
 -include ../tools.mk
 
+ifeq ($(findstring stage1,$(RUST_BUILD_STAGE)),stage1)
+# ignore stage1
+all:
+
+else
 all:
        $(RUSTC) foo.rs
        $(RUSTC) bar.rs --emit dep-info
        grep "proc-macro source" $(TMPDIR)/bar.d && exit 1 || exit 0
+endif
index d030eab64e564026301e6996e34b55d8e6775681..8cb9dc4a1b6ec5ca2aab7dc2c9cb1c1a781874c4 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:custom_derive_plugin.rs
+// ignore-stage1
 
 #![feature(plugin, custom_derive)]
 #![plugin(custom_derive_plugin)]
index 7ea7ceafc28766d6a12f0263aa324c950ff8da9e..5175fe174a9e743230b9b4bb887a91b9da128c88 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:add-impl.rs
+// ignore-stage1
 
 #[macro_use]
 extern crate add_impl;
index 591f3331d28c00382f421852d34df791cf43c583..37aef7ef1318c4dd6b6f520e205070e7d6348d65 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:append-impl.rs
+// ignore-stage1
 
 #![allow(warnings)]
 
index 8a9fdd7536770dc07fdd3357f63e0893e08654c9..2968cc7871d7e1ac04691b19e98401ec3772ada4 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:attr-args.rs
+// ignore-stage1
 
 #![allow(warnings)]
 #![feature(proc_macro)]
index 531bd0dd3569d9b0a191c3330950d60599a8173d..ffa4731f1e6371b0153a9929298a8aebc8cdab89 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:bang-macro.rs
+// ignore-stage1
 
 #![feature(proc_macro)]
 
index 1a2b144e4717bae285eeb833986f12c6c5f13d30..00ad0e76ed014c10c2bf8bcf2f1bf9b538d2fcfe 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:count_compound_ops.rs
+// ignore-stage1
 
 #![feature(proc_macro)]
 
index ba1417ecb56e408cf96d2db98c384b32fa4c96f2..b6acb0faab2a531d1aef4faef0bbf434f173a38d 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:double.rs
+// ignore-stage1
 
 #![allow(unused)]
 
index ce3ba60b0ecf4b264b17523a8c209cf675416f86..ba5a639a759cb826f156524c92730897f7420119 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:derive-same-struct.rs
+// ignore-stage1
 
 #[macro_use]
 extern crate derive_same_struct;
index 51198db5aa76d137fdc81d1da315c29ed7ae0113..4cac7d19b4de8f2472d9fd78d4359bfbce414d61 100644 (file)
@@ -10,6 +10,7 @@
 
 // aux-build:hygiene_example_codegen.rs
 // aux-build:hygiene_example.rs
+// ignore-stage1
 
 #![feature(proc_macro)]
 
index 05610116ad6bff88c260bb5607242612fcef1f8b..87130242c0f04035331fda007066e1f0ee9af507 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:issue-39889.rs
+// ignore-stage1
 
 #![feature(proc_macro)]
 #![allow(unused)]
index 54e84b7f6189fd9be35f9e8c657bdd4b10e8bd85..b7826edd8b4e5215c82aba9325d639a82cf2935e 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:issue-40001-plugin.rs
+// ignore-stage1
 
 #![feature(proc_macro, plugin)]
 #![plugin(issue_40001_plugin)]
index d15a83a2cbe432afc4fb8a17261e10ce24876fac..67c12377814704d84d2abcc32464ab60d8e2996a 100644 (file)
@@ -10,6 +10,7 @@
 
 // aux-build:derive-atob.rs
 // aux-build:derive-ctod.rs
+// ignore-stage1
 
 #[macro_use]
 extern crate derive_atob;
index f0a1bfe652857989c9b5dfacf4a74b79f08ea12b..03dfeb1f5c9a5ce99edcd0f506352d5df154bd97 100644 (file)
@@ -10,6 +10,7 @@
 
 // aux-build:derive-a.rs
 // aux-build:derive-reexport.rs
+// ignore-stage1
 
 #[macro_use]
 extern crate derive_reexport;
diff --git a/src/test/run-pass/issue-43057.rs b/src/test/run-pass/issue-43057.rs
new file mode 100644 (file)
index 0000000..152ddfb
--- /dev/null
@@ -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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(unused)]
+
+macro_rules! column {
+    ($i:ident) => {
+        $i
+    };
+}
+
+fn foo() -> ! {
+    panic!();
+}
+
+fn main() {}
index 1d5c83bc20d9554c3244eaa3d7513d1982d7f255..39053769b24b59d9aff3ffb37128675726c760f0 100644 (file)
@@ -137,4 +137,10 @@ pub fn main() {
         panic!("from outer");
     };
     assert_eq!(break_from_while_to_outer, 567);
+
+    let rust = true;
+    let value = loop {
+        break rust;
+    };
+    assert!(value);
 }
index 827b05c0801e1eb39b5650defc365315f411b3d3..2865b5d04e5be61d4bdaf6ca522d5dac1c7be7ea 100644 (file)
@@ -45,6 +45,11 @@ fn main() {
         assert!(g != h);
         assert!(g != i);
         assert!(h != i);
+
+        // Make sure lifetime anonymization handles nesting correctly
+        let j = TypeId::of::<fn(for<'a> fn(&'a isize) -> &'a usize)>();
+        let k = TypeId::of::<fn(for<'b> fn(&'b isize) -> &'b usize)>();
+        assert_eq!(j, k);
     }
     // Boxed unboxed closures
     {
index 20f58301d45244adfa7c0ded2515b3234bce9be2..64fd9e0a7721b833de1877fd4abb12964d6b01f2 100644 (file)
@@ -107,6 +107,10 @@ fn fishy() {
                String::<>::from::<>("><>").chars::<>().rev::<>().collect::<String>());
 }
 
+fn union() {
+    union union<'union> { union: &'union union<'union>, }
+}
+
 pub fn main() {
     strange();
     funny();
@@ -119,4 +123,5 @@ pub fn main() {
     dots();
     you_eight();
     fishy();
+    union();
 }
index 1e428629cc2ff116b3140f256c8fdce7a1c90702..19ce2362134543b90d49bb515a0823bb2534eddb 100644 (file)
@@ -14,6 +14,7 @@
 // compile-flags: -A test-lint
 
 #![feature(plugin)]
+#![warn(unused)]
 #![plugin(lint_plugin_test)]
 
 fn lintme() { }
index b8513b95d36c09690115c5021cea71ab16cb6be2..7c9c4e9903908d0741c4b0f9d25dbe56b14bab97 100644 (file)
@@ -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)]
 
index f60a0c2e5f6e00f017d93882debb11da567f4f9b..20c7dc416f3bb339851af79389f335581b014b89 100644 (file)
@@ -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
    |
index 41113eb7a573e6b741508415238ce192cf9ef16c..cd8c28cd2cfa8eb0716d78ff675ff7b63b7b819e 100644 (file)
@@ -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`
    |
index a9bcc8bea94cc177d0ebb793ae6025d0c640fa55..c6113ae0c9f6016a6f518dd53be2d2c013601af3 100644 (file)
@@ -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`
    |
index bd670a14f247e7f6b0e58410b3d091c3da8559cf..29dbd5a8cf5999db93ca037d544dd2510f7ba668 100644 (file)
@@ -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
    |
index c77fa74f6e0e5509e52a65826748830f214f8c73..108d7e1ea22a15c17cf916ec8188c37168e0423f 100644 (file)
@@ -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
+}
index 0d4a2ecf512dedbc972b9670e5f4fbbf09808cd7..a1cb3963914c9a42e98628f986ed424f8883eb92 100644 (file)
@@ -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 => {},
    |         ^^^^^
 
index b1b5aedea70d848ff53e8b0e12db1ffc41cba173..e58251c846f8dae0da64f9c7f019431fd423ff24 100644 (file)
@@ -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;
index b02aa5eeb2f54a44f99f3ba9868e0ec4cc7d149c..95db68fea5cf73c534715e841758a84560b663dc 100644 (file)
@@ -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/extern-const.rs b/src/test/ui/extern-const.rs
new file mode 100644 (file)
index 0000000..a77d7b1
--- /dev/null
@@ -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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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 (file)
index 0000000..c5a3149
--- /dev/null
@@ -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`
+   |     ^^^^^ help: instead try using: `static`
+
+error: aborting due to previous error
+
index ea2197f3fd1a0cb24925cedddac29895e79e2c48..5aea5f2ca06423823f51bbee89a1b0f0a66de551 100644 (file)
@@ -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
index 7057c8e9aaad1663872df8f935100172d42e365a..20eb7452aea7163b200f252f09482f150b44ffff 100644 (file)
@@ -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();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
index d71da58829a72772ca51a61d1e91ffe1f648c65c..a79dacbc1c959c4388a8a597436f7f20fed30980 100644 (file)
 
 #![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")
 }
index df62f5acc00748712e059522e358bbad9fd04bb2..67a1f4f88adc64767addf31df7bcc2501c40674f 100644 (file)
@@ -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
 
index d40bc3b333903fee5625460068abfab81c3a5185..8c63d7d6f91c5267666d4f9a8d979e2132cd4cf4 100644 (file)
@@ -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<Foo> {
+   |           ----------- expected `std::option::Option<Foo>` 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<Foo, Bar> {
+   |           ---------------- expected `std::result::Result<Foo, Bar>` 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<X<String, String>, String> {
+   |           ---------------------------- expected `X<X<std::string::String, std::string::String>, 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<X<String, String>, String> {
+   |           ---------------------------- expected `X<X<std::string::String, std::string::String>, std::string::String>` because of return type
+...
 60 |     x
    |     ^ expected struct `std::string::String`, found integral variable
    |
index c43f2229cdc334d189346830af9623382aa087ac..367a2560155588aa7ab644e28cd91e445a997b3b 100644 (file)
@@ -10,6 +10,8 @@
 
 // run-pass
 
+#![warn(unused)]
+
 // Parser test for #37765
 
 fn with_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `with_parens`
index 8fd1b8de68787c71e2ffffc6df8de2a65f714a79..9936a1eb81e2a9fdd39a3a24b25e6ea7dfad46e9 100644 (file)
@@ -1,26 +1,31 @@
 warning: unnecessary parentheses around `return` value
-  --> $DIR/path-lookahead.rs:16:10
+  --> $DIR/path-lookahead.rs:18:10
    |
-16 |   return (<T as ToString>::to_string(&arg)); //~WARN unnecessary parentheses around `return` value
+18 |   return (<T as ToString>::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<T: ToString>(arg: T) -> String { //~WARN function is never used: `with_parens`
-16 | |   return (<T as ToString>::to_string(&arg)); //~WARN unnecessary parentheses around `return` value
-17 | | }
+17 | / fn with_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `with_parens`
+18 | |   return (<T as ToString>::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<T: ToString>(arg: T) -> String { //~WARN function is never used: `no_parens`
-20 | |   return <T as ToString>::to_string(&arg);
-21 | | }
+21 | / fn no_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `no_parens`
+22 | |   return <T as ToString>::to_string(&arg);
+23 | | }
    | |_^
 
index 328b75fd236bcfcf73387b5b66dd447dd159b0df..9f4562fe297180fac5c8f86ca0321a64ebec014c 100644 (file)
@@ -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
 
index def0d9aced3c3e664447329d9bd52a898aa2ef7c..f59d2845108fbd93807eb638106ad5d603beac63 100644 (file)
 //! 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
+#![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.
-#![deny(warnings)]
+#![warn(unused)]
 
+#[rustc_error]
 fn main() {
     let theTwo = 2;
     let theOtherTwo = 2;
index 8332ba50a73dc3b72016dd8f54ab0c4b7df16c6d..4f1c870d87457b4448dab4f73b0737b7d3be4afa 100644 (file)
@@ -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:16:9
+  --> $DIR/issue-24690.rs:18:9
    |
-16 | #![deny(warnings)]
-   |         ^^^^^^^^
-   = note: #[deny(non_snake_case)] implied by #[deny(warnings)]
+18 | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(unused_variables)] implied by #[warn(unused)]
 
-error: variable `theOtherTwo` should have a snake case name such as `the_other_two`
-  --> $DIR/issue-24690.rs:20:9
+warning: variable `theTwo` should have a snake case name such as `the_two`
+  --> $DIR/issue-24690.rs:22:9
    |
-20 |     let theOtherTwo = 2;
-   |         ^^^^^^^^^^^
+22 |     let theTwo = 2;
+   |         ^^^^^^
+   |
+   = note: #[warn(non_snake_case)] on by default
 
-error: unused variable: `theOtherTwo`
-  --> $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;
    |         ^^^^^^^^^^^
-   |
-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
+error: compilation successful
+  --> $DIR/issue-24690.rs:21:1
+   |
+21 | / fn main() {
+22 | |     let theTwo = 2;
+23 | |     let theOtherTwo = 2;
+24 | |     println!("{}", theTwo);
+25 | | }
+   | |_^
 
index d779bec4ace539fe791a63b28fc564299d0727b2..b7aae39c4692710c349a1b60586d84a60070fcdd 100644 (file)
@@ -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;
index e7336697f48e711d191afb86ef5c47e151ccb538..af03aa6a369082662b86b4618923a3362f0c82b4 100644 (file)
@@ -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)]
 
index 43b6cd8f85f824869a1357aa0efe4b0aa39d4ed6..66536b29c0298dfa9ae0de164a8cfb0d9948f6cf 100644 (file)
@@ -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() {
index 4b1ca7f98bbf65d1d2ad8bd2e73462f5dcd16087..1fecdea7d0d06a2db513b990df57170d47a98e6c 100644 (file)
@@ -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/test/ui/trait-method-private.rs b/src/test/ui/trait-method-private.rs
new file mode 100644 (file)
index 0000000..5c1bd66
--- /dev/null
@@ -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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+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 (file)
index 0000000..c7a7b68
--- /dev/null
@@ -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
+
index 305bc25d5e105e84ffe261655b46cf74570f6e5b..7704f7b1fd52607104cc7fdc435d636c9de1fe90 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 305bc25d5e105e84ffe261655b46cf74570f6e5b
+Subproject commit 7704f7b1fd52607104cc7fdc435d636c9de1fe90
index 93696561708738905beefecf607c591e14866ec6..769748c63c02ddb52000fc01d3d3e65909e6dea3 100644 (file)
@@ -1156,9 +1156,21 @@ fn is_unexpected_compiler_message(&self,
     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)
index 1065749a6961ce5c19fcfcde01fbabccfc5517b7..10c99713820460eb869c88688b6ee7196849e3e4 100644 (file)
@@ -69,6 +69,7 @@
     "src/libstd/path.rs",
     "src/libstd/f32.rs",
     "src/libstd/f64.rs",
+    "src/libstd/lib.rs", // Until next stage0 snapshot bump
     "src/libstd/sys_common/mod.rs",
     "src/libstd/sys_common/net.rs",
     "src/libterm", // Not sure how to make this crate portable, but test needs it
index b42beb37821cef09e09f52073161ad62b2cd0eda..a689d8a8be4119d2808ed086b6a83cc81cfb4aa1 100644 (file)
@@ -83,7 +83,7 @@ fn line_is_url(line: &str) -> bool {
                 => state = EXP_END,
 
             (EXP_URL, w)
-                if w.starts_with("http://") || w.starts_with("https://")
+                if w.starts_with("http://") || w.starts_with("https://") || w.starts_with("../")
                 => state = EXP_END,
 
             (_, _) => return false,