Auto merge of #56863 - arielb1:supertrait-self-4, r=nikomatsakis
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
diff --git a/.travis.yml b/.travis.yml
index 3f2e43a..9e46e6b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,7 +16,7 @@
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
diff --git a/Cargo.lock b/Cargo.lock
index be4a1c2..7e03474 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -87,7 +87,7 @@
"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 @@
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 @@
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 @@
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 @@
[[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 @@
"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 @@
"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 @@
"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 @@
"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"
diff --git a/README.md b/README.md
index 3744266..dc013a1 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@
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
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 3e91c2b..0f7b6c2 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -2,6 +2,7 @@
authors = ["The Rust Project Developers"]
name = "bootstrap"
version = "0.0.0"
+edition = "2018"
[lib]
name = "bootstrap"
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index c1d5686..405fc87 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -21,20 +21,20 @@
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};
+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 Compiler;
+pub use crate::Compiler;
use petgraph::graph::NodeIndex;
use petgraph::Graph;
@@ -1252,7 +1252,7 @@
#[cfg(test)]
mod __test {
use super::*;
- use config::Config;
+ use crate::config::Config;
use std::thread;
fn configure(host: &[&str], target: &[&str]) -> Config {
diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs
index 0b561a3..165cffa 100644
--- a/src/bootstrap/cache.rs
+++ b/src/bootstrap/cache.rs
@@ -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>);
diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs
index d5da0ca..3d2b3a2 100644
--- a/src/bootstrap/cc_detect.rs
+++ b/src/bootstrap/cc_detect.rs
@@ -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
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index 878b6ed..8756ec9 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -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";
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 0c6dbb0..84e7c40 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -10,11 +10,12 @@
//! 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)]
diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs
index 87f194f..dc42159 100644
--- a/src/bootstrap/clean.rs
+++ b/src/bootstrap/clean.rs
@@ -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());
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 689d053..61a04b9 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -29,12 +29,12 @@
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 {
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 1dafbe1..2ae9da9 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -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.
///
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index f03eefb..927f9bf 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -26,13 +26,13 @@
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 {
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 2d0625b..217328a 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -22,15 +22,15 @@
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;)+) => {
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index c49da8f..14e2f69 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -19,12 +19,12 @@
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 {
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index cb28698..aebcfb4 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -18,11 +18,11 @@
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));
diff --git a/src/bootstrap/job.rs b/src/bootstrap/job.rs
index f7b1c50..a9da2c4 100644
--- a/src/bootstrap/job.rs
+++ b/src/bootstrap/job.rs
@@ -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;
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index c879291..c5b8f19 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -159,7 +159,7 @@
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;
@@ -188,7 +188,7 @@
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 @@
#[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
diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs
index fa0b198..bb503e8 100644
--- a/src/bootstrap/metadata.rs
+++ b/src/bootstrap/metadata.rs
@@ -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 {
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 8ff175b..d9f51f6 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -28,11 +28,11 @@
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 @@
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,
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 7a9e6d4..f585495 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -27,7 +27,7 @@
use build_helper::output;
-use Build;
+use crate::Build;
struct Finder {
cache: HashMap<OsString, Option<PathBuf>>,
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 87d5737..11932d5 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -23,17 +23,17 @@
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 @@
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,
});
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 1bd4403..4335359 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -15,16 +15,16 @@
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 {
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index be24ae0..b18e38e 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -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-6.0/Dockerfile
similarity index 89%
rename from src/ci/docker/x86_64-gnu-llvm-5.0/Dockerfile
rename to src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile
index 4f90c50..160b23e 100644
--- a/src/ci/docker/x86_64-gnu-llvm-5.0/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile
@@ -11,7 +11,7 @@
cmake \
sudo \
gdb \
- llvm-5.0-tools \
+ llvm-6.0-tools \
libedit-dev \
zlib1g-dev \
xz-utils
@@ -22,6 +22,6 @@
# 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 \
+ --llvm-root=/usr/lib/llvm-6.0 \
--enable-llvm-link-shared
ENV RUST_CHECK_TARGET check
diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs
index 215689d..a2d2d3c 100644
--- a/src/liballoc/collections/btree/node.rs
+++ b/src/liballoc/collections/btree/node.rs
@@ -58,9 +58,34 @@
/// 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 @@
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 @@
.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 @@
/// `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 @@
/// 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 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 @@
>,
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 @@
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 @@
}
}
- 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 @@
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 @@
} 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 @@
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 @@
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 @@
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 @@
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 @@
edge.node
);
- self.as_leaf_mut().len += 1;
+ (*self.as_leaf_mut()).len += 1;
self.correct_all_childrens_parent_links();
}
@@ -732,12 +790,12 @@
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 @@
);
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 @@
}
};
- self.as_leaf_mut().len -= 1;
+ (*self.as_leaf_mut()).len -= 1;
(key, val, edge)
}
@@ -966,7 +1024,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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)) => {
diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs
index 2ef84db..ba46faf 100644
--- a/src/liballoc/collections/linked_list.rs
+++ b/src/liballoc/collections/linked_list.rs
@@ -627,7 +627,9 @@
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 @@
/// 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
///
/// ```
diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs
index e329b45..509195c 100644
--- a/src/liballoc/tests/vec.rs
+++ b/src/liballoc/tests/vec.rs
@@ -80,6 +80,11 @@
}
#[test]
+fn test_zst_capacity() {
+ assert_eq!(Vec::<()>::new().capacity(), usize::max_value());
+}
+
+#[test]
fn test_extend() {
let mut v = Vec::new();
let mut w = Vec::new();
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 0c5256b..8e0caa5 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -609,10 +609,15 @@
/// 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")]
diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs
index 0c870f9..5dee1d6 100644
--- a/src/libcore/future/future.rs
+++ b/src/libcore/future/future.rs
@@ -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;
diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index 92a4aed..c0b83a6 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -98,6 +98,7 @@
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")]
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index 7b273f7..aa23d49 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -649,19 +649,6 @@
_ => (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")]
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index a51674f..c8ad38c 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -121,7 +121,6 @@
#![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)]
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 4acf3a1..f1df1f2 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -70,7 +70,7 @@
#[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 @@
"[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 @@
#[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 }
}
}
diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs
index d1be724..3b356b9 100644
--- a/src/libcore/ops/function.rs
+++ b/src/libcore/ops/function.rs
@@ -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 @@
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 @@
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")]
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 79ca600..b3c93ae 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2928,7 +2928,7 @@
#[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.
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 060983a..d2683e3 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -1072,6 +1072,15 @@
#[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 @@
#[$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]
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 4efa013..00b4aa4 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -1003,6 +1003,8 @@
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]
diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs
index 8d2b1d7..43bc9d8 100644
--- a/src/librustc/infer/canonical/query_response.rs
+++ b/src/librustc/infer/canonical/query_response.rs
@@ -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 @@
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
+ ) -> 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)
- )
- ),
- }
- )
- })
- ) as Box<dyn Iterator<Item = _>>
+ 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.
diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs
index f124623..833da67 100644
--- a/src/librustc/infer/combine.rs
+++ b/src/librustc/infer/combine.rs
@@ -347,6 +347,10 @@
self.infcx.tcx
}
+ fn trait_object_mode(&self) -> relate::TraitObjectMode {
+ self.infcx.trait_object_mode()
+ }
+
fn tag(&self) -> &'static str {
"Generalizer"
}
diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs
index 27faa45..caa120f 100644
--- a/src/librustc/infer/equate.rs
+++ b/src/librustc/infer/equate.rs
@@ -39,6 +39,10 @@
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,
diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs
index 8968c59..ba21ebb 100644
--- a/src/librustc/infer/glb.rs
+++ b/src/librustc/infer/glb.rs
@@ -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 @@
{
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 }
diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs
index 8875b41..80fad44 100644
--- a/src/librustc/infer/lub.rs
+++ b/src/librustc/infer/lub.rs
@@ -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 @@
{
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 }
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index b1a1335..c961fd5 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -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 @@
// 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 @@
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 @@
global_tcx: self,
arena: SyncDroplessArena::default(),
fresh_tables: None,
+ trait_object_mode: TraitObjectMode::NoSquash,
}
}
}
@@ -492,6 +497,12 @@
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<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 @@
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 @@
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())
}
diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs
index 773c712..0ce0eb9 100644
--- a/src/librustc/infer/nll_relate/mod.rs
+++ b/src/librustc/infer/nll_relate/mod.rs
@@ -382,6 +382,13 @@
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 @@
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"
}
diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs
index 3b0f9a5..ef2ef3f 100644
--- a/src/librustc/infer/sub.rs
+++ b/src/librustc/infer/sub.rs
@@ -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 @@
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 }
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index b7759a8..cf43710 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -209,6 +209,12 @@
}
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,
"detects incorrect use of `repr` attribute"
@@ -365,6 +371,13 @@
}
}
+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 @@
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 @@
MACRO_USE_EXTERN_CRATE,
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
parser::QUESTION_MARK_MACRO_SEP,
+ DEPRECATED_IN_FUTURE,
)
}
}
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index e576951..31a75bd 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -1657,11 +1657,15 @@
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();
}
}
}
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index ab379c9..61341cb 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -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 @@
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 @@
// 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 @@
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);
}
}
}
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 68b5c3e..9dff327 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -149,6 +149,14 @@
/// 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 @@
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 @@
spread_arg: None,
span,
cache: cache::Cache::new(),
+ control_flow_destroyed,
}
}
@@ -421,6 +431,7 @@
arg_count,
upvar_decls,
spread_arg,
+ control_flow_destroyed,
span,
cache
});
@@ -1748,6 +1759,9 @@
/// (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 @@
arg_count,
upvar_decls,
spread_arg,
+ control_flow_destroyed,
span,
cache,
}
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index f10f523..af338cd 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -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 @@
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 @@
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 @@
// 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())
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 4ef4f45..373d665 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -459,7 +459,7 @@
{
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 {
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 8d91132..cf37c3f 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -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,
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index c438542..d46389b 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -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 @@
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 @@
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()
}
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 96bb545..70d36e9 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -24,10 +24,10 @@
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 @@
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 @@
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)
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index b0ca2f6..1a22866 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -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 @@
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 @@
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 @@
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,
- |overlap| last_lint = Some(overlap_error(overlap)),
+ 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,
+ TraitObjectMode::NoSquash,
+ |overlap| {
+ last_lint = Some(FutureCompatOverlapError {
+ error: overlap_error(overlap),
+ kind: FutureCompatOverlapErrorKind::Issue43355
+ });
+ },
|| (),
);
}
@@ -272,7 +310,7 @@
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();
diff --git a/src/librustc/ty/_match.rs b/src/librustc/ty/_match.rs
index d20b6d3..29067bf 100644
--- a/src/librustc/ty/_match.rs
+++ b/src/librustc/ty/_match.rs
@@ -29,17 +29,24 @@
/// 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
diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs
index 7005e14..bd01dd8 100644
--- a/src/librustc/ty/fast_reject.rs
+++ b/src/librustc/ty/fast_reject.rs
@@ -43,6 +43,9 @@
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 @@
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 @@
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 @@
ArraySimplifiedType |
PtrSimplifiedType |
NeverSimplifiedType |
- ParameterSimplifiedType => {
+ ParameterSimplifiedType |
+ MarkerTraitObjectSimplifiedType => {
// nothing to do
}
IntSimplifiedType(t) => t.hash_stable(hcx, hasher),
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index a1fc949..429b7f0 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1754,17 +1754,19 @@
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 @@
repr: ReprOptions) -> Self {
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
let mut flags = AdtFlags::NO_ADT_FLAGS;
- let attrs = tcx.get_attrs(did);
- if attr::contains_name(&attrs, "fundamental") {
- flags = flags | AdtFlags::IS_FUNDAMENTAL;
- }
- if Some(did) == tcx.lang_items().phantom_data() {
- flags = flags | AdtFlags::IS_PHANTOM_DATA;
- }
- if Some(did) == tcx.lang_items().owned_box() {
- flags = flags | AdtFlags::IS_BOX;
- }
- if Some(did) == tcx.lang_items().arc() {
- flags = 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 |= 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 |= AdtFlags::IS_FUNDAMENTAL;
+ }
+ if Some(did) == tcx.lang_items().phantom_data() {
+ flags |= AdtFlags::IS_PHANTOM_DATA;
+ }
+ if Some(did) == tcx.lang_items().owned_box() {
+ flags |= AdtFlags::IS_BOX;
+ }
+ if Some(did) == tcx.lang_items().arc() {
+ flags |= AdtFlags::IS_ARC;
+ }
+ if Some(did) == tcx.lang_items().rc() {
+ flags |= AdtFlags::IS_RC;
+ }
+
AdtDef {
did,
variants,
@@ -2114,25 +2128,25 @@
#[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 @@
}
}
- /// 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.
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 7ad4fd5..88c3e5c 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -35,9 +35,20 @@
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 @@
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)?)),
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index d6aeb28..1d28c4f 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -35,6 +35,7 @@
usize,
::ty::layout::VariantIdx,
u64,
+ String,
::middle::region::Scope,
::syntax::ast::FloatTy,
::syntax::ast::NodeId,
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index a95ddef..01b1387 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -1024,17 +1024,11 @@
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(
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 0bd6146..b75cd8f 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -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 @@
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");
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 8b26ada..e229f8d 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -1192,7 +1192,7 @@
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 @@
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 `{}`",
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index 127759a..4732db8 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -1222,12 +1222,12 @@
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>,
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index 12109ae..82b1d7e 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -140,6 +140,7 @@
("avx512vpopcntdq", Some("avx512_target_feature")),
("bmi1", None),
("bmi2", None),
+ ("cmpxchg16b", Some("cmpxchg16b_target_feature")),
("fma", None),
("fxsr", None),
("lzcnt", None),
@@ -212,6 +213,7 @@
("x86", "pclmulqdq") => "pclmul",
("x86", "rdrand") => "rdrnd",
("x86", "bmi1") => "bmi",
+ ("x86", "cmpxchg16b") => "cx16",
("aarch64", "fp") => "fp-armv8",
("aarch64", "fp16") => "fullfp16",
(_, s) => s,
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index 750de1c..d316b3e 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -610,35 +610,13 @@
};
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 @@
};
let variable_access = VariableAccess::IndirectVariable {
- alloca: env_ptr,
+ alloca: place.llval,
address_operations: &ops
};
bx.declare_local(
diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs
index d8871dd..57afb80 100644
--- a/src/librustc_codegen_ssa/traits/misc.rs
+++ b/src/librustc_codegen_ssa/traits/misc.rs
@@ -32,7 +32,6 @@
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);
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 66364ff..3471218 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -294,6 +294,11 @@
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>",
edition: Some(Edition::Edition2018),
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index e3029c6..5eca629 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -545,7 +545,7 @@
self.mutate_place(
ContextKind::SetDiscrim.new(location),
(place, span),
- Shallow(Some(ArtificialField::Discriminant)),
+ Shallow(None),
JustWrite,
flow_state,
);
@@ -782,7 +782,6 @@
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum ArtificialField {
- Discriminant,
ArrayLength,
ShallowBorrow,
}
@@ -1191,14 +1190,14 @@
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,
);
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index 8af23a8..07bda8a 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -99,7 +99,7 @@
self.mutate_place(
ContextKind::SetDiscrim.new(location),
place,
- Shallow(Some(ArtificialField::Discriminant)),
+ Shallow(None),
JustWrite,
);
}
@@ -360,14 +360,14 @@
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,
);
}
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index eeac915..e24586c 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -165,15 +165,12 @@
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`.
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 7e7c0b1..4d61bf8 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -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 @@
.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 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 @@
// 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 @@
},
// 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 @@
// 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 @@
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
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs
index 328b330..0ce6428 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir/build/matches/simplify.rs
@@ -22,10 +22,9 @@
//! 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};
@@ -35,24 +34,23 @@
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 @@
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)))
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 5d9cb01..c8dec6d 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -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 @@
}
}
- 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 @@
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 @@
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 @@
}
}
- 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 @@
// 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 @@
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 @@
}
}
+ (&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 @@
"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 {
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index ab52d9b..d6af125 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -111,13 +111,6 @@
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 @@
}
}
- 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(),
)
}
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index a1471ad..f93dbce 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -372,6 +372,10 @@
// 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 @@
}
}
(hir::BinOpKind::Or, hir::Constness::Const) => {
+ cx.control_flow_destroyed.push((
+ op.span,
+ "`||` operator".into(),
+ ));
ExprKind::Binary {
op: BinOp::BitOr,
lhs: lhs.to_ref(),
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index a0b2d99..5d8732b 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -56,6 +56,9 @@
/// 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 @@
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> {
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index e604b11..b254fce 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -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;
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 5cfcc16..7ec6bbf 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -173,7 +173,7 @@
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 @@
_ => {
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 @@
-> 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 @@
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 @@
) -> 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);
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index ddd6a70..f78a70f 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -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 @@
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 @@
},
}
+#[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 @@
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 @@
);
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 @@
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 @@
} => 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 @@
}
}
-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 @@
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)) {
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 1a35f4d..983488d 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -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"]
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 1141629..2728833 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -219,7 +219,8 @@
local_decls_for_sig(&sig, span),
sig.inputs().len(),
vec![],
- span
+ span,
+ vec![],
);
if let Some(..) = ty {
@@ -396,7 +397,8 @@
self.local_decls,
self.sig.inputs().len(),
vec![],
- self.span
+ self.span,
+ vec![],
)
}
@@ -844,7 +846,8 @@
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 @@
local_decls,
sig.inputs().len(),
vec![],
- span
+ span,
+ vec![],
)
}
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 6af29b7..3607869 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -311,13 +311,9 @@
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 @@
}
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 @@
} 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!(
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index 7f8dfc1..f5bf73b 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -412,7 +412,8 @@
initial_locals,
0,
vec![],
- mir.span
+ mir.span,
+ vec![],
),
tcx,
source: mir,
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 5f08dee..58a3cb9 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -553,7 +553,13 @@
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 @@
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 @@
}
_ => {}
}
-
// 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 @@
// 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()
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 3c1b9db..eee167c 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -230,7 +230,7 @@
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(()),
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index f643870..592f721 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -108,10 +108,14 @@
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 @@
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`
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index 42ead92..a5d2edb 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -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
index fb37f03..0000000
--- a/src/librustc_passes/mir_stats.rs
+++ /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);
- }
-}
diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs
index e926e49..ef41ea3 100644
--- a/src/librustc_target/spec/apple_ios_base.rs
+++ b/src/librustc_target/spec/apple_ios_base.rs
@@ -74,6 +74,8 @@
args.insert(LinkerFlavor::Gcc,
vec!["-arch".to_string(),
arch_name.to_string(),
+ "-isysroot".to_string(),
+ sdk_root.clone(),
"-Wl,-syslibroot".to_string(),
sdk_root]);
diff --git a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
index 07383b3..5b6d8ab 100644
--- a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
+++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
@@ -49,6 +49,7 @@
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())
diff --git a/src/librustc_traits/chalk_context/resolvent_ops.rs b/src/librustc_traits/chalk_context/resolvent_ops.rs
index df6458a..73aa8a1 100644
--- a/src/librustc_traits/chalk_context/resolvent_ops.rs
+++ b/src/librustc_traits/chalk_context/resolvent_ops.rs
@@ -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 @@
self.infcx.tcx
}
+ fn trait_object_mode(&self) -> relate::TraitObjectMode {
+ self.infcx.trait_object_mode()
+ }
+
fn tag(&self) -> &'static str {
"chalk_context::answer_substitutor"
}
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index e4ce049..75ae868 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -280,7 +280,7 @@
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) {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 8901f4b..957c8d9 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -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};
@@ -113,7 +113,8 @@
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 @@
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 @@
// 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 @@
}).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;
+ 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 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)
+ 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(
diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
index ec1a439..c273c8f 100644
--- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs
+++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
@@ -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 @@
}
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 @@
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 @@
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,
+ );
}
}
}
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index c9f3aa0..46002c0 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -868,10 +868,10 @@
}
{
- 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)?;
}
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 51714c3..d5b8ecd 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -213,9 +213,9 @@
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) {
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index d1336b1..01d2cbe 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -305,7 +305,7 @@
overflow-x: auto;
}
-body:not(.source) .example-wrap > pre {
+.rustdoc:not(.source) .example-wrap > pre {
margin: 0;
}
diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js
index d1c377b..22ac52f 100644
--- a/src/librustdoc/html/static/storage.js
+++ b/src/librustdoc/html/static/storage.js
@@ -111,7 +111,7 @@
var found = false;
if (savedHref.length === 0) {
- onEach(document.getElementsByTagName("link"), function(el) {
+ onEachLazy(document.getElementsByTagName("link"), function(el) {
savedHref.push(el.href);
});
}
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 50acde6..84ce9f6 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -395,6 +395,7 @@
// 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 @@
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 @@
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 @@
let expected =
"#![allow(unused)]
-fn main() {
// fn main
+fn main() {
assert_eq!(2+2, 4);
}".to_string();
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 41e778b..9cee00b 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -21,6 +21,7 @@
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"
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 7d17aaf..d0dd4d4 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -550,7 +550,8 @@
#[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 \
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index c800763..9e627ec 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -491,7 +491,8 @@
#[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 \
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index edcfdd9..35ae493 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -1729,7 +1729,7 @@
/// 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
///
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 0febbe5..ead38f2 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -339,6 +339,7 @@
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)]
diff --git a/src/libstd/os/raw/mod.rs b/src/libstd/os/raw/mod.rs
index 95faf3a..05f30f2 100644
--- a/src/libstd/os/raw/mod.rs
+++ b/src/libstd/os/raw/mod.rs
@@ -27,6 +27,10 @@
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")),
@@ -42,6 +46,10 @@
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")),
diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs
index 7737178..e44113f 100644
--- a/src/libstd/sys_common/backtrace.rs
+++ b/src/libstd/sys_common/backtrace.rs
@@ -14,11 +14,12 @@
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 @@
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 @@
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");
- }
-}
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index 7723c15..73cbe49 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -483,7 +483,7 @@
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 @@
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 @@
TokenTree::Delimited(
DelimSpan::from_single(span),
token::Paren,
- TokenStream::concat(tokens).into(),
+ TokenStream::new(tokens).into(),
).into()
}
}
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index f4e9a7e..03c7aa9 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -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 @@
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();
}
}
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index c3497a1..5820b49 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -247,7 +247,7 @@
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
}
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index a76779f..a63abd4 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -103,12 +103,12 @@
}
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());
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 1a4de59..4eca0c9 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -400,9 +400,6 @@
// 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 @@
(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_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 == "_" {
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 0c24c20..1fa11a4 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -145,12 +145,6 @@
#[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;
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index 4ff6048..1bd0656 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -170,7 +170,7 @@
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()
};
diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs
index 86c87cf..0906c25c 100644
--- a/src/libsyntax/parse/lexer/tokentrees.rs
+++ b/src/libsyntax/parse/lexer/tokentrees.rs
@@ -22,7 +22,7 @@
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 @@
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);
}
}
}
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 10c451e..e3cccac 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -863,13 +863,13 @@
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 @@
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(),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a4326d9..a672a08 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2939,7 +2939,7 @@
_ => result.push(self.parse_token_tree().into()),
}
}
- TokenStream::concat(result)
+ TokenStream::new(result)
}
/// Parse a prefix-unary-operator expr
@@ -4635,7 +4635,7 @@
self.unexpected()?;
unreachable!()
};
- TokenStream::concat(vec![
+ TokenStream::new(vec![
args.into(),
TokenTree::Token(token_lo.to(self.prev_span), token::FatArrow).into(),
body.into(),
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index 90191c5..c11ef33 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -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 joint(self) -> TokenStream {
- TokenStream { kind: TokenStreamKind::JointTree(self) }
+ TokenStream::JointTree(self)
}
/// Returns the opening delimiter as a token tree.
@@ -154,65 +154,57 @@
/// 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 @@
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 @@
// 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 @@
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 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 @@
/// 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 @@
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 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 @@
#[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 @@
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 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 @@
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 @@
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 @@
_ 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 @@
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 @@
/// `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 @@
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 @@
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
index 520b7a4..0000000
--- a/src/libsyntax/util/rc_slice.rs
+++ /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
index 99fbce1..0000000
--- a/src/libsyntax/util/rc_vec.rs
+++ /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);
- }
-}
diff --git a/src/llvm b/src/llvm
index a784eca..95185c8 160000
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit a784eca10d2c1f09e65d67e16eca266485e1eac3
+Subproject commit 95185c8c801c765ac1072392d081d265af9fb310
diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp
index 1355c03..2f8dc0d 100644
--- a/src/rustllvm/ArchiveWrapper.cpp
+++ b/src/rustllvm/ArchiveWrapper.cpp
@@ -216,16 +216,11 @@
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;
}
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index aa420bf..4d95368 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -17,21 +17,15 @@
#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 @@
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 @@
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(
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index b9a0b43..86c5dfc 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -297,11 +297,7 @@
// 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 @@
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 @@
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
diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger
index 9cf17c4..a268838 100644
--- a/src/rustllvm/llvm-rebuild-trigger
+++ b/src/rustllvm/llvm-rebuild-trigger
@@ -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
diff --git a/src/stdsimd b/src/stdsimd
index 5e628c5..3c0503d 160000
--- a/src/stdsimd
+++ b/src/stdsimd
@@ -1 +1 @@
-Subproject commit 5e628c5120c619a22799187371f057ec41e06f87
+Subproject commit 3c0503db8439928e42c1175f0009c506fc874ae9
diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs
index 5061d9a..52bdb1b 100644
--- a/src/test/codegen/function-arguments.rs
+++ b/src/test/codegen/function-arguments.rs
@@ -10,7 +10,6 @@
// compile-flags: -C no-prepopulate-passes
// ignore-tidy-linelength
-// min-llvm-version 6.0
#![crate_type = "lib"]
#![feature(custom_attribute)]
diff --git a/src/test/codegen/issue-44056-macos-tls-align.rs b/src/test/codegen/issue-44056-macos-tls-align.rs
index b146e10..ebd436c 100644
--- a/src/test/codegen/issue-44056-macos-tls-align.rs
+++ b/src/test/codegen/issue-44056-macos-tls-align.rs
@@ -11,7 +11,6 @@
// ignore-tidy-linelength
// only-macos
// no-system-llvm
-// min-llvm-version 6.0
// compile-flags: -O
#![crate_type = "rlib"]
diff --git a/src/test/codegen/issue-45222.rs b/src/test/codegen/issue-45222.rs
index 3544786..a6e633b 100644
--- a/src/test/codegen/issue-45222.rs
+++ b/src/test/codegen/issue-45222.rs
@@ -9,7 +9,6 @@
// except according to those terms.
// compile-flags: -O
-// min-llvm-version 6.0
#![crate_type = "lib"]
diff --git a/src/test/codegen/issue-45466.rs b/src/test/codegen/issue-45466.rs
index 1495476..f916c1a 100644
--- a/src/test/codegen/issue-45466.rs
+++ b/src/test/codegen/issue-45466.rs
@@ -9,7 +9,6 @@
// except according to those terms.
// compile-flags: -O
-// min-llvm-version 6.0
#![crate_type="rlib"]
diff --git a/src/test/codegen/simd-intrinsic-generic-gather.rs b/src/test/codegen/simd-intrinsic-generic-gather.rs
index 6c47bf3..605a952 100644
--- a/src/test/codegen/simd-intrinsic-generic-gather.rs
+++ b/src/test/codegen/simd-intrinsic-generic-gather.rs
@@ -10,7 +10,6 @@
// ignore-emscripten
// ignore-tidy-linelength
-// min-llvm-version 6.0
// compile-flags: -C no-prepopulate-passes
diff --git a/src/test/codegen/simd-intrinsic-generic-scatter.rs b/src/test/codegen/simd-intrinsic-generic-scatter.rs
index 7b5b2e5..6645778 100644
--- a/src/test/codegen/simd-intrinsic-generic-scatter.rs
+++ b/src/test/codegen/simd-intrinsic-generic-scatter.rs
@@ -10,7 +10,6 @@
// ignore-emscripten
// ignore-tidy-linelength
-// min-llvm-version 6.0
// compile-flags: -C no-prepopulate-passes
diff --git a/src/test/codegen/vtabletype.rs b/src/test/codegen/vtabletype.rs
index abd1eb3..cb96a84 100644
--- a/src/test/codegen/vtabletype.rs
+++ b/src/test/codegen/vtabletype.rs
@@ -14,7 +14,6 @@
// ignore-tidy-linelength
// ignore-windows
// ignore-macos
-// min-llvm-version 6.0
// compile-flags: -g -C no-prepopulate-passes
diff --git a/src/test/compile-fail/const-fn-error.rs b/src/test/compile-fail/const-fn-error.rs
index 17dc9f9..397bc7e 100644
--- a/src/test/compile-fail/const-fn-error.rs
+++ b/src/test/compile-fail/const-fn-error.rs
@@ -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
index 0000000..4bb5c59
--- /dev/null
+++ b/src/test/compile-fail/must_use-in-stdlib-traits.rs
@@ -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
index 0000000..9bfb728
--- /dev/null
+++ b/src/test/mir-opt/match_test.rs
@@ -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
index 0000000..ef843f7
--- /dev/null
+++ b/src/test/mir-opt/simplify_cfg.rs
@@ -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
index 88f0d07..0000000
--- a/src/test/run-pass/ctfe/const-fn-destructuring-arg.rs
+++ /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
index 0000000..08c6945
--- /dev/null
+++ b/src/test/run-pass/issues/issue-33140.rs
@@ -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
index 0000000..1f96d67
--- /dev/null
+++ b/src/test/run-pass/mir/mir_match_test.rs
@@ -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);
+}
diff --git a/src/test/run-pass/simd/simd-intrinsic-generic-gather.rs b/src/test/run-pass/simd/simd-intrinsic-generic-gather.rs
index 5f6a72a..e5ac577 100644
--- a/src/test/run-pass/simd/simd-intrinsic-generic-gather.rs
+++ b/src/test/run-pass/simd/simd-intrinsic-generic-gather.rs
@@ -10,7 +10,6 @@
// run-pass
// ignore-emscripten
-// min-llvm-version 6.0
// Test that the simd_{gather,scatter} intrinsics produce the correct results.
diff --git a/src/test/run-pass/sse2.rs b/src/test/run-pass/sse2.rs
index 041286f..779c72b 100644
--- a/src/test/run-pass/sse2.rs
+++ b/src/test/run-pass/sse2.rs
@@ -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
index 0000000..3468bb7
--- /dev/null
+++ b/src/test/rustdoc/comment-in-doctest.rs
@@ -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() {}
+//! ```
diff --git a/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr b/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
index 17722bf..6f72de0 100644
--- a/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
@@ -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 | *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`.
diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs
index ef0de61..63e5bcc 100644
--- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs
+++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs
@@ -24,7 +24,7 @@
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() {}
diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr
index 0892b05..740954c 100644
--- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr
+++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr
@@ -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`.
diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
index 01fcc83..6c2fdcc 100644
--- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
+++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
@@ -27,9 +27,7 @@
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
diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
index 01ad1fc..49b39e2 100644
--- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
+++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
@@ -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`.
diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.rs b/src/test/ui/consts/const-fn-not-safe-for-const.rs
index 30a738a..2f7e2ec 100644
--- a/src/test/ui/consts/const-fn-not-safe-for-const.rs
+++ b/src/test/ui/consts/const-fn-not-safe-for-const.rs
@@ -37,15 +37,13 @@
}
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() {}
diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.stderr b/src/test/ui/consts/const-fn-not-safe-for-const.stderr
index 613670a..1a8c5f5 100644
--- a/src/test/ui/consts/const-fn-not-safe-for-const.stderr
+++ b/src/test/ui/consts/const-fn-not-safe-for-const.stderr
@@ -19,7 +19,7 @@
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 @@
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 @@
= 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
| ^
diff --git a/src/test/ui/consts/const_let_assign3.rs b/src/test/ui/consts/const_let_assign3.rs
index 8382545..c2ed6cd 100644
--- a/src/test/ui/consts/const_let_assign3.rs
+++ b/src/test/ui/consts/const_let_assign3.rs
@@ -8,6 +8,7 @@
impl S {
const fn foo(&mut self, x: u32) {
self.state = x;
+ //~^ contains unimplemented expression
}
}
diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr
index 7f9a953..0f29461 100644
--- a/src/test/ui/consts/const_let_assign3.stderr
+++ b/src/test/ui/consts/const_let_assign3.stderr
@@ -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
index 0000000..8739cb8
--- /dev/null
+++ b/src/test/ui/consts/const_let_eq.rs
@@ -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
index 0000000..2c7262d
--- /dev/null
+++ b/src/test/ui/consts/const_let_eq_float.rs
@@ -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
index 0000000..cc49e46
--- /dev/null
+++ b/src/test/ui/consts/const_short_circuit.rs
@@ -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
index 0000000..a67bb0b
--- /dev/null
+++ b/src/test/ui/consts/const_short_circuit.stderr
@@ -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
+
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
index f43befb..6c4e9e0 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
@@ -115,7 +115,7 @@
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
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs
index 43ca9e7..ad983da 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs
@@ -106,7 +106,7 @@
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 }
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
index bcb9be6..a93a4f8 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
@@ -115,7 +115,7 @@
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
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
index f11b43d..92e99c6 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
@@ -28,13 +28,13 @@
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
}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
index 922a788..fafc89d 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
@@ -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 @@
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 @@
|
= 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`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs
index 8a6884b..67a4820 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs
@@ -34,29 +34,28 @@
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
}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr
index 20c75af..63bf9a5 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr
@@ -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 5 previous errors
-error: aborting due to 11 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
index 0000000..3dd76b6
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/mutable_borrow.rs
@@ -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
index 0000000..fa46f5c
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/mutable_borrow.stderr
@@ -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
+
diff --git a/src/test/ui/consts/projection_qualif.rs b/src/test/ui/consts/projection_qualif.rs
index 34e8eab..5863429 100644
--- a/src/test/ui/consts/projection_qualif.rs
+++ b/src/test/ui/consts/projection_qualif.rs
@@ -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}
};
diff --git a/src/test/ui/consts/projection_qualif.stderr b/src/test/ui/consts/projection_qualif.stderr
index d5252f1..cc3635a 100644
--- a/src/test/ui/consts/projection_qualif.stderr
+++ b/src/test/ui/consts/projection_qualif.stderr
@@ -4,6 +4,12 @@
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 @@
|
= 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`.
diff --git a/src/test/ui/consts/single_variant_match_ice.rs b/src/test/ui/consts/single_variant_match_ice.rs
index 67a41bc..79dde3c 100644
--- a/src/test/ui/consts/single_variant_match_ice.rs
+++ b/src/test/ui/consts/single_variant_match_ice.rs
@@ -2,6 +2,14 @@
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::*;
diff --git a/src/test/ui/consts/single_variant_match_ice.stderr b/src/test/ui/consts/single_variant_match_ice.stderr
index a0222b0..f5c2cb5 100644
--- a/src/test/ui/consts/single_variant_match_ice.stderr
+++ b/src/test/ui/consts/single_variant_match_ice.stderr
@@ -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
index 0000000..c6c6017
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-in-future.rs
@@ -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
index 0000000..38392cf
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-in-future.stderr
@@ -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
index 0000000..dc1115b
--- /dev/null
+++ b/src/test/ui/extern/auxiliary/invalid-utf8.txt
@@ -0,0 +1 @@
+Ã(
\ No newline at end of file
diff --git a/src/test/ui/extern/external-doc-error.rs b/src/test/ui/extern/external-doc-error.rs
index 5c6f6e4..e17dda6 100644
--- a/src/test/ui/extern/external-doc-error.rs
+++ b/src/test/ui/extern/external-doc-error.rs
@@ -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() {}
diff --git a/src/test/ui/extern/external-doc-error.stderr b/src/test/ui/extern/external-doc-error.stderr
index 5cc7551..a3be327 100644
--- a/src/test/ui/extern/external-doc-error.stderr
+++ b/src/test/ui/extern/external-doc-error.stderr
@@ -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: aborting due to previous error
+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 6 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-const_let.rs b/src/test/ui/feature-gates/feature-gate-const_let.rs
index 05d02e6..9bf957a 100644
--- a/src/test/ui/feature-gates/feature-gate-const_let.rs
+++ b/src/test/ui/feature-gates/feature-gate-const_let.rs
@@ -10,13 +10,22 @@
// Test use of const let without feature gate.
-#![feature(const_fn)]
-
-const fn foo() -> usize {
+const FOO: usize = {
+ //~^ ERROR statements in constants are unstable
+ //~| ERROR: let bindings in constants are unstable
let x = 42;
- //~^ ERROR statements in constant functions are unstable
- //~| ERROR: let bindings in constant functions are unstable
+ //~^ ERROR statements in constants are unstable
+ //~| ERROR: let bindings in constants are unstable
42
-}
+};
+
+static BAR: usize = {
+ //~^ ERROR statements in statics are unstable
+ //~| ERROR: let bindings in statics are unstable
+ let x = 42;
+ //~^ ERROR statements in statics are unstable
+ //~| ERROR: let bindings in statics are unstable
+ 42
+};
fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-const_let.stderr b/src/test/ui/feature-gates/feature-gate-const_let.stderr
index 6a7f625..acb5165 100644
--- a/src/test/ui/feature-gates/feature-gate-const_let.stderr
+++ b/src/test/ui/feature-gates/feature-gate-const_let.stderr
@@ -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 @@
|
= 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 @@
|
= 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
index ceb8afe..0000000
--- a/src/test/ui/feature-gates/feature-gate-underscore-imports.rs
+++ /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
index 2eea952..0000000
--- a/src/test/ui/feature-gates/feature-gate-underscore-imports.stderr
+++ /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
index 0000000..fef5a82
--- /dev/null
+++ b/src/test/ui/issues/issue-33140.rs
@@ -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
index 0000000..240137f
--- /dev/null
+++ b/src/test/ui/issues/issue-33140.stderr
@@ -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
+
diff --git a/src/test/ui/issues/issue-37550.rs b/src/test/ui/issues/issue-37550.rs
index af1f6ef..a2f40b3 100644
--- a/src/test/ui/issues/issue-37550.rs
+++ b/src/test/ui/issues/issue-37550.rs
@@ -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() {}
diff --git a/src/test/ui/issues/issue-37550.stderr b/src/test/ui/issues/issue-37550.stderr
index 7468510..5a7d1ad 100644
--- a/src/test/ui/issues/issue-37550.stderr
+++ b/src/test/ui/issues/issue-37550.stderr
@@ -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
+LL | let t = true; //~ ERROR local variables in const fn
+ | ^
-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: aborting due to previous error
-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
-
-error: aborting due to 4 previous errors
-
-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
index 0000000..83d4e31
--- /dev/null
+++ b/src/test/ui/issues/issue-56199.rs
@@ -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
index 0000000..6e3c7fd
--- /dev/null
+++ b/src/test/ui/issues/issue-56199.stderr
@@ -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
index 0000000..c16550e
--- /dev/null
+++ b/src/test/ui/issues/issue-56835.rs
@@ -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
index 0000000..b7c3b14
--- /dev/null
+++ b/src/test/ui/issues/issue-56835.stderr
@@ -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`.
diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
index a8b0e3e..6b9e1dc 100644
--- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
+++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
@@ -55,6 +55,7 @@
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
diff --git a/src/test/ui/liveness/liveness-dead.stderr b/src/test/ui/liveness/liveness-dead.stderr
index 6709fee..6e43ccc 100644
--- a/src/test/ui/liveness/liveness-dead.stderr
+++ b/src/test/ui/liveness/liveness-dead.stderr
@@ -9,24 +9,31 @@
|
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
diff --git a/src/test/ui/liveness/liveness-unused.stderr b/src/test/ui/liveness/liveness-unused.stderr
index 2846f24..35ccc79 100644
--- a/src/test/ui/liveness/liveness-unused.stderr
+++ b/src/test/ui/liveness/liveness-unused.stderr
@@ -60,6 +60,7 @@
|
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 @@
|
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
diff --git a/src/test/ui/nll/match-on-borrowed.rs b/src/test/ui/nll/match-on-borrowed.rs
index 6a8ce03..edce2b1 100644
--- a/src/test/ui/nll/match-on-borrowed.rs
+++ b/src/test/ui/nll/match-on-borrowed.rs
@@ -46,9 +46,9 @@
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 @@
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;
diff --git a/src/test/ui/nll/match-on-borrowed.stderr b/src/test/ui/nll/match-on-borrowed.stderr
index cdff29d4..2d34dd7 100644
--- a/src/test/ui/nll/match-on-borrowed.stderr
+++ b/src/test/ui/nll/match-on-borrowed.stderr
@@ -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 @@
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`.
diff --git a/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs b/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs
index 70de916..c335336 100644
--- a/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs
+++ b/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs
@@ -1,5 +1,3 @@
-#![feature(underscore_imports)]
-
#[macro_export]
macro_rules! do_nothing {
() => ()
diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.rs b/src/test/ui/rfc-2166-underscore-imports/basic.rs
index 64a8d07..93b246f 100644
--- a/src/test/ui/rfc-2166-underscore-imports/basic.rs
+++ b/src/test/ui/rfc-2166-underscore-imports/basic.rs
@@ -11,7 +11,6 @@
// compile-pass
// aux-build:underscore-imports.rs
-#![feature(underscore_imports)]
#![warn(unused_imports, unused_extern_crates)]
#[macro_use]
diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.stderr b/src/test/ui/rfc-2166-underscore-imports/basic.stderr
index e1fe5cc..f2b8cc4 100644
--- a/src/test/ui/rfc-2166-underscore-imports/basic.stderr
+++ b/src/test/ui/rfc-2166-underscore-imports/basic.stderr
@@ -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
| ^^^^^^
diff --git a/src/test/ui/rfc-2166-underscore-imports/duplicate.rs b/src/test/ui/rfc-2166-underscore-imports/duplicate.rs
index 92615c4..95f7cae 100644
--- a/src/test/ui/rfc-2166-underscore-imports/duplicate.rs
+++ b/src/test/ui/rfc-2166-underscore-imports/duplicate.rs
@@ -1,8 +1,6 @@
// compile-pass
// aux-build:duplicate.rs
-#![feature(underscore_imports)]
-
extern crate duplicate;
#[duplicate::duplicate]
diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs b/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs
index 611eb3c..d06a26a 100644
--- a/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs
+++ b/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs
@@ -1,6 +1,5 @@
// edition:2018
-#![feature(underscore_imports)]
#![deny(unused_imports)]
mod multi_segment {
diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr b/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr
index 02b29b3..4163c28 100644
--- a/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr
+++ b/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr
@@ -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`
| ^^^^
diff --git a/src/test/ui/rust-2018/future-proofing-locals.rs b/src/test/ui/rust-2018/future-proofing-locals.rs
index d2e6dbb..4f0cada 100644
--- a/src/test/ui/rust-2018/future-proofing-locals.rs
+++ b/src/test/ui/rust-2018/future-proofing-locals.rs
@@ -1,6 +1,6 @@
// edition:2018
-#![feature(uniform_paths, underscore_imports)]
+#![feature(uniform_paths)]
mod T {
pub struct U;
diff --git a/src/test/ui/rust-2018/uniform-paths/macro-rules.rs b/src/test/ui/rust-2018/uniform-paths/macro-rules.rs
index e8098a4..fc433c2 100644
--- a/src/test/ui/rust-2018/uniform-paths/macro-rules.rs
+++ b/src/test/ui/rust-2018/uniform-paths/macro-rules.rs
@@ -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 { () => () }
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
index 2a2d35e..31ec8a7 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
@@ -54,8 +54,14 @@
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
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
index 584f3d5..05317da 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
@@ -16,24 +16,36 @@
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
index 0000000..62fc9e7
--- /dev/null
+++ b/src/test/ui/suggestions/path-display.rs
@@ -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
index 0000000..39d236a
--- /dev/null
+++ b/src/test/ui/suggestions/path-display.stderr
@@ -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`.
diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs
index 8a04588..2d0fb78 100644
--- a/src/test/ui/target-feature-gate.rs
+++ b/src/test/ui/target-feature-gate.rs
@@ -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
diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr
index f18bebc..24141d0 100644
--- a/src/test/ui/target-feature-gate.stderr
+++ b/src/test/ui/target-feature-gate.stderr
@@ -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")]
| ^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy b/src/tools/clippy
index b7a431e..a416c5e 160000
--- a/src/tools/clippy
+++ b/src/tools/clippy
@@ -1 +1 @@
-Subproject commit b7a431ea1ddb96a396921bf9b5f2f6d8690cd474
+Subproject commit a416c5e0f7c4c9473069a58410d3ec3e86b1ac0d
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 0038399..8b3023e 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -873,3 +873,29 @@
*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).");
+}
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 2a71697..381d808 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -86,6 +86,8 @@
}
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 @@
}
}
}
+
+#[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"));
+}
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index e6bf9a2..1aa647a 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -137,7 +137,6 @@
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") ||
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index a65d263..4ade87f 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -34,16 +34,6 @@
'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 @@
}
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 @@
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 @@
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=(',', ': '))
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 2b5cff6..d1e4387 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -79,6 +79,7 @@
Crate("chalk-macros"),
Crate("cloudabi"),
Crate("cmake"),
+ Crate("compiler_builtins"),
Crate("crc"),
Crate("crc32fast"),
Crate("crossbeam-deque"),