]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #56863 - arielb1:supertrait-self-4, r=nikomatsakis
authorbors <bors@rust-lang.org>
Tue, 18 Dec 2018 19:58:14 +0000 (19:58 +0000)
committerbors <bors@rust-lang.org>
Tue, 18 Dec 2018 19:58:14 +0000 (19:58 +0000)
fix trait objects with a Self-containing projection values

Fixes #56288.

This follows ALT2 in the issue.

beta-nominating since this is a regression.

r? @nikomatsakis

213 files changed:
.travis.yml
Cargo.lock
README.md
src/bootstrap/Cargo.toml
src/bootstrap/builder.rs
src/bootstrap/cache.rs
src/bootstrap/cc_detect.rs
src/bootstrap/channel.rs
src/bootstrap/check.rs
src/bootstrap/clean.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/flags.rs
src/bootstrap/install.rs
src/bootstrap/job.rs
src/bootstrap/lib.rs
src/bootstrap/metadata.rs
src/bootstrap/native.rs
src/bootstrap/sanity.rs
src/bootstrap/test.rs
src/bootstrap/tool.rs
src/bootstrap/util.rs
src/ci/docker/x86_64-gnu-llvm-5.0/Dockerfile [deleted file]
src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile [new file with mode: 0644]
src/liballoc/collections/btree/node.rs
src/liballoc/collections/linked_list.rs
src/liballoc/tests/vec.rs
src/libcore/fmt/mod.rs
src/libcore/future/future.rs
src/libcore/iter/iterator.rs
src/libcore/iter/mod.rs
src/libcore/lib.rs
src/libcore/num/mod.rs
src/libcore/ops/function.rs
src/libcore/ptr.rs
src/libcore/sync/atomic.rs
src/libcore/tests/iter.rs
src/librustc/infer/canonical/query_response.rs
src/librustc/infer/combine.rs
src/librustc/infer/equate.rs
src/librustc/infer/glb.rs
src/librustc/infer/lub.rs
src/librustc/infer/mod.rs
src/librustc/infer/nll_relate/mod.rs
src/librustc/infer/sub.rs
src/librustc/lint/builtin.rs
src/librustc/middle/liveness.rs
src/librustc/middle/stability.rs
src/librustc/mir/mod.rs
src/librustc/traits/coherence.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/mod.rs
src/librustc/traits/select.rs
src/librustc/traits/specialize/mod.rs
src/librustc/traits/specialize/specialization_graph.rs
src/librustc/ty/_match.rs
src/librustc/ty/fast_reject.rs
src/librustc/ty/mod.rs
src/librustc/ty/relate.rs
src/librustc/ty/structural_impls.rs
src/librustc_codegen_llvm/builder.rs
src/librustc_codegen_llvm/context.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/librustc_codegen_llvm/llvm_util.rs
src/librustc_codegen_ssa/mir/mod.rs
src/librustc_codegen_ssa/traits/misc.rs
src/librustc_lint/lib.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/nll/invalidation.rs
src/librustc_mir/borrow_check/places_conflict.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/matches/simplify.rs
src/librustc_mir/build/matches/test.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/mod.rs
src/librustc_mir/hair/pattern/_match.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/lib.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/promote_consts.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/qualify_min_const_fn.rs
src/librustc_mir/transform/simplify.rs
src/librustc_passes/lib.rs
src/librustc_passes/mir_stats.rs [deleted file]
src/librustc_target/spec/apple_ios_base.rs
src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
src/librustc_traits/chalk_context/resolvent_ops.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/coherence/inherent_impls_overlap.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/storage.js
src/librustdoc/test.rs
src/libstd/Cargo.toml
src/libstd/f32.rs
src/libstd/f64.rs
src/libstd/fs.rs
src/libstd/lib.rs
src/libstd/os/raw/mod.rs
src/libstd/sys_common/backtrace.rs
src/libsyntax/attr/mod.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/quote.rs
src/libsyntax/ext/tt/transcribe.rs
src/libsyntax/feature_gate.rs
src/libsyntax/lib.rs
src/libsyntax/parse/attr.rs
src/libsyntax/parse/lexer/tokentrees.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/tokenstream.rs
src/libsyntax/util/rc_slice.rs [deleted file]
src/libsyntax/util/rc_vec.rs [deleted file]
src/llvm
src/rustllvm/ArchiveWrapper.cpp
src/rustllvm/PassWrapper.cpp
src/rustllvm/RustWrapper.cpp
src/rustllvm/llvm-rebuild-trigger
src/stdsimd
src/test/codegen/function-arguments.rs
src/test/codegen/issue-44056-macos-tls-align.rs
src/test/codegen/issue-45222.rs
src/test/codegen/issue-45466.rs
src/test/codegen/simd-intrinsic-generic-gather.rs
src/test/codegen/simd-intrinsic-generic-scatter.rs
src/test/codegen/vtabletype.rs
src/test/compile-fail/const-fn-error.rs
src/test/compile-fail/must_use-in-stdlib-traits.rs [new file with mode: 0644]
src/test/mir-opt/match_test.rs [new file with mode: 0644]
src/test/mir-opt/simplify_cfg.rs [new file with mode: 0644]
src/test/run-pass/ctfe/const-fn-destructuring-arg.rs [deleted file]
src/test/run-pass/issues/issue-33140.rs [new file with mode: 0644]
src/test/run-pass/mir/mir_match_test.rs [new file with mode: 0644]
src/test/run-pass/simd/simd-intrinsic-generic-gather.rs
src/test/run-pass/sse2.rs
src/test/rustdoc/comment-in-doctest.rs [new file with mode: 0644]
src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs
src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr
src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
src/test/ui/consts/const-fn-not-safe-for-const.rs
src/test/ui/consts/const-fn-not-safe-for-const.stderr
src/test/ui/consts/const_let_assign3.rs
src/test/ui/consts/const_let_assign3.stderr
src/test/ui/consts/const_let_eq.rs [new file with mode: 0644]
src/test/ui/consts/const_let_eq_float.rs [new file with mode: 0644]
src/test/ui/consts/const_short_circuit.rs [new file with mode: 0644]
src/test/ui/consts/const_short_circuit.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
src/test/ui/consts/min_const_fn/min_const_fn.rs
src/test/ui/consts/min_const_fn/min_const_fn.stderr
src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs
src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr
src/test/ui/consts/min_const_fn/mutable_borrow.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/mutable_borrow.stderr [new file with mode: 0644]
src/test/ui/consts/projection_qualif.rs
src/test/ui/consts/projection_qualif.stderr
src/test/ui/consts/single_variant_match_ice.rs
src/test/ui/consts/single_variant_match_ice.stderr
src/test/ui/deprecation/deprecation-in-future.rs [new file with mode: 0644]
src/test/ui/deprecation/deprecation-in-future.stderr [new file with mode: 0644]
src/test/ui/extern/auxiliary/invalid-utf8.txt [new file with mode: 0644]
src/test/ui/extern/external-doc-error.rs
src/test/ui/extern/external-doc-error.stderr
src/test/ui/feature-gates/feature-gate-const_let.rs
src/test/ui/feature-gates/feature-gate-const_let.stderr
src/test/ui/feature-gates/feature-gate-underscore-imports.rs [deleted file]
src/test/ui/feature-gates/feature-gate-underscore-imports.stderr [deleted file]
src/test/ui/issues/issue-33140.rs [new file with mode: 0644]
src/test/ui/issues/issue-33140.stderr [new file with mode: 0644]
src/test/ui/issues/issue-37550.rs
src/test/ui/issues/issue-37550.stderr
src/test/ui/issues/issue-56199.rs [new file with mode: 0644]
src/test/ui/issues/issue-56199.stderr [new file with mode: 0644]
src/test/ui/issues/issue-56835.rs [new file with mode: 0644]
src/test/ui/issues/issue-56835.stderr [new file with mode: 0644]
src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
src/test/ui/liveness/liveness-dead.stderr
src/test/ui/liveness/liveness-unused.stderr
src/test/ui/nll/match-on-borrowed.rs
src/test/ui/nll/match-on-borrowed.stderr
src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs
src/test/ui/rfc-2166-underscore-imports/basic.rs
src/test/ui/rfc-2166-underscore-imports/basic.stderr
src/test/ui/rfc-2166-underscore-imports/duplicate.rs
src/test/ui/rfc-2166-underscore-imports/unused-2018.rs
src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr
src/test/ui/rust-2018/future-proofing-locals.rs
src/test/ui/rust-2018/uniform-paths/macro-rules.rs
src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
src/test/ui/suggestions/path-display.rs [new file with mode: 0644]
src/test/ui/suggestions/path-display.stderr [new file with mode: 0644]
src/test/ui/target-feature-gate.rs
src/test/ui/target-feature-gate.stderr
src/tools/clippy
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/util.rs
src/tools/linkchecker/main.rs
src/tools/publish_toolstate.py
src/tools/tidy/src/deps.rs

index 3f2e43ab86d90b1159edee7c4986a48bb2631aa7..9e46e6b8ef6b15a39e7d2b472befb604b5ad2e06 100644 (file)
@@ -16,7 +16,7 @@ matrix:
   fast_finish: true
   include:
     # Images used in testing PR and try-build should be run first.
-    - env: IMAGE=x86_64-gnu-llvm-5.0 RUST_BACKTRACE=1
+    - env: IMAGE=x86_64-gnu-llvm-6.0 RUST_BACKTRACE=1
       if: type = pull_request OR branch = auto
 
     - env: IMAGE=dist-x86_64-linux DEPLOY=1
index be4a1c2f1d3c40292b0d5530e59b38a7dcb4b231..7e03474565d857a8b4af3ebc7cc48107076162b4 100644 (file)
@@ -87,7 +87,7 @@ dependencies = [
  "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1813,7 +1813,7 @@ name = "rand_chacha"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1835,7 +1835,7 @@ name = "rand_hc"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1860,7 +1860,7 @@ name = "rand_xorshift"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2195,8 +2195,12 @@ dependencies = [
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.9"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-std-workspace-core 1.0.0",
+]
 
 [[package]]
 name = "rustc-hash"
@@ -2315,7 +2319,7 @@ dependencies = [
  "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_llvm 0.0.0",
 ]
 
@@ -2331,7 +2335,7 @@ dependencies = [
  "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
  "rustc_apfloat 0.0.0",
  "rustc_codegen_utils 0.0.0",
@@ -2892,6 +2896,7 @@ dependencies = [
  "panic_unwind 0.0.0",
  "profiler_builtins 0.0.0",
  "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_asan 0.0.0",
  "rustc_lsan 0.0.0",
  "rustc_msan 0.0.0",
@@ -3578,7 +3583,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2c0e8161e956647592a737074736e6ce05ea36b70c770ea8cca3eb9cb33737"
 "checksum rustc-ap-syntax 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1adc189e5e4500a4167b9afa04e67067f40d0039e0e05870c977bebb561f065a"
 "checksum rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d42c430dbb0be4377bfe6aa5099074c63ac8796b24098562c2e2154aecc5652"
-"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
+"checksum rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "82ae957aa1b3055d8e086486723c0ccd3d7b8fa190ae8fa2e35543b6171c810e"
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
 "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306"
 "checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649"
index 37442661bcbc1f73daab687a1e2e97f25ce263a3..dc013a1ad2be66985b47fc5d0a8313cdd1169bed 100644 (file)
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ standard library, and documentation.
 
 Read ["Installation"] from [The Book].
 
-["Installation"]: https://doc.rust-lang.org/book/second-edition/ch01-01-installation.html
+["Installation"]: https://doc.rust-lang.org/book/ch01-01-installation.html
 [The Book]: https://doc.rust-lang.org/book/index.html
 
 ## Building from Source
index 3e91c2b3e86c8316bf4e9e6a769b1f7e8b2d289c..0f7b6c22e1cc52ff8632881b195b831f8d4d3aca 100644 (file)
@@ -2,6 +2,7 @@
 authors = ["The Rust Project Developers"]
 name = "bootstrap"
 version = "0.0.0"
+edition = "2018"
 
 [lib]
 name = "bootstrap"
index c1d56865da55ceada06595b80834d42ebc827e5b..405fc871eef76e6f22763c3b510261a9d134f80d 100644 (file)
 use std::process::Command;
 use std::time::{Duration, Instant};
 
-use cache::{Cache, Interned, INTERNER};
-use check;
-use compile;
-use dist;
-use doc;
-use flags::Subcommand;
-use install;
-use native;
-use test;
-use tool;
-use util::{add_lib_path, exe, libdir};
-use {Build, DocTests, Mode, GitRepo};
-
-pub use Compiler;
+use crate::cache::{Cache, Interned, INTERNER};
+use crate::check;
+use crate::compile;
+use crate::dist;
+use crate::doc;
+use crate::flags::Subcommand;
+use crate::install;
+use crate::native;
+use crate::test;
+use crate::tool;
+use crate::util::{add_lib_path, exe, libdir};
+use crate::{Build, DocTests, Mode, GitRepo};
+
+pub use crate::Compiler;
 
 use petgraph::graph::NodeIndex;
 use petgraph::Graph;
@@ -1252,7 +1252,7 @@ pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
 #[cfg(test)]
 mod __test {
     use super::*;
-    use config::Config;
+    use crate::config::Config;
     use std::thread;
 
     fn configure(host: &[&str], target: &[&str]) -> Config {
index 0b561a3523f2b483460d8549b75f4913d7a6bcd0..165cffa4587d370bbddf7567c5509c566e480605 100644 (file)
@@ -23,7 +23,7 @@
 use std::sync::Mutex;
 use std::cmp::{PartialOrd, Ord, Ordering};
 
-use builder::Step;
+use crate::builder::Step;
 
 pub struct Interned<T>(usize, PhantomData<*const T>);
 
index d5da0cabec84aa7d5fc61cb3f65011831ca91761..3d2b3a2c9de498ee7bc69bb1f14b5bed96bf82de 100644 (file)
@@ -39,9 +39,9 @@
 use build_helper::output;
 use cc;
 
-use {Build, GitRepo};
-use config::Target;
-use cache::Interned;
+use crate::{Build, GitRepo};
+use crate::config::Target;
+use crate::cache::Interned;
 
 // The `cc` crate doesn't provide a way to obtain a path to the detected archiver,
 // so use some simplified logic here. First we respect the environment variable `AR`, then
index 878b6ed73a3125712e6034aa151188cafa8aa989..8756ec944c25704da8a5dc9e3a3a00aa6c61e7b6 100644 (file)
@@ -20,8 +20,8 @@
 
 use build_helper::output;
 
-use Build;
-use config::Config;
+use crate::Build;
+use crate::config::Config;
 
 // The version number
 pub const CFG_RELEASE_NUM: &str = "1.33.0";
index 0c6dbb06bb8821053171421780a0e556983b5b88..84e7c40e4559e479a94d2b71257ea0bc9fdff3c3 100644 (file)
 
 //! Implementation of compiling the compiler and standard library, in "check" mode.
 
-use compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env, add_to_sysroot};
-use builder::{RunConfig, Builder, ShouldRun, Step};
-use tool::{prepare_tool_cargo, SourceType};
-use {Compiler, Mode};
-use cache::{INTERNER, Interned};
+use crate::compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env,
+                     add_to_sysroot};
+use crate::builder::{RunConfig, Builder, ShouldRun, Step};
+use crate::tool::{prepare_tool_cargo, SourceType};
+use crate::{Compiler, Mode};
+use crate::cache::{INTERNER, Interned};
 use std::path::PathBuf;
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
index 87f194fb7d2f85d4ae3eed1e32efd0390331975b..dc42159d068b1e6bff46bfed57290fc5fc716d15 100644 (file)
@@ -19,7 +19,7 @@
 use std::io::{self, ErrorKind};
 use std::path::Path;
 
-use Build;
+use crate::Build;
 
 pub fn clean(build: &Build, all: bool) {
     rm_rf("tmp".as_ref());
index 689d0530f8b24890b9ff4b9ba99fa7f50ce7f798..61a04b97206029fbb3679f7e17358dc893456bb5 100644 (file)
 use filetime::FileTime;
 use serde_json;
 
-use util::{exe, libdir, is_dylib};
-use {Compiler, Mode, GitRepo};
-use native;
+use crate::util::{exe, libdir, is_dylib};
+use crate::{Compiler, Mode, GitRepo};
+use crate::native;
 
-use cache::{INTERNER, Interned};
-use builder::{Step, RunConfig, ShouldRun, Builder};
+use crate::cache::{INTERNER, Interned};
+use crate::builder::{Step, RunConfig, ShouldRun, Builder};
 
 #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Std {
index 1dafbe148afdafd503f1f640e36c4749d1e69b6d..2ae9da9c085d4397811f30051d9cd8ee5879d26e 100644 (file)
@@ -22,9 +22,9 @@
 
 use num_cpus;
 use toml;
-use cache::{INTERNER, Interned};
-use flags::Flags;
-pub use flags::Subcommand;
+use crate::cache::{INTERNER, Interned};
+use crate::flags::Flags;
+pub use crate::flags::Subcommand;
 
 /// Global configuration for the entire build and/or bootstrap.
 ///
index f03eefb7a129bd3c869006822b6004c1c4eaea48..927f9bf8ddbca36ce57320793902ae916c95b518 100644 (file)
 
 use build_helper::output;
 
-use {Compiler, Mode, LLVM_TOOLS};
-use channel;
-use util::{libdir, is_dylib, exe};
-use builder::{Builder, RunConfig, ShouldRun, Step};
-use compile;
-use tool::{self, Tool};
-use cache::{INTERNER, Interned};
+use crate::{Compiler, Mode, LLVM_TOOLS};
+use crate::channel;
+use crate::util::{libdir, is_dylib, exe};
+use crate::builder::{Builder, RunConfig, ShouldRun, Step};
+use crate::compile;
+use crate::tool::{self, Tool};
+use crate::cache::{INTERNER, Interned};
 use time;
 
 pub fn pkgname(builder: &Builder, component: &str) -> String {
index 2d0625b26dbe3cf19de5a655fcafad2d0669f40a..217328adfbf66403925f23a05a112ef6916a0667 100644 (file)
 use std::io;
 use std::path::{PathBuf, Path};
 
-use Mode;
+use crate::Mode;
 use build_helper::up_to_date;
 
-use util::symlink_dir;
-use builder::{Builder, Compiler, RunConfig, ShouldRun, Step};
-use tool::{self, prepare_tool_cargo, Tool, SourceType};
-use compile;
-use cache::{INTERNER, Interned};
-use config::Config;
+use crate::util::symlink_dir;
+use crate::builder::{Builder, Compiler, RunConfig, ShouldRun, Step};
+use crate::tool::{self, prepare_tool_cargo, Tool, SourceType};
+use crate::compile;
+use crate::cache::{INTERNER, Interned};
+use crate::config::Config;
 
 macro_rules! book {
     ($($name:ident, $path:expr, $book_name:expr;)+) => {
index c49da8fc734892042d4f70c03e2e8a39600461bb..14e2f69432dac21d96753c6e1eeb1d78cb0b1591 100644 (file)
 
 use getopts::Options;
 
-use builder::Builder;
-use config::Config;
-use metadata;
-use {Build, DocTests};
+use crate::builder::Builder;
+use crate::config::Config;
+use crate::metadata;
+use crate::{Build, DocTests};
 
-use cache::{Interned, INTERNER};
+use crate::cache::{Interned, INTERNER};
 
 /// Deserialized version of all flags for this compile.
 pub struct Flags {
index cb28698aa3d6d22b2b7495550a40868c413a90fc..aebcfb4519543abbea8e271b402f66a807c3fbb9 100644 (file)
 use std::path::{Path, PathBuf, Component};
 use std::process::Command;
 
-use dist::{self, pkgname, sanitize_sh, tmpdir};
+use crate::dist::{self, pkgname, sanitize_sh, tmpdir};
 
-use builder::{Builder, RunConfig, ShouldRun, Step};
-use cache::Interned;
-use config::Config;
+use crate::builder::{Builder, RunConfig, ShouldRun, Step};
+use crate::cache::Interned;
+use crate::config::Config;
 
 pub fn install_docs(builder: &Builder, stage: u32, host: Interned<String>) {
     install_sh(builder, "docs", "rust-docs", stage, Some(host));
index f7b1c50f0fd67de61b24743c87b99118a331be59..a9da2c491da53992774affa8f2c2d63660e027ca 100644 (file)
@@ -42,7 +42,7 @@
 use std::env;
 use std::io;
 use std::mem;
-use Build;
+use crate::Build;
 
 type HANDLE = *mut u8;
 type BOOL = i32;
index c8792918db2e2654e95b3c208ca05373f5514cf3..c5b8f19eee6fb0b27a41c2c010cffaf7729b52b1 100644 (file)
 use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppressed, output, mtime};
 use filetime::FileTime;
 
-use util::{exe, libdir, OutputFolder, CiEnv};
+use crate::util::{exe, libdir, OutputFolder, CiEnv};
 
 mod cc_detect;
 mod channel;
 mod job {
     use libc;
 
-    pub unsafe fn setup(build: &mut ::Build) {
+    pub unsafe fn setup(build: &mut crate::Build) {
         if build.config.low_priority {
             libc::setpriority(libc::PRIO_PGRP as _, 0, 10);
         }
@@ -197,14 +197,14 @@ pub unsafe fn setup(build: &mut ::Build) {
 
 #[cfg(any(target_os = "haiku", not(any(unix, windows))))]
 mod job {
-    pub unsafe fn setup(_build: &mut ::Build) {
+    pub unsafe fn setup(_build: &mut crate::Build) {
     }
 }
 
-pub use config::Config;
-use flags::Subcommand;
-use cache::{Interned, INTERNER};
-use toolstate::ToolState;
+pub use crate::config::Config;
+use crate::flags::Subcommand;
+use crate::cache::{Interned, INTERNER};
+use crate::toolstate::ToolState;
 
 const LLVM_TOOLS: &[&str] = &[
     "llvm-nm", // used to inspect binaries; it shows symbol names, their sizes and visibility
index fa0b1983510b90075b44b6ff0175a5cf58ada47a..bb503e8b8d3d1bf8d6bb1bd145297312af3903a2 100644 (file)
@@ -16,8 +16,8 @@
 use build_helper::output;
 use serde_json;
 
-use {Build, Crate};
-use cache::INTERNER;
+use crate::{Build, Crate};
+use crate::cache::INTERNER;
 
 #[derive(Deserialize)]
 struct Output {
index 8ff175b01875688582f1aaec820d5be546b898a9..d9f51f6fd3d070315eb47323809d89fc9dd16c58 100644 (file)
 use cmake;
 use cc;
 
-use util::{self, exe};
+use crate::util::{self, exe};
 use build_helper::up_to_date;
-use builder::{Builder, RunConfig, ShouldRun, Step};
-use cache::Interned;
-use GitRepo;
+use crate::builder::{Builder, RunConfig, ShouldRun, Step};
+use crate::cache::Interned;
+use crate::GitRepo;
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct Llvm {
@@ -278,11 +278,11 @@ fn check_llvm_version(builder: &Builder, llvm_config: &Path) {
     let mut parts = version.split('.').take(2)
         .filter_map(|s| s.parse::<u32>().ok());
     if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) {
-        if major >= 5 {
+        if major >= 6 {
             return
         }
     }
-    panic!("\n\nbad LLVM version: {}, need >=5.0\n\n", version)
+    panic!("\n\nbad LLVM version: {}, need >=6.0\n\n", version)
 }
 
 fn configure_cmake(builder: &Builder,
index 7a9e6d4fd387b8a7fa3b0a6b7954c457b0191fda..f585495b0aa947f573a11ccc16875411032b5d80 100644 (file)
@@ -27,7 +27,7 @@
 
 use build_helper::output;
 
-use Build;
+use crate::Build;
 
 struct Finder {
     cache: HashMap<OsString, Option<PathBuf>>,
index 87d5737e2a0a2202ad89adf38a826442d7e30b74..11932d58ceac623011357f60652b4a15f26a2cea 100644 (file)
 
 use build_helper::{self, output};
 
-use builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
-use cache::{Interned, INTERNER};
-use compile;
-use dist;
-use flags::Subcommand;
-use native;
-use tool::{self, Tool, SourceType};
-use toolstate::ToolState;
-use util::{self, dylib_path, dylib_path_var};
-use Crate as CargoCrate;
-use {DocTests, Mode, GitRepo};
+use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
+use crate::cache::{Interned, INTERNER};
+use crate::compile;
+use crate::dist;
+use crate::flags::Subcommand;
+use crate::native;
+use crate::tool::{self, Tool, SourceType};
+use crate::toolstate::ToolState;
+use crate::util::{self, dylib_path, dylib_path_var};
+use crate::Crate as CargoCrate;
+use crate::{DocTests, Mode, GitRepo};
 
 const ADB_TEST_DIR: &str = "/data/tmp/work";
 
@@ -616,7 +616,7 @@ fn run(self, builder: &Builder) {
         if let Some(ref nodejs) = builder.config.nodejs {
             let mut command = Command::new(nodejs);
             command.args(&["src/tools/rustdoc-js/tester.js", &*self.host]);
-            builder.ensure(::doc::Std {
+            builder.ensure(crate::doc::Std {
                 target: self.target,
                 stage: builder.top_stage,
             });
index 1bd4403a66ffa9aea6888d9f02f7fefd6086f77a..4335359e11589c7295c18e2f4832f615d61d7b2e 100644 (file)
 use std::process::{Command, exit};
 use std::collections::HashSet;
 
-use Mode;
-use Compiler;
-use builder::{Step, RunConfig, ShouldRun, Builder};
-use util::{exe, add_lib_path};
-use compile;
-use native;
-use channel::GitInfo;
-use channel;
-use cache::Interned;
-use toolstate::ToolState;
+use crate::Mode;
+use crate::Compiler;
+use crate::builder::{Step, RunConfig, ShouldRun, Builder};
+use crate::util::{exe, add_lib_path};
+use crate::compile;
+use crate::native;
+use crate::channel::GitInfo;
+use crate::channel;
+use crate::cache::Interned;
+use crate::toolstate::ToolState;
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub enum SourceType {
index be24ae0ce664815e96f42e65c00cd094e2bd6a47..b18e38e471efff47672d499e91ce736aca49c1c2 100644 (file)
@@ -21,8 +21,8 @@
 use std::process::Command;
 use std::time::{SystemTime, Instant};
 
-use config::Config;
-use builder::Builder;
+use crate::config::Config;
+use crate::builder::Builder;
 
 /// Returns the `name` as the filename of a static library for `target`.
 pub fn staticlib(name: &str, target: &str) -> String {
diff --git a/src/ci/docker/x86_64-gnu-llvm-5.0/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-5.0/Dockerfile
deleted file mode 100644 (file)
index 4f90c50..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++ \
-  make \
-  file \
-  curl \
-  ca-certificates \
-  python2.7 \
-  git \
-  cmake \
-  sudo \
-  gdb \
-  llvm-5.0-tools \
-  libedit-dev \
-  zlib1g-dev \
-  xz-utils
-
-COPY scripts/sccache.sh /scripts/
-RUN sh /scripts/sccache.sh
-
-# using llvm-link-shared due to libffi issues -- see #34486
-ENV RUST_CONFIGURE_ARGS \
-      --build=x86_64-unknown-linux-gnu \
-      --llvm-root=/usr/lib/llvm-5.0 \
-      --enable-llvm-link-shared
-ENV RUST_CHECK_TARGET check
diff --git a/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile
new file mode 100644 (file)
index 0000000..160b23e
--- /dev/null
@@ -0,0 +1,27 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  g++ \
+  make \
+  file \
+  curl \
+  ca-certificates \
+  python2.7 \
+  git \
+  cmake \
+  sudo \
+  gdb \
+  llvm-6.0-tools \
+  libedit-dev \
+  zlib1g-dev \
+  xz-utils
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# using llvm-link-shared due to libffi issues -- see #34486
+ENV RUST_CONFIGURE_ARGS \
+      --build=x86_64-unknown-linux-gnu \
+      --llvm-root=/usr/lib/llvm-6.0 \
+      --enable-llvm-link-shared
+ENV RUST_CHECK_TARGET check
index 215689dfc48c99c007d06ce4ec16f91877a2d704..a2d2d3c74be9dd261813b56a42eaa19f8527df2a 100644 (file)
 /// these should always be put behind pointers, and specifically behind `BoxedNode` in the owned
 /// case.
 ///
-/// We put the metadata first so that its position is the same for every `K` and `V`, in order
-/// to statically allocate a single dummy node to avoid allocations. This struct is `repr(C)` to
-/// prevent them from being reordered.
+/// We have a separate type for the header and rely on it matching the prefix of `LeafNode`, in
+/// order to statically allocate a single dummy node to avoid allocations. This struct is
+/// `repr(C)` to prevent them from being reordered.  `LeafNode` does not just contain a
+/// `NodeHeader` because we do not want unnecessary padding between `len` and the keys.
+/// Crucially, `NodeHeader` can be safely transmuted to different K and V.  (This is exploited
+/// by `as_header`.)
+/// See `into_key_slice` for an explanation of K2.  K2 cannot be safely transmuted around
+/// because the size of `NodeHeader` depends on its alignment!
+#[repr(C)]
+struct NodeHeader<K, V, K2 = ()> {
+    /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
+    /// This either points to an actual node or is null.
+    parent: *const InternalNode<K, V>,
+
+    /// This node's index into the parent node's `edges` array.
+    /// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`.
+    /// This is only guaranteed to be initialized when `parent` is non-null.
+    parent_idx: MaybeUninit<u16>,
+
+    /// The number of keys and values this node stores.
+    ///
+    /// This next to `parent_idx` to encourage the compiler to join `len` and
+    /// `parent_idx` into the same 32-bit word, reducing space overhead.
+    len: u16,
+
+    /// See `into_key_slice`.
+    keys_start: [K2; 0],
+}
 #[repr(C)]
 struct LeafNode<K, V> {
     /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
@@ -98,24 +123,25 @@ unsafe fn new() -> Self {
             len: 0
         }
     }
+}
 
+impl<K, V> NodeHeader<K, V> {
     fn is_shared_root(&self) -> bool {
         ptr::eq(self, &EMPTY_ROOT_NODE as *const _ as *const _)
     }
 }
 
 // We need to implement Sync here in order to make a static instance.
-unsafe impl Sync for LeafNode<(), ()> {}
+unsafe impl Sync for NodeHeader<(), ()> {}
 
 // An empty node used as a placeholder for the root node, to avoid allocations.
-// We use () in order to save space, since no operation on an empty tree will
+// We use just a header in order to save space, since no operation on an empty tree will
 // ever take a pointer past the first key.
-static EMPTY_ROOT_NODE: LeafNode<(), ()> = LeafNode {
+static EMPTY_ROOT_NODE: NodeHeader<(), ()> = NodeHeader {
     parent: ptr::null(),
     parent_idx: MaybeUninit::uninitialized(),
     len: 0,
-    keys: MaybeUninit::uninitialized(),
-    vals: MaybeUninit::uninitialized(),
+    keys_start: [],
 };
 
 /// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden
@@ -281,7 +307,7 @@ pub fn pop_level(&mut self) {
                                     .node)
         };
         self.height -= 1;
-        self.as_mut().as_leaf_mut().parent = ptr::null();
+        unsafe { (*self.as_mut().as_leaf_mut()).parent = ptr::null(); }
 
         unsafe {
             Global.dealloc(NonNull::from(top).cast(), Layout::new::<InternalNode<K, V>>());
@@ -306,6 +332,11 @@ pub fn pop_level(&mut self) {
 ///   `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the
 ///   `NodeRef` points to an internal node, and when this is `LeafOrInternal` the
 ///   `NodeRef` could be pointing to either type of node.
+///   Note that in case of a leaf node, this might still be the shared root!  Only turn
+///   this into a `LeafNode` reference if you know it is not a root!  Shared references
+///   must be dereferencable *for the entire size of their pointee*, so `&InternalNode`
+///   pointing to the shared root is UB.
+///   Turning this into a `NodeHeader` is always safe.
 pub struct NodeRef<BorrowType, K, V, Type> {
     height: usize,
     node: NonNull<LeafNode<K, V>>,
@@ -352,7 +383,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
     /// Finds the length of the node. This is the number of keys or values. In an
     /// internal node, the number of edges is `len() + 1`.
     pub fn len(&self) -> usize {
-        self.as_leaf().len as usize
+        self.as_header().len as usize
     }
 
     /// Returns the height of this node in the whole tree. Zero height denotes the
@@ -382,14 +413,19 @@ fn reborrow<'a>(&'a self) -> NodeRef<marker::Immut<'a>, K, V, Type> {
         }
     }
 
-    fn as_leaf(&self) -> &LeafNode<K, V> {
+    /// Assert that this is indeed a proper leaf node, and not the shared root.
+    unsafe fn as_leaf(&self) -> &LeafNode<K, V> {
+        self.node.as_ref()
+    }
+
+    fn as_header(&self) -> &NodeHeader<K, V> {
         unsafe {
-            self.node.as_ref()
+            &*(self.node.as_ptr() as *const NodeHeader<K, V>)
         }
     }
 
     pub fn is_shared_root(&self) -> bool {
-        self.as_leaf().is_shared_root()
+        self.as_header().is_shared_root()
     }
 
     pub fn keys(&self) -> &[K] {
@@ -418,7 +454,7 @@ pub fn ascend(self) -> Result<
         >,
         Self
     > {
-        let parent_as_leaf = self.as_leaf().parent as *const LeafNode<K, V>;
+        let parent_as_leaf = self.as_header().parent as *const LeafNode<K, V>;
         if let Some(non_zero) = NonNull::new(parent_as_leaf as *mut _) {
             Ok(Handle {
                 node: NodeRef {
@@ -427,7 +463,7 @@ pub fn ascend(self) -> Result<
                     root: self.root,
                     _marker: PhantomData
                 },
-                idx: unsafe { usize::from(*self.as_leaf().parent_idx.get_ref()) },
+                idx: unsafe { usize::from(*self.as_header().parent_idx.get_ref()) },
                 _marker: PhantomData
             })
         } else {
@@ -534,10 +570,10 @@ unsafe fn reborrow_mut(&mut self) -> NodeRef<marker::Mut, K, V, Type> {
         }
     }
 
-    fn as_leaf_mut(&mut self) -> &mut LeafNode<K, V> {
-        unsafe {
-            self.node.as_mut()
-        }
+    /// Returns a raw ptr to avoid asserting exclusive access to the entire node.
+    fn as_leaf_mut(&mut self) -> *mut LeafNode<K, V> {
+        // We are mutable, so we cannot be the root, so accessing this as a leaf is okay.
+        self.node.as_ptr()
     }
 
     fn keys_mut(&mut self) -> &mut [K] {
@@ -551,28 +587,50 @@ fn vals_mut(&mut self) -> &mut [V] {
 
 impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
     fn into_key_slice(self) -> &'a [K] {
-        // When taking a pointer to the keys, if our key has a stricter
-        // alignment requirement than the shared root does, then the pointer
-        // would be out of bounds, which LLVM assumes will not happen. If the
-        // alignment is more strict, we need to make an empty slice that doesn't
-        // use an out of bounds pointer.
+        // We have to be careful here because we might be pointing to the shared root.
+        // In that case, we must not create an `&LeafNode`.  We could just return
+        // an empty slice whenever the length is 0 (this includes the shared root),
+        // but we want to avoid that run-time check.
+        // Instead, we create a slice pointing into the node whenever possible.
+        // We can sometimes do this even for the shared root, as the slice will be
+        // empty.  We cannot *always* do this because if the type is too highly
+        // aligned, the offset of `keys` in a "full node" might be outside the bounds
+        // of the header!  So we do an alignment check first, that will be
+        // evaluated at compile-time, and only do any run-time check in the rare case
+        // that the alignment is very big.
         if mem::align_of::<K>() > mem::align_of::<LeafNode<(), ()>>() && self.is_shared_root() {
             &[]
         } else {
-            // Here either it's not the root, or the alignment is less strict,
-            // in which case the keys pointer will point "one-past-the-end" of
-            // the node, which is allowed by LLVM.
+            // Thanks to the alignment check above, we know that `keys` will be
+            // in-bounds of some allocation even if this is the shared root!
+            // (We might be one-past-the-end, but that is allowed by LLVM.)
+            // Getting the pointer is tricky though.  `NodeHeader` does not have a `keys`
+            // field because we want its size to not depend on the alignment of `K`
+            // (needed becuase `as_header` should be safe).  We cannot call `as_leaf`
+            // because we might be the shared root.
+            // For this reason, `NodeHeader` has this `K2` parameter (that's usually `()`
+            // and hence just adds a size-0-align-1 field, not affecting layout).
+            // We know that we can transmute `NodeHeader<K, V, ()>` to `NodeHeader<K, V, K>`
+            // because we did the alignment check above, and hence `NodeHeader<K, V, K>`
+            // is not bigger than `NodeHeader<K, V, ()>`!  Then we can use `NodeHeader<K, V, K>`
+            // to compute the pointer where the keys start.
+            // This entire hack will become unnecessary once
+            // <https://github.com/rust-lang/rfcs/pull/2582> lands, then we can just take a raw
+            // pointer to the `keys` field of `*const InternalNode<K, V>`.
+
+            // This is a non-debug-assert because it can be completely compile-time evaluated.
+            assert!(mem::size_of::<NodeHeader<K, V>>() == mem::size_of::<NodeHeader<K, V, K>>());
+            let header = self.as_header() as *const _ as *const NodeHeader<K, V, K>;
+            let keys = unsafe { &(*header).keys_start as *const _ as *const K };
             unsafe {
-                slice::from_raw_parts(
-                    self.as_leaf().keys.as_ptr() as *const K,
-                    self.len()
-                )
+                slice::from_raw_parts(keys, self.len())
             }
         }
     }
 
     fn into_val_slice(self) -> &'a [V] {
         debug_assert!(!self.is_shared_root());
+        // We cannot be the root, so `as_leaf` is okay
         unsafe {
             slice::from_raw_parts(
                 self.as_leaf().vals.as_ptr() as *const V,
@@ -602,7 +660,7 @@ fn into_key_slice_mut(mut self) -> &'a mut [K] {
         } else {
             unsafe {
                 slice::from_raw_parts_mut(
-                    self.as_leaf_mut().keys.as_mut_ptr() as *mut K,
+                    (*self.as_leaf_mut()).keys.as_mut_ptr() as *mut K,
                     self.len()
                 )
             }
@@ -613,7 +671,7 @@ fn into_val_slice_mut(mut self) -> &'a mut [V] {
         debug_assert!(!self.is_shared_root());
         unsafe {
             slice::from_raw_parts_mut(
-                self.as_leaf_mut().vals.as_mut_ptr() as *mut V,
+                (*self.as_leaf_mut()).vals.as_mut_ptr() as *mut V,
                 self.len()
             )
         }
@@ -637,9 +695,9 @@ pub fn push(&mut self, key: K, val: V) {
         unsafe {
             ptr::write(self.keys_mut().get_unchecked_mut(idx), key);
             ptr::write(self.vals_mut().get_unchecked_mut(idx), val);
-        }
 
-        self.as_leaf_mut().len += 1;
+            (*self.as_leaf_mut()).len += 1;
+        }
     }
 
     /// Adds a key/value pair to the beginning of the node.
@@ -651,9 +709,9 @@ pub fn push_front(&mut self, key: K, val: V) {
         unsafe {
             slice_insert(self.keys_mut(), 0, key);
             slice_insert(self.vals_mut(), 0, val);
-        }
 
-        self.as_leaf_mut().len += 1;
+            (*self.as_leaf_mut()).len += 1;
+        }
     }
 }
 
@@ -672,7 +730,7 @@ pub fn push(&mut self, key: K, val: V, edge: Root<K, V>) {
             ptr::write(self.vals_mut().get_unchecked_mut(idx), val);
             ptr::write(self.as_internal_mut().edges.get_unchecked_mut(idx + 1), edge.node);
 
-            self.as_leaf_mut().len += 1;
+            (*self.as_leaf_mut()).len += 1;
 
             Handle::new_edge(self.reborrow_mut(), idx + 1).correct_parent_link();
         }
@@ -708,7 +766,7 @@ pub fn push_front(&mut self, key: K, val: V, edge: Root<K, V>) {
                 edge.node
             );
 
-            self.as_leaf_mut().len += 1;
+            (*self.as_leaf_mut()).len += 1;
 
             self.correct_all_childrens_parent_links();
         }
@@ -732,12 +790,12 @@ pub fn pop(&mut self) -> (K, V, Option<Root<K, V>>) {
                 ForceResult::Internal(internal) => {
                     let edge = ptr::read(internal.as_internal().edges.get_unchecked(idx + 1));
                     let mut new_root = Root { node: edge, height: internal.height - 1 };
-                    new_root.as_mut().as_leaf_mut().parent = ptr::null();
+                    (*new_root.as_mut().as_leaf_mut()).parent = ptr::null();
                     Some(new_root)
                 }
             };
 
-            self.as_leaf_mut().len -= 1;
+            (*self.as_leaf_mut()).len -= 1;
             (key, val, edge)
         }
     }
@@ -765,7 +823,7 @@ pub fn pop_front(&mut self) -> (K, V, Option<Root<K, V>>) {
                     );
 
                     let mut new_root = Root { node: edge, height: internal.height - 1 };
-                    new_root.as_mut().as_leaf_mut().parent = ptr::null();
+                    (*new_root.as_mut().as_leaf_mut()).parent = ptr::null();
 
                     for i in 0..old_len {
                         Handle::new_edge(internal.reborrow_mut(), i).correct_parent_link();
@@ -775,7 +833,7 @@ pub fn pop_front(&mut self) -> (K, V, Option<Root<K, V>>) {
                 }
             };
 
-            self.as_leaf_mut().len -= 1;
+            (*self.as_leaf_mut()).len -= 1;
 
             (key, val, edge)
         }
@@ -966,7 +1024,7 @@ fn insert_fit(&mut self, key: K, val: V) -> *mut V {
             slice_insert(self.node.keys_mut(), self.idx, key);
             slice_insert(self.node.vals_mut(), self.idx, val);
 
-            self.node.as_leaf_mut().len += 1;
+            (*self.node.as_leaf_mut()).len += 1;
 
             self.node.vals_mut().get_unchecked_mut(self.idx)
         }
@@ -1009,8 +1067,10 @@ fn correct_parent_link(mut self) {
         let idx = self.idx as u16;
         let ptr = self.node.as_internal_mut() as *mut _;
         let mut child = self.descend();
-        child.as_leaf_mut().parent = ptr;
-        child.as_leaf_mut().parent_idx.set(idx);
+        unsafe {
+            (*child.as_leaf_mut()).parent = ptr;
+            (*child.as_leaf_mut()).parent_idx.set(idx);
+        }
     }
 
     /// Unsafely asserts to the compiler some static information about whether the underlying
@@ -1158,7 +1218,7 @@ pub fn split(mut self)
                 new_len
             );
 
-            self.node.as_leaf_mut().len = self.idx as u16;
+            (*self.node.as_leaf_mut()).len = self.idx as u16;
             new_node.len = new_len as u16;
 
             (
@@ -1180,7 +1240,7 @@ pub fn remove(mut self)
         unsafe {
             let k = slice_remove(self.node.keys_mut(), self.idx);
             let v = slice_remove(self.node.vals_mut(), self.idx);
-            self.node.as_leaf_mut().len -= 1;
+            (*self.node.as_leaf_mut()).len -= 1;
             (self.left_edge(), k, v)
         }
     }
@@ -1221,7 +1281,7 @@ pub fn split(mut self)
                 new_len + 1
             );
 
-            self.node.as_leaf_mut().len = self.idx as u16;
+            (*self.node.as_leaf_mut()).len = self.idx as u16;
             new_node.data.len = new_len as u16;
 
             let mut new_root = Root {
@@ -1295,9 +1355,9 @@ pub fn merge(mut self)
             for i in self.idx+1..self.node.len() {
                 Handle::new_edge(self.node.reborrow_mut(), i).correct_parent_link();
             }
-            self.node.as_leaf_mut().len -= 1;
+            (*self.node.as_leaf_mut()).len -= 1;
 
-            left_node.as_leaf_mut().len += right_len as u16 + 1;
+            (*left_node.as_leaf_mut()).len += right_len as u16 + 1;
 
             if self.node.height > 1 {
                 ptr::copy_nonoverlapping(
@@ -1407,8 +1467,8 @@ pub fn bulk_steal_left(&mut self, count: usize) {
                 move_kv(left_kv, new_left_len, parent_kv, 0, 1);
             }
 
-            left_node.reborrow_mut().as_leaf_mut().len -= count as u16;
-            right_node.reborrow_mut().as_leaf_mut().len += count as u16;
+            (*left_node.reborrow_mut().as_leaf_mut()).len -= count as u16;
+            (*right_node.reborrow_mut().as_leaf_mut()).len += count as u16;
 
             match (left_node.force(), right_node.force()) {
                 (ForceResult::Internal(left), ForceResult::Internal(mut right)) => {
@@ -1468,8 +1528,8 @@ pub fn bulk_steal_right(&mut self, count: usize) {
                           new_right_len);
             }
 
-            left_node.reborrow_mut().as_leaf_mut().len += count as u16;
-            right_node.reborrow_mut().as_leaf_mut().len -= count as u16;
+            (*left_node.reborrow_mut().as_leaf_mut()).len += count as u16;
+            (*right_node.reborrow_mut().as_leaf_mut()).len -= count as u16;
 
             match (left_node.force(), right_node.force()) {
                 (ForceResult::Internal(left), ForceResult::Internal(mut right)) => {
@@ -1560,8 +1620,8 @@ pub fn move_suffix(&mut self,
 
             move_kv(left_kv, left_new_len, right_kv, 0, right_new_len);
 
-            left_node.reborrow_mut().as_leaf_mut().len = left_new_len as u16;
-            right_node.reborrow_mut().as_leaf_mut().len = right_new_len as u16;
+            (*left_node.reborrow_mut().as_leaf_mut()).len = left_new_len as u16;
+            (*right_node.reborrow_mut().as_leaf_mut()).len = right_new_len as u16;
 
             match (left_node.force(), right_node.force()) {
                 (ForceResult::Internal(left), ForceResult::Internal(right)) => {
index 2ef84dbade0fbc480f96529db85988407f45e241..ba46fafaf169f6d09bb46a700773dab490639811 100644 (file)
@@ -627,7 +627,9 @@ pub fn pop_front(&mut self) -> Option<T> {
         self.pop_front_node().map(Node::into_element)
     }
 
-    /// Appends an element to the back of a list
+    /// Appends an element to the back of a list.
+    ///
+    /// This operation should compute in O(1) time.
     ///
     /// # Examples
     ///
@@ -647,6 +649,8 @@ pub fn push_back(&mut self, elt: T) {
     /// Removes the last element from a list and returns it, or `None` if
     /// it is empty.
     ///
+    /// This operation should compute in O(1) time.
+    ///
     /// # Examples
     ///
     /// ```
index e329b45a6175d8641532e4d71d6c1e0a7f05cc3a..509195cd047d4846427df0efa53cc7ed9c29124e 100644 (file)
@@ -79,6 +79,11 @@ fn test_reserve() {
     assert!(v.capacity() >= 33)
 }
 
+#[test]
+fn test_zst_capacity() {
+    assert_eq!(Vec::<()>::new().capacity(), usize::max_value());
+}
+
 #[test]
 fn test_extend() {
     let mut v = Vec::new();
index 0c5256b981e5cc63d1cb9abc9d348b5b9f1c0162..8e0caa5ae330deb3f771b2055bae935b0aec9542 100644 (file)
@@ -609,10 +609,15 @@ pub trait Debug {
 /// println!("The origin is: {}", origin);
 /// ```
 #[rustc_on_unimplemented(
+    on(
+        _Self="std::path::Path",
+        label="`{Self}` cannot be formatted with the default formatter; call `.display()` on it",
+        note="call `.display()` or `.to_string_lossy()` to safely print paths, \
+              as they may contain non-Unicode data"
+    ),
     message="`{Self}` doesn't implement `{Display}`",
     label="`{Self}` cannot be formatted with the default formatter",
-    note="in format strings you may be able to use `{{:?}}` \
-          (or {{:#?}} for pretty-print) instead",
+    note="in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead",
 )]
 #[doc(alias = "{}")]
 #[stable(feature = "rust1", since = "1.0.0")]
index 0c870f9e404a26ca59147ea840bb30760bb16a67..5dee1d6dd3a39dcb66115401481d41e23eb7341c 100644 (file)
@@ -33,6 +33,7 @@
 ///
 /// When using a future, you generally won't call `poll` directly, but instead
 /// `await!` the value.
+#[must_use]
 pub trait Future {
     /// The result of the `Future`.
     type Output;
index 92a4aed4e27e586c2eced47623495fc93b40694e..c0b83a6868b383aab4b4df2a8529e234f54051ba 100644 (file)
@@ -98,6 +98,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item=()>) {}
     message="`{Self}` is not an iterator"
 )]
 #[doc(spotlight)]
+#[must_use]
 pub trait Iterator {
     /// The type of the elements being iterated over.
     #[stable(feature = "rust1", since = "1.0.0")]
index 7b273f7862a1f14f730437311ee1714ce1211ea7..aa23d49672a0bcbba08d441624bec26c78affbb6 100644 (file)
@@ -649,19 +649,6 @@ fn size_hint(&self) -> (usize, Option<usize>) {
             _ => (usize::MAX, None)
         }
     }
-
-    #[inline]
-    fn try_fold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R where
-        Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
-    {
-        let mut accum = init;
-        while let Some(x) = self.iter.next() {
-            accum = f(accum, x)?;
-            accum = self.iter.try_fold(accum, &mut f)?;
-            self.iter = self.orig.clone();
-        }
-        Try::from_ok(accum)
-    }
 }
 
 #[stable(feature = "fused", since = "1.26.0")]
index a51674fbfc71a8cb9754451764267ed6caa166c7..c8ad38c52dbe9128facf69f518bc0cd41086428c 100644 (file)
 #![feature(const_slice_len)]
 #![feature(const_str_as_bytes)]
 #![feature(const_str_len)]
-#![feature(const_let)]
 #![feature(const_int_rotate)]
 #![feature(const_int_wrapping)]
 #![feature(const_int_sign)]
index 4acf3a15ebf0dbf5de22104cd667ce00a73e0d26..f1df1f2856ed6b0566f2aa00fb999b4a3fb67a64 100644 (file)
@@ -70,7 +70,7 @@ impl $Ty {
                 #[stable(feature = "nonzero", since = "1.28.0")]
                 #[inline]
                 pub const unsafe fn new_unchecked(n: $Int) -> Self {
-                    $Ty(unsafe { NonZero(n) })
+                    $Ty(NonZero(n))
                 }
 
                 /// Create a non-zero if the given value is not zero.
@@ -2150,19 +2150,6 @@ impl isize {
          "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]" }
 }
 
-// Emits the correct `cttz` call, depending on the size of the type.
-macro_rules! uint_cttz_call {
-    // As of LLVM 3.6 the codegen for the zero-safe cttz8 intrinsic
-    // emits two conditional moves on x86_64. By promoting the value to
-    // u16 and setting bit 8, we get better code without any conditional
-    // operations.
-    // FIXME: There's a LLVM patch (http://reviews.llvm.org/D9284)
-    // pending, remove this workaround once LLVM generates better code
-    // for cttz8.
-    ($value:expr, 8) => { intrinsics::cttz($value as u16 | 0x100) };
-    ($value:expr, $_BITS:expr) => { intrinsics::cttz($value) }
-}
-
 // `Int` + `UnsignedInt` implemented for unsigned integers
 macro_rules! uint_impl {
     ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $Feature:expr, $EndFeature:expr,
@@ -2306,7 +2293,7 @@ pub const fn leading_zeros(self) -> u32 {
             #[rustc_const_unstable(feature = "const_int_ops")]
             #[inline]
             pub const fn trailing_zeros(self) -> u32 {
-                unsafe { uint_cttz_call!(self, $BITS) as u32 }
+                unsafe { intrinsics::cttz(self) as u32 }
             }
         }
 
index d1be724c3264e6c1a7430d94878bb8d1d55eee8b..3b356b9a1e7b4ee73206f66895da7c99ee7fc041 100644 (file)
@@ -72,6 +72,7 @@
     label="expected an `Fn<{Args}>` closure, found `{Self}`",
 )]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
+#[must_use]
 pub trait Fn<Args> : FnMut<Args> {
     /// Performs the call operation.
     #[unstable(feature = "fn_traits", issue = "29625")]
@@ -150,6 +151,7 @@ pub trait Fn<Args> : FnMut<Args> {
     label="expected an `FnMut<{Args}>` closure, found `{Self}`",
 )]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
+#[must_use]
 pub trait FnMut<Args> : FnOnce<Args> {
     /// Performs the call operation.
     #[unstable(feature = "fn_traits", issue = "29625")]
@@ -228,6 +230,7 @@ pub trait FnMut<Args> : FnOnce<Args> {
     label="expected an `FnOnce<{Args}>` closure, found `{Self}`",
 )]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
+#[must_use]
 pub trait FnOnce<Args> {
     /// The returned type after the call operator is used.
     #[stable(feature = "fn_once_output", since = "1.12.0")]
index 79ca600b4a57f0b2742d7202e2d3d3b224cce615..b3c93ae1fa7b24b5a25f862ccb38ec987e75f925 100644 (file)
@@ -2928,7 +2928,7 @@ impl<T: ?Sized> NonNull<T> {
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[inline]
     pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
-        NonNull { pointer: unsafe { NonZero(ptr as _) } }
+        NonNull { pointer: NonZero(ptr as _) }
     }
 
     /// Creates a new `NonNull` if `ptr` is non-null.
index 060983a702f0b79f2e1f2ef87e02442aa9ffc8f3..d2683e31eefb84fc04089034f8cf8d2fdb11a305 100644 (file)
@@ -1072,6 +1072,15 @@ pub fn compare_exchange_weak(&self,
 #[cfg(target_has_atomic = "8")]
 #[stable(feature = "atomic_bool_from", since = "1.24.0")]
 impl From<bool> for AtomicBool {
+    /// Converts a `bool` into an `AtomicBool`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::sync::atomic::AtomicBool;
+    /// let atomic_bool = AtomicBool::from(true);
+    /// assert_eq!(format!("{:?}", atomic_bool), "true")
+    /// ```
     #[inline]
     fn from(b: bool) -> Self { Self::new(b) }
 }
@@ -1126,8 +1135,12 @@ fn default() -> Self {
 
         #[$stable_from]
         impl From<$int_type> for $atomic_type {
-            #[inline]
-            fn from(v: $int_type) -> Self { Self::new(v) }
+            doc_comment! {
+                concat!(
+"Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`."),
+                #[inline]
+                fn from(v: $int_type) -> Self { Self::new(v) }
+            }
         }
 
         #[$stable_debug]
index 4efa01363146b314aa6ac50964a95605f73ae68e..00b4aa4fa2d7aa34c0cc6fb5a2e781326377e18c 100644 (file)
@@ -1003,6 +1003,8 @@ fn test_cycle() {
     assert_eq!(it.next(), None);
 
     assert_eq!(empty::<i32>().cycle().fold(0, |acc, x| acc + x), 0);
+
+    assert_eq!(once(1).cycle().skip(1).take(4).fold(0, |acc, x| acc + x), 4);
 }
 
 #[test]
index 8d2b1d74c554b0f62839a3056f9b04341c3a36ab..43bc9d88895d7e74af0c63c4f4432bd5d40a9972 100644 (file)
@@ -36,6 +36,7 @@
 use ty::fold::TypeFoldable;
 use ty::subst::{Kind, UnpackedKind};
 use ty::{self, BoundVar, Lift, Ty, TyCtxt};
+use util::captures::Captures;
 
 impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> {
     /// The "main method" for a canonicalized trait query. Given the
@@ -527,32 +528,30 @@ fn query_region_constraints_into_obligations<'a>(
         param_env: ty::ParamEnv<'tcx>,
         unsubstituted_region_constraints: &'a [QueryRegionConstraint<'tcx>],
         result_subst: &'a CanonicalVarValues<'tcx>,
-    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a {
-        Box::new(
-            unsubstituted_region_constraints
-                .iter()
-                .map(move |constraint| {
-                    let constraint = substitute_value(self.tcx, result_subst, constraint);
-                    let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
-
-                    Obligation::new(
-                        cause.clone(),
-                        param_env,
-                        match k1.unpack() {
-                            UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives(
-                                ty::Binder::bind(
-                                    ty::OutlivesPredicate(r1, r2)
-                                )
-                            ),
-                            UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives(
-                                ty::Binder::bind(
-                                    ty::OutlivesPredicate(t1, r2)
-                                )
-                            ),
-                        }
-                    )
-                })
-        ) as Box<dyn Iterator<Item = _>>
+    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'gcx> {
+        unsubstituted_region_constraints
+            .iter()
+            .map(move |constraint| {
+                let constraint = substitute_value(self.tcx, result_subst, constraint);
+                let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
+
+                Obligation::new(
+                    cause.clone(),
+                    param_env,
+                    match k1.unpack() {
+                        UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives(
+                            ty::Binder::bind(
+                                ty::OutlivesPredicate(r1, r2)
+                            )
+                        ),
+                        UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives(
+                            ty::Binder::bind(
+                                ty::OutlivesPredicate(t1, r2)
+                            )
+                        ),
+                    }
+                )
+            })
     }
 
     /// Given two sets of values for the same set of canonical variables, unify them.
index f124623becd93ddd06dd043ee8be273379710716..833da67d3f1750a89e1d73613a52b488d0bfc1dd 100644 (file)
@@ -347,6 +347,10 @@ fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> {
         self.infcx.tcx
     }
 
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        self.infcx.trait_object_mode()
+    }
+
     fn tag(&self) -> &'static str {
         "Generalizer"
     }
index 27faa4587f3be937c7a3eb5edf1a9c08f78f08b2..caa120fa267023b9c6f64f61b372dfec88a6c9b1 100644 (file)
@@ -39,6 +39,10 @@ fn tag(&self) -> &'static str { "Equate" }
 
     fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
 
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        self.fields.infcx.trait_object_mode()
+    }
+
     fn a_is_expected(&self) -> bool { self.a_is_expected }
 
     fn relate_item_substs(&mut self,
index 8968c5949b617b8ccb8c525e547d78e6826c5b7c..ba21ebb49eb95a99db0d40b17e0301c5722c2c49 100644 (file)
@@ -15,7 +15,7 @@
 
 use traits::ObligationCause;
 use ty::{self, Ty, TyCtxt};
-use ty::relate::{Relate, RelateResult, TypeRelation};
+use ty::relate::{self, Relate, RelateResult, TypeRelation};
 
 /// "Greatest lower bound" (common subtype)
 pub struct Glb<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
@@ -36,6 +36,10 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
 {
     fn tag(&self) -> &'static str { "Glb" }
 
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        self.fields.infcx.trait_object_mode()
+    }
+
     fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
 
     fn a_is_expected(&self) -> bool { self.a_is_expected }
index 8875b4169dd6e796028916f558fc9ae009e3858d..80fad447b46e30e75dd506ad3499d84cc3d3bb2b 100644 (file)
@@ -15,7 +15,7 @@
 
 use traits::ObligationCause;
 use ty::{self, Ty, TyCtxt};
-use ty::relate::{Relate, RelateResult, TypeRelation};
+use ty::relate::{self, Relate, RelateResult, TypeRelation};
 
 /// "Least upper bound" (common supertype)
 pub struct Lub<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
@@ -36,6 +36,10 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
 {
     fn tag(&self) -> &'static str { "Lub" }
 
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        self.fields.infcx.trait_object_mode()
+    }
+
     fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
 
     fn a_is_expected(&self) -> bool { self.a_is_expected }
index b1a13354b7cdbd275ce869bbaf46834a9c5449a8..c961fd5fbd4b1b608797fd555ac40ce188f76738 100644 (file)
@@ -35,7 +35,7 @@
 use traits::{self, ObligationCause, PredicateObligations, TraitEngine};
 use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
 use ty::fold::TypeFoldable;
-use ty::relate::RelateResult;
+use ty::relate::{RelateResult, TraitObjectMode};
 use ty::subst::{Kind, Substs};
 use ty::{self, GenericParamDefKind, Ty, TyCtxt};
 use ty::{FloatVid, IntVid, TyVid};
@@ -182,6 +182,9 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     // This flag is true while there is an active snapshot.
     in_snapshot: Cell<bool>,
 
+    // The TraitObjectMode used here,
+    trait_object_mode: TraitObjectMode,
+
     // A set of constraints that regionck must validate. Each
     // constraint has the form `T:'a`, meaning "some type `T` must
     // outlive the lifetime 'a". These constraints derive from
@@ -472,6 +475,7 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     global_tcx: TyCtxt<'a, 'gcx, 'gcx>,
     arena: SyncDroplessArena,
     fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
+    trait_object_mode: TraitObjectMode,
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
@@ -480,6 +484,7 @@ pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
             global_tcx: self,
             arena: SyncDroplessArena::default(),
             fresh_tables: None,
+            trait_object_mode: TraitObjectMode::NoSquash,
         }
     }
 }
@@ -492,6 +497,12 @@ pub fn with_fresh_in_progress_tables(mut self, table_owner: DefId) -> Self {
         self
     }
 
+    pub fn with_trait_object_mode(mut self, mode: TraitObjectMode) -> Self {
+        debug!("with_trait_object_mode: setting mode to {:?}", mode);
+        self.trait_object_mode = mode;
+        self
+    }
+
     /// Given a canonical value `C` as a starting point, create an
     /// inference context that contains each of the bound values
     /// within instantiated as a fresh variable. The `f` closure is
@@ -518,6 +529,7 @@ pub fn enter_with_canonical<T, R>(
     pub fn enter<R>(&'tcx mut self, f: impl for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R) -> R {
         let InferCtxtBuilder {
             global_tcx,
+            trait_object_mode,
             ref arena,
             ref fresh_tables,
         } = *self;
@@ -526,6 +538,7 @@ pub fn enter<R>(&'tcx mut self, f: impl for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>
             f(InferCtxt {
                 tcx,
                 in_progress_tables,
+                trait_object_mode,
                 projection_cache: Default::default(),
                 type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
                 int_unification_table: RefCell::new(ut::UnificationTable::new()),
@@ -607,6 +620,10 @@ pub fn is_in_snapshot(&self) -> bool {
         self.in_snapshot.get()
     }
 
+    pub fn trait_object_mode(&self) -> TraitObjectMode {
+        self.trait_object_mode
+    }
+
     pub fn freshen<T: TypeFoldable<'tcx>>(&self, t: T) -> T {
         t.fold_with(&mut self.freshener())
     }
index 773c7129722cf7f4784a535fa05dac0c00649b27..0ce0eb9a1abae169804d5c249a8e91888e3bd40e 100644 (file)
@@ -382,6 +382,13 @@ fn tcx(&self) -> TyCtxt<'me, 'gcx, 'tcx> {
         self.infcx.tcx
     }
 
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        // squashing should only be done in coherence, not NLL
+        assert_eq!(self.infcx.trait_object_mode(),
+                   relate::TraitObjectMode::NoSquash);
+        relate::TraitObjectMode::NoSquash
+    }
+
     fn tag(&self) -> &'static str {
         "nll::subtype"
     }
@@ -696,6 +703,13 @@ fn tcx(&self) -> TyCtxt<'me, 'gcx, 'tcx> {
         self.infcx.tcx
     }
 
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        // squashing should only be done in coherence, not NLL
+        assert_eq!(self.infcx.trait_object_mode(),
+                   relate::TraitObjectMode::NoSquash);
+        relate::TraitObjectMode::NoSquash
+    }
+
     fn tag(&self) -> &'static str {
         "nll::generalizer"
     }
index 3b0f9a5e545fde48e157985c952b8b510f9cb83a..ef2ef3f8a86014ca847f2a6f9f403d7dfc8b8890 100644 (file)
@@ -15,7 +15,7 @@
 use ty::{self, Ty, TyCtxt};
 use ty::TyVar;
 use ty::fold::TypeFoldable;
-use ty::relate::{Cause, Relate, RelateResult, TypeRelation};
+use ty::relate::{self, Cause, Relate, RelateResult, TypeRelation};
 use std::mem;
 
 /// Ensures `a` is made a subtype of `b`. Returns `a` on success.
@@ -43,6 +43,10 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
     for Sub<'combine, 'infcx, 'gcx, 'tcx>
 {
     fn tag(&self) -> &'static str { "Sub" }
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        self.fields.infcx.trait_object_mode()
+    }
+
     fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.infcx.tcx }
     fn a_is_expected(&self) -> bool { self.a_is_expected }
 
index b7759a8c92b07ef64a461f0c7f3bf590e9c8c400..cf437109e6767ab4ebd06440a6a0df53b04f6f67 100644 (file)
     "potentially-conflicting impls were erroneously allowed"
 }
 
+declare_lint! {
+    pub ORDER_DEPENDENT_TRAIT_OBJECTS,
+    Deny,
+    "trait-object types were treated as different depending on marker-trait order"
+}
+
 declare_lint! {
     pub BAD_REPR,
     Warn,
@@ -365,6 +371,13 @@ pub mod parser {
     }
 }
 
+declare_lint! {
+    pub DEPRECATED_IN_FUTURE,
+    Allow,
+    "detects use of items that will be deprecated in a future version",
+    report_in_external_macro: true
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// that are used by other parts of the compiler.
 #[derive(Copy, Clone)]
@@ -405,6 +418,7 @@ fn get_lints(&self) -> LintArray {
             PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
             LATE_BOUND_LIFETIME_ARGUMENTS,
             INCOHERENT_FUNDAMENTAL_IMPLS,
+            ORDER_DEPENDENT_TRAIT_OBJECTS,
             DEPRECATED,
             UNUSED_UNSAFE,
             UNUSED_MUT,
@@ -427,6 +441,7 @@ fn get_lints(&self) -> LintArray {
             MACRO_USE_EXTERN_CRATE,
             MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
             parser::QUESTION_MARK_MACRO_SEP,
+            DEPRECATED_IN_FUTURE,
         )
     }
 }
index e576951417f93b27026c2dbe17169871dedf5e81..31a75bd106e2cb36c6a9b13deabcb7c6a4375ab7 100644 (file)
@@ -1657,11 +1657,15 @@ fn warn_about_dead_assign(&self,
     fn report_dead_assign(&self, hir_id: HirId, sp: Span, var: Variable, is_argument: bool) {
         if let Some(name) = self.should_warn(var) {
             if is_argument {
-                self.ir.tcx.lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
-                    &format!("value passed to `{}` is never read", name));
+                self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
+                &format!("value passed to `{}` is never read", name))
+                .help("maybe it is overwritten before being read?")
+                .emit();
             } else {
-                self.ir.tcx.lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
-                    &format!("value assigned to `{}` is never read", name));
+                self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
+                &format!("value assigned to `{}` is never read", name))
+                .help("maybe it is overwritten before being read?")
+                .emit();
             }
         }
     }
index ab379c910f7764b645e45803c875497b2a99c2d4..61341cbc30ce45ca3ef5f17c4676bf67dd482d70 100644 (file)
@@ -13,7 +13,7 @@
 
 pub use self::StabilityLevel::*;
 
-use lint;
+use lint::{self, Lint};
 use hir::{self, Item, Generics, StructField, Variant, HirId};
 use hir::def::Def;
 use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
@@ -562,18 +562,20 @@ pub fn eval_stability(self, def_id: DefId, id: Option<NodeId>, span: Span) -> Ev
             return EvalResult::Allow;
         }
 
-        let lint_deprecated = |def_id: DefId, id: NodeId, note: Option<Symbol>| {
-            let path = self.item_path_str(def_id);
-
+        let lint_deprecated = |def_id: DefId,
+                               id: NodeId,
+                               note: Option<Symbol>,
+                               message: &str,
+                               lint: &'static Lint| {
             let msg = if let Some(note) = note {
-                format!("use of deprecated item '{}': {}", path, note)
+                format!("{}: {}", message, note)
             } else {
-                format!("use of deprecated item '{}'", path)
+                format!("{}", message)
             };
 
-            self.lint_node(lint::builtin::DEPRECATED, id, span, &msg);
+            self.lint_node(lint, id, span, &msg);
             if id == ast::DUMMY_NODE_ID {
-                span_bug!(span, "emitted a deprecated lint with dummy node id: {:?}", def_id);
+                span_bug!(span, "emitted a {} lint with dummy node id: {:?}", lint.name, def_id);
             }
         };
 
@@ -584,17 +586,39 @@ pub fn eval_stability(self, def_id: DefId, id: Option<NodeId>, span: Span) -> Ev
                 // version, then we should display no warning message.
                 let deprecated_in_future_version = if let Some(sym) = depr_entry.attr.since {
                     let since = sym.as_str();
-                    !deprecation_in_effect(&since)
+                    if !deprecation_in_effect(&since) {
+                        Some(since)
+                    } else {
+                        None
+                    }
                 } else {
-                    false
+                    None
                 };
 
                 let parent_def_id = self.hir().local_def_id(self.hir().get_parent(id));
-                let skip = deprecated_in_future_version ||
-                           self.lookup_deprecation_entry(parent_def_id)
+                let skip = self.lookup_deprecation_entry(parent_def_id)
                                .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry));
-                if !skip {
-                    lint_deprecated(def_id, id, depr_entry.attr.note);
+
+                if let Some(since) = deprecated_in_future_version {
+                    let path = self.item_path_str(def_id);
+                    let message = format!("use of item '{}' \
+                                           that will be deprecated in future version {}",
+                                          path,
+                                          since);
+
+                    lint_deprecated(def_id,
+                                    id,
+                                    depr_entry.attr.note,
+                                    &message,
+                                    lint::builtin::DEPRECATED_IN_FUTURE);
+                } else if !skip {
+                    let path = self.item_path_str(def_id);
+                    let message = format!("use of deprecated item '{}'", path);
+                    lint_deprecated(def_id,
+                                    id,
+                                    depr_entry.attr.note,
+                                    &message,
+                                    lint::builtin::DEPRECATED);
                 }
             };
         }
@@ -614,8 +638,24 @@ pub fn eval_stability(self, def_id: DefId, id: Option<NodeId>, span: Span) -> Ev
         if let Some(&Stability{rustc_depr: Some(attr::RustcDeprecation { reason, since }), ..})
                 = stability {
             if let Some(id) = id {
+                let path = self.item_path_str(def_id);
                 if deprecation_in_effect(&since.as_str()) {
-                    lint_deprecated(def_id, id, Some(reason));
+                    let message = format!("use of deprecated item '{}'", path);
+                    lint_deprecated(def_id,
+                                    id,
+                                    Some(reason),
+                                    &message,
+                                    lint::builtin::DEPRECATED);
+                } else {
+                    let message = format!("use of item '{}' \
+                                           that will be deprecated in future version {}",
+                                          path,
+                                          since);
+                    lint_deprecated(def_id,
+                                    id,
+                                    Some(reason),
+                                    &message,
+                                    lint::builtin::DEPRECATED_IN_FUTURE);
                 }
             }
         }
index 68b5c3e2df3224b108145fe1d166e9ca7b4fb6d0..9dff3277917be14134be79dcf017feba80e3dfa4 100644 (file)
@@ -149,6 +149,14 @@ pub struct Mir<'tcx> {
     /// This is used for the "rust-call" ABI.
     pub spread_arg: Option<Local>,
 
+    /// Mark this MIR of a const context other than const functions as having converted a `&&` or
+    /// `||` expression into `&` or `|` respectively. This is problematic because if we ever stop
+    /// this conversion from happening and use short circuiting, we will cause the following code
+    /// to change the value of `x`: `let mut x = 42; false && { x = 55; true };`
+    ///
+    /// List of places where control flow was destroyed. Used for error reporting.
+    pub control_flow_destroyed: Vec<(Span, String)>,
+
     /// A span representing this MIR, for error reporting
     pub span: Span,
 
@@ -167,6 +175,7 @@ pub fn new(
         arg_count: usize,
         upvar_decls: Vec<UpvarDecl>,
         span: Span,
+        control_flow_destroyed: Vec<(Span, String)>,
     ) -> Self {
         // We need `arg_count` locals, and one for the return place
         assert!(
@@ -191,6 +200,7 @@ pub fn new(
             spread_arg: None,
             span,
             cache: cache::Cache::new(),
+            control_flow_destroyed,
         }
     }
 
@@ -421,6 +431,7 @@ pub enum Safety {
     arg_count,
     upvar_decls,
     spread_arg,
+    control_flow_destroyed,
     span,
     cache
 });
@@ -1748,6 +1759,9 @@ pub enum StatementKind<'tcx> {
     /// (e.g., inspecting constants and discriminant values), and the
     /// kind of pattern it comes from. This is in order to adapt potential
     /// error messages to these specific patterns.
+    ///
+    /// Note that this also is emitted for regular `let` bindings to ensure that locals that are
+    /// never accessed still get some sanity checks for e.g. `let x: ! = ..;`
     FakeRead(FakeReadCause, Place<'tcx>),
 
     /// Write the discriminant for a variant to the enum Place.
@@ -2984,6 +2998,7 @@ impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> {
         arg_count,
         upvar_decls,
         spread_arg,
+        control_flow_destroyed,
         span,
         cache,
     }
index f10f523e2b4872e696979c06b16387bd51fb956d..af338cd3868fad5ada046912163c41c47d697c3d 100644 (file)
@@ -20,6 +20,7 @@
 use traits::IntercrateMode;
 use traits::select::IntercrateAmbiguityCause;
 use ty::{self, Ty, TyCtxt};
+use ty::relate::TraitObjectMode;
 use ty::fold::TypeFoldable;
 use ty::subst::Subst;
 
@@ -52,6 +53,7 @@ pub fn overlapping_impls<'gcx, F1, F2, R>(
     impl1_def_id: DefId,
     impl2_def_id: DefId,
     intercrate_mode: IntercrateMode,
+    trait_object_mode: TraitObjectMode,
     on_overlap: F1,
     no_overlap: F2,
 ) -> R
@@ -62,12 +64,14 @@ pub fn overlapping_impls<'gcx, F1, F2, R>(
     debug!("overlapping_impls(\
            impl1_def_id={:?}, \
            impl2_def_id={:?},
-           intercrate_mode={:?})",
+           intercrate_mode={:?},
+           trait_object_mode={:?})",
            impl1_def_id,
            impl2_def_id,
-           intercrate_mode);
+           intercrate_mode,
+           trait_object_mode);
 
-    let overlaps = tcx.infer_ctxt().enter(|infcx| {
+    let overlaps = tcx.infer_ctxt().with_trait_object_mode(trait_object_mode).enter(|infcx| {
         let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode);
         overlap(selcx, impl1_def_id, impl2_def_id).is_some()
     });
@@ -79,7 +83,7 @@ pub fn overlapping_impls<'gcx, F1, F2, R>(
     // In the case where we detect an error, run the check again, but
     // this time tracking intercrate ambuiguity causes for better
     // diagnostics. (These take time and can lead to false errors.)
-    tcx.infer_ctxt().enter(|infcx| {
+    tcx.infer_ctxt().with_trait_object_mode(trait_object_mode).enter(|infcx| {
         let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode);
         selcx.enable_tracking_intercrate_ambiguity_causes();
         on_overlap(overlap(selcx, impl1_def_id, impl2_def_id).unwrap())
index 4ef4f4571055582ee51dbf2febb2118dff07f1d8..373d6652b9e6abc7935770252e15497669714acb 100644 (file)
@@ -459,7 +459,7 @@ fn find_similar_impl_candidates(&self,
     {
         let simp = fast_reject::simplify_type(self.tcx,
                                               trait_ref.skip_binder().self_ty(),
-                                              true);
+                                              true,);
         let all_impls = self.tcx.all_impls(trait_ref.def_id());
 
         match simp {
index 8d91132a6db93cedf0a0d9da260eb549fd956f23..cf37c3fceba8f2b8a3bb8fb50ef95dcb5591afcc 100644 (file)
@@ -64,6 +64,8 @@
 pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
 pub use self::specialize::{OverlapError, specialization_graph, translate_substs};
 pub use self::specialize::find_associated_item;
+pub use self::specialize::specialization_graph::FutureCompatOverlapError;
+pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
 pub use self::engine::{TraitEngine, TraitEngineExt};
 pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
 pub use self::util::{supertraits, supertrait_def_ids, transitive_bounds,
index c438542106c9e3150777441db11e77c66f19b8ef..d46389b0ee226139a50b61ce82383e3bc2e5dc78 100644 (file)
@@ -44,7 +44,7 @@
 use middle::lang_items;
 use mir::interpret::GlobalId;
 use ty::fast_reject;
-use ty::relate::TypeRelation;
+use ty::relate::{TypeRelation, TraitObjectMode};
 use ty::subst::{Subst, Substs};
 use ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
 
@@ -1501,6 +1501,13 @@ fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool {
             return false;
         }
 
+        // Same idea as the above, but for alt trait object modes. These
+        // should only be used in intercrate mode - better safe than sorry.
+        if self.infcx.trait_object_mode() != TraitObjectMode::NoSquash {
+            bug!("using squashing TraitObjectMode outside of intercrate mode? param_env={:?}",
+                 param_env);
+        }
+
         // Otherwise, we can use the global cache.
         true
     }
@@ -3699,7 +3706,8 @@ fn match_fresh_trait_refs(
         previous: &ty::PolyTraitRef<'tcx>,
         current: &ty::PolyTraitRef<'tcx>,
     ) -> bool {
-        let mut matcher = ty::_match::Match::new(self.tcx());
+        let mut matcher = ty::_match::Match::new(
+            self.tcx(), self.infcx.trait_object_mode());
         matcher.relate(previous, current).is_ok()
     }
 
index 96bb545f25c643442fb27fde267007515265ea8a..70d36e9afe192d76e93afbfd04a20e1755f72cba 100644 (file)
 use hir::def_id::DefId;
 use infer::{InferCtxt, InferOk};
 use lint;
+use traits::{self, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use syntax_pos::DUMMY_SP;
-use traits::{self, ObligationCause, TraitEngine};
 use traits::select::IntercrateAmbiguityCause;
 use ty::{self, TyCtxt, TypeFoldable};
 use ty::subst::{Subst, Substs};
@@ -36,6 +36,7 @@
 use super::util::impl_trait_ref_and_oblig;
 
 /// Information pertinent to an overlapping impl error.
+#[derive(Debug)]
 pub struct OverlapError {
     pub with_impl: DefId,
     pub trait_desc: String,
@@ -318,8 +319,9 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(
             let insert_result = sg.insert(tcx, impl_def_id);
             // Report error if there was one.
             let (overlap, used_to_be_allowed) = match insert_result {
-                Err(overlap) => (Some(overlap), false),
-                Ok(opt_overlap) => (opt_overlap, true)
+                Err(overlap) => (Some(overlap), None),
+                Ok(Some(overlap)) => (Some(overlap.error), Some(overlap.kind)),
+                Ok(None) => (None, None)
             };
 
             if let Some(overlap) = overlap {
@@ -329,14 +331,20 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(
                         String::new(), |ty| {
                             format!(" for type `{}`", ty)
                         }),
-                    if used_to_be_allowed { " (E0119)" } else { "" }
+                    if used_to_be_allowed.is_some() { " (E0119)" } else { "" }
                 );
                 let impl_span = tcx.sess.source_map().def_span(
                     tcx.span_of_impl(impl_def_id).unwrap()
                 );
-                let mut err = if used_to_be_allowed {
+                let mut err = if let Some(kind) = used_to_be_allowed {
+                    let lint = match kind {
+                        FutureCompatOverlapErrorKind::Issue43355 =>
+                            lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
+                        FutureCompatOverlapErrorKind::Issue33140 =>
+                            lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS,
+                    };
                     tcx.struct_span_lint_node(
-                        lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
+                        lint,
                         tcx.hir().as_local_node_id(impl_def_id).unwrap(),
                         impl_span,
                         &msg)
index b0ca2f6cecc0b9d8355e3f2d28f843c1753c61ca..1a228660306418a5aaf10f9d65c5b4d27e576d7d 100644 (file)
@@ -17,6 +17,7 @@
 use traits;
 use ty::{self, TyCtxt, TypeFoldable};
 use ty::fast_reject::{self, SimplifiedType};
+use ty::relate::TraitObjectMode;
 use rustc_data_structures::sync::Lrc;
 use syntax::ast::Ident;
 use util::captures::Captures;
@@ -68,10 +69,22 @@ struct Children {
     blanket_impls: Vec<DefId>,
 }
 
+#[derive(Copy, Clone, Debug)]
+pub enum FutureCompatOverlapErrorKind {
+    Issue43355,
+    Issue33140,
+}
+
+#[derive(Debug)]
+pub struct FutureCompatOverlapError {
+    pub error: OverlapError,
+    pub kind: FutureCompatOverlapErrorKind
+}
+
 /// The result of attempting to insert an impl into a group of children.
 enum Inserted {
     /// The impl was inserted as a new child in this group of children.
-    BecameNewSibling(Option<OverlapError>),
+    BecameNewSibling(Option<FutureCompatOverlapError>),
 
     /// The impl should replace existing impls [X1, ..], because the impl specializes X1, X2, etc.
     ReplaceChildren(Vec<DefId>),
@@ -170,6 +183,7 @@ fn insert(&mut self,
                 possible_sibling,
                 impl_def_id,
                 traits::IntercrateMode::Issue43355,
+                TraitObjectMode::NoSquash,
                 |overlap| {
                     if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
                         return Ok((false, false));
@@ -200,12 +214,36 @@ fn insert(&mut self,
                 replace_children.push(possible_sibling);
             } else {
                 if !tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
+                    // do future-compat checks for overlap. Have issue #43355
+                    // errors overwrite issue #33140 errors when both are present.
+
+                    traits::overlapping_impls(
+                        tcx,
+                        possible_sibling,
+                        impl_def_id,
+                        traits::IntercrateMode::Fixed,
+                        TraitObjectMode::SquashAutoTraitsIssue33140,
+                        |overlap| {
+                            last_lint = Some(FutureCompatOverlapError {
+                                error: overlap_error(overlap),
+                                kind: FutureCompatOverlapErrorKind::Issue33140
+                            });
+                        },
+                        || (),
+                    );
+
                     traits::overlapping_impls(
                         tcx,
                         possible_sibling,
                         impl_def_id,
                         traits::IntercrateMode::Fixed,
-                        |overlap| last_lint = Some(overlap_error(overlap)),
+                        TraitObjectMode::NoSquash,
+                        |overlap| {
+                            last_lint = Some(FutureCompatOverlapError {
+                                error: overlap_error(overlap),
+                                kind: FutureCompatOverlapErrorKind::Issue43355
+                            });
+                        },
                         || (),
                     );
                 }
@@ -272,7 +310,7 @@ pub fn new() -> Graph {
     pub fn insert(&mut self,
                   tcx: TyCtxt<'a, 'gcx, 'tcx>,
                   impl_def_id: DefId)
-                  -> Result<Option<OverlapError>, OverlapError> {
+                  -> Result<Option<FutureCompatOverlapError>, OverlapError> {
         assert!(impl_def_id.is_local());
 
         let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
index d20b6d361991b6804630e997bc0cb5c2d3efe72c..29067bf518da02201de197b28921af2fbaf4a4eb 100644 (file)
 /// important thing about the result is Ok/Err. Also, matching never
 /// affects any type variables or unification state.
 pub struct Match<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'gcx, 'tcx>
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    trait_object_mode: relate::TraitObjectMode
 }
 
 impl<'a, 'gcx, 'tcx> Match<'a, 'gcx, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Match<'a, 'gcx, 'tcx> {
-        Match { tcx }
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+               trait_object_mode: relate::TraitObjectMode)
+               -> Match<'a, 'gcx, 'tcx> {
+        Match { tcx, trait_object_mode }
     }
 }
 
 impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Match<'a, 'gcx, 'tcx> {
     fn tag(&self) -> &'static str { "Match" }
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        self.trait_object_mode
+    }
+
     fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.tcx }
     fn a_is_expected(&self) -> bool { true } // irrelevant
 
index 7005e14c26c4245f242e91e9f2fe01a729c830d8..bd01dd8cb0ce64ecd3628dcdeab6dcd72ffe1cdd 100644 (file)
@@ -43,6 +43,9 @@ pub enum SimplifiedTypeGen<D>
     PtrSimplifiedType,
     NeverSimplifiedType,
     TupleSimplifiedType(usize),
+    /// A trait object, all of whose components are markers
+    /// (e.g., `dyn Send + Sync`).
+    MarkerTraitObjectSimplifiedType,
     TraitSimplifiedType(D),
     ClosureSimplifiedType(D),
     GeneratorSimplifiedType(D),
@@ -78,7 +81,12 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType),
         ty::RawPtr(_) => Some(PtrSimplifiedType),
         ty::Dynamic(ref trait_info, ..) => {
-            Some(TraitSimplifiedType(trait_info.principal().def_id()))
+            let principal_def_id = trait_info.principal().def_id();
+            if tcx.trait_is_auto(principal_def_id) {
+                Some(MarkerTraitObjectSimplifiedType)
+            } else {
+                Some(TraitSimplifiedType(principal_def_id))
+            }
         }
         ty::Ref(_, ty, _) => {
             // since we introduce auto-refs during method lookup, we
@@ -144,6 +152,7 @@ pub fn map_def<U, F>(self, map: F) -> SimplifiedTypeGen<U>
             NeverSimplifiedType => NeverSimplifiedType,
             TupleSimplifiedType(n) => TupleSimplifiedType(n),
             TraitSimplifiedType(d) => TraitSimplifiedType(map(d)),
+            MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType,
             ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
             GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
             GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
@@ -170,7 +179,8 @@ fn hash_stable<W: StableHasherResult>(&self,
             ArraySimplifiedType |
             PtrSimplifiedType |
             NeverSimplifiedType |
-            ParameterSimplifiedType => {
+            ParameterSimplifiedType |
+            MarkerTraitObjectSimplifiedType => {
                 // nothing to do
             }
             IntSimplifiedType(t) => t.hash_stable(hcx, hasher),
index a1fc949137ddef79016c88f53ad6fe337cd5a4a6..429b7f03af8e40a058d9b7674fe4c10da06a9dd8 100644 (file)
@@ -1754,17 +1754,19 @@ pub struct Destructor {
     pub struct AdtFlags: u32 {
         const NO_ADT_FLAGS        = 0;
         const IS_ENUM             = 1 << 0;
-        const IS_PHANTOM_DATA     = 1 << 1;
-        const IS_FUNDAMENTAL      = 1 << 2;
-        const IS_UNION            = 1 << 3;
-        const IS_BOX              = 1 << 4;
+        const IS_UNION            = 1 << 1;
+        const IS_STRUCT           = 1 << 2;
+        const HAS_CTOR            = 1 << 3;
+        const IS_PHANTOM_DATA     = 1 << 4;
+        const IS_FUNDAMENTAL      = 1 << 5;
+        const IS_BOX              = 1 << 6;
         /// Indicates whether the type is an `Arc`.
-        const IS_ARC              = 1 << 5;
+        const IS_ARC              = 1 << 7;
         /// Indicates whether the type is an `Rc`.
-        const IS_RC               = 1 << 6;
+        const IS_RC               = 1 << 8;
         /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
         /// (i.e., this flag is never set unless this ADT is an enum).
-        const IS_VARIANT_LIST_NON_EXHAUSTIVE   = 1 << 7;
+        const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 9;
     }
 }
 
@@ -2079,31 +2081,43 @@ fn new(tcx: TyCtxt<'_, '_, '_>,
            repr: ReprOptions) -> Self {
         debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
         let mut flags = AdtFlags::NO_ADT_FLAGS;
+
+        if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
+            debug!("found non-exhaustive variant list for {:?}", did);
+            flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
+        }
+        flags |= match kind {
+            AdtKind::Enum => AdtFlags::IS_ENUM,
+            AdtKind::Union => AdtFlags::IS_UNION,
+            AdtKind::Struct => AdtFlags::IS_STRUCT,
+        };
+
+        if let AdtKind::Struct = kind {
+            let variant_def = &variants[VariantIdx::new(0)];
+            let def_key = tcx.def_key(variant_def.did);
+            match def_key.disambiguated_data.data {
+                DefPathData::StructCtor => flags |= AdtFlags::HAS_CTOR,
+                _ => (),
+            }
+        }
+
         let attrs = tcx.get_attrs(did);
         if attr::contains_name(&attrs, "fundamental") {
-            flags = flags | AdtFlags::IS_FUNDAMENTAL;
+            flags |= AdtFlags::IS_FUNDAMENTAL;
         }
         if Some(did) == tcx.lang_items().phantom_data() {
-            flags = flags | AdtFlags::IS_PHANTOM_DATA;
+            flags |= AdtFlags::IS_PHANTOM_DATA;
         }
         if Some(did) == tcx.lang_items().owned_box() {
-            flags = flags | AdtFlags::IS_BOX;
+            flags |= AdtFlags::IS_BOX;
         }
         if Some(did) == tcx.lang_items().arc() {
-            flags = flags | AdtFlags::IS_ARC;
+            flags |= AdtFlags::IS_ARC;
         }
         if Some(did) == tcx.lang_items().rc() {
-            flags = flags | AdtFlags::IS_RC;
-        }
-        if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
-            debug!("found non-exhaustive variant list for {:?}", did);
-            flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
-        }
-        match kind {
-            AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
-            AdtKind::Union => flags = flags | AdtFlags::IS_UNION,
-            AdtKind::Struct => {}
+            flags |= AdtFlags::IS_RC;
         }
+
         AdtDef {
             did,
             variants,
@@ -2114,25 +2128,25 @@ fn new(tcx: TyCtxt<'_, '_, '_>,
 
     #[inline]
     pub fn is_struct(&self) -> bool {
-        !self.is_union() && !self.is_enum()
+        self.flags.contains(AdtFlags::IS_STRUCT)
     }
 
     #[inline]
     pub fn is_union(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_UNION)
+        self.flags.contains(AdtFlags::IS_UNION)
     }
 
     #[inline]
     pub fn is_enum(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_ENUM)
+        self.flags.contains(AdtFlags::IS_ENUM)
     }
 
     #[inline]
     pub fn is_variant_list_non_exhaustive(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
+        self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
     }
 
-    /// Returns the kind of the ADT - Struct or Enum.
+    /// Returns the kind of the ADT.
     #[inline]
     pub fn adt_kind(&self) -> AdtKind {
         if self.is_enum() {
@@ -2161,33 +2175,39 @@ pub fn variant_descr(&self) -> &'static str {
         }
     }
 
-    /// Returns whether this type is #[fundamental] for the purposes
+    /// If this function returns `true`, it implies that `is_struct` must return `true`.
+    #[inline]
+    pub fn has_ctor(&self) -> bool {
+        self.flags.contains(AdtFlags::HAS_CTOR)
+    }
+
+    /// Returns whether this type is `#[fundamental]` for the purposes
     /// of coherence checking.
     #[inline]
     pub fn is_fundamental(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_FUNDAMENTAL)
+        self.flags.contains(AdtFlags::IS_FUNDAMENTAL)
     }
 
     /// Returns `true` if this is PhantomData<T>.
     #[inline]
     pub fn is_phantom_data(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_PHANTOM_DATA)
+        self.flags.contains(AdtFlags::IS_PHANTOM_DATA)
     }
 
     /// Returns `true` if this is `Arc<T>`.
     pub fn is_arc(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_ARC)
+        self.flags.contains(AdtFlags::IS_ARC)
     }
 
     /// Returns `true` if this is `Rc<T>`.
     pub fn is_rc(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_RC)
+        self.flags.contains(AdtFlags::IS_RC)
     }
 
     /// Returns `true` if this is Box<T>.
     #[inline]
     pub fn is_box(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_BOX)
+        self.flags.contains(AdtFlags::IS_BOX)
     }
 
     /// Returns whether this type has a destructor.
index 7ad4fd58273ee679f0554678f4a0b880cfbd6892..88c3e5c8715668fd5423de2ae386418ffcc471b3 100644 (file)
@@ -35,9 +35,20 @@ pub enum Cause {
     ExistentialRegionBound, // relating an existential region bound
 }
 
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum TraitObjectMode {
+    NoSquash,
+    /// A temporary mode to treat `Send + Sync = Sync + Send`, should be
+    /// used only in coherence.
+    SquashAutoTraitsIssue33140
+}
+
 pub trait TypeRelation<'a, 'gcx: 'a+'tcx, 'tcx: 'a> : Sized {
     fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx>;
 
+    /// Return the trait object mode to be used.
+    fn trait_object_mode(&self) -> TraitObjectMode;
+
     /// Returns a static string we can use for printouts.
     fn tag(&self) -> &'static str;
 
@@ -596,14 +607,44 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
                            a: &Self,
                            b: &Self)
         -> RelateResult<'tcx, Self>
-            where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a {
+        where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a {
+        use ty::ExistentialPredicate::*;
 
-        if a.len() != b.len() {
+        let tcx = relation.tcx();
+        let (a_buf, b_buf);
+        let (a_norm, b_norm): (&[_], &[_]) = match relation.trait_object_mode() {
+            TraitObjectMode::NoSquash => {
+                (a, b)
+            }
+            TraitObjectMode::SquashAutoTraitsIssue33140 => {
+                // Treat auto-trait "principal" components as equal
+                // to the non-principal components, to make
+                // `dyn Send+Sync = dyn Sync+Send`.
+                let normalize = |d: &[ty::ExistentialPredicate<'tcx>]| {
+                    let mut result: Vec<_> = d.iter().map(|pi| match pi {
+                        Trait(ref a) if tcx.trait_is_auto(a.def_id) => {
+                            AutoTrait(a.def_id)
+                        },
+                        other => *other
+                    }).collect();
+
+                    result.sort_by(|a, b| a.stable_cmp(tcx, b));
+                    result.dedup();
+                    result
+                };
+
+                a_buf = normalize(a);
+                b_buf = normalize(b);
+
+                (&a_buf, &b_buf)
+            }
+        };
+
+        if a_norm.len() != b_norm.len() {
             return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
         }
 
-        let tcx = relation.tcx();
-        let v = a.iter().zip(b.iter()).map(|(ep_a, ep_b)| {
+        let v = a_norm.iter().zip(b_norm.iter()).map(|(ep_a, ep_b)| {
             use ty::ExistentialPredicate::*;
             match (*ep_a, *ep_b) {
                 (Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)),
index d6aeb288b5cdcbe2b533f94301eef4f57fb37b93..1d28c4fa114ef2fbc8d29b839d41f80d8317df10 100644 (file)
@@ -35,6 +35,7 @@
     usize,
     ::ty::layout::VariantIdx,
     u64,
+    String,
     ::middle::region::Scope,
     ::syntax::ast::FloatTy,
     ::syntax::ast::NodeId,
index a95ddefc86906a2815e72ffb93ae1a865757bb3e..01b1387d9cc2f50dc5284c844541c588ac93716b 100644 (file)
@@ -1024,17 +1024,11 @@ fn memset(
 
     fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("minnum");
-        unsafe {
-            let instr = llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs);
-            instr.expect("LLVMRustBuildMinNum is not available in LLVM version < 6.0")
-        }
+        unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
     }
     fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("maxnum");
-        unsafe {
-            let instr = llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs);
-            instr.expect("LLVMRustBuildMaxNum is not available in LLVM version < 6.0")
-        }
+        unsafe { llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs) }
     }
 
     fn select(
index 0bd6146f5aaa0e002924e625562e08c7ee1398ff..b75cd8f68b368070fadbee4c90814dfefaddd51a 100644 (file)
@@ -10,7 +10,6 @@
 
 use attributes;
 use llvm;
-use llvm_util;
 use rustc::dep_graph::DepGraphSafe;
 use rustc::hir;
 use debuginfo;
@@ -446,10 +445,6 @@ fn apply_target_cpu_attr(&self, llfn: &'ll Value) {
         attributes::apply_target_cpu_attr(self, llfn)
     }
 
-    fn closure_env_needs_indirect_debuginfo(&self) -> bool {
-        llvm_util::get_major_version() < 6
-    }
-
     fn create_used_variable(&self) {
         let name = const_cstr!("llvm.used");
         let section = const_cstr!("llvm.metadata");
index 8b26ada1576063db231af8f977c05bb6b89447a3..e229f8d95cd5b566d09c8ef47cc9f6e445fa8cc3 100644 (file)
@@ -1192,7 +1192,7 @@ macro_rules! require_simd {
         return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
     }
 
-    // every intrinsic takes a SIMD vector as its first argument
+    // every intrinsic below takes a SIMD vector as its first argument
     require_simd!(arg_tys[0], "input");
     let in_ty = arg_tys[0];
     let in_elem = arg_tys[0].simd_type(tcx);
@@ -1296,6 +1296,7 @@ macro_rules! require_simd {
     if name == "simd_select" {
         let m_elem_ty = in_elem;
         let m_len = in_len;
+        require_simd!(arg_tys[1], "argument");
         let v_len = arg_tys[1].simd_size(tcx);
         require!(m_len == v_len,
                  "mismatched lengths: mask length `{}` != other vector length `{}`",
index 127759a432664baeb13816384490eb6de9178837..4732db88ec1cb60535213affef54373fc772a998 100644 (file)
@@ -1222,12 +1222,12 @@ pub fn LLVMRustBuildMinNum(
         B: &Builder<'a>,
         LHS: &'a Value,
         LHS: &'a Value,
-    ) -> Option<&'a Value>;
+    ) -> &'a Value;
     pub fn LLVMRustBuildMaxNum(
         B: &Builder<'a>,
         LHS: &'a Value,
         LHS: &'a Value,
-    ) -> Option<&'a Value>;
+    ) -> &'a Value;
 
     // Atomic Operations
     pub fn LLVMRustBuildAtomicLoad(B: &Builder<'a>,
index 12109ae1662ff5364b8fe79de6f0e9f3c16fb507..82b1d7e8b40e4554adb485776992b7aa04924d64 100644 (file)
@@ -140,6 +140,7 @@ unsafe fn configure_llvm(sess: &Session) {
     ("avx512vpopcntdq", Some("avx512_target_feature")),
     ("bmi1", None),
     ("bmi2", None),
+    ("cmpxchg16b", Some("cmpxchg16b_target_feature")),
     ("fma", None),
     ("fxsr", None),
     ("lzcnt", None),
@@ -212,6 +213,7 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
         ("x86", "pclmulqdq") => "pclmul",
         ("x86", "rdrand") => "rdrnd",
         ("x86", "bmi1") => "bmi",
+        ("x86", "cmpxchg16b") => "cx16",
         ("aarch64", "fp") => "fp-armv8",
         ("aarch64", "fp16") => "fullfp16",
         (_, s) => s,
index 750de1c660cf347c3d411c724a4e3f8993be6e68..d316b3ec3508c71c69b52edcb1e862c9de2e3489 100644 (file)
@@ -610,35 +610,13 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
             };
             let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
 
-            // Store the pointer to closure data in an alloca for debuginfo
-            // because that's what the llvm.dbg.declare intrinsic expects.
-
-            // FIXME(eddyb) this shouldn't be necessary but SROA seems to
-            // mishandle DW_OP_plus not preceded by DW_OP_deref, i.e., it
-            // doesn't actually strip the offset when splitting the closure
-            // environment into its components so it ends up out of bounds.
-            // (cuviper) It seems to be fine without the alloca on LLVM 6 and later.
-            let env_alloca = !env_ref && bx.closure_env_needs_indirect_debuginfo();
-            let env_ptr = if env_alloca {
-                let scratch = PlaceRef::alloca(bx,
-                    bx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
-                    "__debuginfo_env_ptr");
-                bx.store(place.llval, scratch.llval, scratch.align);
-                scratch.llval
-            } else {
-                place.llval
-            };
-
             for (i, (decl, ty)) in mir.upvar_decls.iter().zip(upvar_tys).enumerate() {
                 let byte_offset_of_var_in_env = closure_layout.fields.offset(i).bytes();
 
                 let ops = bx.debuginfo_upvar_decls_ops_sequence(byte_offset_of_var_in_env);
 
                 // The environment and the capture can each be indirect.
-
-                // FIXME(eddyb) see above why we sometimes have to keep
-                // a pointer in an alloca for debuginfo atm.
-                let mut ops = if env_ref || env_alloca { &ops[..] } else { &ops[1..] };
+                let mut ops = if env_ref { &ops[..] } else { &ops[1..] };
 
                 let ty = if let (true, &ty::Ref(_, ty, _)) = (decl.by_ref, &ty.sty) {
                     ty
@@ -648,7 +626,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
                 };
 
                 let variable_access = VariableAccess::IndirectVariable {
-                    alloca: env_ptr,
+                    alloca: place.llval,
                     address_operations: &ops
                 };
                 bx.declare_local(
index d8871dd3a58caba94373c5e6606063ccf08a1c04..57afb800d014cc7fdead38ea10844bbede3ecebe 100644 (file)
@@ -32,7 +32,6 @@ fn vtables(
     fn stats(&self) -> &RefCell<Stats>;
     fn consume_stats(self) -> RefCell<Stats>;
     fn codegen_unit(&self) -> &Arc<CodegenUnit<'tcx>>;
-    fn closure_env_needs_indirect_debuginfo(&self) -> bool;
     fn used_statics(&self) -> &RefCell<Vec<Self::Value>>;
     fn set_frame_pointer_elimination(&self, llfn: Self::Value);
     fn apply_target_cpu_attr(&self, llfn: Self::Value);
index 66364ff88b38dce963a368511cbb1a951dbe107e..347121833d3f14f889de3389f03b71a162e31edf 100644 (file)
@@ -293,6 +293,11 @@ macro_rules! add_lint_group {
             reference: "issue #46205 <https://github.com/rust-lang/rust/issues/46205>",
             edition: None,
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(ORDER_DEPENDENT_TRAIT_OBJECTS),
+            reference: "issue #56484 <https://github.com/rust-lang/rust/issues/56484>",
+            edition: None,
+        },
         FutureIncompatibleInfo {
             id: LintId::of(TYVAR_BEHIND_RAW_POINTER),
             reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
index e3029c6a19d499d057268af5c690546fcf731554..5eca62938f7a8c821cbe68b18930779f7c770b12 100644 (file)
@@ -545,7 +545,7 @@ fn visit_statement_entry(
                 self.mutate_place(
                     ContextKind::SetDiscrim.new(location),
                     (place, span),
-                    Shallow(Some(ArtificialField::Discriminant)),
+                    Shallow(None),
                     JustWrite,
                     flow_state,
                 );
@@ -782,7 +782,6 @@ enum MutateMode {
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 enum ArtificialField {
-    Discriminant,
     ArrayLength,
     ShallowBorrow,
 }
@@ -1191,14 +1190,14 @@ fn consume_rvalue(
 
             Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => {
                 let af = match *rvalue {
-                    Rvalue::Len(..) => ArtificialField::ArrayLength,
-                    Rvalue::Discriminant(..) => ArtificialField::Discriminant,
+                    Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
+                    Rvalue::Discriminant(..) => None,
                     _ => unreachable!(),
                 };
                 self.access_place(
                     context,
                     (place, span),
-                    (Shallow(Some(af)), Read(ReadKind::Copy)),
+                    (Shallow(af), Read(ReadKind::Copy)),
                     LocalMutationIsAllowed::No,
                     flow_state,
                 );
index 8af23a8813a9e6d8eac91be8c07d60a2e0461433..07bda8af62618a6191df91d1533277641add6939 100644 (file)
@@ -99,7 +99,7 @@ fn visit_statement(&mut self,
                 self.mutate_place(
                     ContextKind::SetDiscrim.new(location),
                     place,
-                    Shallow(Some(ArtificialField::Discriminant)),
+                    Shallow(None),
                     JustWrite,
                 );
             }
@@ -360,14 +360,14 @@ fn consume_rvalue(
 
             Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => {
                 let af = match *rvalue {
-                    Rvalue::Len(..) => ArtificialField::ArrayLength,
-                    Rvalue::Discriminant(..) => ArtificialField::Discriminant,
+                    Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
+                    Rvalue::Discriminant(..) => None,
                     _ => unreachable!(),
                 };
                 self.access_place(
                     context,
                     place,
-                    (Shallow(Some(af)), Read(ReadKind::Copy)),
+                    (Shallow(af), Read(ReadKind::Copy)),
                     LocalMutationIsAllowed::No,
                 );
             }
index eeac915cff37eb79b6a33619917d96f057016454..e24586cca0929ba372e8e084253a839f6e3b4c13 100644 (file)
@@ -165,15 +165,12 @@ fn place_components_conflict<'gcx, 'tcx>(
                 let base_ty = base.ty(mir, tcx).to_ty(tcx);
 
                 match (elem, &base_ty.sty, access) {
-                    (_, _, Shallow(Some(ArtificialField::Discriminant)))
-                    | (_, _, Shallow(Some(ArtificialField::ArrayLength)))
+                    (_, _, Shallow(Some(ArtificialField::ArrayLength)))
                     | (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => {
-                        // The discriminant and array length are like
-                        // additional fields on the type; they do not
-                        // overlap any existing data there. Furthermore,
-                        // they cannot actually be a prefix of any
-                        // borrowed place (at least in MIR as it is
-                        // currently.)
+                        // The array length is like  additional fields on the
+                        // type; it does not overlap any existing data there.
+                        // Furthermore, if cannot actually be a prefix of any
+                        // borrowed place (at least in MIR as it is currently.)
                         //
                         // e.g., a (mutable) borrow of `a[5]` while we read the
                         // array length of `a`.
index 7e7c0b15555f838fa292cf11089ea5ee238ce781..4d61bf8dae681b5451116e2cb0a0f70022dabcf6 100644 (file)
@@ -19,7 +19,6 @@
 use build::{GuardFrame, GuardFrameLocal, LocalsForNode};
 use hair::*;
 use hair::pattern::PatternTypeProjections;
-use rustc::hir;
 use rustc::mir::*;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::VariantIdx;
@@ -100,7 +99,7 @@ pub fn match_expr(
             .collect();
 
         // create binding start block for link them by false edges
-        let candidate_count = arms.iter().fold(0, |ac, c| ac + c.patterns.len());
+        let candidate_count = arms.iter().map(|c| c.patterns.len()).sum::<usize>();
         let pre_binding_blocks: Vec<_> = (0..=candidate_count)
             .map(|_| self.cfg.start_new_block())
             .collect();
@@ -337,7 +336,7 @@ pub(super) fn expr_into_pattern(
 
     pub fn place_into_pattern(
         &mut self,
-        mut block: BasicBlock,
+        block: BasicBlock,
         irrefutable_pat: Pattern<'tcx>,
         initializer: &Place<'tcx>,
         set_match_place: bool,
@@ -359,7 +358,7 @@ pub fn place_into_pattern(
 
         // Simplify the candidate. Since the pattern is irrefutable, this should
         // always convert all match-pairs into bindings.
-        unpack!(block = self.simplify_candidate(block, &mut candidate));
+        self.simplify_candidate(&mut candidate);
 
         if !candidate.match_pairs.is_empty() {
             span_bug!(
@@ -681,12 +680,7 @@ enum TestKind<'tcx> {
     },
 
     // test whether the value falls within an inclusive or exclusive range
-    Range {
-        lo: &'tcx ty::Const<'tcx>,
-        hi: &'tcx ty::Const<'tcx>,
-        ty: Ty<'tcx>,
-        end: hir::RangeEnd,
-    },
+    Range(PatternRange<'tcx>),
 
     // test length of the slice is equal to len
     Len {
@@ -745,7 +739,7 @@ fn match_candidates<'pat>(
         // complete, all the match pairs which remain require some
         // form of test, whether it be a switch or pattern comparison.
         for candidate in &mut candidates {
-            unpack!(block = self.simplify_candidate(block, candidate));
+            self.simplify_candidate(candidate);
         }
 
         // The candidates are sorted by priority. Check to see
@@ -1035,7 +1029,7 @@ fn test_candidates<'pat>(
             test, match_pair
         );
         let target_blocks = self.perform_test(block, &match_pair.place, &test);
-        let mut target_candidates: Vec<_> = (0..target_blocks.len()).map(|_| vec![]).collect();
+        let mut target_candidates = vec![vec![]; target_blocks.len()];
 
         // Sort the candidates into the appropriate vector in
         // `target_candidates`. Note that at some point we may
index 328b330f762dc14135cb9c4aad51f402f672fbcf..0ce642838707ed5aac8e95b3d1b659fa87e7b8c2 100644 (file)
 //! sort of test: for example, testing which variant an enum is, or
 //! testing a value against a constant.
 
-use build::{BlockAnd, BlockAndExtension, Builder};
+use build::Builder;
 use build::matches::{Ascription, Binding, MatchPair, Candidate};
 use hair::*;
-use rustc::mir::*;
 use rustc::ty;
 use rustc::ty::layout::{Integer, IntegerExt, Size};
 use syntax::attr::{SignedInt, UnsignedInt};
 
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     pub fn simplify_candidate<'pat>(&mut self,
-                                    block: BasicBlock,
-                                    candidate: &mut Candidate<'pat, 'tcx>)
-                                    -> BlockAnd<()> {
+                                    candidate: &mut Candidate<'pat, 'tcx>) {
         // repeatedly simplify match pairs until fixed point is reached
         loop {
             let match_pairs = mem::replace(&mut candidate.match_pairs, vec![]);
-            let mut progress = match_pairs.len(); // count how many were simplified
+            let mut changed = false;
             for match_pair in match_pairs {
                 match self.simplify_match_pair(match_pair, candidate) {
-                    Ok(()) => {}
+                    Ok(()) => {
+                        changed = true;
+                    }
                     Err(match_pair) => {
                         candidate.match_pairs.push(match_pair);
-                        progress -= 1; // this one was not simplified
                     }
                 }
             }
-            if progress == 0 {
-                return block.unit(); // if we were not able to simplify any, done.
+            if !changed {
+                return; // if we were not able to simplify any, done.
             }
         }
     }
@@ -109,7 +107,7 @@ fn simplify_match_pair<'pat>(&mut self,
                 Err(match_pair)
             }
 
-            PatternKind::Range { lo, hi, ty, end } => {
+            PatternKind::Range(PatternRange { lo, hi, ty, end }) => {
                 let range = match ty.sty {
                     ty::Char => {
                         Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32)))
index 5d9cb014f5821bda850c2b0340545efaa86df840..c8dec6d0b9764b67528e2d531a5d06f17f3dce03 100644 (file)
@@ -18,6 +18,7 @@
 use build::Builder;
 use build::matches::{Candidate, MatchPair, Test, TestKind};
 use hair::*;
+use hair::pattern::compare_const_vals;
 use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::fx::FxHashMap;
 use rustc::ty::{self, Ty};
@@ -71,16 +72,11 @@ pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
                 }
             }
 
-            PatternKind::Range { lo, hi, ty, end } => {
-                assert!(ty == match_pair.pattern.ty);
+            PatternKind::Range(range) => {
+                assert!(range.ty == match_pair.pattern.ty);
                 Test {
                     span: match_pair.pattern.span,
-                    kind: TestKind::Range {
-                        lo,
-                        hi,
-                        ty,
-                        end,
-                    },
+                    kind: TestKind::Range(range),
                 }
             }
 
@@ -136,7 +132,11 @@ pub fn add_cases_to_switch<'pat>(&mut self,
             PatternKind::Variant { .. } => {
                 panic!("you should have called add_variants_to_switch instead!");
             }
-            PatternKind::Range { .. } |
+            PatternKind::Range(range) => {
+                // Check that none of the switch values are in the range.
+                self.values_not_contained_in_range(range, indices)
+                    .unwrap_or(false)
+            }
             PatternKind::Slice { .. } |
             PatternKind::Array { .. } |
             PatternKind::Wild |
@@ -200,20 +200,18 @@ pub fn perform_test(&mut self,
                 for (idx, discr) in adt_def.discriminants(tcx) {
                     target_blocks.push(if variants.contains(idx) {
                         values.push(discr.val);
-                        targets.push(self.cfg.start_new_block());
-                        *targets.last().unwrap()
+                        let block = self.cfg.start_new_block();
+                        targets.push(block);
+                        block
                     } else {
-                        if otherwise_block.is_none() {
-                            otherwise_block = Some(self.cfg.start_new_block());
-                        }
-                        otherwise_block.unwrap()
+                        *otherwise_block
+                            .get_or_insert_with(|| self.cfg.start_new_block())
                     });
                 }
-                if let Some(otherwise_block) = otherwise_block {
-                    targets.push(otherwise_block);
-                } else {
-                    targets.push(self.unreachable_block());
-                }
+                targets.push(
+                    otherwise_block
+                        .unwrap_or_else(|| self.unreachable_block()),
+                );
                 debug!("num_enum_variants: {}, tested variants: {:?}, variants: {:?}",
                        num_enum_variants, values, variants);
                 let discr_ty = adt_def.repr.discr_type().to_ty(tcx);
@@ -378,7 +376,7 @@ pub fn perform_test(&mut self,
                 }
             }
 
-            TestKind::Range { ref lo, ref hi, ty, ref end } => {
+            TestKind::Range(PatternRange { ref lo, ref hi, ty, ref end }) => {
                 // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
                 let lo = self.literal_operand(test.span, ty.clone(), lo.clone());
                 let hi = self.literal_operand(test.span, ty.clone(), hi.clone());
@@ -490,8 +488,7 @@ pub fn sort_candidate<'pat>(&mut self,
         // away.)
         let tested_match_pair = candidate.match_pairs.iter()
                                                      .enumerate()
-                                                     .filter(|&(_, mp)| mp.place == *test_place)
-                                                     .next();
+                                                     .find(|&(_, mp)| mp.place == *test_place);
         let (match_pair_index, match_pair) = match tested_match_pair {
             Some(pair) => pair,
             None => {
@@ -532,6 +529,24 @@ pub fn sort_candidate<'pat>(&mut self,
                 resulting_candidates[index].push(new_candidate);
                 true
             }
+
+            (&TestKind::SwitchInt { switch_ty: _, ref options, ref indices },
+             &PatternKind::Range(range)) => {
+                let not_contained = self
+                    .values_not_contained_in_range(range, indices)
+                    .unwrap_or(false);
+
+                if not_contained {
+                    // No switch values are contained in the pattern range,
+                    // so the pattern can be matched only if this test fails.
+                    let otherwise = options.len();
+                    resulting_candidates[otherwise].push(candidate.clone());
+                    true
+                } else {
+                    false
+                }
+            }
+
             (&TestKind::SwitchInt { .. }, _) => false,
 
 
@@ -610,8 +625,63 @@ pub fn sort_candidate<'pat>(&mut self,
                 }
             }
 
+            (&TestKind::Range(test),
+             &PatternKind::Range(pat)) => {
+                if test == pat {
+                    resulting_candidates[0]
+                        .push(self.candidate_without_match_pair(
+                            match_pair_index,
+                            candidate,
+                        ));
+                    return true;
+                }
+
+                let no_overlap = (|| {
+                    use std::cmp::Ordering::*;
+                    use rustc::hir::RangeEnd::*;
+
+                    let param_env = ty::ParamEnv::empty().and(test.ty);
+                    let tcx = self.hir.tcx();
+
+                    let lo = compare_const_vals(tcx, test.lo, pat.hi, param_env)?;
+                    let hi = compare_const_vals(tcx, test.hi, pat.lo, param_env)?;
+
+                    match (test.end, pat.end, lo, hi) {
+                        // pat < test
+                        (_, _, Greater, _) |
+                        (_, Excluded, Equal, _) |
+                        // pat > test
+                        (_, _, _, Less) |
+                        (Excluded, _, _, Equal) => Some(true),
+                        _ => Some(false),
+                    }
+                })();
+
+                if no_overlap == Some(true) {
+                    // Testing range does not overlap with pattern range,
+                    // so the pattern can be matched only if this test fails.
+                    resulting_candidates[1].push(candidate.clone());
+                    true
+                } else {
+                    false
+                }
+            }
+
+            (&TestKind::Range(range), &PatternKind::Constant { ref value }) => {
+                if self.const_range_contains(range, value) == Some(false) {
+                    // `value` is not contained in the testing range,
+                    // so `value` can be matched only if this test fails.
+                    resulting_candidates[1].push(candidate.clone());
+                    true
+                } else {
+                    false
+                }
+            }
+
+            (&TestKind::Range { .. }, _) => false,
+
+
             (&TestKind::Eq { .. }, _) |
-            (&TestKind::Range { .. }, _) |
             (&TestKind::Len { .. }, _) => {
                 // These are all binary tests.
                 //
@@ -722,6 +792,40 @@ fn error_simplifyable<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> !
                   "simplifyable pattern found: {:?}",
                   match_pair.pattern)
     }
+
+    fn const_range_contains(
+        &self,
+        range: PatternRange<'tcx>,
+        value: &'tcx ty::Const<'tcx>,
+    ) -> Option<bool> {
+        use std::cmp::Ordering::*;
+
+        let param_env = ty::ParamEnv::empty().and(range.ty);
+        let tcx = self.hir.tcx();
+
+        let a = compare_const_vals(tcx, range.lo, value, param_env)?;
+        let b = compare_const_vals(tcx, value, range.hi, param_env)?;
+
+        match (b, range.end) {
+            (Less, _) |
+            (Equal, RangeEnd::Included) if a != Greater => Some(true),
+            _ => Some(false),
+        }
+    }
+
+    fn values_not_contained_in_range(
+        &self,
+        range: PatternRange<'tcx>,
+        indices: &FxHashMap<&'tcx ty::Const<'tcx>, usize>,
+    ) -> Option<bool> {
+        for val in indices.keys() {
+            if self.const_range_contains(range, val)? {
+                return Some(false);
+            }
+        }
+
+        Some(true)
+    }
 }
 
 fn is_switch_ty<'tcx>(ty: Ty<'tcx>) -> bool {
index ab52d9be6b81bc7255f5aeb2e0530a298886a061..d6af125debf8ec956ac4373a7dd91076c39e25b2 100644 (file)
@@ -111,13 +111,6 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
 
             let safety = match fn_sig.unsafety {
                 hir::Unsafety::Normal => Safety::Safe,
-                hir::Unsafety::Unsafe if tcx.is_min_const_fn(fn_def_id) => {
-                    // As specified in #55607, a `const unsafe fn` differs
-                    // from an `unsafe fn` in that its body is still considered
-                    // safe code by default.
-                    assert!(implicit_argument.is_none());
-                    Safety::Safe
-                },
                 hir::Unsafety::Unsafe => Safety::FnUnsafe,
             };
 
@@ -856,15 +849,17 @@ fn finish(self,
             }
         }
 
-        Mir::new(self.cfg.basic_blocks,
-                 self.source_scopes,
-                 ClearCrossCrate::Set(self.source_scope_local_data),
-                 IndexVec::new(),
-                 yield_ty,
-                 self.local_decls,
-                 self.arg_count,
-                 self.upvar_decls,
-                 self.fn_span
+        Mir::new(
+            self.cfg.basic_blocks,
+            self.source_scopes,
+            ClearCrossCrate::Set(self.source_scope_local_data),
+            IndexVec::new(),
+            yield_ty,
+            self.local_decls,
+            self.arg_count,
+            self.upvar_decls,
+            self.fn_span,
+            self.hir.control_flow_destroyed(),
         )
     }
 
index a1471adac6050dcc92401d93a8c59b67438aa36a..f93dbce97b54a6f47fb6cd74969b726433c9b385 100644 (file)
@@ -372,6 +372,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                     // FIXME(eddyb) use logical ops in constants when
                     // they can handle that kind of control-flow.
                     (hir::BinOpKind::And, hir::Constness::Const) => {
+                        cx.control_flow_destroyed.push((
+                            op.span,
+                            "`&&` operator".into(),
+                        ));
                         ExprKind::Binary {
                             op: BinOp::BitAnd,
                             lhs: lhs.to_ref(),
@@ -379,6 +383,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         }
                     }
                     (hir::BinOpKind::Or, hir::Constness::Const) => {
+                        cx.control_flow_destroyed.push((
+                            op.span,
+                            "`||` operator".into(),
+                        ));
                         ExprKind::Binary {
                             op: BinOp::BitOr,
                             lhs: lhs.to_ref(),
index a0b2d99dfd30531cbb2f0cfc2f0cce6c38b9566e..5d8732bb8aee8dcf1d474a212eab6387b99c4ad3 100644 (file)
@@ -56,6 +56,9 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
 
     /// True if this constant/function needs overflow checks.
     check_overflow: bool,
+
+    /// See field with the same name on `Mir`
+    control_flow_destroyed: Vec<(Span, String)>,
 }
 
 impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
@@ -96,9 +99,13 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
             constness,
             body_owner_kind,
             check_overflow,
+            control_flow_destroyed: Vec::new(),
         }
     }
 
+    pub fn control_flow_destroyed(self) -> Vec<(Span, String)> {
+        self.control_flow_destroyed
+    }
 }
 
 impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
index e604b118eacf1f8f445acd5553806bf1ef9dc8e8..b254fce4b7684a6678d77ad99c75e2da1733d340 100644 (file)
@@ -29,7 +29,7 @@
 mod constant;
 
 pub mod pattern;
-pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
+pub use self::pattern::{BindingMode, Pattern, PatternKind, PatternRange, FieldPattern};
 pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections};
 
 mod util;
index 5cfcc16162ee2bb2426315be0ff18efa3e281d2c..7ec6bbfe3c11e32a057491edf217551487c0782a 100644 (file)
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
 
-use super::{FieldPattern, Pattern, PatternKind};
+use super::{FieldPattern, Pattern, PatternKind, PatternRange};
 use super::{PatternFoldable, PatternFolder, compare_const_vals};
 
 use rustc::hir::def_id::DefId;
@@ -604,12 +604,12 @@ fn apply_constructor<'a>(
                 _ => {
                     match *ctor {
                         ConstantValue(value) => PatternKind::Constant { value },
-                        ConstantRange(lo, hi, ty, end) => PatternKind::Range {
+                        ConstantRange(lo, hi, ty, end) => PatternKind::Range(PatternRange {
                             lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)),
                             hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)),
                             ty,
                             end,
-                        },
+                        }),
                         _ => PatternKind::Wild,
                     }
                 }
@@ -872,7 +872,7 @@ fn from_pat(tcx: TyCtxt<'_, 'tcx, 'tcx>,
                 -> Option<IntRange<'tcx>> {
         Self::from_ctor(tcx, &match pat.kind {
             box PatternKind::Constant { value } => ConstantValue(value),
-            box PatternKind::Range { lo, hi, ty, end } => ConstantRange(
+            box PatternKind::Range(PatternRange { lo, hi, ty, end }) => ConstantRange(
                 lo.to_bits(tcx, ty::ParamEnv::empty().and(ty)).unwrap(),
                 hi.to_bits(tcx, ty::ParamEnv::empty().and(ty)).unwrap(),
                 ty,
@@ -1311,7 +1311,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>,
             Some(vec![Variant(adt_def.variants[variant_index].did)])
         }
         PatternKind::Constant { value } => Some(vec![ConstantValue(value)]),
-        PatternKind::Range { lo, hi, ty, end } =>
+        PatternKind::Range(PatternRange { lo, hi, ty, end }) =>
             Some(vec![ConstantRange(
                 lo.to_bits(cx.tcx, ty::ParamEnv::empty().and(ty)).unwrap(),
                 hi.to_bits(cx.tcx, ty::ParamEnv::empty().and(ty)).unwrap(),
@@ -1642,7 +1642,7 @@ fn constructor_covered_by_range<'a, 'tcx>(
 ) -> Result<bool, ErrorReported> {
     let (from, to, end, ty) = match pat.kind {
         box PatternKind::Constant { value } => (value, value, RangeEnd::Included, value.ty),
-        box PatternKind::Range { lo, hi, ty, end } => (lo, hi, end, ty),
+        box PatternKind::Range(PatternRange { lo, hi, end, ty }) => (lo, hi, end, ty),
         _ => bug!("`constructor_covered_by_range` called with {:?}", pat),
     };
     trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty);
index ddd6a705b04d116a8d1135d91d4342ef19e20552..f78a70f6a25f436895cc84261616ad8de0ba509a 100644 (file)
@@ -24,7 +24,7 @@
 use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
 use rustc::mir::{ProjectionElem, UserTypeAnnotation, UserTypeProjection, UserTypeProjections};
 use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
-use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty};
+use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift};
 use rustc::ty::subst::{Substs, Kind};
 use rustc::ty::layout::VariantIdx;
 use rustc::hir::{self, PatKind, RangeEnd};
@@ -219,12 +219,7 @@ pub enum PatternKind<'tcx> {
         value: &'tcx ty::Const<'tcx>,
     },
 
-    Range {
-        lo: &'tcx ty::Const<'tcx>,
-        hi: &'tcx ty::Const<'tcx>,
-        ty: Ty<'tcx>,
-        end: RangeEnd,
-    },
+    Range(PatternRange<'tcx>),
 
     /// matches against a slice, checking the length and extracting elements.
     /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
@@ -243,6 +238,14 @@ pub enum PatternKind<'tcx> {
     },
 }
 
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub struct PatternRange<'tcx> {
+    pub lo: &'tcx ty::Const<'tcx>,
+    pub hi: &'tcx ty::Const<'tcx>,
+    pub ty: Ty<'tcx>,
+    pub end: RangeEnd,
+}
+
 impl<'tcx> fmt::Display for Pattern<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self.kind {
@@ -354,7 +357,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             PatternKind::Constant { value } => {
                 fmt_const_val(f, value)
             }
-            PatternKind::Range { lo, hi, ty: _, end } => {
+            PatternKind::Range(PatternRange { lo, hi, ty: _, end }) => {
                 fmt_const_val(f, lo)?;
                 match end {
                     RangeEnd::Included => write!(f, "..=")?,
@@ -483,7 +486,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                         );
                         match (end, cmp) {
                             (RangeEnd::Excluded, Some(Ordering::Less)) =>
-                                PatternKind::Range { lo, hi, ty, end },
+                                PatternKind::Range(PatternRange { lo, hi, ty, end }),
                             (RangeEnd::Excluded, _) => {
                                 span_err!(
                                     self.tcx.sess,
@@ -497,7 +500,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                                 PatternKind::Constant { value: lo }
                             }
                             (RangeEnd::Included, Some(Ordering::Less)) => {
-                                PatternKind::Range { lo, hi, ty, end }
+                                PatternKind::Range(PatternRange { lo, hi, ty, end })
                             }
                             (RangeEnd::Included, _) => {
                                 let mut err = struct_span_err!(
@@ -1177,17 +1180,17 @@ fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
             } => PatternKind::Constant {
                 value: value.fold_with(folder)
             },
-            PatternKind::Range {
+            PatternKind::Range(PatternRange {
                 lo,
                 hi,
                 ty,
                 end,
-            } => PatternKind::Range {
+            }) => PatternKind::Range(PatternRange {
                 lo: lo.fold_with(folder),
                 hi: hi.fold_with(folder),
                 ty: ty.fold_with(folder),
                 end,
-            },
+            }),
             PatternKind::Slice {
                 ref prefix,
                 ref slice,
@@ -1210,8 +1213,8 @@ fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
     }
 }
 
-pub fn compare_const_vals<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub fn compare_const_vals<'a, 'gcx, 'tcx>(
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
     a: &'tcx ty::Const<'tcx>,
     b: &'tcx ty::Const<'tcx>,
     ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
@@ -1233,6 +1236,9 @@ pub fn compare_const_vals<'a, 'tcx>(
         return fallback();
     }
 
+    let tcx = tcx.global_tcx();
+    let (a, b, ty) = (a, b, ty).lift_to_tcx(tcx).unwrap();
+
     // FIXME: This should use assert_bits(ty) instead of use_bits
     // but triggers possibly bugs due to mismatching of arrays and slices
     if let (Some(a), Some(b)) = (a.to_bits(tcx, ty), b.to_bits(tcx, ty)) {
index 1a35f4da20bf158a1fddab082043edcf30e28cc0..983488da0031da2f9b56d22526b379574d45722e 100644 (file)
@@ -37,7 +37,7 @@
 #![feature(if_while_or_patterns)]
 #![feature(try_from)]
 #![feature(reverse_bits)]
-#![feature(underscore_imports)]
+#![cfg_attr(stage0, feature(underscore_imports))]
 
 #![recursion_limit="256"]
 
index 114162946051ea71cf6657a1f8a9c758acf1b8d0..2728833251ac2f6dbd185c00bd79751ad50f3d31 100644 (file)
@@ -219,7 +219,8 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         local_decls_for_sig(&sig, span),
         sig.inputs().len(),
         vec![],
-        span
+        span,
+        vec![],
     );
 
     if let Some(..) = ty {
@@ -396,7 +397,8 @@ fn into_mir(self) -> Mir<'tcx> {
             self.local_decls,
             self.sig.inputs().len(),
             vec![],
-            self.span
+            self.span,
+            vec![],
         )
     }
 
@@ -844,7 +846,8 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         local_decls,
         sig.inputs().len(),
         vec![],
-        span
+        span,
+        vec![],
     );
     if let Abi::RustCall = sig.abi {
         mir.spread_arg = Some(Local::new(sig.inputs().len()));
@@ -921,6 +924,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
         local_decls,
         sig.inputs().len(),
         vec![],
-        span
+        span,
+        vec![],
     )
 }
index 6af29b74c1c4fab1e535a8b8ee492e47202b66ad..3607869384077656bcc6591ceb6ee520d9f1bae4 100644 (file)
@@ -311,13 +311,9 @@ fn register_violations(&mut self,
                            violations: &[UnsafetyViolation],
                            unsafe_blocks: &[(ast::NodeId, bool)]) {
         let safety = self.source_scope_local_data[self.source_info.scope].safety;
-        let within_unsafe = match (safety, self.min_const_fn) {
-            // Erring on the safe side, pun intended
-            (Safety::BuiltinUnsafe, true) |
-            // mir building encodes const fn bodies as safe, even for `const unsafe fn`
-            (Safety::FnUnsafe, true) => bug!("const unsafe fn body treated as inherently unsafe"),
+        let within_unsafe = match safety {
             // `unsafe` blocks are required in safe code
-            (Safety::Safe, _) => {
+            Safety::Safe => {
                 for violation in violations {
                     let mut violation = violation.clone();
                     match violation.kind {
@@ -342,9 +338,9 @@ fn register_violations(&mut self,
                 }
                 false
             }
-            // regular `unsafe` function bodies allow unsafe without additional unsafe blocks
-            (Safety::BuiltinUnsafe, false) | (Safety::FnUnsafe, false) => true,
-            (Safety::ExplicitUnsafe(node_id), _) => {
+            // `unsafe` function bodies allow unsafe without additional unsafe blocks
+            Safety::BuiltinUnsafe | Safety::FnUnsafe => true,
+            Safety::ExplicitUnsafe(node_id) => {
                 // mark unsafe block as used if there are any unsafe operations inside
                 if !violations.is_empty() {
                     self.used_unsafe.insert(node_id);
@@ -616,21 +612,6 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
     } in violations.iter() {
         // Report an error.
         match kind {
-            UnsafetyViolationKind::General if tcx.is_min_const_fn(def_id) => {
-                let mut err = tcx.sess.struct_span_err(
-                    source_info.span,
-                    &format!("{} is unsafe and unsafe operations \
-                            are not allowed in const fn", description));
-                err.span_label(source_info.span, &description.as_str()[..])
-                    .note(&details.as_str()[..]);
-                if tcx.fn_sig(def_id).unsafety() == hir::Unsafety::Unsafe {
-                    err.note(
-                        "unsafe action within a `const unsafe fn` still require an `unsafe` \
-                        block in contrast to regular `unsafe fn`."
-                    );
-                }
-                err.emit();
-            }
             UnsafetyViolationKind::GeneralAndConstFn |
             UnsafetyViolationKind::General => {
                 struct_span_err!(
index 7f8dfc111a4bde777ed23af81866d7a21ea859b3..f5bf73b4300acc0955c78c1246c9194b91d2c648 100644 (file)
@@ -412,7 +412,8 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
                 initial_locals,
                 0,
                 vec![],
-                mir.span
+                mir.span,
+                vec![],
             ),
             tcx,
             source: mir,
index 5f08dee87285928dc6d7361a9b7d681a741792ba..58a3cb97e4156470fbf715e57063a5f9d779d64d 100644 (file)
@@ -553,7 +553,13 @@ fn visit_place(&mut self,
                     this.super_place(place, context, location);
                     match proj.elem {
                         ProjectionElem::Deref => {
-                            this.add(Qualif::NOT_CONST);
+                            if context.is_mutating_use() {
+                                // `not_const` errors out in const contexts
+                                this.not_const()
+                            } else {
+                                // just make sure this doesn't get promoted
+                                this.add(Qualif::NOT_CONST);
+                            }
                             let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
                             match this.mode {
                                 Mode::Fn => {},
@@ -1178,7 +1184,6 @@ fn visit_assign(&mut self,
             if self.mir.local_kind(index) == LocalKind::Var &&
                self.const_fn_arg_vars.insert(index) &&
                !self.tcx.features().const_let {
-
                 // Direct use of an argument is permitted.
                 match *rvalue {
                     Rvalue::Use(Operand::Copy(Place::Local(local))) |
@@ -1189,7 +1194,6 @@ fn visit_assign(&mut self,
                     }
                     _ => {}
                 }
-
                 // Avoid a generic error for other uses of arguments.
                 if self.qualif.contains(Qualif::FN_ARGUMENT) {
                     let decl = &self.mir.local_decls[index];
@@ -1348,6 +1352,37 @@ fn run_pass<'a, 'tcx>(&self,
             // Do the actual promotion, now that we know what's viable.
             promote_consts::promote_candidates(mir, tcx, temps, candidates);
         } else {
+            if !mir.control_flow_destroyed.is_empty() {
+                let mut locals = mir.vars_iter();
+                if let Some(local) = locals.next() {
+                    let span = mir.local_decls[local].source_info.span;
+                    let mut error = tcx.sess.struct_span_err(
+                        span,
+                        &format!(
+                            "new features like let bindings are not permitted in {}s \
+                            which also use short circuiting operators",
+                            mode,
+                        ),
+                    );
+                    for (span, kind) in mir.control_flow_destroyed.iter() {
+                        error.span_note(
+                            *span,
+                            &format!("use of {} here does not actually short circuit due to \
+                            the const evaluator presently not being able to do control flow. \
+                            See https://github.com/rust-lang/rust/issues/49146 for more \
+                            information.", kind),
+                        );
+                    }
+                    for local in locals {
+                        let span = mir.local_decls[local].source_info.span;
+                        error.span_note(
+                            span,
+                            "more locals defined here",
+                        );
+                    }
+                    error.emit();
+                }
+            }
             let promoted_temps = if mode == Mode::Const {
                 // Already computed by `mir_const_qualif`.
                 const_promoted_temps.unwrap()
index 3c1b9dbd91fa80e60548fbe54ab1ddc9012659a5..eee167c3579370a2df560a395c57b0ca67dd8857 100644 (file)
@@ -230,7 +230,7 @@ fn check_statement(
             check_rvalue(tcx, mir, rval, span)
         }
 
-        StatementKind::FakeRead(..) => Err((span, "match in const fn is unstable".into())),
+        StatementKind::FakeRead(_, place) => check_place(tcx, mir, place, span, PlaceMode::Read),
 
         // just an assignment
         StatementKind::SetDiscriminant { .. } => Ok(()),
index f643870dec207c6e28bf08ea42460bbf6b735212..592f721b2f545d79a611e0c4db0eb1d5eae9d394 100644 (file)
@@ -108,10 +108,14 @@ pub fn new(mir: &'a mut Mir<'tcx>) -> Self {
     pub fn simplify(mut self) {
         self.strip_nops();
 
+        let mut start = START_BLOCK;
+
         loop {
             let mut changed = false;
 
-            for bb in (0..self.basic_blocks.len()).map(BasicBlock::new) {
+            self.collapse_goto_chain(&mut start, &mut changed);
+
+            for bb in self.basic_blocks.indices() {
                 if self.pred_count[bb] == 0 {
                     continue
                 }
@@ -142,6 +146,27 @@ pub fn simplify(mut self) {
 
             if !changed { break }
         }
+
+        if start != START_BLOCK {
+            debug_assert!(self.pred_count[START_BLOCK] == 0);
+            self.basic_blocks.swap(START_BLOCK, start);
+            self.pred_count.swap(START_BLOCK, start);
+
+            // pred_count == 1 if the start block has no predecessor _blocks_.
+            if self.pred_count[START_BLOCK] > 1 {
+                for (bb, data) in self.basic_blocks.iter_enumerated_mut() {
+                    if self.pred_count[bb] == 0 {
+                        continue;
+                    }
+
+                    for target in data.terminator_mut().successors_mut() {
+                        if *target == start {
+                            *target = START_BLOCK;
+                        }
+                    }
+                }
+            }
+        }
     }
 
     // Collapse a goto chain starting from `start`
index 42ead92783d7af2a424e713bdf92df85fc7510c5..a5d2edbc5d4396f286688ded2938246aa7dbf509 100644 (file)
@@ -41,7 +41,6 @@
 pub mod rvalue_promotion;
 pub mod hir_stats;
 pub mod loops;
-mod mir_stats;
 
 __build_diagnostic_array! { librustc_passes, DIAGNOSTICS }
 
diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs
deleted file mode 100644 (file)
index fb37f03..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-// Copyright 2016 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.
-
-// The visitors in this module collect sizes and counts of the most important
-// pieces of MIR. The resulting numbers are good approximations but not
-// completely accurate (some things might be counted twice, others missed).
-
-use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData};
-use rustc::mir::{Constant, Location, Local, LocalDecl};
-use rustc::mir::{Place, PlaceElem, PlaceProjection};
-use rustc::mir::{Mir, Operand, ProjectionElem};
-use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind};
-use rustc::mir::{Terminator, TerminatorKind, SourceScope, SourceScopeData};
-use rustc::mir::interpret::EvalErrorKind;
-use rustc::mir::visit as mir_visit;
-use rustc::ty::{self, ClosureSubsts, TyCtxt};
-use rustc::util::nodemap::{FxHashMap};
-
-struct NodeData {
-    count: usize,
-    size: usize,
-}
-
-struct StatCollector<'a, 'tcx: 'a> {
-    _tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    data: FxHashMap<&'static str, NodeData>,
-}
-
-impl<'a, 'tcx> StatCollector<'a, 'tcx> {
-
-    fn record_with_size(&mut self, label: &'static str, node_size: usize) {
-        let entry = self.data.entry(label).or_insert(NodeData {
-            count: 0,
-            size: 0,
-        });
-
-        entry.count += 1;
-        entry.size = node_size;
-    }
-
-    fn record<T>(&mut self, label: &'static str, node: &T) {
-        self.record_with_size(label, ::std::mem::size_of_val(node));
-    }
-}
-
-impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
-    fn visit_mir(&mut self, mir: &Mir<'tcx>) {
-        self.record("Mir", mir);
-
-        // since the `super_mir` method does not traverse the MIR of
-        // promoted rvalues, (but we still want to gather statistics
-        // on the structures represented there) we manually traverse
-        // the promoted rvalues here.
-        for promoted_mir in &mir.promoted {
-            self.visit_mir(promoted_mir);
-        }
-
-        self.super_mir(mir);
-    }
-
-    fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) {
-        self.record("BasicBlockData", data);
-        self.super_basic_block_data(block, data);
-    }
-
-    fn visit_source_scope_data(&mut self, scope_data: &SourceScopeData) {
-        self.record("SourceScopeData", scope_data);
-        self.super_source_scope_data(scope_data);
-    }
-
-    fn visit_statement(&mut self,
-                       block: BasicBlock,
-                       statement: &Statement<'tcx>,
-                       location: Location) {
-        self.record("Statement", statement);
-        self.record(match statement.kind {
-            StatementKind::Assign(..) => "StatementKind::Assign",
-            StatementKind::FakeRead(..) => "StatementKind::FakeRead",
-            StatementKind::Retag { .. } => "StatementKind::Retag",
-            StatementKind::EscapeToRaw { .. } => "StatementKind::EscapeToRaw",
-            StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant",
-            StatementKind::StorageLive(..) => "StatementKind::StorageLive",
-            StatementKind::StorageDead(..) => "StatementKind::StorageDead",
-            StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm",
-            StatementKind::AscribeUserType(..) => "StatementKind::AscribeUserType",
-            StatementKind::Nop => "StatementKind::Nop",
-        }, &statement.kind);
-        self.super_statement(block, statement, location);
-    }
-
-    fn visit_terminator(&mut self,
-                        block: BasicBlock,
-                        terminator: &Terminator<'tcx>,
-                        location: Location) {
-        self.record("Terminator", terminator);
-        self.super_terminator(block, terminator, location);
-    }
-
-    fn visit_terminator_kind(&mut self,
-                             block: BasicBlock,
-                             kind: &TerminatorKind<'tcx>,
-                             location: Location) {
-        self.record("TerminatorKind", kind);
-        self.record(match *kind {
-            TerminatorKind::Goto { .. } => "TerminatorKind::Goto",
-            TerminatorKind::SwitchInt { .. } => "TerminatorKind::SwitchInt",
-            TerminatorKind::Resume => "TerminatorKind::Resume",
-            TerminatorKind::Abort => "TerminatorKind::Abort",
-            TerminatorKind::Return => "TerminatorKind::Return",
-            TerminatorKind::Unreachable => "TerminatorKind::Unreachable",
-            TerminatorKind::Drop { .. } => "TerminatorKind::Drop",
-            TerminatorKind::DropAndReplace { .. } => "TerminatorKind::DropAndReplace",
-            TerminatorKind::Call { .. } => "TerminatorKind::Call",
-            TerminatorKind::Assert { .. } => "TerminatorKind::Assert",
-            TerminatorKind::GeneratorDrop => "TerminatorKind::GeneratorDrop",
-            TerminatorKind::Yield { .. } => "TerminatorKind::Yield",
-            TerminatorKind::FalseEdges { .. } => "TerminatorKind::FalseEdges",
-            TerminatorKind::FalseUnwind { .. } => "TerminatorKind::FalseUnwind",
-        }, kind);
-        self.super_terminator_kind(block, kind, location);
-    }
-
-    fn visit_assert_message(&mut self, msg: &AssertMessage<'tcx>, location: Location) {
-        self.record("AssertMessage", msg);
-        self.record(match *msg {
-            EvalErrorKind::BoundsCheck { .. } => "AssertMessage::BoundsCheck",
-            EvalErrorKind::Overflow(..) => "AssertMessage::Overflow",
-            EvalErrorKind::OverflowNeg => "AssertMessage::OverflowNeg",
-            EvalErrorKind::DivisionByZero => "AssertMessage::DivisionByZero",
-            EvalErrorKind::RemainderByZero => "AssertMessage::RemainderByZero",
-            EvalErrorKind::GeneratorResumedAfterReturn => {
-                "AssertMessage::GeneratorResumedAfterReturn"
-            }
-            EvalErrorKind::GeneratorResumedAfterPanic => {
-                "AssertMessage::GeneratorResumedAfterPanic"
-            }
-            _ => bug!(),
-        }, msg);
-        self.super_assert_message(msg, location);
-    }
-
-    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
-        self.record("Rvalue", rvalue);
-        let rvalue_kind = match *rvalue {
-            Rvalue::Use(..) => "Rvalue::Use",
-            Rvalue::Repeat(..) => "Rvalue::Repeat",
-            Rvalue::Ref(..) => "Rvalue::Ref",
-            Rvalue::Len(..) => "Rvalue::Len",
-            Rvalue::Cast(..) => "Rvalue::Cast",
-            Rvalue::BinaryOp(..) => "Rvalue::BinaryOp",
-            Rvalue::CheckedBinaryOp(..) => "Rvalue::CheckedBinaryOp",
-            Rvalue::UnaryOp(..) => "Rvalue::UnaryOp",
-            Rvalue::Discriminant(..) => "Rvalue::Discriminant",
-            Rvalue::NullaryOp(..) => "Rvalue::NullaryOp",
-            Rvalue::Aggregate(ref kind, ref _operands) => {
-                // AggregateKind is not distinguished by visit API, so
-                // record it. (`super_rvalue` handles `_operands`.)
-                self.record(match **kind {
-                    AggregateKind::Array(_) => "AggregateKind::Array",
-                    AggregateKind::Tuple => "AggregateKind::Tuple",
-                    AggregateKind::Adt(..) => "AggregateKind::Adt",
-                    AggregateKind::Closure(..) => "AggregateKind::Closure",
-                    AggregateKind::Generator(..) => "AggregateKind::Generator",
-                }, kind);
-
-                "Rvalue::Aggregate"
-            }
-        };
-        self.record(rvalue_kind, rvalue);
-        self.super_rvalue(rvalue, location);
-    }
-
-    fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
-        self.record("Operand", operand);
-        self.record(match *operand {
-            Operand::Copy(..) => "Operand::Copy",
-            Operand::Move(..) => "Operand::Move",
-            Operand::Constant(..) => "Operand::Constant",
-        }, operand);
-        self.super_operand(operand, location);
-    }
-
-    fn visit_place(&mut self,
-                    place: &Place<'tcx>,
-                    context: mir_visit::PlaceContext<'tcx>,
-                    location: Location) {
-        self.record("Place", place);
-        self.record(match *place {
-            Place::Local(..) => "Place::Local",
-            Place::Static(..) => "Place::Static",
-            Place::Promoted(..) => "Place::Promoted",
-            Place::Projection(..) => "Place::Projection",
-        }, place);
-        self.super_place(place, context, location);
-    }
-
-    fn visit_projection(&mut self,
-                        place: &PlaceProjection<'tcx>,
-                        context: mir_visit::PlaceContext<'tcx>,
-                        location: Location) {
-        self.record("PlaceProjection", place);
-        self.super_projection(place, context, location);
-    }
-
-    fn visit_projection_elem(&mut self,
-                             place: &PlaceElem<'tcx>,
-                             location: Location) {
-        self.record("PlaceElem", place);
-        self.record(match *place {
-            ProjectionElem::Deref => "PlaceElem::Deref",
-            ProjectionElem::Subslice { .. } => "PlaceElem::Subslice",
-            ProjectionElem::Field(..) => "PlaceElem::Field",
-            ProjectionElem::Index(..) => "PlaceElem::Index",
-            ProjectionElem::ConstantIndex { .. } => "PlaceElem::ConstantIndex",
-            ProjectionElem::Downcast(..) => "PlaceElem::Downcast",
-        }, place);
-        self.super_projection_elem(place, location);
-    }
-
-    fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
-        self.record("Constant", constant);
-        self.super_constant(constant, location);
-    }
-
-    fn visit_source_info(&mut self, source_info: &SourceInfo) {
-        self.record("SourceInfo", source_info);
-        self.super_source_info(source_info);
-    }
-
-    fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, _: Location) {
-        self.record("ClosureSubsts", substs);
-        self.super_closure_substs(substs);
-    }
-
-    fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
-        self.record("Const", constant);
-        self.super_const(constant);
-    }
-
-    fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
-        self.record("LocalDecl", local_decl);
-        self.super_local_decl(local, local_decl);
-    }
-
-    fn visit_source_scope(&mut self, scope: &SourceScope) {
-        self.record("VisiblityScope", scope);
-        self.super_source_scope(scope);
-    }
-}
index e926e4913d634801a0b1fac235f461fb01ddc0fb..ef41ea31e3ef9c0a9b5beec9d6a89881fd0f1438 100644 (file)
@@ -74,6 +74,8 @@ fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
     args.insert(LinkerFlavor::Gcc,
                 vec!["-arch".to_string(),
                      arch_name.to_string(),
+                     "-isysroot".to_string(),
+                     sdk_root.clone(),
                      "-Wl,-syslibroot".to_string(),
                      sdk_root]);
 
index 07383b3d64862430b332413b5490cad227025756..5b6d8abc5ef3e51c0244e07c971266f1588b7a8f 100644 (file)
@@ -49,6 +49,7 @@ pub fn target() -> Result<Target, String> {
         max_atomic_width: Some(64),
         panic_strategy: PanicStrategy::Abort,
         cpu: "x86-64".into(),
+        features: "+rdrnd,+rdseed".into(),
         position_independent_executables: true,
         pre_link_args: iter::once(
                 (LinkerFlavor::Gcc, PRE_LINK_ARGS.iter().cloned().map(String::from).collect())
index df6458a766d4e89f128697551a741469333627a0..73aa8a107247ddb128d2a9cb5818aadb96c92dfa 100644 (file)
@@ -17,7 +17,7 @@
 };
 use rustc::ty::{self, Ty};
 use rustc::ty::subst::Kind;
-use rustc::ty::relate::{Relate, RelateResult, TypeRelation};
+use rustc::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use syntax_pos::DUMMY_SP;
 
 use super::{ChalkInferenceContext, ChalkArenas, ChalkExClause, ConstrainedSubst};
@@ -137,6 +137,10 @@ fn tcx(&self) -> ty::TyCtxt<'cx, 'gcx, 'tcx> {
         self.infcx.tcx
     }
 
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        self.infcx.trait_object_mode()
+    }
+
     fn tag(&self) -> &'static str {
         "chalk_context::answer_substitutor"
     }
index e4ce04916ce6428322bee28fccd7fd0345e9dccf..75ae868883484e0bd308d9b07d02386331faef7d 100644 (file)
@@ -280,7 +280,7 @@ fn confirm_builtin_call(&self,
                         Def::Local(id) | Def::Upvar(id, ..) => {
                             Some(self.tcx.hir().span(id))
                         }
-                        _ => self.tcx.hir().span_if_local(def.def_id())
+                        _ => def.opt_def_id().and_then(|did| self.tcx.hir().span_if_local(did)),
                     };
                     if let Some(span) = def_span {
                         let label = match (unit_variant, inner_callee_path) {
index 8901f4b6b291bdf2f68b08d88e60fb166999d129..957c8d9f19f0ebe1f8e14ea8bb1c0ab4ad1eb087 100644 (file)
@@ -95,7 +95,7 @@
 
 use astconv::AstConv;
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
-use rustc::hir::{self, GenericArg, Node, ItemKind, PatKind};
+use rustc::hir::{self, GenericArg, ItemKind, Node, PatKind};
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs,
                        UserSelfTy, UserSubsts};
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
-use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind};
+use rustc::ty::{self, AdtKind, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate,
+                RegionKind};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::query::Providers;
@@ -3217,8 +3218,8 @@ fn check_return_expr(&self, return_expr: &'gcx hir::Expr) {
                             return_expr_ty);
     }
 
-    // A generic function for checking the then and else in an if
-    // or if-else.
+    // A generic function for checking the 'then' and 'else' clauses in an 'if'
+    // or 'if-else' expression.
     fn check_then_else(&self,
                        cond_expr: &'gcx hir::Expr,
                        then_expr: &'gcx hir::Expr,
@@ -3544,7 +3545,7 @@ fn check_expr_struct_fields(&self,
                 // We don't look at stability attributes on
                 // struct-like enums (yet...), but it's definitely not
                 // a bug to have constructed one.
-                if adt_kind != ty::AdtKind::Enum {
+                if adt_kind != AdtKind::Enum {
                     tcx.check_stability(v_field.did, Some(expr_id), field.span);
                 }
 
@@ -5156,26 +5157,48 @@ pub fn instantiate_value_path(&self,
         }).unwrap_or(false);
 
         let mut new_def = def;
-        let (def_id, ty) = if let Def::SelfCtor(impl_def_id) = def {
-            let ty = self.impl_self_ty(span, impl_def_id).ty;
-
-            match ty.ty_adt_def() {
-                Some(adt_def) if adt_def.is_struct() => {
-                    let variant = adt_def.non_enum_variant();
-                    new_def = Def::StructCtor(variant.did, variant.ctor_kind);
-                    (variant.did, self.tcx.type_of(variant.did))
-                }
-                _ => {
-                    (impl_def_id, self.tcx.types.err)
+        let (def_id, ty) = match def {
+            Def::SelfCtor(impl_def_id) => {
+                let ty = self.impl_self_ty(span, impl_def_id).ty;
+                let adt_def = ty.ty_adt_def();
+
+                match adt_def {
+                    Some(adt_def) if adt_def.has_ctor() => {
+                        let variant = adt_def.non_enum_variant();
+                        new_def = Def::StructCtor(variant.did, variant.ctor_kind);
+                        (variant.did, self.tcx.type_of(variant.did))
+                    }
+                    _ => {
+                        let mut err = self.tcx.sess.struct_span_err(span,
+                            "the `Self` constructor can only be used with tuple or unit structs");
+                        if let Some(adt_def) = adt_def {
+                            match adt_def.adt_kind() {
+                                AdtKind::Enum => {
+                                    err.note("did you mean to use one of the enum's variants?");
+                                },
+                                AdtKind::Struct |
+                                AdtKind::Union => {
+                                    err.span_label(
+                                        span,
+                                        format!("did you mean `Self {{ /* fields */ }}`?"),
+                                    );
+                                }
+                            }
+                        }
+                        err.emit();
+
+                        (impl_def_id, self.tcx.types.err)
+                    }
                 }
             }
-        } else {
-            let def_id = def.def_id();
+            _ => {
+                let def_id = def.def_id();
 
-            // The things we are substituting into the type should not contain
-            // escaping late-bound regions, and nor should the base type scheme.
-            let ty = self.tcx.type_of(def_id);
-            (def_id, ty)
+                // The things we are substituting into the type should not contain
+                // escaping late-bound regions, and nor should the base type scheme.
+                let ty = self.tcx.type_of(def_id);
+                (def_id, ty)
+            }
         };
 
         let substs = AstConv::create_substs_for_generic_args(
index ec1a43991f6aaa158d1f04e08a0dca7438beee1a..c273c8f64567756a3e84c6410bde3752f95c653a 100644 (file)
@@ -12,8 +12,9 @@
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::traits::{self, IntercrateMode};
+use rustc::traits::{self, IntercrateMode, FutureCompatOverlapErrorKind};
 use rustc::ty::TyCtxt;
+use rustc::ty::relate::TraitObjectMode;
 
 use lint;
 
@@ -29,9 +30,11 @@ struct InherentOverlapChecker<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
-    fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId,
-                                       overlap: traits::OverlapResult,
-                                       used_to_be_allowed: bool) {
+    fn check_for_common_items_in_impls(
+        &self, impl1: DefId, impl2: DefId,
+        overlap: traits::OverlapResult,
+        used_to_be_allowed: Option<FutureCompatOverlapErrorKind>)
+    {
 
         let name_and_namespace = |def_id| {
             let item = self.tcx.associated_item(def_id);
@@ -47,19 +50,28 @@ fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId,
             for &item2 in &impl_items2[..] {
                 if (name, namespace) == name_and_namespace(item2) {
                     let node_id = self.tcx.hir().as_local_node_id(impl1);
-                    let mut err = if used_to_be_allowed && node_id.is_some() {
-                        self.tcx.struct_span_lint_node(
-                            lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
-                            node_id.unwrap(),
-                            self.tcx.span_of_impl(item1).unwrap(),
-                            &format!("duplicate definitions with name `{}` (E0592)", name)
-                        )
-                    } else {
-                        struct_span_err!(self.tcx.sess,
-                                         self.tcx.span_of_impl(item1).unwrap(),
-                                         E0592,
-                                         "duplicate definitions with name `{}`",
-                                         name)
+                    let mut err = match used_to_be_allowed {
+                        Some(kind) if node_id.is_some() => {
+                            let lint = match kind {
+                                FutureCompatOverlapErrorKind::Issue43355 =>
+                                    lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
+                                FutureCompatOverlapErrorKind::Issue33140 =>
+                                    lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS,
+                            };
+                            self.tcx.struct_span_lint_node(
+                                lint,
+                                node_id.unwrap(),
+                                self.tcx.span_of_impl(item1).unwrap(),
+                                &format!("duplicate definitions with name `{}` (E0592)", name)
+                            )
+                        }
+                        _ => {
+                            struct_span_err!(self.tcx.sess,
+                                             self.tcx.span_of_impl(item1).unwrap(),
+                                             E0592,
+                                             "duplicate definitions with name `{}`",
+                                             name)
+                        }
                     };
 
                     err.span_label(self.tcx.span_of_impl(item1).unwrap(),
@@ -82,38 +94,73 @@ fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
 
         for (i, &impl1_def_id) in impls.iter().enumerate() {
             for &impl2_def_id in &impls[(i + 1)..] {
+                // First, check if the impl was forbidden under the
+                // old rules. In that case, just have an error.
                 let used_to_be_allowed = traits::overlapping_impls(
                     self.tcx,
                     impl1_def_id,
                     impl2_def_id,
                     IntercrateMode::Issue43355,
+                    TraitObjectMode::NoSquash,
                     |overlap| {
                         self.check_for_common_items_in_impls(
                             impl1_def_id,
                             impl2_def_id,
                             overlap,
-                            false,
+                            None,
                         );
                         false
                     },
                     || true,
                 );
 
-                if used_to_be_allowed {
-                    traits::overlapping_impls(
-                        self.tcx,
-                        impl1_def_id,
-                        impl2_def_id,
-                        IntercrateMode::Fixed,
-                        |overlap| self.check_for_common_items_in_impls(
+                if !used_to_be_allowed {
+                    continue;
+                }
+
+                // Then, check if the impl was forbidden under only
+                // #43355. In that case, emit an #43355 error.
+                let used_to_be_allowed = traits::overlapping_impls(
+                    self.tcx,
+                    impl1_def_id,
+                    impl2_def_id,
+                    IntercrateMode::Fixed,
+                    TraitObjectMode::NoSquash,
+                    |overlap| {
+                        self.check_for_common_items_in_impls(
                             impl1_def_id,
                             impl2_def_id,
                             overlap,
-                            true,
-                        ),
-                        || (),
-                    );
+                            Some(FutureCompatOverlapErrorKind::Issue43355),
+                        );
+                        false
+                    },
+                    || true,
+                );
+
+                if !used_to_be_allowed {
+                    continue;
                 }
+
+                // Then, check if the impl was forbidden under
+                // #33140. In that case, emit a #33140 error.
+                traits::overlapping_impls(
+                    self.tcx,
+                    impl1_def_id,
+                    impl2_def_id,
+                    IntercrateMode::Fixed,
+                    TraitObjectMode::SquashAutoTraitsIssue33140,
+                    |overlap| {
+                        self.check_for_common_items_in_impls(
+                            impl1_def_id,
+                            impl2_def_id,
+                            overlap,
+                            Some(FutureCompatOverlapErrorKind::Issue33140),
+                        );
+                        false
+                    },
+                    || true,
+                );
             }
         }
     }
index c9f3aa011a1d4987dec7b0602b0c7310f6dbf246..46002c089cf9f36d84d5673e6f33cd48fce0011e 100644 (file)
@@ -868,10 +868,10 @@ fn write_shared(
     }
 
     {
-        let mut data = static_files::STORAGE_JS.to_owned();
-        data.push_str(&format!("var resourcesSuffix = \"{}\";", cx.shared.resource_suffix));
         write_minify(cx.dst.join(&format!("storage{}.js", cx.shared.resource_suffix)),
-                     &data,
+                     &format!("var resourcesSuffix = \"{}\";{}",
+                              cx.shared.resource_suffix,
+                              static_files::STORAGE_JS),
                      options.enable_minification)?;
     }
 
index 51714c35d6faa2dddb3e0266a23dbe4a846213c7..d5b8ecd4807f13442bc650c94da00095c4d2090c 100644 (file)
@@ -213,9 +213,9 @@ if (!DOMTokenList.prototype.remove) {
     function expandSection(id) {
         var elem = document.getElementById(id);
         if (elem && isHidden(elem)) {
-            var h3 = elem.parentNode.previousSibling;
+            var h3 = elem.parentNode.previousElementSibling;
             if (h3 && h3.tagName !== "H3") {
-                h3 = h3.previousSibling; // skip div.docblock
+                h3 = h3.previousElementSibling; // skip div.docblock
             }
 
             if (h3) {
index d1336b1e8eb0b7aa510bd30df42795ef893dcd1d..01d2cbec1922145445b74d85b24f7df27ebe66a7 100644 (file)
@@ -305,7 +305,7 @@ nav.sub {
        overflow-x: auto;
 }
 
-body:not(.source) .example-wrap > pre {
+.rustdoc:not(.source) .example-wrap > pre {
        margin: 0;
 }
 
index d1c377bf95ac87e29c6cd117849992d7c7029cdb..22ac52f87285c951bd47159caa07c525278fdff2 100644 (file)
@@ -111,7 +111,7 @@ function switchTheme(styleElem, mainStyleElem, newTheme) {
 
     var found = false;
     if (savedHref.length === 0) {
-        onEach(document.getElementsByTagName("link"), function(el) {
+        onEachLazy(document.getElementsByTagName("link"), function(el) {
             savedHref.push(el.href);
         });
     }
index 50acde64cf023b32e1f817ab43fe67d2f3d49eeb..84ce9f6d2574d1bc54926aa1c99ff32fb004b94f 100644 (file)
@@ -395,6 +395,7 @@ pub fn make_test(s: &str,
     // Now push any outer attributes from the example, assuming they
     // are intended to be crate attributes.
     prog.push_str(&crate_attrs);
+    prog.push_str(&crates);
 
     // Uses libsyntax to parse the doctest and find if there's a main fn and the extern
     // crate already is included.
@@ -488,37 +489,78 @@ pub fn make_test(s: &str,
         prog.push_str("\n}");
     }
 
+    debug!("final doctest:\n{}", prog);
+
     (prog, line_offset)
 }
 
 // FIXME(aburka): use a real parser to deal with multiline attributes
 fn partition_source(s: &str) -> (String, String, String) {
-    let mut after_header = false;
+    #[derive(Copy, Clone, PartialEq)]
+    enum PartitionState {
+        Attrs,
+        Crates,
+        Other,
+    }
+    let mut state = PartitionState::Attrs;
     let mut before = String::new();
     let mut crates = String::new();
     let mut after = String::new();
 
     for line in s.lines() {
         let trimline = line.trim();
-        let header = trimline.chars().all(|c| c.is_whitespace()) ||
-            trimline.starts_with("#![") ||
-            trimline.starts_with("#[macro_use] extern crate") ||
-            trimline.starts_with("extern crate");
-        if !header || after_header {
-            after_header = true;
-            after.push_str(line);
-            after.push_str("\n");
-        } else {
-            if trimline.starts_with("#[macro_use] extern crate")
-                || trimline.starts_with("extern crate") {
+
+        // FIXME(misdreavus): if a doc comment is placed on an extern crate statement, it will be
+        // shunted into "everything else"
+        match state {
+            PartitionState::Attrs => {
+                state = if trimline.starts_with("#![") ||
+                    trimline.chars().all(|c| c.is_whitespace()) ||
+                    (trimline.starts_with("//") && !trimline.starts_with("///"))
+                {
+                    PartitionState::Attrs
+                } else if trimline.starts_with("extern crate") ||
+                    trimline.starts_with("#[macro_use] extern crate")
+                {
+                    PartitionState::Crates
+                } else {
+                    PartitionState::Other
+                };
+            }
+            PartitionState::Crates => {
+                state = if trimline.starts_with("extern crate") ||
+                    trimline.starts_with("#[macro_use] extern crate") ||
+                    trimline.chars().all(|c| c.is_whitespace()) ||
+                    (trimline.starts_with("//") && !trimline.starts_with("///"))
+                {
+                    PartitionState::Crates
+                } else {
+                    PartitionState::Other
+                };
+            }
+            PartitionState::Other => {}
+        }
+
+        match state {
+            PartitionState::Attrs => {
+                before.push_str(line);
+                before.push_str("\n");
+            }
+            PartitionState::Crates => {
                 crates.push_str(line);
                 crates.push_str("\n");
             }
-            before.push_str(line);
-            before.push_str("\n");
+            PartitionState::Other => {
+                after.push_str(line);
+                after.push_str("\n");
+            }
         }
     }
 
+    debug!("before:\n{}", before);
+    debug!("crates:\n{}", crates);
+    debug!("after:\n{}", after);
+
     (before, after, crates)
 }
 
@@ -1035,8 +1077,8 @@ fn make_test_fake_main() {
 assert_eq!(2+2, 4);";
         let expected =
 "#![allow(unused)]
-fn main() {
 //Ceci n'est pas une `fn main`
+fn main() {
 assert_eq!(2+2, 4);
 }".to_string();
         let output = make_test(input, None, false, &opts);
@@ -1083,8 +1125,8 @@ fn make_test_issues_21299_33731() {
 
         let expected =
 "#![allow(unused)]
-fn main() {
 // fn main
+fn main() {
 assert_eq!(2+2, 4);
 }".to_string();
 
index 41e778b6a4c728d73f9e6657e2ce48a3acdae37f..9cee00b9c76d0a81387559b8b92168e04a00ab55 100644 (file)
@@ -21,6 +21,7 @@ libc = { version = "0.2.44", default-features = false, features = ['rustc-dep-of
 compiler_builtins = { version = "0.1.1" }
 profiler_builtins = { path = "../libprofiler_builtins", optional = true }
 unwind = { path = "../libunwind" }
+rustc-demangle = { version = "0.1.10", features = ['rustc-dep-of-std'] }
 
 [dev-dependencies]
 rand = "0.6.1"
index 7d17aaf2f261b24e723e9012c88390e62d6ad052..d0dd4d4adcb9850a7d558d5453dc414ae1255c75 100644 (file)
@@ -550,7 +550,8 @@ pub fn log10(self) -> f32 {
     #[inline]
     #[rustc_deprecated(since = "1.10.0",
                        reason = "you probably meant `(self - other).abs()`: \
-                                 this operation is `(self - other).max(0.0)` (also \
+                                 this operation is `(self - other).max(0.0)` \
+                                 except that `abs_sub` also propagates NaNs (also \
                                  known as `fdimf` in C). If you truly need the positive \
                                  difference, consider using that expression or the C function \
                                  `fdimf`, depending on how you wish to handle NaN (please consider \
index c800763167fcbb40ed42fcc697ecfbf2684da77f..9e627ec204291bf9afd2b64a612f578dc8a67d1e 100644 (file)
@@ -491,7 +491,8 @@ pub fn log10(self) -> f64 {
     #[inline]
     #[rustc_deprecated(since = "1.10.0",
                        reason = "you probably meant `(self - other).abs()`: \
-                                 this operation is `(self - other).max(0.0)` (also \
+                                 this operation is `(self - other).max(0.0)` \
+                                 except that `abs_sub` also propagates NaNs (also \
                                  known as `fdim` in C). If you truly need the positive \
                                  difference, consider using that expression or the C function \
                                  `fdim`, depending on how you wish to handle NaN (please consider \
index edcfdd9e5348336c2764ab4fb7607c465542e656..35ae4939249ea5a83ec1f7d76e9fabdd0fa42339 100644 (file)
@@ -1729,7 +1729,7 @@ pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
 /// limited to just these cases:
 ///
 /// * `path` does not exist.
-/// * A component in path is not a directory.
+/// * A non-final component in path is not a directory.
 ///
 /// # Examples
 ///
index 0febbe5694bc4f568e9bdcf671dc0483cdf9c716..ead38f2112687144b85198b463c86a451779cb55 100644 (file)
 extern crate alloc as alloc_crate;
 #[doc(masked)]
 extern crate libc;
+extern crate rustc_demangle;
 
 // We always need an unwinder currently for backtraces
 #[doc(masked)]
index 95faf3a5dd63d351460c7f70fa2a770e7d711690..05f30f2881a00e7d0ab35dcab1a71bdf65540739 100644 (file)
           all(target_os = "android", any(target_arch = "aarch64",
                                          target_arch = "arm")),
           all(target_os = "l4re", target_arch = "x86_64"),
+          all(target_os = "freebsd", any(target_arch = "aarch64",
+                                         target_arch = "arm",
+                                         target_arch = "powerpc",
+                                         target_arch = "powerpc64")),
           all(target_os = "netbsd", any(target_arch = "aarch64",
                                         target_arch = "arm",
                                         target_arch = "powerpc")),
               all(target_os = "android", any(target_arch = "aarch64",
                                              target_arch = "arm")),
               all(target_os = "l4re", target_arch = "x86_64"),
+              all(target_os = "freebsd", any(target_arch = "aarch64",
+                                             target_arch = "arm",
+                                             target_arch = "powerpc",
+                                             target_arch = "powerpc64")),
               all(target_os = "netbsd", any(target_arch = "aarch64",
                                             target_arch = "arm",
                                             target_arch = "powerpc")),
index 77371782977b1c6f580d97cee6a5a4c3d4cbb860..e44113f76f40ed3b18665081889c366d99a16bc2 100644 (file)
 use env;
 use io::prelude::*;
 use io;
+use path::{self, Path};
+use ptr;
+use rustc_demangle::demangle;
 use str;
 use sync::atomic::{self, Ordering};
-use path::{self, Path};
 use sys::mutex::Mutex;
-use ptr;
 
 pub use sys::backtrace::{
     unwind_backtrace,
@@ -191,7 +192,14 @@ fn output(w: &mut dyn Write, idx: usize, frame: Frame,
         PrintFormat::Short => write!(w, "  {:2}: ", idx)?,
     }
     match s {
-        Some(string) => demangle(w, string, format)?,
+        Some(string) => {
+            let symbol = demangle(string);
+            match format {
+                PrintFormat::Full => write!(w, "{}", symbol)?,
+                // strip the trailing hash if short mode
+                PrintFormat::Short => write!(w, "{:#}", symbol)?,
+            }
+        }
         None => w.write_all(b"<unknown>")?,
     }
     w.write_all(b"\n")
@@ -235,228 +243,3 @@ fn output_fileline(w: &mut dyn Write,
     w.write_all(b"\n")
 }
 
-
-// All rust symbols are in theory lists of "::"-separated identifiers. Some
-// assemblers, however, can't handle these characters in symbol names. To get
-// around this, we use C++-style mangling. The mangling method is:
-//
-// 1. Prefix the symbol with "_ZN"
-// 2. For each element of the path, emit the length plus the element
-// 3. End the path with "E"
-//
-// For example, "_ZN4testE" => "test" and "_ZN3foo3barE" => "foo::bar".
-//
-// We're the ones printing our backtraces, so we can't rely on anything else to
-// demangle our symbols. It's *much* nicer to look at demangled symbols, so
-// this function is implemented to give us nice pretty output.
-//
-// Note that this demangler isn't quite as fancy as it could be. We have lots
-// of other information in our symbols like hashes, version, type information,
-// etc. Additionally, this doesn't handle glue symbols at all.
-pub fn demangle(writer: &mut dyn Write, mut s: &str, format: PrintFormat) -> io::Result<()> {
-    // During ThinLTO LLVM may import and rename internal symbols, so strip out
-    // those endings first as they're one of the last manglings applied to
-    // symbol names.
-    let llvm = ".llvm.";
-    if let Some(i) = s.find(llvm) {
-        let candidate = &s[i + llvm.len()..];
-        let all_hex = candidate.chars().all(|c| {
-            match c {
-                'A' ..= 'F' | '0' ..= '9' => true,
-                _ => false,
-            }
-        });
-
-        if all_hex {
-            s = &s[..i];
-        }
-    }
-
-    // Validate the symbol. If it doesn't look like anything we're
-    // expecting, we just print it literally. Note that we must handle non-rust
-    // symbols because we could have any function in the backtrace.
-    let mut valid = true;
-    let mut inner = s;
-    if s.len() > 4 && s.starts_with("_ZN") && s.ends_with("E") {
-        inner = &s[3 .. s.len() - 1];
-    // On Windows, dbghelp strips leading underscores, so we accept "ZN...E" form too.
-    } else if s.len() > 3 && s.starts_with("ZN") && s.ends_with("E") {
-        inner = &s[2 .. s.len() - 1];
-    } else {
-        valid = false;
-    }
-
-    if valid {
-        let mut chars = inner.chars();
-        while valid {
-            let mut i = 0;
-            for c in chars.by_ref() {
-                if c.is_numeric() {
-                    i = i * 10 + c as usize - '0' as usize;
-                } else {
-                    break
-                }
-            }
-            if i == 0 {
-                valid = chars.next().is_none();
-                break
-            } else if chars.by_ref().take(i - 1).count() != i - 1 {
-                valid = false;
-            }
-        }
-    }
-
-    // Alright, let's do this.
-    if !valid {
-        writer.write_all(s.as_bytes())?;
-    } else {
-        // remove the `::hfc2edb670e5eda97` part at the end of the symbol.
-        if format == PrintFormat::Short {
-            // The symbol in still mangled.
-            let mut split = inner.rsplitn(2, "17h");
-            match (split.next(), split.next()) {
-                (Some(addr), rest) => {
-                    if addr.len() == 16 &&
-                       addr.chars().all(|c| c.is_digit(16))
-                    {
-                        inner = rest.unwrap_or("");
-                    }
-                }
-                _ => (),
-            }
-        }
-
-        let mut first = true;
-        while !inner.is_empty() {
-            if !first {
-                writer.write_all(b"::")?;
-            } else {
-                first = false;
-            }
-            let mut rest = inner;
-            while rest.chars().next().unwrap().is_numeric() {
-                rest = &rest[1..];
-            }
-            let i: usize = inner[.. (inner.len() - rest.len())].parse().unwrap();
-            inner = &rest[i..];
-            rest = &rest[..i];
-            if rest.starts_with("_$") {
-                rest = &rest[1..];
-            }
-            while !rest.is_empty() {
-                if rest.starts_with(".") {
-                    if let Some('.') = rest[1..].chars().next() {
-                        writer.write_all(b"::")?;
-                        rest = &rest[2..];
-                    } else {
-                        writer.write_all(b".")?;
-                        rest = &rest[1..];
-                    }
-                } else if rest.starts_with("$") {
-                    macro_rules! demangle {
-                        ($($pat:expr => $demangled:expr),*) => ({
-                            $(if rest.starts_with($pat) {
-                                writer.write_all($demangled)?;
-                                rest = &rest[$pat.len()..];
-                              } else)*
-                            {
-                                writer.write_all(rest.as_bytes())?;
-                                break;
-                            }
-
-                        })
-                    }
-
-                    // see src/librustc/back/link.rs for these mappings
-                    demangle! (
-                        "$SP$" => b"@",
-                        "$BP$" => b"*",
-                        "$RF$" => b"&",
-                        "$LT$" => b"<",
-                        "$GT$" => b">",
-                        "$LP$" => b"(",
-                        "$RP$" => b")",
-                        "$C$" => b",",
-
-                        // in theory we can demangle any Unicode code point, but
-                        // for simplicity we just catch the common ones.
-                        "$u7e$" => b"~",
-                        "$u20$" => b" ",
-                        "$u27$" => b"'",
-                        "$u5b$" => b"[",
-                        "$u5d$" => b"]",
-                        "$u7b$" => b"{",
-                        "$u7d$" => b"}",
-                        "$u3b$" => b";",
-                        "$u2b$" => b"+",
-                        "$u22$" => b"\""
-                    )
-                } else {
-                    let idx = match rest.char_indices().find(|&(_, c)| c == '$' || c == '.') {
-                        None => rest.len(),
-                        Some((i, _)) => i,
-                    };
-                    writer.write_all(rest[..idx].as_bytes())?;
-                    rest = &rest[idx..];
-                }
-            }
-        }
-    }
-
-    Ok(())
-}
-
-#[cfg(test)]
-mod tests {
-    use sys_common;
-    macro_rules! t { ($a:expr, $b:expr) => ({
-        let mut m = Vec::new();
-        sys_common::backtrace::demangle(&mut m,
-                                        $a,
-                                        super::PrintFormat::Full).unwrap();
-        assert_eq!(String::from_utf8(m).unwrap(), $b);
-    }) }
-
-    #[test]
-    fn demangle() {
-        t!("test", "test");
-        t!("_ZN4testE", "test");
-        t!("_ZN4test", "_ZN4test");
-        t!("_ZN4test1a2bcE", "test::a::bc");
-    }
-
-    #[test]
-    fn demangle_dollars() {
-        t!("_ZN4$RP$E", ")");
-        t!("_ZN8$RF$testE", "&test");
-        t!("_ZN8$BP$test4foobE", "*test::foob");
-        t!("_ZN9$u20$test4foobE", " test::foob");
-        t!("_ZN35Bar$LT$$u5b$u32$u3b$$u20$4$u5d$$GT$E", "Bar<[u32; 4]>");
-    }
-
-    #[test]
-    fn demangle_many_dollars() {
-        t!("_ZN13test$u20$test4foobE", "test test::foob");
-        t!("_ZN12test$BP$test4foobE", "test*test::foob");
-    }
-
-    #[test]
-    fn demangle_windows() {
-        t!("ZN4testE", "test");
-        t!("ZN13test$u20$test4foobE", "test test::foob");
-        t!("ZN12test$RF$test4foobE", "test&test::foob");
-    }
-
-    #[test]
-    fn demangle_elements_beginning_with_underscore() {
-        t!("_ZN13_$LT$test$GT$E", "<test>");
-        t!("_ZN28_$u7b$$u7b$closure$u7d$$u7d$E", "{{closure}}");
-        t!("_ZN15__STATIC_FMTSTRE", "__STATIC_FMTSTR");
-    }
-
-    #[test]
-    fn demangle_trait_impls() {
-        t!("_ZN71_$LT$Test$u20$$u2b$$u20$$u27$static$u20$as$u20$foo..Bar$LT$Test$GT$$GT$3barE",
-           "<Test + 'static as foo::Bar<Test>>::bar");
-    }
-}
index 7723c15a266f197ea3ce411f440bbb3af63091fc..73cbe49f43b049ee955b140d0e3e547e3ed1eb2f 100644 (file)
@@ -483,7 +483,7 @@ fn tokens(&self) -> TokenStream {
             last_pos = segment.ident.span.hi();
         }
         idents.push(self.node.tokens(self.span));
-        TokenStream::concat(idents)
+        TokenStream::new(idents)
     }
 
     fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
@@ -539,7 +539,7 @@ pub fn tokens(&self, span: Span) -> TokenStream {
         match *self {
             MetaItemKind::Word => TokenStream::empty(),
             MetaItemKind::NameValue(ref lit) => {
-                TokenStream::concat(vec![TokenTree::Token(span, Token::Eq).into(), lit.tokens()])
+                TokenStream::new(vec![TokenTree::Token(span, Token::Eq).into(), lit.tokens()])
             }
             MetaItemKind::List(ref list) => {
                 let mut tokens = Vec::new();
@@ -552,7 +552,7 @@ pub fn tokens(&self, span: Span) -> TokenStream {
                 TokenTree::Delimited(
                     DelimSpan::from_single(span),
                     token::Paren,
-                    TokenStream::concat(tokens).into(),
+                    TokenStream::new(tokens).into(),
                 ).into()
             }
         }
index f4e9a7e409359aa5000886970332defd81c71f02..03c7aa9682477701d5fc0efa52ba72b720088418 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast::{self, Block, Ident, NodeId, PatKind, Path};
+use ast::{self, Block, Ident, LitKind, NodeId, PatKind, Path};
 use ast::{MacStmtStyle, StmtKind, ItemKind};
 use attr::{self, HasAttrs};
 use source_map::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, respan};
@@ -1535,21 +1535,65 @@ fn fold_attribute(&mut self, at: ast::Attribute) -> Option<ast::Attribute> {
                             let item = attr::mk_list_item(DUMMY_SP, include_ident, include_info);
                             items.push(dummy_spanned(ast::NestedMetaItemKind::MetaItem(item)));
                         }
-                        Err(ref e) if e.kind() == ErrorKind::InvalidData => {
-                            self.cx.span_err(
-                                at.span,
-                                &format!("{} wasn't a utf-8 file", filename.display()),
-                            );
-                        }
                         Err(e) => {
-                            self.cx.span_err(
-                                at.span,
-                                &format!("couldn't read {}: {}", filename.display(), e),
-                            );
+                            let lit = it
+                                .meta_item()
+                                .and_then(|item| item.name_value_literal())
+                                .unwrap();
+
+                            if e.kind() == ErrorKind::InvalidData {
+                                self.cx
+                                    .struct_span_err(
+                                        lit.span,
+                                        &format!("{} wasn't a utf-8 file", filename.display()),
+                                    )
+                                    .span_label(lit.span, "contains invalid utf-8")
+                                    .emit();
+                            } else {
+                                let mut err = self.cx.struct_span_err(
+                                    lit.span,
+                                    &format!("couldn't read {}: {}", filename.display(), e),
+                                );
+                                err.span_label(lit.span, "couldn't read file");
+
+                                if e.kind() == ErrorKind::NotFound {
+                                    err.help("external doc paths are relative to the crate root");
+                                }
+
+                                err.emit();
+                            }
                         }
                     }
                 } else {
-                    items.push(noop_fold_meta_list_item(it, self));
+                    let mut err = self.cx.struct_span_err(
+                        it.span,
+                        &format!("expected path to external documentation"),
+                    );
+
+                    // Check if the user erroneously used `doc(include(...))` syntax.
+                    let literal = it.meta_item_list().and_then(|list| {
+                        if list.len() == 1 {
+                            list[0].literal().map(|literal| &literal.node)
+                        } else {
+                            None
+                        }
+                    });
+
+                    let (path, applicability) = match &literal {
+                        Some(LitKind::Str(path, ..)) => {
+                            (path.to_string(), Applicability::MachineApplicable)
+                        }
+                        _ => (String::from("<path>"), Applicability::HasPlaceholders),
+                    };
+
+                    err.span_suggestion_with_applicability(
+                        it.span,
+                        "provide a file path with `=`",
+                        format!("include = \"{}\"", path),
+                        applicability,
+                    );
+
+                    err.emit();
                 }
             }
 
index c3497a17806b1797ed86b02801331852b8ab9633..5820b49ab621636bb19735b3e4ae045121ad6198 100644 (file)
@@ -247,7 +247,7 @@ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
 
             let delim_span = DelimSpan::from_single(self.span);
             r.push(TokenTree::Delimited(
-                delim_span, token::Bracket, TokenStream::concat(inner).into()
+                delim_span, token::Bracket, TokenStream::new(inner).into()
             ));
             r
         }
index a76779ffebdc003dd39f420920527220f0e59705..a63abd40495136e457d055dca0fb088837973488 100644 (file)
@@ -103,12 +103,12 @@ pub fn transcribe(cx: &ExtCtxt,
                 }
                 Frame::Delimited { forest, span, .. } => {
                     if result_stack.is_empty() {
-                        return TokenStream::concat(result);
+                        return TokenStream::new(result);
                     }
                     let tree = TokenTree::Delimited(
                         span,
                         forest.delim,
-                        TokenStream::concat(result).into(),
+                        TokenStream::new(result).into(),
                     );
                     result = result_stack.pop().unwrap();
                     result.push(tree.into());
index 1a4de59cce63ba7d2affb43f0af5c800d825df50..4eca0c942f34e2af6b236038556106803cd6ac02 100644 (file)
@@ -400,9 +400,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // Allows `#[repr(packed)]` attribute on structs.
     (active, repr_packed, "1.26.0", Some(33158), None),
 
-    // Allows `use path as _;` and `extern crate c as _;`.
-    (active, underscore_imports, "1.26.0", Some(48216), None),
-
     // Allows macro invocations in `extern {}` blocks.
     (active, macros_in_extern, "1.27.0", Some(49476), None),
 
@@ -694,6 +691,8 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     (accepted, self_struct_ctor, "1.32.0", Some(51994), None),
     // `Self` in type definitions (RFC 2300)
     (accepted, self_in_typedefs, "1.32.0", Some(49303), None),
+    // `use path as _;` and `extern crate c as _;`
+    (accepted, underscore_imports, "1.33.0", Some(48216), None),
 );
 
 // If you change this, please modify `src/doc/unstable-book` as well. You must
@@ -1547,26 +1546,8 @@ fn visit_name(&mut self, sp: Span, name: ast::Name) {
         }
     }
 
-    fn visit_use_tree(&mut self, use_tree: &'a ast::UseTree, id: NodeId, _nested: bool) {
-        if let ast::UseTreeKind::Simple(Some(ident), ..) = use_tree.kind {
-            if ident.name == "_" {
-                gate_feature_post!(&self, underscore_imports, use_tree.span,
-                                   "renaming imports with `_` is unstable");
-            }
-        }
-
-        visit::walk_use_tree(self, use_tree, id);
-    }
-
     fn visit_item(&mut self, i: &'a ast::Item) {
         match i.node {
-            ast::ItemKind::ExternCrate(_) => {
-                if i.ident.name == "_" {
-                    gate_feature_post!(&self, underscore_imports, i.span,
-                                       "renaming extern crates with `_` is unstable");
-                }
-            }
-
             ast::ItemKind::Static(..) |
             ast::ItemKind::Const(_,_) => {
                 if i.ident.name == "_" {
index 0c24c20554acc35dc1656b45d8451a51e08b99e0..1fa11a4d6c856a3467bc3867bc1a91472e8db51f 100644 (file)
@@ -145,12 +145,6 @@ pub mod util {
     #[cfg(test)]
     pub mod parser_testing;
     pub mod move_map;
-
-    mod rc_slice;
-    pub use self::rc_slice::RcSlice;
-
-    mod rc_vec;
-    pub use self::rc_vec::RcVec;
 }
 
 pub mod json;
index 4ff6048e821787693269ef053f496fe4ad50ef44..1bd0656846bcea90ebddb47a26b56e74e9ff06d5 100644 (file)
@@ -170,7 +170,7 @@ fn parse_attribute_with_inner_parse_policy(&mut self,
                     token::CloseDelim(_) | token::Eof => self.unexpected()?,
                     _ => self.parse_token_tree(),
                 };
-                TokenStream::concat(vec![eq.into(), tree.into()])
+                TokenStream::new(vec![eq.into(), tree.into()])
             } else {
                 TokenStream::empty()
             };
index 86c87cf898d09615eabcf1c990e6f508648aa98f..0906c25cab36103e9d38ec30541d6eaabba1ad3b 100644 (file)
@@ -22,7 +22,7 @@ impl<'a> StringReader<'a> {
             tts.push(self.parse_token_tree()?);
         }
 
-        Ok(TokenStream::concat(tts))
+        Ok(TokenStream::new(tts))
     }
 
     // Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`.
@@ -30,14 +30,14 @@ fn parse_token_trees_until_close_delim(&mut self) -> TokenStream {
         let mut tts = vec![];
         loop {
             if let token::CloseDelim(..) = self.token {
-                return TokenStream::concat(tts);
+                return TokenStream::new(tts);
             }
 
             match self.parse_token_tree() {
                 Ok(tree) => tts.push(tree),
                 Err(mut e) => {
                     e.emit();
-                    return TokenStream::concat(tts);
+                    return TokenStream::new(tts);
                 }
             }
         }
index 10c451e1f81994463e049b1919ab510c80b32c2b..e3cccacb3c3db9343d138227091df9cc2278d163 100644 (file)
@@ -863,13 +863,13 @@ fn string_to_tts_1() {
         with_globals(|| {
             let tts = string_to_stream("fn a (b : i32) { b; }".to_string());
 
-            let expected = TokenStream::concat(vec![
+            let expected = TokenStream::new(vec![
                 TokenTree::Token(sp(0, 2), token::Ident(Ident::from_str("fn"), false)).into(),
                 TokenTree::Token(sp(3, 4), token::Ident(Ident::from_str("a"), false)).into(),
                 TokenTree::Delimited(
                     DelimSpan::from_pair(sp(5, 6), sp(13, 14)),
                     token::DelimToken::Paren,
-                    TokenStream::concat(vec![
+                    TokenStream::new(vec![
                         TokenTree::Token(sp(6, 7),
                                          token::Ident(Ident::from_str("b"), false)).into(),
                         TokenTree::Token(sp(8, 9), token::Colon).into(),
@@ -880,7 +880,7 @@ fn string_to_tts_1() {
                 TokenTree::Delimited(
                     DelimSpan::from_pair(sp(15, 16), sp(20, 21)),
                     token::DelimToken::Brace,
-                    TokenStream::concat(vec![
+                    TokenStream::new(vec![
                         TokenTree::Token(sp(17, 18),
                                          token::Ident(Ident::from_str("b"), false)).into(),
                         TokenTree::Token(sp(18, 19), token::Semi).into(),
index a4326d9ba47be03f8a4bf099cbeb4196602f0d40..a672a08a15a85cac21c4b5b9acbab13a7673359b 100644 (file)
@@ -2939,7 +2939,7 @@ pub fn parse_tokens(&mut self) -> TokenStream {
                 _ => result.push(self.parse_token_tree().into()),
             }
         }
-        TokenStream::concat(result)
+        TokenStream::new(result)
     }
 
     /// Parse a prefix-unary-operator expr
@@ -4635,7 +4635,7 @@ fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility, lo: Span)
                         self.unexpected()?;
                         unreachable!()
                     };
-                    TokenStream::concat(vec![
+                    TokenStream::new(vec![
                         args.into(),
                         TokenTree::Token(token_lo.to(self.prev_span), token::FatArrow).into(),
                         body.into(),
index 90191c54126d112f396cb8ceb40f40f24c17bf0f..c11ef33f931d8ab94a82ba8ceca62795333595f1 100644 (file)
@@ -28,8 +28,8 @@
 use parse::Directory;
 use parse::token::{self, DelimToken, Token};
 use print::pprust;
+use rustc_data_structures::sync::Lrc;
 use serialize::{Decoder, Decodable, Encoder, Encodable};
-use util::RcVec;
 
 use std::borrow::Cow;
 use std::{fmt, iter, mem};
@@ -123,7 +123,7 @@ pub fn eq_token(&self, t: Token) -> bool {
     }
 
     pub fn joint(self) -> TokenStream {
-        TokenStream { kind: TokenStreamKind::JointTree(self) }
+        TokenStream::JointTree(self)
     }
 
     /// Returns the opening delimiter as a token tree.
@@ -154,65 +154,57 @@ pub fn close_tt(span: Span, delim: DelimToken) -> TokenTree {
 /// instead of a representation of the abstract syntax tree.
 /// Today's `TokenTree`s can still contain AST via `Token::Interpolated` for back-compat.
 #[derive(Clone, Debug)]
-pub struct TokenStream {
-    kind: TokenStreamKind,
+pub enum TokenStream {
+    Empty,
+    Tree(TokenTree),
+    JointTree(TokenTree),
+    Stream(Lrc<Vec<TokenStream>>),
 }
 
 // `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 40);
+static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 32);
 
 impl TokenStream {
     /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
     /// separating the two arguments with a comma for diagnostic suggestions.
     pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> {
         // Used to suggest if a user writes `foo!(a b);`
-        if let TokenStreamKind::Stream(ref slice) = self.kind {
+        if let TokenStream::Stream(ref stream) = self {
             let mut suggestion = None;
-            let mut iter = slice.iter().enumerate().peekable();
+            let mut iter = stream.iter().enumerate().peekable();
             while let Some((pos, ts)) = iter.next() {
                 if let Some((_, next)) = iter.peek() {
-                    let sp = match (&ts.kind, &next.kind) {
-                        (TokenStreamKind::Tree(TokenTree::Token(_, token::Token::Comma)), _) |
-                        (_, TokenStreamKind::Tree(TokenTree::Token(_, token::Token::Comma))) => {
+                    let sp = match (&ts, &next) {
+                        (TokenStream::Tree(TokenTree::Token(_, token::Token::Comma)), _) |
+                        (_, TokenStream::Tree(TokenTree::Token(_, token::Token::Comma))) => {
                             continue;
                         }
-                        (TokenStreamKind::Tree(TokenTree::Token(sp, _)), _) => *sp,
-                        (TokenStreamKind::Tree(TokenTree::Delimited(sp, ..)), _) => sp.entire(),
+                        (TokenStream::Tree(TokenTree::Token(sp, _)), _) => *sp,
+                        (TokenStream::Tree(TokenTree::Delimited(sp, ..)), _) => sp.entire(),
                         _ => continue,
                     };
                     let sp = sp.shrink_to_hi();
-                    let comma = TokenStream {
-                        kind: TokenStreamKind::Tree(TokenTree::Token(sp, token::Comma)),
-                    };
+                    let comma = TokenStream::Tree(TokenTree::Token(sp, token::Comma));
                     suggestion = Some((pos, comma, sp));
                 }
             }
             if let Some((pos, comma, sp)) = suggestion {
-                let mut new_slice = vec![];
-                let parts = slice.split_at(pos + 1);
-                new_slice.extend_from_slice(parts.0);
-                new_slice.push(comma);
-                new_slice.extend_from_slice(parts.1);
-                let slice = RcVec::new(new_slice);
-                return Some((TokenStream { kind: TokenStreamKind::Stream(slice) }, sp));
+                let mut new_stream = vec![];
+                let parts = stream.split_at(pos + 1);
+                new_stream.extend_from_slice(parts.0);
+                new_stream.push(comma);
+                new_stream.extend_from_slice(parts.1);
+                return Some((TokenStream::new(new_stream), sp));
             }
         }
         None
     }
 }
 
-#[derive(Clone, Debug)]
-enum TokenStreamKind {
-    Empty,
-    Tree(TokenTree),
-    JointTree(TokenTree),
-    Stream(RcVec<TokenStream>),
-}
-
 impl From<TokenTree> for TokenStream {
     fn from(tt: TokenTree) -> TokenStream {
-        TokenStream { kind: TokenStreamKind::Tree(tt) }
+        TokenStream::Tree(tt)
     }
 }
 
@@ -224,29 +216,29 @@ fn from(token: Token) -> TokenStream {
 
 impl<T: Into<TokenStream>> iter::FromIterator<T> for TokenStream {
     fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
-        TokenStream::concat(iter.into_iter().map(Into::into).collect::<Vec<_>>())
+        TokenStream::new(iter.into_iter().map(Into::into).collect::<Vec<_>>())
     }
 }
 
 impl Extend<TokenStream> for TokenStream {
     fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, iter: I) {
         let iter = iter.into_iter();
-        let kind = mem::replace(&mut self.kind, TokenStreamKind::Empty);
+        let this = mem::replace(self, TokenStream::Empty);
 
         // Vector of token streams originally in self.
-        let tts: Vec<TokenStream> = match kind {
-            TokenStreamKind::Empty => {
+        let tts: Vec<TokenStream> = match this {
+            TokenStream::Empty => {
                 let mut vec = Vec::new();
                 vec.reserve(iter.size_hint().0);
                 vec
             }
-            TokenStreamKind::Tree(_) | TokenStreamKind::JointTree(_) => {
+            TokenStream::Tree(_) | TokenStream::JointTree(_) => {
                 let mut vec = Vec::new();
                 vec.reserve(1 + iter.size_hint().0);
-                vec.push(TokenStream { kind });
+                vec.push(this);
                 vec
             }
-            TokenStreamKind::Stream(rc_vec) => match RcVec::try_unwrap(rc_vec) {
+            TokenStream::Stream(rc_vec) => match Lrc::try_unwrap(rc_vec) {
                 Ok(mut vec) => {
                     // Extend in place using the existing capacity if possible.
                     // This is the fast path for libraries like `quote` that
@@ -273,12 +265,7 @@ fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, iter: I) {
         // Build the resulting token stream. If it contains more than one token,
         // preserve capacity in the vector in anticipation of the caller
         // performing additional calls to extend.
-        let mut tts = builder.0;
-        *self = match tts.len() {
-            0 => TokenStream::empty(),
-            1 => tts.pop().unwrap(),
-            _ => TokenStream::concat_rc_vec(RcVec::new_preserving_capacity(tts)),
-        };
+        *self = TokenStream::new(builder.0);
     }
 }
 
@@ -292,7 +279,7 @@ fn eq(&self, other: &TokenStream) -> bool {
 
 impl TokenStream {
     pub fn len(&self) -> usize {
-        if let TokenStreamKind::Stream(ref slice) = self.kind {
+        if let TokenStream::Stream(ref slice) = self {
             slice.len()
         } else {
             0
@@ -300,28 +287,24 @@ pub fn len(&self) -> usize {
     }
 
     pub fn empty() -> TokenStream {
-        TokenStream { kind: TokenStreamKind::Empty }
+        TokenStream::Empty
     }
 
     pub fn is_empty(&self) -> bool {
-        match self.kind {
-            TokenStreamKind::Empty => true,
+        match self {
+            TokenStream::Empty => true,
             _ => false,
         }
     }
 
-    pub fn concat(mut streams: Vec<TokenStream>) -> TokenStream {
+    pub fn new(mut streams: Vec<TokenStream>) -> TokenStream {
         match streams.len() {
             0 => TokenStream::empty(),
             1 => streams.pop().unwrap(),
-            _ => TokenStream::concat_rc_vec(RcVec::new(streams)),
+            _ => TokenStream::Stream(Lrc::new(streams)),
         }
     }
 
-    fn concat_rc_vec(streams: RcVec<TokenStream>) -> TokenStream {
-        TokenStream { kind: TokenStreamKind::Stream(streams) }
-    }
-
     pub fn trees(&self) -> Cursor {
         self.clone().into_trees()
     }
@@ -383,9 +366,9 @@ fn semantic_tree(tree: &TokenTree) -> bool {
     /// Precondition: `self` consists of a single token tree.
     /// Returns true if the token tree is a joint operation w.r.t. `proc_macro::TokenNode`.
     pub fn as_tree(self) -> (TokenTree, bool /* joint? */) {
-        match self.kind {
-            TokenStreamKind::Tree(tree) => (tree, false),
-            TokenStreamKind::JointTree(tree) => (tree, true),
+        match self {
+            TokenStream::Tree(tree) => (tree, false),
+            TokenStream::JointTree(tree) => (tree, true),
             _ => unreachable!(),
         }
     }
@@ -395,43 +378,43 @@ pub fn map_enumerated<F: FnMut(usize, TokenTree) -> TokenTree>(self, mut f: F) -
         let mut result = Vec::new();
         let mut i = 0;
         while let Some(stream) = trees.next_as_stream() {
-            result.push(match stream.kind {
-                TokenStreamKind::Tree(tree) => f(i, tree).into(),
-                TokenStreamKind::JointTree(tree) => f(i, tree).joint(),
+            result.push(match stream {
+                TokenStream::Tree(tree) => f(i, tree).into(),
+                TokenStream::JointTree(tree) => f(i, tree).joint(),
                 _ => unreachable!()
             });
             i += 1;
         }
-        TokenStream::concat(result)
+        TokenStream::new(result)
     }
 
     pub fn map<F: FnMut(TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
         let mut trees = self.into_trees();
         let mut result = Vec::new();
         while let Some(stream) = trees.next_as_stream() {
-            result.push(match stream.kind {
-                TokenStreamKind::Tree(tree) => f(tree).into(),
-                TokenStreamKind::JointTree(tree) => f(tree).joint(),
+            result.push(match stream {
+                TokenStream::Tree(tree) => f(tree).into(),
+                TokenStream::JointTree(tree) => f(tree).joint(),
                 _ => unreachable!()
             });
         }
-        TokenStream::concat(result)
+        TokenStream::new(result)
     }
 
     fn first_tree_and_joint(&self) -> Option<(TokenTree, bool)> {
-        match self.kind {
-            TokenStreamKind::Empty => None,
-            TokenStreamKind::Tree(ref tree) => Some((tree.clone(), false)),
-            TokenStreamKind::JointTree(ref tree) => Some((tree.clone(), true)),
-            TokenStreamKind::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(),
+        match self {
+            TokenStream::Empty => None,
+            TokenStream::Tree(ref tree) => Some((tree.clone(), false)),
+            TokenStream::JointTree(ref tree) => Some((tree.clone(), true)),
+            TokenStream::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(),
         }
     }
 
     fn last_tree_if_joint(&self) -> Option<TokenTree> {
-        match self.kind {
-            TokenStreamKind::Empty | TokenStreamKind::Tree(..) => None,
-            TokenStreamKind::JointTree(ref tree) => Some(tree.clone()),
-            TokenStreamKind::Stream(ref stream) => stream.last().unwrap().last_tree_if_joint(),
+        match self {
+            TokenStream::Empty | TokenStream::Tree(..) => None,
+            TokenStream::JointTree(ref tree) => Some(tree.clone()),
+            TokenStream::Stream(ref stream) => stream.last().unwrap().last_tree_if_joint(),
         }
     }
 }
@@ -474,28 +457,28 @@ pub fn add<T: Into<TokenStream>>(mut self, stream: T) -> Self {
     }
 
     pub fn build(self) -> TokenStream {
-        TokenStream::concat(self.0)
+        TokenStream::new(self.0)
     }
 
     fn push_all_but_last_tree(&mut self, stream: &TokenStream) {
-        if let TokenStreamKind::Stream(ref streams) = stream.kind {
+        if let TokenStream::Stream(ref streams) = stream {
             let len = streams.len();
             match len {
                 1 => {}
                 2 => self.0.push(streams[0].clone().into()),
-                _ => self.0.push(TokenStream::concat_rc_vec(streams.sub_slice(0 .. len - 1))),
+                _ => self.0.push(TokenStream::new(streams[0 .. len - 1].to_vec())),
             }
             self.push_all_but_last_tree(&streams[len - 1])
         }
     }
 
     fn push_all_but_first_tree(&mut self, stream: &TokenStream) {
-        if let TokenStreamKind::Stream(ref streams) = stream.kind {
+        if let TokenStream::Stream(ref streams) = stream {
             let len = streams.len();
             match len {
                 1 => {}
                 2 => self.0.push(streams[1].clone().into()),
-                _ => self.0.push(TokenStream::concat_rc_vec(streams.sub_slice(1 .. len))),
+                _ => self.0.push(TokenStream::new(streams[1 .. len].to_vec())),
             }
             self.push_all_but_first_tree(&streams[0])
         }
@@ -515,13 +498,13 @@ enum CursorKind {
 
 #[derive(Clone)]
 struct StreamCursor {
-    stream: RcVec<TokenStream>,
+    stream: Lrc<Vec<TokenStream>>,
     index: usize,
-    stack: Vec<(RcVec<TokenStream>, usize)>,
+    stack: Vec<(Lrc<Vec<TokenStream>>, usize)>,
 }
 
 impl StreamCursor {
-    fn new(stream: RcVec<TokenStream>) -> Self {
+    fn new(stream: Lrc<Vec<TokenStream>>) -> Self {
         StreamCursor { stream: stream, index: 0, stack: Vec::new() }
     }
 
@@ -530,10 +513,10 @@ fn next_as_stream(&mut self) -> Option<TokenStream> {
             if self.index < self.stream.len() {
                 self.index += 1;
                 let next = self.stream[self.index - 1].clone();
-                match next.kind {
-                    TokenStreamKind::Tree(..) | TokenStreamKind::JointTree(..) => return Some(next),
-                    TokenStreamKind::Stream(stream) => self.insert(stream),
-                    TokenStreamKind::Empty => {}
+                match next {
+                    TokenStream::Tree(..) | TokenStream::JointTree(..) => return Some(next),
+                    TokenStream::Stream(stream) => self.insert(stream),
+                    TokenStream::Empty => {}
                 }
             } else if let Some((stream, index)) = self.stack.pop() {
                 self.stream = stream;
@@ -544,7 +527,7 @@ fn next_as_stream(&mut self) -> Option<TokenStream> {
         }
     }
 
-    fn insert(&mut self, stream: RcVec<TokenStream>) {
+    fn insert(&mut self, stream: Lrc<Vec<TokenStream>>) {
         self.stack.push((mem::replace(&mut self.stream, stream),
                          mem::replace(&mut self.index, 0)));
     }
@@ -554,8 +537,8 @@ impl Iterator for Cursor {
     type Item = TokenTree;
 
     fn next(&mut self) -> Option<TokenTree> {
-        self.next_as_stream().map(|stream| match stream.kind {
-            TokenStreamKind::Tree(tree) | TokenStreamKind::JointTree(tree) => tree,
+        self.next_as_stream().map(|stream| match stream {
+            TokenStream::Tree(tree) | TokenStream::JointTree(tree) => tree,
             _ => unreachable!()
         })
     }
@@ -563,11 +546,11 @@ fn next(&mut self) -> Option<TokenTree> {
 
 impl Cursor {
     fn new(stream: TokenStream) -> Self {
-        Cursor(match stream.kind {
-            TokenStreamKind::Empty => CursorKind::Empty,
-            TokenStreamKind::Tree(tree) => CursorKind::Tree(tree, false),
-            TokenStreamKind::JointTree(tree) => CursorKind::JointTree(tree, false),
-            TokenStreamKind::Stream(stream) => CursorKind::Stream(StreamCursor::new(stream)),
+        Cursor(match stream {
+            TokenStream::Empty => CursorKind::Empty,
+            TokenStream::Tree(tree) => CursorKind::Tree(tree, false),
+            TokenStream::JointTree(tree) => CursorKind::JointTree(tree, false),
+            TokenStream::Stream(stream) => CursorKind::Stream(StreamCursor::new(stream)),
         })
     }
 
@@ -590,7 +573,7 @@ pub fn insert(&mut self, stream: TokenStream) {
             _ if stream.is_empty() => return,
             CursorKind::Empty => *self = stream.trees(),
             CursorKind::Tree(_, consumed) | CursorKind::JointTree(_, consumed) => {
-                *self = TokenStream::concat(vec![self.original_stream(), stream]).trees();
+                *self = TokenStream::new(vec![self.original_stream(), stream]).trees();
                 if consumed {
                     self.next();
                 }
@@ -606,21 +589,21 @@ pub fn original_stream(&self) -> TokenStream {
             CursorKind::Empty => TokenStream::empty(),
             CursorKind::Tree(ref tree, _) => tree.clone().into(),
             CursorKind::JointTree(ref tree, _) => tree.clone().joint(),
-            CursorKind::Stream(ref cursor) => TokenStream::concat_rc_vec({
+            CursorKind::Stream(ref cursor) => TokenStream::Stream(
                 cursor.stack.get(0).cloned().map(|(stream, _)| stream)
                     .unwrap_or_else(|| cursor.stream.clone())
-            }),
+            ),
         }
     }
 
     pub fn look_ahead(&self, n: usize) -> Option<TokenTree> {
         fn look_ahead(streams: &[TokenStream], mut n: usize) -> Result<TokenTree, usize> {
             for stream in streams {
-                n = match stream.kind {
-                    TokenStreamKind::Tree(ref tree) | TokenStreamKind::JointTree(ref tree)
+                n = match stream {
+                    TokenStream::Tree(ref tree) | TokenStream::JointTree(ref tree)
                         if n == 0 => return Ok(tree.clone()),
-                    TokenStreamKind::Tree(..) | TokenStreamKind::JointTree(..) => n - 1,
-                    TokenStreamKind::Stream(ref stream) => match look_ahead(stream, n) {
+                    TokenStream::Tree(..) | TokenStream::JointTree(..) => n - 1,
+                    TokenStream::Stream(ref stream) => match look_ahead(stream, n) {
                         Ok(tree) => return Ok(tree),
                         Err(n) => n,
                     },
@@ -656,7 +639,7 @@ fn look_ahead(streams: &[TokenStream], mut n: usize) -> Result<TokenTree, usize>
 /// `ThinTokenStream` is smaller, but needs to allocate to represent a single `TokenTree`.
 /// We must use `ThinTokenStream` in `TokenTree::Delimited` to avoid infinite size due to recursion.
 #[derive(Debug, Clone)]
-pub struct ThinTokenStream(Option<RcVec<TokenStream>>);
+pub struct ThinTokenStream(Option<Lrc<Vec<TokenStream>>>);
 
 impl ThinTokenStream {
     pub fn stream(&self) -> TokenStream {
@@ -666,18 +649,18 @@ pub fn stream(&self) -> TokenStream {
 
 impl From<TokenStream> for ThinTokenStream {
     fn from(stream: TokenStream) -> ThinTokenStream {
-        ThinTokenStream(match stream.kind {
-            TokenStreamKind::Empty => None,
-            TokenStreamKind::Tree(tree) => Some(RcVec::new(vec![tree.into()])),
-            TokenStreamKind::JointTree(tree) => Some(RcVec::new(vec![tree.joint()])),
-            TokenStreamKind::Stream(stream) => Some(stream),
+        ThinTokenStream(match stream {
+            TokenStream::Empty => None,
+            TokenStream::Tree(tree) => Some(Lrc::new(vec![tree.into()])),
+            TokenStream::JointTree(tree) => Some(Lrc::new(vec![tree.joint()])),
+            TokenStream::Stream(stream) => Some(stream),
         })
     }
 }
 
 impl From<ThinTokenStream> for TokenStream {
     fn from(stream: ThinTokenStream) -> TokenStream {
-        stream.0.map(TokenStream::concat_rc_vec).unwrap_or_else(TokenStream::empty)
+        stream.0.map(TokenStream::Stream).unwrap_or_else(TokenStream::empty)
     }
 }
 
@@ -776,7 +759,7 @@ fn test_concat() {
             let test_res = string_to_ts("foo::bar::baz");
             let test_fst = string_to_ts("foo::bar");
             let test_snd = string_to_ts("::baz");
-            let eq_res = TokenStream::concat(vec![test_fst, test_snd]);
+            let eq_res = TokenStream::new(vec![test_fst, test_snd]);
             assert_eq!(test_res.trees().count(), 5);
             assert_eq!(eq_res.trees().count(), 5);
             assert_eq!(test_res.eq_unspanned(&eq_res), true);
diff --git a/src/libsyntax/util/rc_slice.rs b/src/libsyntax/util/rc_slice.rs
deleted file mode 100644 (file)
index 520b7a4..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-// 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::fmt;
-use std::ops::{Deref, Range};
-use rustc_data_structures::sync::Lrc;
-
-use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
-                                           HashStable};
-
-#[derive(Clone)]
-pub struct RcSlice<T> {
-    data: Lrc<Box<[T]>>,
-    offset: u32,
-    len: u32,
-}
-
-impl<T> RcSlice<T> {
-    pub fn new(vec: Vec<T>) -> Self {
-        RcSlice {
-            offset: 0,
-            len: vec.len() as u32,
-            data: Lrc::new(vec.into_boxed_slice()),
-        }
-    }
-
-    pub fn sub_slice(&self, range: Range<usize>) -> Self {
-        RcSlice {
-            data: self.data.clone(),
-            offset: self.offset + range.start as u32,
-            len: (range.end - range.start) as u32,
-        }
-    }
-}
-
-impl<T> Deref for RcSlice<T> {
-    type Target = [T];
-    fn deref(&self) -> &[T] {
-        &self.data[self.offset as usize .. (self.offset + self.len) as usize]
-    }
-}
-
-impl<T: fmt::Debug> fmt::Debug for RcSlice<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(self.deref(), f)
-    }
-}
-
-impl<CTX, T> HashStable<CTX> for RcSlice<T>
-    where T: HashStable<CTX>
-{
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut CTX,
-                                          hasher: &mut StableHasher<W>) {
-        (**self).hash_stable(hcx, hasher);
-    }
-}
diff --git a/src/libsyntax/util/rc_vec.rs b/src/libsyntax/util/rc_vec.rs
deleted file mode 100644 (file)
index 99fbce1..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-// 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::fmt;
-use std::ops::{Deref, Range};
-
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
-use rustc_data_structures::sync::Lrc;
-
-#[derive(Clone)]
-pub struct RcVec<T> {
-    data: Lrc<Vec<T>>,
-    offset: u32,
-    len: u32,
-}
-
-impl<T> RcVec<T> {
-    pub fn new(mut vec: Vec<T>) -> Self {
-        // By default, constructing RcVec from Vec gives it just enough capacity
-        // to hold the initial elements. Callers that anticipate needing to
-        // extend the vector may prefer RcVec::new_preserving_capacity.
-        vec.shrink_to_fit();
-        Self::new_preserving_capacity(vec)
-    }
-
-    pub fn new_preserving_capacity(vec: Vec<T>) -> Self {
-        RcVec {
-            offset: 0,
-            len: vec.len() as u32,
-            data: Lrc::new(vec),
-        }
-    }
-
-    pub fn sub_slice(&self, range: Range<usize>) -> Self {
-        RcVec {
-            data: self.data.clone(),
-            offset: self.offset + range.start as u32,
-            len: (range.end - range.start) as u32,
-        }
-    }
-
-    /// If this RcVec has exactly one strong reference, returns ownership of the
-    /// underlying vector. Otherwise returns self unmodified.
-    pub fn try_unwrap(self) -> Result<Vec<T>, Self> {
-        match Lrc::try_unwrap(self.data) {
-            // If no other RcVec shares ownership of this data.
-            Ok(mut vec) => {
-                // Drop any elements after our view of the data.
-                vec.truncate(self.offset as usize + self.len as usize);
-                // Drop any elements before our view of the data. Do this after
-                // the `truncate` so that elements past the end of our view do
-                // not need to be copied around.
-                vec.drain(..self.offset as usize);
-                Ok(vec)
-            }
-
-            // If the data is shared.
-            Err(data) => Err(RcVec { data, ..self }),
-        }
-    }
-}
-
-impl<T> Deref for RcVec<T> {
-    type Target = [T];
-    fn deref(&self) -> &[T] {
-        &self.data[self.offset as usize..(self.offset + self.len) as usize]
-    }
-}
-
-impl<T: fmt::Debug> fmt::Debug for RcVec<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(self.deref(), f)
-    }
-}
-
-impl<CTX, T> HashStable<CTX> for RcVec<T>
-where
-    T: HashStable<CTX>,
-{
-    fn hash_stable<W: StableHasherResult>(&self, hcx: &mut CTX, hasher: &mut StableHasher<W>) {
-        (**self).hash_stable(hcx, hasher);
-    }
-}
index a784eca10d2c1f09e65d67e16eca266485e1eac3..95185c8c801c765ac1072392d081d265af9fb310 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit a784eca10d2c1f09e65d67e16eca266485e1eac3
+Subproject commit 95185c8c801c765ac1072392d081d265af9fb310
index 1355c0377ce913eed566ae4d08f80689087cc095..2f8dc0d466fb4e8271169a1643c455450bec8d0a 100644 (file)
@@ -216,16 +216,11 @@ LLVMRustWriteArchive(char *Dst, size_t NumMembers,
       Members.push_back(std::move(*MOrErr));
     }
   }
+
   auto Result = writeArchive(Dst, Members, WriteSymbtab, Kind, true, false);
-#if LLVM_VERSION_GE(6, 0)
   if (!Result)
     return LLVMRustResult::Success;
   LLVMRustSetLastError(toString(std::move(Result)).c_str());
-#else
-  if (!Result.second)
-    return LLVMRustResult::Success;
-  LLVMRustSetLastError(Result.second.message().c_str());
-#endif
 
   return LLVMRustResult::Failure;
 }
index aa420bf6100c789a9ac31201b78ac896d1c44911..4d95368c00f1e5a9e171ef678489db717c0d3d59 100644 (file)
 
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/IR/AutoUpgrade.h"
 #include "llvm/IR/AssemblyAnnotationWriter.h"
+#include "llvm/IR/IntrinsicInst.h"
 #include "llvm/Support/CBindingWrapping.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
-
-#if LLVM_VERSION_GE(6, 0)
-#include "llvm/CodeGen/TargetSubtargetInfo.h"
-#include "llvm/IR/IntrinsicInst.h"
-#else
-#include "llvm/Target/TargetSubtargetInfo.h"
-#endif
-
 #include "llvm/Transforms/IPO/AlwaysInliner.h"
 #include "llvm/Transforms/IPO/FunctionImport.h"
 #include "llvm/Transforms/Utils/FunctionImportUtils.h"
@@ -198,13 +192,9 @@ GEN_SUBTARGETS
 
 extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM,
                                    const char *Feature) {
-#if LLVM_VERSION_GE(6, 0)
   TargetMachine *Target = unwrap(TM);
   const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
   return MCInfo->checkFeatures(std::string("+") + Feature);
-#else
-  return false;
-#endif
 }
 
 enum class LLVMRustCodeModel {
@@ -392,13 +382,9 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
     Options.ThreadModel = ThreadModel::Single;
   }
 
-#if LLVM_VERSION_GE(6, 0)
   Options.EmitStackSizeSection = EmitStackSizeSection;
 
   Optional<CodeModel::Model> CM;
-#else
-  CodeModel::Model CM = CodeModel::Model::Default;
-#endif
   if (RustCM != LLVMRustCodeModel::None)
     CM = fromRust(RustCM);
   TargetMachine *TM = TheTarget->createTargetMachine(
index b9a0b435d3e368a9ecd91f31a74497b898050ada..86c5dfcfb98277df0b886649e8e49c1f19a7f589 100644 (file)
@@ -297,11 +297,7 @@ extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
 // enable fpmath flag UnsafeAlgebra
 extern "C" void LLVMRustSetHasUnsafeAlgebra(LLVMValueRef V) {
   if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
-#if LLVM_VERSION_GE(6, 0)
     I->setFast(true);
-#else
-    I->setHasUnsafeAlgebra(true);
-#endif
   }
 }
 
@@ -1437,7 +1433,6 @@ LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
   return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN));
 }
 
-#if LLVM_VERSION_GE(6, 0)
 extern "C" LLVMValueRef
 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
     return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
@@ -1446,13 +1441,3 @@ extern "C" LLVMValueRef
 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
     return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
 }
-#else
-extern "C" LLVMValueRef
-LLVMRustBuildMinNum(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) {
-   return nullptr;
-}
-extern "C" LLVMValueRef
-LLVMRustBuildMaxNum(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) {
-   return nullptr;
-}
-#endif
index 9cf17c45e87a27af99f031d844aab242ca63f853..a268838de451550fe5518de5be28fbc00563be9c 100644 (file)
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2018-11-28
+2018-12-13
index 5e628c5120c619a22799187371f057ec41e06f87..3c0503db8439928e42c1175f0009c506fc874ae9 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 5e628c5120c619a22799187371f057ec41e06f87
+Subproject commit 3c0503db8439928e42c1175f0009c506fc874ae9
index 5061d9a915e2e9296fe462c750dc1f7f0a3a02ec..52bdb1b103afd0fec930686c894a485ce4105951 100644 (file)
@@ -10,7 +10,6 @@
 
 // compile-flags: -C no-prepopulate-passes
 // ignore-tidy-linelength
-// min-llvm-version 6.0
 
 #![crate_type = "lib"]
 #![feature(custom_attribute)]
index b146e106aa10406a59bc868b9b62dc152774fb6b..ebd436cc6478b94f721da754bfe78f149de40d35 100644 (file)
@@ -11,7 +11,6 @@
 // ignore-tidy-linelength
 // only-macos
 // no-system-llvm
-// min-llvm-version 6.0
 // compile-flags: -O
 
 #![crate_type = "rlib"]
index 3544786e2e60a651990a5bd66e1659dd62b11506..a6e633bf285ac6cf80939e7711ea60aec15cf6c7 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // compile-flags: -O
-// min-llvm-version 6.0
 
 #![crate_type = "lib"]
 
index 149547639440cf39187535a6d168bae4bad3f70b..f916c1a0640931ac614236a47b3827c9d9e73c34 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // compile-flags: -O
-// min-llvm-version 6.0
 
 #![crate_type="rlib"]
 
index 6c47bf3e321fbb3eb19afb6bb564f9d9f558f2f5..605a952e8ff051e85858a5efa5aead868dc882ef 100644 (file)
@@ -10,7 +10,6 @@
 
 // ignore-emscripten
 // ignore-tidy-linelength
-// min-llvm-version 6.0
 
 // compile-flags: -C no-prepopulate-passes
 
index 7b5b2e55e2949986fc9ffec3a7ee46acaa9a0ec5..6645778468cbed3dfd6ef8c907d0d88e24fb3b2c 100644 (file)
@@ -10,7 +10,6 @@
 
 // ignore-emscripten
 // ignore-tidy-linelength
-// min-llvm-version 6.0
 
 // compile-flags: -C no-prepopulate-passes
 
index abd1eb3e2cc7b061d16b054969534ea7a2614eb6..cb96a844341b7ffffd6e70991d072b15ae141d0d 100644 (file)
@@ -14,7 +14,6 @@
 // ignore-tidy-linelength
 // ignore-windows
 // ignore-macos
-// min-llvm-version 6.0
 
 // compile-flags: -g -C no-prepopulate-passes
 
index 17dc9f94fe19c80c4ed26e877e121b5b34e43c3e..397bc7efd633c8541568c482bf62c41603cdd3a7 100644 (file)
@@ -8,14 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(const_fn, const_let)]
 
 const X : usize = 2;
 
 const fn f(x: usize) -> usize {
     let mut sum = 0;
-    //~^ let bindings in constant functions are unstable
-    //~| statements in constant functions are unstable
     for i in 0..x {
         //~^ ERROR E0015
         //~| ERROR E0019
diff --git a/src/test/compile-fail/must_use-in-stdlib-traits.rs b/src/test/compile-fail/must_use-in-stdlib-traits.rs
new file mode 100644 (file)
index 0000000..4bb5c59
--- /dev/null
@@ -0,0 +1,47 @@
+#![deny(unused_must_use)]
+#![feature(futures_api, pin, arbitrary_self_types)]
+
+use std::iter::Iterator;
+use std::future::Future;
+
+use std::task::{Poll, LocalWaker};
+use std::pin::Pin;
+use std::unimplemented;
+
+struct MyFuture;
+
+impl Future for MyFuture {
+   type Output = u32;
+
+   fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<u32> {
+      Poll::Pending
+   }
+}
+
+fn iterator() -> impl Iterator {
+   std::iter::empty::<u32>()
+}
+
+fn future() -> impl Future {
+   MyFuture
+}
+
+fn square_fn_once() -> impl FnOnce(u32) -> u32 {
+   |x| x * x
+}
+
+fn square_fn_mut() -> impl FnMut(u32) -> u32 {
+   |x| x * x
+}
+
+fn square_fn() -> impl Fn(u32) -> u32 {
+   |x| x * x
+}
+
+fn main() {
+   iterator(); //~ ERROR unused implementer of `std::iter::Iterator` that must be used
+   future(); //~ ERROR unused implementer of `std::future::Future` that must be used
+   square_fn_once(); //~ ERROR unused implementer of `std::ops::FnOnce` that must be used
+   square_fn_mut(); //~ ERROR unused implementer of `std::ops::FnMut` that must be used
+   square_fn(); //~ ERROR unused implementer of `std::ops::Fn` that must be used
+}
diff --git a/src/test/mir-opt/match_test.rs b/src/test/mir-opt/match_test.rs
new file mode 100644 (file)
index 0000000..9bfb728
--- /dev/null
@@ -0,0 +1,85 @@
+// Make sure redundant testing paths in `match` expressions are sorted out.
+
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    let x = 3;
+    let b = true;
+
+    // When `(0..=10).contains(x) && !b`, we should jump to the last arm
+    // without testing two other candidates.
+    match x {
+        0..10 if b => 0,
+        10..=20 => 1,
+        -1 => 2,
+        _ => 3,
+    };
+}
+
+// END RUST SOURCE
+// START rustc.main.SimplifyCfg-initial.after.mir
+//    bb0: {
+//        ...
+//        _4 = Le(const 0i32, _1);
+//        switchInt(move _4) -> [false: bb10, otherwise: bb11];
+//    }
+//    bb1: {
+//        _3 = const 0i32;
+//        goto -> bb16;
+//    }
+//    bb2: {
+//        _3 = const 1i32;
+//        goto -> bb16;
+//    }
+//    bb3: {
+//        _3 = const 2i32;
+//        goto -> bb16;
+//    }
+//    bb4: {
+//        _3 = const 3i32;
+//        goto -> bb16;
+//    }
+//    bb5: {
+//        falseEdges -> [real: bb12, imaginary: bb6];
+//    }
+//    bb6: {
+//        falseEdges -> [real: bb2, imaginary: bb7];
+//    }
+//    bb7: {
+//        falseEdges -> [real: bb3, imaginary: bb8];
+//    }
+//    bb8: {
+//        falseEdges -> [real: bb4, imaginary: bb9];
+//    }
+//    bb9: {
+//        unreachable;
+//    }
+//    bb10: {
+//        _7 = Le(const 10i32, _1);
+//        switchInt(move _7) -> [false: bb14, otherwise: bb15];
+//    }
+//    bb11: {
+//        _5 = Lt(_1, const 10i32);
+//        switchInt(move _5) -> [false: bb10, otherwise: bb5];
+//    }
+//    bb12: {
+//        StorageLive(_6);
+//        _6 = _2;
+//        switchInt(move _6) -> [false: bb13, otherwise: bb1];
+//    }
+//    bb13: {
+//        falseEdges -> [real: bb8, imaginary: bb6];
+//    }
+//    bb14: {
+//        switchInt(_1) -> [-1i32: bb7, otherwise: bb8];
+//    }
+//    bb15: {
+//        _8 = Le(_1, const 20i32);
+//        switchInt(move _8) -> [false: bb14, otherwise: bb6];
+//    }
+//    bb16: {
+//        StorageDead(_6);
+//        ...
+//        return;
+//    }
+// END rustc.main.SimplifyCfg-initial.after.mir
diff --git a/src/test/mir-opt/simplify_cfg.rs b/src/test/mir-opt/simplify_cfg.rs
new file mode 100644 (file)
index 0000000..ef843f7
--- /dev/null
@@ -0,0 +1,54 @@
+// Test that the goto chain starting from bb0 is collapsed.
+
+fn main() {
+    loop {
+        if bar() {
+            break;
+        }
+    }
+}
+
+#[inline(never)]
+fn bar() -> bool {
+    true
+}
+
+// END RUST SOURCE
+// START rustc.main.SimplifyCfg-initial.before.mir
+//     bb0: {
+//         goto -> bb1;
+//     }
+//     bb1: {
+//         falseUnwind -> [real: bb3, cleanup: bb4];
+//     }
+//     ...
+//     bb11: {
+//         ...
+//         goto -> bb1;
+//     }
+// END rustc.main.SimplifyCfg-initial.before.mir
+// START rustc.main.SimplifyCfg-initial.after.mir
+//     bb0: {
+//         falseUnwind -> [real: bb1, cleanup: bb2];
+//     }
+//     ...
+//     bb5: {
+//         ...
+//         goto -> bb0;
+//     }
+// END rustc.main.SimplifyCfg-initial.after.mir
+// START rustc.main.SimplifyCfg-early-opt.before.mir
+//     bb0: {
+//         goto -> bb1;
+//     }
+//     bb1: {
+//         StorageLive(_2);
+//         _2 = const bar() -> bb3;
+//     }
+// END rustc.main.SimplifyCfg-early-opt.before.mir
+// START rustc.main.SimplifyCfg-early-opt.after.mir
+//     bb0: {
+//         StorageLive(_2);
+//         _2 = const bar() -> bb1;
+//     }
+// END rustc.main.SimplifyCfg-early-opt.after.mir
diff --git a/src/test/run-pass/ctfe/const-fn-destructuring-arg.rs b/src/test/run-pass/ctfe/const-fn-destructuring-arg.rs
deleted file mode 100644 (file)
index 88f0d07..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// run-pass
-#![allow(dead_code)]
-
-// test that certain things are disallowed in constant functions
-
-#![feature(const_fn, const_let)]
-
-// no destructuring
-const fn i((
-            a,
-            b
-           ): (u32, u32)) -> u32 {
-    a + b
-}
-
-fn main() {}
diff --git a/src/test/run-pass/issues/issue-33140.rs b/src/test/run-pass/issues/issue-33140.rs
new file mode 100644 (file)
index 0000000..08c6945
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright 2018 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(order_dependent_trait_objects)]
+
+trait Trait {
+    fn xyz() -> bool;
+}
+
+impl Trait for dyn Send + Sync {
+    fn xyz() -> bool { false }
+}
+
+impl Trait for dyn Sync + Send {
+    fn xyz() -> bool { true }
+}
+
+trait Trait2 {
+    fn uvw() -> bool;
+}
+
+impl Trait2 for dyn Send + Sync {
+    fn uvw() -> bool { false }
+}
+
+impl Trait2 for dyn Sync + Send + Sync {
+    fn uvw() -> bool { true }
+}
+
+struct Foo<T: ?Sized>(T);
+impl Foo<dyn Send + Sync> {
+    fn abc() -> bool {
+        false
+    }
+}
+
+impl Foo<dyn Sync + Send> {
+    fn abc() -> bool {
+        true
+    }
+}
+
+fn main() {
+    assert_eq!(<dyn Send+Sync>::xyz(), false);
+    assert_eq!(<dyn Sync+Send>::xyz(), true);
+    assert_eq!(<dyn Send+Sync>::uvw(), false);
+    assert_eq!(<dyn Sync+Send+Sync>::uvw(), true);
+    assert_eq!(<Foo<dyn Send+Sync>>::abc(), false);
+    assert_eq!(<Foo<dyn Sync+Send>>::abc(), true);
+}
diff --git a/src/test/run-pass/mir/mir_match_test.rs b/src/test/run-pass/mir/mir_match_test.rs
new file mode 100644 (file)
index 0000000..1f96d67
--- /dev/null
@@ -0,0 +1,83 @@
+#![feature(exclusive_range_pattern)]
+
+// run-pass
+
+fn main() {
+    let incl_range = |x, b| {
+        match x {
+            0..=5 if b => 0,
+            5..=10 if b => 1,
+            1..=4 if !b => 2,
+            _ => 3,
+        }
+    };
+    assert_eq!(incl_range(3, false), 2);
+    assert_eq!(incl_range(3, true), 0);
+    assert_eq!(incl_range(5, false), 3);
+    assert_eq!(incl_range(5, true), 0);
+
+    let excl_range = |x, b| {
+        match x {
+            0..5 if b => 0,
+            5..10 if b => 1,
+            1..4 if !b => 2,
+            _ => 3,
+        }
+    };
+    assert_eq!(excl_range(3, false), 2);
+    assert_eq!(excl_range(3, true), 0);
+    assert_eq!(excl_range(5, false), 3);
+    assert_eq!(excl_range(5, true), 1);
+
+    let incl_range_vs_const = |x, b| {
+        match x {
+            0..=5 if b => 0,
+            7 => 1,
+            3 => 2,
+            _ => 3,
+        }
+    };
+    assert_eq!(incl_range_vs_const(5, false), 3);
+    assert_eq!(incl_range_vs_const(5, true), 0);
+    assert_eq!(incl_range_vs_const(3, false), 2);
+    assert_eq!(incl_range_vs_const(3, true), 0);
+    assert_eq!(incl_range_vs_const(7, false), 1);
+    assert_eq!(incl_range_vs_const(7, true), 1);
+
+    let excl_range_vs_const = |x, b| {
+        match x {
+            0..5 if b => 0,
+            7 => 1,
+            3 => 2,
+            _ => 3,
+        }
+    };
+    assert_eq!(excl_range_vs_const(5, false), 3);
+    assert_eq!(excl_range_vs_const(5, true), 3);
+    assert_eq!(excl_range_vs_const(3, false), 2);
+    assert_eq!(excl_range_vs_const(3, true), 0);
+    assert_eq!(excl_range_vs_const(7, false), 1);
+    assert_eq!(excl_range_vs_const(7, true), 1);
+
+    let const_vs_incl_range = |x, b| {
+        match x {
+            3 if b => 0,
+            5..=7 => 2,
+            1..=4 => 1,
+            _ => 3,
+        }
+    };
+    assert_eq!(const_vs_incl_range(3, false), 1);
+    assert_eq!(const_vs_incl_range(3, true), 0);
+
+    let const_vs_excl_range = |x, b| {
+        match x {
+            3 if b => 0,
+            5..7 => 2,
+            1..4 => 1,
+            _ => 3,
+        }
+    };
+    assert_eq!(const_vs_excl_range(3, false), 1);
+    assert_eq!(const_vs_excl_range(3, true), 0);
+}
index 5f6a72a8e1e11705e2916e87d31df445e806704c..e5ac5775b0cb946b4e4c56c110ccd832e8fa9be7 100644 (file)
@@ -10,7 +10,6 @@
 
 // run-pass
 // ignore-emscripten
-// min-llvm-version 6.0
 
 // Test that the simd_{gather,scatter} intrinsics produce the correct results.
 
index 041286fe656a0d10a3154f5e34628cc530c284da..779c72b8df127bcf93e24ce41ec57c73fc102610 100644 (file)
@@ -8,11 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(stable_features)]
-// min-llvm-version 6.0
-// ^ needs MCSubtargetInfo::checkFeatures()
 // ignore-cloudabi no std::env
 
+#![allow(stable_features)]
 #![feature(cfg_target_feature)]
 
 use std::env;
diff --git a/src/test/rustdoc/comment-in-doctest.rs b/src/test/rustdoc/comment-in-doctest.rs
new file mode 100644 (file)
index 0000000..3468bb7
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2018 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:--test
+
+// comments, both doc comments and regular ones, used to trick rustdoc's doctest parser into
+// thinking that everything after it was part of the regular program. combined with the libsyntax
+// parser loop failing to detect the manual main function, it would wrap everything in `fn main`,
+// which would cause the doctest to fail as the "extern crate" declaration was no longer valid.
+// oddly enough, it would pass in 2018 if a crate was in the extern prelude. see
+// https://github.com/rust-lang/rust/issues/56727
+
+//! ```
+//! // crate: proc-macro-test
+//! //! this is a test
+//!
+//! // used to pull in proc-macro specific items
+//! extern crate proc_macro;
+//!
+//! use proc_macro::TokenStream;
+//!
+//! # fn main() {}
+//! ```
index 17722bf226d82992f403f2493ca45280f0f52743..6f72de0edee327be283d5389f05ea746f85fd5e7 100644 (file)
@@ -1,3 +1,31 @@
+warning[E0503]: cannot use `y` because it was mutably borrowed
+  --> $DIR/borrowck-anon-fields-variant.rs:27:7
+   |
+LL |       Foo::Y(ref mut a, _) => a,
+   |              --------- borrow of `y.0` occurs here
+...
+LL |       Foo::Y(_, ref mut b) => b,
+   |       ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
+...
+LL |     *a += 1;
+   |     ------- borrow later used here
+   |
+   = warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
+           It represents potential unsoundness in your code.
+           This warning will become a hard error in the future.
+
+error[E0503]: cannot use `y` because it was mutably borrowed
+  --> $DIR/borrowck-anon-fields-variant.rs:44:7
+   |
+LL |       Foo::Y(ref mut a, _) => a,
+   |              --------- borrow of `y.0` occurs here
+...
+LL |       Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow
+   |       ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
+...
+LL |     *a += 1;
+   |     ------- borrow later used here
+
 error[E0499]: cannot borrow `y.0` as mutable more than once at a time
   --> $DIR/borrowck-anon-fields-variant.rs:44:14
    |
@@ -10,6 +38,7 @@ LL |       Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow
 LL |     *a += 1;
    |     ------- first borrow later used here
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0499`.
+Some errors occurred: E0499, E0503.
+For more information about an error, try `rustc --explain E0499`.
index ef0de61d219adbbb91b553b34b405b54b315271f..63e5bcccf5d3488a3e7e10d8c523d541cfcac7a7 100644 (file)
@@ -24,7 +24,7 @@ unsafe impl Sync for Foo {}
 static FOO: Foo = Foo(UnsafeCell::new(42));
 
 static BAR: () = unsafe {
-    *FOO.0.get() = 5; //~ ERROR could not evaluate static initializer
+    *FOO.0.get() = 5; //~ ERROR contains unimplemented expression type
 };
 
 fn main() {}
index 0892b05a69df273ea05da0cba2433462b118c3e9..740954c6c66239bf92bda010b1e9c4645eeec5ae 100644 (file)
@@ -1,9 +1,9 @@
-error[E0080]: could not evaluate static initializer
+error[E0019]: static contains unimplemented expression type
   --> $DIR/assign-to-static-within-other-static-2.rs:27:5
    |
-LL |     *FOO.0.get() = 5; //~ ERROR could not evaluate static initializer
-   |     ^^^^^^^^^^^^^^^^ tried to modify a static's initial value from another static's initializer
+LL |     *FOO.0.get() = 5; //~ ERROR contains unimplemented expression type
+   |     ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0080`.
+For more information about this error, try `rustc --explain E0019`.
index 01fcc8307c0c11b55ad8b2bda635a018297cf729..6c2fdcc8615c893f89b60507b675c212268cb1bf 100644 (file)
@@ -27,9 +27,7 @@ fn foo() {}
 
 static BAR: () = unsafe {
     *FOO.0.get() = 5;
-    // we do not error on the above access, because that is not detectable statically. Instead,
-    // const evaluation will error when trying to evaluate it. Due to the error below, we never even
-    // attempt to const evaluate `BAR`, so we don't see the error
+    //~^ contains unimplemented expression
 
     foo();
     //~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants
index 01ad1fc9a21b9fac6164b2a5bf06b57e81ddbbae..49b39e2f5c6c933b115e25ec314cdec2a5ccf475 100644 (file)
@@ -1,9 +1,16 @@
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/mod-static-with-const-fn.rs:29:5
+   |
+LL |     *FOO.0.get() = 5;
+   |     ^^^^^^^^^^^^^^^^
+
 error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/mod-static-with-const-fn.rs:34:5
+  --> $DIR/mod-static-with-const-fn.rs:32:5
    |
 LL |     foo();
    |     ^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0015`.
+Some errors occurred: E0015, E0019.
+For more information about an error, try `rustc --explain E0015`.
index 30a738a83a3b67d2b769f8be34840c1c3cb02464..2f7e2ecaa4e40085336a7db5dc67b05d65e948bc 100644 (file)
@@ -37,15 +37,13 @@ const fn get_Y_addr() -> &'static u32 {
 }
 
 const fn get() -> u32 {
-    let x = 22;
-    //~^ ERROR let bindings in constant functions are unstable
-    //~| ERROR statements in constant functions are unstable
-    let y = 44;
-    //~^ ERROR let bindings in constant functions are unstable
-    //~| ERROR statements in constant functions are unstable
+    let x = 22; //~ ERROR let bindings in constant functions are unstable
+//~^ ERROR statements in constant functions
+    let y = 44; //~ ERROR let bindings in constant functions are unstable
+//~^ ERROR statements in constant functions
     x + y
-    //~^ ERROR let bindings in constant functions are unstable
-    //~| ERROR let bindings in constant functions are unstable
+//~^ ERROR let bindings in constant functions are unstable
+//~| ERROR let bindings in constant functions are unstable
 }
 
 fn main() {}
index 613670acc93264ede0300a5364baacd94f7fe917..1a8c5f558a212a305e8f49a908f55223e1bfa6a1 100644 (file)
@@ -19,7 +19,7 @@ LL |     &Y
 error[E0658]: let bindings in constant functions are unstable (see issue #48821)
   --> $DIR/const-fn-not-safe-for-const.rs:40:13
    |
-LL |     let x = 22;
+LL |     let x = 22; //~ ERROR let bindings in constant functions are unstable
    |             ^^
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
@@ -27,29 +27,29 @@ LL |     let x = 22;
 error[E0658]: statements in constant functions are unstable (see issue #48821)
   --> $DIR/const-fn-not-safe-for-const.rs:40:13
    |
-LL |     let x = 22;
+LL |     let x = 22; //~ ERROR let bindings in constant functions are unstable
    |             ^^
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
 
 error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-not-safe-for-const.rs:43:13
+  --> $DIR/const-fn-not-safe-for-const.rs:42:13
    |
-LL |     let y = 44;
+LL |     let y = 44; //~ ERROR let bindings in constant functions are unstable
    |             ^^
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
 
 error[E0658]: statements in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-not-safe-for-const.rs:43:13
+  --> $DIR/const-fn-not-safe-for-const.rs:42:13
    |
-LL |     let y = 44;
+LL |     let y = 44; //~ ERROR let bindings in constant functions are unstable
    |             ^^
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
 
 error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-not-safe-for-const.rs:46:5
+  --> $DIR/const-fn-not-safe-for-const.rs:44:5
    |
 LL |     x + y
    |     ^
@@ -57,7 +57,7 @@ LL |     x + y
    = help: add #![feature(const_let)] to the crate attributes to enable
 
 error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-not-safe-for-const.rs:46:9
+  --> $DIR/const-fn-not-safe-for-const.rs:44:9
    |
 LL |     x + y
    |         ^
index 83825456b5c61d9f732303cd858e69afdd6da34f..c2ed6cd85ab5c176b795a4ad4d8eba8453cbd8da 100644 (file)
@@ -8,6 +8,7 @@ struct S {
 impl S {
     const fn foo(&mut self, x: u32) {
         self.state = x;
+        //~^ contains unimplemented expression
     }
 }
 
index 7f9a953c10fe8ae8b9fe0190b3e5097751aa86a9..0f294616d255c3f73c7eba1f3b2687a53702427e 100644 (file)
@@ -1,9 +1,16 @@
+error[E0019]: constant function contains unimplemented expression type
+  --> $DIR/const_let_assign3.rs:10:9
+   |
+LL |         self.state = x;
+   |         ^^^^^^^^^^^^^^
+
 error[E0017]: references in constants may only refer to immutable values
-  --> $DIR/const_let_assign3.rs:16:5
+  --> $DIR/const_let_assign3.rs:17:5
    |
 LL |     s.foo(3); //~ ERROR references in constants may only refer to immutable values
    |     ^ constants require immutable values
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0017`.
+Some errors occurred: E0017, E0019.
+For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/consts/const_let_eq.rs b/src/test/ui/consts/const_let_eq.rs
new file mode 100644 (file)
index 0000000..8739cb8
--- /dev/null
@@ -0,0 +1,470 @@
+#![feature(const_let, const_fn)]
+
+// run-pass
+
+struct Foo<T>(T);
+struct Bar<T> { x: T }
+struct W(u32);
+struct A { a: u32 }
+
+const fn basics((a,): (u32,)) -> u32 {
+    // Deferred assignment:
+    let b: u32;
+    b = a + 1;
+
+    // Immediate assignment:
+    let c: u32 = b + 1;
+
+    // Mutables:
+    let mut d: u32 = c + 1;
+    d = d + 1;
+    // +4 so far.
+
+    // No effect statements work:
+    ; ;
+    1;
+
+    // Array projection
+    let mut arr: [u32; 1] = [0];
+    arr[0] = 1;
+    d = d + arr[0];
+    // +5
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(0);
+    let mut bar: Bar<u32> = Bar { x: 0 };
+    foo.0 = 1;
+    bar.x = 1;
+    d = d + foo.0 + bar.x;
+    // +7
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(0)];
+    arr[0].0 = 1;
+    d = d + arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 0 }];
+    arr[0].x = 1;
+    d = d + arr[0].x;
+    // +9
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([0]);
+    (arr.0)[0] = 1;
+    d = d + (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [0] };
+    arr.x[0] = 1;
+    d = d + arr.x[0];
+    // +11
+
+    d
+}
+
+const fn add_assign(W(a): W) -> u32 {
+    // Mutables:
+    let mut d: u32 = a + 1;
+    d += 1;
+    // +2 so far.
+
+    // Array projection
+    let mut arr: [u32; 1] = [0];
+    arr[0] += 1;
+    d += arr[0];
+    // +3
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(0);
+    let mut bar: Bar<u32> = Bar { x: 0 };
+    foo.0 += 1;
+    bar.x += 1;
+    d += foo.0 + bar.x;
+    // +5
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(0)];
+    arr[0].0 += 1;
+    d += arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 0 }];
+    arr[0].x += 1;
+    d += arr[0].x;
+    // +7
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([0]);
+    (arr.0)[0] += 1;
+    d += (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [0] };
+    arr.x[0] += 1;
+    d += arr.x[0];
+    // +9
+
+    d
+}
+
+const fn mul_assign(A { a }: A) -> u32 {
+    // Mutables:
+    let mut d: u32 = a + 1;
+    d *= 2;
+    // 2^1 * (a + 1)
+
+    // Array projection
+    let mut arr: [u32; 1] = [1];
+    arr[0] *= 2;
+    d *= arr[0];
+    // 2^2 * (a + 1)
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(1);
+    let mut bar: Bar<u32> = Bar { x: 1 };
+    foo.0 *= 2;
+    bar.x *= 2;
+    d *= foo.0 + bar.x;
+    // 2^4 * (a + 1)
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(1)];
+    arr[0].0 *= 2;
+    d *= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 1 }];
+    arr[0].x *= 2;
+    d *= arr[0].x;
+    // 2^6 * (a + 1)
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([1]);
+    (arr.0)[0] *= 2;
+    d *= (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [1] };
+    arr.x[0] *= 2;
+    d *= arr.x[0];
+    // 2^8 * (a + 1)
+
+    d
+}
+
+const fn div_assign(a: [u32; 1]) -> u32 {
+    let a = a[0];
+    // Mutables:
+    let mut d: u32 = 1024 * a;
+    d /= 2;
+    // 512
+
+    // Array projection
+    let mut arr: [u32; 1] = [4];
+    arr[0] /= 2;
+    d /= arr[0];
+    // 256
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(4);
+    let mut bar: Bar<u32> = Bar { x: 4 };
+    foo.0 /= 2;
+    bar.x /= 2;
+    d /= foo.0;
+    d /= bar.x;
+    // 64
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(4)];
+    arr[0].0 /= 2;
+    d /= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 4 }];
+    arr[0].x /= 2;
+    d /= arr[0].x;
+    // 16
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([4]);
+    (arr.0)[0] /= 2;
+    d /= (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [4] };
+    arr.x[0] /= 2;
+    d /= arr.x[0];
+    // 4
+
+    d
+}
+
+const fn rem_assign(W(a): W) -> u32 {
+    // Mutables:
+    let mut d: u32 = a;
+    d %= 10;
+    d += 10;
+
+    // Array projection
+    let mut arr: [u32; 1] = [3];
+    arr[0] %= 2;
+    d %= 9 + arr[0];
+    d += 10;
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(5);
+    let mut bar: Bar<u32> = Bar { x: 7 };
+    foo.0 %= 2;
+    bar.x %= 2;
+    d %= 8 + foo.0 + bar.x;
+    d += 10;
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(4)];
+    arr[0].0 %= 3;
+    d %= 9 + arr[0].0;
+    d += 10;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 7 }];
+    arr[0].x %= 3;
+    d %= 9 + arr[0].x;
+    d += 10;
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([6]);
+    (arr.0)[0] %= 5;
+    d %= 9 + (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [11] };
+    arr.x[0] %= 5;
+    d %= 9 + arr.x[0];
+
+    d
+}
+
+const fn sub_assign(W(a): W) -> u32 {
+    // Mutables:
+    let mut d: u32 = a;
+    d -= 1;
+
+    // Array projection
+    let mut arr: [u32; 1] = [2];
+    arr[0] -= 1;
+    d -= arr[0];
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(2);
+    let mut bar: Bar<u32> = Bar { x: 2 };
+    foo.0 -= 1;
+    bar.x -= 1;
+    d -= foo.0 + bar.x;
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(2)];
+    arr[0].0 -= 1;
+    d -= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 2 }];
+    arr[0].x -= 1;
+    d -= arr[0].x;
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([2]);
+    (arr.0)[0] -= 1;
+    d -= (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [2] };
+    arr.x[0] -= 1;
+    d -= arr.x[0];
+
+    d
+}
+
+const fn shl_assign(W(a): W) -> u32 {
+    // Mutables:
+    let mut d: u32 = a;
+    d <<= 1; // 10
+
+    // Array projection
+    let mut arr: [u32; 1] = [1];
+    arr[0] <<= 1;
+    d <<= arr[0]; // 10 << 2
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(1);
+    let mut bar: Bar<u32> = Bar { x: 1 };
+    foo.0 <<= 1;
+    bar.x <<= 1;
+    d <<= foo.0 + bar.x; // 1000 << 4
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(1)];
+    arr[0].0 <<= 1;
+    d <<= arr[0].0; // 1000_0000 << 2
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 1 }];
+    arr[0].x <<= 1;
+    d <<= arr[0].x; // 1000_0000_00 << 2
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([1]);
+    (arr.0)[0] <<= 1;
+    d <<= (arr.0)[0]; // 1000_0000_0000 << 2
+    let mut arr: Bar<[u32; 1]> = Bar { x: [1] };
+    arr.x[0] <<= 1;
+    d <<= arr.x[0]; // 1000_0000_0000_00 << 2
+
+    d
+}
+
+const fn shr_assign(W(a): W) -> u32 {
+    // Mutables:
+    let mut d: u32 = a;
+    d >>= 1; // /= 2
+
+    // Array projection
+    let mut arr: [u32; 1] = [2];
+    arr[0] >>= 1;
+    d >>= arr[0]; // /= 4
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(2);
+    let mut bar: Bar<u32> = Bar { x: 2 };
+    foo.0 >>= 1;
+    bar.x >>= 1;
+    d >>= foo.0 + bar.x; // /= 16
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(2)];
+    arr[0].0 >>= 1;
+    d >>= arr[0].0; // /= 32
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 2 }];
+    arr[0].x >>= 1;
+    d >>= arr[0].x; // /= 64
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([2]);
+    (arr.0)[0] >>= 1;
+    d >>= (arr.0)[0]; // /= 128
+    let mut arr: Bar<[u32; 1]> = Bar { x: [2] };
+    arr.x[0] >>= 1;
+    d >>= arr.x[0]; // /= 256
+
+    d
+}
+
+const fn bit_and_assign(W(a): W) -> u32 {
+    let f = 0b1111_1111_1111_1111;
+
+    // Mutables:
+    let mut d: u32 = a;
+    d &= 0b1111_1111_1111_1110;
+
+    // Array projection
+    let mut arr: [u32; 1] = [f];
+    arr[0] &= 0b1111_1111_1111_1101;
+    d &= arr[0];
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(f);
+    let mut bar: Bar<u32> = Bar { x: f };
+    foo.0 &= 0b1111_1111_1111_0111;
+    bar.x &= 0b1111_1111_1101_1111;
+    d &= foo.0 & bar.x;
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(f)];
+    arr[0].0 &= 0b1111_1110_1111_1111;
+    d &= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: f }];
+    arr[0].x &= 0b1111_1101_1111_1111;
+    d &= arr[0].x;
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([f]);
+    (arr.0)[0] &= 0b1011_1111_1111_1111;
+    d &= (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [f] };
+    arr.x[0] &= 0b0111_1111_1111_1111;
+    d &= arr.x[0];
+
+    d
+}
+
+const fn bit_or_assign(W(a): W) -> u32 {
+    let f = 0b0000_0000_0000_0000;
+
+    // Mutables:
+    let mut d: u32 = a;
+    d |= 0b0000_0000_0000_0001;
+
+    // Array projection
+    let mut arr: [u32; 1] = [f];
+    arr[0] |= 0b0000_0000_0000_1001;
+    d |= arr[0];
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(f);
+    let mut bar: Bar<u32> = Bar { x: f };
+    foo.0 |= 0b0000_0000_0001_0000;
+    bar.x |= 0b0000_0000_0100_0000;
+    d |= foo.0 | bar.x;
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(f)];
+    arr[0].0 |= 0b0000_0001_0000_0000;
+    d |= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: f }];
+    arr[0].x |= 0b0000_0010_0000_0000;
+    d |= arr[0].x;
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([f]);
+    (arr.0)[0] |= 0b1000_0000_0000_0000;
+    d |= (arr.0)[0]; // /= 128
+    let mut arr: Bar<[u32; 1]> = Bar { x: [f] };
+    arr.x[0] |= 0b1100_0000_0000_0000;
+    d |= arr.x[0]; // /= 256
+
+    d
+}
+
+const fn bit_xor_assign(W(a): W) -> u32 {
+    let f = 0b0000_0000_0000_0000;
+
+    // Mutables:
+    let mut d: u32 = a;
+    d ^= 0b0000_0000_0000_0001;
+
+    // Array projection
+    let mut arr: [u32; 1] = [f];
+    arr[0] ^= 0b0000_0000_0000_0010;
+    d ^= arr[0];
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(f);
+    let mut bar: Bar<u32> = Bar { x: f };
+    foo.0 ^= 0b0000_0000_0001_0000;
+    bar.x ^= 0b0000_0000_1000_0000;
+    d ^= foo.0 ^ bar.x;
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(f)];
+    arr[0].0 ^= 0b0000_0001_0000_0000;
+    d ^= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: f }];
+    arr[0].x ^= 0b0000_0010_0000_0000;
+    d ^= arr[0].x;
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([f]);
+    (arr.0)[0] ^= 0b0100_0000_0000_0000;
+    d ^= (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [f] };
+    arr.x[0] ^= 0b1000_0000_0000_0000;
+    d ^= arr.x[0];
+
+    d
+}
+
+macro_rules! test {
+    ($c:ident, $e:expr, $r:expr) => {
+        const $c: u32 = $e;
+        assert_eq!($c, $r);
+        assert_eq!($e, $r);
+    }
+}
+
+fn main() {
+    test!(BASICS, basics((2,)), 13);
+    test!(ADD, add_assign(W(1)), 10);
+    test!(MUL, mul_assign(A { a: 0 }), 256);
+    test!(DIV, div_assign([1]), 4);
+    test!(REM, rem_assign(W(5)), 5);
+    test!(SUB, sub_assign(W(8)), 0);
+    test!(SHL, shl_assign(W(1)), 0b1000_0000_0000_0000);
+    test!(SHR, shr_assign(W(256)), 1);
+    test!(AND, bit_and_assign(W(0b1011_1111_1111_1111_1111)), 0b0011_1100_1101_0100);
+    test!(OR, bit_or_assign(W(0b1011_0000_0000_0000)), 0b1111_0011_0101_1001);
+    test!(XOR, bit_xor_assign(W(0b0000_0000_0000_0000)), 0b1100_0011_1001_0011);
+}
diff --git a/src/test/ui/consts/const_let_eq_float.rs b/src/test/ui/consts/const_let_eq_float.rs
new file mode 100644 (file)
index 0000000..2c7262d
--- /dev/null
@@ -0,0 +1,279 @@
+// compile-pass
+
+#![feature(const_let, const_fn)]
+
+struct Foo<T>(T);
+struct Bar<T> { x: T }
+struct W(f32);
+struct A { a: f32 }
+
+const fn basics((a,): (f32,)) -> f32 {
+    // Deferred assignment:
+    let b: f32;
+    b = a + 1.0;
+
+    // Immediate assignment:
+    let c: f32 = b + 1.0;
+
+    // Mutables:
+    let mut d: f32 = c + 1.0;
+    d = d + 1.0;
+    // +4 so far.
+
+    // No effect statements work:
+    ; ;
+    1;
+
+    // Array projection
+    let mut arr: [f32; 1] = [0.0];
+    arr[0] = 1.0;
+    d = d + arr[0];
+    // +5
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(0.0);
+    let mut bar: Bar<f32> = Bar { x: 0.0 };
+    foo.0 = 1.0;
+    bar.x = 1.0;
+    d = d + foo.0 + bar.x;
+    // +7
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(0.0)];
+    arr[0].0 = 1.0;
+    d = d + arr[0].0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 0.0 }];
+    arr[0].x = 1.0;
+    d = d + arr[0].x;
+    // +9
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([0.0]);
+    (arr.0)[0] = 1.0;
+    d = d + (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [0.0] };
+    arr.x[0] = 1.0;
+    d = d + arr.x[0];
+    // +11
+
+    d
+}
+
+const fn add_assign(W(a): W) -> f32 {
+    // Mutables:
+    let mut d: f32 = a + 1.0;
+    d += 1.0;
+    // +2 so far.
+
+    // Array projection
+    let mut arr: [f32; 1] = [0.0];
+    arr[0] += 1.0;
+    d += arr[0];
+    // +3
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(0.0);
+    let mut bar: Bar<f32> = Bar { x: 0.0 };
+    foo.0 += 1.0;
+    bar.x += 1.0;
+    d += foo.0 + bar.x;
+    // +5
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(0.0)];
+    arr[0].0 += 1.0;
+    d += arr[0].0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 0.0 }];
+    arr[0].x += 1.0;
+    d += arr[0].x;
+    // +7
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([0.0]);
+    (arr.0)[0] += 1.0;
+    d += (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [0.0] };
+    arr.x[0] += 1.0;
+    d += arr.x[0];
+    // +9
+
+    d
+}
+
+const fn mul_assign(A { a }: A) -> f32 {
+    // Mutables:
+    let mut d: f32 = a + 1.0;
+    d *= 2.0;
+    // 2^1 * (a + 1)
+
+    // Array projection
+    let mut arr: [f32; 1] = [1.0];
+    arr[0] *= 2.0;
+    d *= arr[0];
+    // 2^2 * (a + 1)
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(1.0);
+    let mut bar: Bar<f32> = Bar { x: 1.0 };
+    foo.0 *= 2.0;
+    bar.x *= 2.0;
+    d *= foo.0 + bar.x;
+    // 2^4 * (a + 1)
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(1.0)];
+    arr[0].0 *= 2.0;
+    d *= arr[0].0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 1.0 }];
+    arr[0].x *= 2.0;
+    d *= arr[0].x;
+    // 2^6 * (a + 1)
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([1.0]);
+    (arr.0)[0] *= 2.0;
+    d *= (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [1.0] };
+    arr.x[0] *= 2.0;
+    d *= arr.x[0];
+    // 2^8 * (a + 1)
+
+    d
+}
+
+const fn div_assign(a: [f32; 1]) -> f32 {
+    let a = a[0];
+    // Mutables:
+    let mut d: f32 = 1024.0 * a;
+    d /= 2.0;
+    // 512
+
+    // Array projection
+    let mut arr: [f32; 1] = [4.0];
+    arr[0] /= 2.0;
+    d /= arr[0];
+    // 256
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(4.0);
+    let mut bar: Bar<f32> = Bar { x: 4.0 };
+    foo.0 /= 2.0;
+    bar.x /= 2.0;
+    d /= foo.0;
+    d /= bar.x;
+    // 64
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(4.0)];
+    arr[0].0 /= 2.0;
+    d /= arr[0].0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 4.0 }];
+    arr[0].x /= 2.0;
+    d /= arr[0].x;
+    // 16
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([4.0]);
+    (arr.0)[0] /= 2.0;
+    d /= (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [4.0] };
+    arr.x[0] /= 2.0;
+    d /= arr.x[0];
+    // 4
+
+    d
+}
+
+const fn rem_assign(W(a): W) -> f32 {
+    // Mutables:
+    let mut d: f32 = a;
+    d %= 10.0;
+    d += 10.0;
+
+    // Array projection
+    let mut arr: [f32; 1] = [3.0];
+    arr[0] %= 2.0;
+    d %= 9.0 + arr[0];
+    d += 10.0;
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(5.0);
+    let mut bar: Bar<f32> = Bar { x: 7.0 };
+    foo.0 %= 2.0;
+    bar.x %= 2.0;
+    d %= 8.0 + foo.0 + bar.x;
+    d += 10.0;
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(4.0)];
+    arr[0].0 %= 3.0;
+    d %= 9.0 + arr[0].0;
+    d += 10.0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 7.0 }];
+    arr[0].x %= 3.0;
+    d %= 9.0 + arr[0].x;
+    d += 10.0;
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([6.0]);
+    (arr.0)[0] %= 5.0;
+    d %= 9.0 + (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [11.0] };
+    arr.x[0] %= 5.0;
+    d %= 9.0 + arr.x[0];
+
+    d
+}
+
+const fn sub_assign(W(a): W) -> f32 {
+    // Mutables:
+    let mut d: f32 = a;
+    d -= 1.0;
+
+    // Array projection
+    let mut arr: [f32; 1] = [2.0];
+    arr[0] -= 1.0;
+    d -= arr[0];
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(2.0);
+    let mut bar: Bar<f32> = Bar { x: 2.0 };
+    foo.0 -= 1.0;
+    bar.x -= 1.0;
+    d -= foo.0 + bar.x;
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(2.0)];
+    arr[0].0 -= 1.0;
+    d -= arr[0].0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 2.0 }];
+    arr[0].x -= 1.0;
+    d -= arr[0].x;
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([2.0]);
+    (arr.0)[0] -= 1.0;
+    d -= (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [2.0] };
+    arr.x[0] -= 1.0;
+    d -= arr.x[0];
+
+    d
+}
+
+macro_rules! test {
+    ($c:ident, $e:expr, $r:expr) => {
+        const $c: f32 = $e;
+        assert_eq!($c, $r);
+        assert_eq!($e, $r);
+    }
+}
+
+fn main() {
+    test!(BASICS, basics((2.0,)), 13.0);
+    test!(ADD, add_assign(W(1.0)), 10.0);
+    test!(MUL, mul_assign(A { a: 0.0 }), 256.0);
+    test!(DIV, div_assign([1.0]), 4.0);
+    test!(REM, rem_assign(W(5.0)), 5.0);
+    test!(SUB, sub_assign(W(8.0)), 0.0);
+}
diff --git a/src/test/ui/consts/const_short_circuit.rs b/src/test/ui/consts/const_short_circuit.rs
new file mode 100644 (file)
index 0000000..cc49e46
--- /dev/null
@@ -0,0 +1,16 @@
+#![feature(underscore_const_names, const_let)]
+
+const _: bool = false && false;
+const _: bool = true && false;
+const _: bool = {
+    let mut x = true && false;
+    //~^ ERROR new features like let bindings are not permitted
+    x
+};
+const _: bool = {
+    let x = true && false;
+    //~^ ERROR new features like let bindings are not permitted
+    x
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/const_short_circuit.stderr b/src/test/ui/consts/const_short_circuit.stderr
new file mode 100644 (file)
index 0000000..a67bb0b
--- /dev/null
@@ -0,0 +1,26 @@
+error: new features like let bindings are not permitted in constants which also use short circuiting operators
+  --> $DIR/const_short_circuit.rs:6:9
+   |
+LL |     let mut x = true && false;
+   |         ^^^^^
+   |
+note: use of `&&` operator here does not actually short circuit due to the const evaluator presently not being able to do control flow. See https://github.com/rust-lang/rust/issues/49146 for more information.
+  --> $DIR/const_short_circuit.rs:6:22
+   |
+LL |     let mut x = true && false;
+   |                      ^^
+
+error: new features like let bindings are not permitted in constants which also use short circuiting operators
+  --> $DIR/const_short_circuit.rs:11:9
+   |
+LL |     let x = true && false;
+   |         ^
+   |
+note: use of `&&` operator here does not actually short circuit due to the const evaluator presently not being able to do control flow. See https://github.com/rust-lang/rust/issues/49146 for more information.
+  --> $DIR/const_short_circuit.rs:11:18
+   |
+LL |     let x = true && false;
+   |                  ^^
+
+error: aborting due to 2 previous errors
+
index f43befb37c134ad72629ffde0c713f995dc34081..6c4e9e0a067d7dcf74c6249fa1b49e2a5808d3b0 100644 (file)
@@ -115,7 +115,7 @@ LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
 error: local variables in const fn are unstable
   --> $DIR/min_const_fn.rs:109:34
    |
-LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn
    |                                  ^
 
 error: `if`, `match`, `&&` and `||` are not stable in const fn
index 43ca9e75393095255de640fd75327cae146ab6c1..ad983da4df9d81a6a71df9846b0b285ec04a5849 100644 (file)
@@ -106,7 +106,7 @@ const fn foo30_2(x: *mut u32) -> usize { x as usize }
 const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
 //~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
 const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
-const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn
 const fn foo36(a: bool, b: bool) -> bool { a && b }
 //~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
 const fn foo37(a: bool, b: bool) -> bool { a || b }
index bcb9be6e5485eff485765fc077d4b9a2e78e1110..a93a4f817fc14d1aaeaaeca770572a81e5889287 100644 (file)
@@ -115,7 +115,7 @@ LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
 error: local variables in const fn are unstable
   --> $DIR/min_const_fn.rs:109:34
    |
-LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn
    |                                  ^
 
 error: `if`, `match`, `&&` and `||` are not stable in const fn
index f11b43dcd865ce54e407a2c7a5f537acebcdc818..92e99c6228a9b853e471dc5d3257146e3808e758 100644 (file)
@@ -28,13 +28,13 @@ const fn call_unsafe_generic_cell_const_fn() -> *const Vec<std::cell::Cell<u32>>
     unsafe { ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() }
     //~^ ERROR calls to `const unsafe fn` in const fns
 }
-const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x }
 //~^ dereferencing raw pointers in constant functions
 
 fn main() {}
 
 const unsafe fn no_union() {
     union Foo { x: (), y: () }
-    Foo { x: () }.y //~ ERROR not allowed in const fn
+    Foo { x: () }.y
     //~^ unions in const fn
 }
index 922a7883b9f2d3b4e933c2a8ae9efdedbd910d7b..fafc89d1493685e1619b21729acec88de921ad7f 100644 (file)
@@ -1,7 +1,7 @@
 error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
   --> $DIR/min_const_fn_unsafe.rs:31:59
    |
-LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x }
    |                                                           ^^
    |
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
@@ -9,7 +9,7 @@ LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR no
 error[E0658]: unions in const fn are unstable (see issue #51909)
   --> $DIR/min_const_fn_unsafe.rs:38:5
    |
-LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
+LL |     Foo { x: () }.y
    |     ^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_fn_union)] to the crate attributes to enable
@@ -38,24 +38,6 @@ LL |     unsafe { ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() }
    |
    = help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable
 
-error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe.rs:31:59
-   |
-LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
-   |                                                           ^^ dereference of raw pointer
-   |
-   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: access to union field is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe.rs:38:5
-   |
-LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
-   |     ^^^^^^^^^^^^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: aborting due to 7 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 8a6884bc6b93c3207e5c09b4ff2cc942834c5cdb..67a48206126421f973e497d0c1ad2eae03dda04b 100644 (file)
@@ -34,29 +34,28 @@ const fn foo10() -> *const Vec<std::cell::Cell<u32>> {
 const unsafe fn foo10_3() -> *const Vec<std::cell::Cell<u32>> {
     unsafe { foo6::<Vec<std::cell::Cell<u32>>>() }
 }
-// not ok
 const unsafe fn foo8_2() -> i32 {
-    foo4() //~ ERROR not allowed in const fn
+    foo4()
 }
 const unsafe fn foo9_2() -> *const String {
-    foo5::<String>() //~ ERROR not allowed in const fn
+    foo5::<String>()
 }
 const unsafe fn foo10_2() -> *const Vec<std::cell::Cell<u32>> {
-    foo6::<Vec<std::cell::Cell<u32>>>() //~ ERROR not allowed in const fn
+    foo6::<Vec<std::cell::Cell<u32>>>()
 }
-const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+const unsafe fn foo30_3(x: *mut usize) -> usize { *x }
 //~^ dereferencing raw pointers in constant functions
 
-const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } //~ ERROR not allowed in const fn
+const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x }
 //~^ dereferencing raw pointers in constant functions
 
-const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ ERROR not allowed
+const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
 //~^ dereferencing raw pointers in constant functions
 
 fn main() {}
 
 const unsafe fn no_union() {
     union Foo { x: (), y: () }
-    Foo { x: () }.y //~ ERROR not allowed in const fn
+    Foo { x: () }.y
     //~^ unions in const fn
 }
index 20c75afbe638b81478c0cb9dfb3ab6b00e9fd363..63bf9a53e509cc7a908b2813d23c5d92b00bbdd8 100644 (file)
@@ -1,97 +1,44 @@
 error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:47:51
+  --> $DIR/min_const_fn_unsafe_feature_gate.rs:46:51
    |
-LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x }
    |                                                   ^^
    |
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
 error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:50:60
+  --> $DIR/min_const_fn_unsafe_feature_gate.rs:49:60
    |
-LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } //~ ERROR not allowed in const fn
+LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x }
    |                                                            ^^^
    |
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
 error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:53:62
+  --> $DIR/min_const_fn_unsafe_feature_gate.rs:52:62
    |
-LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ ERROR not allowed
+LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
    |                                                              ^^^
    |
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
 error[E0658]: unions in const fn are unstable (see issue #51909)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:60:5
+  --> $DIR/min_const_fn_unsafe_feature_gate.rs:59:5
    |
-LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
+LL |     Foo { x: () }.y
    |     ^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_fn_union)] to the crate attributes to enable
 
-error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:39:5
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/min_const_fn_unsafe_feature_gate.rs:52:62
    |
-LL |     foo4() //~ ERROR not allowed in const fn
-   |     ^^^^^^ call to unsafe function
-   |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:42:5
-   |
-LL |     foo5::<String>() //~ ERROR not allowed in const fn
-   |     ^^^^^^^^^^^^^^^^ call to unsafe function
-   |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:45:5
-   |
-LL |     foo6::<Vec<std::cell::Cell<u32>>>() //~ ERROR not allowed in const fn
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
-   |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:47:51
-   |
-LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
-   |                                                   ^^ dereference of raw pointer
-   |
-   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:50:60
-   |
-LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } //~ ERROR not allowed in const fn
-   |                                                            ^^^ dereference of raw pointer
-   |
-   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:53:62
-   |
-LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ ERROR not allowed
+LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
    |                                                              ^^^ dereference of raw pointer
    |
    = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
-error: access to union field is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:60:5
-   |
-LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
-   |     ^^^^^^^^^^^^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: aborting due to 11 previous errors
+error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
+Some errors occurred: E0133, E0658.
+For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/consts/min_const_fn/mutable_borrow.rs b/src/test/ui/consts/min_const_fn/mutable_borrow.rs
new file mode 100644 (file)
index 0000000..3dd76b6
--- /dev/null
@@ -0,0 +1,17 @@
+const fn mutable_ref_in_const() -> u8 {
+    let mut a = 0; //~ ERROR local variables in const fn
+    let b = &mut a;
+    *b
+}
+
+struct X;
+
+impl X {
+    const fn inherent_mutable_ref_in_const() -> u8 {
+        let mut a = 0; //~ ERROR local variables in const fn
+        let b = &mut a;
+        *b
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/mutable_borrow.stderr b/src/test/ui/consts/min_const_fn/mutable_borrow.stderr
new file mode 100644 (file)
index 0000000..fa46f5c
--- /dev/null
@@ -0,0 +1,14 @@
+error: local variables in const fn are unstable
+  --> $DIR/mutable_borrow.rs:2:9
+   |
+LL |     let mut a = 0; //~ ERROR local variables in const fn
+   |         ^^^^^
+
+error: local variables in const fn are unstable
+  --> $DIR/mutable_borrow.rs:11:13
+   |
+LL |         let mut a = 0; //~ ERROR local variables in const fn
+   |             ^^^^^
+
+error: aborting due to 2 previous errors
+
index 34e8eaba9f28f6ba91d96425eb73470958218e9b..5863429a2f2c5ddd19ad6e7efc57eb130582155f 100644 (file)
@@ -7,6 +7,7 @@
     {
         let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
         unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
+        //~^ contains unimplemented expression
     }
     &{a}
 };
index d5252f199beac10bf42384c0e212c2b948574d7f..cc3635a979b370f792afd0c1e34da3b5a3141daa 100644 (file)
@@ -4,6 +4,12 @@ error[E0017]: references in constants may only refer to immutable values
 LL |         let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
    |                           ^^^^^^ constants require immutable values
 
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/projection_qualif.rs:9:18
+   |
+LL |         unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
+   |                  ^^^^^^
+
 error[E0658]: dereferencing raw pointers in constants is unstable (see issue #51911)
   --> $DIR/projection_qualif.rs:9:18
    |
@@ -12,7 +18,7 @@ LL |         unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constant
    |
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
-Some errors occurred: E0017, E0658.
+Some errors occurred: E0017, E0019, E0658.
 For more information about an error, try `rustc --explain E0017`.
index 67a41bc5dc4addaa52b0efeeb9612c3b3f1ebb8d..79dde3c18e8fa995ed58414fb85beb8dec9a39b1 100644 (file)
@@ -2,6 +2,14 @@ enum Foo {
     Prob,
 }
 
+const FOO: u32 = match Foo::Prob {
+    Foo::Prob => 42, //~ ERROR unimplemented expression type
+};
+
+const BAR: u32 = match Foo::Prob {
+    x => 42, //~ ERROR unimplemented expression type
+};
+
 impl Foo {
     pub const fn as_val(&self) -> u8 {
         use self::Foo::*;
index a0222b0d489a465c33d3441e4e99f59ebb54f281..f5c2cb5e0e9dcb95931e6e7d07a0cea6f4ac8967 100644 (file)
@@ -1,8 +1,21 @@
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/single_variant_match_ice.rs:6:5
+   |
+LL |     Foo::Prob => 42, //~ ERROR unimplemented expression type
+   |     ^^^^^^^^^
+
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/single_variant_match_ice.rs:10:5
+   |
+LL |     x => 42, //~ ERROR unimplemented expression type
+   |     ^
+
 error: `if`, `match`, `&&` and `||` are not stable in const fn
-  --> $DIR/single_variant_match_ice.rs:10:13
+  --> $DIR/single_variant_match_ice.rs:18:13
    |
 LL |             Prob => 0x1, //~ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
    |             ^^^^
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0019`.
diff --git a/src/test/ui/deprecation/deprecation-in-future.rs b/src/test/ui/deprecation/deprecation-in-future.rs
new file mode 100644 (file)
index 0000000..c6c6017
--- /dev/null
@@ -0,0 +1,12 @@
+// ignore-tidy-linelength
+
+#![deny(deprecated_in_future)]
+
+#[deprecated(since = "99.99.99", note = "text")]
+pub fn deprecated_future() {}
+
+fn test() {
+    deprecated_future(); //~ ERROR use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text
+}
+
+fn main() {}
diff --git a/src/test/ui/deprecation/deprecation-in-future.stderr b/src/test/ui/deprecation/deprecation-in-future.stderr
new file mode 100644 (file)
index 0000000..38392cf
--- /dev/null
@@ -0,0 +1,14 @@
+error: use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text
+  --> $DIR/deprecation-in-future.rs:9:5
+   |
+LL |     deprecated_future(); //~ ERROR use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text
+   |     ^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/deprecation-in-future.rs:3:9
+   |
+LL | #![deny(deprecated_in_future)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/extern/auxiliary/invalid-utf8.txt b/src/test/ui/extern/auxiliary/invalid-utf8.txt
new file mode 100644 (file)
index 0000000..dc1115b
--- /dev/null
@@ -0,0 +1 @@
+Ã(
\ No newline at end of file
index 5c6f6e49b3d77f9bcec8d825ca8206ea434e8bff..e17dda65568e9139d6cdcdf190f990f3a103f25b 100644 (file)
@@ -2,7 +2,31 @@
 
 #![feature(external_doc)]
 
-#[doc(include = "not-a-file.md")] //~ ERROR: couldn't read
-pub struct SomeStruct;
+#[doc(include = "not-a-file.md")]
+pub struct SomeStruct; //~^ ERROR couldn't read
+                       //~| HELP external doc paths are relative to the crate root
+
+#[doc(include = "auxiliary/invalid-utf8.txt")]
+pub struct InvalidUtf8; //~^ ERROR wasn't a utf-8 file
+
+#[doc(include)]
+pub struct MissingPath; //~^ ERROR expected path
+                        //~| HELP provide a file path with `=`
+                        //~| SUGGESTION include = "<path>"
+
+#[doc(include("../README.md"))]
+pub struct InvalidPathSyntax; //~^ ERROR expected path
+                              //~| HELP provide a file path with `=`
+                              //~| SUGGESTION include = "../README.md"
+
+#[doc(include = 123)]
+pub struct InvalidPathType; //~^ ERROR expected path
+                            //~| HELP provide a file path with `=`
+                            //~| SUGGESTION include = "<path>"
+
+#[doc(include(123))]
+pub struct InvalidPathSyntaxAndType; //~^ ERROR expected path
+                                     //~| HELP provide a file path with `=`
+                                     //~| SUGGESTION include = "<path>"
 
 fn main() {}
index 5cc7551ee03aa253732711a91bae481c4f956c99..a3be3277de5455691be7259c318e267e9262a3c2 100644 (file)
@@ -1,8 +1,40 @@
 error: couldn't read $DIR/not-a-file.md: $FILE_NOT_FOUND_MSG (os error 2)
-  --> $DIR/external-doc-error.rs:5:1
+  --> $DIR/external-doc-error.rs:5:17
    |
-LL | #[doc(include = "not-a-file.md")] //~ ERROR: couldn't read
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[doc(include = "not-a-file.md")]
+   |                 ^^^^^^^^^^^^^^^ couldn't read file
+   |
+   = help: external doc paths are relative to the crate root
+
+error: $DIR/auxiliary/invalid-utf8.txt wasn't a utf-8 file
+  --> $DIR/external-doc-error.rs:9:17
+   |
+LL | #[doc(include = "auxiliary/invalid-utf8.txt")]
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ contains invalid utf-8
+
+error: expected path to external documentation
+  --> $DIR/external-doc-error.rs:12:7
+   |
+LL | #[doc(include)]
+   |       ^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
+
+error: expected path to external documentation
+  --> $DIR/external-doc-error.rs:17:7
+   |
+LL | #[doc(include("../README.md"))]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "../README.md"`
+
+error: expected path to external documentation
+  --> $DIR/external-doc-error.rs:22:7
+   |
+LL | #[doc(include = 123)]
+   |       ^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
+
+error: expected path to external documentation
+  --> $DIR/external-doc-error.rs:27:7
+   |
+LL | #[doc(include(123))]
+   |       ^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
 
-error: aborting due to previous error
+error: aborting due to 6 previous errors
 
index 05d02e62bc8710d44876e3286780808c2eb68538..9bf957a5f1e05988a3f0de479442d264e8f86000 100644 (file)
 
 // Test use of const let without feature gate.
 
-#![feature(const_fn)]
+const FOO: usize = {
+    //~^ ERROR statements in constants are unstable
+    //~| ERROR: let bindings in constants are unstable
+    let x = 42;
+    //~^ ERROR statements in constants are unstable
+    //~| ERROR: let bindings in constants are unstable
+    42
+};
 
-const fn foo() -> usize {
+static BAR: usize = {
+    //~^ ERROR statements in statics are unstable
+    //~| ERROR: let bindings in statics are unstable
     let x = 42;
-    //~^ ERROR statements in constant functions are unstable
-    //~| ERROR: let bindings in constant functions are unstable
+    //~^ ERROR statements in statics are unstable
+    //~| ERROR: let bindings in statics are unstable
     42
-}
+};
 
 fn main() {}
index 6a7f6255678ff2ac117e1ec1481a7107accfe926..acb5165918e2a6caefb6236e83adcd7548f8fd5f 100644 (file)
@@ -1,4 +1,4 @@
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
+error[E0658]: let bindings in constants are unstable (see issue #48821)
   --> $DIR/feature-gate-const_let.rs:16:13
    |
 LL |     let x = 42;
@@ -6,7 +6,7 @@ LL |     let x = 42;
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
 
-error[E0658]: statements in constant functions are unstable (see issue #48821)
+error[E0658]: statements in constants are unstable (see issue #48821)
   --> $DIR/feature-gate-const_let.rs:16:13
    |
 LL |     let x = 42;
@@ -14,6 +14,78 @@ LL |     let x = 42;
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
 
-error: aborting due to 2 previous errors
+error[E0658]: let bindings in constants are unstable (see issue #48821)
+  --> $DIR/feature-gate-const_let.rs:13:1
+   |
+LL | / const FOO: usize = {
+LL | |     //~^ ERROR statements in constants are unstable
+LL | |     //~| ERROR: let bindings in constants are unstable
+LL | |     let x = 42;
+...  |
+LL | |     42
+LL | | };
+   | |__^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/feature-gate-const_let.rs:13:1
+   |
+LL | / const FOO: usize = {
+LL | |     //~^ ERROR statements in constants are unstable
+LL | |     //~| ERROR: let bindings in constants are unstable
+LL | |     let x = 42;
+...  |
+LL | |     42
+LL | | };
+   | |__^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in statics are unstable (see issue #48821)
+  --> $DIR/feature-gate-const_let.rs:25:13
+   |
+LL |     let x = 42;
+   |             ^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in statics are unstable (see issue #48821)
+  --> $DIR/feature-gate-const_let.rs:25:13
+   |
+LL |     let x = 42;
+   |             ^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in statics are unstable (see issue #48821)
+  --> $DIR/feature-gate-const_let.rs:22:1
+   |
+LL | / static BAR: usize = {
+LL | |     //~^ ERROR statements in statics are unstable
+LL | |     //~| ERROR: let bindings in statics are unstable
+LL | |     let x = 42;
+...  |
+LL | |     42
+LL | | };
+   | |__^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in statics are unstable (see issue #48821)
+  --> $DIR/feature-gate-const_let.rs:22:1
+   |
+LL | / static BAR: usize = {
+LL | |     //~^ ERROR statements in statics are unstable
+LL | |     //~| ERROR: let bindings in statics are unstable
+LL | |     let x = 42;
+...  |
+LL | |     42
+LL | | };
+   | |__^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-underscore-imports.rs b/src/test/ui/feature-gates/feature-gate-underscore-imports.rs
deleted file mode 100644 (file)
index ceb8afe..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2018 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.
-
-extern crate std as _; //~ ERROR renaming extern crates with `_` is unstable
-use std::vec as _; //~ ERROR renaming imports with `_` is unstable
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-underscore-imports.stderr b/src/test/ui/feature-gates/feature-gate-underscore-imports.stderr
deleted file mode 100644 (file)
index 2eea952..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0658]: renaming extern crates with `_` is unstable (see issue #48216)
-  --> $DIR/feature-gate-underscore-imports.rs:11:1
-   |
-LL | extern crate std as _; //~ ERROR renaming extern crates with `_` is unstable
-   | ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(underscore_imports)] to the crate attributes to enable
-
-error[E0658]: renaming imports with `_` is unstable (see issue #48216)
-  --> $DIR/feature-gate-underscore-imports.rs:12:5
-   |
-LL | use std::vec as _; //~ ERROR renaming imports with `_` is unstable
-   |     ^^^^^^^^^^^^^
-   |
-   = help: add #![feature(underscore_imports)] to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-33140.rs b/src/test/ui/issues/issue-33140.rs
new file mode 100644 (file)
index 0000000..fef5a82
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(order_dependent_trait_objects)]
+
+trait Trait {
+    fn xyz() -> bool;
+}
+
+impl Trait for dyn Send + Sync {
+    fn xyz() -> bool { false }
+}
+
+impl Trait for dyn Sync + Send {
+//~^ ERROR conflicting implementations
+//~| hard error
+    fn xyz() -> bool { true }
+}
+
+trait Trait2 {
+    fn uvw() -> bool;
+}
+
+impl Trait2 for dyn Send + Sync {
+    fn uvw() -> bool { false }
+}
+
+impl Trait2 for dyn Sync + Send + Sync {
+//~^ ERROR conflicting implementations
+//~| hard error
+    fn uvw() -> bool { true }
+}
+
+struct Foo<T: ?Sized>(T);
+impl Foo<dyn Send + Sync> {
+    fn abc() -> bool { //~ ERROR duplicate definitions with name `abc`
+                       //~| hard error
+        false
+    }
+}
+
+impl Foo<dyn Sync + Send> {
+    fn abc() -> bool {
+        true
+    }
+}
+
+fn main() {
+    assert_eq!(<Send+Sync>::xyz(), false);
+    assert_eq!(<Sync+Send>::xyz(), true);
+    assert_eq!(<Send+Sync>::uvw(), false);
+    assert_eq!(<Sync+Send+Sync>::uvw(), true);
+    assert_eq!(<Foo<Send+Sync>>::abc(), false);
+    assert_eq!(<Foo<Sync+Send>>::abc(), true);
+}
diff --git a/src/test/ui/issues/issue-33140.stderr b/src/test/ui/issues/issue-33140.stderr
new file mode 100644 (file)
index 0000000..240137f
--- /dev/null
@@ -0,0 +1,48 @@
+error: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/issue-33140.rs:21:1
+   |
+LL | impl Trait for dyn Send + Sync {
+   | ------------------------------ first implementation here
+...
+LL | impl Trait for dyn Sync + Send {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+note: lint level defined here
+  --> $DIR/issue-33140.rs:11:9
+   |
+LL | #![deny(order_dependent_trait_objects)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/issue-33140.rs:35:1
+   |
+LL | impl Trait2 for dyn Send + Sync {
+   | ------------------------------- first implementation here
+...
+LL | impl Trait2 for dyn Sync + Send + Sync {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: duplicate definitions with name `abc` (E0592)
+  --> $DIR/issue-33140.rs:43:5
+   |
+LL | /     fn abc() -> bool { //~ ERROR duplicate definitions with name `abc`
+LL | |                        //~| hard error
+LL | |         false
+LL | |     }
+   | |_____^ duplicate definitions for `abc`
+...
+LL | /     fn abc() -> bool {
+LL | |         true
+LL | |     }
+   | |_____- other definition for `abc`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: aborting due to 3 previous errors
+
index af1f6ef5ed4ac041b9390958671d159c4593f269..a2f40b3f5396c2f48461809aa96ae1b502108071 100644 (file)
@@ -8,15 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
-
 const fn x() {
-    let t = true;
-    //~^ ERROR let bindings in constant functions are unstable
-    //~| ERROR statements in constant functions are unstable
+    let t = true; //~ ERROR local variables in const fn
     let x = || t;
-    //~^ ERROR let bindings in constant functions are unstable
-    //~| ERROR statements in constant functions are unstable
 }
 
 fn main() {}
index 7468510de6a33231c6b2ac407132c9137a64f716..5a7d1ad043ee47a0cbd2aaf51ac0869d87481cf5 100644 (file)
@@ -1,35 +1,8 @@
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/issue-37550.rs:14:13
+error: local variables in const fn are unstable
+  --> $DIR/issue-37550.rs:12:9
    |
-LL |     let t = true;
-   |             ^^^^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constant functions are unstable (see issue #48821)
-  --> $DIR/issue-37550.rs:14:13
-   |
-LL |     let t = true;
-   |             ^^^^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/issue-37550.rs:17:13
-   |
-LL |     let x = || t;
-   |             ^^^^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constant functions are unstable (see issue #48821)
-  --> $DIR/issue-37550.rs:17:13
-   |
-LL |     let x = || t;
-   |             ^^^^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
+LL |     let t = true; //~ ERROR local variables in const fn
+   |         ^
 
-error: aborting due to 4 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-56199.rs b/src/test/ui/issues/issue-56199.rs
new file mode 100644 (file)
index 0000000..83d4e31
--- /dev/null
@@ -0,0 +1,23 @@
+
+enum Foo {}
+struct Bar {}
+
+impl Foo {
+    fn foo() {
+        let _ = Self;
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+        let _ = Self();
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+    }
+}
+
+impl Bar {
+    fn bar() {
+        let _ = Self;
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+        let _ = Self();
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-56199.stderr b/src/test/ui/issues/issue-56199.stderr
new file mode 100644 (file)
index 0000000..6e3c7fd
--- /dev/null
@@ -0,0 +1,30 @@
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:7:17
+   |
+LL |         let _ = Self;
+   |                 ^^^^
+   |
+   = note: did you mean to use one of the enum's variants?
+
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:9:17
+   |
+LL |         let _ = Self();
+   |                 ^^^^
+   |
+   = note: did you mean to use one of the enum's variants?
+
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:16:17
+   |
+LL |         let _ = Self;
+   |                 ^^^^ did you mean `Self { /* fields */ }`?
+
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:18:17
+   |
+LL |         let _ = Self();
+   |                 ^^^^ did you mean `Self { /* fields */ }`?
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/issues/issue-56835.rs b/src/test/ui/issues/issue-56835.rs
new file mode 100644 (file)
index 0000000..c16550e
--- /dev/null
@@ -0,0 +1,10 @@
+
+pub struct Foo {}
+
+impl Foo {
+    fn bar(Self(foo): Self) {}
+    //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+    //~^^ ERROR expected tuple struct/variant, found self constructor `Self` [E0164]
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-56835.stderr b/src/test/ui/issues/issue-56835.stderr
new file mode 100644 (file)
index 0000000..b7c3b14
--- /dev/null
@@ -0,0 +1,15 @@
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56835.rs:5:12
+   |
+LL |     fn bar(Self(foo): Self) {}
+   |            ^^^^^^^^^ did you mean `Self { /* fields */ }`?
+
+error[E0164]: expected tuple struct/variant, found self constructor `Self`
+  --> $DIR/issue-56835.rs:5:12
+   |
+LL |     fn bar(Self(foo): Self) {}
+   |            ^^^^^^^^^ not a tuple variant or struct
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0164`.
index a8b0e3e4250ea751410c6b07e0425e4ed682cf35..6b9e1dc70573ee58ffe0887bbaa6e0db04602ee8 100644 (file)
@@ -55,6 +55,7 @@ note: lint level defined here
 LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
    |         ^^^^^^
    = note: #[warn(unused_assignments)] implied by #[warn(unused)]
+   = help: maybe it is overwritten before being read?
 
 warning: unused variable: `fire`
   --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:54:32
index 6709fee0abb72fd015b012d14e4fe410f3bc7933..6e43cccdccff230b5b9916021bb0958e0e607d41 100644 (file)
@@ -9,24 +9,31 @@ note: lint level defined here
    |
 LL | #![deny(unused_assignments)]
    |         ^^^^^^^^^^^^^^^^^^
+   = help: maybe it is overwritten before being read?
 
 error: value assigned to `x` is never read
   --> $DIR/liveness-dead.rs:27:5
    |
 LL |     x = 4; //~ ERROR: value assigned to `x` is never read
    |     ^
+   |
+   = help: maybe it is overwritten before being read?
 
 error: value passed to `x` is never read
   --> $DIR/liveness-dead.rs:30:11
    |
 LL | fn f4(mut x: i32) { //~ ERROR: value passed to `x` is never read
    |           ^
+   |
+   = help: maybe it is overwritten before being read?
 
 error: value assigned to `x` is never read
   --> $DIR/liveness-dead.rs:37:5
    |
 LL |     x = 4; //~ ERROR: value assigned to `x` is never read
    |     ^
+   |
+   = help: maybe it is overwritten before being read?
 
 error: aborting due to 4 previous errors
 
index 2846f242fbe4c47077bcce3b4a80e0043abaab58..35ccc79a19ac094f3210762d67dcc006daa2e8a6 100644 (file)
@@ -60,6 +60,7 @@ note: lint level defined here
    |
 LL | #![deny(unused_assignments)]
    |         ^^^^^^^^^^^^^^^^^^
+   = help: maybe it is overwritten before being read?
 
 error: variable `z` is assigned to, but never used
   --> $DIR/liveness-unused.rs:47:13
@@ -106,6 +107,8 @@ error: value assigned to `x` is never read
    |
 LL |         x = 0;  //~ ERROR value assigned to `x` is never read
    |         ^
+   |
+   = help: maybe it is overwritten before being read?
 
 error: aborting due to 13 previous errors
 
index 6a8ce03e8fd255cba0ec950ed7fc8e1924f7e944..edce2b185df34bdcd3372e1845953e7d49ddaf96 100644 (file)
@@ -46,9 +46,9 @@ fn enum_example(mut e: E) {
         E::V(ref mut x, _) => x,
         E::W => panic!(),
     };
-    match e { // OK, no access of borrowed data
+    match e { // Don't know that E uses a tag for its discriminant
         _ if false => (),
-        E::V(_, r) => (),
+        E::V(_, r) => (), //~ ERROR
         E::W => (),
     }
     x;
@@ -59,9 +59,9 @@ fn indirect_enum_example(mut f: &mut E) {
         E::V(ref mut x, _) => x,
         E::W => panic!(),
     };
-    match f { // OK, no access of borrowed data
+    match f { // Don't know that E uses a tag for its discriminant
         _ if false => (),
-        E::V(_, r) => (),
+        E::V(_, r) => (), //~ ERROR
         E::W => (),
     }
     x;
index cdff29d44b85bf904ca22917546ea6f07c2b4965..2d34dd7805dbf5337f08b3d3a5d00937d117363a 100644 (file)
@@ -1,3 +1,27 @@
+error[E0503]: cannot use `e` because it was mutably borrowed
+  --> $DIR/match-on-borrowed.rs:51:9
+   |
+LL |         E::V(ref mut x, _) => x,
+   |              --------- borrow of `e.0` occurs here
+...
+LL |         E::V(_, r) => (), //~ ERROR
+   |         ^^^^^^^^^^ use of borrowed `e.0`
+...
+LL |     x;
+   |     - borrow later used here
+
+error[E0503]: cannot use `*f` because it was mutably borrowed
+  --> $DIR/match-on-borrowed.rs:64:9
+   |
+LL |         E::V(ref mut x, _) => x,
+   |              --------- borrow of `f.0` occurs here
+...
+LL |         E::V(_, r) => (), //~ ERROR
+   |         ^^^^^^^^^^ use of borrowed `f.0`
+...
+LL |     x;
+   |     - borrow later used here
+
 error[E0503]: cannot use `t` because it was mutably borrowed
   --> $DIR/match-on-borrowed.rs:82:9
    |
@@ -16,7 +40,7 @@ error[E0381]: use of possibly uninitialized variable: `n`
 LL |     match n {} //~ ERROR
    |           ^ use of possibly uninitialized `n`
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 Some errors occurred: E0381, E0503.
 For more information about an error, try `rustc --explain E0381`.
index 70de9167332b01cf5ff554fedf08d7092c5f0ff5..c335336bee8e3ab800aee18e01836512c023569c 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(underscore_imports)]
-
 #[macro_export]
 macro_rules! do_nothing {
     () => ()
index 64a8d0720d628c45afd9e0ce838ecc4c519d8979..93b246fb92d5fdf3d22bcf8492f8fafcf65710e8 100644 (file)
@@ -11,7 +11,6 @@
 // compile-pass
 // aux-build:underscore-imports.rs
 
-#![feature(underscore_imports)]
 #![warn(unused_imports, unused_extern_crates)]
 
 #[macro_use]
index e1fe5cc0783d960bc1feb171e5558c2adfb75c51..f2b8cc411ffe26195334ac99af6e99afa0205b07 100644 (file)
@@ -1,17 +1,17 @@
 warning: unused import: `m::Tr1 as _`
-  --> $DIR/basic.rs:37:9
+  --> $DIR/basic.rs:36:9
    |
 LL |     use m::Tr1 as _; //~ WARN unused import
    |         ^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/basic.rs:15:9
+  --> $DIR/basic.rs:14:9
    |
 LL | #![warn(unused_imports, unused_extern_crates)]
    |         ^^^^^^^^^^^^^^
 
 warning: unused import: `S as _`
-  --> $DIR/basic.rs:38:9
+  --> $DIR/basic.rs:37:9
    |
 LL |     use S as _; //~ WARN unused import
    |         ^^^^^^
index 92615c4966dae0fe76b4fbdfb4ddc1e9e1a90bd6..95f7cae0b87d20435afc2ed5dfe436a21073c5e6 100644 (file)
@@ -1,8 +1,6 @@
 // compile-pass
 // aux-build:duplicate.rs
 
-#![feature(underscore_imports)]
-
 extern crate duplicate;
 
 #[duplicate::duplicate]
index 611eb3c67ca52299ef73eec1f902cca999bfdd1e..d06a26a5f116664b5ce0094e594d5e50b4a5c4c0 100644 (file)
@@ -1,6 +1,5 @@
 // edition:2018
 
-#![feature(underscore_imports)]
 #![deny(unused_imports)]
 
 mod multi_segment {
index 02b29b3f4fe617eadb9d098a05c6f75a874e0e3f..4163c2876074befdc95f7a8fda5184b84e03d9a2 100644 (file)
@@ -1,17 +1,17 @@
 error: unused import: `core::any`
-  --> $DIR/unused-2018.rs:7:9
+  --> $DIR/unused-2018.rs:6:9
    |
 LL |     use core::any; //~ ERROR unused import: `core::any`
    |         ^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/unused-2018.rs:4:9
+  --> $DIR/unused-2018.rs:3:9
    |
 LL | #![deny(unused_imports)]
    |         ^^^^^^^^^^^^^^
 
 error: unused import: `core`
-  --> $DIR/unused-2018.rs:11:9
+  --> $DIR/unused-2018.rs:10:9
    |
 LL |     use core; //~ ERROR unused import: `core`
    |         ^^^^
index d2e6dbbb95412ac260d8bb55407d3f7b976cd571..4f0cadaae5d53299251b36c17aada8e036f90b04 100644 (file)
@@ -1,6 +1,6 @@
 // edition:2018
 
-#![feature(uniform_paths, underscore_imports)]
+#![feature(uniform_paths)]
 
 mod T {
     pub struct U;
index e8098a467904e31ccef5d4bb5b9c7f314fc69a0a..fc433c201b062b137f33003625204b70216647b0 100644 (file)
@@ -2,7 +2,7 @@
 
 // For the time being `macro_rules` items are treated as *very* private...
 
-#![feature(underscore_imports, decl_macro, uniform_paths)]
+#![feature(decl_macro, uniform_paths)]
 
 mod m1 {
     macro_rules! legacy_macro { () => () }
index 2a2d35e7bd9228a11d251881520e44d530c4a566..31ec8a7dc1c83a8a227f7cfa69f7993ebe101510 100644 (file)
@@ -54,8 +54,14 @@ fn main() {
         simd_select(z, z, z);
         //~^ ERROR mask element type is `f32`, expected `i_`
 
+        simd_select(m4, 0u32, 1u32);
+        //~^ ERROR found non-SIMD `u32`
+
         simd_select_bitmask(0u8, x, x);
         //~^ ERROR mask length `8` != other vector length `4`
+        //
+        simd_select_bitmask(0u8, 1u32, 2u32);
+        //~^ ERROR found non-SIMD `u32`
 
         simd_select_bitmask(0.0f32, x, x);
         //~^ ERROR `f32` is not an integral type
index 584f3d539213b8a99ea8cd0fc368ad99df1e2954..05317da2475f1298f488d6828c5632538222de39 100644 (file)
@@ -16,24 +16,36 @@ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element
 LL |         simd_select(z, z, z);
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
+error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD argument type, found non-SIMD `u32`
   --> $DIR/simd-intrinsic-generic-select.rs:57:9
    |
+LL |         simd_select(m4, 0u32, 1u32);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
+  --> $DIR/simd-intrinsic-generic-select.rs:60:9
+   |
 LL |         simd_select_bitmask(0u8, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: expected SIMD argument type, found non-SIMD `u32`
+  --> $DIR/simd-intrinsic-generic-select.rs:63:9
+   |
+LL |         simd_select_bitmask(0u8, 1u32, 2u32);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `f32` is not an integral type
-  --> $DIR/simd-intrinsic-generic-select.rs:60:9
+  --> $DIR/simd-intrinsic-generic-select.rs:66:9
    |
 LL |         simd_select_bitmask(0.0f32, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `&str` is not an integral type
-  --> $DIR/simd-intrinsic-generic-select.rs:63:9
+  --> $DIR/simd-intrinsic-generic-select.rs:69:9
    |
 LL |         simd_select_bitmask("x", x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/suggestions/path-display.rs b/src/test/ui/suggestions/path-display.rs
new file mode 100644 (file)
index 0000000..62fc9e7
--- /dev/null
@@ -0,0 +1,7 @@
+use std::path::Path;
+
+fn main() {
+    let path = Path::new("/tmp/foo/bar.txt");
+    println!("{}", path);
+    //~^ ERROR E0277
+}
diff --git a/src/test/ui/suggestions/path-display.stderr b/src/test/ui/suggestions/path-display.stderr
new file mode 100644 (file)
index 0000000..39d236a
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0277]: `std::path::Path` doesn't implement `std::fmt::Display`
+  --> $DIR/path-display.rs:5:20
+   |
+LL |     println!("{}", path);
+   |                    ^^^^ `std::path::Path` cannot be formatted with the default formatter; call `.display()` on it
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `std::path::Path`
+   = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data
+   = note: required because of the requirements on the impl of `std::fmt::Display` for `&std::path::Path`
+   = note: required by `std::fmt::Display::fmt`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 8a045884cae315b495c2494ef7cd1bab06051f0f..2d0fb78897de10403e2f25fd0d2272a1aa93c473 100644 (file)
@@ -24,7 +24,6 @@
 // gate-test-mips_target_feature
 // gate-test-mmx_target_feature
 // gate-test-wasm_target_feature
-// min-llvm-version 6.0
 
 #[target_feature(enable = "avx512bw")]
 //~^ ERROR: currently unstable
index f18bebc0c290dada8e67fd4444c6c4690c92373f..24141d0064fb0f2c0cf92dd52a710ad22bb54785 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839)
-  --> $DIR/target-feature-gate.rs:29:18
+  --> $DIR/target-feature-gate.rs:28:18
    |
 LL | #[target_feature(enable = "avx512bw")]
    |                  ^^^^^^^^^^^^^^^^^^^
index b7a431ea1ddb96a396921bf9b5f2f6d8690cd474..a416c5e0f7c4c9473069a58410d3ec3e86b1ac0d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b7a431ea1ddb96a396921bf9b5f2f6d8690cd474
+Subproject commit a416c5e0f7c4c9473069a58410d3ec3e86b1ac0d
index 003839982429ff467bdfc3331731149096cb94b9..8b3023e63dfb49c732a5f2668629a416c2684e09 100644 (file)
@@ -873,3 +873,29 @@ fn parse_normalization_string(line: &mut &str) -> Option<String> {
     *line = &line[end + 1..];
     Some(result)
 }
+
+#[test]
+fn test_parse_normalization_string() {
+    let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits)\".";
+    let first = parse_normalization_string(&mut s);
+    assert_eq!(first, Some("something (32 bits)".to_owned()));
+    assert_eq!(s, " -> \"something ($WORD bits)\".");
+
+    // Nothing to normalize (No quotes)
+    let mut s = "normalize-stderr-32bit: something (32 bits) -> something ($WORD bits).";
+    let first = parse_normalization_string(&mut s);
+    assert_eq!(first, None);
+    assert_eq!(s, r#"normalize-stderr-32bit: something (32 bits) -> something ($WORD bits)."#);
+
+    // Nothing to normalize (Only a single quote)
+    let mut s = "normalize-stderr-32bit: \"something (32 bits) -> something ($WORD bits).";
+    let first = parse_normalization_string(&mut s);
+    assert_eq!(first, None);
+    assert_eq!(s, "normalize-stderr-32bit: \"something (32 bits) -> something ($WORD bits).");
+
+    // Nothing to normalize (Three quotes)
+    let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits).";
+    let first = parse_normalization_string(&mut s);
+    assert_eq!(first, Some("something (32 bits)".to_owned()));
+    assert_eq!(s, " -> \"something ($WORD bits).");
+}
index 2a716970ca7b9a03edead9992cc41fa2dc203e0b..381d808e8028f9f5760b976d4042e94865d7e445 100644 (file)
@@ -86,6 +86,8 @@ pub fn matches_os(triple: &str, name: &str) -> bool {
     }
     panic!("Cannot determine OS from triple");
 }
+
+/// Determine the architecture from `triple`
 pub fn get_arch(triple: &str) -> &'static str {
     let triple: Vec<_> = triple.split('-').collect();
     for &(triple_arch, arch) in ARCH_TABLE {
@@ -151,3 +153,29 @@ fn with_extra_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
         }
     }
 }
+
+#[test]
+#[should_panic(expected = "Cannot determine Architecture from triple")]
+fn test_get_arch_failure() {
+    get_arch("abc");
+}
+
+#[test]
+fn test_get_arch() {
+    assert_eq!("x86_64", get_arch("x86_64-unknown-linux-gnu"));
+    assert_eq!("x86_64", get_arch("amd64"));
+}
+
+#[test]
+#[should_panic(expected = "Cannot determine OS from triple")]
+fn test_matches_os_failure() {
+    matches_os("abc", "abc");
+}
+
+#[test]
+fn test_matches_os() {
+    assert!(matches_os("x86_64-unknown-linux-gnu", "linux"));
+    assert!(matches_os("wasm32-unknown-unknown", "emscripten"));
+    assert!(matches_os("wasm32-unknown-unknown", "wasm32-bare"));
+    assert!(!matches_os("wasm32-unknown-unknown", "windows"));
+}
index e6bf9a285723b41ec3a5e594b2ca0d680ca38e37..1aa647a6a1b7822e4186786a287bdd3d7fbe7ad5 100644 (file)
@@ -137,7 +137,6 @@ fn check(cache: &mut Cache,
        file.ends_with("symbol/struct.InternedString.html") ||
        file.ends_with("ast/struct.ThinVec.html") ||
        file.ends_with("util/struct.ThinVec.html") ||
-       file.ends_with("util/struct.RcSlice.html") ||
        file.ends_with("layout/struct.TyLayout.html") ||
        file.ends_with("humantime/struct.Timestamp.html") ||
        file.ends_with("log/index.html") ||
index a65d263d2e3a3e3a7f5507a7fcd8e13c43234e14..4ade87f5d65bd2c167175bcf27ca178a28df1b50 100755 (executable)
@@ -34,16 +34,6 @@ MAINTAINERS = {
     'rust-by-example': '@steveklabnik @marioidival @projektir',
 }
 
-EMOJI = {
-    'miri': '🛰️',
-    'clippy-driver': '📎',
-    'rls': '💻',
-    'rustfmt': '📝',
-    'book': '📖',
-    'nomicon': '👿',
-    'reference': '📚',
-    'rust-by-example': '👩‍🏫',
-}
 
 def read_current_status(current_commit, path):
     '''Reads build status of `current_commit` from content of `history/*.tsv`
@@ -73,12 +63,13 @@ def update_latest(
         }
 
         slug = 'rust-lang/rust'
-        long_message = textwrap.dedent('''\
+        message = textwrap.dedent('''\
+            📣 Toolstate changed by {}!
+
             Tested on commit {}@{}.
             Direct link to PR: <{}>
 
-        ''').format(slug, current_commit, relevant_pr_url)
-        emoji_status = []
+        ''').format(relevant_pr_number, slug, current_commit, relevant_pr_url)
         anything_changed = False
         for status in latest:
             tool = status['tool']
@@ -90,18 +81,12 @@ def update_latest(
                 status[os] = new
                 if new > old:
                     changed = True
-                    long_message += '🎉 {} on {}: {} → {}.\n' \
-                        .format(tool, os, old, new)
-                    emoji = "{}🎉".format(EMOJI.get(tool))
-                    if msg not in emoji_status:
-                        emoji_status += [msg]
+                    message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
+                        .format(tool, os, old, new, MAINTAINERS.get(tool))
                 elif new < old:
                     changed = True
-                    long_message += '💔 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
+                    message += '💔 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
                         .format(tool, os, old, new, MAINTAINERS.get(tool))
-                    emoji = "{}💔".format(EMOJI.get(tool))
-                    if msg not in emoji_status:
-                        emoji_status += [msg]
 
             if changed:
                 status['commit'] = current_commit
@@ -111,9 +96,6 @@ def update_latest(
         if not anything_changed:
             return ''
 
-        short_message = "📣 Toolstate changed by {}! ({})"
-            .format(relevant_pr_number, '/'.join(emoji_status))
-        message = short_message + "\n\n" + long_message
         f.seek(0)
         f.truncate(0)
         json.dump(latest, f, indent=4, separators=(',', ': '))
index 2b5cff6e07b2a27b70d95aa5d109b7b63dd24700..d1e4387166ca663a30d0566ac58449d37a07e678 100644 (file)
@@ -79,6 +79,7 @@
     Crate("chalk-macros"),
     Crate("cloudabi"),
     Crate("cmake"),
+    Crate("compiler_builtins"),
     Crate("crc"),
     Crate("crc32fast"),
     Crate("crossbeam-deque"),