Auto merge of #66927 - RalfJung:engines-dont-panic, r=oli-obk
Miri core engine: use throw_ub instead of throw_panic
See https://github.com/rust-lang/rust/issues/66902 for context: panicking is not really an "interpreter error", but just part of a normal Rust execution. This is a first step towards removing the `InterpError::Panic` variant: the core Miri engine does not use it any more.
ConstProp and ConstEval still use it, though. This will be addressed in future PRs.
From what I can tell, all the error messages this removes are actually duplicates.
r? @oli-obk @wesleywiser
diff --git a/Cargo.lock b/Cargo.lock
index 67259ae..26727c5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -468,12 +468,14 @@
"clippy_lints",
"compiletest_rs",
"derive-new",
+ "git2",
"lazy_static 1.3.0",
"regex",
"rustc-workspace-hack",
"rustc_tools_util 0.2.0",
"semver",
"serde",
+ "tempfile",
"tester",
]
@@ -1292,7 +1294,7 @@
dependencies = [
"cfg-if",
"libc",
- "wasi",
+ "wasi 0.7.0",
]
[[package]]
@@ -3203,6 +3205,7 @@
"rustc_fs_util",
"rustc_index",
"rustc_macros",
+ "rustc_session",
"rustc_target",
"scoped-tls",
"serialize",
@@ -3516,6 +3519,7 @@
"rustc_fs_util",
"rustc_incremental",
"rustc_index",
+ "rustc_session",
"rustc_target",
"serialize",
"syntax",
@@ -3632,6 +3636,7 @@
"rustc",
"rustc_data_structures",
"rustc_fs_util",
+ "rustc_session",
"serialize",
"syntax",
"syntax_pos",
@@ -3695,6 +3700,7 @@
"rustc_error_codes",
"rustc_feature",
"rustc_index",
+ "rustc_session",
"rustc_target",
"syntax",
"syntax_pos",
@@ -3800,7 +3806,6 @@
"rustc_errors",
"rustc_feature",
"rustc_lexer",
- "rustc_target",
"smallvec 1.0.0",
"syntax",
"syntax_pos",
@@ -3883,6 +3888,22 @@
]
[[package]]
+name = "rustc_session"
+version = "0.0.0"
+dependencies = [
+ "log",
+ "num_cpus",
+ "rustc_data_structures",
+ "rustc_errors",
+ "rustc_feature",
+ "rustc_fs_util",
+ "rustc_index",
+ "rustc_target",
+ "serialize",
+ "syntax_pos",
+]
+
+[[package]]
name = "rustc_target"
version = "0.0.0"
dependencies = [
@@ -4299,7 +4320,7 @@
"rustc_msan",
"rustc_tsan",
"unwind",
- "wasi",
+ "wasi 0.9.0+wasi-snapshot-preview1",
]
[[package]]
@@ -4461,6 +4482,7 @@
"rustc_index",
"rustc_lexer",
"rustc_macros",
+ "rustc_session",
"scoped-tls",
"serialize",
"smallvec 1.0.0",
@@ -5170,6 +5192,12 @@
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d"
+
+[[package]]
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-alloc",
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 730e8cf..bb16941 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -643,7 +643,9 @@
env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \
(os.pathsep + env["LIBRARY_PATH"]) \
if "LIBRARY_PATH" in env else ""
- env["RUSTFLAGS"] = "-Cdebuginfo=2 "
+ # preserve existing RUSTFLAGS
+ env.setdefault("RUSTFLAGS", "")
+ env["RUSTFLAGS"] += " -Cdebuginfo=2"
build_section = "target.{}".format(self.build_triple())
target_features = []
@@ -652,13 +654,13 @@
elif self.get_toml("crt-static", build_section) == "false":
target_features += ["-crt-static"]
if target_features:
- env["RUSTFLAGS"] += "-C target-feature=" + (",".join(target_features)) + " "
+ env["RUSTFLAGS"] += " -C target-feature=" + (",".join(target_features))
target_linker = self.get_toml("linker", build_section)
if target_linker is not None:
- env["RUSTFLAGS"] += "-C linker=" + target_linker + " "
- env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes "
+ env["RUSTFLAGS"] += " -C linker=" + target_linker
+ env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes"
if self.get_toml("deny-warnings", "rust") != "false":
- env["RUSTFLAGS"] += "-Dwarnings "
+ env["RUSTFLAGS"] += " -Dwarnings"
env["PATH"] = os.path.join(self.bin_root(), "bin") + \
os.pathsep + env["PATH"]
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index 384219c..f8734eb 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -260,7 +260,7 @@
};
Rustc, "src/librustc", true, only_hosts: true, {
builder.ensure(dist::Rustc {
- compiler: self.compiler,
+ compiler: builder.compiler(builder.top_stage, self.target),
});
install_rustc(builder, self.compiler.stage, self.target);
};
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 39d7ea9..7ea2bb1 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -810,6 +810,7 @@
!target.contains("emscripten") &&
!target.contains("wasm32") &&
!target.contains("nvptx") &&
+ !target.contains("fortanix") &&
!target.contains("fuchsia") {
Some(self.cc(target))
} else {
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 2e89fd5..be13b9a 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -294,11 +294,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 >= 6 {
+ if major >= 7 {
return
}
}
- panic!("\n\nbad LLVM version: {}, need >=6.0\n\n", version)
+ panic!("\n\nbad LLVM version: {}, need >=7.0\n\n", version)
}
fn configure_cmake(builder: &Builder<'_>,
diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml
index bfe5174..70d6bad 100644
--- a/src/ci/azure-pipelines/auto.yml
+++ b/src/ci/azure-pipelines/auto.yml
@@ -18,7 +18,7 @@
- template: steps/run.yml
strategy:
matrix:
- x86_64-gnu-llvm-6.0:
+ x86_64-gnu-llvm-7:
RUST_BACKTRACE: 1
dist-x86_64-linux: {}
dist-x86_64-linux-alt:
diff --git a/src/ci/azure-pipelines/pr.yml b/src/ci/azure-pipelines/pr.yml
index aee4d8d..1f0be53 100644
--- a/src/ci/azure-pipelines/pr.yml
+++ b/src/ci/azure-pipelines/pr.yml
@@ -18,7 +18,7 @@
- template: steps/run.yml
strategy:
matrix:
- x86_64-gnu-llvm-6.0: {}
+ x86_64-gnu-llvm-7: {}
mingw-check: {}
x86_64-gnu-tools:
CI_ONLY_WHEN_SUBMODULES_CHANGED: 1
diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md
index a2d83ec..872f2c3 100644
--- a/src/ci/docker/README.md
+++ b/src/ci/docker/README.md
@@ -16,6 +16,13 @@
Images will output artifacts in an `obj` dir at the root of a repository.
+**NOTE**: Re-using the same `obj` dir with different docker images with
+the same target triple (e.g. `dist-x86_64-linux` and `dist-various-1`)
+may result in strange linker errors, due shared library versions differing between platforms.
+
+If you encounter any issues when using multiple Docker images, try deleting your `obj` directory
+before running your command.
+
## Filesystem layout
- Each directory, excluding `scripts` and `disabled`, corresponds to a docker image
diff --git a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
index 17aa789..925d5ca 100755
--- a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
+++ b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
@@ -12,7 +12,7 @@
git clone https://github.com/CraneStation/wasi-libc
cd wasi-libc
-git reset --hard a94d2d04e7722b323573da2bd04e909a5763d35b
+git reset --hard f645f498dfbbbc00a7a97874d33082d3605c3f21
make -j$(nproc) INSTALL_DIR=/wasm32-wasi install
cd ..
diff --git a/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile
similarity index 90%
rename from src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile
rename to src/ci/docker/x86_64-gnu-llvm-7/Dockerfile
index 6dbbb22..a1c9c13 100644
--- a/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:16.04
+FROM ubuntu:18.04
RUN apt-get update && apt-get install -y --no-install-recommends \
g++ \
@@ -11,7 +11,7 @@
cmake \
sudo \
gdb \
- llvm-6.0-tools \
+ llvm-7-tools \
libedit-dev \
libssl-dev \
pkg-config \
@@ -24,7 +24,7 @@
# using llvm-link-shared due to libffi issues -- see #34486
ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
- --llvm-root=/usr/lib/llvm-6.0 \
+ --llvm-root=/usr/lib/llvm-7 \
--enable-llvm-link-shared
ENV SCRIPT python2.7 ../x.py test src/tools/tidy && python2.7 ../x.py test
diff --git a/src/ci/run.sh b/src/ci/run.sh
index ae5b224..38d1d2b 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -23,7 +23,7 @@
ci_dir=`cd $(dirname $0) && pwd`
source "$ci_dir/shared.sh"
-if [ ! isCI ] || isCiBranch auto || isCiBranch beta; then
+if ! isCI || isCiBranch auto || isCiBranch beta; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests"
fi
diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md
index 77642a8..386f600 100644
--- a/src/doc/rustc/src/lints/listing/warn-by-default.md
+++ b/src/doc/rustc/src/lints/listing/warn-by-default.md
@@ -307,18 +307,6 @@
|
```
-## plugin-as-library
-
-This lint detects when compiler plugins are used as ordinary library in
-non-plugin crate. Some example code that triggers this lint:
-
-```rust,ignore
-#![feature(plugin)]
-#![plugin(macro_crate_test)]
-
-extern crate macro_crate_test;
-```
-
## private-in-public
This lint detects private items in public interfaces not caught by the old implementation. Some
diff --git a/src/doc/unstable-book/src/language-features/cfg-sanitize.md b/src/doc/unstable-book/src/language-features/cfg-sanitize.md
new file mode 100644
index 0000000..949f24a
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/cfg-sanitize.md
@@ -0,0 +1,36 @@
+# `cfg_sanitize`
+
+The tracking issue for this feature is: [#39699]
+
+[#39699]: https://github.com/rust-lang/rust/issues/39699
+
+------------------------
+
+The `cfg_sanitize` feature makes it possible to execute different code
+depending on whether a particular sanitizer is enabled or not.
+
+## Examples
+
+``` rust
+#![feature(cfg_sanitize)]
+
+#[cfg(sanitize = "thread")]
+fn a() {
+ // ...
+}
+
+#[cfg(not(sanitize = "thread"))]
+fn a() {
+ // ...
+}
+
+fn b() {
+ if cfg!(sanitize = "leak") {
+ // ...
+ } else {
+ // ...
+ }
+}
+
+```
+
diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md
index cd1137e..495cdee 100644
--- a/src/doc/unstable-book/src/language-features/plugin.md
+++ b/src/doc/unstable-book/src/language-features/plugin.md
@@ -21,15 +21,10 @@
`rustc_driver::plugin` documentation for more about the
mechanics of defining and loading a plugin.
-If present, arguments passed as `#![plugin(foo(... args ...))]` are not
-interpreted by rustc itself. They are provided to the plugin through the
-`Registry`'s `args` method.
-
In the vast majority of cases, a plugin should *only* be used through
`#![plugin]` and not through an `extern crate` item. Linking a plugin would
pull in all of libsyntax and librustc as dependencies of your crate. This is
-generally unwanted unless you are building another plugin. The
-`plugin_as_library` lint checks these guidelines.
+generally unwanted unless you are building another plugin.
The usual practice is to put compiler plugins in their own crate, separate from
any `macro_rules!` macros or ordinary Rust code meant to be used by consumers
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index ec08965..1ff1c3c 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -926,7 +926,7 @@
// reference (see #54908).
let layout = Layout::new::<RcBox<()>>()
.extend(value_layout).unwrap().0
- .pad_to_align().unwrap();
+ .pad_to_align();
// Allocate for the layout.
let mem = Global.alloc(layout)
@@ -1648,10 +1648,8 @@
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
///
- /// It is up to the caller to ensure that the object is still alive when accessing it through
- /// the pointer.
- ///
- /// The pointer may be [`null`] or be dangling in case the object has already been destroyed.
+ /// The pointer is valid only if there are some strong references. The pointer may be dangling
+ /// or even [`null`] otherwise.
///
/// # Examples
///
@@ -1731,14 +1729,18 @@
/// This can be used to safely get a strong reference (by calling [`upgrade`]
/// later) or to deallocate the weak count by dropping the `Weak<T>`.
///
- /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is
- /// returned.
+ /// It takes ownership of one weak count (with the exception of pointers created by [`new`],
+ /// as these don't have any corresponding weak count).
///
/// # Safety
///
- /// The pointer must represent one valid weak count. In other words, it must point to `T` which
- /// is or *was* managed by an [`Rc`] and the weak count of that [`Rc`] must not have reached
- /// 0. It is allowed for the strong count to be 0.
+ /// The pointer must have originated from the [`into_raw`] (or [`as_raw`], provided there was
+ /// a corresponding [`forget`] on the `Weak<T>`) and must still own its potential weak reference
+ /// count.
+ ///
+ /// It is allowed for the strong count to be 0 at the time of calling this, but the weak count
+ /// must be non-zero or the pointer must have originated from a dangling `Weak<T>` (one created
+ /// by [`new`]).
///
/// # Examples
///
@@ -1763,11 +1765,13 @@
/// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
/// ```
///
- /// [`null`]: ../../std/ptr/fn.null.html
/// [`into_raw`]: struct.Weak.html#method.into_raw
/// [`upgrade`]: struct.Weak.html#method.upgrade
/// [`Rc`]: struct.Rc.html
/// [`Weak`]: struct.Weak.html
+ /// [`as_raw`]: struct.Weak.html#method.as_raw
+ /// [`new`]: struct.Weak.html#method.new
+ /// [`forget`]: ../../std/mem/fn.forget.html
#[unstable(feature = "weak_into_raw", issue = "60728")]
pub unsafe fn from_raw(ptr: *const T) -> Self {
if ptr.is_null() {
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index 0deb321..19b0086 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -780,7 +780,7 @@
// reference (see #54908).
let layout = Layout::new::<ArcInner<()>>()
.extend(value_layout).unwrap().0
- .pad_to_align().unwrap();
+ .pad_to_align();
let mem = Global.alloc(layout)
.unwrap_or_else(|_| handle_alloc_error(layout));
@@ -1324,10 +1324,8 @@
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
///
- /// It is up to the caller to ensure that the object is still alive when accessing it through
- /// the pointer.
- ///
- /// The pointer may be [`null`] or be dangling in case the object has already been destroyed.
+ /// The pointer is valid only if there are some strong references. The pointer may be dangling
+ /// or even [`null`] otherwise.
///
/// # Examples
///
@@ -1408,14 +1406,18 @@
/// This can be used to safely get a strong reference (by calling [`upgrade`]
/// later) or to deallocate the weak count by dropping the `Weak<T>`.
///
- /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is
- /// returned.
+ /// It takes ownership of one weak count (with the exception of pointers created by [`new`],
+ /// as these don't have any corresponding weak count).
///
/// # Safety
///
- /// The pointer must represent one valid weak count. In other words, it must point to `T` which
- /// is or *was* managed by an [`Arc`] and the weak count of that [`Arc`] must not have reached
- /// 0. It is allowed for the strong count to be 0.
+ /// The pointer must have originated from the [`into_raw`] (or [`as_raw'], provided there was
+ /// a corresponding [`forget`] on the `Weak<T>`) and must still own its potential weak reference
+ /// count.
+ ///
+ /// It is allowed for the strong count to be 0 at the time of calling this, but the weak count
+ /// must be non-zero or the pointer must have originated from a dangling `Weak<T>` (one created
+ /// by [`new`]).
///
/// # Examples
///
@@ -1440,11 +1442,13 @@
/// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
/// ```
///
- /// [`null`]: ../../std/ptr/fn.null.html
+ /// [`as_raw`]: struct.Weak.html#method.as_raw
+ /// [`new`]: struct.Weak.html#method.new
/// [`into_raw`]: struct.Weak.html#method.into_raw
/// [`upgrade`]: struct.Weak.html#method.upgrade
/// [`Weak`]: struct.Weak.html
/// [`Arc`]: struct.Arc.html
+ /// [`forget`]: ../../std/mem/fn.forget.html
#[unstable(feature = "weak_into_raw", issue = "60728")]
pub unsafe fn from_raw(ptr: *const T) -> Self {
if ptr.is_null() {
diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs
index 1b06bae..20248f7 100644
--- a/src/libcore/alloc.rs
+++ b/src/libcore/alloc.rs
@@ -53,7 +53,7 @@
impl Layout {
/// Constructs a `Layout` from a given `size` and `align`,
- /// or returns `LayoutErr` if either of the following conditions
+ /// or returns `LayoutErr` if any of the following conditions
/// are not met:
///
/// * `align` must not be zero,
@@ -137,7 +137,7 @@
#[inline]
pub fn for_value<T: ?Sized>(t: &T) -> Self {
let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
- // See rationale in `new` for why this us using an unsafe variant below
+ // See rationale in `new` for why this is using an unsafe variant below
debug_assert!(Layout::from_size_align(size, align).is_ok());
unsafe {
Layout::from_size_align_unchecked(size, align)
@@ -196,7 +196,7 @@
// valid.
//
// 2. `len + align - 1` can overflow by at most `align - 1`,
- // so the &-mask wth `!(align - 1)` will ensure that in the
+ // so the &-mask with `!(align - 1)` will ensure that in the
// case of overflow, `len_rounded_up` will itself be 0.
// Thus the returned padding, when added to `len`, yields 0,
// which trivially satisfies the alignment `align`.
@@ -213,18 +213,19 @@
/// Creates a layout by rounding the size of this layout up to a multiple
/// of the layout's alignment.
///
- /// Returns `Err` if the padded size would overflow.
- ///
/// This is equivalent to adding the result of `padding_needed_for`
/// to the layout's current size.
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
#[inline]
- pub fn pad_to_align(&self) -> Result<Layout, LayoutErr> {
+ pub fn pad_to_align(&self) -> Layout {
let pad = self.padding_needed_for(self.align());
- let new_size = self.size().checked_add(pad)
- .ok_or(LayoutErr { private: () })?;
+ // This cannot overflow. Quoting from the invariant of Layout:
+ // > `size`, when rounded up to the nearest multiple of `align`,
+ // > must not overflow (i.e., the rounded value must be less than
+ // > `usize::MAX`)
+ let new_size = self.size() + pad;
- Layout::from_size_align(new_size, self.align())
+ Layout::from_size_align(new_size, self.align()).unwrap()
}
/// Creates a layout describing the record for `n` instances of
diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs
index 617bdd2..1b3c254 100644
--- a/src/libcore/bool.rs
+++ b/src/libcore/bool.rs
@@ -9,12 +9,12 @@
/// ```
/// #![feature(bool_to_option)]
///
- /// assert_eq!(false.then(0), None);
- /// assert_eq!(true.then(0), Some(0));
+ /// assert_eq!(false.then_some(0), None);
+ /// assert_eq!(true.then_some(0), Some(0));
/// ```
#[unstable(feature = "bool_to_option", issue = "64260")]
#[inline]
- pub fn then<T>(self, t: T) -> Option<T> {
+ pub fn then_some<T>(self, t: T) -> Option<T> {
if self {
Some(t)
} else {
@@ -29,12 +29,12 @@
/// ```
/// #![feature(bool_to_option)]
///
- /// assert_eq!(false.then_with(|| 0), None);
- /// assert_eq!(true.then_with(|| 0), Some(0));
+ /// assert_eq!(false.then(|| 0), None);
+ /// assert_eq!(true.then(|| 0), Some(0));
/// ```
#[unstable(feature = "bool_to_option", issue = "64260")]
#[inline]
- pub fn then_with<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
+ pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
if self {
Some(f())
} else {
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index eea3dc3..a5f355c 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -534,7 +534,6 @@
/// }
/// }
/// ```
-#[lang = "ord"]
#[doc(alias = "<")]
#[doc(alias = ">")]
#[doc(alias = "<=")]
diff --git a/src/libcore/convert.rs b/src/libcore/convert/mod.rs
similarity index 98%
rename from src/libcore/convert.rs
rename to src/libcore/convert/mod.rs
index 08802b3..16d5375 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert/mod.rs
@@ -40,6 +40,11 @@
#![stable(feature = "rust1", since = "1.0.0")]
+mod num;
+
+#[unstable(feature = "convert_float_to_int", issue = "67057")]
+pub use num::FloatToInt;
+
/// The identity function.
///
/// Two things are important to note about this function:
diff --git a/src/libcore/convert/num.rs b/src/libcore/convert/num.rs
new file mode 100644
index 0000000..0877dac
--- /dev/null
+++ b/src/libcore/convert/num.rs
@@ -0,0 +1,369 @@
+use super::{From, TryFrom};
+use crate::num::TryFromIntError;
+
+mod private {
+ /// This trait being unreachable from outside the crate
+ /// prevents other implementations of the `FloatToInt` trait,
+ /// which allows potentially adding more trait methods after the trait is `#[stable]`.
+ #[unstable(feature = "convert_float_to_int", issue = "67057")]
+ pub trait Sealed {}
+}
+
+/// Supporting trait for inherent methods of `f32` and `f64` such as `round_unchecked_to`.
+/// Typically doesn’t need to be used directly.
+#[unstable(feature = "convert_float_to_int", issue = "67057")]
+pub trait FloatToInt<Int>: private::Sealed + Sized {
+ #[cfg(not(bootstrap))]
+ #[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
+ #[doc(hidden)]
+ unsafe fn approx_unchecked(self) -> Int;
+}
+
+macro_rules! impl_float_to_int {
+ ( $Float: ident => $( $Int: ident )+ ) => {
+ #[unstable(feature = "convert_float_to_int", issue = "67057")]
+ impl private::Sealed for $Float {}
+ $(
+ #[unstable(feature = "convert_float_to_int", issue = "67057")]
+ impl FloatToInt<$Int> for $Float {
+ #[cfg(not(bootstrap))]
+ #[doc(hidden)]
+ #[inline]
+ unsafe fn approx_unchecked(self) -> $Int {
+ crate::intrinsics::float_to_int_approx_unchecked(self)
+ }
+ }
+ )+
+ }
+}
+
+impl_float_to_int!(f32 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
+impl_float_to_int!(f64 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
+
+// Conversion traits for primitive integer and float types
+// Conversions T -> T are covered by a blanket impl and therefore excluded
+// Some conversions from and to usize/isize are not implemented due to portability concerns
+macro_rules! impl_from {
+ ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
+ #[$attr]
+ #[doc = $doc]
+ impl From<$Small> for $Large {
+ #[inline]
+ fn from(small: $Small) -> $Large {
+ small as $Large
+ }
+ }
+ };
+ ($Small: ty, $Large: ty, #[$attr:meta]) => {
+ impl_from!($Small,
+ $Large,
+ #[$attr],
+ concat!("Converts `",
+ stringify!($Small),
+ "` to `",
+ stringify!($Large),
+ "` losslessly."));
+ }
+}
+
+macro_rules! impl_from_bool {
+ ($target: ty, #[$attr:meta]) => {
+ impl_from!(bool, $target, #[$attr], concat!("Converts a `bool` to a `",
+ stringify!($target), "`. The resulting value is `0` for `false` and `1` for `true`
+values.
+
+# Examples
+
+```
+assert_eq!(", stringify!($target), "::from(true), 1);
+assert_eq!(", stringify!($target), "::from(false), 0);
+```"));
+ };
+}
+
+// Bool -> Any
+impl_from_bool! { u8, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u16, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u32, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u64, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u128, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { usize, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i8, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i16, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i32, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i64, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i128, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { isize, #[stable(feature = "from_bool", since = "1.28.0")] }
+
+// Unsigned -> Unsigned
+impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u32, u128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u64, u128, #[stable(feature = "i128", since = "1.26.0")] }
+
+// Signed -> Signed
+impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i32, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { i64, i128, #[stable(feature = "i128", since = "1.26.0")] }
+
+// Unsigned -> Signed
+impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u32, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u64, i128, #[stable(feature = "i128", since = "1.26.0")] }
+
+// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX
+// which imply that pointer-sized integers must be at least 16 bits:
+// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4
+impl_from! { u16, usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
+impl_from! { u8, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
+impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
+
+// RISC-V defines the possibility of a 128-bit address space (RV128).
+
+// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize.
+// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf
+// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf
+
+
+// Note: integers can only be represented with full precision in a float if
+// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
+// Lossy float conversions are not implemented at this time.
+
+// Signed -> Float
+impl_from! { i8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+
+// Unsigned -> Float
+impl_from! { u8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+
+// Float -> Float
+impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+
+// no possible bounds violation
+macro_rules! try_from_unbounded {
+ ($source:ty, $($target:ty),*) => {$(
+ #[stable(feature = "try_from", since = "1.34.0")]
+ impl TryFrom<$source> for $target {
+ type Error = TryFromIntError;
+
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
+ #[inline]
+ fn try_from(value: $source) -> Result<Self, Self::Error> {
+ Ok(value as $target)
+ }
+ }
+ )*}
+}
+
+// only negative bounds
+macro_rules! try_from_lower_bounded {
+ ($source:ty, $($target:ty),*) => {$(
+ #[stable(feature = "try_from", since = "1.34.0")]
+ impl TryFrom<$source> for $target {
+ type Error = TryFromIntError;
+
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
+ #[inline]
+ fn try_from(u: $source) -> Result<$target, TryFromIntError> {
+ if u >= 0 {
+ Ok(u as $target)
+ } else {
+ Err(TryFromIntError(()))
+ }
+ }
+ }
+ )*}
+}
+
+// unsigned to signed (only positive bound)
+macro_rules! try_from_upper_bounded {
+ ($source:ty, $($target:ty),*) => {$(
+ #[stable(feature = "try_from", since = "1.34.0")]
+ impl TryFrom<$source> for $target {
+ type Error = TryFromIntError;
+
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
+ #[inline]
+ fn try_from(u: $source) -> Result<$target, TryFromIntError> {
+ if u > (<$target>::max_value() as $source) {
+ Err(TryFromIntError(()))
+ } else {
+ Ok(u as $target)
+ }
+ }
+ }
+ )*}
+}
+
+// all other cases
+macro_rules! try_from_both_bounded {
+ ($source:ty, $($target:ty),*) => {$(
+ #[stable(feature = "try_from", since = "1.34.0")]
+ impl TryFrom<$source> for $target {
+ type Error = TryFromIntError;
+
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
+ #[inline]
+ fn try_from(u: $source) -> Result<$target, TryFromIntError> {
+ let min = <$target>::min_value() as $source;
+ let max = <$target>::max_value() as $source;
+ if u < min || u > max {
+ Err(TryFromIntError(()))
+ } else {
+ Ok(u as $target)
+ }
+ }
+ }
+ )*}
+}
+
+macro_rules! rev {
+ ($mac:ident, $source:ty, $($target:ty),*) => {$(
+ $mac!($target, $source);
+ )*}
+}
+
+// intra-sign conversions
+try_from_upper_bounded!(u16, u8);
+try_from_upper_bounded!(u32, u16, u8);
+try_from_upper_bounded!(u64, u32, u16, u8);
+try_from_upper_bounded!(u128, u64, u32, u16, u8);
+
+try_from_both_bounded!(i16, i8);
+try_from_both_bounded!(i32, i16, i8);
+try_from_both_bounded!(i64, i32, i16, i8);
+try_from_both_bounded!(i128, i64, i32, i16, i8);
+
+// unsigned-to-signed
+try_from_upper_bounded!(u8, i8);
+try_from_upper_bounded!(u16, i8, i16);
+try_from_upper_bounded!(u32, i8, i16, i32);
+try_from_upper_bounded!(u64, i8, i16, i32, i64);
+try_from_upper_bounded!(u128, i8, i16, i32, i64, i128);
+
+// signed-to-unsigned
+try_from_lower_bounded!(i8, u8, u16, u32, u64, u128);
+try_from_lower_bounded!(i16, u16, u32, u64, u128);
+try_from_lower_bounded!(i32, u32, u64, u128);
+try_from_lower_bounded!(i64, u64, u128);
+try_from_lower_bounded!(i128, u128);
+try_from_both_bounded!(i16, u8);
+try_from_both_bounded!(i32, u16, u8);
+try_from_both_bounded!(i64, u32, u16, u8);
+try_from_both_bounded!(i128, u64, u32, u16, u8);
+
+// usize/isize
+try_from_upper_bounded!(usize, isize);
+try_from_lower_bounded!(isize, usize);
+
+#[cfg(target_pointer_width = "16")]
+mod ptr_try_from_impls {
+ use super::TryFromIntError;
+ use crate::convert::TryFrom;
+
+ try_from_upper_bounded!(usize, u8);
+ try_from_unbounded!(usize, u16, u32, u64, u128);
+ try_from_upper_bounded!(usize, i8, i16);
+ try_from_unbounded!(usize, i32, i64, i128);
+
+ try_from_both_bounded!(isize, u8);
+ try_from_lower_bounded!(isize, u16, u32, u64, u128);
+ try_from_both_bounded!(isize, i8);
+ try_from_unbounded!(isize, i16, i32, i64, i128);
+
+ rev!(try_from_upper_bounded, usize, u32, u64, u128);
+ rev!(try_from_lower_bounded, usize, i8, i16);
+ rev!(try_from_both_bounded, usize, i32, i64, i128);
+
+ rev!(try_from_upper_bounded, isize, u16, u32, u64, u128);
+ rev!(try_from_both_bounded, isize, i32, i64, i128);
+}
+
+#[cfg(target_pointer_width = "32")]
+mod ptr_try_from_impls {
+ use super::TryFromIntError;
+ use crate::convert::TryFrom;
+
+ try_from_upper_bounded!(usize, u8, u16);
+ try_from_unbounded!(usize, u32, u64, u128);
+ try_from_upper_bounded!(usize, i8, i16, i32);
+ try_from_unbounded!(usize, i64, i128);
+
+ try_from_both_bounded!(isize, u8, u16);
+ try_from_lower_bounded!(isize, u32, u64, u128);
+ try_from_both_bounded!(isize, i8, i16);
+ try_from_unbounded!(isize, i32, i64, i128);
+
+ rev!(try_from_unbounded, usize, u32);
+ rev!(try_from_upper_bounded, usize, u64, u128);
+ rev!(try_from_lower_bounded, usize, i8, i16, i32);
+ rev!(try_from_both_bounded, usize, i64, i128);
+
+ rev!(try_from_unbounded, isize, u16);
+ rev!(try_from_upper_bounded, isize, u32, u64, u128);
+ rev!(try_from_unbounded, isize, i32);
+ rev!(try_from_both_bounded, isize, i64, i128);
+}
+
+#[cfg(target_pointer_width = "64")]
+mod ptr_try_from_impls {
+ use super::TryFromIntError;
+ use crate::convert::TryFrom;
+
+ try_from_upper_bounded!(usize, u8, u16, u32);
+ try_from_unbounded!(usize, u64, u128);
+ try_from_upper_bounded!(usize, i8, i16, i32, i64);
+ try_from_unbounded!(usize, i128);
+
+ try_from_both_bounded!(isize, u8, u16, u32);
+ try_from_lower_bounded!(isize, u64, u128);
+ try_from_both_bounded!(isize, i8, i16, i32);
+ try_from_unbounded!(isize, i64, i128);
+
+ rev!(try_from_unbounded, usize, u32, u64);
+ rev!(try_from_upper_bounded, usize, u128);
+ rev!(try_from_lower_bounded, usize, i8, i16, i32, i64);
+ rev!(try_from_both_bounded, usize, i128);
+
+ rev!(try_from_unbounded, isize, u16, u32);
+ rev!(try_from_upper_bounded, isize, u64, u128);
+ rev!(try_from_unbounded, isize, i32, i64);
+ rev!(try_from_both_bounded, isize, i128);
+}
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 4c941e2..e2f49ee 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -662,7 +662,7 @@
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// let val = self.0;
///
-/// write!(f, "{:o}", val) // delegate to i32's implementation
+/// fmt::Octal::fmt(&val, f) // delegate to i32's implementation
/// }
/// }
///
@@ -712,7 +712,7 @@
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// let val = self.0;
///
-/// write!(f, "{:b}", val) // delegate to i32's implementation
+/// fmt::Binary::fmt(&val, f) // delegate to i32's implementation
/// }
/// }
///
@@ -771,7 +771,7 @@
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// let val = self.0;
///
-/// write!(f, "{:x}", val) // delegate to i32's implementation
+/// fmt::LowerHex::fmt(&val, f) // delegate to i32's implementation
/// }
/// }
///
@@ -824,7 +824,7 @@
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// let val = self.0;
///
-/// write!(f, "{:X}", val) // delegate to i32's implementation
+/// fmt::UpperHex::fmt(&val, f) // delegate to i32's implementation
/// }
/// }
///
@@ -869,7 +869,8 @@
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// // use `as` to convert to a `*const T`, which implements Pointer, which we can use
///
-/// write!(f, "{:p}", self as *const Length)
+/// let ptr = self as *const Self;
+/// fmt::Pointer::fmt(&ptr, f)
/// }
/// }
///
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index e3dc563..18aae59 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -939,6 +939,7 @@
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_transmute")]
pub fn transmute<T, U>(e: T) -> U;
/// Returns `true` if the actual type given as `T` requires drop
@@ -1143,6 +1144,11 @@
/// May assume inputs are finite.
pub fn frem_fast<T>(a: T, b: T) -> T;
+ /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range
+ /// https://github.com/rust-lang/rust/issues/10184
+ #[cfg(not(bootstrap))]
+ pub fn float_to_int_approx_unchecked<Float, Int>(value: Float) -> Int;
+
/// Returns the number of bits set in an integer type `T`
pub fn ctpop<T>(x: T) -> T;
@@ -1348,9 +1354,11 @@
pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
/// Internal hook used by Miri to implement unwinding.
+ /// Compiles to a NOP during non-Miri codegen.
+ ///
/// Perma-unstable: do not use
#[cfg(not(bootstrap))]
- pub fn miri_start_panic(data: *mut (dyn crate::any::Any + crate::marker::Send)) -> !;
+ pub fn miri_start_panic(data: *mut (dyn crate::any::Any + crate::marker::Send)) -> ();
}
// Some functions are defined here because they accidentally got made
diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs
index bbdb169..d6ae5cf 100644
--- a/src/libcore/iter/traits/collect.rs
+++ b/src/libcore/iter/traits/collect.rs
@@ -91,9 +91,9 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
- message="a collection of type `{Self}` cannot be built from an iterator \
+ message="a value of type `{Self}` cannot be built from an iterator \
over elements of type `{A}`",
- label="a collection of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`",
+ label="value of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`",
)]
pub trait FromIterator<A>: Sized {
/// Creates a value from an iterator.
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index ec19392..188ea1a 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -74,6 +74,8 @@
#![feature(const_fn)]
#![feature(const_fn_union)]
#![feature(const_generics)]
+#![cfg_attr(not(bootstrap), feature(const_ptr_offset_from))]
+#![cfg_attr(not(bootstrap), feature(const_type_name))]
#![feature(custom_inner_attributes)]
#![feature(decl_macro)]
#![feature(doc_cfg)]
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 913c0f9..ac06f95 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -7,9 +7,10 @@
#![stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(bootstrap))]
+use crate::convert::FloatToInt;
#[cfg(not(test))]
use crate::intrinsics;
-
use crate::mem;
use crate::num::FpCategory;
@@ -400,6 +401,35 @@
intrinsics::minnumf32(self, other)
}
+ /// Rounds toward zero and converts to any primitive integer type,
+ /// assuming that the value is finite and fits in that type.
+ ///
+ /// ```
+ /// #![feature(float_approx_unchecked_to)]
+ ///
+ /// let value = 4.6_f32;
+ /// let rounded = unsafe { value.approx_unchecked_to::<u16>() };
+ /// assert_eq!(rounded, 4);
+ ///
+ /// let value = -128.9_f32;
+ /// let rounded = unsafe { value.approx_unchecked_to::<i8>() };
+ /// assert_eq!(rounded, std::i8::MIN);
+ /// ```
+ ///
+ /// # Safety
+ ///
+ /// The value must:
+ ///
+ /// * Not be `NaN`
+ /// * Not be infinite
+ /// * Be representable in the return type `Int`, after truncating off its fractional part
+ #[cfg(not(bootstrap))]
+ #[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
+ #[inline]
+ pub unsafe fn approx_unchecked_to<Int>(self) -> Int where Self: FloatToInt<Int> {
+ FloatToInt::<Int>::approx_unchecked(self)
+ }
+
/// Raw transmutation to `u32`.
///
/// This is currently identical to `transmute::<f32, u32>(self)` on all platforms.
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index 6ca830b..794f77f 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -7,9 +7,10 @@
#![stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(bootstrap))]
+use crate::convert::FloatToInt;
#[cfg(not(test))]
use crate::intrinsics;
-
use crate::mem;
use crate::num::FpCategory;
@@ -413,6 +414,35 @@
intrinsics::minnumf64(self, other)
}
+ /// Rounds toward zero and converts to any primitive integer type,
+ /// assuming that the value is finite and fits in that type.
+ ///
+ /// ```
+ /// #![feature(float_approx_unchecked_to)]
+ ///
+ /// let value = 4.6_f32;
+ /// let rounded = unsafe { value.approx_unchecked_to::<u16>() };
+ /// assert_eq!(rounded, 4);
+ ///
+ /// let value = -128.9_f32;
+ /// let rounded = unsafe { value.approx_unchecked_to::<i8>() };
+ /// assert_eq!(rounded, std::i8::MIN);
+ /// ```
+ ///
+ /// # Safety
+ ///
+ /// The value must:
+ ///
+ /// * Not be `NaN`
+ /// * Not be infinite
+ /// * Be representable in the return type `Int`, after truncating off its fractional part
+ #[cfg(not(bootstrap))]
+ #[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
+ #[inline]
+ pub unsafe fn approx_unchecked_to<Int>(self) -> Int where Self: FloatToInt<Int> {
+ FloatToInt::<Int>::approx_unchecked(self)
+ }
+
/// Raw transmutation to `u64`.
///
/// This is currently identical to `transmute::<f64, u64>(self)` on all platforms.
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 4313248..585f144 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -4,7 +4,6 @@
#![stable(feature = "rust1", since = "1.0.0")]
-use crate::convert::TryFrom;
use crate::fmt;
use crate::intrinsics;
use crate::mem;
@@ -4701,7 +4700,7 @@
/// The error type returned when a checked integral type conversion fails.
#[stable(feature = "try_from", since = "1.34.0")]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub struct TryFromIntError(());
+pub struct TryFromIntError(pub(crate) ());
impl TryFromIntError {
#[unstable(feature = "int_error_internals",
@@ -4728,206 +4727,6 @@
}
}
-// no possible bounds violation
-macro_rules! try_from_unbounded {
- ($source:ty, $($target:ty),*) => {$(
- #[stable(feature = "try_from", since = "1.34.0")]
- impl TryFrom<$source> for $target {
- type Error = TryFromIntError;
-
- /// Try to create the target number type from a source
- /// number type. This returns an error if the source value
- /// is outside of the range of the target type.
- #[inline]
- fn try_from(value: $source) -> Result<Self, Self::Error> {
- Ok(value as $target)
- }
- }
- )*}
-}
-
-// only negative bounds
-macro_rules! try_from_lower_bounded {
- ($source:ty, $($target:ty),*) => {$(
- #[stable(feature = "try_from", since = "1.34.0")]
- impl TryFrom<$source> for $target {
- type Error = TryFromIntError;
-
- /// Try to create the target number type from a source
- /// number type. This returns an error if the source value
- /// is outside of the range of the target type.
- #[inline]
- fn try_from(u: $source) -> Result<$target, TryFromIntError> {
- if u >= 0 {
- Ok(u as $target)
- } else {
- Err(TryFromIntError(()))
- }
- }
- }
- )*}
-}
-
-// unsigned to signed (only positive bound)
-macro_rules! try_from_upper_bounded {
- ($source:ty, $($target:ty),*) => {$(
- #[stable(feature = "try_from", since = "1.34.0")]
- impl TryFrom<$source> for $target {
- type Error = TryFromIntError;
-
- /// Try to create the target number type from a source
- /// number type. This returns an error if the source value
- /// is outside of the range of the target type.
- #[inline]
- fn try_from(u: $source) -> Result<$target, TryFromIntError> {
- if u > (<$target>::max_value() as $source) {
- Err(TryFromIntError(()))
- } else {
- Ok(u as $target)
- }
- }
- }
- )*}
-}
-
-// all other cases
-macro_rules! try_from_both_bounded {
- ($source:ty, $($target:ty),*) => {$(
- #[stable(feature = "try_from", since = "1.34.0")]
- impl TryFrom<$source> for $target {
- type Error = TryFromIntError;
-
- /// Try to create the target number type from a source
- /// number type. This returns an error if the source value
- /// is outside of the range of the target type.
- #[inline]
- fn try_from(u: $source) -> Result<$target, TryFromIntError> {
- let min = <$target>::min_value() as $source;
- let max = <$target>::max_value() as $source;
- if u < min || u > max {
- Err(TryFromIntError(()))
- } else {
- Ok(u as $target)
- }
- }
- }
- )*}
-}
-
-macro_rules! rev {
- ($mac:ident, $source:ty, $($target:ty),*) => {$(
- $mac!($target, $source);
- )*}
-}
-
-// intra-sign conversions
-try_from_upper_bounded!(u16, u8);
-try_from_upper_bounded!(u32, u16, u8);
-try_from_upper_bounded!(u64, u32, u16, u8);
-try_from_upper_bounded!(u128, u64, u32, u16, u8);
-
-try_from_both_bounded!(i16, i8);
-try_from_both_bounded!(i32, i16, i8);
-try_from_both_bounded!(i64, i32, i16, i8);
-try_from_both_bounded!(i128, i64, i32, i16, i8);
-
-// unsigned-to-signed
-try_from_upper_bounded!(u8, i8);
-try_from_upper_bounded!(u16, i8, i16);
-try_from_upper_bounded!(u32, i8, i16, i32);
-try_from_upper_bounded!(u64, i8, i16, i32, i64);
-try_from_upper_bounded!(u128, i8, i16, i32, i64, i128);
-
-// signed-to-unsigned
-try_from_lower_bounded!(i8, u8, u16, u32, u64, u128);
-try_from_lower_bounded!(i16, u16, u32, u64, u128);
-try_from_lower_bounded!(i32, u32, u64, u128);
-try_from_lower_bounded!(i64, u64, u128);
-try_from_lower_bounded!(i128, u128);
-try_from_both_bounded!(i16, u8);
-try_from_both_bounded!(i32, u16, u8);
-try_from_both_bounded!(i64, u32, u16, u8);
-try_from_both_bounded!(i128, u64, u32, u16, u8);
-
-// usize/isize
-try_from_upper_bounded!(usize, isize);
-try_from_lower_bounded!(isize, usize);
-
-#[cfg(target_pointer_width = "16")]
-mod ptr_try_from_impls {
- use super::TryFromIntError;
- use crate::convert::TryFrom;
-
- try_from_upper_bounded!(usize, u8);
- try_from_unbounded!(usize, u16, u32, u64, u128);
- try_from_upper_bounded!(usize, i8, i16);
- try_from_unbounded!(usize, i32, i64, i128);
-
- try_from_both_bounded!(isize, u8);
- try_from_lower_bounded!(isize, u16, u32, u64, u128);
- try_from_both_bounded!(isize, i8);
- try_from_unbounded!(isize, i16, i32, i64, i128);
-
- rev!(try_from_upper_bounded, usize, u32, u64, u128);
- rev!(try_from_lower_bounded, usize, i8, i16);
- rev!(try_from_both_bounded, usize, i32, i64, i128);
-
- rev!(try_from_upper_bounded, isize, u16, u32, u64, u128);
- rev!(try_from_both_bounded, isize, i32, i64, i128);
-}
-
-#[cfg(target_pointer_width = "32")]
-mod ptr_try_from_impls {
- use super::TryFromIntError;
- use crate::convert::TryFrom;
-
- try_from_upper_bounded!(usize, u8, u16);
- try_from_unbounded!(usize, u32, u64, u128);
- try_from_upper_bounded!(usize, i8, i16, i32);
- try_from_unbounded!(usize, i64, i128);
-
- try_from_both_bounded!(isize, u8, u16);
- try_from_lower_bounded!(isize, u32, u64, u128);
- try_from_both_bounded!(isize, i8, i16);
- try_from_unbounded!(isize, i32, i64, i128);
-
- rev!(try_from_unbounded, usize, u32);
- rev!(try_from_upper_bounded, usize, u64, u128);
- rev!(try_from_lower_bounded, usize, i8, i16, i32);
- rev!(try_from_both_bounded, usize, i64, i128);
-
- rev!(try_from_unbounded, isize, u16);
- rev!(try_from_upper_bounded, isize, u32, u64, u128);
- rev!(try_from_unbounded, isize, i32);
- rev!(try_from_both_bounded, isize, i64, i128);
-}
-
-#[cfg(target_pointer_width = "64")]
-mod ptr_try_from_impls {
- use super::TryFromIntError;
- use crate::convert::TryFrom;
-
- try_from_upper_bounded!(usize, u8, u16, u32);
- try_from_unbounded!(usize, u64, u128);
- try_from_upper_bounded!(usize, i8, i16, i32, i64);
- try_from_unbounded!(usize, i128);
-
- try_from_both_bounded!(isize, u8, u16, u32);
- try_from_lower_bounded!(isize, u64, u128);
- try_from_both_bounded!(isize, i8, i16, i32);
- try_from_unbounded!(isize, i64, i128);
-
- rev!(try_from_unbounded, usize, u32, u64);
- rev!(try_from_upper_bounded, usize, u128);
- rev!(try_from_lower_bounded, usize, i8, i16, i32, i64);
- rev!(try_from_both_bounded, usize, i128);
-
- rev!(try_from_unbounded, isize, u16, u32);
- rev!(try_from_upper_bounded, isize, u64, u128);
- rev!(try_from_unbounded, isize, i32, i64);
- rev!(try_from_both_bounded, isize, i128);
-}
-
#[doc(hidden)]
trait FromStrRadixHelper: PartialOrd + Copy {
fn min_value() -> Self;
@@ -5110,131 +4909,3 @@
#[stable(feature = "rust1", since = "1.0.0")]
pub use crate::num::dec2flt::ParseFloatError;
-
-// Conversion traits for primitive integer and float types
-// Conversions T -> T are covered by a blanket impl and therefore excluded
-// Some conversions from and to usize/isize are not implemented due to portability concerns
-macro_rules! impl_from {
- ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
- #[$attr]
- #[doc = $doc]
- impl From<$Small> for $Large {
- #[inline]
- fn from(small: $Small) -> $Large {
- small as $Large
- }
- }
- };
- ($Small: ty, $Large: ty, #[$attr:meta]) => {
- impl_from!($Small,
- $Large,
- #[$attr],
- concat!("Converts `",
- stringify!($Small),
- "` to `",
- stringify!($Large),
- "` losslessly."));
- }
-}
-
-macro_rules! impl_from_bool {
- ($target: ty, #[$attr:meta]) => {
- impl_from!(bool, $target, #[$attr], concat!("Converts a `bool` to a `",
- stringify!($target), "`. The resulting value is `0` for `false` and `1` for `true`
-values.
-
-# Examples
-
-```
-assert_eq!(", stringify!($target), "::from(true), 1);
-assert_eq!(", stringify!($target), "::from(false), 0);
-```"));
- };
-}
-
-// Bool -> Any
-impl_from_bool! { u8, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u16, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u32, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u64, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u128, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { usize, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i8, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i16, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i32, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i64, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i128, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { isize, #[stable(feature = "from_bool", since = "1.28.0")] }
-
-// Unsigned -> Unsigned
-impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, u128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, u128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u32, u128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u64, u128, #[stable(feature = "i128", since = "1.26.0")] }
-
-// Signed -> Signed
-impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i8, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i16, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i32, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { i64, i128, #[stable(feature = "i128", since = "1.26.0")] }
-
-// Unsigned -> Signed
-impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u32, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u64, i128, #[stable(feature = "i128", since = "1.26.0")] }
-
-// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX
-// which imply that pointer-sized integers must be at least 16 bits:
-// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4
-impl_from! { u16, usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
-impl_from! { u8, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
-impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
-
-// RISC-V defines the possibility of a 128-bit address space (RV128).
-
-// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize.
-// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf
-// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf
-
-
-// Note: integers can only be represented with full precision in a float if
-// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
-// Lossy float conversions are not implemented at this time.
-
-// Signed -> Float
-impl_from! { i8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-
-// Unsigned -> Float
-impl_from! { u8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-
-// Float -> Float
-impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs
index 4f46520..a748ee8 100644
--- a/src/libcore/ops/try.rs
+++ b/src/libcore/ops/try.rs
@@ -5,19 +5,20 @@
/// extracting those success or failure values from an existing instance and
/// creating a new instance from a success or failure value.
#[unstable(feature = "try_trait", issue = "42327")]
-#[rustc_on_unimplemented(
+#[cfg_attr(not(bootstrap), rustc_on_unimplemented(
on(all(
any(from_method="from_error", from_method="from_ok"),
from_desugaring="QuestionMark"),
message="the `?` operator can only be used in {ItemContext} \
that returns `Result` or `Option` \
(or another type that implements `{Try}`)",
-label="cannot use the `?` operator in {ItemContext} that returns `{Self}`"),
+label="cannot use the `?` operator in {ItemContext} that returns `{Self}`",
+enclosing_scope="this function should return `Result` or `Option` to accept `?`"),
on(all(from_method="into_result", from_desugaring="QuestionMark"),
message="the `?` operator can only be applied to values \
that implement `{Try}`",
label="the `?` operator cannot be applied to type `{Self}`")
-)]
+))]
#[doc(alias = "?")]
pub trait Try {
/// The type of this value when viewed as successful.
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 25b7eec..b2a420f 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -3371,8 +3371,8 @@
/// An iterator over the disjoint matches of a pattern within the given string
/// slice.
///
- /// The pattern can be any type that implements the Pattern trait. Notable
- /// examples are `&str`, [`char`], and closures that determines the split.
+ /// The pattern can be a `&str`, [`char`], or a closure that determines if
+ /// a character matches.
///
/// # Iterator behavior
///
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 251d49d..6e1aac0 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -27,7 +27,7 @@
//!
//! Atomic variables are safe to share between threads (they implement [`Sync`])
//! but they do not themselves provide the mechanism for sharing and follow the
-//! [threading model](../../../std/thread/index.html#the-threading-model) of rust.
+//! [threading model](../../../std/thread/index.html#the-threading-model) of Rust.
//! The most common way to share an atomic variable is to put it into an [`Arc`][arc] (an
//! atomically-reference-counted shared pointer).
//!
diff --git a/src/libcore/tests/bool.rs b/src/libcore/tests/bool.rs
index 0f1e6e8..e89eb2c 100644
--- a/src/libcore/tests/bool.rs
+++ b/src/libcore/tests/bool.rs
@@ -1,7 +1,7 @@
#[test]
fn test_bool_to_option() {
- assert_eq!(false.then(0), None);
- assert_eq!(true.then(0), Some(0));
- assert_eq!(false.then_with(|| 0), None);
- assert_eq!(true.then_with(|| 0), Some(0));
+ assert_eq!(false.then_some(0), None);
+ assert_eq!(true.then_some(0), Some(0));
+ assert_eq!(false.then(|| 0), None);
+ assert_eq!(true.then(|| 0), Some(0));
}
diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs
index 900c6ed..2ecbe77 100644
--- a/src/libfmt_macros/lib.rs
+++ b/src/libfmt_macros/lib.rs
@@ -11,6 +11,7 @@
#![feature(nll)]
#![feature(rustc_private)]
#![feature(unicode_internals)]
+#![feature(bool_to_option)]
pub use Piece::*;
pub use Position::*;
@@ -644,11 +645,7 @@
break;
}
}
- if found {
- Some(cur)
- } else {
- None
- }
+ found.then_some(cur)
}
}
diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs
index 0c834e5..3a14197 100644
--- a/src/libpanic_unwind/lib.rs
+++ b/src/libpanic_unwind/lib.rs
@@ -36,10 +36,7 @@
use core::panic::BoxMeUp;
cfg_if::cfg_if! {
- if #[cfg(miri)] {
- #[path = "miri.rs"]
- mod imp;
- } else if #[cfg(target_os = "emscripten")] {
+ if #[cfg(target_os = "emscripten")] {
#[path = "emcc.rs"]
mod imp;
} else if #[cfg(target_arch = "wasm32")] {
@@ -94,5 +91,14 @@
#[unwind(allowed)]
pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 {
let payload = payload as *mut &mut dyn BoxMeUp;
- imp::panic(Box::from_raw((*payload).take_box()))
+ let payload = (*payload).take_box();
+
+ // Miri panic support: cfg'd out of normal builds just to be sure.
+ // When going through normal codegen, `miri_start_panic` is a NOP, so the
+ // Miri-enabled sysroot still supports normal unwinding. But when executed in
+ // Miri, this line initiates unwinding.
+ #[cfg(miri)]
+ core::intrinsics::miri_start_panic(payload);
+
+ imp::panic(Box::from_raw(payload))
}
diff --git a/src/libpanic_unwind/miri.rs b/src/libpanic_unwind/miri.rs
deleted file mode 100644
index f26c42f..0000000
--- a/src/libpanic_unwind/miri.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-#![allow(nonstandard_style)]
-
-use core::any::Any;
-use alloc::boxed::Box;
-
-pub fn payload() -> *mut u8 {
- core::ptr::null_mut()
-}
-
-pub unsafe fn panic(data: Box<dyn Any + Send>) -> ! {
- core::intrinsics::miri_start_panic(Box::into_raw(data))
-}
-
-pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
- Box::from_raw(ptr)
-}
-
-// This is required by the compiler to exist (e.g., it's a lang item),
-// but is never used by Miri. Therefore, we just use a stub here
-#[lang = "eh_personality"]
-#[cfg(not(test))]
-fn rust_eh_personality() {
- unsafe { core::intrinsics::abort() }
-}
-
-// The rest is required on *some* targets to exist (specifically, MSVC targets that use SEH).
-// We just add it on all targets. Copied from `seh.rs`.
-#[repr(C)]
-pub struct _TypeDescriptor {
- pub pVFTable: *const u8,
- pub spare: *mut u8,
- pub name: [u8; 11],
-}
-
-const TYPE_NAME: [u8; 11] = *b"rust_panic\0";
-
-#[cfg_attr(not(test), lang = "eh_catch_typeinfo")]
-static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
- pVFTable: core::ptr::null(),
- spare: core::ptr::null_mut(),
- name: TYPE_NAME,
-};
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index fb30d6c..f8ad6f8 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -39,3 +39,4 @@
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
measureme = "0.4"
rustc_error_codes = { path = "../librustc_error_codes" }
+rustc_session = { path = "../librustc_session" }
diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs
index 1d6a342..364a35f 100644
--- a/src/librustc/arena.rs
+++ b/src/librustc/arena.rs
@@ -23,17 +23,17 @@
[] generics: rustc::ty::Generics,
[] trait_def: rustc::ty::TraitDef,
[] adt_def: rustc::ty::AdtDef,
- [] steal_mir: rustc::ty::steal::Steal<rustc::mir::Body<$tcx>>,
- [] mir: rustc::mir::Body<$tcx>,
+ [] steal_mir: rustc::ty::steal::Steal<rustc::mir::BodyCache<$tcx>>,
+ [] mir: rustc::mir::BodyCache<$tcx>,
[] steal_promoted: rustc::ty::steal::Steal<
rustc_index::vec::IndexVec<
rustc::mir::Promoted,
- rustc::mir::Body<$tcx>
+ rustc::mir::BodyCache<$tcx>
>
>,
[] promoted: rustc_index::vec::IndexVec<
rustc::mir::Promoted,
- rustc::mir::Body<$tcx>
+ rustc::mir::BodyCache<$tcx>
>,
[] tables: rustc::ty::TypeckTables<$tcx>,
[] const_allocs: rustc::mir::interpret::Allocation,
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 0104507..d952bf7 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -710,14 +710,25 @@
return None
}
None => {
- if !tcx.sess.has_errors() {
+ if !tcx.sess.has_errors_or_delayed_span_bugs() {
bug!("try_mark_previous_green() - Forcing the DepNode \
should have set its color")
} else {
- // If the query we just forced has resulted
- // in some kind of compilation error, we
- // don't expect that the corresponding
- // dep-node color has been updated.
+ // If the query we just forced has resulted in
+ // some kind of compilation error, we cannot rely on
+ // the dep-node color having been properly updated.
+ // This means that the query system has reached an
+ // invalid state. We let the compiler continue (by
+ // returning `None`) so it can emit error messages
+ // and wind down, but rely on the fact that this
+ // invalid state will not be persisted to the
+ // incremental compilation cache because of
+ // compilation errors being present.
+ debug!("try_mark_previous_green({:?}) - END - \
+ dependency {:?} resulted in compilation error",
+ dep_node,
+ dep_dep_node);
+ return None
}
}
}
diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs
index 43f3d7e..a1321d5 100644
--- a/src/librustc/dep_graph/mod.rs
+++ b/src/librustc/dep_graph/mod.rs
@@ -5,7 +5,6 @@
mod query;
mod safe;
mod serialized;
-pub mod cgu_reuse_tracker;
pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, RecoverKey, label_strs};
pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor, TaskDeps, hash_result};
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index ac8173f..e13f6ca 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1003,7 +1003,7 @@
AttrKind::Normal(ref item) => {
AttrKind::Normal(AttrItem {
path: item.path.clone(),
- tokens: self.lower_token_stream(item.tokens.clone()),
+ args: self.lower_mac_args(&item.args),
})
}
AttrKind::DocComment(comment) => AttrKind::DocComment(comment)
@@ -1017,6 +1017,16 @@
}
}
+ fn lower_mac_args(&mut self, args: &MacArgs) -> MacArgs {
+ match *args {
+ MacArgs::Empty => MacArgs::Empty,
+ MacArgs::Delimited(dspan, delim, ref tokens) =>
+ MacArgs::Delimited(dspan, delim, self.lower_token_stream(tokens.clone())),
+ MacArgs::Eq(eq_span, ref tokens) =>
+ MacArgs::Eq(eq_span, self.lower_token_stream(tokens.clone())),
+ }
+ }
+
fn lower_token_stream(&mut self, tokens: TokenStream) -> TokenStream {
tokens
.into_trees()
diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs
index f689e7f..ff9d8c8 100644
--- a/src/librustc/hir/lowering/item.rs
+++ b/src/librustc/hir/lowering/item.rs
@@ -233,7 +233,7 @@
if let ItemKind::MacroDef(ref def) = i.kind {
if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) {
- let body = self.lower_token_stream(def.stream());
+ let body = self.lower_token_stream(def.body.inner_tokens());
let hir_id = self.lower_node_id(i.id);
self.exported_macros.push(hir::MacroDef {
name: ident.name,
diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs
index f25f3b5..8f9f398 100644
--- a/src/librustc/hir/map/blocks.rs
+++ b/src/librustc/hir/map/blocks.rs
@@ -147,13 +147,7 @@
map::Node::Expr(e) => e.is_fn_like(),
_ => false
};
- if fn_like {
- Some(FnLikeNode {
- node,
- })
- } else {
- None
- }
+ fn_like.then_some(FnLikeNode { node })
}
pub fn body(self) -> ast::BodyId {
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 5a940f2..58c1498 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -1809,12 +1809,17 @@
sub_region,
"...",
);
- err.note(&format!(
- "...so that the {}:\nexpected {}\n found {}",
- sup_trace.cause.as_requirement_str(),
- sup_expected.content(),
- sup_found.content()
+ err.span_note(sup_trace.cause.span, &format!(
+ "...so that the {}",
+ sup_trace.cause.as_requirement_str()
));
+
+ err.note_expected_found(
+ &"",
+ sup_expected,
+ &"",
+ sup_found
+ );
err.emit();
return;
}
diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs
index c1f840a..4b93373 100644
--- a/src/librustc/infer/error_reporting/note.rs
+++ b/src/librustc/infer/error_reporting/note.rs
@@ -13,12 +13,20 @@
match *origin {
infer::Subtype(ref trace) => {
if let Some((expected, found)) = self.values_str(&trace.values) {
- let expected = expected.content();
- let found = found.content();
- err.note(&format!("...so that the {}:\nexpected {}\n found {}",
- trace.cause.as_requirement_str(),
- expected,
- found));
+ err.span_note(
+ trace.cause.span,
+ &format!(
+ "...so that the {}",
+ trace.cause.as_requirement_str()
+ )
+ );
+
+ err.note_expected_found(
+ &"",
+ expected,
+ &"",
+ found
+ );
} else {
// FIXME: this really should be handled at some earlier stage. Our
// handling of region checking when type errors are present is
diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs
index 3110b02..3e28145 100644
--- a/src/librustc/infer/outlives/verify.rs
+++ b/src/librustc/infer/outlives/verify.rs
@@ -211,11 +211,7 @@
(r, p)
);
let p_ty = p.to_ty(tcx);
- if compare_ty(p_ty) {
- Some(ty::OutlivesPredicate(p_ty, r))
- } else {
- None
- }
+ compare_ty(p_ty).then_some(ty::OutlivesPredicate(p_ty, r))
});
param_bounds
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 481ae3b..24b87ff 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -29,6 +29,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(arbitrary_self_types)]
+#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(const_fn)]
@@ -64,7 +65,6 @@
#![recursion_limit="512"]
#[macro_use] extern crate bitflags;
-extern crate getopts;
#[macro_use] extern crate scoped_tls;
#[cfg(windows)]
extern crate libc;
@@ -74,10 +74,6 @@
#[macro_use] extern crate syntax;
#[macro_use] extern crate smallvec;
-// Use the test crate here so we depend on getopts through it. This allow tools to link to both
-// librustc_driver and libtest.
-extern crate test as _;
-
#[cfg(test)]
mod tests;
@@ -113,7 +109,7 @@
}
pub mod mir;
-pub mod session;
+pub use rustc_session as session;
pub mod traits;
pub mod ty;
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index f8a592d..1aba73e 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -12,6 +12,8 @@
use syntax::edition::Edition;
use syntax::source_map::Span;
use syntax::symbol::Symbol;
+use syntax::early_buffered_lints::{ILL_FORMED_ATTRIBUTE_INPUT, META_VARIABLE_MISUSE};
+use rustc_session::declare_lint;
declare_lint! {
pub EXCEEDING_BITSHIFTS,
@@ -404,31 +406,6 @@
};
}
-/// Some lints that are buffered from `libsyntax`. See `syntax::early_buffered_lints`.
-pub mod parser {
- declare_lint! {
- pub ILL_FORMED_ATTRIBUTE_INPUT,
- Deny,
- "ill-formed attribute inputs that were previously accepted and used in practice",
- @future_incompatible = super::FutureIncompatibleInfo {
- reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
- edition: None,
- };
- }
-
- declare_lint! {
- pub META_VARIABLE_MISUSE,
- Allow,
- "possible meta-variable misuse at macro definition"
- }
-
- declare_lint! {
- pub INCOMPLETE_INCLUDE,
- Deny,
- "trailing content in included file"
- }
-}
-
declare_lint! {
pub DEPRECATED_IN_FUTURE,
Allow,
@@ -520,8 +497,8 @@
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
MACRO_USE_EXTERN_CRATE,
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
- parser::ILL_FORMED_ATTRIBUTE_INPUT,
- parser::META_VARIABLE_MISUSE,
+ ILL_FORMED_ATTRIBUTE_INPUT,
+ META_VARIABLE_MISUSE,
DEPRECATED_IN_FUTURE,
AMBIGUOUS_ASSOCIATED_ITEMS,
MUTABLE_BORROW_RESERVATION_CONFLICT,
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 05543f1..7f72154 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -47,8 +47,7 @@
/// This is basically the subset of `Context` that we can
/// build early in the compile pipeline.
pub struct LintStore {
- /// Registered lints. The bool is true if the lint was
- /// added by a plugin.
+ /// Registered lints.
lints: Vec<&'static Lint>,
/// Constructor functions for each variety of lint pass.
diff --git a/src/librustc/lint/internal.rs b/src/librustc/lint/internal.rs
index 1c5f86f..10c0c63 100644
--- a/src/librustc/lint/internal.rs
+++ b/src/librustc/lint/internal.rs
@@ -9,6 +9,7 @@
use rustc_data_structures::fx::FxHashMap;
use syntax::ast::{Ident, Item, ItemKind};
use syntax::symbol::{sym, Symbol};
+use rustc_session::declare_tool_lint;
declare_tool_lint! {
pub rustc::DEFAULT_HASH_TYPES,
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index 619ca72..f29d1a3 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -8,7 +8,7 @@
use crate::session::Session;
use crate::util::nodemap::FxHashMap;
use errors::{Applicability, DiagnosticBuilder};
-use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use syntax::ast;
use syntax::attr;
use syntax::feature_gate;
@@ -93,7 +93,7 @@
// If `level` is none then we actually assume the default level for this
// lint.
- let mut level = level.unwrap_or_else(|| lint.default_level(sess));
+ let mut level = level.unwrap_or_else(|| lint.default_level(sess.edition()));
// If we're about to issue a warning, check at the last minute for any
// directives against the warnings "lint". If, for example, there's an
@@ -566,19 +566,3 @@
})
}
}
-
-impl<HCX> HashStable<HCX> for LintId {
- #[inline]
- fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
- self.lint_name_raw().hash_stable(hcx, hasher);
- }
-}
-
-impl<HCX> ToStableHashKey<HCX> for LintId {
- type KeyType = &'static str;
-
- #[inline]
- fn to_stable_hash_key(&self, _: &HCX) -> &'static str {
- self.lint_name_raw()
- }
-}
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index d84102f..a8d8868 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -27,19 +27,14 @@
use crate::hir::intravisit;
use crate::hir;
use crate::lint::builtin::BuiltinLintDiagnostics;
-use crate::lint::builtin::parser::{ILL_FORMED_ATTRIBUTE_INPUT, META_VARIABLE_MISUSE};
-use crate::lint::builtin::parser::INCOMPLETE_INCLUDE;
use crate::session::{Session, DiagnosticMessageId};
use crate::ty::TyCtxt;
use crate::ty::query::Providers;
use crate::util::nodemap::NodeMap;
use errors::{DiagnosticBuilder, DiagnosticId};
-use std::{hash, ptr};
use syntax::ast;
use syntax::source_map::{MultiSpan, ExpnKind, DesugaringKind};
-use syntax::early_buffered_lints::BufferedEarlyLintId;
-use syntax::edition::Edition;
-use syntax::symbol::{Symbol, sym};
+use syntax::symbol::Symbol;
use syntax_pos::hygiene::MacroKind;
use syntax_pos::Span;
@@ -47,150 +42,7 @@
check_crate, check_ast_crate, late_lint_mod, CheckLintNameResult,
BufferedEarlyLint,};
-/// Specification of a single lint.
-#[derive(Copy, Clone, Debug)]
-pub struct Lint {
- /// A string identifier for the lint.
- ///
- /// This identifies the lint in attributes and in command-line arguments.
- /// In those contexts it is always lowercase, but this field is compared
- /// in a way which is case-insensitive for ASCII characters. This allows
- /// `declare_lint!()` invocations to follow the convention of upper-case
- /// statics without repeating the name.
- ///
- /// The name is written with underscores, e.g., "unused_imports".
- /// On the command line, underscores become dashes.
- pub name: &'static str,
-
- /// Default level for the lint.
- pub default_level: Level,
-
- /// Description of the lint or the issue it detects.
- ///
- /// e.g., "imports that are never used"
- pub desc: &'static str,
-
- /// Starting at the given edition, default to the given lint level. If this is `None`, then use
- /// `default_level`.
- pub edition_lint_opts: Option<(Edition, Level)>,
-
- /// `true` if this lint is reported even inside expansions of external macros.
- pub report_in_external_macro: bool,
-
- pub future_incompatible: Option<FutureIncompatibleInfo>,
-
- pub is_plugin: bool,
-}
-
-/// Extra information for a future incompatibility lint.
-#[derive(Copy, Clone, Debug)]
-pub struct FutureIncompatibleInfo {
- /// e.g., a URL for an issue/PR/RFC or error code
- pub reference: &'static str,
- /// If this is an edition fixing lint, the edition in which
- /// this lint becomes obsolete
- pub edition: Option<Edition>,
-}
-
-impl Lint {
- pub const fn default_fields_for_macro() -> Self {
- Lint {
- name: "",
- default_level: Level::Forbid,
- desc: "",
- edition_lint_opts: None,
- is_plugin: false,
- report_in_external_macro: false,
- future_incompatible: None,
- }
- }
-
- /// Returns the `rust::lint::Lint` for a `syntax::early_buffered_lints::BufferedEarlyLintId`.
- pub fn from_parser_lint_id(lint_id: BufferedEarlyLintId) -> &'static Self {
- match lint_id {
- BufferedEarlyLintId::IllFormedAttributeInput => ILL_FORMED_ATTRIBUTE_INPUT,
- BufferedEarlyLintId::MetaVariableMisuse => META_VARIABLE_MISUSE,
- BufferedEarlyLintId::IncompleteInclude => INCOMPLETE_INCLUDE,
- }
- }
-
- /// Gets the lint's name, with ASCII letters converted to lowercase.
- pub fn name_lower(&self) -> String {
- self.name.to_ascii_lowercase()
- }
-
- pub fn default_level(&self, session: &Session) -> Level {
- self.edition_lint_opts
- .filter(|(e, _)| *e <= session.edition())
- .map(|(_, l)| l)
- .unwrap_or(self.default_level)
- }
-}
-
-/// Declares a static item of type `&'static Lint`.
-#[macro_export]
-macro_rules! declare_lint {
- ($vis: vis $NAME: ident, $Level: ident, $desc: expr) => (
- declare_lint!(
- $vis $NAME, $Level, $desc,
- );
- );
- ($vis: vis $NAME: ident, $Level: ident, $desc: expr,
- $(@future_incompatible = $fi:expr;)? $($v:ident),*) => (
- $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
- name: stringify!($NAME),
- default_level: $crate::lint::$Level,
- desc: $desc,
- edition_lint_opts: None,
- is_plugin: false,
- $($v: true,)*
- $(future_incompatible: Some($fi),)*
- ..$crate::lint::Lint::default_fields_for_macro()
- };
- );
- ($vis: vis $NAME: ident, $Level: ident, $desc: expr,
- $lint_edition: expr => $edition_level: ident
- ) => (
- $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
- name: stringify!($NAME),
- default_level: $crate::lint::$Level,
- desc: $desc,
- edition_lint_opts: Some(($lint_edition, $crate::lint::Level::$edition_level)),
- report_in_external_macro: false,
- is_plugin: false,
- };
- );
-}
-
-#[macro_export]
-macro_rules! declare_tool_lint {
- (
- $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level: ident, $desc: expr
- ) => (
- declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, false}
- );
- (
- $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
- report_in_external_macro: $rep:expr
- ) => (
- declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, $rep}
- );
- (
- $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
- $external:expr
- ) => (
- $(#[$attr])*
- $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
- name: &concat!(stringify!($tool), "::", stringify!($NAME)),
- default_level: $crate::lint::$Level,
- desc: $desc,
- edition_lint_opts: None,
- report_in_external_macro: $external,
- future_incompatible: None,
- is_plugin: true,
- };
- );
-}
+pub use rustc_session::lint::{Lint, LintId, Level, FutureIncompatibleInfo};
/// Declares a static `LintArray` and return it as an expression.
#[macro_export]
@@ -502,86 +354,6 @@
pub type LateLintPassObject = Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + sync::Send
+ sync::Sync + 'static>;
-/// Identifies a lint known to the compiler.
-#[derive(Clone, Copy, Debug)]
-pub struct LintId {
- // Identity is based on pointer equality of this field.
- lint: &'static Lint,
-}
-
-impl PartialEq for LintId {
- fn eq(&self, other: &LintId) -> bool {
- ptr::eq(self.lint, other.lint)
- }
-}
-
-impl Eq for LintId { }
-
-impl hash::Hash for LintId {
- fn hash<H: hash::Hasher>(&self, state: &mut H) {
- let ptr = self.lint as *const Lint;
- ptr.hash(state);
- }
-}
-
-impl LintId {
- /// Gets the `LintId` for a `Lint`.
- pub fn of(lint: &'static Lint) -> LintId {
- LintId {
- lint,
- }
- }
-
- pub fn lint_name_raw(&self) -> &'static str {
- self.lint.name
- }
-
- /// Gets the name of the lint.
- pub fn to_string(&self) -> String {
- self.lint.name_lower()
- }
-}
-
-/// Setting for how to handle a lint.
-#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash, HashStable)]
-pub enum Level {
- Allow, Warn, Deny, Forbid,
-}
-
-impl Level {
- /// Converts a level to a lower-case string.
- pub fn as_str(self) -> &'static str {
- match self {
- Allow => "allow",
- Warn => "warn",
- Deny => "deny",
- Forbid => "forbid",
- }
- }
-
- /// Converts a lower-case string to a level.
- pub fn from_str(x: &str) -> Option<Level> {
- match x {
- "allow" => Some(Allow),
- "warn" => Some(Warn),
- "deny" => Some(Deny),
- "forbid" => Some(Forbid),
- _ => None,
- }
- }
-
- /// Converts a symbol to a level.
- pub fn from_symbol(x: Symbol) -> Option<Level> {
- match x {
- sym::allow => Some(Allow),
- sym::warn => Some(Warn),
- sym::deny => Some(Deny),
- sym::forbid => Some(Forbid),
- _ => None,
- }
- }
-}
-
/// How a lint level was set.
#[derive(Clone, Copy, PartialEq, Eq, HashStable)]
pub enum LintSource {
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 44c6f6b..324b013 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -20,6 +20,7 @@
use rustc_data_structures::sync::{self, MetadataRef};
use rustc_macros::HashStable;
+pub use rustc_session::utils::NativeLibraryKind;
pub use self::NativeLibraryKind::*;
// lonely orphan structs and enums looking for a better home
@@ -94,21 +95,6 @@
RequireStatic,
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash,
- RustcEncodable, RustcDecodable, HashStable)]
-pub enum NativeLibraryKind {
- /// native static library (.a archive)
- NativeStatic,
- /// native static library, which doesn't get bundled into .rlibs
- NativeStaticNobundle,
- /// macOS-specific
- NativeFramework,
- /// Windows dynamic library without import library.
- NativeRawDylib,
- /// default way to specify a dynamic library
- NativeUnknown,
-}
-
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
pub struct NativeLibrary {
pub kind: NativeLibraryKind,
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index f6cd9b1..6f7a022 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -358,7 +358,6 @@
// Don't be fooled by the naming here: this lang item denotes `PartialEq`, not `Eq`.
EqTraitLangItem, "eq", eq_trait, Target::Trait;
PartialOrdTraitLangItem, "partial_ord", partial_ord_trait, Target::Trait;
- OrdTraitLangItem, "ord", ord_trait, Target::Trait;
// A number of panic-related lang items. The `panic` item corresponds to
// divide-by-zero and various panic cases with `match`. The
diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs
index 9b41366..95e9f09 100644
--- a/src/librustc/mir/cache.rs
+++ b/src/librustc/mir/cache.rs
@@ -1,16 +1,19 @@
use rustc_index::vec::IndexVec;
-use rustc_data_structures::sync::{RwLock, MappedReadGuard, ReadGuard};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
use crate::ich::StableHashingContext;
-use crate::mir::{Body, BasicBlock};
+use crate::mir::{BasicBlock, BasicBlockData, Body, LocalDecls, Location, Successors};
+use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
+use rustc_data_structures::graph::dominators::{dominators, Dominators};
+use std::iter;
+use std::ops::{Deref, DerefMut, Index, IndexMut};
+use std::vec::IntoIter;
#[derive(Clone, Debug)]
pub struct Cache {
- predecessors: RwLock<Option<IndexVec<BasicBlock, Vec<BasicBlock>>>>
+ predecessors: Option<IndexVec<BasicBlock, Vec<BasicBlock>>>,
}
-
impl rustc_serialize::Encodable for Cache {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
Encodable::encode(&(), s)
@@ -31,39 +34,256 @@
impl Cache {
pub fn new() -> Self {
- Cache {
- predecessors: RwLock::new(None)
+ Self {
+ predecessors: None,
}
}
- pub fn invalidate(&self) {
+ pub fn invalidate_predecessors(&mut self) {
// FIXME: consider being more fine-grained
- *self.predecessors.borrow_mut() = None;
+ self.predecessors = None;
}
- pub fn predecessors(
- &self,
- body: &Body<'_>
- ) -> MappedReadGuard<'_, IndexVec<BasicBlock, Vec<BasicBlock>>> {
- if self.predecessors.borrow().is_none() {
- *self.predecessors.borrow_mut() = Some(calculate_predecessors(body));
- }
+ pub fn ensure_predecessors(&mut self, body: &Body<'_>) {
+ if self.predecessors.is_none() {
+ let mut result = IndexVec::from_elem(vec![], body.basic_blocks());
+ for (bb, data) in body.basic_blocks().iter_enumerated() {
+ if let Some(ref term) = data.terminator {
+ for &tgt in term.successors() {
+ result[tgt].push(bb);
+ }
+ }
+ }
- ReadGuard::map(self.predecessors.borrow(), |p| p.as_ref().unwrap())
+ self.predecessors = Some(result)
+ }
+ }
+
+ /// This will recompute the predecessors cache if it is not available
+ fn predecessors(&mut self, body: &Body<'_>) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
+ self.ensure_predecessors(body);
+ self.predecessors.as_ref().unwrap()
+ }
+
+ fn unwrap_predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] {
+ &self.predecessors.as_ref().unwrap()[bb]
+ }
+
+ fn unwrap_predecessor_locations<'a>(
+ &'a self,
+ loc: Location,
+ body: &'a Body<'a>
+ ) -> impl Iterator<Item = Location> + 'a {
+ let if_zero_locations = if loc.statement_index == 0 {
+ let predecessor_blocks = self.unwrap_predecessors_for(loc.block);
+ let num_predecessor_blocks = predecessor_blocks.len();
+ Some(
+ (0..num_predecessor_blocks)
+ .map(move |i| predecessor_blocks[i])
+ .map(move |bb| body.terminator_loc(bb)),
+ )
+ } else {
+ None
+ };
+
+ let if_not_zero_locations = if loc.statement_index == 0 {
+ None
+ } else {
+ Some(Location { block: loc.block, statement_index: loc.statement_index - 1 })
+ };
+
+ if_zero_locations.into_iter().flatten().chain(if_not_zero_locations)
+ }
+
+ pub fn basic_blocks_mut<'a, 'tcx>(
+ &mut self,
+ body: &'a mut Body<'tcx>
+ ) -> &'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
+ debug!("bbm: Clearing predecessors cache for body at: {:?}", body.span.data());
+ self.invalidate_predecessors();
+ &mut body.basic_blocks
+ }
+
+ pub fn basic_blocks_and_local_decls_mut<'a, 'tcx>(
+ &mut self,
+ body: &'a mut Body<'tcx>
+ ) -> (&'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &'a mut LocalDecls<'tcx>) {
+ debug!("bbaldm: Clearing predecessors cache for body at: {:?}", body.span.data());
+ self.invalidate_predecessors();
+ (&mut body.basic_blocks, &mut body.local_decls)
}
}
-fn calculate_predecessors(body: &Body<'_>) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
- let mut result = IndexVec::from_elem(vec![], body.basic_blocks());
- for (bb, data) in body.basic_blocks().iter_enumerated() {
- if let Some(ref term) = data.terminator {
- for &tgt in term.successors() {
- result[tgt].push(bb);
- }
+#[derive(Clone, Debug, HashStable, RustcEncodable, RustcDecodable, TypeFoldable)]
+pub struct BodyCache<'tcx> {
+ cache: Cache,
+ body: Body<'tcx>,
+}
+
+impl BodyCache<'tcx> {
+ pub fn new(body: Body<'tcx>) -> Self {
+ Self {
+ cache: Cache::new(),
+ body,
+ }
+ }
+}
+
+#[macro_export]
+macro_rules! read_only {
+ ($body:expr) => {
+ {
+ $body.ensure_predecessors();
+ $body.unwrap_read_only()
+ }
+ };
+}
+
+impl BodyCache<'tcx> {
+ pub fn ensure_predecessors(&mut self) {
+ self.cache.ensure_predecessors(&self.body);
+ }
+
+ pub fn predecessors(&mut self) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
+ self.cache.predecessors(&self.body)
+ }
+
+ pub fn unwrap_read_only(&self) -> ReadOnlyBodyCache<'_, 'tcx> {
+ ReadOnlyBodyCache::new(&self.cache, &self.body)
+ }
+
+ pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
+ self.cache.basic_blocks_mut(&mut self.body)
+ }
+
+ pub fn basic_blocks_and_local_decls_mut(
+ &mut self
+ ) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) {
+ self.cache.basic_blocks_and_local_decls_mut(&mut self.body)
+ }
+}
+
+impl<'tcx> Index<BasicBlock> for BodyCache<'tcx> {
+ type Output = BasicBlockData<'tcx>;
+
+ fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
+ &self.body[index]
+ }
+}
+
+impl<'tcx> IndexMut<BasicBlock> for BodyCache<'tcx> {
+ fn index_mut(&mut self, index: BasicBlock) -> &mut Self::Output {
+ &mut self.basic_blocks_mut()[index]
+ }
+}
+
+impl<'tcx> Deref for BodyCache<'tcx> {
+ type Target = Body<'tcx>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.body
+ }
+}
+
+impl<'tcx> DerefMut for BodyCache<'tcx> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.body
+ }
+}
+
+#[derive(Copy, Clone, Debug)]
+pub struct ReadOnlyBodyCache<'a, 'tcx> {
+ cache: &'a Cache,
+ body: &'a Body<'tcx>,
+}
+
+impl ReadOnlyBodyCache<'a, 'tcx> {
+ fn new(cache: &'a Cache, body: &'a Body<'tcx>) -> Self {
+ assert!(
+ cache.predecessors.is_some(),
+ "Cannot construct ReadOnlyBodyCache without computed predecessors");
+ Self {
+ cache,
+ body,
}
}
- result
+ pub fn predecessors(&self) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
+ self.cache.predecessors.as_ref().unwrap()
+ }
+
+ pub fn predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] {
+ self.cache.unwrap_predecessors_for(bb)
+ }
+
+ pub fn predecessor_locations(&self, loc: Location) -> impl Iterator<Item = Location> + '_ {
+ self.cache.unwrap_predecessor_locations(loc, self.body)
+ }
+
+ pub fn body(&self) -> &'a Body<'tcx> {
+ self.body
+ }
+
+ pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
+ &self.body.basic_blocks
+ }
+
+ pub fn dominators(&self) -> Dominators<BasicBlock> {
+ dominators(self)
+ }
+}
+
+impl graph::DirectedGraph for ReadOnlyBodyCache<'a, 'tcx> {
+ type Node = BasicBlock;
+}
+
+impl graph::GraphPredecessors<'graph> for ReadOnlyBodyCache<'a, 'tcx> {
+ type Item = BasicBlock;
+ type Iter = IntoIter<BasicBlock>;
+}
+
+impl graph::WithPredecessors for ReadOnlyBodyCache<'a, 'tcx> {
+ fn predecessors(
+ &self,
+ node: Self::Node,
+ ) -> <Self as GraphPredecessors<'_>>::Iter {
+ self.cache.unwrap_predecessors_for(node).to_vec().into_iter()
+ }
+}
+
+impl graph::WithNumNodes for ReadOnlyBodyCache<'a, 'tcx> {
+ fn num_nodes(&self) -> usize {
+ self.body.num_nodes()
+ }
+}
+
+impl graph::WithStartNode for ReadOnlyBodyCache<'a, 'tcx> {
+ fn start_node(&self) -> Self::Node {
+ self.body.start_node()
+ }
+}
+
+impl graph::WithSuccessors for ReadOnlyBodyCache<'a, 'tcx> {
+ fn successors(
+ &self,
+ node: Self::Node,
+ ) -> <Self as GraphSuccessors<'_>>::Iter {
+ self.body.successors(node)
+ }
+}
+
+impl<'a, 'b, 'tcx> graph::GraphSuccessors<'b> for ReadOnlyBodyCache<'a, 'tcx> {
+ type Item = BasicBlock;
+ type Iter = iter::Cloned<Successors<'b>>;
+}
+
+
+impl Deref for ReadOnlyBodyCache<'a, 'tcx> {
+ type Target = &'a Body<'tcx>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.body
+ }
}
CloneTypeFoldableAndLiftImpls! {
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 41c22de..0dec7c0 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -14,7 +14,7 @@
use syntax_pos::{Pos, Span};
use syntax::symbol::Symbol;
use hir::GeneratorKind;
-use std::{fmt, env};
+use std::{fmt, env, any::Any};
use rustc_error_codes::*;
@@ -44,14 +44,14 @@
pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
-#[derive(Clone, Debug)]
+#[derive(Debug)]
pub struct ConstEvalErr<'tcx> {
pub span: Span,
pub error: crate::mir::interpret::InterpError<'tcx>,
pub stacktrace: Vec<FrameInfo<'tcx>>,
}
-#[derive(Clone, Debug)]
+#[derive(Debug)]
pub struct FrameInfo<'tcx> {
/// This span is in the caller.
pub call_site: Span,
@@ -138,6 +138,7 @@
lint_root: Option<hir::HirId>,
) -> Result<DiagnosticBuilder<'tcx>, ErrorHandled> {
let must_error = match self.error {
+ InterpError::MachineStop(_) => bug!("CTFE does not stop"),
err_inval!(Layout(LayoutError::Unknown(_))) |
err_inval!(TooGeneric) =>
return Err(ErrorHandled::TooGeneric),
@@ -189,7 +190,7 @@
/// Thsese should always be constructed by calling `.into()` on
/// a `InterpError`. In `librustc_mir::interpret`, we have `throw_err_*`
/// macros for this.
-#[derive(Debug, Clone)]
+#[derive(Debug)]
pub struct InterpErrorInfo<'tcx> {
pub kind: InterpError<'tcx>,
backtrace: Option<Box<Backtrace>>,
@@ -331,7 +332,6 @@
/// Error information for when the program we executed turned out not to actually be a valid
/// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp
/// where we work on generic code or execution does not have all information available.
-#[derive(Clone, HashStable)]
pub enum InvalidProgramInfo<'tcx> {
/// Resolution can fail if we are in a too generic context.
TooGeneric,
@@ -361,7 +361,6 @@
}
/// Error information for when the program caused Undefined Behavior.
-#[derive(Clone, HashStable)]
pub enum UndefinedBehaviorInfo {
/// Free-form case. Only for errors that are never caught!
Ub(String),
@@ -411,7 +410,6 @@
///
/// Currently, we also use this as fall-back error kind for errors that have not been
/// categorized yet.
-#[derive(Clone, HashStable)]
pub enum UnsupportedOpInfo<'tcx> {
/// Free-form case. Only for errors that are never caught!
Unsupported(String),
@@ -588,7 +586,6 @@
/// Error information for when the program exhausted the resources granted to it
/// by the interpreter.
-#[derive(Clone, HashStable)]
pub enum ResourceExhaustionInfo {
/// The stack grew too big.
StackFrameLimitReached,
@@ -609,7 +606,6 @@
}
}
-#[derive(Clone, HashStable)]
pub enum InterpError<'tcx> {
/// The program panicked.
Panic(PanicInfo<u64>),
@@ -618,14 +614,14 @@
/// The program did something the interpreter does not support (some of these *might* be UB
/// but the interpreter is not sure).
Unsupported(UnsupportedOpInfo<'tcx>),
- /// The program was invalid (ill-typed, not sufficiently monomorphized, ...).
+ /// The program was invalid (ill-typed, bad MIR, not sufficiently monomorphized, ...).
InvalidProgram(InvalidProgramInfo<'tcx>),
/// The program exhausted the interpreter's resources (stack/heap too big,
- /// execution takes too long, ..).
+ /// execution takes too long, ...).
ResourceExhaustion(ResourceExhaustionInfo),
- /// Not actually an interpreter error -- used to signal that execution has exited
- /// with the given status code. Used by Miri, but not by CTFE.
- Exit(i32),
+ /// Stop execution for a machine-controlled reason. This is never raised by
+ /// the core engine itself.
+ MachineStop(Box<dyn Any + Send>),
}
pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
@@ -651,8 +647,8 @@
write!(f, "{:?}", msg),
Panic(ref msg) =>
write!(f, "{:?}", msg),
- Exit(code) =>
- write!(f, "exited with status code {}", code),
+ MachineStop(_) =>
+ write!(f, "machine caused execution to stop"),
}
}
}
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index 65f4ee8..fff8767 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -90,6 +90,13 @@
($($tt:tt)*) => { return Err(err_exhaust!($($tt)*).into()) };
}
+#[macro_export]
+macro_rules! throw_machine_stop {
+ ($($tt:tt)*) => {
+ return Err($crate::mir::interpret::InterpError::MachineStop(Box::new($($tt)*)).into())
+ };
+}
+
mod error;
mod value;
mod allocation;
diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs
index f82af62..a038ca2 100644
--- a/src/librustc/mir/interpret/value.rs
+++ b/src/librustc/mir/interpret/value.rs
@@ -471,6 +471,13 @@
}
}
+impl<Tag> From<Pointer<Tag>> for ScalarMaybeUndef<Tag> {
+ #[inline(always)]
+ fn from(s: Pointer<Tag>) -> Self {
+ ScalarMaybeUndef::Scalar(s.into())
+ }
+}
+
impl<Tag: fmt::Debug, Id: fmt::Debug> fmt::Debug for ScalarMaybeUndef<Tag, Id> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 8c1690a..814c244 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -21,25 +21,25 @@
use polonius_engine::Atom;
use rustc_index::bit_set::BitMatrix;
use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::graph::dominators::{dominators, Dominators};
-use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
+use rustc_data_structures::graph::dominators::Dominators;
+use rustc_data_structures::graph::{self, GraphSuccessors};
use rustc_index::vec::{Idx, IndexVec};
use rustc_data_structures::sync::Lrc;
-use rustc_data_structures::sync::MappedReadGuard;
use rustc_macros::HashStable;
use rustc_serialize::{Encodable, Decodable};
use smallvec::SmallVec;
use std::borrow::Cow;
use std::fmt::{self, Debug, Display, Formatter, Write};
-use std::ops::{Index, IndexMut};
+use std::ops::Index;
use std::slice;
-use std::vec::IntoIter;
use std::{iter, mem, option, u32};
use syntax::ast::Name;
use syntax::symbol::Symbol;
use syntax_pos::{Span, DUMMY_SP};
pub use crate::mir::interpret::AssertMessage;
+pub use crate::mir::cache::{BodyCache, ReadOnlyBodyCache};
+pub use crate::read_only;
mod cache;
pub mod interpret;
@@ -104,15 +104,11 @@
/// and used for debuginfo. Indexed by a `SourceScope`.
pub source_scopes: IndexVec<SourceScope, SourceScopeData>,
- /// Crate-local information for each source scope, that can't (and
- /// needn't) be tracked across crates.
- pub source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
-
/// The yield type of the function, if it is a generator.
pub yield_ty: Option<Ty<'tcx>>,
/// Generator drop glue.
- pub generator_drop: Option<Box<Body<'tcx>>>,
+ pub generator_drop: Option<Box<BodyCache<'tcx>>>,
/// The layout of a generator. Produced by the state transformation.
pub generator_layout: Option<GeneratorLayout<'tcx>>,
@@ -158,16 +154,12 @@
/// A span representing this MIR, for error reporting.
pub span: Span,
-
- /// A cache for various calculations.
- cache: cache::Cache,
}
impl<'tcx> Body<'tcx> {
pub fn new(
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
source_scopes: IndexVec<SourceScope, SourceScopeData>,
- source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
local_decls: LocalDecls<'tcx>,
user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
arg_count: usize,
@@ -188,7 +180,6 @@
phase: MirPhase::Build,
basic_blocks,
source_scopes,
- source_scope_local_data,
yield_ty: None,
generator_drop: None,
generator_layout: None,
@@ -199,7 +190,6 @@
spread_arg: None,
var_debug_info,
span,
- cache: cache::Cache::new(),
control_flow_destroyed,
}
}
@@ -209,58 +199,6 @@
&self.basic_blocks
}
- #[inline]
- pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
- self.cache.invalidate();
- &mut self.basic_blocks
- }
-
- #[inline]
- pub fn basic_blocks_and_local_decls_mut(
- &mut self,
- ) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) {
- self.cache.invalidate();
- (&mut self.basic_blocks, &mut self.local_decls)
- }
-
- #[inline]
- pub fn predecessors(&self) -> MappedReadGuard<'_, IndexVec<BasicBlock, Vec<BasicBlock>>> {
- self.cache.predecessors(self)
- }
-
- #[inline]
- pub fn predecessors_for(&self, bb: BasicBlock) -> MappedReadGuard<'_, Vec<BasicBlock>> {
- MappedReadGuard::map(self.predecessors(), |p| &p[bb])
- }
-
- #[inline]
- pub fn predecessor_locations(&self, loc: Location) -> impl Iterator<Item = Location> + '_ {
- let if_zero_locations = if loc.statement_index == 0 {
- let predecessor_blocks = self.predecessors_for(loc.block);
- let num_predecessor_blocks = predecessor_blocks.len();
- Some(
- (0..num_predecessor_blocks)
- .map(move |i| predecessor_blocks[i])
- .map(move |bb| self.terminator_loc(bb)),
- )
- } else {
- None
- };
-
- let if_not_zero_locations = if loc.statement_index == 0 {
- None
- } else {
- Some(Location { block: loc.block, statement_index: loc.statement_index - 1 })
- };
-
- if_zero_locations.into_iter().flatten().chain(if_not_zero_locations)
- }
-
- #[inline]
- pub fn dominators(&self) -> Dominators<BasicBlock> {
- dominators(self)
- }
-
/// Returns `true` if a cycle exists in the control-flow graph that is reachable from the
/// `START_BLOCK`.
pub fn is_cfg_cyclic(&self) -> bool {
@@ -304,11 +242,7 @@
pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
(self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
- if self.local_decls[local].is_user_variable() {
- Some(local)
- } else {
- None
- }
+ self.local_decls[local].is_user_variable().then_some(local)
})
}
@@ -361,7 +295,7 @@
/// Changes a statement to a nop. This is both faster than deleting instructions and avoids
/// invalidating statement indices in `Location`s.
pub fn make_statement_nop(&mut self, location: Location) {
- let block = &mut self[location.block];
+ let block = &mut self.basic_blocks[location.block];
debug_assert!(location.statement_index < block.statements.len());
block.statements[location.statement_index].make_nop()
}
@@ -421,13 +355,6 @@
}
}
-impl<'tcx> IndexMut<BasicBlock> for Body<'tcx> {
- #[inline]
- fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
- &mut self.basic_blocks_mut()[index]
- }
-}
-
#[derive(Copy, Clone, Debug, HashStable, TypeFoldable)]
pub enum ClearCrossCrate<T> {
Clear,
@@ -435,6 +362,13 @@
}
impl<T> ClearCrossCrate<T> {
+ pub fn as_ref(&'a self) -> ClearCrossCrate<&'a T> {
+ match self {
+ ClearCrossCrate::Clear => ClearCrossCrate::Clear,
+ ClearCrossCrate::Set(v) => ClearCrossCrate::Set(v),
+ }
+ }
+
pub fn assert_crate_local(self) -> T {
match self {
ClearCrossCrate::Clear => bug!("unwrapping cross-crate data"),
@@ -2027,6 +1961,10 @@
pub struct SourceScopeData {
pub span: Span,
pub parent_scope: Option<SourceScope>,
+
+ /// Crate-local information for this source scope, that can't (and
+ /// needn't) be tracked across crates.
+ pub local_data: ClearCrossCrate<SourceScopeLocalData>,
}
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
@@ -2308,10 +2246,14 @@
}
}
- AggregateKind::Closure(def_id, _) => ty::tls::with(|tcx| {
+ AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| {
if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) {
let name = if tcx.sess.opts.debugging_opts.span_free_formats {
- format!("[closure@{:?}]", hir_id)
+ let substs = tcx.lift(&substs).unwrap();
+ format!(
+ "[closure@{}]",
+ tcx.def_path_str_with_substs(def_id, substs),
+ )
} else {
format!("[closure@{:?}]", tcx.hir().span(hir_id))
};
@@ -2609,15 +2551,6 @@
}
}
-impl<'tcx> graph::WithPredecessors for Body<'tcx> {
- fn predecessors(
- &self,
- node: Self::Node,
- ) -> <Self as GraphPredecessors<'_>>::Iter {
- self.predecessors_for(node).clone().into_iter()
- }
-}
-
impl<'tcx> graph::WithSuccessors for Body<'tcx> {
fn successors(
&self,
@@ -2627,11 +2560,6 @@
}
}
-impl<'a, 'b> graph::GraphPredecessors<'b> for Body<'a> {
- type Item = BasicBlock;
- type Iter = IntoIter<BasicBlock>;
-}
-
impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> {
type Item = BasicBlock;
type Iter = iter::Cloned<Successors<'b>>;
@@ -2666,7 +2594,11 @@
}
/// Returns `true` if `other` is earlier in the control flow graph than `self`.
- pub fn is_predecessor_of<'tcx>(&self, other: Location, body: &Body<'tcx>) -> bool {
+ pub fn is_predecessor_of<'tcx>(
+ &self,
+ other: Location,
+ body: ReadOnlyBodyCache<'_, 'tcx>
+ ) -> bool {
// If we are in the same block as the other location and are an earlier statement
// then we are a predecessor of `other`.
if self.block == other.block && self.statement_index < other.statement_index {
@@ -2674,13 +2606,13 @@
}
// If we're in another block, then we want to check that block is a predecessor of `other`.
- let mut queue: Vec<BasicBlock> = body.predecessors_for(other.block).clone();
+ let mut queue: Vec<BasicBlock> = body.predecessors_for(other.block).to_vec();
let mut visited = FxHashSet::default();
while let Some(block) = queue.pop() {
// If we haven't visited this block before, then make sure we visit it's predecessors.
if visited.insert(block) {
- queue.append(&mut body.predecessors_for(block).clone());
+ queue.extend(body.predecessors_for(block).iter().cloned());
} else {
continue;
}
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 58c12ef..47a1d67 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -65,13 +65,25 @@
// variant argument) that does not require visiting, as in
// `is_cleanup` above.
+macro_rules! body_cache_type {
+ (mut $a:lifetime, $tcx:lifetime) => {
+ &mut BodyCache<$tcx>
+ };
+ ($a:lifetime, $tcx:lifetime) => {
+ ReadOnlyBodyCache<$a, $tcx>
+ };
+}
+
macro_rules! make_mir_visitor {
($visitor_trait_name:ident, $($mutability:ident)?) => {
pub trait $visitor_trait_name<'tcx> {
// Override these, and call `self.super_xxx` to revert back to the
// default behavior.
- fn visit_body(&mut self, body: & $($mutability)? Body<'tcx>) {
+ fn visit_body(
+ &mut self,
+ body: body_cache_type!($($mutability)? '_, 'tcx)
+ ) {
self.super_body(body);
}
@@ -240,11 +252,14 @@
// The `super_xxx` methods comprise the default behavior and are
// not meant to be overridden.
- fn super_body(&mut self,
- body: & $($mutability)? Body<'tcx>) {
+ fn super_body(
+ &mut self,
+ $($mutability)? body: body_cache_type!($($mutability)? '_, 'tcx)
+ ) {
+ let span = body.span;
if let Some(yield_ty) = &$($mutability)? body.yield_ty {
self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
- span: body.span,
+ span,
scope: OUTERMOST_SOURCE_SCOPE,
}));
}
@@ -260,6 +275,7 @@
self.visit_basic_block_data(bb, data);
}
+ let body: & $($mutability)? Body<'_> = & $($mutability)? body;
for scope in &$($mutability)? body.source_scopes {
self.visit_source_scope_data(scope);
}
@@ -317,6 +333,7 @@
let SourceScopeData {
span,
parent_scope,
+ local_data: _,
} = scope_data;
self.visit_span(span);
@@ -789,7 +806,11 @@
// Convenience methods
- fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Location) {
+ fn visit_location(
+ &mut self,
+ body: body_cache_type!($($mutability)? '_, 'tcx),
+ location: Location
+ ) {
let basic_block = & $($mutability)? body[location.block];
if basic_block.statements.len() == location.statement_index {
if let Some(ref $($mutability)? terminator) = basic_block.terminator {
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index d715ddb..a6d7e5c 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -106,44 +106,54 @@
/// Fetch the MIR for a given `DefId` right after it's built - this includes
/// unreachable code.
- query mir_built(_: DefId) -> &'tcx Steal<mir::Body<'tcx>> {}
+ query mir_built(_: DefId) -> &'tcx Steal<mir::BodyCache<'tcx>> {}
/// Fetch the MIR for a given `DefId` up till the point where it is
/// ready for const evaluation.
///
/// See the README for the `mir` module for details.
- query mir_const(_: DefId) -> &'tcx Steal<mir::Body<'tcx>> {
+ query mir_const(_: DefId) -> &'tcx Steal<mir::BodyCache<'tcx>> {
no_hash
}
query mir_validated(_: DefId) ->
(
- &'tcx Steal<mir::Body<'tcx>>,
- &'tcx Steal<IndexVec<mir::Promoted, mir::Body<'tcx>>>
+ &'tcx Steal<mir::BodyCache<'tcx>>,
+ &'tcx Steal<IndexVec<mir::Promoted, mir::BodyCache<'tcx>>>
) {
no_hash
}
/// MIR after our optimization passes have run. This is MIR that is ready
/// for codegen. This is also the only query that can fetch non-local MIR, at present.
- query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> {
+ query optimized_mir(key: DefId) -> &'tcx mir::BodyCache<'tcx> {
cache_on_disk_if { key.is_local() }
load_cached(tcx, id) {
- let mir: Option<crate::mir::Body<'tcx>> = tcx.queries.on_disk_cache
- .try_load_query_result(tcx, id);
- mir.map(|x| &*tcx.arena.alloc(x))
+ let mir: Option<crate::mir::BodyCache<'tcx>>
+ = tcx.queries.on_disk_cache.try_load_query_result(tcx, id);
+ mir.map(|x| {
+ let cache = tcx.arena.alloc(x);
+ cache.ensure_predecessors();
+ &*cache
+ })
}
}
- query promoted_mir(key: DefId) -> &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>> {
+ query promoted_mir(key: DefId) -> &'tcx IndexVec<mir::Promoted, mir::BodyCache<'tcx>> {
cache_on_disk_if { key.is_local() }
load_cached(tcx, id) {
let promoted: Option<
rustc_index::vec::IndexVec<
crate::mir::Promoted,
- crate::mir::Body<'tcx>
+ crate::mir::BodyCache<'tcx>
>> = tcx.queries.on_disk_cache.try_load_query_result(tcx, id);
- promoted.map(|p| &*tcx.arena.alloc(p))
+ promoted.map(|p| {
+ let cache = tcx.arena.alloc(p);
+ for body in cache.iter_mut() {
+ body.ensure_predecessors();
+ }
+ &*cache
+ })
}
}
}
@@ -502,7 +512,7 @@
/// in the case of closures, this will be redirected to the enclosing function.
query region_scope_tree(_: DefId) -> &'tcx region::ScopeTree {}
- query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::Body<'tcx> {
+ query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::BodyCache<'tcx> {
no_force
desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
}
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 90db1fe..35017d6 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -363,11 +363,7 @@
return None
};
- if tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented) {
- Some(impl_def_id)
- } else {
- None
- }
+ tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented).then_some(impl_def_id)
}
fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
@@ -521,7 +517,7 @@
) {
command.evaluate(self.tcx, trait_ref, &flags[..])
} else {
- OnUnimplementedNote::empty()
+ OnUnimplementedNote::default()
}
}
@@ -697,6 +693,7 @@
fallback_has_occurred: bool,
points_at_arg: bool,
) {
+ let tcx = self.tcx;
let span = obligation.cause.span;
let mut err = match *error {
@@ -732,6 +729,7 @@
message,
label,
note,
+ enclosing_scope,
} = self.on_unimplemented_note(trait_ref, obligation);
let have_alt_message = message.is_some() || label.is_some();
let is_try = self.tcx.sess.source_map().span_to_snippet(span)
@@ -798,6 +796,19 @@
// If it has a custom `#[rustc_on_unimplemented]` note, let's display it
err.note(s.as_str());
}
+ if let Some(ref s) = enclosing_scope {
+ let enclosing_scope_span = tcx.def_span(
+ tcx.hir()
+ .opt_local_def_id(obligation.cause.body_id)
+ .unwrap_or_else(|| {
+ tcx.hir().body_owner_def_id(hir::BodyId {
+ hir_id: obligation.cause.body_id,
+ })
+ }),
+ );
+
+ err.span_label(enclosing_scope_span, s.as_str());
+ }
self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
@@ -2199,6 +2210,10 @@
}
let span = self.tcx.def_span(generator_did);
+ // Do not ICE on closure typeck (#66868).
+ if let None = self.tcx.hir().as_local_hir_id(generator_did) {
+ return false;
+ }
let tables = self.tcx.typeck_tables_of(generator_did);
debug!("note_obligation_cause_for_async_await: generator_did={:?} span={:?} ",
generator_did, span);
diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs
index 59aa081..604f39d 100644
--- a/src/librustc/traits/on_unimplemented.rs
+++ b/src/librustc/traits/on_unimplemented.rs
@@ -22,18 +22,15 @@
pub message: Option<OnUnimplementedFormatString>,
pub label: Option<OnUnimplementedFormatString>,
pub note: Option<OnUnimplementedFormatString>,
+ pub enclosing_scope: Option<OnUnimplementedFormatString>,
}
+#[derive(Default)]
pub struct OnUnimplementedNote {
pub message: Option<String>,
pub label: Option<String>,
pub note: Option<String>,
-}
-
-impl OnUnimplementedNote {
- pub fn empty() -> Self {
- OnUnimplementedNote { message: None, label: None, note: None }
- }
+ pub enclosing_scope: Option<String>,
}
fn parse_error(
@@ -85,24 +82,33 @@
let mut message = None;
let mut label = None;
let mut note = None;
+ let mut enclosing_scope = None;
let mut subcommands = vec![];
+
+ let parse_value = |value_str| {
+ OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span)
+ .map(Some)
+ };
+
for item in item_iter {
if item.check_name(sym::message) && message.is_none() {
if let Some(message_) = item.value_str() {
- message = Some(OnUnimplementedFormatString::try_parse(
- tcx, trait_def_id, message_, span)?);
+ message = parse_value(message_)?;
continue;
}
} else if item.check_name(sym::label) && label.is_none() {
if let Some(label_) = item.value_str() {
- label = Some(OnUnimplementedFormatString::try_parse(
- tcx, trait_def_id, label_, span)?);
+ label = parse_value(label_)?;
continue;
}
} else if item.check_name(sym::note) && note.is_none() {
if let Some(note_) = item.value_str() {
- note = Some(OnUnimplementedFormatString::try_parse(
- tcx, trait_def_id, note_, span)?);
+ note = parse_value(note_)?;
+ continue;
+ }
+ } else if item.check_name(sym::enclosing_scope) && enclosing_scope.is_none() {
+ if let Some(enclosing_scope_) = item.value_str() {
+ enclosing_scope = parse_value(enclosing_scope_)?;
continue;
}
} else if item.check_name(sym::on) && is_root &&
@@ -130,7 +136,14 @@
if errored {
Err(ErrorReported)
} else {
- Ok(OnUnimplementedDirective { condition, message, label, subcommands, note })
+ Ok(OnUnimplementedDirective {
+ condition,
+ subcommands,
+ message,
+ label,
+ note,
+ enclosing_scope
+ })
}
}
@@ -157,6 +170,7 @@
label: Some(OnUnimplementedFormatString::try_parse(
tcx, trait_def_id, value, attr.span)?),
note: None,
+ enclosing_scope: None,
}))
} else {
return Err(ErrorReported);
@@ -174,6 +188,7 @@
let mut message = None;
let mut label = None;
let mut note = None;
+ let mut enclosing_scope = None;
info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
for command in self.subcommands.iter().chain(Some(self)).rev() {
@@ -202,6 +217,10 @@
if let Some(ref note_) = command.note {
note = Some(note_.clone());
}
+
+ if let Some(ref enclosing_scope_) = command.enclosing_scope {
+ enclosing_scope = Some(enclosing_scope_.clone());
+ }
}
let options: FxHashMap<Symbol, String> = options.into_iter()
@@ -211,6 +230,7 @@
label: label.map(|l| l.format(tcx, trait_ref, &options)),
message: message.map(|m| m.format(tcx, trait_ref, &options)),
note: note.map(|n| n.format(tcx, trait_ref, &options)),
+ enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options)),
}
}
}
diff --git a/src/librustc/ty/constness.rs b/src/librustc/ty/constness.rs
index 676916f..268015a 100644
--- a/src/librustc/ty/constness.rs
+++ b/src/librustc/ty/constness.rs
@@ -2,7 +2,8 @@
use crate::hir::def_id::DefId;
use crate::hir;
use crate::ty::TyCtxt;
-use syntax_pos::symbol::Symbol;
+use syntax_pos::symbol::{sym, Symbol};
+use rustc_target::spec::abi::Abi;
use crate::hir::map::blocks::FnLikeNode;
use syntax::attr;
@@ -35,12 +36,51 @@
}
}
+ /// Returns `true` if the `def_id` refers to an intrisic which we've whitelisted
+ /// for being called from stable `const fn`s (`min_const_fn`).
+ ///
+ /// Adding more intrinsics requires sign-off from @rust-lang/lang.
+ ///
+ /// This list differs from the list in `is_const_intrinsic` in the sense that any item on this
+ /// list must be on the `is_const_intrinsic` list, too, because if an intrinsic is callable from
+ /// stable, it must be callable at all.
+ fn is_intrinsic_min_const_fn(self, def_id: DefId) -> bool {
+ match self.item_name(def_id) {
+ | sym::size_of
+ | sym::min_align_of
+ | sym::needs_drop
+ // Arithmetic:
+ | sym::add_with_overflow // ~> .overflowing_add
+ | sym::sub_with_overflow // ~> .overflowing_sub
+ | sym::mul_with_overflow // ~> .overflowing_mul
+ | sym::wrapping_add // ~> .wrapping_add
+ | sym::wrapping_sub // ~> .wrapping_sub
+ | sym::wrapping_mul // ~> .wrapping_mul
+ | sym::saturating_add // ~> .saturating_add
+ | sym::saturating_sub // ~> .saturating_sub
+ | sym::unchecked_shl // ~> .wrapping_shl
+ | sym::unchecked_shr // ~> .wrapping_shr
+ | sym::rotate_left // ~> .rotate_left
+ | sym::rotate_right // ~> .rotate_right
+ | sym::ctpop // ~> .count_ones
+ | sym::ctlz // ~> .leading_zeros
+ | sym::cttz // ~> .trailing_zeros
+ | sym::bswap // ~> .swap_bytes
+ | sym::bitreverse // ~> .reverse_bits
+ => true,
+ _ => false,
+ }
+ }
+
/// Returns `true` if this function must conform to `min_const_fn`
pub fn is_min_const_fn(self, def_id: DefId) -> bool {
// Bail out if the signature doesn't contain `const`
if !self.is_const_fn_raw(def_id) {
return false;
}
+ if let Abi::RustIntrinsic = self.fn_sig(def_id).abi() {
+ return self.is_intrinsic_min_const_fn(def_id);
+ }
if self.features().staged_api {
// in order for a libstd function to be considered min_const_fn
@@ -63,13 +103,82 @@
pub fn provide(providers: &mut Providers<'_>) {
- /// only checks whether the function has a `const` modifier
+ /// Const evaluability whitelist is here to check evaluability at the
+ /// top level beforehand.
+ fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
+ match tcx.fn_sig(def_id).abi() {
+ Abi::RustIntrinsic |
+ Abi::PlatformIntrinsic => {
+ // FIXME: deduplicate these two lists as much as possible
+ match tcx.item_name(def_id) {
+ // Keep this list in the same order as the match patterns in
+ // `librustc_mir/interpret/intrinsics.rs`
+
+ // This whitelist is a list of intrinsics that have a miri-engine implementation
+ // and can thus be called when enabling enough feature gates. The similar
+ // whitelist in `is_intrinsic_min_const_fn` (in this file), exists for allowing
+ // the intrinsics to be called by stable const fns.
+ | sym::caller_location
+
+ | sym::min_align_of
+ | sym::pref_align_of
+ | sym::needs_drop
+ | sym::size_of
+ | sym::type_id
+ | sym::type_name
+
+ | sym::ctpop
+ | sym::cttz
+ | sym::cttz_nonzero
+ | sym::ctlz
+ | sym::ctlz_nonzero
+ | sym::bswap
+ | sym::bitreverse
+
+ | sym::wrapping_add
+ | sym::wrapping_sub
+ | sym::wrapping_mul
+ | sym::add_with_overflow
+ | sym::sub_with_overflow
+ | sym::mul_with_overflow
+
+ | sym::saturating_add
+ | sym::saturating_sub
+
+ | sym::unchecked_shl
+ | sym::unchecked_shr
+
+ | sym::rotate_left
+ | sym::rotate_right
+
+ | sym::ptr_offset_from
+
+ | sym::transmute
+
+ | sym::simd_insert
+
+ | sym::simd_extract
+
+ => Some(true),
+
+ _ => Some(false)
+ }
+ }
+ _ => None
+ }
+ }
+
+ /// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether
+ /// said intrinsic is on the whitelist for being const callable.
fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
let hir_id = tcx.hir().as_local_hir_id(def_id)
.expect("Non-local call to local provider is_const_fn");
let node = tcx.hir().get(hir_id);
- if let Some(fn_like) = FnLikeNode::from_node(node) {
+
+ if let Some(whitelisted) = is_const_intrinsic(tcx, def_id) {
+ whitelisted
+ } else if let Some(fn_like) = FnLikeNode::from_node(node) {
fn_like.constness() == hir::Constness::Const
} else if let hir::Node::Ctor(_) = node {
true
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 776ae7d..6a0002c 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -22,7 +22,7 @@
use crate::middle::lang_items;
use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault};
use crate::middle::stability;
-use crate::mir::{Body, Field, interpret, Local, Place, PlaceElem, ProjectionKind, Promoted};
+use crate::mir::{BodyCache, Field, interpret, Local, Place, PlaceElem, ProjectionKind, Promoted};
use crate::mir::interpret::{ConstValue, Allocation, Scalar};
use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef, Subst};
use crate::ty::ReprOptions;
@@ -1083,17 +1083,17 @@
&self.hir_map
}
- pub fn alloc_steal_mir(self, mir: Body<'tcx>) -> &'tcx Steal<Body<'tcx>> {
+ pub fn alloc_steal_mir(self, mir: BodyCache<'tcx>) -> &'tcx Steal<BodyCache<'tcx>> {
self.arena.alloc(Steal::new(mir))
}
- pub fn alloc_steal_promoted(self, promoted: IndexVec<Promoted, Body<'tcx>>) ->
- &'tcx Steal<IndexVec<Promoted, Body<'tcx>>> {
+ pub fn alloc_steal_promoted(self, promoted: IndexVec<Promoted, BodyCache<'tcx>>) ->
+ &'tcx Steal<IndexVec<Promoted, BodyCache<'tcx>>> {
self.arena.alloc(Steal::new(promoted))
}
- pub fn intern_promoted(self, promoted: IndexVec<Promoted, Body<'tcx>>) ->
- &'tcx IndexVec<Promoted, Body<'tcx>> {
+ pub fn intern_promoted(self, promoted: IndexVec<Promoted, BodyCache<'tcx>>) ->
+ &'tcx IndexVec<Promoted, BodyCache<'tcx>> {
self.arena.alloc(promoted)
}
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 777db38..801dfa8 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -1,8 +1,7 @@
use crate::hir::CodegenFnAttrFlags;
-use crate::hir::Unsafety;
use crate::hir::def::Namespace;
use crate::hir::def_id::DefId;
-use crate::ty::{self, Ty, PolyFnSig, TypeFoldable, SubstsRef, TyCtxt};
+use crate::ty::{self, Ty, TypeFoldable, SubstsRef, TyCtxt};
use crate::ty::print::{FmtPrinter, Printer};
use crate::traits;
use crate::middle::lang_items::DropInPlaceFnLangItem;
@@ -10,7 +9,6 @@
use rustc_macros::HashStable;
use std::fmt;
-use std::iter;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
#[derive(HashStable, Lift)]
@@ -29,17 +27,26 @@
/// `fn()` pointer where the function itself cannot be turned into a pointer.
///
- /// One example in the compiler today is functions annotated with `#[track_caller]`, which
- /// must have their implicit caller location argument populated for a call. Because this is a
- /// required part of the function's ABI but can't be tracked as a property of the function
- /// pointer, we create a single "caller location" at the site where the function is reified.
+ /// One example is `<dyn Trait as Trait>::fn`, where the shim contains
+ /// a virtual call, which codegen supports only via a direct call to the
+ /// `<dyn Trait as Trait>::fn` instance (an `InstanceDef::Virtual`).
+ ///
+ /// Another example is functions annotated with `#[track_caller]`, which
+ /// must have their implicit caller location argument populated for a call.
+ /// Because this is a required part of the function's ABI but can't be tracked
+ /// as a property of the function pointer, we use a single "caller location"
+ /// (the definition of the function itself).
ReifyShim(DefId),
/// `<fn() as FnTrait>::call_*`
/// `DefId` is `FnTrait::call_*`.
FnPtrShim(DefId, Ty<'tcx>),
- /// `<dyn Trait as Trait>::fn`
+ /// `<dyn Trait as Trait>::fn`, "direct calls" of which are implicitly
+ /// codegen'd as virtual calls.
+ ///
+ /// NB: if this is reified to a `fn` pointer, a `ReifyShim` is used
+ /// (see `ReifyShim` above for more details on that).
Virtual(DefId, usize),
/// `<[mut closure] as FnOnce>::call_once`
@@ -61,70 +68,6 @@
&ty,
)
}
-
- fn fn_sig_noadjust(&self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
- let ty = self.ty(tcx);
- match ty.kind {
- ty::FnDef(..) |
- // Shims currently have type FnPtr. Not sure this should remain.
- ty::FnPtr(_) => ty.fn_sig(tcx),
- ty::Closure(def_id, substs) => {
- let sig = substs.as_closure().sig(def_id, tcx);
-
- let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
- sig.map_bound(|sig| tcx.mk_fn_sig(
- iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()),
- sig.output(),
- sig.c_variadic,
- sig.unsafety,
- sig.abi
- ))
- }
- ty::Generator(def_id, substs, _) => {
- let sig = substs.as_generator().poly_sig(def_id, tcx);
-
- let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
- let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
-
- let pin_did = tcx.lang_items().pin_type().unwrap();
- let pin_adt_ref = tcx.adt_def(pin_did);
- let pin_substs = tcx.intern_substs(&[env_ty.into()]);
- let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
-
- sig.map_bound(|sig| {
- let state_did = tcx.lang_items().gen_state().unwrap();
- let state_adt_ref = tcx.adt_def(state_did);
- let state_substs = tcx.intern_substs(&[
- sig.yield_ty.into(),
- sig.return_ty.into(),
- ]);
- let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
-
- tcx.mk_fn_sig(iter::once(env_ty),
- ret_ty,
- false,
- Unsafety::Normal,
- Abi::Rust
- )
- })
- }
- _ => bug!("unexpected type {:?} in Instance::fn_sig_noadjust", ty)
- }
- }
-
- pub fn fn_sig(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
- let mut fn_sig = self.fn_sig_noadjust(tcx);
- if let InstanceDef::VtableShim(..) = self.def {
- // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`.
- fn_sig = fn_sig.map_bound(|mut fn_sig| {
- let mut inputs_and_output = fn_sig.inputs_and_output.to_vec();
- inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]);
- fn_sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output);
- fn_sig
- });
- }
- fn_sig
- }
}
impl<'tcx> InstanceDef<'tcx> {
@@ -196,7 +139,7 @@
write!(f, " - intrinsic")
}
InstanceDef::Virtual(_, num) => {
- write!(f, " - shim(#{})", num)
+ write!(f, " - virtual#{}", num)
}
InstanceDef::FnPtrShim(_, ty) => {
write!(f, " - shim({:?})", ty)
@@ -311,20 +254,23 @@
substs: SubstsRef<'tcx>,
) -> Option<Instance<'tcx>> {
debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
- Instance::resolve(tcx, param_env, def_id, substs).map(|resolved| {
+ Instance::resolve(tcx, param_env, def_id, substs).map(|mut resolved| {
let has_track_caller = |def| tcx.codegen_fn_attrs(def).flags
.contains(CodegenFnAttrFlags::TRACK_CALLER);
match resolved.def {
InstanceDef::Item(def_id) if has_track_caller(def_id) => {
debug!(" => fn pointer created for function with #[track_caller]");
- Instance {
- def: InstanceDef::ReifyShim(def_id),
- substs,
- }
- },
- _ => resolved,
+ resolved.def = InstanceDef::ReifyShim(def_id);
+ }
+ InstanceDef::Virtual(def_id, _) => {
+ debug!(" => fn pointer created for virtual call");
+ resolved.def = InstanceDef::ReifyShim(def_id);
+ }
+ _ => {}
}
+
+ resolved
})
}
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index c67e6a0..7f93e8c 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -2339,6 +2339,76 @@
}
}
+
+impl<'tcx> ty::Instance<'tcx> {
+ // NOTE(eddyb) this is private to avoid using it from outside of
+ // `FnAbi::of_instance` - any other uses are either too high-level
+ // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead),
+ // or should go through `FnAbi` instead, to avoid losing any
+ // adjustments `FnAbi::of_instance` might be performing.
+ fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
+ let ty = self.ty(tcx);
+ match ty.kind {
+ ty::FnDef(..) |
+ // Shims currently have type FnPtr. Not sure this should remain.
+ ty::FnPtr(_) => {
+ let mut sig = ty.fn_sig(tcx);
+ if let ty::InstanceDef::VtableShim(..) = self.def {
+ // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`.
+ sig = sig.map_bound(|mut sig| {
+ let mut inputs_and_output = sig.inputs_and_output.to_vec();
+ inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]);
+ sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output);
+ sig
+ });
+ }
+ sig
+ }
+ ty::Closure(def_id, substs) => {
+ let sig = substs.as_closure().sig(def_id, tcx);
+
+ let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
+ sig.map_bound(|sig| tcx.mk_fn_sig(
+ iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()),
+ sig.output(),
+ sig.c_variadic,
+ sig.unsafety,
+ sig.abi
+ ))
+ }
+ ty::Generator(def_id, substs, _) => {
+ let sig = substs.as_generator().poly_sig(def_id, tcx);
+
+ let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
+ let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
+
+ let pin_did = tcx.lang_items().pin_type().unwrap();
+ let pin_adt_ref = tcx.adt_def(pin_did);
+ let pin_substs = tcx.intern_substs(&[env_ty.into()]);
+ let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
+
+ sig.map_bound(|sig| {
+ let state_did = tcx.lang_items().gen_state().unwrap();
+ let state_adt_ref = tcx.adt_def(state_did);
+ let state_substs = tcx.intern_substs(&[
+ sig.yield_ty.into(),
+ sig.return_ty.into(),
+ ]);
+ let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
+
+ tcx.mk_fn_sig(iter::once(env_ty),
+ ret_ty,
+ false,
+ hir::Unsafety::Normal,
+ rustc_target::spec::abi::Abi::Rust
+ )
+ })
+ }
+ _ => bug!("unexpected type {:?} in Instance::fn_sig", ty)
+ }
+ }
+}
+
pub trait FnAbiExt<'tcx, C>
where
C: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>>
@@ -2347,12 +2417,22 @@
+ HasTyCtxt<'tcx>
+ HasParamEnv<'tcx>,
{
- fn of_instance(cx: &C, instance: ty::Instance<'tcx>) -> Self;
- fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
- fn new_vtable(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
+ /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
+ ///
+ /// NB: this doesn't handle virtual calls - those should use `FnAbi::of_instance`
+ /// instead, where the instance is a `InstanceDef::Virtual`.
+ fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
+
+ /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
+ /// direct calls to an `fn`.
+ ///
+ /// NB: that includes virtual calls, which are represented by "direct calls"
+ /// to a `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
+ fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
+
fn new_internal(
cx: &C,
- sig: ty::FnSig<'tcx>,
+ sig: ty::PolyFnSig<'tcx>,
extra_args: &[Ty<'tcx>],
mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgAbi<'tcx, Ty<'tcx>>,
) -> Self;
@@ -2367,25 +2447,19 @@
+ HasTyCtxt<'tcx>
+ HasParamEnv<'tcx>,
{
- fn of_instance(cx: &C, instance: ty::Instance<'tcx>) -> Self {
- let sig = instance.fn_sig(cx.tcx());
- let sig = cx
- .tcx()
- .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
- call::FnAbi::new(cx, sig, &[])
- }
-
- fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
+ fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
call::FnAbi::new_internal(cx, sig, extra_args, |ty, _| ArgAbi::new(cx.layout_of(ty)))
}
- fn new_vtable(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
- FnAbiExt::new_internal(cx, sig, extra_args, |ty, arg_idx| {
+ fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
+ let sig = instance.fn_sig_for_fn_abi(cx.tcx());
+
+ call::FnAbi::new_internal(cx, sig, extra_args, |ty, arg_idx| {
let mut layout = cx.layout_of(ty);
// Don't pass the vtable, it's not an argument of the virtual fn.
// Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
// or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
- if arg_idx == Some(0) {
+ if let (ty::InstanceDef::Virtual(..), Some(0)) = (&instance.def, arg_idx) {
let fat_pointer_ty = if layout.is_unsized() {
// unsized `self` is passed as a pointer to `self`
// FIXME (mikeyhew) change this to use &own if it is ever added to the language
@@ -2436,15 +2510,19 @@
fn new_internal(
cx: &C,
- sig: ty::FnSig<'tcx>,
+ sig: ty::PolyFnSig<'tcx>,
extra_args: &[Ty<'tcx>],
mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgAbi<'tcx, Ty<'tcx>>,
) -> Self {
debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args);
+ let sig = cx
+ .tcx()
+ .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
+
use rustc_target::spec::abi::Abi::*;
let conv = match cx.tcx().sess.target.target.adjust_abi(sig.abi) {
- RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::C,
+ RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::Rust,
// It's the ABI's job to select this, not ours.
System => bug!("system abi should be selected elsewhere"),
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 8ccfc46..05a2704 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -18,7 +18,7 @@
use crate::middle::cstore::CrateStoreDyn;
use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
-use crate::mir::Body;
+use crate::mir::ReadOnlyBodyCache;
use crate::mir::interpret::{GlobalId, ErrorHandled};
use crate::mir::GeneratorLayout;
use crate::session::CrateDisambiguator;
@@ -2784,11 +2784,7 @@
}
};
- if is_associated_item {
- Some(self.associated_item(def_id))
- } else {
- None
- }
+ is_associated_item.then(|| self.associated_item(def_id))
}
fn associated_item_from_trait_item_ref(self,
@@ -2985,10 +2981,10 @@
}
/// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair.
- pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
+ pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> ReadOnlyBodyCache<'tcx, 'tcx> {
match instance {
ty::InstanceDef::Item(did) => {
- self.optimized_mir(did)
+ self.optimized_mir(did).unwrap_read_only()
}
ty::InstanceDef::VtableShim(..) |
ty::InstanceDef::ReifyShim(..) |
@@ -2998,7 +2994,7 @@
ty::InstanceDef::ClosureOnceShim { .. } |
ty::InstanceDef::DropGlue(..) |
ty::InstanceDef::CloneShim(..) => {
- self.mir_shims(instance)
+ self.mir_shims(instance).unwrap_read_only()
}
}
}
@@ -3253,7 +3249,7 @@
let unnormalized_env = ty::ParamEnv::new(
tcx.intern_predicates(&predicates),
traits::Reveal::UserFacing,
- if tcx.sess.opts.debugging_opts.chalk { Some(def_id) } else { None }
+ tcx.sess.opts.debugging_opts.chalk.then_some(def_id),
);
let body_id = tcx.hir().as_local_hir_id(def_id).map_or(hir::DUMMY_HIR_ID, |id| {
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index c941b3e..745f7d0 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -682,7 +682,7 @@
// FIXME(eddyb) should use `def_span`.
if let Some(hir_id) = self.tcx().hir().as_local_hir_id(did) {
if self.tcx().sess.opts.debugging_opts.span_free_formats {
- p!(write("@{:?}", hir_id));
+ p!(write("@"), print_def_path(did, substs));
} else {
p!(write("@{:?}", self.tcx().hir().span(hir_id)));
}
@@ -1282,6 +1282,9 @@
if !self.empty_path {
write!(self, "::")?;
}
+ if ast::Ident::from_str(&name).is_raw_guess() {
+ write!(self, "r#")?;
+ }
write!(self, "{}", name)?;
// FIXME(eddyb) this will print e.g. `{{closure}}#3`, but it
diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs
index e5f4e79..2f30b79 100644
--- a/src/librustc/ty/query/job.rs
+++ b/src/librustc/ty/query/job.rs
@@ -303,13 +303,8 @@
return true;
}
- visit_waiters(query, |_, successor| {
- if connected_to_root(successor, visited) {
- Some(None)
- } else {
- None
- }
- }).is_some()
+ visit_waiters(query, |_, successor| connected_to_root(successor, visited).then_some(None))
+ .is_some()
}
// Deterministically pick an query from a list
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index ffbf881..ce76a4c 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -3,6 +3,7 @@
//! hand, though we've recently added some macros and proc-macros to help with the tedium.
use crate::hir::def::Namespace;
+use crate::hir::def_id::CRATE_DEF_INDEX;
use crate::mir::ProjectionKind;
use crate::mir::interpret;
use crate::ty::{self, Lift, Ty, TyCtxt, InferConst};
@@ -95,8 +96,11 @@
match *self {
ty::BrAnon(n) => write!(f, "BrAnon({:?})", n),
ty::BrNamed(did, name) => {
- write!(f, "BrNamed({:?}:{:?}, {})",
- did.krate, did.index, name)
+ if did.index == CRATE_DEF_INDEX {
+ write!(f, "BrNamed({})", name)
+ } else {
+ write!(f, "BrNamed({:?}, {})", did, name)
+ }
}
ty::BrEnv => write!(f, "BrEnv"),
}
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 8581a5b..7515d30 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -88,15 +88,7 @@
what);
}
-// Hack up our own formatting for the duration to make it easier for scripts
-// to parse (always use the same number of decimal places and the same unit).
-pub fn duration_to_secs_str(dur: Duration) -> String {
- const NANOS_PER_SEC: f64 = 1_000_000_000.0;
- let secs = dur.as_secs() as f64 +
- dur.subsec_nanos() as f64 / NANOS_PER_SEC;
-
- format!("{:.3}", secs)
-}
+pub use rustc_session::utils::duration_to_secs_str;
pub fn to_readable_str(mut val: usize) -> String {
let mut groups = vec![];
diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs
index 804a7af..1f3c8e1 100644
--- a/src/librustc_codegen_llvm/abi.rs
+++ b/src/librustc_codegen_llvm/abi.rs
@@ -372,7 +372,7 @@
fn llvm_cconv(&self) -> llvm::CallConv {
match self.conv {
- Conv::C => llvm::CCallConv,
+ Conv::C | Conv::Rust => llvm::CCallConv,
Conv::AmdGpuKernel => llvm::AmdGpuKernel,
Conv::ArmAapcs => llvm::ArmAapcsCallConv,
Conv::Msp430Intr => llvm::Msp430Intr,
@@ -388,6 +388,11 @@
}
fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
+ // FIXME(eddyb) can this also be applied to callsites?
+ if self.ret.layout.abi.is_uninhabited() {
+ llvm::Attribute::NoReturn.apply_llfn(llvm::AttributePlace::Function, llfn);
+ }
+
let mut i = 0;
let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn, ty);
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index 6f4e7d0..1ea9362 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -2,19 +2,20 @@
use std::ffi::CString;
-use rustc::hir::{CodegenFnAttrFlags, CodegenFnAttrs};
+use rustc::hir::CodegenFnAttrFlags;
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::session::Session;
use rustc::session::config::{Sanitizer, OptLevel};
-use rustc::ty::{self, TyCtxt, PolyFnSig};
+use rustc::ty::{self, TyCtxt, Ty};
use rustc::ty::layout::HasTyCtxt;
use rustc::ty::query::Providers;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_data_structures::fx::FxHashMap;
+use rustc_target::abi::call::Conv;
use rustc_target::spec::PanicStrategy;
use rustc_codegen_ssa::traits::*;
-use crate::abi::Abi;
+use crate::abi::FnAbi;
use crate::attributes;
use crate::llvm::{self, Attribute};
use crate::llvm::AttributePlace::Function;
@@ -26,7 +27,7 @@
/// Mark LLVM function to use provided inline heuristic.
#[inline]
-pub fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) {
+fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) {
use self::InlineAttr::*;
match inline {
Hint => Attribute::InlineHint.apply_llfn(Function, val),
@@ -58,7 +59,7 @@
/// Tell LLVM if this function should be 'naked', i.e., skip the epilogue and prologue.
#[inline]
-pub fn naked(val: &'ll Value, is_naked: bool) {
+fn naked(val: &'ll Value, is_naked: bool) {
Attribute::Naked.toggle_llfn(Function, val, is_naked);
}
@@ -72,7 +73,7 @@
/// Tell LLVM what instrument function to insert.
#[inline]
-pub fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
+fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
if cx.sess().instrument_mcount() {
// Similar to `clang -pg` behavior. Handled by the
// `post-inline-ee-instrument` LLVM pass.
@@ -88,7 +89,7 @@
}
}
-pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
+fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
// Only use stack probes if the target specification indicates that we
// should be using stack probes
if !cx.sess().target.target.options.stack_probes {
@@ -202,11 +203,10 @@
pub fn from_fn_attrs(
cx: &CodegenCx<'ll, 'tcx>,
llfn: &'ll Value,
- id: Option<DefId>,
- sig: PolyFnSig<'tcx>,
+ instance: ty::Instance<'tcx>,
+ fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
) {
- let codegen_fn_attrs = id.map(|id| cx.tcx.codegen_fn_attrs(id))
- .unwrap_or_else(|| CodegenFnAttrs::new());
+ let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id());
match codegen_fn_attrs.optimize {
OptimizeAttr::None => {
@@ -224,6 +224,11 @@
}
}
+ // FIXME(eddyb) consolidate these two `inline` calls (and avoid overwrites).
+ if instance.def.is_inline(cx.tcx) {
+ inline(cx, llfn, attributes::InlineAttr::Hint);
+ }
+
inline(cx, llfn, codegen_fn_attrs.inline);
// The `uwtable` attribute according to LLVM is:
@@ -276,8 +281,7 @@
// Special attribute for allocator functions, which can't unwind.
false
} else {
- let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
- if sig.abi == Abi::Rust || sig.abi == Abi::RustCall {
+ if fn_abi.conv == Conv::Rust {
// Any Rust method (or `extern "Rust" fn` or `extern
// "rust-call" fn`) is explicitly allowed to unwind
// (unless it has no-unwind attribute, handled above).
@@ -331,16 +335,14 @@
// Note that currently the `wasm-import-module` doesn't do anything, but
// eventually LLVM 7 should read this and ferry the appropriate import
// module to the output file.
- if let Some(id) = id {
- if cx.tcx.sess.target.target.arch == "wasm32" {
- if let Some(module) = wasm_import_module(cx.tcx, id) {
- llvm::AddFunctionAttrStringValue(
- llfn,
- llvm::AttributePlace::Function,
- const_cstr!("wasm-import-module"),
- &module,
- );
- }
+ if cx.tcx.sess.target.target.arch == "wasm32" {
+ if let Some(module) = wasm_import_module(cx.tcx, instance.def_id()) {
+ llvm::AddFunctionAttrStringValue(
+ llfn,
+ llvm::AttributePlace::Function,
+ const_cstr!("wasm-import-module"),
+ &module,
+ );
}
}
}
@@ -373,11 +375,7 @@
let native_libs = tcx.native_libraries(cnum);
let def_id_to_native_lib = native_libs.iter().filter_map(|lib|
- if let Some(id) = lib.foreign_module {
- Some((id, lib))
- } else {
- None
- }
+ lib.foreign_module.map(|id| (id, lib))
).collect::<FxHashMap<_, _>>();
let mut ret = FxHashMap::default();
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index d0b065c..858dd59 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -10,7 +10,7 @@
use rustc_codegen_ssa::traits::*;
use errors::{FatalError, Handler};
use rustc::dep_graph::WorkProduct;
-use rustc::dep_graph::cgu_reuse_tracker::CguReuse;
+use rustc_session::cgu_reuse_tracker::CguReuse;
use rustc::hir::def_id::LOCAL_CRATE;
use rustc::middle::exported_symbols::SymbolExportLevel;
use rustc::session::config::{self, Lto};
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 5dfb04a..ada29c3 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -22,7 +22,7 @@
use rustc_data_structures::small_c_str::SmallCStr;
use errors::{Handler, FatalError};
-use std::ffi::{CString, CStr};
+use std::ffi::CString;
use std::fs;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
@@ -167,7 +167,7 @@
let emit_stack_size_section = sess.opts.debugging_opts.emit_stack_sizes;
let asm_comments = sess.asm_comments();
-
+ let relax_elf_relocations = sess.target.target.options.relax_elf_relocations;
Arc::new(move || {
let tm = unsafe {
llvm::LLVMRustCreateTargetMachine(
@@ -183,6 +183,7 @@
singlethread,
asm_comments,
emit_stack_size_section,
+ relax_elf_relocations,
)
};
@@ -365,20 +366,6 @@
add_sanitizer_passes(config, &mut extra_passes);
- for pass_name in &cgcx.plugin_passes {
- if let Some(pass) = find_pass(pass_name) {
- extra_passes.push(pass);
- } else {
- diag_handler.err(&format!("a plugin asked for LLVM pass \
- `{}` but LLVM does not \
- recognize it", pass_name));
- }
-
- if pass_name == "name-anon-globals" {
- have_name_anon_globals_pass = true;
- }
- }
-
// Some options cause LLVM bitcode to be emitted, which uses ThinLTOBuffers, so we need
// to make sure we run LLVM's NameAnonGlobals pass when emitting bitcode; otherwise
// we'll get errors in LLVM.
@@ -601,14 +588,11 @@
cursor.position() as size_t
}
- with_codegen(tm, llmod, config.no_builtins, |cpm| {
- let result =
- llvm::LLVMRustPrintModule(cpm, llmod, out_c.as_ptr(), demangle_callback);
- llvm::LLVMDisposePassManager(cpm);
- result.into_result().map_err(|()| {
- let msg = format!("failed to write LLVM IR to {}", out.display());
- llvm_err(diag_handler, &msg)
- })
+ let result =
+ llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback);
+ result.into_result().map_err(|()| {
+ let msg = format!("failed to write LLVM IR to {}", out.display());
+ llvm_err(diag_handler, &msg)
})?;
}
@@ -849,8 +833,8 @@
})
.filter_map(|val| {
// Exclude some symbols that we know are not Rust symbols.
- let name = CStr::from_ptr(llvm::LLVMGetValueName(val));
- if ignored(name.to_bytes()) {
+ let name = llvm::get_value_name(val);
+ if ignored(name) {
None
} else {
Some((val, name))
@@ -858,7 +842,7 @@
})
.map(move |(val, name)| {
let mut imp_name = prefix.as_bytes().to_vec();
- imp_name.extend(name.to_bytes());
+ imp_name.extend(name);
let imp_name = CString::new(imp_name).unwrap();
(imp_name, val)
})
diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs
index 08fa23f..e0db7ca 100644
--- a/src/librustc_codegen_llvm/callee.rs
+++ b/src/librustc_codegen_llvm/callee.rs
@@ -4,6 +4,7 @@
//! and methods are represented as just a fn ptr and not a full
//! closure.
+use crate::abi::{FnAbi, FnAbiLlvmExt};
use crate::attributes;
use crate::llvm;
use crate::context::CodegenCx;
@@ -11,7 +12,7 @@
use rustc_codegen_ssa::traits::*;
use rustc::ty::{TypeFoldable, Instance};
-use rustc::ty::layout::{LayoutOf, HasTyCtxt};
+use rustc::ty::layout::{FnAbiExt, HasTyCtxt};
/// Codegens a reference to a fn/method item, monomorphizing and
/// inlining as it goes.
@@ -32,19 +33,19 @@
assert!(!instance.substs.has_escaping_bound_vars());
assert!(!instance.substs.has_param_types());
- let sig = instance.fn_sig(cx.tcx());
if let Some(&llfn) = cx.instances.borrow().get(&instance) {
return llfn;
}
let sym = tcx.symbol_name(instance).name.as_str();
- debug!("get_fn({:?}: {:?}) => {}", instance, sig, sym);
+ debug!("get_fn({:?}: {:?}) => {}", instance, instance.ty(cx.tcx()), sym);
- // Create a fn pointer with the substituted signature.
- let fn_ptr_ty = tcx.mk_fn_ptr(sig);
- let llptrty = cx.backend_type(cx.layout_of(fn_ptr_ty));
+ let fn_abi = FnAbi::of_instance(cx, instance, &[]);
let llfn = if let Some(llfn) = cx.get_declared_value(&sym) {
+ // Create a fn pointer with the new signature.
+ let llptrty = fn_abi.ptr_to_llvm_type(cx);
+
// This is subtle and surprising, but sometimes we have to bitcast
// the resulting fn pointer. The reason has to do with external
// functions. If you have two crates that both bind the same C
@@ -76,14 +77,10 @@
llfn
}
} else {
- let llfn = cx.declare_fn(&sym, sig);
- assert_eq!(cx.val_ty(llfn), llptrty);
+ let llfn = cx.declare_fn(&sym, &fn_abi);
debug!("get_fn: not casting pointer!");
- if instance.def.is_inline(tcx) {
- attributes::inline(cx, llfn, attributes::InlineAttr::Hint);
- }
- attributes::from_fn_attrs(cx, llfn, Some(instance.def.def_id()), sig);
+ attributes::from_fn_attrs(cx, llfn, instance, &fn_abi);
let instance_def_id = instance.def_id();
diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index f38f9df..419e99d 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -245,11 +245,7 @@
let (mut lo, mut hi) = (0u64, 0u64);
let success = llvm::LLVMRustConstInt128Get(v, sign_ext,
&mut hi, &mut lo);
- if success {
- Some(hi_lo_to_u128(lo, hi))
- } else {
- None
- }
+ success.then_some(hi_lo_to_u128(lo, hi))
})
}
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs
index 541b3d9..297aff9 100644
--- a/src/librustc_codegen_llvm/consts.rs
+++ b/src/librustc_codegen_llvm/consts.rs
@@ -21,7 +21,7 @@
use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags};
-use std::ffi::{CStr, CString};
+use std::ffi::CStr;
pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value {
let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1);
@@ -392,16 +392,14 @@
} else {
// If we created the global with the wrong type,
// correct the type.
- let empty_string = const_cstr!("");
- let name_str_ref = CStr::from_ptr(llvm::LLVMGetValueName(g));
- let name_string = CString::new(name_str_ref.to_bytes()).unwrap();
- llvm::LLVMSetValueName(g, empty_string.as_ptr());
+ let name = llvm::get_value_name(g).to_vec();
+ llvm::set_value_name(g, b"");
let linkage = llvm::LLVMRustGetLinkage(g);
let visibility = llvm::LLVMRustGetVisibility(g);
let new_g = llvm::LLVMRustGetOrInsertGlobal(
- self.llmod, name_string.as_ptr(), val_llty);
+ self.llmod, name.as_ptr().cast(), name.len(), val_llty);
llvm::LLVMRustSetLinkage(new_g, linkage);
llvm::LLVMRustSetVisibility(new_g, visibility);
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 4a40349..39ea1f6 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -1,3 +1,4 @@
+use crate::abi::FnAbi;
use crate::attributes;
use crate::llvm;
use crate::llvm_util;
@@ -15,7 +16,7 @@
use rustc::session::config::{self, DebugInfo};
use rustc::session::Session;
use rustc::ty::layout::{
- LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, HasParamEnv
+ FnAbiExt, LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, HasParamEnv
};
use rustc::ty::{self, Ty, TyCtxt, Instance};
use rustc::util::nodemap::FxHashMap;
@@ -420,7 +421,8 @@
Abi::C
));
- let llfn = self.declare_fn("rust_eh_unwind_resume", sig);
+ let fn_abi = FnAbi::of_fn_ptr(self, sig, &[]);
+ let llfn = self.declare_fn("rust_eh_unwind_resume", &fn_abi);
attributes::apply_target_cpu_attr(self, llfn);
unwresume.set(Some(llfn));
llfn
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 7713fe4..a3782ec 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -16,7 +16,7 @@
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
use rustc::ty::subst::{SubstsRef, GenericArgKind};
-use crate::abi::Abi;
+use crate::abi::FnAbi;
use crate::common::CodegenCx;
use crate::builder::Builder;
use crate::value::Value;
@@ -32,7 +32,7 @@
use libc::c_uint;
use std::cell::RefCell;
-use std::ffi::{CStr, CString};
+use std::ffi::CString;
use smallvec::SmallVec;
use syntax_pos::{self, BytePos, Span, Pos};
@@ -255,23 +255,11 @@
return;
}
- let old_name = unsafe {
- CStr::from_ptr(llvm::LLVMGetValueName(value))
- };
- match old_name.to_str() {
- Ok("") => {}
- Ok(_) => {
- // Avoid replacing the name if it already exists.
- // While we could combine the names somehow, it'd
- // get noisy quick, and the usefulness is dubious.
- return;
- }
- Err(_) => return,
- }
-
- let cname = SmallCStr::new(name);
- unsafe {
- llvm::LLVMSetValueName(value, cname.as_ptr());
+ // Avoid replacing the name if it already exists.
+ // While we could combine the names somehow, it'd
+ // get noisy quick, and the usefulness is dubious.
+ if llvm::get_value_name(value).is_empty() {
+ llvm::set_value_name(value, name.as_bytes());
}
}
}
@@ -280,7 +268,7 @@
fn create_function_debug_context(
&self,
instance: Instance<'tcx>,
- sig: ty::FnSig<'tcx>,
+ fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
llfn: &'ll Value,
mir: &mir::Body<'_>,
) -> Option<FunctionDebugContext<&'ll DIScope>> {
@@ -308,7 +296,7 @@
let file_metadata = file_metadata(self, &loc.file.name, def_id.krate);
let function_type_metadata = unsafe {
- let fn_signature = get_function_signature(self, sig);
+ let fn_signature = get_function_signature(self, fn_abi);
llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), file_metadata, fn_signature)
};
@@ -338,7 +326,7 @@
let mut flags = DIFlags::FlagPrototyped;
- if self.layout_of(sig.output()).abi.is_uninhabited() {
+ if fn_abi.ret.layout.abi.is_uninhabited() {
flags |= DIFlags::FlagNoReturn;
}
@@ -392,25 +380,20 @@
fn get_function_signature<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
- sig: ty::FnSig<'tcx>,
+ fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
) -> &'ll DIArray {
if cx.sess().opts.debuginfo == DebugInfo::Limited {
return create_DIArray(DIB(cx), &[]);
}
- let mut signature = Vec::with_capacity(sig.inputs().len() + 1);
+ let mut signature = Vec::with_capacity(fn_abi.args.len() + 1);
// Return type -- llvm::DIBuilder wants this at index 0
- signature.push(match sig.output().kind {
- ty::Tuple(ref tys) if tys.is_empty() => None,
- _ => Some(type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP))
- });
-
- let inputs = if sig.abi == Abi::RustCall {
- &sig.inputs()[..sig.inputs().len() - 1]
+ signature.push(if fn_abi.ret.is_ignore() {
+ None
} else {
- sig.inputs()
- };
+ Some(type_metadata(cx, fn_abi.ret.layout.ty, syntax_pos::DUMMY_SP))
+ });
// Arguments types
if cx.sess().target.target.options.is_like_msvc {
@@ -424,7 +407,8 @@
// and a function `fn bar(x: [(); 7])` as `fn bar(x: *const ())`.
// This transformed type is wrong, but these function types are
// already inaccurate due to ABI adjustments (see #42800).
- signature.extend(inputs.iter().map(|&t| {
+ signature.extend(fn_abi.args.iter().map(|arg| {
+ let t = arg.layout.ty;
let t = match t.kind {
ty::Array(ct, _)
if (ct == cx.tcx.types.u8) || cx.layout_of(ct).is_zst() => {
@@ -435,21 +419,11 @@
Some(type_metadata(cx, t, syntax_pos::DUMMY_SP))
}));
} else {
- signature.extend(inputs.iter().map(|t| {
- Some(type_metadata(cx, t, syntax_pos::DUMMY_SP))
+ signature.extend(fn_abi.args.iter().map(|arg| {
+ Some(type_metadata(cx, arg.layout.ty, syntax_pos::DUMMY_SP))
}));
}
- if sig.abi == Abi::RustCall && !sig.inputs().is_empty() {
- if let ty::Tuple(args) = sig.inputs()[sig.inputs().len() - 1].kind {
- signature.extend(
- args.iter().map(|argument_type| {
- Some(type_metadata(cx, argument_type.expect_ty(), syntax_pos::DUMMY_SP))
- })
- );
- }
- }
-
create_DIArray(DIB(cx), &signature[..])
}
diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs
index 46cdd2a..fa9fc46 100644
--- a/src/librustc_codegen_llvm/declare.rs
+++ b/src/librustc_codegen_llvm/declare.rs
@@ -18,8 +18,7 @@
use crate::context::CodegenCx;
use crate::type_::Type;
use crate::value::Value;
-use rustc::ty::{self, PolyFnSig};
-use rustc::ty::layout::{FnAbiExt, LayoutOf};
+use rustc::ty::Ty;
use rustc::session::config::Sanitizer;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_codegen_ssa::traits::*;
@@ -77,9 +76,8 @@
name: &str, ty: &'ll Type
) -> &'ll Value {
debug!("declare_global(name={:?})", name);
- let namebuf = SmallCStr::new(name);
unsafe {
- llvm::LLVMRustGetOrInsertGlobal(self.llmod, namebuf.as_ptr(), ty)
+ llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_ptr().cast(), name.len(), ty)
}
}
@@ -94,21 +92,12 @@
fn declare_fn(
&self,
name: &str,
- sig: PolyFnSig<'tcx>,
+ fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
) -> &'ll Value {
- debug!("declare_rust_fn(name={:?}, sig={:?})", name, sig);
- let sig = self.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
- debug!("declare_rust_fn (after region erasure) sig={:?}", sig);
+ debug!("declare_rust_fn(name={:?}, fn_abi={:?})", name, fn_abi);
- let fn_abi = FnAbi::new(self, sig, &[]);
let llfn = declare_raw_fn(self, name, fn_abi.llvm_cconv(), fn_abi.llvm_type(self));
-
- if self.layout_of(sig.output()).abi.is_uninhabited() {
- llvm::Attribute::NoReturn.apply_llfn(Function, llfn);
- }
-
fn_abi.apply_attrs_llfn(self, llfn);
-
llfn
}
@@ -130,28 +119,6 @@
}
}
- fn define_fn(
- &self,
- name: &str,
- fn_sig: PolyFnSig<'tcx>,
- ) -> &'ll Value {
- if self.get_defined_value(name).is_some() {
- self.sess().fatal(&format!("symbol `{}` already defined", name))
- } else {
- self.declare_fn(name, fn_sig)
- }
- }
-
- fn define_internal_fn(
- &self,
- name: &str,
- fn_sig: PolyFnSig<'tcx>,
- ) -> &'ll Value {
- let llfn = self.define_fn(name, fn_sig);
- unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };
- llfn
- }
-
fn get_declared_value(&self, name: &str) -> Option<&'ll Value> {
debug!("get_declared_value(name={:?})", name);
let namebuf = SmallCStr::new(name);
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index aa55f3a..1767ad1 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -1,4 +1,3 @@
-use crate::attributes;
use crate::llvm;
use crate::llvm_util;
use crate::abi::{Abi, FnAbi, LlvmType, PassMode};
@@ -14,7 +13,7 @@
use rustc_codegen_ssa::glue;
use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types};
use rustc::ty::{self, Ty};
-use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive};
+use rustc::ty::layout::{self, FnAbiExt, LayoutOf, HasTyCtxt, Primitive};
use rustc::mir::interpret::GlobalId;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc::hir;
@@ -442,32 +441,11 @@
let is_left = name == "rotate_left";
let val = args[0].immediate();
let raw_shift = args[1].immediate();
- if llvm_util::get_major_version() >= 7 {
- // rotate = funnel shift with first two args the same
- let llvm_name = &format!("llvm.fsh{}.i{}",
- if is_left { 'l' } else { 'r' }, width);
- let llfn = self.get_intrinsic(llvm_name);
- self.call(llfn, &[val, val, raw_shift], None)
- } else {
- // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
- // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
- let width = self.const_uint(
- self.type_ix(width),
- width,
- );
- let shift = self.urem(raw_shift, width);
- let width_minus_raw_shift = self.sub(width, raw_shift);
- let inv_shift = self.urem(width_minus_raw_shift, width);
- let shift1 = self.shl(
- val,
- if is_left { shift } else { inv_shift },
- );
- let shift2 = self.lshr(
- val,
- if !is_left { shift } else { inv_shift },
- );
- self.or(shift1, shift2)
- }
+ // rotate = funnel shift with first two args the same
+ let llvm_name = &format!("llvm.fsh{}.i{}",
+ if is_left { 'l' } else { 'r' }, width);
+ let llfn = self.get_intrinsic(llvm_name);
+ self.call(llfn, &[val, val, raw_shift], None)
},
"saturating_add" | "saturating_sub" => {
let is_add = name == "saturating_add";
@@ -538,9 +516,36 @@
return;
}
}
-
},
+ "float_to_int_approx_unchecked" => {
+ if float_type_width(arg_tys[0]).is_none() {
+ span_invalid_monomorphization_error(
+ tcx.sess, span,
+ &format!("invalid monomorphization of `float_to_int_approx_unchecked` \
+ intrinsic: expected basic float type, \
+ found `{}`", arg_tys[0]));
+ return;
+ }
+ match int_type_width_signed(ret_ty, self.cx) {
+ Some((width, signed)) => {
+ if signed {
+ self.fptosi(args[0].immediate(), self.cx.type_ix(width))
+ } else {
+ self.fptoui(args[0].immediate(), self.cx.type_ix(width))
+ }
+ }
+ None => {
+ span_invalid_monomorphization_error(
+ tcx.sess, span,
+ &format!("invalid monomorphization of `float_to_int_approx_unchecked` \
+ intrinsic: expected basic integer type, \
+ found `{}`", ret_ty));
+ return;
+ }
+ }
+ }
+
"discriminant_value" => {
args[0].deref(self.cx()).codegen_get_discr(self, ret_ty)
}
@@ -1013,8 +1018,10 @@
hir::Unsafety::Unsafe,
Abi::Rust
));
- let llfn = cx.define_internal_fn(name, rust_fn_sig);
- attributes::from_fn_attrs(cx, llfn, None, rust_fn_sig);
+ let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]);
+ let llfn = cx.declare_fn(name, &fn_abi);
+ // FIXME(eddyb) find a nicer way to do this.
+ unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };
let bx = Builder::new_block(cx, llfn, "entry-block");
codegen(bx);
llfn
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index acc221f..00a84f8 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -6,6 +6,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(const_cstr_unchecked)]
@@ -43,6 +44,7 @@
extern crate syntax;
extern crate syntax_pos;
extern crate rustc_errors as errors;
+extern crate rustc_session;
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, FatLTOInput};
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index a49e863..5da3275 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -701,8 +701,8 @@
// Operations on all values
pub fn LLVMTypeOf(Val: &Value) -> &Type;
- pub fn LLVMGetValueName(Val: &Value) -> *const c_char;
- pub fn LLVMSetValueName(Val: &Value, Name: *const c_char);
+ pub fn LLVMGetValueName2(Val: &Value, Length: *mut size_t) -> *const c_char;
+ pub fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t);
pub fn LLVMReplaceAllUsesWith(OldVal: &'a Value, NewVal: &'a Value);
pub fn LLVMSetMetadata(Val: &'a Value, KindID: c_uint, Node: &'a Value);
@@ -774,7 +774,8 @@
pub fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>;
pub fn LLVMAddGlobal(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value;
pub fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>;
- pub fn LLVMRustGetOrInsertGlobal(M: &'a Module, Name: *const c_char, T: &'a Type) -> &'a Value;
+ pub fn LLVMRustGetOrInsertGlobal(M: &'a Module, Name: *const c_char, NameLen: size_t,
+ T: &'a Type) -> &'a Value;
pub fn LLVMRustInsertPrivateGlobal(M: &'a Module, T: &'a Type) -> &'a Value;
pub fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>;
pub fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>;
@@ -1702,7 +1703,8 @@
TrapUnreachable: bool,
Singlethread: bool,
AsmComments: bool,
- EmitStackSizeSection: bool)
+ EmitStackSizeSection: bool,
+ RelaxELFRelocations: bool)
-> Option<&'static mut TargetMachine>;
pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine);
pub fn LLVMRustAddBuilderLibraryInfo(PMB: &'a PassManagerBuilder,
@@ -1726,8 +1728,7 @@
Output: *const c_char,
FileType: FileType)
-> LLVMRustResult;
- pub fn LLVMRustPrintModule(PM: &PassManager<'a>,
- M: &'a Module,
+ pub fn LLVMRustPrintModule(M: &'a Module,
Output: *const c_char,
Demangle: extern fn(*const c_char,
size_t,
@@ -1811,7 +1812,7 @@
pub fn LLVMRustPositionBuilderAtStart(B: &Builder<'a>, BB: &'a BasicBlock);
- pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char);
+ pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char, NameLen: size_t);
pub fn LLVMRustUnsetComdat(V: &Value);
pub fn LLVMRustSetModulePICLevel(M: &Module);
pub fn LLVMRustSetModulePIELevel(M: &Module);
diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs
index 5781593..d2d4187 100644
--- a/src/librustc_codegen_llvm/llvm/mod.rs
+++ b/src/librustc_codegen_llvm/llvm/mod.rs
@@ -115,7 +115,8 @@
// For more details on COMDAT sections see e.g., http://www.airs.com/blog/archives/52
pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) {
unsafe {
- LLVMRustSetComdat(llmod, val, LLVMGetValueName(val));
+ let name = get_value_name(val);
+ LLVMRustSetComdat(llmod, val, name.as_ptr().cast(), name.len());
}
}
@@ -217,6 +218,23 @@
}
}
+/// Safe wrapper for `LLVMGetValueName2` into a byte slice
+pub fn get_value_name(value: &'a Value) -> &'a [u8] {
+ unsafe {
+ let mut len = 0;
+ let data = LLVMGetValueName2(value, &mut len);
+ std::slice::from_raw_parts(data.cast(), len)
+ }
+}
+
+/// Safe wrapper for `LLVMSetValueName2` from a byte slice
+pub fn set_value_name(value: &Value, name: &[u8]) {
+ unsafe {
+ let data = name.as_ptr().cast();
+ LLVMSetValueName2(value, data, name.len());
+ }
+}
+
pub fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
let sr = RustString {
bytes: RefCell::new(Vec::new()),
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index 7bff9e6..72612c4 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -108,6 +108,8 @@
("rclass", Some(sym::arm_target_feature)),
("dsp", Some(sym::arm_target_feature)),
("neon", Some(sym::arm_target_feature)),
+ ("crc", Some(sym::arm_target_feature)),
+ ("crypto", Some(sym::arm_target_feature)),
("v5te", Some(sym::arm_target_feature)),
("v6", Some(sym::arm_target_feature)),
("v6k", Some(sym::arm_target_feature)),
diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs
index c1703ff..cbc8af4 100644
--- a/src/librustc_codegen_llvm/mono_item.rs
+++ b/src/librustc_codegen_llvm/mono_item.rs
@@ -1,3 +1,4 @@
+use crate::abi::FnAbi;
use crate::attributes;
use crate::base;
use crate::context::CodegenCx;
@@ -6,7 +7,7 @@
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::mir::mono::{Linkage, Visibility};
use rustc::ty::{TypeFoldable, Instance};
-use rustc::ty::layout::{LayoutOf, HasTyCtxt};
+use rustc::ty::layout::{FnAbiExt, LayoutOf};
use rustc_codegen_ssa::traits::*;
pub use rustc::mir::mono::MonoItem;
@@ -42,10 +43,10 @@
assert!(!instance.substs.needs_infer() &&
!instance.substs.has_param_types());
- let mono_sig = instance.fn_sig(self.tcx());
- let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
- let lldecl = self.declare_fn(symbol_name, mono_sig);
+ let fn_abi = FnAbi::of_instance(self, instance, &[]);
+ let lldecl = self.declare_fn(symbol_name, &fn_abi);
unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) };
+ let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
base::set_link_section(lldecl, &attrs);
if linkage == Linkage::LinkOnceODR ||
linkage == Linkage::WeakODR {
@@ -67,16 +68,9 @@
}
}
- debug!("predefine_fn: mono_sig = {:?} instance = {:?}", mono_sig, instance);
- if instance.def.is_inline(self.tcx) {
- attributes::inline(self, lldecl, attributes::InlineAttr::Hint);
- }
- attributes::from_fn_attrs(
- self,
- lldecl,
- Some(instance.def.def_id()),
- mono_sig,
- );
+ debug!("predefine_fn: instance = {:?}", instance);
+
+ attributes::from_fn_attrs(self, lldecl, instance, &fn_abi);
self.instances.borrow_mut().insert(instance, lldecl);
}
diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs
index c21e62e..d77bbb2 100644
--- a/src/librustc_codegen_llvm/type_of.rs
+++ b/src/librustc_codegen_llvm/type_of.rs
@@ -235,11 +235,7 @@
cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx))
}
ty::FnPtr(sig) => {
- let sig = cx.tcx.normalize_erasing_late_bound_regions(
- ty::ParamEnv::reveal_all(),
- &sig,
- );
- cx.fn_ptr_backend_type(&FnAbi::new(cx, sig, &[]))
+ cx.fn_ptr_backend_type(&FnAbi::of_fn_ptr(cx, sig, &[]))
}
_ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO)
};
diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml
index 478c3a9..53d3c51 100644
--- a/src/librustc_codegen_ssa/Cargo.toml
+++ b/src/librustc_codegen_ssa/Cargo.toml
@@ -32,3 +32,4 @@
rustc_index = { path = "../librustc_index" }
rustc_target = { path = "../librustc_target" }
rustc_error_codes = { path = "../librustc_error_codes" }
+rustc_session = { path = "../librustc_session" }
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index 999cc40..4278852 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -398,7 +398,8 @@
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
// Symbol visibility in object files typically takes care of this.
- if crate_type == CrateType::Executable {
+ if crate_type == CrateType::Executable &&
+ self.sess.target.target.options.override_export_symbols.is_none() {
return;
}
diff --git a/src/librustc_codegen_ssa/back/rpath.rs b/src/librustc_codegen_ssa/back/rpath.rs
index e27cb6d..cd3d999 100644
--- a/src/librustc_codegen_ssa/back/rpath.rs
+++ b/src/librustc_codegen_ssa/back/rpath.rs
@@ -119,11 +119,7 @@
use std::path::Component;
if path.is_absolute() != base.is_absolute() {
- if path.is_absolute() {
- Some(PathBuf::from(path))
- } else {
- None
- }
+ path.is_absolute().then(|| PathBuf::from(path))
} else {
let mut ita = path.components();
let mut itb = base.components();
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index f8b3e0f..cea5dc1 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -85,11 +85,7 @@
match tcx.hir().get(hir_id) {
Node::ForeignItem(..) => {
let def_id = tcx.hir().local_def_id(hir_id);
- if tcx.is_statically_included_foreign_item(def_id) {
- Some(def_id)
- } else {
- None
- }
+ tcx.is_statically_included_foreign_item(def_id).then_some(def_id)
}
// Only consider nodes that actually have exported symbols.
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 9d3e574..283295c 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -10,7 +10,7 @@
use rustc_incremental::{copy_cgu_workproducts_to_incr_comp_cache_dir,
in_incr_comp_dir, in_incr_comp_dir_sess};
use rustc::dep_graph::{WorkProduct, WorkProductId, WorkProductFileKind};
-use rustc::dep_graph::cgu_reuse_tracker::CguReuseTracker;
+use rustc_session::cgu_reuse_tracker::CguReuseTracker;
use rustc::middle::cstore::EncodedMetadata;
use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Lto,
Sanitizer, SwitchWithOptPath};
@@ -231,8 +231,6 @@
pub total_cgus: usize,
// Handler to use for diagnostics produced during codegen.
pub diag_emitter: SharedEmitter,
- // LLVM passes added by plugins.
- pub plugin_passes: Vec<String>,
// LLVM optimizations for which we want to print remarks.
pub remark: Passes,
// Worker thread number
@@ -1028,7 +1026,6 @@
time_passes: sess.time_extended(),
prof: sess.prof.clone(),
exported_symbols,
- plugin_passes: sess.plugin_llvm_passes.borrow().clone(),
remark: sess.opts.cg.remark.clone(),
worker: 0,
incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()),
@@ -1755,7 +1752,7 @@
}
};
- sess.cgu_reuse_tracker.check_expected_reuse(sess);
+ sess.cgu_reuse_tracker.check_expected_reuse(sess.diagnostic());
sess.abort_if_errors();
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index 22693be..f6725e6 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -25,8 +25,8 @@
use crate::mir::place::PlaceRef;
use crate::traits::*;
-use rustc::dep_graph::cgu_reuse_tracker::CguReuse;
use rustc::hir;
+use rustc_session::cgu_reuse_tracker::CguReuse;
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::middle::cstore::EncodedMetadata;
use rustc::middle::lang_items::StartFnLangItem;
@@ -368,13 +368,7 @@
// release builds.
info!("codegen_instance({})", instance);
- let sig = instance.fn_sig(cx.tcx());
- let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
-
- let lldecl = cx.get_fn(instance);
-
- let mir = cx.tcx().instance_mir(instance.def);
- mir::codegen_mir::<Bx>(cx, lldecl, &mir, instance, sig);
+ mir::codegen_mir::<Bx>(cx, instance);
}
/// Creates the `main` function which will initialize the rust runtime and call
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index 9784d87..9919666 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -1,5 +1,6 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(core_intrinsics)]
@@ -68,22 +69,14 @@
emit_bc: bool,
emit_bc_compressed: bool,
outputs: &OutputFilenames) -> CompiledModule {
- let object = if emit_obj {
- Some(outputs.temp_path(OutputType::Object, Some(&self.name)))
- } else {
- None
- };
- let bytecode = if emit_bc {
- Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name)))
- } else {
- None
- };
- let bytecode_compressed = if emit_bc_compressed {
- Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name))
- .with_extension(RLIB_BYTECODE_EXTENSION))
- } else {
- None
- };
+ let object = emit_obj
+ .then(|| outputs.temp_path(OutputType::Object, Some(&self.name)));
+ let bytecode = emit_bc
+ .then(|| outputs.temp_path(OutputType::Bitcode, Some(&self.name)));
+ let bytecode_compressed = emit_bc_compressed.then(|| {
+ outputs.temp_path(OutputType::Bitcode, Some(&self.name))
+ .with_extension(RLIB_BYTECODE_EXTENSION)
+ });
CompiledModule {
name: self.name.clone(),
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index e44551f..6c62708 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -29,7 +29,7 @@
// FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
// of putting everything in allocas just so we can use llvm.dbg.declare.
if fx.cx.sess().opts.debuginfo == DebugInfo::Full {
- if mir.local_kind(local) == mir::LocalKind::Arg {
+ if fx.mir.local_kind(local) == mir::LocalKind::Arg {
analyzer.not_ssa(local);
continue;
}
@@ -70,9 +70,10 @@
fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>) -> Self {
let invalid_location =
mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location();
+ let dominators = fx.mir.dominators();
let mut analyzer = LocalAnalyzer {
fx,
- dominators: fx.mir.dominators(),
+ dominators,
non_ssa_locals: BitSet::new_empty(fx.mir.local_decls.len()),
first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls)
};
@@ -130,7 +131,7 @@
};
if is_consume {
let base_ty =
- mir::Place::ty_from(place_ref.base, proj_base, self.fx.mir, cx.tcx());
+ mir::Place::ty_from(place_ref.base, proj_base, *self.fx.mir, cx.tcx());
let base_ty = self.fx.monomorphize(&base_ty);
// ZSTs don't require any actual memory access.
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 14be0e8..ce703f2 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -24,28 +24,28 @@
/// Used by `FunctionCx::codegen_terminator` for emitting common patterns
/// e.g., creating a basic block, calling a function, etc.
-struct TerminatorCodegenHelper<'a, 'tcx> {
- bb: &'a mir::BasicBlock,
- terminator: &'a mir::Terminator<'tcx>,
+struct TerminatorCodegenHelper<'tcx> {
+ bb: mir::BasicBlock,
+ terminator: &'tcx mir::Terminator<'tcx>,
funclet_bb: Option<mir::BasicBlock>,
}
-impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> {
+impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
/// Returns the associated funclet from `FunctionCx::funclets` for the
/// `funclet_bb` member if it is not `None`.
- fn funclet<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
+ fn funclet<'b, Bx: BuilderMethods<'a, 'tcx>>(
&self,
- fx: &'c mut FunctionCx<'b, 'tcx, Bx>,
- ) -> Option<&'c Bx::Funclet> {
+ fx: &'b mut FunctionCx<'a, 'tcx, Bx>,
+ ) -> Option<&'b Bx::Funclet> {
match self.funclet_bb {
Some(funcl) => fx.funclets[funcl].as_ref(),
None => None,
}
}
- fn lltarget<'b, 'c, Bx: BuilderMethods<'b, 'tcx>>(
+ fn lltarget<Bx: BuilderMethods<'a, 'tcx>>(
&self,
- fx: &'c mut FunctionCx<'b, 'tcx, Bx>,
+ fx: &mut FunctionCx<'a, 'tcx, Bx>,
target: mir::BasicBlock,
) -> (Bx::BasicBlock, bool) {
let span = self.terminator.source_info.span;
@@ -63,9 +63,9 @@
}
/// Create a basic block.
- fn llblock<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
+ fn llblock<Bx: BuilderMethods<'a, 'tcx>>(
&self,
- fx: &'c mut FunctionCx<'b, 'tcx, Bx>,
+ fx: &mut FunctionCx<'a, 'tcx, Bx>,
target: mir::BasicBlock,
) -> Bx::BasicBlock {
let (lltarget, is_cleanupret) = self.lltarget(fx, target);
@@ -83,9 +83,9 @@
}
}
- fn funclet_br<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
+ fn funclet_br<Bx: BuilderMethods<'a, 'tcx>>(
&self,
- fx: &'c mut FunctionCx<'b, 'tcx, Bx>,
+ fx: &mut FunctionCx<'a, 'tcx, Bx>,
bx: &mut Bx,
target: mir::BasicBlock,
) {
@@ -101,9 +101,9 @@
/// Call `fn_ptr` of `fn_abi` with the arguments `llargs`, the optional
/// return destination `destination` and the cleanup function `cleanup`.
- fn do_call<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
+ fn do_call<Bx: BuilderMethods<'a, 'tcx>>(
&self,
- fx: &'c mut FunctionCx<'b, 'tcx, Bx>,
+ fx: &mut FunctionCx<'a, 'tcx, Bx>,
bx: &mut Bx,
fn_abi: FnAbi<'tcx, Ty<'tcx>>,
fn_ptr: Bx::Value,
@@ -132,7 +132,7 @@
} else {
let llret = bx.call(fn_ptr, &llargs, self.funclet(fx));
bx.apply_attrs_callsite(&fn_abi, llret);
- if fx.mir[*self.bb].is_cleanup {
+ if fx.mir[self.bb].is_cleanup {
// Cleanup is always the cold path. Don't inline
// drop glue. Also, when there is a deeply-nested
// struct, there are "symmetry" issues that cause
@@ -151,15 +151,15 @@
// Generate sideeffect intrinsic if jumping to any of the targets can form
// a loop.
- fn maybe_sideeffect<'b, 'tcx2: 'b, Bx: BuilderMethods<'b, 'tcx2>>(
+ fn maybe_sideeffect<Bx: BuilderMethods<'a, 'tcx>>(
&self,
- mir: &'b mir::Body<'tcx>,
+ mir: mir::ReadOnlyBodyCache<'tcx, 'tcx>,
bx: &mut Bx,
targets: &[mir::BasicBlock],
) {
if bx.tcx().sess.opts.debugging_opts.insert_sideeffect {
- if targets.iter().any(|target| {
- *target <= *self.bb
+ if targets.iter().any(|&target| {
+ target <= self.bb
&& target
.start_location()
.is_predecessor_of(self.bb.start_location(), mir)
@@ -173,9 +173,9 @@
/// Codegen implementations for some terminator variants.
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
/// Generates code for a `Resume` terminator.
- fn codegen_resume_terminator<'b>(
+ fn codegen_resume_terminator(
&mut self,
- helper: TerminatorCodegenHelper<'b, 'tcx>,
+ helper: TerminatorCodegenHelper<'tcx>,
mut bx: Bx,
) {
if let Some(funclet) = helper.funclet(self) {
@@ -201,9 +201,9 @@
}
}
- fn codegen_switchint_terminator<'b>(
+ fn codegen_switchint_terminator(
&mut self,
- helper: TerminatorCodegenHelper<'b, 'tcx>,
+ helper: TerminatorCodegenHelper<'tcx>,
mut bx: Bx,
discr: &mir::Operand<'tcx>,
switch_ty: Ty<'tcx>,
@@ -261,7 +261,11 @@
if self.fn_abi.ret.layout.abi.is_uninhabited() {
// Functions with uninhabited return values are marked `noreturn`,
// so we should make sure that we never actually do.
+ // We play it safe by using a well-defined `abort`, but we could go for immediate UB
+ // if that turns out to be helpful.
bx.abort();
+ // `abort` does not terminate the block, so we still need to generate
+ // an `unreachable` terminator after it.
bx.unreachable();
return;
}
@@ -316,15 +320,15 @@
}
- fn codegen_drop_terminator<'b>(
+ fn codegen_drop_terminator(
&mut self,
- helper: TerminatorCodegenHelper<'b, 'tcx>,
+ helper: TerminatorCodegenHelper<'tcx>,
mut bx: Bx,
location: &mir::Place<'tcx>,
target: mir::BasicBlock,
unwind: Option<mir::BasicBlock>,
) {
- let ty = location.ty(self.mir, bx.tcx()).ty;
+ let ty = location.ty(*self.mir, bx.tcx()).ty;
let ty = self.monomorphize(&ty);
let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty);
@@ -345,20 +349,21 @@
&args1[..]
};
let (drop_fn, fn_abi) = match ty.kind {
+ // FIXME(eddyb) perhaps move some of this logic into
+ // `Instance::resolve_drop_in_place`?
ty::Dynamic(..) => {
- let sig = drop_fn.fn_sig(self.cx.tcx());
- let sig = self.cx.tcx().normalize_erasing_late_bound_regions(
- ty::ParamEnv::reveal_all(),
- &sig,
- );
- let fn_abi = FnAbi::new_vtable(&bx, sig, &[]);
+ let virtual_drop = Instance {
+ def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
+ substs: drop_fn.substs,
+ };
+ let fn_abi = FnAbi::of_instance(&bx, virtual_drop, &[]);
let vtable = args[1];
args = &args[..1];
(meth::DESTRUCTOR.get_fn(&mut bx, vtable, &fn_abi), fn_abi)
}
_ => {
(bx.get_fn_addr(drop_fn),
- FnAbi::of_instance(&bx, drop_fn))
+ FnAbi::of_instance(&bx, drop_fn, &[]))
}
};
helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
@@ -367,9 +372,9 @@
unwind);
}
- fn codegen_assert_terminator<'b>(
+ fn codegen_assert_terminator(
&mut self,
- helper: TerminatorCodegenHelper<'b, 'tcx>,
+ helper: TerminatorCodegenHelper<'tcx>,
mut bx: Bx,
terminator: &mir::Terminator<'tcx>,
cond: &mir::Operand<'tcx>,
@@ -439,16 +444,16 @@
// Obtain the panic entry point.
let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item);
let instance = ty::Instance::mono(bx.tcx(), def_id);
- let fn_abi = FnAbi::of_instance(&bx, instance);
+ let fn_abi = FnAbi::of_instance(&bx, instance, &[]);
let llfn = bx.get_fn_addr(instance);
// Codegen the actual panic invoke/call.
helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup);
}
- fn codegen_call_terminator<'b>(
+ fn codegen_call_terminator(
&mut self,
- helper: TerminatorCodegenHelper<'b, 'tcx>,
+ helper: TerminatorCodegenHelper<'tcx>,
mut bx: Bx,
terminator: &mir::Terminator<'tcx>,
func: &mir::Operand<'tcx>,
@@ -474,12 +479,20 @@
_ => bug!("{} is not callable", callee.layout.ty),
};
let def = instance.map(|i| i.def);
+
+ if let Some(ty::InstanceDef::DropGlue(_, None)) = def {
+ // Empty drop glue; a no-op.
+ let &(_, target) = destination.as_ref().unwrap();
+ helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
+ helper.funclet_br(self, &mut bx, target);
+ return;
+ }
+
+ // FIXME(eddyb) avoid computing this if possible, when `instance` is
+ // available - right now `sig` is only needed for getting the `abi`
+ // and figuring out how many extra args were passed to a C-variadic `fn`.
let sig = callee.layout.ty.fn_sig(bx.tcx());
- let sig = bx.tcx().normalize_erasing_late_bound_regions(
- ty::ParamEnv::reveal_all(),
- &sig,
- );
- let abi = sig.abi;
+ let abi = sig.abi();
// Handle intrinsics old codegen wants Expr's for, ourselves.
let intrinsic = match def {
@@ -489,6 +502,17 @@
};
let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
+ let extra_args = &args[sig.inputs().skip_binder().len()..];
+ let extra_args = extra_args.iter().map(|op_arg| {
+ let op_ty = op_arg.ty(*self.mir, bx.tcx());
+ self.monomorphize(&op_ty)
+ }).collect::<Vec<_>>();
+
+ let fn_abi = match instance {
+ Some(instance) => FnAbi::of_instance(&bx, instance, &extra_args),
+ None => FnAbi::of_fn_ptr(&bx, sig, &extra_args)
+ };
+
if intrinsic == Some("transmute") {
if let Some(destination_ref) = destination.as_ref() {
let &(ref dest, target) = destination_ref;
@@ -502,44 +526,17 @@
// we can do what we like. Here, we declare that transmuting
// into an uninhabited type is impossible, so anything following
// it must be unreachable.
- assert_eq!(bx.layout_of(sig.output()).abi, layout::Abi::Uninhabited);
+ assert_eq!(fn_abi.ret.layout.abi, layout::Abi::Uninhabited);
bx.unreachable();
}
return;
}
- let extra_args = &args[sig.inputs().len()..];
- let extra_args = extra_args.iter().map(|op_arg| {
- let op_ty = op_arg.ty(self.mir, bx.tcx());
- self.monomorphize(&op_ty)
- }).collect::<Vec<_>>();
-
- let fn_abi = match def {
- Some(ty::InstanceDef::Virtual(..)) => {
- FnAbi::new_vtable(&bx, sig, &extra_args)
- }
- Some(ty::InstanceDef::DropGlue(_, None)) => {
- // Empty drop glue; a no-op.
- let &(_, target) = destination.as_ref().unwrap();
- helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
- helper.funclet_br(self, &mut bx, target);
- return;
- }
- _ => FnAbi::new(&bx, sig, &extra_args)
- };
-
- // This should never be reachable at runtime:
- // We should only emit a call to this intrinsic in #[cfg(miri)] mode,
- // which means that we will never actually use the generate object files
- // (we will just be interpreting the MIR)
- //
- // Note that we still need to be able to codegen *something* for this intrisnic:
- // Miri currently uses Xargo to build a special libstd. As a side effect,
- // we generate normal object files for libstd - while these are never used,
- // we still need to be able to build them.
+ // For normal codegen, this Miri-specific intrinsic is just a NOP.
if intrinsic == Some("miri_start_panic") {
- bx.abort();
- bx.unreachable();
+ let target = destination.as_ref().unwrap().1;
+ helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
+ helper.funclet_br(self, &mut bx, target);
return;
}
@@ -556,7 +553,7 @@
let def_id =
common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
let instance = ty::Instance::mono(bx.tcx(), def_id);
- let fn_abi = FnAbi::of_instance(&bx, instance);
+ let fn_abi = FnAbi::of_instance(&bx, instance, &[]);
let llfn = bx.get_fn_addr(instance);
if let Some((_, target)) = destination.as_ref() {
@@ -576,7 +573,7 @@
// a NOP
let target = destination.as_ref().unwrap().1;
helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
- helper.funclet_br(self, &mut bx, target);
+ helper.funclet_br(self, &mut bx, target)
}
return;
}
@@ -798,7 +795,8 @@
bb: mir::BasicBlock,
) {
let mut bx = self.build_block(bb);
- let data = &self.mir[bb];
+ let mir = self.mir;
+ let data = &mir[bb];
debug!("codegen_block({:?}={:?})", bb, data);
@@ -813,14 +811,14 @@
&mut self,
mut bx: Bx,
bb: mir::BasicBlock,
- terminator: &mir::Terminator<'tcx>
+ terminator: &'tcx mir::Terminator<'tcx>
) {
debug!("codegen_terminator: {:?}", terminator);
// Create the cleanup bundle, if needed.
let funclet_bb = self.cleanup_kinds[bb].funclet_bb(bb);
let helper = TerminatorCodegenHelper {
- bb: &bb, terminator, funclet_bb
+ bb, terminator, funclet_bb
};
self.set_debug_loc(&mut bx, terminator.source_info);
@@ -831,6 +829,8 @@
mir::TerminatorKind::Abort => {
bx.abort();
+ // `abort` does not terminate the block, so we still need to generate
+ // an `unreachable` terminator after it.
bx.unreachable();
}
@@ -1057,7 +1057,7 @@
fn landing_pad_uncached(
&mut self,
- target_bb: Bx::BasicBlock
+ target_bb: Bx::BasicBlock,
) -> Bx::BasicBlock {
if base::wants_msvc_seh(self.cx.sess()) {
span_bug!(self.mir.span, "landing pad was not inserted?")
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index 6041232..3a157ca 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -1,6 +1,6 @@
use rustc::ty::{self, Ty, TypeFoldable, Instance};
use rustc::ty::layout::{TyLayout, HasTyCtxt, FnAbiExt};
-use rustc::mir::{self, Body};
+use rustc::mir;
use rustc_target::abi::call::{FnAbi, PassMode};
use crate::base;
use crate::traits::*;
@@ -21,7 +21,7 @@
pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
instance: Instance<'tcx>,
- mir: &'a mir::Body<'tcx>,
+ mir: mir::ReadOnlyBodyCache<'tcx, 'tcx>,
debug_context: Option<FunctionDebugContext<Bx::DIScope>>,
@@ -76,7 +76,7 @@
/// All `VarDebuginfo` from the MIR body, partitioned by `Local`.
/// This is `None` if no variable debuginfo/names are needed.
- per_local_var_debug_info: Option<IndexVec<mir::Local, Vec<&'a mir::VarDebugInfo<'tcx>>>>,
+ per_local_var_debug_info: Option<IndexVec<mir::Local, Vec<&'tcx mir::VarDebugInfo<'tcx>>>>,
}
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
@@ -121,18 +121,18 @@
pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
cx: &'a Bx::CodegenCx,
- llfn: Bx::Function,
- mir: &'a Body<'tcx>,
instance: Instance<'tcx>,
- sig: ty::FnSig<'tcx>,
) {
assert!(!instance.substs.needs_infer());
- let fn_abi = FnAbi::new(cx, sig, &[]);
+ let llfn = cx.get_fn(instance);
+
+ let mir = cx.tcx().instance_mir(instance.def);
+
+ let fn_abi = FnAbi::of_instance(cx, instance, &[]);
debug!("fn_abi: {:?}", fn_abi);
- let debug_context =
- cx.create_function_debug_context(instance, sig, llfn, mir);
+ let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir);
let mut bx = Bx::new_block(cx, llfn, "start");
@@ -155,8 +155,8 @@
}
}).collect();
- let (landing_pads, funclets) = create_funclets(mir, &mut bx, &cleanup_kinds, &block_bxs);
-
+ let (landing_pads, funclets) = create_funclets(&mir, &mut bx, &cleanup_kinds, &block_bxs);
+ let mir_body: &mir::Body<'_> = mir.body();
let mut fx = FunctionCx {
instance,
mir,
@@ -171,7 +171,7 @@
funclets,
locals: IndexVec::new(),
debug_context,
- per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir),
+ per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir_body),
};
let memory_locals = analyze::non_ssa_locals(&fx);
@@ -181,7 +181,7 @@
let args = arg_local_refs(&mut bx, &fx, &memory_locals);
let mut allocate_local = |local| {
- let decl = &mir.local_decls[local];
+ let decl = &mir_body.local_decls[local];
let layout = bx.layout_of(fx.monomorphize(&decl.ty));
assert!(!layout.ty.has_erasable_regions());
@@ -207,7 +207,7 @@
let retptr = allocate_local(mir::RETURN_PLACE);
iter::once(retptr)
.chain(args.into_iter())
- .chain(mir.vars_and_temps_iter().map(allocate_local))
+ .chain(mir_body.vars_and_temps_iter().map(allocate_local))
.collect()
};
@@ -226,8 +226,8 @@
debug_context.source_locations_enabled = true;
}
- let rpo = traversal::reverse_postorder(&mir);
- let mut visited = BitSet::new_empty(mir.basic_blocks().len());
+ let rpo = traversal::reverse_postorder(&mir_body);
+ let mut visited = BitSet::new_empty(mir_body.basic_blocks().len());
// Codegen the body of each block using reverse postorder
for (bb, _) in rpo {
@@ -237,7 +237,7 @@
// Remove blocks that haven't been visited, or have no
// predecessors.
- for bb in mir.basic_blocks().indices() {
+ for bb in mir_body.basic_blocks().indices() {
// Unreachable block
if !visited.contains(bb.index()) {
debug!("codegen_mir: block {:?} was not visited", bb);
@@ -249,7 +249,7 @@
}
fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
- mir: &'a Body<'tcx>,
+ mir: &'tcx mir::Body<'tcx>,
bx: &mut Bx,
cleanup_kinds: &IndexVec<mir::BasicBlock, CleanupKind>,
block_bxs: &IndexVec<mir::BasicBlock, Bx::BasicBlock>,
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 310b8ae..a6dec81 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -475,9 +475,10 @@
},
}
// Allow RalfJ to sleep soundly knowing that even refactorings that remove
- // the above error (or silence it under some conditions) will not cause UB
+ // the above error (or silence it under some conditions) will not cause UB.
bx.abort();
- // We've errored, so we don't have to produce working code.
+ // We still have to return an operand but it doesn't matter,
+ // this code is unreachable.
let ty = self.monomorphize(&constant.literal.ty);
let layout = bx.cx().layout_of(ty);
bx.load_operand(PlaceRef::new_sized(
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index 4df5bce..e60b886 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -333,6 +333,9 @@
variant_index: VariantIdx
) {
if self.layout.for_variant(bx.cx(), variant_index).abi.is_uninhabited() {
+ // We play it safe by using a well-defined `abort`, but we could go for immediate UB
+ // if that turns out to be helpful.
+ bx.abort();
return;
}
match self.layout.variants {
@@ -488,10 +491,12 @@
},
Err(_) => {
// This is unreachable as long as runtime
- // and compile-time agree on values
+ // and compile-time agree perfectly.
// With floats that won't always be true,
- // so we generate an abort.
+ // so we generate a (safe) abort.
bx.abort();
+ // We still have to return a place but it doesn't matter,
+ // this code is unreachable.
let llval = bx.cx().const_undef(
bx.cx().type_ptr_to(bx.cx().backend_type(layout))
);
@@ -591,7 +596,12 @@
pub fn monomorphized_place_ty(&self, place_ref: &mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> {
let tcx = self.cx.tcx();
- let place_ty = mir::Place::ty_from(place_ref.base, place_ref.projection, self.mir, tcx);
+ let place_ty = mir::Place::ty_from(
+ place_ref.base,
+ place_ref.projection,
+ *self.mir,
+ tcx,
+ );
self.monomorphize(&place_ty.ty)
}
}
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index f7fb4a5..488ae8d 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -460,7 +460,7 @@
}
mir::Rvalue::Discriminant(ref place) => {
- let discr_ty = rvalue.ty(&*self.mir, bx.tcx());
+ let discr_ty = rvalue.ty(*self.mir, bx.tcx());
let discr = self.codegen_place(&mut bx, &place.as_ref())
.codegen_get_discr(&mut bx, discr_ty);
(bx, OperandRef {
@@ -513,7 +513,7 @@
mir::Rvalue::Aggregate(..) => {
// According to `rvalue_creates_operand`, only ZST
// aggregate rvalues are allowed to be operands.
- let ty = rvalue.ty(self.mir, self.cx.tcx());
+ let ty = rvalue.ty(*self.mir, self.cx.tcx());
let operand = OperandRef::new_zst(
&mut bx,
self.cx.layout_of(self.monomorphize(&ty)),
@@ -710,7 +710,7 @@
true,
mir::Rvalue::Repeat(..) |
mir::Rvalue::Aggregate(..) => {
- let ty = rvalue.ty(self.mir, self.cx.tcx());
+ let ty = rvalue.ty(*self.mir, self.cx.tcx());
let ty = self.monomorphize(&ty);
self.cx.spanned_layout_of(ty, span).is_zst()
}
diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs
index 802eaaa..e67201b 100644
--- a/src/librustc_codegen_ssa/traits/debuginfo.rs
+++ b/src/librustc_codegen_ssa/traits/debuginfo.rs
@@ -2,8 +2,9 @@
use crate::mir::debuginfo::{FunctionDebugContext, VariableKind};
use rustc::hir::def_id::CrateNum;
use rustc::mir;
-use rustc::ty::{self, Ty, Instance};
+use rustc::ty::{Ty, Instance};
use rustc::ty::layout::Size;
+use rustc_target::abi::call::FnAbi;
use syntax::ast::Name;
use syntax_pos::{SourceFile, Span};
@@ -17,7 +18,7 @@
fn create_function_debug_context(
&self,
instance: Instance<'tcx>,
- sig: ty::FnSig<'tcx>,
+ fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
llfn: Self::Function,
mir: &mir::Body<'_>,
) -> Option<FunctionDebugContext<Self::DIScope>>;
diff --git a/src/librustc_codegen_ssa/traits/declare.rs b/src/librustc_codegen_ssa/traits/declare.rs
index cd42044..1dd2c74 100644
--- a/src/librustc_codegen_ssa/traits/declare.rs
+++ b/src/librustc_codegen_ssa/traits/declare.rs
@@ -1,7 +1,8 @@
use super::BackendTypes;
use rustc::hir::def_id::DefId;
use rustc::mir::mono::{Linkage, Visibility};
-use rustc::ty::{self, Instance};
+use rustc::ty::{Instance, Ty};
+use rustc_target::abi::call::FnAbi;
pub trait DeclareMethods<'tcx>: BackendTypes {
/// Declare a global value.
@@ -23,7 +24,7 @@
///
/// If there’s a value with the same name already declared, the function will
/// update the declaration and return existing Value instead.
- fn declare_fn(&self, name: &str, sig: ty::PolyFnSig<'tcx>) -> Self::Function;
+ fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Function;
/// Declare a global with an intention to define it.
///
@@ -38,20 +39,6 @@
/// Use this function when you intend to define a global without a name.
fn define_private_global(&self, ty: Self::Type) -> Self::Value;
- /// Declare a Rust function with an intention to define it.
- ///
- /// Use this function when you intend to define a function. This function will
- /// return panic if the name already has a definition associated with it. This
- /// can happen with #[no_mangle] or #[export_name], for example.
- fn define_fn(&self, name: &str, fn_sig: ty::PolyFnSig<'tcx>) -> Self::Value;
-
- /// Declare a Rust function with an intention to define it.
- ///
- /// Use this function when you intend to define a function. This function will
- /// return panic if the name already has a definition associated with it. This
- /// can happen with #[no_mangle] or #[export_name], for example.
- fn define_internal_fn(&self, name: &str, fn_sig: ty::PolyFnSig<'tcx>) -> Self::Value;
-
/// Gets declared value by name.
fn get_declared_value(&self, name: &str) -> Option<Self::Value>;
diff --git a/src/librustc_data_structures/graph/dominators/mod.rs b/src/librustc_data_structures/graph/dominators/mod.rs
index 444463c..5fb58ee 100644
--- a/src/librustc_data_structures/graph/dominators/mod.rs
+++ b/src/librustc_data_structures/graph/dominators/mod.rs
@@ -7,32 +7,33 @@
use rustc_index::vec::{Idx, IndexVec};
use super::iterate::reverse_post_order;
use super::ControlFlowGraph;
+use std::borrow::BorrowMut;
#[cfg(test)]
mod tests;
-pub fn dominators<G: ControlFlowGraph>(graph: &G) -> Dominators<G::Node> {
+pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
let start_node = graph.start_node();
- let rpo = reverse_post_order(graph, start_node);
+ let rpo = reverse_post_order(&graph, start_node);
dominators_given_rpo(graph, &rpo)
}
-fn dominators_given_rpo<G: ControlFlowGraph>(
- graph: &G,
+fn dominators_given_rpo<G: ControlFlowGraph + BorrowMut<G>>(
+ mut graph: G,
rpo: &[G::Node],
) -> Dominators<G::Node> {
- let start_node = graph.start_node();
+ let start_node = graph.borrow().start_node();
assert_eq!(rpo[0], start_node);
// compute the post order index (rank) for each node
let mut post_order_rank: IndexVec<G::Node, usize> =
- (0..graph.num_nodes()).map(|_| 0).collect();
+ (0..graph.borrow().num_nodes()).map(|_| 0).collect();
for (index, node) in rpo.iter().rev().cloned().enumerate() {
post_order_rank[node] = index;
}
let mut immediate_dominators: IndexVec<G::Node, Option<G::Node>> =
- (0..graph.num_nodes()).map(|_| None).collect();
+ (0..graph.borrow().num_nodes()).map(|_| None).collect();
immediate_dominators[start_node] = Some(start_node);
let mut changed = true;
@@ -41,7 +42,7 @@
for &node in &rpo[1..] {
let mut new_idom = None;
- for pred in graph.predecessors(node) {
+ for pred in graph.borrow_mut().predecessors(node) {
if immediate_dominators[pred].is_some() {
// (*) dominators for `pred` have been calculated
new_idom = Some(if let Some(new_idom) = new_idom {
diff --git a/src/librustc_data_structures/jobserver.rs b/src/librustc_data_structures/jobserver.rs
index b42ccb9..a811c88 100644
--- a/src/librustc_data_structures/jobserver.rs
+++ b/src/librustc_data_structures/jobserver.rs
@@ -1,4 +1,4 @@
-use jobserver_crate::Client;
+pub use jobserver_crate::Client;
use lazy_static::lazy_static;
lazy_static! {
diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs
index 958ab61..8a5badd 100644
--- a/src/librustc_data_structures/obligation_forest/mod.rs
+++ b/src/librustc_data_structures/obligation_forest/mod.rs
@@ -395,7 +395,16 @@
let mut errors = vec![];
let mut stalled = true;
- for index in 0..self.nodes.len() {
+ // Note that the loop body can append new nodes, and those new nodes
+ // will then be processed by subsequent iterations of the loop.
+ //
+ // We can't use an iterator for the loop because `self.nodes` is
+ // appended to and the borrow checker would complain. We also can't use
+ // `for index in 0..self.nodes.len() { ... }` because the range would
+ // be computed with the initial length, and we would miss the appended
+ // nodes. Therefore we use a `while` loop.
+ let mut index = 0;
+ while index < self.nodes.len() {
let node = &mut self.nodes[index];
debug!("process_obligations: node {} == {:?}", index, node);
@@ -406,6 +415,7 @@
// out of sync with `nodes`. It's not very common, but it does
// happen, and code in `compress` has to allow for it.
if node.state.get() != NodeState::Pending {
+ index += 1;
continue;
}
let result = processor.process_obligation(&mut node.obligation);
@@ -441,6 +451,7 @@
});
}
}
+ index += 1;
}
if stalled {
diff --git a/src/librustc_data_structures/obligation_forest/tests.rs b/src/librustc_data_structures/obligation_forest/tests.rs
index 54b6f6d..995c99b 100644
--- a/src/librustc_data_structures/obligation_forest/tests.rs
+++ b/src/librustc_data_structures/obligation_forest/tests.rs
@@ -70,6 +70,7 @@
"A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]),
"B" => ProcessResult::Error("B is for broken"),
"C" => ProcessResult::Changed(vec![]),
+ "A.1" | "A.2" | "A.3" => ProcessResult::Unchanged,
_ => unreachable!(),
}
}, |_| {}), DoCompleted::Yes);
@@ -94,6 +95,7 @@
"A.2" => ProcessResult::Unchanged,
"A.3" => ProcessResult::Changed(vec!["A.3.i"]),
"D" => ProcessResult::Changed(vec!["D.1", "D.2"]),
+ "A.3.i" | "D.1" | "D.2" => ProcessResult::Unchanged,
_ => unreachable!(),
}
}, |_| {}), DoCompleted::Yes);
@@ -113,6 +115,7 @@
"A.3.i" => ProcessResult::Changed(vec![]),
"D.1" => ProcessResult::Changed(vec!["D.1.i"]),
"D.2" => ProcessResult::Changed(vec!["D.2.i"]),
+ "D.1.i" | "D.2.i" => ProcessResult::Unchanged,
_ => unreachable!(),
}
}, |_| {}), DoCompleted::Yes);
@@ -161,18 +164,10 @@
forest.process_obligations(&mut C(|obligation| {
match *obligation {
"A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]),
- _ => unreachable!(),
- }
- }, |_| {}), DoCompleted::Yes);
- assert!(ok.unwrap().is_empty());
- assert!(err.is_empty());
-
- let Outcome { completed: ok, errors: err, .. } =
- forest.process_obligations(&mut C(|obligation| {
- match *obligation {
"A.1" => ProcessResult::Changed(vec![]),
"A.2" => ProcessResult::Changed(vec!["A.2.i", "A.2.ii"]),
"A.3" => ProcessResult::Changed(vec![]),
+ "A.2.i" | "A.2.ii" => ProcessResult::Unchanged,
_ => unreachable!(),
}
}, |_| {}), DoCompleted::Yes);
@@ -184,7 +179,7 @@
let Outcome { completed: ok, errors: err, .. } =
forest.process_obligations(&mut C(|obligation| {
match *obligation {
- "A.2.i" => ProcessResult::Changed(vec!["A.2.i.a"]),
+ "A.2.i" => ProcessResult::Unchanged,
"A.2.ii" => ProcessResult::Changed(vec![]),
_ => unreachable!(),
}
@@ -195,6 +190,17 @@
let Outcome { completed: ok, errors: err, .. } =
forest.process_obligations(&mut C(|obligation| {
match *obligation {
+ "A.2.i" => ProcessResult::Changed(vec!["A.2.i.a"]),
+ "A.2.i.a" => ProcessResult::Unchanged,
+ _ => unreachable!(),
+ }
+ }, |_| {}), DoCompleted::Yes);
+ assert!(ok.unwrap().is_empty());
+ assert!(err.is_empty());
+
+ let Outcome { completed: ok, errors: err, .. } =
+ forest.process_obligations(&mut C(|obligation| {
+ match *obligation {
"A.2.i.a" => ProcessResult::Changed(vec![]),
_ => unreachable!(),
}
@@ -222,6 +228,7 @@
forest.process_obligations(&mut C(|obligation| {
match *obligation {
"A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]),
+ "A.1" | "A.2" | "A.3" => ProcessResult::Unchanged,
_ => unreachable!(),
}
}, |_|{}), DoCompleted::Yes);
@@ -243,6 +250,7 @@
forest.process_obligations(&mut C(|obligation| {
match *obligation {
"A" => ProcessResult::Changed(vec!["A.1", "A.2"]),
+ "A.1" | "A.2" => ProcessResult::Unchanged,
_ => unreachable!(),
}
}, |_|{}), DoCompleted::Yes);
@@ -254,6 +262,7 @@
match *obligation {
"A.1" => ProcessResult::Changed(vec!["D"]),
"A.2" => ProcessResult::Changed(vec!["D"]),
+ "D" => ProcessResult::Unchanged,
_ => unreachable!(),
}
}, |_|{}), DoCompleted::Yes);
@@ -282,6 +291,7 @@
forest.process_obligations(&mut C(|obligation| {
match *obligation {
"A'" => ProcessResult::Changed(vec!["A'.1", "A'.2"]),
+ "A'.1" | "A'.2" => ProcessResult::Unchanged,
_ => unreachable!(),
}
}, |_|{}), DoCompleted::Yes);
@@ -293,6 +303,7 @@
match *obligation {
"A'.1" => ProcessResult::Changed(vec!["D'", "A'"]),
"A'.2" => ProcessResult::Changed(vec!["D'"]),
+ "D'" | "A'" => ProcessResult::Unchanged,
_ => unreachable!(),
}
}, |_|{}), DoCompleted::Yes);
@@ -370,6 +381,7 @@
"B" => ProcessResult::Unchanged,
"C1" => ProcessResult::Changed(vec![]),
"C2" => ProcessResult::Changed(vec![]),
+ "D" | "E" => ProcessResult::Unchanged,
_ => unreachable!(),
}
}, |_|{}), DoCompleted::Yes);
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 93f4e73..0594550 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -828,7 +828,7 @@
fn sort_lints(sess: &Session, mut lints: Vec<&'static Lint>) -> Vec<&'static Lint> {
// The sort doesn't case-fold but it's doubtful we care.
- lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess), x.name));
+ lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess.edition()), x.name));
lints
}
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 7f111b4..9c1bec3 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -18,7 +18,6 @@
E0013: include_str!("./error_codes/E0013.md"),
E0014: include_str!("./error_codes/E0014.md"),
E0015: include_str!("./error_codes/E0015.md"),
-E0017: include_str!("./error_codes/E0017.md"),
E0019: include_str!("./error_codes/E0019.md"),
E0023: include_str!("./error_codes/E0023.md"),
E0025: include_str!("./error_codes/E0025.md"),
@@ -347,6 +346,7 @@
E0623: include_str!("./error_codes/E0623.md"),
E0624: include_str!("./error_codes/E0624.md"),
E0626: include_str!("./error_codes/E0626.md"),
+E0631: include_str!("./error_codes/E0631.md"),
E0633: include_str!("./error_codes/E0633.md"),
E0635: include_str!("./error_codes/E0635.md"),
E0636: include_str!("./error_codes/E0636.md"),
@@ -580,7 +580,6 @@
// rustc_const_unstable attribute must be paired with stable/unstable
// attribute
E0630,
- E0631, // type mismatch in closure arguments
E0632, // cannot provide explicit generic arguments when `impl Trait` is
// used in argument position
E0634, // type has conflicting packed representaton hints
diff --git a/src/librustc_error_codes/error_codes/E0017.md b/src/librustc_error_codes/error_codes/E0017.md
deleted file mode 100644
index d5e6857..0000000
--- a/src/librustc_error_codes/error_codes/E0017.md
+++ /dev/null
@@ -1,20 +0,0 @@
-References in statics and constants may only refer to immutable values.
-
-Erroneous code example:
-
-```compile_fail,E0017
-static X: i32 = 1;
-const C: i32 = 2;
-
-// these three are not allowed:
-const CR: &mut i32 = &mut C;
-static STATIC_REF: &'static mut i32 = &mut X;
-static CONST_REF: &'static mut i32 = &mut C;
-```
-
-Statics are shared everywhere, and if they refer to mutable data one might
-violate memory safety since holding multiple mutable references to shared data
-is not allowed.
-
-If you really want global mutable state, try using `static mut` or a global
-`UnsafeCell`.
diff --git a/src/librustc_error_codes/error_codes/E0092.md b/src/librustc_error_codes/error_codes/E0092.md
index 2750a7d..e289534 100644
--- a/src/librustc_error_codes/error_codes/E0092.md
+++ b/src/librustc_error_codes/error_codes/E0092.md
@@ -1,4 +1,5 @@
-You tried to declare an undefined atomic operation function.
+An undefined atomic operation function was declared.
+
Erroneous code example:
```compile_fail,E0092
@@ -11,8 +12,8 @@
```
Please check you didn't make a mistake in the function's name. All intrinsic
-functions are defined in librustc_codegen_llvm/intrinsic.rs and in
-libcore/intrinsics.rs in the Rust source code. Example:
+functions are defined in `librustc_codegen_llvm/intrinsic.rs` and in
+`libcore/intrinsics.rs` in the Rust source code. Example:
```
#![feature(intrinsics)]
diff --git a/src/librustc_error_codes/error_codes/E0093.md b/src/librustc_error_codes/error_codes/E0093.md
index 9633f79..8e7de1a 100644
--- a/src/librustc_error_codes/error_codes/E0093.md
+++ b/src/librustc_error_codes/error_codes/E0093.md
@@ -1,4 +1,6 @@
-You declared an unknown intrinsic function. Erroneous code example:
+An unknown intrinsic function was declared.
+
+Erroneous code example:
```compile_fail,E0093
#![feature(intrinsics)]
@@ -15,8 +17,8 @@
```
Please check you didn't make a mistake in the function's name. All intrinsic
-functions are defined in librustc_codegen_llvm/intrinsic.rs and in
-libcore/intrinsics.rs in the Rust source code. Example:
+functions are defined in `librustc_codegen_llvm/intrinsic.rs` and in
+`libcore/intrinsics.rs` in the Rust source code. Example:
```
#![feature(intrinsics)]
diff --git a/src/librustc_error_codes/error_codes/E0094.md b/src/librustc_error_codes/error_codes/E0094.md
index 4d27f61..42baa65 100644
--- a/src/librustc_error_codes/error_codes/E0094.md
+++ b/src/librustc_error_codes/error_codes/E0094.md
@@ -1,4 +1,5 @@
-You gave an invalid number of type parameters to an intrinsic function.
+An invalid number of type parameters was given to an intrinsic function.
+
Erroneous code example:
```compile_fail,E0094
diff --git a/src/librustc_error_codes/error_codes/E0106.md b/src/librustc_error_codes/error_codes/E0106.md
index 8a49c1f..60ca1dd 100644
--- a/src/librustc_error_codes/error_codes/E0106.md
+++ b/src/librustc_error_codes/error_codes/E0106.md
@@ -2,7 +2,7 @@
inside a function signature, the problem may be with failing to adhere to the
lifetime elision rules (see below).
-Here are some simple examples of where you'll run into this error:
+Erroneous code examples:
```compile_fail,E0106
struct Foo1 { x: &bool }
@@ -27,7 +27,7 @@
For more background on lifetime elision see [the book][book-le].
The lifetime elision rules require that any function signature with an elided
-output lifetime must either have
+output lifetime must either have:
- exactly one input lifetime
- or, multiple input lifetimes, but the function must also be a method with a
diff --git a/src/librustc_error_codes/error_codes/E0107.md b/src/librustc_error_codes/error_codes/E0107.md
index bfe0d21..4d22b17 100644
--- a/src/librustc_error_codes/error_codes/E0107.md
+++ b/src/librustc_error_codes/error_codes/E0107.md
@@ -1,4 +1,6 @@
-This error means that an incorrect number of generic arguments were provided:
+An incorrect number of generic arguments were provided.
+
+Erroneous code example:
```compile_fail,E0107
struct Foo<T> { x: T }
@@ -9,6 +11,7 @@
// expected 1, found 2
fn foo<T, U>(x: T, y: U) {}
+fn f() {}
fn main() {
let x: bool = true;
@@ -16,12 +19,26 @@
// expected 2, found 1
foo::<bool, i32, i32>(x, 2, 4); // error: wrong number of type arguments:
// expected 2, found 3
+ f::<'static>(); // error: wrong number of lifetime arguments
+ // expected 0, found 1
}
+```
+When using/declaring an item with generic arguments, you must provide the exact
+same number:
+
+```
+struct Foo<T> { x: T }
+
+struct Bar<T> { x: Foo<T> } // ok!
+struct Baz<S, T> { x: Foo<S>, y: Foo<T> } // ok!
+
+fn foo<T, U>(x: T, y: U) {}
fn f() {}
fn main() {
- f::<'static>(); // error: wrong number of lifetime arguments:
- // expected 0, found 1
+ let x: bool = true;
+ foo::<bool, u32>(x, 12); // ok!
+ f(); // ok!
}
```
diff --git a/src/librustc_error_codes/error_codes/E0109.md b/src/librustc_error_codes/error_codes/E0109.md
index 5bc229a..2eab972 100644
--- a/src/librustc_error_codes/error_codes/E0109.md
+++ b/src/librustc_error_codes/error_codes/E0109.md
@@ -1,4 +1,5 @@
You tried to provide a generic argument to a type which doesn't need it.
+
Erroneous code example:
```compile_fail,E0109
diff --git a/src/librustc_error_codes/error_codes/E0116.md b/src/librustc_error_codes/error_codes/E0116.md
index 27759a4..ca849c2 100644
--- a/src/librustc_error_codes/error_codes/E0116.md
+++ b/src/librustc_error_codes/error_codes/E0116.md
@@ -1,11 +1,15 @@
-You can only define an inherent implementation for a type in the same crate
-where the type was defined. For example, an `impl` block as below is not allowed
-since `Vec` is defined in the standard library:
+An inherent implementation was defined for a type outside the current crate.
+
+Erroneous code example:
```compile_fail,E0116
impl Vec<u8> { } // error
```
+You can only define an inherent implementation for a type in the same crate
+where the type was defined. For example, an `impl` block as above is not allowed
+since `Vec` is defined in the standard library.
+
To fix this problem, you can do either of these things:
- define a trait that has the desired associated functions/types/constants and
diff --git a/src/librustc_error_codes/error_codes/E0117.md b/src/librustc_error_codes/error_codes/E0117.md
index bd36230..7fa211d 100644
--- a/src/librustc_error_codes/error_codes/E0117.md
+++ b/src/librustc_error_codes/error_codes/E0117.md
@@ -1,3 +1,11 @@
+The `Drop` trait was implemented on a non-struct type.
+
+Erroneous code example:
+
+```compile_fail,E0117
+impl Drop for u32 {}
+```
+
This error indicates a violation of one of Rust's orphan rules for trait
implementations. The rule prohibits any implementation of a foreign trait (a
trait defined in another crate) where
@@ -6,12 +14,6 @@
- all of the parameters being passed to the trait (if there are any) are also
foreign.
-Here's one example of this error:
-
-```compile_fail,E0117
-impl Drop for u32 {}
-```
-
To avoid this kind of error, ensure that at least one local type is referenced
by the `impl`:
diff --git a/src/librustc_error_codes/error_codes/E0118.md b/src/librustc_error_codes/error_codes/E0118.md
index baf35ff..5cb5f50 100644
--- a/src/librustc_error_codes/error_codes/E0118.md
+++ b/src/librustc_error_codes/error_codes/E0118.md
@@ -1,5 +1,7 @@
-You're trying to write an inherent implementation for something which isn't a
-struct nor an enum. Erroneous code example:
+An inherent implementation was defined for something which isn't a struct nor
+an enum.
+
+Erroneous code example:
```compile_fail,E0118
impl (u8, u8) { // error: no base type found for inherent implementation
diff --git a/src/librustc_error_codes/error_codes/E0119.md b/src/librustc_error_codes/error_codes/E0119.md
index 0af3bd4..e596349 100644
--- a/src/librustc_error_codes/error_codes/E0119.md
+++ b/src/librustc_error_codes/error_codes/E0119.md
@@ -1,5 +1,6 @@
There are conflicting trait implementations for the same type.
-Example of erroneous code:
+
+Erroneous code example:
```compile_fail,E0119
trait MyTrait {
diff --git a/src/librustc_error_codes/error_codes/E0631.md b/src/librustc_error_codes/error_codes/E0631.md
new file mode 100644
index 0000000..6188d5f
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0631.md
@@ -0,0 +1,27 @@
+This error indicates a type mismatch in closure arguments.
+
+Erroneous code example:
+
+```compile_fail,E0631
+fn foo<F: Fn(i32)>(f: F) {
+}
+
+fn main() {
+ foo(|x: &str| {});
+}
+```
+
+The error occurs because `foo` accepts a closure that takes an `i32` argument,
+but in `main`, it is passed a closure with a `&str` argument.
+
+This can be resolved by changing the type annotation or removing it entirely
+if it can be inferred.
+
+```
+fn foo<F: Fn(i32)>(f: F) {
+}
+
+fn main() {
+ foo(|x: i32| {});
+}
+```
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 7c0d399..b1ae7c6 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -408,10 +408,6 @@
/// Allows using `#[doc(keyword = "...")]`.
(active, doc_keyword, "1.28.0", Some(51315), None),
- /// Allows reinterpretation of the bits of a value of one type as another
- /// type during const eval.
- (active, const_transmute, "1.29.0", Some(53605), None),
-
/// Allows using `try {...}` expressions.
(active, try_blocks, "1.29.0", Some(31436), None),
@@ -524,6 +520,12 @@
/// Allows the use of `if` and `match` in constants.
(active, const_if_match, "1.41.0", Some(49146), None),
+ /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
+ (active, cfg_sanitize, "1.41.0", Some(39699), None),
+
+ /// Allows using `&mut` in constant functions.
+ (active, const_mut_refs, "1.41.0", Some(57349), None),
+
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs
index f72df00..4fa0198 100644
--- a/src/librustc_feature/builtin_attrs.rs
+++ b/src/librustc_feature/builtin_attrs.rs
@@ -25,6 +25,7 @@
(sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)),
(sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
(sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
+ (sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)),
];
/// Find a gated cfg determined by the `pred`icate which is given the cfg's name.
@@ -283,7 +284,7 @@
)
),
(
- sym::plugin, CrateLevel, template!(List: "name|name(args)"),
+ sym::plugin, CrateLevel, template!(List: "name"),
Gated(
Stability::Deprecated(
"https://github.com/rust-lang/rust/pull/64675",
diff --git a/src/librustc_incremental/Cargo.toml b/src/librustc_incremental/Cargo.toml
index 659c4c8..8dac726 100644
--- a/src/librustc_incremental/Cargo.toml
+++ b/src/librustc_incremental/Cargo.toml
@@ -19,3 +19,4 @@
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
rustc_fs_util = { path = "../librustc_fs_util" }
+rustc_session = { path = "../librustc_session" }
diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
index 483b515..c2e3fa8 100644
--- a/src/librustc_incremental/assert_module_sources.rs
+++ b/src/librustc_incremental/assert_module_sources.rs
@@ -22,7 +22,7 @@
//! was re-used.
use rustc::hir::def_id::LOCAL_CRATE;
-use rustc::dep_graph::cgu_reuse_tracker::*;
+use rustc_session::cgu_reuse_tracker::*;
use rustc::mir::mono::CodegenUnitNameBuilder;
use rustc::ty::TyCtxt;
use std::collections::BTreeSet;
diff --git a/src/librustc_interface/lib.rs b/src/librustc_interface/lib.rs
index 76af434..9bb1878 100644
--- a/src/librustc_interface/lib.rs
+++ b/src/librustc_interface/lib.rs
@@ -1,3 +1,4 @@
+#![feature(bool_to_option)]
#![feature(box_syntax)]
#![feature(set_stdio)]
#![feature(nll)]
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index e953a64f..2a4bc41 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -30,7 +30,6 @@
use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str};
use rustc_passes::{self, ast_validation, hir_stats, layout_test};
use rustc_plugin_impl as plugin;
-use rustc_plugin_impl::registry::Registry;
use rustc_privacy;
use rustc_resolve::{Resolver, ResolverArenas};
use rustc_traits;
@@ -106,8 +105,7 @@
(&mut Resolver<'_>) -> (Result<ast::Crate>, ResolverOutputs)
);
-/// Runs the "early phases" of the compiler: initial `cfg` processing,
-/// loading compiler plugins (including those from `addl_plugins`),
+/// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins,
/// syntax expansion, secondary `cfg` expansion, synthesis of a test
/// harness if one is to be provided, injection of a dependency on the
/// standard library and prelude, and name resolution.
@@ -209,33 +207,22 @@
middle::recursion_limit::update_limits(sess, &krate);
});
- let registrars = time(sess, "plugin loading", || {
- plugin::load::load_plugins(
- sess,
- metadata_loader,
- &krate,
- Some(sess.opts.debugging_opts.extra_plugins.clone()),
- )
- });
-
let mut lint_store = rustc_lint::new_lint_store(
sess.opts.debugging_opts.no_interleave_lints,
sess.unstable_options(),
);
+ register_lints(&sess, &mut lint_store);
- (register_lints)(&sess, &mut lint_store);
-
- let mut registry = Registry::new(sess, &mut lint_store, krate.span);
-
+ let registrars = time(sess, "plugin loading", || {
+ plugin::load::load_plugins(sess, metadata_loader, &krate)
+ });
time(sess, "plugin registration", || {
+ let mut registry = plugin::Registry { lint_store: &mut lint_store };
for registrar in registrars {
- registry.args_hidden = Some(registrar.args);
- (registrar.fun)(&mut registry);
+ registrar(&mut registry);
}
});
- *sess.plugin_llvm_passes.borrow_mut() = registry.llvm_passes;
-
Ok((krate, Lrc::new(lint_store)))
}
@@ -452,8 +439,7 @@
sess.parse_sess.buffered_lints.with_lock(|buffered_lints| {
info!("{} parse sess buffered_lints", buffered_lints.len());
for BufferedEarlyLint{id, span, msg, lint_id} in buffered_lints.drain(..) {
- let lint = lint::Lint::from_parser_lint_id(lint_id);
- resolver.lint_buffer().buffer_lint(lint, id, span, &msg);
+ resolver.lint_buffer().buffer_lint(lint_id, id, span, &msg);
}
});
@@ -561,13 +547,7 @@
}
fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option<PathBuf> {
- let check = |output_path: &PathBuf| {
- if output_path.is_dir() {
- Some(output_path.clone())
- } else {
- None
- }
- };
+ let check = |output_path: &PathBuf| output_path.is_dir().then(|| output_path.clone());
check_output(output_paths, check)
}
diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs
index 6103d42..e429b4d 100644
--- a/src/librustc_interface/queries.rs
+++ b/src/librustc_interface/queries.rs
@@ -22,7 +22,7 @@
use syntax::{self, ast};
/// Represent the result of a query.
-/// This result can be stolen with the `take` method and returned with the `give` method.
+/// This result can be stolen with the `take` method and generated with the `compute` method.
pub struct Query<T> {
result: RefCell<Option<Result<T>>>,
}
@@ -37,7 +37,7 @@
}
/// Takes ownership of the query result. Further attempts to take or peek the query
- /// result will panic unless it is returned by calling the `give` method.
+ /// result will panic unless it is generated by calling the `compute` method.
pub fn take(&self) -> T {
self.result
.borrow_mut()
@@ -117,11 +117,9 @@
pub fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> {
self.dep_graph_future.compute(|| {
- Ok(if self.session().opts.build_dep_graph() {
- Some(rustc_incremental::load_dep_graph(self.session()))
- } else {
- None
- })
+ Ok(self.session().opts.build_dep_graph().then(|| {
+ rustc_incremental::load_dep_graph(self.session())
+ }))
})
}
diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs
index d39a5d3..4c630b5 100644
--- a/src/librustc_interface/tests.rs
+++ b/src/librustc_interface/tests.rs
@@ -651,10 +651,6 @@
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
- opts.debugging_opts.extra_plugins = vec![String::from("plugin1"), String::from("plugin2")];
- assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
-
- opts = reference.clone();
opts.debugging_opts.force_overflow_checks = Some(true);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index d8e20e1..8c225b8 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -107,11 +107,7 @@
fn get_stack_size() -> Option<usize> {
// FIXME: Hacks on hacks. If the env is trying to override the stack size
// then *don't* set it explicitly.
- if env::var_os("RUST_MIN_STACK").is_none() {
- Some(STACK_SIZE)
- } else {
- None
- }
+ env::var_os("RUST_MIN_STACK").is_none().then_some(STACK_SIZE)
}
struct Sink(Arc<Mutex<Vec<u8>>>);
@@ -285,11 +281,7 @@
} else {
"rustc"
});
- if candidate.exists() {
- Some(candidate)
- } else {
- None
- }
+ candidate.exists().then_some(candidate)
})
.next()
}
diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml
index ed38243..e834b87 100644
--- a/src/librustc_lint/Cargo.toml
+++ b/src/librustc_lint/Cargo.toml
@@ -18,3 +18,4 @@
rustc_feature = { path = "../librustc_feature" }
rustc_index = { path = "../librustc_index" }
rustc_error_codes = { path = "../librustc_error_codes" }
+rustc_session = { path = "../librustc_session" }
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 5d3a6cc..10b00d3 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -24,7 +24,7 @@
use std::fmt::Write;
use rustc::hir::def::{Res, DefKind};
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::hir::def_id::DefId;
use rustc::ty::{self, Ty, TyCtxt, layout::VariantIdx};
use rustc::{lint, util};
use rustc::lint::FutureIncompatibleInfo;
@@ -801,45 +801,6 @@
}
declare_lint! {
- PLUGIN_AS_LIBRARY,
- Warn,
- "compiler plugin used as ordinary library in non-plugin crate"
-}
-
-declare_lint_pass!(PluginAsLibrary => [PLUGIN_AS_LIBRARY]);
-
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PluginAsLibrary {
- fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
- if cx.tcx.plugin_registrar_fn(LOCAL_CRATE).is_some() {
- // We're compiling a plugin; it's fine to link other plugins.
- return;
- }
-
- match it.kind {
- hir::ItemKind::ExternCrate(..) => (),
- _ => return,
- };
-
- let def_id = cx.tcx.hir().local_def_id(it.hir_id);
- let prfn = match cx.tcx.extern_mod_stmt_cnum(def_id) {
- Some(cnum) => cx.tcx.plugin_registrar_fn(cnum),
- None => {
- // Probably means we aren't linking the crate for some reason.
- //
- // Not sure if / when this could happen.
- return;
- }
- };
-
- if prfn.is_some() {
- cx.span_lint(PLUGIN_AS_LIBRARY,
- it.span,
- "compiler plugin used as an ordinary library");
- }
- }
-}
-
-declare_lint! {
NO_MANGLE_CONST_ITEMS,
Deny,
"const items will not have their symbols exported"
@@ -1268,7 +1229,6 @@
MISSING_DEBUG_IMPLEMENTATIONS,
ANONYMOUS_PARAMETERS,
UNUSED_DOC_COMMENTS,
- PLUGIN_AS_LIBRARY,
NO_MANGLE_CONST_ITEMS,
NO_MANGLE_GENERIC_ITEMS,
MUTABLE_TRANSMUTES,
@@ -1490,10 +1450,10 @@
impl EarlyLintPass for KeywordIdents {
fn check_mac_def(&mut self, cx: &EarlyContext<'_>, mac_def: &ast::MacroDef, _id: ast::NodeId) {
- self.check_tokens(cx, mac_def.stream());
+ self.check_tokens(cx, mac_def.body.inner_tokens());
}
fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) {
- self.check_tokens(cx, mac.tts.clone().into());
+ self.check_tokens(cx, mac.args.inner_tokens());
}
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: ast::Ident) {
self.check_ident_token(cx, UnderMacro(false), ident);
@@ -1531,11 +1491,7 @@
match pred {
ty::Predicate::TypeOutlives(outlives) => {
let outlives = outlives.skip_binder();
- if outlives.0.is_param(index) {
- Some(outlives.1)
- } else {
- None
- }
+ outlives.0.is_param(index).then_some(outlives.1)
}
_ => None
}
@@ -1594,11 +1550,7 @@
}),
_ => false,
};
- if is_inferred {
- Some((i, bound.span()))
- } else {
- None
- }
+ is_inferred.then_some((i, bound.span()))
} else {
None
}
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 7e8dc1d..12aab4b 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -12,6 +12,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![cfg_attr(test, feature(test))]
+#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(nll)]
@@ -21,6 +22,8 @@
#[macro_use]
extern crate rustc;
+#[macro_use]
+extern crate rustc_session;
mod array_into_iter;
mod nonstandard_style;
@@ -157,8 +160,6 @@
// Depends on types used in type definitions
MissingCopyImplementations: MissingCopyImplementations,
- PluginAsLibrary: PluginAsLibrary,
-
// Depends on referenced function signatures in expressions
MutableTransmutes: MutableTransmutes,
@@ -350,6 +351,7 @@
"converted into hard error, see https://github.com/rust-lang/rust/issues/35896");
store.register_removed("nested_impl_trait",
"converted into hard error, see https://github.com/rust-lang/rust/issues/59014");
+ store.register_removed("plugin_as_library", "plugins have been deprecated and retired");
}
fn register_internals(store: &mut lint::LintStore) {
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index dbf2dcf..25bd2c4 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -802,11 +802,8 @@
// First up we check for global allocators. Look at the crate graph here
// and see what's a global allocator, including if we ourselves are a
// global allocator.
- let mut global_allocator = if self.cstore.has_global_allocator {
- Some(Symbol::intern("this crate"))
- } else {
- None
- };
+ let mut global_allocator = self.cstore.has_global_allocator
+ .then(|| Symbol::intern("this crate"));
self.cstore.iter_crate_data(|_, data| {
if !data.has_global_allocator() {
return
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 8c0b734..aaaff7e 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -1,5 +1,6 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(core_intrinsics)]
#![feature(crate_visibility_modifier)]
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index 820783b..6edd17f 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -18,12 +18,11 @@
use rustc_data_structures::svh::Svh;
use rustc::dep_graph::{self, DepNodeIndex};
use rustc::middle::lang_items;
-use rustc::mir::{self, interpret};
+use rustc::mir::{self, BodyCache, interpret, Promoted};
use rustc::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc::session::Session;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::codec::TyDecoder;
-use rustc::mir::{Body, Promoted};
use rustc::util::common::record_time;
use rustc::util::captures::Captures;
@@ -1080,26 +1079,32 @@
self.root.per_def.mir.get(self, id).is_some()
}
- fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
- self.root.per_def.mir.get(self, id)
+ fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> BodyCache<'tcx> {
+ let mut cache = self.root.per_def.mir.get(self, id)
.filter(|_| !self.is_proc_macro(id))
.unwrap_or_else(|| {
bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id))
})
- .decode((self, tcx))
+ .decode((self, tcx));
+ cache.ensure_predecessors();
+ cache
}
fn get_promoted_mir(
&self,
tcx: TyCtxt<'tcx>,
id: DefIndex,
- ) -> IndexVec<Promoted, Body<'tcx>> {
- self.root.per_def.promoted_mir.get(self, id)
+ ) -> IndexVec<Promoted, BodyCache<'tcx>> {
+ let mut cache = self.root.per_def.promoted_mir.get(self, id)
.filter(|_| !self.is_proc_macro(id))
.unwrap_or_else(|| {
bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id))
})
- .decode((self, tcx))
+ .decode((self, tcx));
+ for body in cache.iter_mut() {
+ body.ensure_predecessors();
+ }
+ cache
}
fn mir_const_qualif(&self, id: DefIndex) -> mir::ConstQualifs {
@@ -1355,10 +1360,16 @@
}
}
+ // This replicates some of the logic of the crate-local `is_const_fn_raw` query, because we
+ // don't serialize constness for tuple variant and tuple struct constructors.
fn is_const_fn_raw(&self, id: DefIndex) -> bool {
let constness = match self.kind(id) {
EntryKind::Method(data) => data.decode(self).fn_data.constness,
EntryKind::Fn(data) => data.decode(self).constness,
+ // Some intrinsics can be const fn. While we could recompute this (at least until we
+ // stop having hardcoded whitelists and move to stability attributes), it seems cleaner
+ // to treat all const fns equally.
+ EntryKind::ForeignFn(data) => data.decode(self).constness,
EntryKind::Variant(..) | EntryKind::Struct(..) => hir::Constness::Const,
_ => hir::Constness::NotConst,
};
diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
index 8214153..13db9a6 100644
--- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
+++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
@@ -32,6 +32,8 @@
use syntax::source_map::Spanned;
use syntax::symbol::Symbol;
use syntax::expand::allocator::AllocatorKind;
+use syntax::ptr::P;
+use syntax::tokenstream::DelimSpan;
use syntax_pos::{Span, FileName};
macro_rules! provide {
@@ -427,6 +429,7 @@
let source_file = sess.parse_sess.source_map().new_source_file(source_name, def.body);
let local_span = Span::with_root_ctxt(source_file.start_pos, source_file.end_pos);
+ let dspan = DelimSpan::from_single(local_span);
let (body, mut errors) = source_file_to_stream(&sess.parse_sess, source_file, None);
emit_unclosed_delims(&mut errors, &sess.parse_sess);
@@ -448,7 +451,7 @@
span: local_span,
attrs: attrs.iter().cloned().collect(),
kind: ast::ItemKind::MacroDef(ast::MacroDef {
- tokens: body.into(),
+ body: P(ast::MacArgs::Delimited(dspan, ast::MacDelimiter::Brace, body)),
legacy: def.legacy,
}),
vis: source_map::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited),
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index 3a318dd..fb70e10 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -1525,7 +1525,11 @@
hir::ForeignItemKind::Fn(_, ref names, _) => {
let data = FnData {
asyncness: hir::IsAsync::NotAsync,
- constness: hir::Constness::NotConst,
+ constness: if self.tcx.is_const_fn_raw(def_id) {
+ hir::Constness::Const
+ } else {
+ hir::Constness::NotConst
+ },
param_names: self.encode_fn_param_names(names),
};
EntryKind::ForeignFn(self.lazy(data))
diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs
index 4ea562f..fdf43f0 100644
--- a/src/librustc_metadata/rmeta/mod.rs
+++ b/src/librustc_metadata/rmeta/mod.rs
@@ -276,8 +276,8 @@
// Also, as an optimization, a missing entry indicates an empty `&[]`.
inferred_outlives: Table<DefIndex, Lazy!(&'tcx [(ty::Predicate<'tcx>, Span)])>,
super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
- mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
- promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
+ mir: Table<DefIndex, Lazy!(mir::BodyCache<'tcx>)>,
+ promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::BodyCache<'tcx>>)>,
}
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs
index 9432343..802464c 100644
--- a/src/librustc_mir/borrow_check/borrow_set.rs
+++ b/src/librustc_mir/borrow_check/borrow_set.rs
@@ -5,7 +5,7 @@
use crate::dataflow::move_paths::MoveData;
use rustc::mir::traversal;
use rustc::mir::visit::{PlaceContext, Visitor, NonUseContext, MutatingUseContext};
-use rustc::mir::{self, Location, Body, Local};
+use rustc::mir::{self, Location, Body, Local, ReadOnlyBodyCache};
use rustc::ty::{RegionVid, TyCtxt};
use rustc::util::nodemap::{FxHashMap, FxHashSet};
use rustc_index::vec::IndexVec;
@@ -90,7 +90,7 @@
impl LocalsStateAtExit {
fn build(
locals_are_invalidated_at_exit: bool,
- body: &Body<'tcx>,
+ body: ReadOnlyBodyCache<'_, 'tcx>,
move_data: &MoveData<'tcx>
) -> Self {
struct HasStorageDead(BitSet<Local>);
@@ -106,7 +106,8 @@
if locals_are_invalidated_at_exit {
LocalsStateAtExit::AllAreInvalidated
} else {
- let mut has_storage_dead = HasStorageDead(BitSet::new_empty(body.local_decls.len()));
+ let mut has_storage_dead
+ = HasStorageDead(BitSet::new_empty(body.local_decls.len()));
has_storage_dead.visit_body(body);
let mut has_storage_dead_or_moved = has_storage_dead.0;
for move_out in &move_data.moves {
@@ -123,13 +124,13 @@
impl<'tcx> BorrowSet<'tcx> {
pub fn build(
tcx: TyCtxt<'tcx>,
- body: &Body<'tcx>,
+ body: ReadOnlyBodyCache<'_, 'tcx>,
locals_are_invalidated_at_exit: bool,
move_data: &MoveData<'tcx>,
) -> Self {
let mut visitor = GatherBorrows {
tcx,
- body,
+ body: &body,
idx_vec: IndexVec::new(),
location_map: Default::default(),
activation_map: Default::default(),
@@ -139,7 +140,7 @@
LocalsStateAtExit::build(locals_are_invalidated_at_exit, body, move_data),
};
- for (block, block_data) in traversal::preorder(body) {
+ for (block, block_data) in traversal::preorder(&body) {
visitor.visit_basic_block_data(block, block_data);
}
diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
similarity index 96%
rename from src/librustc_mir/borrow_check/conflict_errors.rs
rename to src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
index 48f8ad9..d14957b 100644
--- a/src/librustc_mir/borrow_check/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
@@ -14,18 +14,22 @@
use syntax_pos::Span;
use syntax::source_map::DesugaringKind;
-use super::nll::explain_borrow::BorrowExplanation;
-use super::nll::region_infer::{RegionName, RegionNameSource};
-use super::prefixes::IsPrefixOf;
-use super::WriteKind;
-use super::borrow_set::BorrowData;
-use super::MirBorrowckCtxt;
-use super::{InitializationRequiringAction, PrefixSet};
-use super::error_reporting::{IncludingDowncast, UseSpans};
use crate::dataflow::drop_flag_effects;
use crate::dataflow::indexes::{MovePathIndex, MoveOutIndex};
use crate::util::borrowck_errors;
+use crate::borrow_check::{
+ prefixes::IsPrefixOf,
+ WriteKind,
+ borrow_set::BorrowData,
+ MirBorrowckCtxt, InitializationRequiringAction, PrefixSet
+};
+
+use super::{
+ IncludingDowncast, UseSpans, RegionName, RegionNameSource,
+ explain_borrow::BorrowExplanation,
+};
+
#[derive(Debug)]
struct MoveSite {
/// Index of the "move out" that we found. The `MoveData` can
@@ -46,7 +50,7 @@
}
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
- pub(super) fn report_use_of_moved_or_uninitialized(
+ pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
&mut self,
location: Location,
desired_action: InitializationRequiringAction,
@@ -205,9 +209,12 @@
);
}
- let ty =
- Place::ty_from(used_place.base, used_place.projection, self.body, self.infcx.tcx)
- .ty;
+ let ty = Place::ty_from(
+ used_place.base,
+ used_place.projection,
+ *self.body,
+ self.infcx.tcx
+ ).ty;
let needs_note = match ty.kind {
ty::Closure(id, _) => {
let tables = self.infcx.tcx.typeck_tables_of(id);
@@ -222,7 +229,7 @@
let mpi = self.move_data.moves[move_out_indices[0]].path;
let place = &self.move_data.move_paths[mpi].place;
- let ty = place.ty(self.body, self.infcx.tcx).ty;
+ let ty = place.ty(*self.body, self.infcx.tcx).ty;
let opt_name =
self.describe_place_with_options(place.as_ref(), IncludingDowncast(true));
let note_msg = match opt_name {
@@ -266,7 +273,7 @@
}
}
- pub(super) fn report_move_out_while_borrowed(
+ pub(in crate::borrow_check) fn report_move_out_while_borrowed(
&mut self,
location: Location,
(place, span): (&Place<'tcx>, Span),
@@ -314,7 +321,7 @@
None,
).add_explanation_to_diagnostic(
self.infcx.tcx,
- self.body,
+ &self.body,
&self.local_names,
&mut err,
"",
@@ -323,7 +330,7 @@
err.buffer(&mut self.errors_buffer);
}
- pub(super) fn report_use_while_mutably_borrowed(
+ pub(in crate::borrow_check) fn report_use_while_mutably_borrowed(
&mut self,
location: Location,
(place, _span): (&Place<'tcx>, Span),
@@ -356,7 +363,7 @@
self.explain_why_borrow_contains_point(location, borrow, None)
.add_explanation_to_diagnostic(
self.infcx.tcx,
- self.body,
+ &self.body,
&self.local_names,
&mut err,
"",
@@ -365,7 +372,7 @@
err
}
- pub(super) fn report_conflicting_borrow(
+ pub(in crate::borrow_check) fn report_conflicting_borrow(
&mut self,
location: Location,
(place, span): (&Place<'tcx>, Span),
@@ -578,7 +585,7 @@
explanation.add_explanation_to_diagnostic(
self.infcx.tcx,
- self.body,
+ &self.body,
&self.local_names,
&mut err,
first_borrow_desc,
@@ -611,7 +618,7 @@
///
/// > cannot borrow `a.u` (via `a.u.z.c`) as immutable because it is also borrowed as
/// > mutable (via `a.u.s.b`) [E0502]
- pub(super) fn describe_place_for_conflicting_borrow(
+ pub(in crate::borrow_check) fn describe_place_for_conflicting_borrow(
&self,
first_borrowed_place: &Place<'tcx>,
second_borrowed_place: &Place<'tcx>,
@@ -619,7 +626,12 @@
// Define a small closure that we can use to check if the type of a place
// is a union.
let union_ty = |place_base, place_projection| {
- let ty = Place::ty_from(place_base, place_projection, self.body, self.infcx.tcx).ty;
+ let ty = Place::ty_from(
+ place_base,
+ place_projection,
+ *self.body,
+ self.infcx.tcx
+ ).ty;
ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty)
};
let describe_place = |place| self.describe_place(place).unwrap_or_else(|| "_".to_owned());
@@ -714,7 +726,7 @@
/// short a lifetime. (But sometimes it is more useful to report
/// it as a more direct conflict between the execution of a
/// `Drop::drop` with an aliasing borrow.)
- pub(super) fn report_borrowed_value_does_not_live_long_enough(
+ pub(in crate::borrow_check) fn report_borrowed_value_does_not_live_long_enough(
&mut self,
location: Location,
borrow: &BorrowData<'tcx>,
@@ -965,7 +977,7 @@
} else {
explanation.add_explanation_to_diagnostic(
self.infcx.tcx,
- self.body,
+ &self.body,
&self.local_names,
&mut err,
"",
@@ -991,7 +1003,7 @@
);
explanation.add_explanation_to_diagnostic(
- self.infcx.tcx, self.body, &self.local_names, &mut err, "", None);
+ self.infcx.tcx, &self.body, &self.local_names, &mut err, "", None);
}
err
@@ -1051,7 +1063,7 @@
explanation.add_explanation_to_diagnostic(
self.infcx.tcx,
- self.body,
+ &self.body,
&self.local_names,
&mut err,
"",
@@ -1138,7 +1150,7 @@
}
explanation.add_explanation_to_diagnostic(
self.infcx.tcx,
- self.body,
+ &self.body,
&self.local_names,
&mut err,
"",
@@ -1174,11 +1186,12 @@
};
// FIXME use a better heuristic than Spans
- let reference_desc = if return_span == self.body.source_info(borrow.reserve_location).span {
- "reference to"
- } else {
- "value referencing"
- };
+ let reference_desc
+ = if return_span == self.body.source_info(borrow.reserve_location).span {
+ "reference to"
+ } else {
+ "value referencing"
+ };
let (place_desc, note) = if let Some(place_desc) = opt_place_desc {
let local_kind = if let Some(local) = borrow.borrowed_place.as_local() {
@@ -1372,10 +1385,8 @@
}
fn get_moved_indexes(&mut self, location: Location, mpi: MovePathIndex) -> Vec<MoveSite> {
- let body = self.body;
-
let mut stack = Vec::new();
- stack.extend(body.predecessor_locations(location).map(|predecessor| {
+ stack.extend(self.body.predecessor_locations(location).map(|predecessor| {
let is_back_edge = location.dominates(predecessor, &self.dominators);
(predecessor, is_back_edge)
}));
@@ -1394,7 +1405,7 @@
}
// check for moves
- let stmt_kind = body[location.block]
+ let stmt_kind = self.body[location.block]
.statements
.get(location.statement_index)
.map(|s| &s.kind);
@@ -1449,7 +1460,7 @@
let mut any_match = false;
drop_flag_effects::for_location_inits(
self.infcx.tcx,
- self.body,
+ &self.body,
self.move_data,
location,
|m| {
@@ -1462,7 +1473,7 @@
continue 'dfs;
}
- stack.extend(body.predecessor_locations(location).map(|predecessor| {
+ stack.extend(self.body.predecessor_locations(location).map(|predecessor| {
let back_edge = location.dominates(predecessor, &self.dominators);
(predecessor, is_back_edge || back_edge)
}));
@@ -1471,7 +1482,7 @@
result
}
- pub(super) fn report_illegal_mutation_of_borrowed(
+ pub(in crate::borrow_check) fn report_illegal_mutation_of_borrowed(
&mut self,
location: Location,
(place, span): (&Place<'tcx>, Span),
@@ -1514,7 +1525,7 @@
self.explain_why_borrow_contains_point(location, loan, None)
.add_explanation_to_diagnostic(
self.infcx.tcx,
- self.body,
+ &self.body,
&self.local_names,
&mut err,
"",
@@ -1530,7 +1541,7 @@
/// assigned; `err_place` is a place providing a reason why
/// `place` is not mutable (e.g., the non-`mut` local `x` in an
/// assignment to `x.f`).
- pub(super) fn report_illegal_reassignment(
+ pub(in crate::borrow_check) fn report_illegal_reassignment(
&mut self,
_location: Location,
(place, span): (&Place<'tcx>, Span),
@@ -1625,7 +1636,12 @@
StorageDeadOrDrop::LocalStorageDead
| StorageDeadOrDrop::BoxedStorageDead => {
assert!(
- Place::ty_from(&place.base, proj_base, self.body, tcx).ty.is_box(),
+ Place::ty_from(
+ &place.base,
+ proj_base,
+ *self.body,
+ tcx
+ ).ty.is_box(),
"Drop of value behind a reference or raw pointer"
);
StorageDeadOrDrop::BoxedStorageDead
@@ -1633,7 +1649,12 @@
StorageDeadOrDrop::Destructor(_) => base_access,
},
ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
- let base_ty = Place::ty_from(&place.base, proj_base, self.body, tcx).ty;
+ let base_ty = Place::ty_from(
+ &place.base,
+ proj_base,
+ *self.body,
+ tcx
+ ).ty;
match base_ty.kind {
ty::Adt(def, _) if def.has_dtor(tcx) => {
// Report the outermost adt with a destructor
@@ -1678,7 +1699,7 @@
}
}
let mut visitor = FakeReadCauseFinder { place, cause: None };
- visitor.visit_body(&self.body);
+ visitor.visit_body(self.body);
match visitor.cause {
Some(FakeReadCause::ForMatchGuard) => Some("match guard"),
Some(FakeReadCause::ForIndex) => Some("indexing expression"),
@@ -1736,7 +1757,8 @@
// Next, look through the rest of the block, checking if we are assigning the
// `target` (that is, the place that contains our borrow) to anything.
let mut annotated_closure = None;
- for stmt in &self.body[location.block].statements[location.statement_index + 1..] {
+ for stmt in &self.body[location.block].statements[location.statement_index + 1..]
+ {
debug!(
"annotate_argument_and_return_for_borrow: target={:?} stmt={:?}",
target, stmt
@@ -2062,7 +2084,7 @@
impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
/// Annotate the provided diagnostic with information about borrow from the fn signature that
/// helps explain.
- pub(super) fn emit(
+ pub(in crate::borrow_check) fn emit(
&self,
cx: &mut MirBorrowckCtxt<'_, 'tcx>,
diag: &mut DiagnosticBuilder<'_>,
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
similarity index 98%
rename from src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
rename to src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
index c705853..67c3c36 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
@@ -1,8 +1,7 @@
use std::collections::VecDeque;
use crate::borrow_check::borrow_set::BorrowData;
-use crate::borrow_check::error_reporting::UseSpans;
-use crate::borrow_check::nll::region_infer::{Cause, RegionName};
+use crate::borrow_check::nll::region_infer::Cause;
use crate::borrow_check::nll::ConstraintDescription;
use crate::borrow_check::{MirBorrowckCtxt, WriteKind};
use rustc::mir::{
@@ -17,7 +16,7 @@
use syntax_pos::Span;
use syntax_pos::symbol::Symbol;
-mod find_use;
+use super::{UseSpans, find_use, RegionName};
#[derive(Debug)]
pub(in crate::borrow_check) enum BorrowExplanation {
@@ -237,7 +236,7 @@
);
let regioncx = &self.nonlexical_regioncx;
- let body = self.body;
+ let body: &Body<'_> = &self.body;
let tcx = self.infcx.tcx;
let borrow_region_vid = borrow.region;
@@ -297,9 +296,9 @@
if let Some(region) = regioncx.to_error_region_vid(borrow_region_vid) {
let (category, from_closure, span, region_name) =
self.nonlexical_regioncx.free_region_constraint_info(
- self.body,
- &self.local_names,
- &self.upvars,
+ &self.body,
+ &self.local_names,
+ &self.upvars,
self.mir_def_id,
self.infcx,
borrow_region_vid,
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs b/src/librustc_mir/borrow_check/diagnostics/find_use.rs
similarity index 100%
rename from src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs
rename to src/librustc_mir/borrow_check/diagnostics/find_use.rs
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs
similarity index 96%
rename from src/librustc_mir/borrow_check/error_reporting.rs
rename to src/librustc_mir/borrow_check/diagnostics/mod.rs
index a555e0b..1a76265 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs
@@ -1,3 +1,5 @@
+//! Borrow checker diagnostics.
+
use rustc::hir;
use rustc::hir::def::Namespace;
use rustc::hir::def_id::DefId;
@@ -17,6 +19,22 @@
use super::MirBorrowckCtxt;
use crate::dataflow::move_paths::{InitLocation, LookupResult};
+mod find_use;
+mod var_name;
+mod region_name;
+mod outlives_suggestion;
+
+mod conflict_errors;
+mod move_errors;
+mod mutability_errors;
+mod region_errors;
+mod explain_borrow;
+
+crate use mutability_errors::AccessKind;
+crate use region_name::{RegionName, RegionNameSource, RegionErrorNamingCtx};
+crate use region_errors::{ErrorReportingCtx, ErrorConstraintInfo};
+crate use outlives_suggestion::OutlivesSuggestionBuilder;
+
pub(super) struct IncludingDowncast(pub(super) bool);
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
@@ -369,8 +387,11 @@
}, field)
}
ProjectionElem::Downcast(_, variant_index) => {
- let base_ty =
- Place::ty_from(place.base, place.projection, self.body, self.infcx.tcx).ty;
+ let base_ty = Place::ty_from(
+ place.base,
+ place.projection,
+ *self.body,
+ self.infcx.tcx).ty;
self.describe_field_from_ty(&base_ty, field, Some(*variant_index))
}
ProjectionElem::Field(_, field_type) => {
@@ -498,9 +519,10 @@
},
..
}) = bbd.terminator {
- if let Some(source)
- = BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx)
- {
+ if let Some(source) = BorrowedContentSource::from_call(
+ func.ty(*self.body, tcx),
+ tcx
+ ) {
return source;
}
}
@@ -512,7 +534,12 @@
// If we didn't find an overloaded deref or index, then assume it's a
// built in deref and check the type of the base.
- let base_ty = Place::ty_from(deref_base.base, deref_base.projection, self.body, tcx).ty;
+ let base_ty = Place::ty_from(
+ deref_base.base,
+ deref_base.projection,
+ *self.body,
+ tcx
+ ).ty;
if base_ty.is_unsafe_ptr() {
BorrowedContentSource::DerefRawPointer
} else if base_ty.is_mutable_ptr() {
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
similarity index 98%
rename from src/librustc_mir/borrow_check/move_errors.rs
rename to src/librustc_mir/borrow_check/diagnostics/move_errors.rs
index bf61eb9..938836d 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
@@ -5,7 +5,7 @@
use crate::borrow_check::MirBorrowckCtxt;
use crate::borrow_check::prefixes::PrefixSet;
-use crate::borrow_check::error_reporting::UseSpans;
+use crate::borrow_check::diagnostics::UseSpans;
use crate::dataflow::move_paths::{
IllegalMoveOrigin, IllegalMoveOriginKind,
LookupResult, MoveError, MovePathIndex,
@@ -300,7 +300,7 @@
// Inspect the type of the content behind the
// borrow to provide feedback about why this
// was a move rather than a copy.
- let ty = deref_target_place.ty(self.body, self.infcx.tcx).ty;
+ let ty = deref_target_place.ty(*self.body, self.infcx.tcx).ty;
let upvar_field = self.prefixes(move_place.as_ref(), PrefixSet::All)
.find_map(|p| self.is_upvar_field_projection(p));
@@ -411,7 +411,7 @@
};
let move_ty = format!(
"{:?}",
- move_place.ty(self.body, self.infcx.tcx).ty,
+ move_place.ty(*self.body, self.infcx.tcx).ty,
);
if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
let is_option = move_ty.starts_with("std::option::Option");
@@ -454,7 +454,7 @@
}
if binds_to.is_empty() {
- let place_ty = move_from.ty(self.body, self.infcx.tcx).ty;
+ let place_ty = move_from.ty(*self.body, self.infcx.tcx).ty;
let place_desc = match self.describe_place(move_from.as_ref()) {
Some(desc) => format!("`{}`", desc),
None => format!("value"),
@@ -482,7 +482,7 @@
// No binding. Nothing to suggest.
GroupedMoveError::OtherIllegalMove { ref original_path, use_spans, .. } => {
let span = use_spans.var_or_use();
- let place_ty = original_path.ty(self.body, self.infcx.tcx).ty;
+ let place_ty = original_path.ty(*self.body, self.infcx.tcx).ty;
let place_desc = match self.describe_place(original_path.as_ref()) {
Some(desc) => format!("`{}`", desc),
None => format!("value"),
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
similarity index 97%
rename from src/librustc_mir/borrow_check/mutability_errors.rs
rename to src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
index bf070c3..6449ae3 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
@@ -1,6 +1,6 @@
use rustc::hir;
use rustc::hir::Node;
-use rustc::mir::{self, Body, ClearCrossCrate, Local, LocalInfo, Location};
+use rustc::mir::{self, ClearCrossCrate, Local, LocalInfo, Location, ReadOnlyBodyCache};
use rustc::mir::{Mutability, Place, PlaceRef, PlaceBase, ProjectionElem};
use rustc::ty::{self, Ty, TyCtxt};
use rustc_index::vec::Idx;
@@ -8,18 +8,18 @@
use syntax_pos::symbol::kw;
use crate::borrow_check::MirBorrowckCtxt;
-use crate::borrow_check::error_reporting::BorrowedContentSource;
+use crate::borrow_check::diagnostics::BorrowedContentSource;
use crate::util::collect_writes::FindAssignments;
use rustc_errors::Applicability;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub(super) enum AccessKind {
+pub(crate) enum AccessKind {
MutableBorrow,
Mutate,
}
impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
- pub(super) fn report_mutability_error(
+ pub(crate) fn report_mutability_error(
&mut self,
access_place: &Place<'tcx>,
span: Span,
@@ -61,8 +61,12 @@
projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
} => {
debug_assert!(is_closure_or_generator(
- Place::ty_from(&the_place_err.base, proj_base, self.body, self.infcx.tcx).ty
- ));
+ Place::ty_from(
+ &the_place_err.base,
+ proj_base,
+ *self.body,
+ self.infcx.tcx
+ ).ty));
item_msg = format!("`{}`", access_place_desc.unwrap());
if self.is_upvar_field_projection(access_place.as_ref()).is_some() {
@@ -111,7 +115,7 @@
Place::ty_from(
the_place_err.base,
the_place_err.projection,
- self.body,
+ *self.body,
self.infcx.tcx
)
.ty
@@ -225,7 +229,7 @@
if let Some((span, message)) = annotate_struct_field(
self.infcx.tcx,
- Place::ty_from(base, proj_base, self.body, self.infcx.tcx).ty,
+ Place::ty_from(base, proj_base, *self.body, self.infcx.tcx).ty,
field,
) {
err.span_suggestion(
@@ -300,7 +304,7 @@
projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
} => {
debug_assert!(is_closure_or_generator(
- Place::ty_from(base, proj_base, self.body, self.infcx.tcx).ty
+ Place::ty_from(base, proj_base, *self.body, self.infcx.tcx).ty
));
err.span_label(span, format!("cannot {ACT}", ACT = act));
@@ -529,7 +533,7 @@
// by trying (3.), then (2.) and finally falling back on (1.).
fn suggest_ampmut<'tcx>(
tcx: TyCtxt<'tcx>,
- body: &Body<'tcx>,
+ body: ReadOnlyBodyCache<'_, 'tcx>,
local: Local,
local_decl: &mir::LocalDecl<'tcx>,
opt_ty_info: Option<Span>,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/outlives_suggestion.rs b/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
similarity index 97%
rename from src/librustc_mir/borrow_check/nll/region_infer/error_reporting/outlives_suggestion.rs
rename to src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
index 938059c..7aecada 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/outlives_suggestion.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
@@ -13,12 +13,10 @@
use smallvec::SmallVec;
-use crate::borrow_check::nll::region_infer::{
- error_reporting::{
- region_name::{RegionName, RegionNameSource},
- ErrorConstraintInfo, ErrorReportingCtx, RegionErrorNamingCtx,
- },
- RegionInferenceContext,
+use crate::borrow_check::nll::region_infer::RegionInferenceContext;
+
+use super::{
+ RegionName, RegionNameSource, ErrorConstraintInfo, ErrorReportingCtx, RegionErrorNamingCtx,
};
/// The different things we could suggest.
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
similarity index 97%
rename from src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
rename to src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index 5e79a2f..66f0330 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -19,14 +19,7 @@
use syntax_pos::Span;
use syntax_pos::symbol::Symbol;
-use self::outlives_suggestion::OutlivesSuggestionBuilder;
-
-pub mod outlives_suggestion;
-
-mod region_name;
-mod var_name;
-
-crate use self::region_name::{RegionName, RegionNameSource, RegionErrorNamingCtx};
+use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource, RegionErrorNamingCtx};
impl ConstraintDescription for ConstraintCategory {
fn description(&self) -> &'static str {
@@ -61,36 +54,36 @@
/// Various pieces of state used when reporting borrow checker errors.
pub struct ErrorReportingCtx<'a, 'b, 'tcx> {
/// The region inference context used for borrow chekcing this MIR body.
- region_infcx: &'b RegionInferenceContext<'tcx>,
+ pub(super) region_infcx: &'b RegionInferenceContext<'tcx>,
/// The inference context used for type checking.
- infcx: &'b InferCtxt<'a, 'tcx>,
+ pub(super) infcx: &'b InferCtxt<'a, 'tcx>,
/// The MIR def we are reporting errors on.
- mir_def_id: DefId,
+ pub(super) mir_def_id: DefId,
/// The MIR body we are reporting errors on (for convenience).
- body: &'b Body<'tcx>,
+ pub(super) body: &'b Body<'tcx>,
/// User variable names for MIR locals (where applicable).
- local_names: &'b IndexVec<Local, Option<Symbol>>,
+ pub(super) local_names: &'b IndexVec<Local, Option<Symbol>>,
/// Any upvars for the MIR body we have kept track of during borrow checking.
- upvars: &'b [Upvar],
+ pub(super) upvars: &'b [Upvar],
}
/// Information about the various region constraints involved in a borrow checker error.
#[derive(Clone, Debug)]
pub struct ErrorConstraintInfo {
// fr: outlived_fr
- fr: RegionVid,
- fr_is_local: bool,
- outlived_fr: RegionVid,
- outlived_fr_is_local: bool,
+ pub(super) fr: RegionVid,
+ pub(super) fr_is_local: bool,
+ pub(super) outlived_fr: RegionVid,
+ pub(super) outlived_fr_is_local: bool,
// Category and span for best blame constraint
- category: ConstraintCategory,
- span: Span,
+ pub(super) category: ConstraintCategory,
+ pub(super) span: Span,
}
impl<'tcx> RegionInferenceContext<'tcx> {
@@ -368,7 +361,7 @@
/// ```
///
/// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
- pub(super) fn report_error<'a>(
+ pub(in crate::borrow_check) fn report_error<'a>(
&'a self,
body: &Body<'tcx>,
local_names: &IndexVec<Local, Option<Symbol>>,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
similarity index 98%
rename from src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
rename to src/librustc_mir/borrow_check/diagnostics/region_name.rs
index 0f5d1c5..e2e7596 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
@@ -1,12 +1,5 @@
use std::fmt::{self, Display};
-use crate::borrow_check::nll::region_infer::{
- RegionInferenceContext,
- error_reporting::ErrorReportingCtx,
-};
-use crate::borrow_check::nll::universal_regions::DefiningTy;
-use crate::borrow_check::nll::ToRegionVid;
-use crate::borrow_check::Upvar;
use rustc::hir;
use rustc::hir::def::{Res, DefKind};
use rustc::hir::def_id::DefId;
@@ -21,6 +14,15 @@
use rustc_data_structures::fx::FxHashMap;
use syntax_pos::{Span, symbol::Symbol, DUMMY_SP};
+use crate::borrow_check::{
+ nll::region_infer::RegionInferenceContext,
+ nll::universal_regions::DefiningTy,
+ nll::ToRegionVid,
+ Upvar,
+};
+
+use super::region_errors::ErrorReportingCtx;
+
/// A name for a particular region used in emitting diagnostics. This name could be a generated
/// name like `'1`, a name used by the user like `'a`, or a name like `'static`.
#[derive(Debug, Clone)]
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs b/src/librustc_mir/borrow_check/diagnostics/var_name.rs
similarity index 100%
rename from src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs
rename to src/librustc_mir/borrow_check/diagnostics/var_name.rs
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 649aeac..a1932b5 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -9,8 +9,8 @@
use rustc::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT};
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
use rustc::mir::{
- ClearCrossCrate, Local, Location, Body, Mutability, Operand, Place, PlaceBase, PlaceElem,
- PlaceRef, Static, StaticKind
+ ClearCrossCrate, Local, Location, Body, BodyCache, Mutability, Operand, Place, PlaceBase,
+ PlaceElem, PlaceRef, ReadOnlyBodyCache, Static, StaticKind, read_only
};
use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
use rustc::mir::{Terminator, TerminatorKind};
@@ -46,17 +46,14 @@
use self::location::LocationTable;
use self::prefixes::PrefixSet;
use self::MutateMode::{JustWrite, WriteAndRead};
-use self::mutability_errors::AccessKind;
+use self::diagnostics::AccessKind;
use self::path_utils::*;
crate mod borrow_set;
-mod error_reporting;
+mod diagnostics;
mod flows;
mod location;
-mod conflict_errors;
-mod move_errors;
-mod mutability_errors;
mod path_utils;
crate mod place_ext;
crate mod places_conflict;
@@ -102,7 +99,7 @@
fn do_mir_borrowck<'a, 'tcx>(
infcx: &InferCtxt<'a, 'tcx>,
input_body: &Body<'tcx>,
- input_promoted: &IndexVec<Promoted, Body<'tcx>>,
+ input_promoted: &IndexVec<Promoted, BodyCache<'tcx>>,
def_id: DefId,
) -> BorrowCheckResult<'tcx> {
debug!("do_mir_borrowck(def_id = {:?})", def_id);
@@ -162,16 +159,22 @@
// requires first making our own copy of the MIR. This copy will
// be modified (in place) to contain non-lexical lifetimes. It
// will have a lifetime tied to the inference context.
- let mut body: Body<'tcx> = input_body.clone();
- let mut promoted: IndexVec<Promoted, Body<'tcx>> = input_promoted.clone();
+ let body_clone: Body<'tcx> = input_body.clone();
+ let mut promoted = input_promoted.clone();
+ let mut body = BodyCache::new(body_clone);
let free_regions =
nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted);
- let body = &body; // no further changes
- let location_table = &LocationTable::new(body);
+ let body = read_only!(body); // no further changes
+ let promoted: IndexVec<_, _> = promoted
+ .iter_mut()
+ .map(|body| read_only!(body))
+ .collect();
+
+ let location_table = &LocationTable::new(&body);
let mut errors_buffer = Vec::new();
let (move_data, move_errors): (MoveData<'tcx>, Option<Vec<(Place<'tcx>, MoveError<'tcx>)>>) =
- match MoveData::gather_moves(body, tcx) {
+ match MoveData::gather_moves(&body, tcx) {
Ok(move_data) => (move_data, None),
Err((move_data, move_errors)) => (move_data, Some(move_errors)),
};
@@ -184,17 +187,17 @@
let dead_unwinds = BitSet::new_empty(body.basic_blocks().len());
let mut flow_inits = FlowAtLocation::new(do_dataflow(
tcx,
- body,
+ &body,
def_id,
&attributes,
&dead_unwinds,
- MaybeInitializedPlaces::new(tcx, body, &mdpe),
+ MaybeInitializedPlaces::new(tcx, &body, &mdpe),
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
));
let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(id).is_fn_or_closure();
let borrow_set = Rc::new(BorrowSet::build(
- tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));
+ tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));
// If we are in non-lexical mode, compute the non-lexical lifetimes.
let (regioncx, polonius_output, opt_closure_req) = nll::compute_regions(
@@ -222,29 +225,29 @@
let flow_borrows = FlowAtLocation::new(do_dataflow(
tcx,
- body,
+ &body,
def_id,
&attributes,
&dead_unwinds,
- Borrows::new(tcx, body, param_env, regioncx.clone(), &borrow_set),
+ Borrows::new(tcx, &body, param_env, regioncx.clone(), &borrow_set),
|rs, i| DebugFormatted::new(&rs.location(i)),
));
let flow_uninits = FlowAtLocation::new(do_dataflow(
tcx,
- body,
+ &body,
def_id,
&attributes,
&dead_unwinds,
- MaybeUninitializedPlaces::new(tcx, body, &mdpe),
+ MaybeUninitializedPlaces::new(tcx, &body, &mdpe),
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
));
let flow_ever_inits = FlowAtLocation::new(do_dataflow(
tcx,
- body,
+ &body,
def_id,
&attributes,
&dead_unwinds,
- EverInitializedPlaces::new(tcx, body, &mdpe),
+ EverInitializedPlaces::new(tcx, &body, &mdpe),
|bd, i| DebugFormatted::new(&bd.move_data().inits[i]),
));
@@ -300,11 +303,10 @@
let mut initial_diag =
mbcx.report_conflicting_borrow(location, (&place, span), bk, &borrow);
- let lint_root = if let ClearCrossCrate::Set(ref vsi) = mbcx.body.source_scope_local_data {
- let scope = mbcx.body.source_info(location).scope;
- vsi[scope].lint_root
- } else {
- id
+ let scope = mbcx.body.source_info(location).scope;
+ let lint_root = match &mbcx.body.source_scopes[scope].local_data {
+ ClearCrossCrate::Set(data) => data.lint_root,
+ _ => id,
};
// Span and message don't matter; we overwrite them below anyway
@@ -337,39 +339,42 @@
debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
let used_mut = mbcx.used_mut;
- for local in mbcx.body.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) {
- if let ClearCrossCrate::Set(ref vsi) = mbcx.body.source_scope_local_data {
- let local_decl = &mbcx.body.local_decls[local];
+ for local in mbcx.body.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local))
+ {
+ let local_decl = &mbcx.body.local_decls[local];
+ let lint_root = match &mbcx.body.source_scopes[local_decl.source_info.scope].local_data {
+ ClearCrossCrate::Set(data) => data.lint_root,
+ _ => continue,
+ };
- // Skip over locals that begin with an underscore or have no name
- match mbcx.local_names[local] {
- Some(name) => if name.as_str().starts_with("_") {
- continue;
- },
- None => continue,
- }
-
- let span = local_decl.source_info.span;
- if span.desugaring_kind().is_some() {
- // If the `mut` arises as part of a desugaring, we should ignore it.
+ // Skip over locals that begin with an underscore or have no name
+ match mbcx.local_names[local] {
+ Some(name) => if name.as_str().starts_with("_") {
continue;
- }
-
- let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
- tcx.struct_span_lint_hir(
- UNUSED_MUT,
- vsi[local_decl.source_info.scope].lint_root,
- span,
- "variable does not need to be mutable",
- )
- .span_suggestion_short(
- mut_span,
- "remove this `mut`",
- String::new(),
- Applicability::MachineApplicable,
- )
- .emit();
+ },
+ None => continue,
}
+
+ let span = local_decl.source_info.span;
+ if span.desugaring_kind().is_some() {
+ // If the `mut` arises as part of a desugaring, we should ignore it.
+ continue;
+ }
+
+ let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
+ tcx.struct_span_lint_hir(
+ UNUSED_MUT,
+ lint_root,
+ span,
+ "variable does not need to be mutable",
+ )
+ .span_suggestion_short(
+ mut_span,
+ "remove this `mut`",
+ String::new(),
+ Applicability::MachineApplicable,
+ )
+ .emit();
}
// Buffer any move errors that we collected and de-duplicated.
@@ -397,7 +402,7 @@
crate struct MirBorrowckCtxt<'cx, 'tcx> {
crate infcx: &'cx InferCtxt<'cx, 'tcx>,
- body: &'cx Body<'tcx>,
+ body: ReadOnlyBodyCache<'cx, 'tcx>,
mir_def_id: DefId,
param_env: ty::ParamEnv<'tcx>,
move_data: &'cx MoveData<'tcx>,
@@ -488,7 +493,7 @@
type FlowState = Flows<'cx, 'tcx>;
fn body(&self) -> &'cx Body<'tcx> {
- self.body
+ self.body.body()
}
fn visit_block_entry(&mut self, bb: BasicBlock, flow_state: &Self::FlowState) {
@@ -638,7 +643,7 @@
let tcx = self.infcx.tcx;
// Compute the type with accurate region information.
- let drop_place_ty = drop_place.ty(self.body, self.infcx.tcx);
+ let drop_place_ty = drop_place.ty(*self.body, self.infcx.tcx);
// Erase the regions.
let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty).ty;
@@ -983,6 +988,7 @@
let mut error_reported = false;
let tcx = self.infcx.tcx;
let body = self.body;
+ let body: &Body<'_> = &body;
let param_env = self.param_env;
let location_table = self.location_table.start_index(location);
let borrow_set = self.borrow_set.clone();
@@ -1333,7 +1339,8 @@
_ => bug!("temporary initialized in arguments"),
};
- let bbd = &self.body[loc.block];
+ let body = self.body;
+ let bbd = &body[loc.block];
let stmt = &bbd.statements[loc.statement_index];
debug!("temporary assigned in: stmt={:?}", stmt);
@@ -1452,7 +1459,7 @@
if places_conflict::borrow_conflicts_with_place(
self.infcx.tcx,
self.param_env,
- self.body,
+ &self.body,
place,
borrow.kind,
root_place,
@@ -1743,7 +1750,7 @@
// assigning to `P.f` requires `P` itself
// be already initialized
let tcx = self.infcx.tcx;
- let base_ty = Place::ty_from(&place.base, proj_base, self.body, tcx).ty;
+ let base_ty = Place::ty_from(&place.base, proj_base, self.body(), tcx).ty;
match base_ty.kind {
ty::Adt(def, _) if def.has_dtor(tcx) => {
self.check_if_path_or_subpath_is_moved(
@@ -1850,7 +1857,7 @@
// of the union - we should error in that case.
let tcx = this.infcx.tcx;
if let ty::Adt(def, _) =
- Place::ty_from(base.base, base.projection, this.body, tcx).ty.kind
+ Place::ty_from(base.base, base.projection, this.body(), tcx).ty.kind
{
if def.is_union() {
if this.move_data.path_map[mpi].iter().any(|moi| {
@@ -2120,7 +2127,7 @@
match elem {
ProjectionElem::Deref => {
let base_ty =
- Place::ty_from(place.base, proj_base, self.body, self.infcx.tcx).ty;
+ Place::ty_from(place.base, proj_base, self.body(), self.infcx.tcx).ty;
// Check the kind of deref to decide
match base_ty.kind {
@@ -2260,7 +2267,7 @@
match place_projection {
[base @ .., ProjectionElem::Field(field, _ty)] => {
let tcx = self.infcx.tcx;
- let base_ty = Place::ty_from(place_ref.base, base, self.body, tcx).ty;
+ let base_ty = Place::ty_from(place_ref.base, base, self.body(), tcx).ty;
if (base_ty.is_closure() || base_ty.is_generator()) &&
(!by_ref || self.upvars[field.index()].by_ref) {
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index 1d429e3..98679f2 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -11,7 +11,7 @@
use crate::dataflow::indexes::BorrowIndex;
use rustc::ty::{self, TyCtxt};
use rustc::mir::visit::Visitor;
-use rustc::mir::{BasicBlock, Location, Body, Place, Rvalue};
+use rustc::mir::{BasicBlock, Location, Body, Place, ReadOnlyBodyCache, Rvalue};
use rustc::mir::{Statement, StatementKind};
use rustc::mir::TerminatorKind;
use rustc::mir::{Operand, BorrowKind};
@@ -22,7 +22,7 @@
param_env: ty::ParamEnv<'tcx>,
all_facts: &mut Option<AllFacts>,
location_table: &LocationTable,
- body: &Body<'tcx>,
+ body: ReadOnlyBodyCache<'_, 'tcx>,
borrow_set: &BorrowSet<'tcx>,
) {
if all_facts.is_none() {
@@ -38,7 +38,7 @@
param_env,
tcx,
location_table,
- body,
+ body: &body,
dominators,
};
ig.visit_body(body);
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index 4d67b72..7a5bbb4 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -12,7 +12,8 @@
use rustc::hir::def_id::DefId;
use rustc::infer::InferCtxt;
use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements,
- Local, Location, Body, LocalKind, BasicBlock, Promoted};
+ Local, Location, Body, BodyCache, LocalKind, BasicBlock,
+ Promoted, ReadOnlyBodyCache};
use rustc::ty::{self, RegionKind, RegionVid};
use rustc_index::vec::IndexVec;
use rustc_errors::Diagnostic;
@@ -31,17 +32,17 @@
use crate::util::pretty;
mod constraint_generation;
-pub mod explain_borrow;
mod facts;
mod invalidation;
-crate mod region_infer;
mod renumber;
-crate mod type_check;
-mod universal_regions;
-mod constraints;
mod member_constraints;
+crate mod constraints;
+crate mod universal_regions;
+crate mod type_check;
+crate mod region_infer;
+
use self::facts::AllFacts;
use self::region_infer::RegionInferenceContext;
use self::universal_regions::UniversalRegions;
@@ -54,8 +55,8 @@
infcx: &InferCtxt<'cx, 'tcx>,
def_id: DefId,
param_env: ty::ParamEnv<'tcx>,
- body: &mut Body<'tcx>,
- promoted: &mut IndexVec<Promoted, Body<'tcx>>,
+ body: &mut BodyCache<'tcx>,
+ promoted: &mut IndexVec<Promoted, BodyCache<'tcx>>,
) -> UniversalRegions<'tcx> {
debug!("replace_regions_in_mir(def_id={:?})", def_id);
@@ -157,8 +158,8 @@
infcx: &InferCtxt<'cx, 'tcx>,
def_id: DefId,
universal_regions: UniversalRegions<'tcx>,
- body: &Body<'tcx>,
- promoted: &IndexVec<Promoted, Body<'tcx>>,
+ body: ReadOnlyBodyCache<'_, 'tcx>,
+ promoted: &IndexVec<Promoted, ReadOnlyBodyCache<'_, 'tcx>>,
local_names: &IndexVec<Local, Option<Symbol>>,
upvars: &[Upvar],
location_table: &LocationTable,
@@ -172,15 +173,12 @@
Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex, Local, MovePathIndex>>>,
Option<ClosureRegionRequirements<'tcx>>,
) {
- let mut all_facts = if AllFacts::enabled(infcx.tcx) {
- Some(AllFacts::default())
- } else {
- None
- };
+ let mut all_facts = AllFacts::enabled(infcx.tcx).then_some(AllFacts::default());
let universal_regions = Rc::new(universal_regions);
- let elements = &Rc::new(RegionValueElements::new(body));
+ let elements
+ = &Rc::new(RegionValueElements::new(&body));
// Run the MIR type-checker.
let MirTypeckResults {
@@ -205,7 +203,7 @@
all_facts
.universal_region
.extend(universal_regions.universal_regions());
- populate_polonius_move_facts(all_facts, move_data, location_table, body);
+ populate_polonius_move_facts(all_facts, move_data, location_table, &body);
}
// Create the region inference context, taking ownership of the
@@ -238,7 +236,6 @@
universal_regions,
placeholder_indices,
universal_region_relations,
- body,
outlives_constraints,
member_constraints,
closure_bounds_mapping,
@@ -253,7 +250,7 @@
param_env,
&mut all_facts,
location_table,
- &body,
+ body,
borrow_set,
);
@@ -283,7 +280,7 @@
// Solve the region constraints.
let closure_region_requirements =
- regioncx.solve(infcx, body, local_names, upvars, def_id, errors_buffer);
+ regioncx.solve(infcx, &body, local_names, upvars, def_id, errors_buffer);
// Dump MIR results into a file, if that is enabled. This let us
// write unit-tests, as well as helping with debugging.
@@ -297,7 +294,13 @@
// We also have a `#[rustc_nll]` annotation that causes us to dump
// information
- dump_annotation(infcx, &body, def_id, ®ioncx, &closure_region_requirements, errors_buffer);
+ dump_annotation(
+ infcx,
+ &body,
+ def_id,
+ ®ioncx,
+ &closure_region_requirements,
+ errors_buffer);
(regioncx, polonius_output, closure_region_requirements)
}
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index d44e85f..0b3cb29 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -1,21 +1,5 @@
use std::rc::Rc;
-use crate::borrow_check::nll::{
- constraints::{
- graph::NormalConstraintGraph,
- ConstraintSccIndex,
- OutlivesConstraint,
- OutlivesConstraintSet,
- },
- member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
- region_infer::values::{
- PlaceholderIndices, RegionElement, ToElementIndex
- },
- region_infer::error_reporting::outlives_suggestion::OutlivesSuggestionBuilder,
- type_check::{free_region_relations::UniversalRegionRelations, Locations},
-};
-use crate::borrow_check::Upvar;
-
use rustc::hir::def_id::DefId;
use rustc::infer::canonical::QueryOutlivesConstraint;
use rustc::infer::opaque_types;
@@ -38,13 +22,31 @@
use syntax_pos::Span;
use syntax_pos::symbol::Symbol;
-crate use self::error_reporting::{RegionName, RegionNameSource, RegionErrorNamingCtx};
+use crate::borrow_check::{
+ nll::{
+ constraints::{
+ graph::NormalConstraintGraph,
+ ConstraintSccIndex,
+ OutlivesConstraint,
+ OutlivesConstraintSet,
+ },
+ member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
+ region_infer::values::{
+ PlaceholderIndices, RegionElement, ToElementIndex
+ },
+ type_check::{free_region_relations::UniversalRegionRelations, Locations},
+ },
+ diagnostics::{
+ OutlivesSuggestionBuilder, RegionErrorNamingCtx,
+ },
+ Upvar,
+};
+
use self::values::{LivenessValues, RegionValueElements, RegionValues};
use super::universal_regions::UniversalRegions;
use super::ToRegionVid;
mod dump_mir;
-mod error_reporting;
mod graphviz;
pub mod values;
@@ -54,48 +56,51 @@
/// variables are identified by their index (`RegionVid`). The
/// definition contains information about where the region came
/// from as well as its final inferred value.
- definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
+ pub(in crate::borrow_check) definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
/// The liveness constraints added to each region. For most
/// regions, these start out empty and steadily grow, though for
/// each universally quantified region R they start out containing
/// the entire CFG and `end(R)`.
- liveness_constraints: LivenessValues<RegionVid>,
+ pub(in crate::borrow_check) liveness_constraints: LivenessValues<RegionVid>,
/// The outlives constraints computed by the type-check.
- constraints: Rc<OutlivesConstraintSet>,
+ pub(in crate::borrow_check) constraints: Rc<OutlivesConstraintSet>,
/// The constraint-set, but in graph form, making it easy to traverse
/// the constraints adjacent to a particular region. Used to construct
/// the SCC (see `constraint_sccs`) and for error reporting.
- constraint_graph: Rc<NormalConstraintGraph>,
+ pub(in crate::borrow_check) constraint_graph: Rc<NormalConstraintGraph>,
/// The SCC computed from `constraints` and the constraint
/// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
/// compute the values of each region.
- constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
+ pub(in crate::borrow_check) constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
/// Reverse of the SCC constraint graph -- i.e., an edge `A -> B`
/// exists if `B: A`. Computed lazilly.
- rev_constraint_graph: Option<Rc<VecGraph<ConstraintSccIndex>>>,
+ pub(in crate::borrow_check) rev_constraint_graph:
+ Option<Rc<VecGraph<ConstraintSccIndex>>>,
/// The "R0 member of [R1..Rn]" constraints, indexed by SCC.
- member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
+ pub(in crate::borrow_check) member_constraints:
+ Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
/// Records the member constraints that we applied to each scc.
/// This is useful for error reporting. Once constraint
/// propagation is done, this vector is sorted according to
/// `member_region_scc`.
- member_constraints_applied: Vec<AppliedMemberConstraint>,
+ pub(in crate::borrow_check) member_constraints_applied: Vec<AppliedMemberConstraint>,
/// Map closure bounds to a `Span` that should be used for error reporting.
- closure_bounds_mapping:
+ pub(in crate::borrow_check) closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
/// Contains the minimum universe of any variable within the same
/// SCC. We will ensure that no SCC contains values that are not
/// visible from this index.
- scc_universes: IndexVec<ConstraintSccIndex, ty::UniverseIndex>,
+ pub(in crate::borrow_check) scc_universes:
+ IndexVec<ConstraintSccIndex, ty::UniverseIndex>,
/// Contains a "representative" from each SCC. This will be the
/// minimal RegionVid belonging to that universe. It is used as a
@@ -104,23 +109,25 @@
/// of its SCC and be sure that -- if they have the same repr --
/// they *must* be equal (though not having the same repr does not
/// mean they are unequal).
- scc_representatives: IndexVec<ConstraintSccIndex, ty::RegionVid>,
+ pub(in crate::borrow_check) scc_representatives:
+ IndexVec<ConstraintSccIndex, ty::RegionVid>,
/// The final inferred values of the region variables; we compute
/// one value per SCC. To get the value for any given *region*,
/// you first find which scc it is a part of.
- scc_values: RegionValues<ConstraintSccIndex>,
+ pub(in crate::borrow_check) scc_values: RegionValues<ConstraintSccIndex>,
/// Type constraints that we check after solving.
- type_tests: Vec<TypeTest<'tcx>>,
+ pub(in crate::borrow_check) type_tests: Vec<TypeTest<'tcx>>,
/// Information about the universally quantified regions in scope
/// on this function.
- universal_regions: Rc<UniversalRegions<'tcx>>,
+ pub (in crate::borrow_check) universal_regions: Rc<UniversalRegions<'tcx>>,
/// Information about how the universally quantified regions in
/// scope on this function relate to one another.
- universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
+ pub(in crate::borrow_check) universal_region_relations:
+ Rc<UniversalRegionRelations<'tcx>>,
}
/// Each time that `apply_member_constraint` is successful, it appends
@@ -132,38 +139,38 @@
/// with `'R: 'O` where `'R` is the pick-region and `'O` is the
/// minimal viable option.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
-struct AppliedMemberConstraint {
+pub(crate) struct AppliedMemberConstraint {
/// The SCC that was affected. (The "member region".)
///
/// The vector if `AppliedMemberConstraint` elements is kept sorted
/// by this field.
- member_region_scc: ConstraintSccIndex,
+ pub(in crate::borrow_check) member_region_scc: ConstraintSccIndex,
/// The "best option" that `apply_member_constraint` found -- this was
/// added as an "ad-hoc" lower-bound to `member_region_scc`.
- min_choice: ty::RegionVid,
+ pub(in crate::borrow_check) min_choice: ty::RegionVid,
/// The "member constraint index" -- we can find out details about
/// the constraint from
/// `set.member_constraints[member_constraint_index]`.
- member_constraint_index: NllMemberConstraintIndex,
+ pub(in crate::borrow_check) member_constraint_index: NllMemberConstraintIndex,
}
-struct RegionDefinition<'tcx> {
+pub(crate) struct RegionDefinition<'tcx> {
/// What kind of variable is this -- a free region? existential
/// variable? etc. (See the `NLLRegionVariableOrigin` for more
/// info.)
- origin: NLLRegionVariableOrigin,
+ pub(in crate::borrow_check) origin: NLLRegionVariableOrigin,
/// Which universe is this region variable defined in? This is
/// most often `ty::UniverseIndex::ROOT`, but when we encounter
/// forall-quantifiers like `for<'a> { 'a = 'b }`, we would create
/// the variable for `'a` in a fresh universe that extends ROOT.
- universe: ty::UniverseIndex,
+ pub(in crate::borrow_check) universe: ty::UniverseIndex,
/// If this is 'static or an early-bound region, then this is
/// `Some(X)` where `X` is the name of the region.
- external_name: Option<ty::Region<'tcx>>,
+ pub(in crate::borrow_check) external_name: Option<ty::Region<'tcx>>,
}
/// N.B., the variants in `Cause` are intentionally ordered. Lower
@@ -239,7 +246,6 @@
universal_regions: Rc<UniversalRegions<'tcx>>,
placeholder_indices: Rc<PlaceholderIndices>,
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
- _body: &Body<'tcx>,
outlives_constraints: OutlivesConstraintSet,
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
closure_bounds_mapping: FxHashMap<
@@ -456,7 +462,9 @@
/// Once region solving has completed, this function will return
/// the member constraints that were applied to the value of a given
/// region `r`. See `AppliedMemberConstraint`.
- fn applied_member_constraints(&self, r: impl ToRegionVid) -> &[AppliedMemberConstraint] {
+ pub(in crate::borrow_check) fn applied_member_constraints(
+ &self, r: impl ToRegionVid
+ ) -> &[AppliedMemberConstraint] {
let scc = self.constraint_sccs.scc(r.to_region_vid());
binary_search_util::binary_search_slice(
&self.member_constraints_applied,
@@ -485,7 +493,7 @@
// functions below, which will trigger them to report errors
// eagerly.
let mut outlives_requirements =
- if infcx.tcx.is_closure(mir_def_id) { Some(vec![]) } else { None };
+ infcx.tcx.is_closure(mir_def_id).then(|| vec![]);
self.check_type_tests(
infcx,
@@ -701,14 +709,11 @@
let min = |r1: ty::RegionVid, r2: ty::RegionVid| -> Option<ty::RegionVid> {
let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
- if r1_outlives_r2 && r2_outlives_r1 {
- Some(r1.min(r2))
- } else if r1_outlives_r2 {
- Some(r2)
- } else if r2_outlives_r1 {
- Some(r1)
- } else {
- None
+ match (r1_outlives_r2, r2_outlives_r1) {
+ (true, true) => Some(r1.min(r2)),
+ (true, false) => Some(r2),
+ (false, true) => Some(r1),
+ (false, false) => None,
}
};
let mut min_choice = choice_regions[0];
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
index 7a86536..b4414c5 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
@@ -1,4 +1,4 @@
-use rustc::mir::{BasicBlock, Location, Body};
+use rustc::mir::{BasicBlock, Location, Body, ReadOnlyBodyCache};
use rustc::ty::{self, RegionVid};
use rustc_index::bit_set::{HybridBitSet, SparseBitMatrix};
use rustc_data_structures::fx::FxHashMap;
@@ -92,7 +92,7 @@
/// Pushes all predecessors of `index` onto `stack`.
crate fn push_predecessors(
&self,
- body: &Body<'_>,
+ body: ReadOnlyBodyCache<'_, '_>,
index: PointIndex,
stack: &mut Vec<PointIndex>,
) {
diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs
index d949c7e..db15d2c 100644
--- a/src/librustc_mir/borrow_check/nll/renumber.rs
+++ b/src/librustc_mir/borrow_check/nll/renumber.rs
@@ -1,6 +1,6 @@
use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc::mir::{Body, Location, PlaceElem, Promoted};
+use rustc::mir::{BodyCache, Location, PlaceElem, Promoted};
use rustc::mir::visit::{MutVisitor, TyContext};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
use rustc_index::vec::IndexVec;
@@ -9,8 +9,8 @@
/// inference variables, returning the number of variables created.
pub fn renumber_mir<'tcx>(
infcx: &InferCtxt<'_, 'tcx>,
- body: &mut Body<'tcx>,
- promoted: &mut IndexVec<Promoted, Body<'tcx>>,
+ body: &mut BodyCache<'tcx>,
+ promoted: &mut IndexVec<Promoted, BodyCache<'tcx>>,
) {
debug!("renumber_mir()");
debug!("renumber_mir: body.arg_count={:?}", body.arg_count);
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
index 7dee00b..d6aa314 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
@@ -1,7 +1,7 @@
use crate::borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements};
use crate::util::liveness::{categorize, DefUse};
use rustc::mir::visit::{PlaceContext, Visitor};
-use rustc::mir::{Body, Local, Location};
+use rustc::mir::{Local, Location, ReadOnlyBodyCache};
use rustc_index::vec::{Idx, IndexVec};
use rustc_data_structures::vec_linked_list as vll;
@@ -60,7 +60,7 @@
crate fn build(
live_locals: &Vec<Local>,
elements: &RegionValueElements,
- body: &Body<'_>,
+ body: ReadOnlyBodyCache<'_, '_>,
) -> Self {
let nones = IndexVec::from_elem_n(None, body.local_decls.len());
let mut local_use_map = LocalUseMap {
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
index a01b528..dfd505f 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
@@ -7,7 +7,7 @@
use crate::dataflow::move_paths::MoveData;
use crate::dataflow::FlowAtLocation;
use crate::dataflow::MaybeInitializedPlaces;
-use rustc::mir::{Body, Local};
+use rustc::mir::{Body, Local, ReadOnlyBodyCache};
use rustc::ty::{RegionVid, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
use std::rc::Rc;
@@ -28,7 +28,7 @@
/// performed before
pub(super) fn generate<'tcx>(
typeck: &mut TypeChecker<'_, 'tcx>,
- body: &Body<'tcx>,
+ body: ReadOnlyBodyCache<'_, 'tcx>,
elements: &Rc<RegionValueElements>,
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
move_data: &MoveData<'tcx>,
@@ -41,10 +41,9 @@
&typeck.borrowck_context.universal_regions,
&typeck.borrowck_context.constraints.outlives_constraints,
);
- let live_locals = compute_live_locals(typeck.tcx(), &free_regions, body);
+ let live_locals = compute_live_locals(typeck.tcx(), &free_regions, &body);
let facts_enabled = AllFacts::enabled(typeck.tcx());
-
let polonius_drop_used = if facts_enabled {
let mut drop_used = Vec::new();
polonius::populate_access_facts(
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs
index 526ad7f..e67de6c 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs
@@ -3,7 +3,7 @@
use crate::dataflow::move_paths::{LookupResult, MoveData};
use crate::util::liveness::{categorize, DefUse};
use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
-use rustc::mir::{Body, Local, Location, Place};
+use rustc::mir::{Local, Location, Place, ReadOnlyBodyCache};
use rustc::ty::subst::GenericArg;
use rustc::ty::Ty;
@@ -97,7 +97,7 @@
pub(super) fn populate_access_facts(
typeck: &mut TypeChecker<'_, 'tcx>,
- body: &Body<'tcx>,
+ body: ReadOnlyBodyCache<'_, 'tcx>,
location_table: &LocationTable,
move_data: &MoveData<'_>,
drop_used: &mut Vec<(Local, Location)>,
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
index eacc4d0..229cbed 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
@@ -7,7 +7,7 @@
use crate::dataflow::move_paths::MoveData;
use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
use rustc::infer::canonical::QueryRegionConstraints;
-use rustc::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
+use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, ReadOnlyBodyCache};
use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
use rustc::traits::query::type_op::outlives::DropckOutlives;
use rustc::traits::query::type_op::TypeOp;
@@ -32,7 +32,7 @@
/// this respects `#[may_dangle]` annotations).
pub(super) fn trace(
typeck: &mut TypeChecker<'_, 'tcx>,
- body: &Body<'tcx>,
+ body: ReadOnlyBodyCache<'_, 'tcx>,
elements: &Rc<RegionValueElements>,
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
move_data: &MoveData<'tcx>,
@@ -71,7 +71,7 @@
elements: &'me RegionValueElements,
/// MIR we are analyzing.
- body: &'me Body<'tcx>,
+ body: ReadOnlyBodyCache<'me, 'tcx>,
/// Mapping to/from the various indices used for initialization tracking.
move_data: &'me MoveData<'tcx>,
@@ -302,7 +302,8 @@
}
}
- for &pred_block in self.cx.body.predecessors_for(block).iter() {
+ let body = self.cx.body;
+ for &pred_block in body.predecessors_for(block).iter() {
debug!("compute_drop_live_points_for_block: pred_block = {:?}", pred_block,);
// Check whether the variable is (at least partially)
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 99bcfa9..de30420 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -1,57 +1,59 @@
//! This pass type-checks the MIR to ensure it is not broken.
+use std::{fmt, iter, mem};
+use std::rc::Rc;
+
+use either::Either;
+
+use rustc::hir;
+use rustc::hir::def_id::DefId;
+use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
+use rustc::infer::canonical::QueryRegionConstraints;
+use rustc::infer::outlives::env::RegionBoundPairs;
+use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc::mir::*;
+use rustc::mir::interpret::PanicInfo;
+use rustc::mir::tcx::PlaceTy;
+use rustc::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
+use rustc::traits::{self, ObligationCause, PredicateObligations};
+use rustc::traits::query::{Fallible, NoSolution};
+use rustc::traits::query::type_op;
+use rustc::traits::query::type_op::custom::CustomTypeOp;
+use rustc::ty::{
+ self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, RegionVid, ToPolyTraitRef, Ty,
+ TyCtxt, UserType,
+ UserTypeAnnotationIndex,
+};
+use rustc::ty::adjustment::PointerCast;
+use rustc::ty::cast::CastTy;
+use rustc::ty::fold::TypeFoldable;
+use rustc::ty::layout::VariantIdx;
+use rustc::ty::subst::{GenericArgKind, Subst, SubstsRef, UserSubsts};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_error_codes::*;
+use rustc_index::vec::{Idx, IndexVec};
+use syntax_pos::{DUMMY_SP, Span};
+
use crate::borrow_check::borrow_set::BorrowSet;
use crate::borrow_check::location::LocationTable;
-use crate::borrow_check::nll::constraints::{OutlivesConstraintSet, OutlivesConstraint};
-use crate::borrow_check::nll::member_constraints::MemberConstraintSet;
+use crate::borrow_check::nll::constraints::{OutlivesConstraint, OutlivesConstraintSet};
use crate::borrow_check::nll::facts::AllFacts;
+use crate::borrow_check::nll::member_constraints::MemberConstraintSet;
+use crate::borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest};
use crate::borrow_check::nll::region_infer::values::LivenessValues;
use crate::borrow_check::nll::region_infer::values::PlaceholderIndex;
use crate::borrow_check::nll::region_infer::values::PlaceholderIndices;
use crate::borrow_check::nll::region_infer::values::RegionValueElements;
-use crate::borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest};
use crate::borrow_check::nll::renumber;
+use crate::borrow_check::nll::ToRegionVid;
use crate::borrow_check::nll::type_check::free_region_relations::{
CreateResult, UniversalRegionRelations,
};
use crate::borrow_check::nll::universal_regions::{DefiningTy, UniversalRegions};
-use crate::borrow_check::nll::ToRegionVid;
-use crate::transform::promote_consts::should_suggest_const_in_array_repeat_expressions_attribute;
-use crate::dataflow::move_paths::MoveData;
use crate::dataflow::FlowAtLocation;
use crate::dataflow::MaybeInitializedPlaces;
-use either::Either;
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::infer::canonical::QueryRegionConstraints;
-use rustc::infer::outlives::env::RegionBoundPairs;
-use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
-use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc::mir::interpret::PanicInfo;
-use rustc::mir::tcx::PlaceTy;
-use rustc::mir::visit::{PlaceContext, Visitor, NonMutatingUseContext};
-use rustc::mir::*;
-use rustc::traits::query::type_op;
-use rustc::traits::query::type_op::custom::CustomTypeOp;
-use rustc::traits::query::{Fallible, NoSolution};
-use rustc::traits::{self, ObligationCause, PredicateObligations};
-use rustc::ty::adjustment::{PointerCast};
-use rustc::ty::cast::CastTy;
-use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::{Subst, SubstsRef, GenericArgKind, UserSubsts};
-use rustc::ty::{
- self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, UserType,
- CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
- UserTypeAnnotationIndex,
-};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_index::vec::{IndexVec, Idx};
-use rustc::ty::layout::VariantIdx;
-use std::rc::Rc;
-use std::{fmt, iter, mem};
-use syntax_pos::{Span, DUMMY_SP};
-
-use rustc_error_codes::*;
+use crate::dataflow::move_paths::MoveData;
+use crate::transform::promote_consts::should_suggest_const_in_array_repeat_expressions_attribute;
macro_rules! span_mirbug {
($context:expr, $elem:expr, $($message:tt)*) => ({
@@ -115,8 +117,8 @@
pub(crate) fn type_check<'tcx>(
infcx: &InferCtxt<'_, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
- body: &Body<'tcx>,
- promoted: &IndexVec<Promoted, Body<'tcx>>,
+ body: ReadOnlyBodyCache<'_, 'tcx>,
+ promoted: &IndexVec<Promoted, ReadOnlyBodyCache<'_, 'tcx>>,
mir_def_id: DefId,
universal_regions: &Rc<UniversalRegions<'tcx>>,
location_table: &LocationTable,
@@ -168,8 +170,17 @@
&mut borrowck_context,
&universal_region_relations,
|mut cx| {
- cx.equate_inputs_and_outputs(body, universal_regions, &normalized_inputs_and_output);
- liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table);
+ cx.equate_inputs_and_outputs(
+ &body,
+ universal_regions,
+ &normalized_inputs_and_output);
+ liveness::generate(
+ &mut cx,
+ body,
+ elements,
+ flow_inits,
+ move_data,
+ location_table);
translate_outlives_facts(cx.borrowck_context);
},
@@ -185,17 +196,17 @@
infcx: &'a InferCtxt<'a, 'tcx>,
mir_def_id: DefId,
param_env: ty::ParamEnv<'tcx>,
- body: &'a Body<'tcx>,
- promoted: &'a IndexVec<Promoted, Body<'tcx>>,
+ body: ReadOnlyBodyCache<'a, 'tcx>,
+ promoted: &'a IndexVec<Promoted, ReadOnlyBodyCache<'_, 'tcx>>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: ty::Region<'tcx>,
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
universal_region_relations: &'a UniversalRegionRelations<'tcx>,
mut extra: impl FnMut(&mut TypeChecker<'a, 'tcx>) -> R,
-) -> R where {
+) -> R {
let mut checker = TypeChecker::new(
infcx,
- body,
+ body.body(),
mir_def_id,
param_env,
region_bound_pairs,
@@ -204,7 +215,7 @@
universal_region_relations,
);
let errors_reported = {
- let mut verifier = TypeVerifier::new(&mut checker, body, promoted);
+ let mut verifier = TypeVerifier::new(&mut checker, body.body(), promoted);
verifier.visit_body(body);
verifier.errors_reported
};
@@ -261,7 +272,7 @@
struct TypeVerifier<'a, 'b, 'tcx> {
cx: &'a mut TypeChecker<'b, 'tcx>,
body: &'b Body<'tcx>,
- promoted: &'b IndexVec<Promoted, Body<'tcx>>,
+ promoted: &'b IndexVec<Promoted, ReadOnlyBodyCache<'b, 'tcx>>,
last_span: Span,
mir_def_id: DefId,
errors_reported: bool,
@@ -385,7 +396,7 @@
}
}
- fn visit_body(&mut self, body: &Body<'tcx>) {
+ fn visit_body(&mut self, body: ReadOnlyBodyCache<'_, 'tcx>) {
self.sanitize_type(&"return type", body.return_ty());
for local_decl in &body.local_decls {
self.sanitize_type(local_decl, local_decl.ty);
@@ -401,7 +412,7 @@
fn new(
cx: &'a mut TypeChecker<'b, 'tcx>,
body: &'b Body<'tcx>,
- promoted: &'b IndexVec<Promoted, Body<'tcx>>,
+ promoted: &'b IndexVec<Promoted, ReadOnlyBodyCache<'b, 'tcx>>,
) -> Self {
TypeVerifier {
body,
@@ -464,10 +475,10 @@
match kind {
StaticKind::Promoted(promoted, _) => {
if !self.errors_reported {
- let promoted_body = &self.promoted[*promoted];
- self.sanitize_promoted(promoted_body, location);
+ let promoted_body_cache = self.promoted[*promoted];
+ self.sanitize_promoted(promoted_body_cache, location);
- let promoted_ty = promoted_body.return_ty();
+ let promoted_ty = promoted_body_cache.return_ty();
check_err(self, place, promoted_ty, san_ty);
}
}
@@ -535,12 +546,16 @@
place_ty
}
- fn sanitize_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Location) {
+ fn sanitize_promoted(
+ &mut self,
+ promoted_body: ReadOnlyBodyCache<'b, 'tcx>,
+ location: Location
+ ) {
// Determine the constraints from the promoted MIR by running the type
// checker on the promoted MIR, then transfer the constraints back to
// the main MIR, changing the locations to the provided location.
- let parent_body = mem::replace(&mut self.body, promoted_body);
+ let parent_body = mem::replace(&mut self.body, promoted_body.body());
// Use new sets of constraints and closure bounds so that we can
// modify their locations.
@@ -548,7 +563,7 @@
let mut constraints = Default::default();
let mut closure_bounds = Default::default();
let mut liveness_constraints = LivenessValues::new(
- Rc::new(RegionValueElements::new(promoted_body)),
+ Rc::new(RegionValueElements::new(&promoted_body)),
);
// Don't try to add borrow_region facts for the promoted MIR
@@ -1361,7 +1376,12 @@
self.infcx.tcx
}
- fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
+ fn check_stmt(
+ &mut self,
+ body: ReadOnlyBodyCache<'_, 'tcx>,
+ stmt: &Statement<'tcx>,
+ location: Location)
+ {
debug!("check_stmt: {:?}", stmt);
let tcx = self.tcx();
match stmt.kind {
@@ -1393,9 +1413,9 @@
_ => ConstraintCategory::Assignment,
};
- let place_ty = place.ty(body, tcx).ty;
+ let place_ty = place.ty(*body, tcx).ty;
let place_ty = self.normalize(place_ty, location);
- let rv_ty = rv.ty(body, tcx);
+ let rv_ty = rv.ty(*body, tcx);
let rv_ty = self.normalize(rv_ty, location);
if let Err(terr) =
self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category)
@@ -1447,7 +1467,7 @@
ref place,
variant_index,
} => {
- let place_type = place.ty(body, tcx).ty;
+ let place_type = place.ty(*body, tcx).ty;
let adt = match place_type.kind {
ty::Adt(adt, _) if adt.is_enum() => adt,
_ => {
@@ -1469,7 +1489,7 @@
};
}
StatementKind::AscribeUserType(box(ref place, ref projection), variance) => {
- let place_ty = place.ty(body, tcx).ty;
+ let place_ty = place.ty(*body, tcx).ty;
if let Err(terr) = self.relate_type_and_user_type(
place_ty,
variance,
@@ -1972,12 +1992,17 @@
}
}
- fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
+ fn check_rvalue(
+ &mut self,
+ body: ReadOnlyBodyCache<'_, 'tcx>,
+ rvalue: &Rvalue<'tcx>,
+ location: Location)
+ {
let tcx = self.tcx();
match rvalue {
Rvalue::Aggregate(ak, ops) => {
- self.check_aggregate_rvalue(body, rvalue, ak, ops, location)
+ self.check_aggregate_rvalue(&body, rvalue, ak, ops, location)
}
Rvalue::Repeat(operand, len) => if *len > 1 {
@@ -1985,7 +2010,7 @@
// While this is located in `nll::typeck` this error is not an NLL error, it's
// a required check to make sure that repeated elements implement `Copy`.
let span = body.source_info(location).span;
- let ty = operand.ty(body, tcx);
+ let ty = operand.ty(*body, tcx);
if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) {
// To determine if `const_in_array_repeat_expressions` feature gate should
// be mentioned, need to check if the rvalue is promotable.
@@ -2039,7 +2064,7 @@
Rvalue::Cast(cast_kind, op, ty) => {
match cast_kind {
CastKind::Pointer(PointerCast::ReifyFnPointer) => {
- let fn_sig = op.ty(body, tcx).fn_sig(tcx);
+ let fn_sig = op.ty(*body, tcx).fn_sig(tcx);
// The type that we see in the fcx is like
// `foo::<'a, 'b>`, where `foo` is the path to a
@@ -2068,7 +2093,7 @@
}
CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => {
- let sig = match op.ty(body, tcx).kind {
+ let sig = match op.ty(*body, tcx).kind {
ty::Closure(def_id, substs) => {
substs.as_closure().sig_ty(def_id, tcx).fn_sig(tcx)
}
@@ -2094,7 +2119,7 @@
}
CastKind::Pointer(PointerCast::UnsafeFnPointer) => {
- let fn_sig = op.ty(body, tcx).fn_sig(tcx);
+ let fn_sig = op.ty(*body, tcx).fn_sig(tcx);
// The type that we see in the fcx is like
// `foo::<'a, 'b>`, where `foo` is the path to a
@@ -2126,7 +2151,7 @@
let &ty = ty;
let trait_ref = ty::TraitRef {
def_id: tcx.lang_items().coerce_unsized_trait().unwrap(),
- substs: tcx.mk_substs_trait(op.ty(body, tcx), &[ty.into()]),
+ substs: tcx.mk_substs_trait(op.ty(*body, tcx), &[ty.into()]),
};
self.prove_trait_ref(
@@ -2137,7 +2162,7 @@
}
CastKind::Pointer(PointerCast::MutToConstPointer) => {
- let ty_from = match op.ty(body, tcx).kind {
+ let ty_from = match op.ty(*body, tcx).kind {
ty::RawPtr(ty::TypeAndMut {
ty: ty_from,
mutbl: hir::Mutability::Mutable,
@@ -2185,7 +2210,7 @@
}
CastKind::Pointer(PointerCast::ArrayToPointer) => {
- let ty_from = op.ty(body, tcx);
+ let ty_from = op.ty(*body, tcx);
let opt_ty_elem = match ty_from.kind {
ty::RawPtr(
@@ -2247,7 +2272,7 @@
}
CastKind::Misc => {
- let ty_from = op.ty(body, tcx);
+ let ty_from = op.ty(*body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(ty);
match (cast_ty_from, cast_ty_to) {
@@ -2305,7 +2330,7 @@
}
Rvalue::Ref(region, _borrow_kind, borrowed_place) => {
- self.add_reborrow_constraint(body, location, region, borrowed_place);
+ self.add_reborrow_constraint(&body, location, region, borrowed_place);
}
Rvalue::BinaryOp(BinOp::Eq, left, right)
@@ -2314,9 +2339,9 @@
| Rvalue::BinaryOp(BinOp::Le, left, right)
| Rvalue::BinaryOp(BinOp::Gt, left, right)
| Rvalue::BinaryOp(BinOp::Ge, left, right) => {
- let ty_left = left.ty(body, tcx);
+ let ty_left = left.ty(*body, tcx);
if let ty::RawPtr(_) | ty::FnPtr(_) = ty_left.kind {
- let ty_right = right.ty(body, tcx);
+ let ty_right = right.ty(*body, tcx);
let common_ty = self.infcx.next_ty_var(
TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
@@ -2741,12 +2766,12 @@
})
}
- fn typeck_mir(&mut self, body: &Body<'tcx>) {
+ fn typeck_mir(&mut self, body: ReadOnlyBodyCache<'_, 'tcx>) {
self.last_span = body.span;
debug!("run_on_mir: {:?}", body.span);
for (local, local_decl) in body.local_decls.iter_enumerated() {
- self.check_local(body, local, local_decl);
+ self.check_local(&body, local, local_decl);
}
for (block, block_data) in body.basic_blocks().iter_enumerated() {
@@ -2762,8 +2787,8 @@
location.statement_index += 1;
}
- self.check_terminator(body, block_data.terminator(), location);
- self.check_iscleanup(body, block_data);
+ self.check_terminator(&body, block_data.terminator(), location);
+ self.check_iscleanup(&body, block_data);
}
}
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index fbedac4..9ad15fc 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -312,9 +312,9 @@
match self.defining_ty {
DefiningTy::Closure(def_id, substs) => {
err.note(&format!(
- "defining type: {:?} with closure substs {:#?}",
- def_id,
- &substs[..]
+ "defining type: {} with closure substs {:#?}",
+ tcx.def_path_str_with_substs(def_id, substs),
+ &substs[tcx.generics_of(def_id).parent_count..],
));
// FIXME: It'd be nice to print the late-bound regions
@@ -332,9 +332,9 @@
}
DefiningTy::Generator(def_id, substs, _) => {
err.note(&format!(
- "defining type: {:?} with generator substs {:#?}",
- def_id,
- &substs[..]
+ "defining type: {} with generator substs {:#?}",
+ tcx.def_path_str_with_substs(def_id, substs),
+ &substs[tcx.generics_of(def_id).parent_count..],
));
// FIXME: As above, we'd like to print out the region
@@ -350,16 +350,14 @@
}
DefiningTy::FnDef(def_id, substs) => {
err.note(&format!(
- "defining type: {:?} with substs {:#?}",
- def_id,
- &substs[..]
+ "defining type: {}",
+ tcx.def_path_str_with_substs(def_id, substs),
));
}
DefiningTy::Const(def_id, substs) => {
err.note(&format!(
- "defining constant type: {:?} with substs {:#?}",
- def_id,
- &substs[..]
+ "defining constant type: {}",
+ tcx.def_path_str_with_substs(def_id, substs),
));
}
}
diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs
index 57833ca..b58bf73 100644
--- a/src/librustc_mir/borrow_check/prefixes.rs
+++ b/src/librustc_mir/borrow_check/prefixes.rs
@@ -11,7 +11,7 @@
use rustc::hir;
use rustc::ty::{self, TyCtxt};
-use rustc::mir::{Body, Place, PlaceBase, PlaceRef, ProjectionElem};
+use rustc::mir::{Place, PlaceBase, PlaceRef, ProjectionElem, ReadOnlyBodyCache};
pub trait IsPrefixOf<'cx, 'tcx> {
fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool;
@@ -26,7 +26,7 @@
}
pub(super) struct Prefixes<'cx, 'tcx> {
- body: &'cx Body<'tcx>,
+ body: ReadOnlyBodyCache<'cx, 'tcx>,
tcx: TyCtxt<'tcx>,
kind: PrefixSet,
next: Option<PlaceRef<'cx, 'tcx>>,
@@ -143,7 +143,7 @@
// derefs, except we stop at the deref of a shared
// reference.
- let ty = Place::ty_from(cursor.base, proj_base, self.body, self.tcx).ty;
+ let ty = Place::ty_from(cursor.base, proj_base, *self.body, self.tcx).ty;
match ty.kind {
ty::RawPtr(_) |
ty::Ref(
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index c893d6f..e320811 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -680,7 +680,7 @@
}
})();
- if no_overlap == Some(true) {
+ if let Some(true) = no_overlap {
// Testing range does not overlap with pattern range,
// so the pattern can be matched only if this test fails.
Some(1)
@@ -690,7 +690,7 @@
}
(&TestKind::Range(range), &PatKind::Constant { value }) => {
- if self.const_range_contains(range, value) == Some(false) {
+ if let Some(false) = self.const_range_contains(range, value) {
// `value` is not contained in the testing range,
// so `value` can be matched only if this test fails.
Some(1)
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 91ddd5a..b84461d 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -24,7 +24,7 @@
use super::lints;
/// Construct the MIR for a given `DefId`.
-pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> {
+pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyCache<'_> {
let id = tcx.hir().as_local_hir_id(def_id).unwrap();
// Figure out what primary body this item has.
@@ -196,6 +196,8 @@
lints::check(tcx, &body, def_id);
+ let mut body = BodyCache::new(body);
+ body.ensure_predecessors();
body
})
}
@@ -309,7 +311,6 @@
/// The vector of all scopes that we have created thus far;
/// we track this for debuginfo later.
source_scopes: IndexVec<SourceScope, SourceScopeData>,
- source_scope_local_data: IndexVec<SourceScope, SourceScopeLocalData>,
source_scope: SourceScope,
/// The guard-context: each time we build the guard expression for
@@ -704,7 +705,6 @@
block_context: BlockContext::new(),
source_scopes: IndexVec::new(),
source_scope: OUTERMOST_SOURCE_SCOPE,
- source_scope_local_data: IndexVec::new(),
guard_context: vec![],
push_unsafe_count: 0,
unpushed_unsafe: safety,
@@ -741,7 +741,6 @@
Body::new(
self.cfg.basic_blocks,
self.source_scopes,
- ClearCrossCrate::Set(self.source_scope_local_data),
self.local_decls,
self.canonical_user_type_annotations,
self.arg_count,
@@ -942,7 +941,11 @@
self.hir.root_lint_level
);
let parent_root = tcx.maybe_lint_level_root_bounded(
- self.source_scope_local_data[original_source_scope].lint_root,
+ self.source_scopes[original_source_scope]
+ .local_data
+ .as_ref()
+ .assert_crate_local()
+ .lint_root,
self.hir.root_lint_level,
);
if current_root != parent_root {
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index bb25b28..00a30af 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -436,7 +436,11 @@
// We estimate the true lint roots here to avoid creating a lot of source scopes.
let parent_root = tcx.maybe_lint_level_root_bounded(
- self.source_scope_local_data[source_scope].lint_root,
+ self.source_scopes[source_scope]
+ .local_data
+ .as_ref()
+ .assert_crate_local()
+ .lint_root,
self.hir.root_lint_level,
);
let current_root = tcx.maybe_lint_level_root_bounded(
@@ -654,23 +658,22 @@
let parent = self.source_scope;
debug!("new_source_scope({:?}, {:?}, {:?}) - parent({:?})={:?}",
span, lint_level, safety,
- parent, self.source_scope_local_data.get(parent));
- let scope = self.source_scopes.push(SourceScopeData {
- span,
- parent_scope: Some(parent),
- });
+ parent, self.source_scopes.get(parent));
let scope_local_data = SourceScopeLocalData {
lint_root: if let LintLevel::Explicit(lint_root) = lint_level {
lint_root
} else {
- self.source_scope_local_data[parent].lint_root
+ self.source_scopes[parent].local_data.as_ref().assert_crate_local().lint_root
},
safety: safety.unwrap_or_else(|| {
- self.source_scope_local_data[parent].safety
+ self.source_scopes[parent].local_data.as_ref().assert_crate_local().safety
})
};
- self.source_scope_local_data.push(scope_local_data);
- scope
+ self.source_scopes.push(SourceScopeData {
+ span,
+ parent_scope: Some(parent),
+ local_data: ClearCrossCrate::Set(scope_local_data),
+ })
}
/// Given a span and the current source scope, make a SourceInfo.
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 0967b25..968a8a7 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -23,7 +23,7 @@
use crate::interpret::{self,
PlaceTy, MPlaceTy, OpTy, ImmTy, Immediate, Scalar, Pointer,
RawConst, ConstValue, Machine,
- InterpResult, InterpErrorInfo, GlobalId, InterpCx, StackPopCleanup,
+ InterpResult, InterpErrorInfo, GlobalId, InterpCx, StackPopCleanup, AssertMessage,
Allocation, AllocId, MemoryKind, Memory,
snapshot, RefTracking, intern_const_alloc_recursive,
};
@@ -328,20 +328,32 @@
false // for now, we don't enforce validity
}
- fn find_fn(
+ fn find_mir_or_eval_fn(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx>],
ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
_unwind: Option<mir::BasicBlock> // unwinding is not supported in consts
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
- debug!("eval_fn_call: {:?}", instance);
+ debug!("find_mir_or_eval_fn: {:?}", instance);
+
// Only check non-glue functions
if let ty::InstanceDef::Item(def_id) = instance.def {
// Execution might have wandered off into other crates, so we cannot do a stability-
// sensitive check here. But we can at least rule out functions that are not const
// at all.
- if !ecx.tcx.is_const_fn_raw(def_id) {
+ if ecx.tcx.is_const_fn_raw(def_id) {
+ // If this function is a `const fn` then as an optimization we can query this
+ // evaluation immediately.
+ //
+ // For the moment we only do this for functions which take no arguments
+ // (or all arguments are ZSTs) so that we don't memoize too much.
+ if args.iter().all(|a| a.layout.is_zst()) {
+ let gid = GlobalId { instance, promoted: None };
+ ecx.eval_const_fn_call(gid, ret)?;
+ return Ok(None);
+ }
+ } else {
// Some functions we support even if they are non-const -- but avoid testing
// that for const fn! We certainly do *not* want to actually call the fn
// though, so be sure we return here.
@@ -354,7 +366,7 @@
}
// This is a const fn. Call it.
Ok(Some(match ecx.load_mir(instance.def, None) {
- Ok(body) => body,
+ Ok(body) => body.body(),
Err(err) => {
if let err_unsup!(NoMirFor(ref path)) = err.kind {
return Err(
@@ -395,6 +407,40 @@
)
}
+ fn assert_panic(
+ ecx: &mut InterpCx<'mir, 'tcx, Self>,
+ _span: Span,
+ msg: &AssertMessage<'tcx>,
+ _unwind: Option<mir::BasicBlock>,
+ ) -> InterpResult<'tcx> {
+ use rustc::mir::interpret::PanicInfo::*;
+ Err(match msg {
+ BoundsCheck { ref len, ref index } => {
+ let len = ecx
+ .read_immediate(ecx.eval_operand(len, None)?)
+ .expect("can't eval len")
+ .to_scalar()?
+ .to_machine_usize(&*ecx)?;
+ let index = ecx
+ .read_immediate(ecx.eval_operand(index, None)?)
+ .expect("can't eval index")
+ .to_scalar()?
+ .to_machine_usize(&*ecx)?;
+ err_panic!(BoundsCheck { len, index })
+ }
+ Overflow(op) => err_panic!(Overflow(*op)),
+ OverflowNeg => err_panic!(OverflowNeg),
+ DivisionByZero => err_panic!(DivisionByZero),
+ RemainderByZero => err_panic!(RemainderByZero),
+ ResumedAfterReturn(generator_kind)
+ => err_panic!(ResumedAfterReturn(*generator_kind)),
+ ResumedAfterPanic(generator_kind)
+ => err_panic!(ResumedAfterPanic(*generator_kind)),
+ Panic { .. } => bug!("`Panic` variant cannot occur in MIR"),
+ }
+ .into())
+ }
+
fn ptr_to_int(
_mem: &Memory<'mir, 'tcx, Self>,
_ptr: Pointer,
@@ -423,7 +469,7 @@
}
#[inline(always)]
- fn tag_allocation<'b>(
+ fn init_allocation_extra<'b>(
_memory_extra: &(),
_id: AllocId,
alloc: Cow<'b, Allocation>,
@@ -518,7 +564,7 @@
tcx.type_of(tcx.require_lang_item(PanicLocationLangItem, None))
.subst(tcx, tcx.mk_substs([tcx.lifetimes.re_static.into()].iter())),
);
- let loc_place = ecx.alloc_caller_location(file, line, col).unwrap();
+ let loc_place = ecx.alloc_caller_location(file, line, col);
intern_const_alloc_recursive(&mut ecx, None, loc_place).unwrap();
let loc_const = ty::Const {
ty: loc_ty,
@@ -697,7 +743,7 @@
let res = ecx.load_mir(cid.instance.def, cid.promoted);
res.and_then(
- |body| eval_body_using_ecx(&mut ecx, cid, body)
+ |body| eval_body_using_ecx(&mut ecx, cid, body.body())
).and_then(|place| {
Ok(RawConst {
alloc_id: place.ptr.assert_ptr().alloc_id,
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 402e5ae..7e7652c 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -98,7 +98,7 @@
// Add successor BBs to the work list, if necessary.
let bb_data = &body[bb];
assert!(hi == bb_data.statements.len());
- for &succ_bb in bb_data.terminator.as_ref().unwrap().successors() {
+ for &succ_bb in bb_data.terminator().successors() {
visited.entry(succ_bb)
.and_modify(|lo| {
// `succ_bb` has been seen before. If it wasn't
@@ -153,8 +153,8 @@
}
Borrows {
- tcx: tcx,
- body: body,
+ tcx,
+ body,
param_env,
borrow_set: borrow_set.clone(),
borrows_out_of_scope_at_location,
diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs
index 6f860d0..0fb912b 100644
--- a/src/librustc_mir/dataflow/impls/mod.rs
+++ b/src/librustc_mir/dataflow/impls/mod.rs
@@ -71,7 +71,7 @@
impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
- MaybeInitializedPlaces { tcx: tcx, body: body, mdpe: mdpe }
+ MaybeInitializedPlaces { tcx, body, mdpe }
}
}
@@ -122,7 +122,7 @@
impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
- MaybeUninitializedPlaces { tcx: tcx, body: body, mdpe: mdpe }
+ MaybeUninitializedPlaces { tcx, body, mdpe }
}
}
@@ -172,7 +172,7 @@
impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
- DefinitelyInitializedPlaces { tcx: tcx, body: body, mdpe: mdpe }
+ DefinitelyInitializedPlaces { tcx, body, mdpe }
}
}
@@ -217,7 +217,7 @@
impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
- EverInitializedPlaces { tcx: tcx, body: body, mdpe: mdpe }
+ EverInitializedPlaces { tcx, body, mdpe }
}
}
diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs
index 1b81032..c4b97d1 100644
--- a/src/librustc_mir/dataflow/impls/storage_liveness.rs
+++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs
@@ -75,24 +75,26 @@
/// Dataflow analysis that determines whether each local requires storage at a
/// given location; i.e. whether its storage can go away without being observed.
pub struct RequiresStorage<'mir, 'tcx> {
- body: &'mir Body<'tcx>,
+ body: ReadOnlyBodyCache<'mir, 'tcx>,
borrowed_locals:
RefCell<DataflowResultsRefCursor<'mir, 'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>>,
}
impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> {
pub fn new(
- body: &'mir Body<'tcx>,
+ body: ReadOnlyBodyCache<'mir, 'tcx>,
borrowed_locals: &'mir DataflowResults<'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>,
) -> Self {
RequiresStorage {
body,
- borrowed_locals: RefCell::new(DataflowResultsCursor::new(borrowed_locals, body)),
+ borrowed_locals: RefCell::new(
+ DataflowResultsCursor::new(borrowed_locals, body.body())
+ ),
}
}
pub fn body(&self) -> &Body<'tcx> {
- self.body
+ &self.body
}
}
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index f2c5bf1..37a9381 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -425,16 +425,12 @@
}
/// This computes `S(constructor, self)`. See top of the file for explanations.
- fn specialize_constructor<'a, 'q>(
+ fn specialize_constructor(
&self,
- cx: &mut MatchCheckCtxt<'a, 'tcx>,
+ cx: &mut MatchCheckCtxt<'p, 'tcx>,
constructor: &Constructor<'tcx>,
- ctor_wild_subpatterns: &[&'q Pat<'tcx>],
- ) -> Option<PatStack<'q, 'tcx>>
- where
- 'a: 'q,
- 'p: 'q,
- {
+ ctor_wild_subpatterns: &'p [Pat<'tcx>],
+ ) -> Option<PatStack<'p, 'tcx>> {
let new_heads = specialize_one_pattern(cx, self.head(), constructor, ctor_wild_subpatterns);
new_heads.map(|mut new_head| {
new_head.0.extend_from_slice(&self.0[1..]);
@@ -459,6 +455,7 @@
}
/// A 2D matrix.
+#[derive(Clone)]
pub struct Matrix<'p, 'tcx>(Vec<PatStack<'p, 'tcx>>);
impl<'p, 'tcx> Matrix<'p, 'tcx> {
@@ -486,16 +483,12 @@
}
/// This computes `S(constructor, self)`. See top of the file for explanations.
- fn specialize_constructor<'a, 'q>(
+ fn specialize_constructor(
&self,
- cx: &mut MatchCheckCtxt<'a, 'tcx>,
+ cx: &mut MatchCheckCtxt<'p, 'tcx>,
constructor: &Constructor<'tcx>,
- ctor_wild_subpatterns: &[&'q Pat<'tcx>],
- ) -> Matrix<'q, 'tcx>
- where
- 'a: 'q,
- 'p: 'q,
- {
+ ctor_wild_subpatterns: &'p [Pat<'tcx>],
+ ) -> Matrix<'p, 'tcx> {
self.0
.iter()
.filter_map(|r| r.specialize_constructor(cx, constructor, ctor_wild_subpatterns))
@@ -1033,17 +1026,19 @@
}
#[derive(Clone, Debug)]
-pub enum Usefulness<'tcx> {
- Useful,
+pub enum Usefulness<'tcx, 'p> {
+ /// Carries a list of unreachable subpatterns. Used only in the presence of or-patterns.
+ Useful(Vec<&'p Pat<'tcx>>),
+ /// Carries a list of witnesses of non-exhaustiveness.
UsefulWithWitness(Vec<Witness<'tcx>>),
NotUseful,
}
-impl<'tcx> Usefulness<'tcx> {
+impl<'tcx, 'p> Usefulness<'tcx, 'p> {
fn new_useful(preference: WitnessPreference) -> Self {
match preference {
ConstructWitness => UsefulWithWitness(vec![Witness(vec![])]),
- LeaveOutWitness => Useful,
+ LeaveOutWitness => Useful(vec![]),
}
}
@@ -1604,13 +1599,13 @@
/// relation to preceding patterns, it is not reachable) and exhaustiveness
/// checking (if a wildcard pattern is useful in relation to a matrix, the
/// matrix isn't exhaustive).
-pub fn is_useful<'p, 'a, 'tcx>(
- cx: &mut MatchCheckCtxt<'a, 'tcx>,
+pub fn is_useful<'p, 'tcx>(
+ cx: &mut MatchCheckCtxt<'p, 'tcx>,
matrix: &Matrix<'p, 'tcx>,
- v: &PatStack<'_, 'tcx>,
+ v: &PatStack<'p, 'tcx>,
witness_preference: WitnessPreference,
hir_id: HirId,
-) -> Usefulness<'tcx> {
+) -> Usefulness<'tcx, 'p> {
let &Matrix(ref rows) = matrix;
debug!("is_useful({:#?}, {:#?})", matrix, v);
@@ -1631,11 +1626,26 @@
// If the first pattern is an or-pattern, expand it.
if let Some(vs) = v.expand_or_pat() {
- return vs
- .into_iter()
- .map(|v| is_useful(cx, matrix, &v, witness_preference, hir_id))
- .find(|result| result.is_useful())
- .unwrap_or(NotUseful);
+ // We need to push the already-seen patterns into the matrix in order to detect redundant
+ // branches like `Some(_) | Some(0)`. We also keep track of the unreachable subpatterns.
+ let mut matrix = matrix.clone();
+ let mut unreachable_pats = Vec::new();
+ let mut any_is_useful = false;
+ for v in vs {
+ let res = is_useful(cx, &matrix, &v, witness_preference, hir_id);
+ match res {
+ Useful(pats) => {
+ any_is_useful = true;
+ unreachable_pats.extend(pats);
+ }
+ NotUseful => unreachable_pats.push(v.head()),
+ UsefulWithWitness(_) => {
+ bug!("Encountered or-pat in `v` during exhaustiveness checking")
+ }
+ }
+ matrix.push(v);
+ }
+ return if any_is_useful { Useful(unreachable_pats) } else { NotUseful };
}
let (ty, span) = matrix
@@ -1768,21 +1778,21 @@
/// A shorthand for the `U(S(c, P), S(c, q))` operation from the paper. I.e., `is_useful` applied
/// to the specialised version of both the pattern matrix `P` and the new pattern `q`.
-fn is_useful_specialized<'p, 'a, 'tcx>(
- cx: &mut MatchCheckCtxt<'a, 'tcx>,
+fn is_useful_specialized<'p, 'tcx>(
+ cx: &mut MatchCheckCtxt<'p, 'tcx>,
matrix: &Matrix<'p, 'tcx>,
- v: &PatStack<'_, 'tcx>,
+ v: &PatStack<'p, 'tcx>,
ctor: Constructor<'tcx>,
lty: Ty<'tcx>,
witness_preference: WitnessPreference,
hir_id: HirId,
-) -> Usefulness<'tcx> {
+) -> Usefulness<'tcx, 'p> {
debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty);
- let ctor_wild_subpatterns_owned: Vec<_> = ctor.wildcard_subpatterns(cx, lty);
- let ctor_wild_subpatterns: Vec<_> = ctor_wild_subpatterns_owned.iter().collect();
- let matrix = matrix.specialize_constructor(cx, &ctor, &ctor_wild_subpatterns);
- v.specialize_constructor(cx, &ctor, &ctor_wild_subpatterns)
+ let ctor_wild_subpatterns =
+ cx.pattern_arena.alloc_from_iter(ctor.wildcard_subpatterns(cx, lty));
+ let matrix = matrix.specialize_constructor(cx, &ctor, ctor_wild_subpatterns);
+ v.specialize_constructor(cx, &ctor, ctor_wild_subpatterns)
.map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id))
.map(|u| u.apply_constructor(cx, &ctor, lty))
.unwrap_or(NotUseful)
@@ -2250,13 +2260,13 @@
if intersects { Some(()) } else { None }
}
-fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
- cx: &mut MatchCheckCtxt<'a, 'tcx>,
+fn patterns_for_variant<'p, 'tcx>(
+ cx: &mut MatchCheckCtxt<'p, 'tcx>,
subpatterns: &'p [FieldPat<'tcx>],
- ctor_wild_subpatterns: &[&'p Pat<'tcx>],
+ ctor_wild_subpatterns: &'p [Pat<'tcx>],
is_non_exhaustive: bool,
) -> PatStack<'p, 'tcx> {
- let mut result = SmallVec::from_slice(ctor_wild_subpatterns);
+ let mut result: SmallVec<_> = ctor_wild_subpatterns.iter().collect();
for subpat in subpatterns {
if !is_non_exhaustive || !cx.is_uninhabited(subpat.pattern.ty) {
@@ -2280,11 +2290,11 @@
/// different patterns.
/// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
/// fields filled with wild patterns.
-fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
- cx: &mut MatchCheckCtxt<'a, 'tcx>,
- pat: &'q Pat<'tcx>,
+fn specialize_one_pattern<'p, 'tcx>(
+ cx: &mut MatchCheckCtxt<'p, 'tcx>,
+ pat: &'p Pat<'tcx>,
constructor: &Constructor<'tcx>,
- ctor_wild_subpatterns: &[&'p Pat<'tcx>],
+ ctor_wild_subpatterns: &'p [Pat<'tcx>],
) -> Option<PatStack<'p, 'tcx>> {
if let NonExhaustive = constructor {
// Only a wildcard pattern can match the special extra constructor
@@ -2294,9 +2304,7 @@
let result = match *pat.kind {
PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
- PatKind::Binding { .. } | PatKind::Wild => {
- Some(PatStack::from_slice(ctor_wild_subpatterns))
- }
+ PatKind::Binding { .. } | PatKind::Wild => Some(ctor_wild_subpatterns.iter().collect()),
PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
let ref variant = adt_def.variants[variant_index];
@@ -2406,7 +2414,6 @@
.chain(
ctor_wild_subpatterns
.iter()
- .map(|p| *p)
.skip(prefix.len())
.take(slice_count)
.chain(suffix.iter()),
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 30586e9..737af3e 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -139,39 +139,22 @@
MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |ref mut cx| {
let mut have_errors = false;
- let inlined_arms: Vec<(Vec<_>, _)> = arms
+ let inlined_arms: Vec<_> = arms
.iter()
.map(|arm| {
- (
- // HACK(or_patterns; Centril | dlrobertson): Remove this and
- // correctly handle exhaustiveness checking for nested or-patterns.
- match &arm.pat.kind {
- hir::PatKind::Or(pats) => pats,
- _ => std::slice::from_ref(&arm.pat),
- }
- .iter()
- .map(|pat| {
- let mut patcx = PatCtxt::new(
- self.tcx,
- self.param_env.and(self.identity_substs),
- self.tables,
- );
- patcx.include_lint_checks();
- let pattern = cx
- .pattern_arena
- .alloc(expand_pattern(cx, patcx.lower_pattern(&pat)))
- as &_;
- if !patcx.errors.is_empty() {
- patcx.report_inlining_errors(pat.span);
- have_errors = true;
- }
- (pattern, &**pat)
- })
- .collect(),
- arm.guard.as_ref().map(|g| match g {
- hir::Guard::If(ref e) => &**e,
- }),
- )
+ let mut patcx = PatCtxt::new(
+ self.tcx,
+ self.param_env.and(self.identity_substs),
+ self.tables,
+ );
+ patcx.include_lint_checks();
+ let pattern: &_ =
+ cx.pattern_arena.alloc(expand_pattern(cx, patcx.lower_pattern(&arm.pat)));
+ if !patcx.errors.is_empty() {
+ patcx.report_inlining_errors(arm.pat.span);
+ have_errors = true;
+ }
+ (pattern, &*arm.pat, arm.guard.is_some())
})
.collect();
@@ -181,7 +164,7 @@
}
// Fourth, check for unreachable arms.
- check_arms(cx, &inlined_arms, source);
+ let matrix = check_arms(cx, &inlined_arms, source);
// Then, if the match has no arms, check whether the scrutinee
// is uninhabited.
@@ -248,12 +231,6 @@
return;
}
- let matrix: Matrix<'_, '_> = inlined_arms
- .iter()
- .filter(|&&(_, guard)| guard.is_none())
- .flat_map(|arm| &arm.0)
- .map(|pat| PatStack::from_pattern(pat.0))
- .collect();
let scrut_ty = self.tables.node_type(scrut.hir_id);
check_exhaustive(cx, scrut_ty, scrut.span, &matrix, scrut.hir_id);
})
@@ -267,8 +244,8 @@
patcx.include_lint_checks();
let pattern = patcx.lower_pattern(pat);
let pattern_ty = pattern.ty;
- let pattern = expand_pattern(cx, pattern);
- let pats: Matrix<'_, '_> = vec![PatStack::from_pattern(&pattern)].into_iter().collect();
+ let pattern = cx.pattern_arena.alloc(expand_pattern(cx, pattern));
+ let pats: Matrix<'_, '_> = vec![PatStack::from_pattern(pattern)].into_iter().collect();
let witnesses = match check_not_useful(cx, pattern_ty, &pats, pat.hir_id) {
Ok(_) => return,
@@ -403,113 +380,120 @@
}
// Check for unreachable patterns
-fn check_arms<'tcx>(
- cx: &mut MatchCheckCtxt<'_, 'tcx>,
- arms: &[(Vec<(&super::Pat<'tcx>, &hir::Pat)>, Option<&hir::Expr>)],
+fn check_arms<'p, 'tcx>(
+ cx: &mut MatchCheckCtxt<'p, 'tcx>,
+ arms: &[(&'p super::Pat<'tcx>, &hir::Pat, bool)],
source: hir::MatchSource,
-) {
+) -> Matrix<'p, 'tcx> {
let mut seen = Matrix::empty();
let mut catchall = None;
- for (arm_index, &(ref pats, guard)) in arms.iter().enumerate() {
- for &(pat, hir_pat) in pats {
- let v = PatStack::from_pattern(pat);
+ for (arm_index, (pat, hir_pat, has_guard)) in arms.iter().enumerate() {
+ let v = PatStack::from_pattern(pat);
- match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id) {
- NotUseful => {
- match source {
- hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar => {
- bug!()
- }
- hir::MatchSource::IfLetDesugar { .. } => {
- cx.tcx.lint_hir(
- lint::builtin::IRREFUTABLE_LET_PATTERNS,
- hir_pat.hir_id,
- pat.span,
- "irrefutable if-let pattern",
- );
- }
+ match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id) {
+ NotUseful => {
+ match source {
+ hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar => bug!(),
- hir::MatchSource::WhileLetDesugar => {
- // check which arm we're on.
- match arm_index {
- // The arm with the user-specified pattern.
- 0 => {
- cx.tcx.lint_hir(
- lint::builtin::UNREACHABLE_PATTERNS,
- hir_pat.hir_id,
- pat.span,
- "unreachable pattern",
- );
- }
- // The arm with the wildcard pattern.
- 1 => {
- cx.tcx.lint_hir(
- lint::builtin::IRREFUTABLE_LET_PATTERNS,
- hir_pat.hir_id,
- pat.span,
- "irrefutable while-let pattern",
- );
- }
- _ => bug!(),
+ hir::MatchSource::IfLetDesugar { .. } | hir::MatchSource::WhileLetDesugar => {
+ // check which arm we're on.
+ match arm_index {
+ // The arm with the user-specified pattern.
+ 0 => {
+ cx.tcx.lint_hir(
+ lint::builtin::UNREACHABLE_PATTERNS,
+ hir_pat.hir_id,
+ pat.span,
+ "unreachable pattern",
+ );
}
- }
-
- hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => {
- let mut err = cx.tcx.struct_span_lint_hir(
- lint::builtin::UNREACHABLE_PATTERNS,
- hir_pat.hir_id,
- pat.span,
- "unreachable pattern",
- );
- // if we had a catchall pattern, hint at that
- if let Some(catchall) = catchall {
- err.span_label(pat.span, "unreachable pattern");
- err.span_label(catchall, "matches any value");
+ // The arm with the wildcard pattern.
+ 1 => {
+ let msg = match source {
+ hir::MatchSource::IfLetDesugar { .. } => {
+ "irrefutable if-let pattern"
+ }
+ hir::MatchSource::WhileLetDesugar => {
+ "irrefutable while-let pattern"
+ }
+ _ => bug!(),
+ };
+ cx.tcx.lint_hir(
+ lint::builtin::IRREFUTABLE_LET_PATTERNS,
+ hir_pat.hir_id,
+ pat.span,
+ msg,
+ );
}
- err.emit();
+ _ => bug!(),
}
-
- // Unreachable patterns in try and await expressions occur when one of
- // the arms are an uninhabited type. Which is OK.
- hir::MatchSource::AwaitDesugar | hir::MatchSource::TryDesugar => {}
}
+
+ hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => {
+ let mut err = cx.tcx.struct_span_lint_hir(
+ lint::builtin::UNREACHABLE_PATTERNS,
+ hir_pat.hir_id,
+ pat.span,
+ "unreachable pattern",
+ );
+ // if we had a catchall pattern, hint at that
+ if let Some(catchall) = catchall {
+ err.span_label(pat.span, "unreachable pattern");
+ err.span_label(catchall, "matches any value");
+ }
+ err.emit();
+ }
+
+ // Unreachable patterns in try and await expressions occur when one of
+ // the arms are an uninhabited type. Which is OK.
+ hir::MatchSource::AwaitDesugar | hir::MatchSource::TryDesugar => {}
}
- Useful => (),
- UsefulWithWitness(_) => bug!(),
}
- if guard.is_none() {
- seen.push(v);
- if catchall.is_none() && pat_is_catchall(hir_pat) {
- catchall = Some(pat.span);
+ Useful(unreachable_subpatterns) => {
+ for pat in unreachable_subpatterns {
+ cx.tcx.lint_hir(
+ lint::builtin::UNREACHABLE_PATTERNS,
+ hir_pat.hir_id,
+ pat.span,
+ "unreachable pattern",
+ );
}
}
+ UsefulWithWitness(_) => bug!(),
+ }
+ if !has_guard {
+ seen.push(v);
+ if catchall.is_none() && pat_is_catchall(hir_pat) {
+ catchall = Some(pat.span);
+ }
}
}
+ seen
}
-fn check_not_useful(
- cx: &mut MatchCheckCtxt<'_, 'tcx>,
+fn check_not_useful<'p, 'tcx>(
+ cx: &mut MatchCheckCtxt<'p, 'tcx>,
ty: Ty<'tcx>,
- matrix: &Matrix<'_, 'tcx>,
+ matrix: &Matrix<'p, 'tcx>,
hir_id: HirId,
) -> Result<(), Vec<super::Pat<'tcx>>> {
- let wild_pattern = super::Pat::wildcard_from_ty(ty);
- match is_useful(cx, matrix, &PatStack::from_pattern(&wild_pattern), ConstructWitness, hir_id) {
+ let wild_pattern = cx.pattern_arena.alloc(super::Pat::wildcard_from_ty(ty));
+ match is_useful(cx, matrix, &PatStack::from_pattern(wild_pattern), ConstructWitness, hir_id) {
NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable.
UsefulWithWitness(pats) => Err(if pats.is_empty() {
- vec![wild_pattern]
+ bug!("Exhaustiveness check returned no witnesses")
} else {
pats.into_iter().map(|w| w.single_pattern()).collect()
}),
- Useful => bug!(),
+ Useful(_) => bug!(),
}
}
-fn check_exhaustive<'tcx>(
- cx: &mut MatchCheckCtxt<'_, 'tcx>,
+fn check_exhaustive<'p, 'tcx>(
+ cx: &mut MatchCheckCtxt<'p, 'tcx>,
scrut_ty: Ty<'tcx>,
sp: Span,
- matrix: &Matrix<'_, 'tcx>,
+ matrix: &Matrix<'p, 'tcx>,
hir_id: HirId,
) {
let witnesses = match check_not_useful(cx, scrut_ty, matrix, hir_id) {
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 92c7178..0086c3b 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -1154,13 +1154,7 @@
) -> Option<Ordering> {
trace!("compare_const_vals: {:?}, {:?}", a, b);
- let from_bool = |v: bool| {
- if v {
- Some(Ordering::Equal)
- } else {
- None
- }
- };
+ let from_bool = |v: bool| v.then_some(Ordering::Equal);
let fallback = || from_bool(a == b);
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 1fb8b3c..e9602ec 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -55,7 +55,7 @@
).ok_or_else(|| err_inval!(TooGeneric))?;
let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
- self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?;
+ self.write_scalar(fn_ptr, dest)?;
}
_ => bug!("reify fn pointer on {:?}", src.layout.ty),
}
@@ -88,8 +88,7 @@
ty::ClosureKind::FnOnce,
);
let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
- let val = Immediate::Scalar(Scalar::Ptr(fn_ptr.into()).into());
- self.write_immediate(val, dest)?;
+ self.write_scalar(fn_ptr, dest)?;
}
_ => bug!("closure fn pointer on {:?}", src.layout.ty),
}
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 228e5ca..9af47f3 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -164,6 +164,20 @@
}
}
+impl<'mir, 'tcx, Tag, Extra> Frame<'mir, 'tcx, Tag, Extra> {
+ /// Return the `SourceInfo` of the current instruction.
+ pub fn current_source_info(&self) -> Option<mir::SourceInfo> {
+ self.block.map(|block| {
+ let block = &self.body.basic_blocks()[block];
+ if self.stmt < block.statements.len() {
+ block.statements[self.stmt].source_info
+ } else {
+ block.terminator().source_info
+ }
+ })
+ }
+}
+
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for InterpCx<'mir, 'tcx, M> {
#[inline]
fn data_layout(&self) -> &layout::TargetDataLayout {
@@ -236,6 +250,12 @@
self.memory.force_bits(scalar, size)
}
+ /// Call this to turn untagged "global" pointers (obtained via `tcx`) into
+ /// the *canonical* machine pointer to the allocation. Must never be used
+ /// for any other pointers!
+ ///
+ /// This represents a *direct* access to that memory, as opposed to access
+ /// through a pointer that was created by the program.
#[inline(always)]
pub fn tag_static_base_pointer(&self, ptr: Pointer) -> Pointer<M::PointerTag> {
self.memory.tag_static_base_pointer(ptr)
@@ -292,7 +312,7 @@
&self,
instance: ty::InstanceDef<'tcx>,
promoted: Option<mir::Promoted>,
- ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
+ ) -> InterpResult<'tcx, mir::ReadOnlyBodyCache<'tcx, 'tcx>> {
// do not continue if typeck errors occurred (can only occur in local crate)
let did = instance.def_id();
if did.is_local()
@@ -303,11 +323,11 @@
}
trace!("load mir(instance={:?}, promoted={:?})", instance, promoted);
if let Some(promoted) = promoted {
- return Ok(&self.tcx.promoted_mir(did)[promoted]);
+ return Ok(self.tcx.promoted_mir(did)[promoted].unwrap_read_only());
}
match instance {
ty::InstanceDef::Item(def_id) => if self.tcx.is_mir_available(did) {
- Ok(self.tcx.optimized_mir(did))
+ Ok(self.tcx.optimized_mir(did).unwrap_read_only())
} else {
throw_unsup!(NoMirFor(self.tcx.def_path_str(def_id)))
},
@@ -828,34 +848,28 @@
pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> Vec<FrameInfo<'tcx>> {
let mut last_span = None;
let mut frames = Vec::new();
- for &Frame { instance, span, body, block, stmt, .. } in self.stack().iter().rev() {
+ for frame in self.stack().iter().rev() {
// make sure we don't emit frames that are duplicates of the previous
- if explicit_span == Some(span) {
- last_span = Some(span);
+ if explicit_span == Some(frame.span) {
+ last_span = Some(frame.span);
continue;
}
if let Some(last) = last_span {
- if last == span {
+ if last == frame.span {
continue;
}
} else {
- last_span = Some(span);
+ last_span = Some(frame.span);
}
- let lint_root = block.and_then(|block| {
- let block = &body.basic_blocks()[block];
- let source_info = if stmt < block.statements.len() {
- block.statements[stmt].source_info
- } else {
- block.terminator().source_info
- };
- match body.source_scope_local_data {
- mir::ClearCrossCrate::Set(ref ivs) => Some(ivs[source_info.scope].lint_root),
+ let lint_root = frame.current_source_info().and_then(|source_info| {
+ match &frame.body.source_scopes[source_info.scope].local_data {
+ mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
mir::ClearCrossCrate::Clear => None,
}
});
- frames.push(FrameInfo { call_site: span, instance, lint_root });
+ frames.push(FrameInfo { call_site: frame.span, instance: frame.instance, lint_root });
}
trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span);
frames
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 7bcf84a..ad5df5a 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -2,7 +2,7 @@
//! looking at their MIR. Intrinsics/functions supported here are shared by CTFE
//! and miri.
-use syntax::symbol::Symbol;
+use syntax_pos::symbol::{sym, Symbol};
use syntax_pos::Span;
use rustc::ty;
use rustc::ty::layout::{LayoutOf, Primitive, Size};
@@ -22,7 +22,7 @@
mod type_name;
fn numeric_intrinsic<'tcx, Tag>(
- name: &str,
+ name: Symbol,
bits: u128,
kind: Primitive,
) -> InterpResult<'tcx, Scalar<Tag>> {
@@ -32,11 +32,11 @@
};
let extra = 128 - size.bits() as u128;
let bits_out = match name {
- "ctpop" => bits.count_ones() as u128,
- "ctlz" => bits.leading_zeros() as u128 - extra,
- "cttz" => (bits << extra).trailing_zeros() as u128 - extra,
- "bswap" => (bits << extra).swap_bytes(),
- "bitreverse" => (bits << extra).reverse_bits(),
+ sym::ctpop => bits.count_ones() as u128,
+ sym::ctlz => bits.leading_zeros() as u128 - extra,
+ sym::cttz => (bits << extra).trailing_zeros() as u128 - extra,
+ sym::bswap => (bits << extra).swap_bytes(),
+ sym::bitreverse => (bits << extra).reverse_bits(),
_ => bug!("not a numeric intrinsic: {}", name),
};
Ok(Scalar::from_uint(bits_out, size))
@@ -51,9 +51,9 @@
substs: SubstsRef<'tcx>,
) -> InterpResult<'tcx, &'tcx ty::Const<'tcx>> {
let tp_ty = substs.type_at(0);
- let name = &*tcx.item_name(def_id).as_str();
+ let name = tcx.item_name(def_id);
Ok(match name {
- "type_name" => {
+ sym::type_name => {
let alloc = type_name::alloc_type_name(tcx, tp_ty);
tcx.mk_const(ty::Const {
val: ty::ConstKind::Value(ConstValue::Slice {
@@ -64,20 +64,20 @@
ty: tcx.mk_static_str(),
})
},
- "needs_drop" => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)),
- "size_of" |
- "min_align_of" |
- "pref_align_of" => {
+ sym::needs_drop => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)),
+ sym::size_of |
+ sym::min_align_of |
+ sym::pref_align_of => {
let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
let n = match name {
- "pref_align_of" => layout.align.pref.bytes(),
- "min_align_of" => layout.align.abi.bytes(),
- "size_of" => layout.size.bytes(),
+ sym::pref_align_of => layout.align.pref.bytes(),
+ sym::min_align_of => layout.align.abi.bytes(),
+ sym::size_of => layout.size.bytes(),
_ => bug!(),
};
ty::Const::from_usize(tcx, n)
},
- "type_id" => ty::Const::from_bits(
+ sym::type_id => ty::Const::from_bits(
tcx,
tcx.type_id_hash(tp_ty).into(),
param_env.and(tcx.types.u64),
@@ -96,36 +96,32 @@
ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
) -> InterpResult<'tcx, bool> {
let substs = instance.substs;
- let intrinsic_name = &*self.tcx.item_name(instance.def_id()).as_str();
+ let intrinsic_name = self.tcx.item_name(instance.def_id());
// We currently do not handle any intrinsics that are *allowed* to diverge,
// but `transmute` could lack a return place in case of UB.
let (dest, ret) = match ret {
Some(p) => p,
None => match intrinsic_name {
- "transmute" => throw_ub!(Unreachable),
+ sym::transmute => throw_ub!(Unreachable),
_ => return Ok(false),
}
};
+ // Keep the patterns in this match ordered the same as the list in
+ // `src/librustc/ty/constness.rs`
match intrinsic_name {
- "caller_location" => {
- let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
- let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
- let location = self.alloc_caller_location(
- Symbol::intern(&caller.file.name.to_string()),
- caller.line as u32,
- caller.col_display as u32 + 1,
- )?;
+ sym::caller_location => {
+ let location = self.alloc_caller_location_for_span(span);
self.write_scalar(location.ptr, dest)?;
}
- "min_align_of" |
- "pref_align_of" |
- "needs_drop" |
- "size_of" |
- "type_id" |
- "type_name" => {
+ sym::min_align_of |
+ sym::pref_align_of |
+ sym::needs_drop |
+ sym::size_of |
+ sym::type_id |
+ sym::type_name => {
let gid = GlobalId {
instance,
promoted: None,
@@ -135,13 +131,13 @@
self.copy_op(val, dest)?;
}
- | "ctpop"
- | "cttz"
- | "cttz_nonzero"
- | "ctlz"
- | "ctlz_nonzero"
- | "bswap"
- | "bitreverse" => {
+ | sym::ctpop
+ | sym::cttz
+ | sym::cttz_nonzero
+ | sym::ctlz
+ | sym::ctlz_nonzero
+ | sym::bswap
+ | sym::bitreverse => {
let ty = substs.type_at(0);
let layout_of = self.layout_of(ty)?;
let val = self.read_scalar(args[0])?.not_undef()?;
@@ -150,31 +146,32 @@
ty::layout::Abi::Scalar(ref scalar) => scalar.value,
_ => throw_unsup!(TypeNotPrimitive(ty)),
};
- let out_val = if intrinsic_name.ends_with("_nonzero") {
- if bits == 0 {
- throw_ub_format!("`{}` called on 0", intrinsic_name);
- }
- numeric_intrinsic(intrinsic_name.trim_end_matches("_nonzero"), bits, kind)?
- } else {
- numeric_intrinsic(intrinsic_name, bits, kind)?
+ let (nonzero, intrinsic_name) = match intrinsic_name {
+ sym::cttz_nonzero => (true, sym::cttz),
+ sym::ctlz_nonzero => (true, sym::ctlz),
+ other => (false, other),
};
+ if nonzero && bits == 0 {
+ throw_ub_format!("`{}_nonzero` called on 0", intrinsic_name);
+ }
+ let out_val = numeric_intrinsic(intrinsic_name, bits, kind)?;
self.write_scalar(out_val, dest)?;
}
- | "wrapping_add"
- | "wrapping_sub"
- | "wrapping_mul"
- | "add_with_overflow"
- | "sub_with_overflow"
- | "mul_with_overflow" => {
+ | sym::wrapping_add
+ | sym::wrapping_sub
+ | sym::wrapping_mul
+ | sym::add_with_overflow
+ | sym::sub_with_overflow
+ | sym::mul_with_overflow => {
let lhs = self.read_immediate(args[0])?;
let rhs = self.read_immediate(args[1])?;
let (bin_op, ignore_overflow) = match intrinsic_name {
- "wrapping_add" => (BinOp::Add, true),
- "wrapping_sub" => (BinOp::Sub, true),
- "wrapping_mul" => (BinOp::Mul, true),
- "add_with_overflow" => (BinOp::Add, false),
- "sub_with_overflow" => (BinOp::Sub, false),
- "mul_with_overflow" => (BinOp::Mul, false),
+ sym::wrapping_add => (BinOp::Add, true),
+ sym::wrapping_sub => (BinOp::Sub, true),
+ sym::wrapping_mul => (BinOp::Mul, true),
+ sym::add_with_overflow => (BinOp::Add, false),
+ sym::sub_with_overflow => (BinOp::Sub, false),
+ sym::mul_with_overflow => (BinOp::Mul, false),
_ => bug!("Already checked for int ops")
};
if ignore_overflow {
@@ -183,10 +180,10 @@
self.binop_with_overflow(bin_op, lhs, rhs, dest)?;
}
}
- "saturating_add" | "saturating_sub" => {
+ sym::saturating_add | sym::saturating_sub => {
let l = self.read_immediate(args[0])?;
let r = self.read_immediate(args[1])?;
- let is_add = intrinsic_name == "saturating_add";
+ let is_add = intrinsic_name == sym::saturating_add;
let (val, overflowed, _ty) = self.overflowing_binary_op(if is_add {
BinOp::Add
} else {
@@ -226,12 +223,12 @@
};
self.write_scalar(val, dest)?;
}
- "unchecked_shl" | "unchecked_shr" => {
+ sym::unchecked_shl | sym::unchecked_shr => {
let l = self.read_immediate(args[0])?;
let r = self.read_immediate(args[1])?;
let bin_op = match intrinsic_name {
- "unchecked_shl" => BinOp::Shl,
- "unchecked_shr" => BinOp::Shr,
+ sym::unchecked_shl => BinOp::Shl,
+ sym::unchecked_shr => BinOp::Shr,
_ => bug!("Already checked for int ops")
};
let (val, overflowed, _ty) = self.overflowing_binary_op(bin_op, l, r)?;
@@ -242,7 +239,7 @@
}
self.write_scalar(val, dest)?;
}
- "rotate_left" | "rotate_right" => {
+ sym::rotate_left | sym::rotate_right => {
// rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
// rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
let layout = self.layout_of(substs.type_at(0))?;
@@ -253,7 +250,7 @@
let width_bits = layout.size.bits() as u128;
let shift_bits = raw_shift_bits % width_bits;
let inv_shift_bits = (width_bits - shift_bits) % width_bits;
- let result_bits = if intrinsic_name == "rotate_left" {
+ let result_bits = if intrinsic_name == sym::rotate_left {
(val_bits << shift_bits) | (val_bits >> inv_shift_bits)
} else {
(val_bits >> shift_bits) | (val_bits << inv_shift_bits)
@@ -263,7 +260,7 @@
self.write_scalar(result, dest)?;
}
- "ptr_offset_from" => {
+ sym::ptr_offset_from => {
let isize_layout = self.layout_of(self.tcx.types.isize)?;
let a = self.read_immediate(args[0])?.to_scalar()?;
let b = self.read_immediate(args[1])?.to_scalar()?;
@@ -309,10 +306,10 @@
}
}
- "transmute" => {
+ sym::transmute => {
self.copy_op_transmute(args[0], dest)?;
}
- "simd_insert" => {
+ sym::simd_insert => {
let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
let elem = args[2];
let input = args[0];
@@ -343,7 +340,7 @@
self.copy_op(value, place)?;
}
}
- "simd_extract" => {
+ sym::simd_extract => {
let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
let (len, e_ty) = args[0].layout.ty.simd_size_and_type(self.tcx.tcx);
assert!(
@@ -430,13 +427,13 @@
if self.binary_op(BinOp::Rem, a, b)?.to_bits()? != 0 {
// Then, check if `b` is -1, which is the "min_value / -1" case.
let minus1 = Scalar::from_int(-1, dest.layout.size);
- let b = b.to_scalar().unwrap();
- if b == minus1 {
+ let b_scalar = b.to_scalar().unwrap();
+ if b_scalar == minus1 {
throw_ub_format!("exact_div: result of dividing MIN by -1 cannot be represented")
} else {
throw_ub_format!(
"exact_div: {} cannot be divided by {} without remainder",
- a.to_scalar().unwrap(),
+ a,
b,
)
}
diff --git a/src/librustc_mir/interpret/intrinsics/caller_location.rs b/src/librustc_mir/interpret/intrinsics/caller_location.rs
index 9e07a3f..ecf4b7a 100644
--- a/src/librustc_mir/interpret/intrinsics/caller_location.rs
+++ b/src/librustc_mir/interpret/intrinsics/caller_location.rs
@@ -1,50 +1,48 @@
use rustc::middle::lang_items::PanicLocationLangItem;
-use rustc::mir::interpret::{Pointer, PointerArithmetic, Scalar};
use rustc::ty::subst::Subst;
-use rustc_target::abi::{LayoutOf, Size};
-use syntax_pos::Symbol;
+use rustc_target::abi::LayoutOf;
+use syntax_pos::{Symbol, Span};
-use crate::interpret::{MemoryKind, MPlaceTy, intrinsics::{InterpCx, InterpResult, Machine}};
+use crate::interpret::{Scalar, MemoryKind, MPlaceTy, intrinsics::{InterpCx, Machine}};
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
- pub fn alloc_caller_location(
+ crate fn alloc_caller_location(
&mut self,
filename: Symbol,
line: u32,
col: u32,
- ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
+ ) -> MPlaceTy<'tcx, M::PointerTag> {
+ let file = self.allocate_str(&filename.as_str(), MemoryKind::CallerLocation);
let line = Scalar::from_u32(line);
let col = Scalar::from_u32(col);
- let ptr_size = self.pointer_size();
- let u32_size = Size::from_bits(32);
-
+ // Allocate memory for `CallerLocation` struct.
let loc_ty = self.tcx.type_of(self.tcx.require_lang_item(PanicLocationLangItem, None))
.subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_static.into()].iter()));
- let loc_layout = self.layout_of(loc_ty)?;
-
- let file_alloc = self.tcx.allocate_bytes(filename.as_str().as_bytes());
- let file_ptr = Pointer::new(file_alloc, Size::ZERO);
- let file = Scalar::Ptr(self.tag_static_base_pointer(file_ptr));
- let file_len = Scalar::from_uint(filename.as_str().len() as u128, ptr_size);
-
+ let loc_layout = self.layout_of(loc_ty).unwrap();
let location = self.allocate(loc_layout, MemoryKind::CallerLocation);
- let file_out = self.mplace_field(location, 0)?;
- let file_ptr_out = self.force_ptr(self.mplace_field(file_out, 0)?.ptr)?;
- let file_len_out = self.force_ptr(self.mplace_field(file_out, 1)?.ptr)?;
- let line_out = self.force_ptr(self.mplace_field(location, 1)?.ptr)?;
- let col_out = self.force_ptr(self.mplace_field(location, 2)?.ptr)?;
+ // Initialize fields.
+ self.write_immediate(file.to_ref(), self.mplace_field(location, 0).unwrap().into())
+ .expect("writing to memory we just allocated cannot fail");
+ self.write_scalar(line, self.mplace_field(location, 1).unwrap().into())
+ .expect("writing to memory we just allocated cannot fail");
+ self.write_scalar(col, self.mplace_field(location, 2).unwrap().into())
+ .expect("writing to memory we just allocated cannot fail");
- let layout = &self.tcx.data_layout;
- // We just allocated this, so we can skip the bounds checks.
- let alloc = self.memory.get_raw_mut(file_ptr_out.alloc_id)?;
+ location
+ }
- alloc.write_scalar(layout, file_ptr_out, file.into(), ptr_size)?;
- alloc.write_scalar(layout, file_len_out, file_len.into(), ptr_size)?;
- alloc.write_scalar(layout, line_out, line.into(), u32_size)?;
- alloc.write_scalar(layout, col_out, col.into(), u32_size)?;
-
- Ok(location)
+ pub fn alloc_caller_location_for_span(
+ &mut self,
+ span: Span,
+ ) -> MPlaceTy<'tcx, M::PointerTag> {
+ let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
+ let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
+ self.alloc_caller_location(
+ Symbol::intern(&caller.file.name.to_string()),
+ caller.line as u32,
+ caller.col_display as u32 + 1,
+ )
}
}
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index b7cde62..74206ad 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -11,7 +11,7 @@
use syntax_pos::Span;
use super::{
- Allocation, AllocId, InterpResult, Scalar, AllocationExtra,
+ Allocation, AllocId, InterpResult, Scalar, AllocationExtra, AssertMessage,
InterpCx, PlaceTy, OpTy, ImmTy, MemoryKind, Pointer, Memory,
Frame, Operand,
};
@@ -146,7 +146,7 @@
/// nor just jump to `ret`, but instead push their own stack frame.)
/// Passing `dest`and `ret` in the same `Option` proved very annoying when only one of them
/// was used.
- fn find_fn(
+ fn find_mir_or_eval_fn(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Self::PointerTag>],
@@ -175,6 +175,14 @@
unwind: Option<mir::BasicBlock>,
) -> InterpResult<'tcx>;
+ /// Called to evaluate `Assert` MIR terminators that trigger a panic.
+ fn assert_panic(
+ ecx: &mut InterpCx<'mir, 'tcx, Self>,
+ span: Span,
+ msg: &AssertMessage<'tcx>,
+ unwind: Option<mir::BasicBlock>,
+ ) -> InterpResult<'tcx>;
+
/// Called for read access to a foreign static item.
///
/// This will only be called once per static and machine; the result is cached in
@@ -233,20 +241,19 @@
/// cache the result. (This relies on `AllocMap::get_or` being able to add the
/// owned allocation to the map even when the map is shared.)
///
- /// For static allocations, the tag returned must be the same as the one returned by
- /// `tag_static_base_pointer`.
- fn tag_allocation<'b>(
+ /// Also return the "base" tag to use for this allocation: the one that is used for direct
+ /// accesses to this allocation. If `kind == STATIC_KIND`, this tag must be consistent
+ /// with `tag_static_base_pointer`.
+ fn init_allocation_extra<'b>(
memory_extra: &Self::MemoryExtra,
id: AllocId,
alloc: Cow<'b, Allocation>,
kind: Option<MemoryKind<Self::MemoryKinds>>,
) -> (Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>, Self::PointerTag);
- /// Return the "base" tag for the given static allocation: the one that is used for direct
- /// accesses to this static/const/fn allocation.
- ///
- /// Be aware that requesting the `Allocation` for that `id` will lead to cycles
- /// for cyclic statics!
+ /// Return the "base" tag for the given *static* allocation: the one that is used for direct
+ /// accesses to this static/const/fn allocation. If `id` is not a static allocation,
+ /// this will return an unusable tag (i.e., accesses will be UB)!
fn tag_static_base_pointer(
memory_extra: &Self::MemoryExtra,
id: AllocId,
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index a8011f7..8f177ad 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -143,6 +143,12 @@
}
}
+ /// Call this to turn untagged "global" pointers (obtained via `tcx`) into
+ /// the *canonical* machine pointer to the allocation. Must never be used
+ /// for any other pointers!
+ ///
+ /// This represents a *direct* access to that memory, as opposed to access
+ /// through a pointer that was created by the program.
#[inline]
pub fn tag_static_base_pointer(&self, ptr: Pointer) -> Pointer<M::PointerTag> {
ptr.with_tag(M::tag_static_base_pointer(&self.extra, ptr.alloc_id))
@@ -191,7 +197,9 @@
kind: MemoryKind<M::MemoryKinds>,
) -> Pointer<M::PointerTag> {
let id = self.tcx.alloc_map.lock().reserve();
- let (alloc, tag) = M::tag_allocation(&self.extra, id, Cow::Owned(alloc), Some(kind));
+ debug_assert_ne!(Some(kind), M::STATIC_KIND.map(MemoryKind::Machine),
+ "dynamically allocating static memory");
+ let (alloc, tag) = M::init_allocation_extra(&self.extra, id, Cow::Owned(alloc), Some(kind));
self.alloc_map.insert(id, (kind, alloc.into_owned()));
Pointer::from(id).with_tag(tag)
}
@@ -316,7 +324,7 @@
size: Size,
align: Align,
) -> InterpResult<'tcx, Option<Pointer<M::PointerTag>>> {
- let align = if M::CHECK_ALIGN { Some(align) } else { None };
+ let align = M::CHECK_ALIGN.then_some(align);
self.check_ptr_access_align(sptr, size, align, CheckInAllocMsg::MemoryAccessTest)
}
@@ -350,7 +358,7 @@
sptr
} else {
// A "real" access, we must get a pointer.
- Scalar::Ptr(self.force_ptr(sptr)?)
+ Scalar::from(self.force_ptr(sptr)?)
};
Ok(match normalized.to_bits_or_ptr(self.pointer_size(), self) {
Ok(bits) => {
@@ -473,14 +481,15 @@
}
}
};
- // We got tcx memory. Let the machine figure out whether and how to
- // turn that into memory with the right pointer tag.
- Ok(M::tag_allocation(
+ // We got tcx memory. Let the machine initialize its "extra" stuff.
+ let (alloc, tag) = M::init_allocation_extra(
memory_extra,
id, // always use the ID we got as input, not the "hidden" one.
alloc,
M::STATIC_KIND.map(MemoryKind::Machine),
- ).0)
+ );
+ debug_assert_eq!(tag, M::tag_static_base_pointer(memory_extra, id));
+ Ok(alloc)
}
/// Gives raw access to the `Allocation`, without bounds or alignment checks.
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 8dd5807..48e7193 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -19,12 +19,13 @@
};
pub use rustc::mir::interpret::ScalarMaybeUndef;
use rustc_macros::HashStable;
+use syntax::ast;
/// An `Immediate` represents a single immediate self-contained Rust value.
///
/// For optimization of a few very common cases, there is also a representation for a pair of
/// primitive values (`ScalarPair`). It allows Miri to avoid making allocations for checked binary
-/// operations and fat pointers. This idea was taken from rustc's codegen.
+/// operations and wide pointers. This idea was taken from rustc's codegen.
/// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely
/// defined on `Immediate`, and do not have to work with a `Place`.
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, Hash)]
@@ -47,6 +48,13 @@
}
}
+impl<Tag> From<Pointer<Tag>> for Immediate<Tag> {
+ #[inline(always)]
+ fn from(val: Pointer<Tag>) -> Self {
+ Immediate::Scalar(Scalar::from(val).into())
+ }
+}
+
impl<'tcx, Tag> Immediate<Tag> {
pub fn new_slice(
val: Scalar<Tag>,
@@ -60,14 +68,14 @@
}
pub fn new_dyn_trait(val: Scalar<Tag>, vtable: Pointer<Tag>) -> Self {
- Immediate::ScalarPair(val.into(), Scalar::Ptr(vtable).into())
+ Immediate::ScalarPair(val.into(), vtable.into())
}
#[inline]
pub fn to_scalar_or_undef(self) -> ScalarMaybeUndef<Tag> {
match self {
Immediate::Scalar(val) => val,
- Immediate::ScalarPair(..) => bug!("Got a fat pointer where a scalar was expected"),
+ Immediate::ScalarPair(..) => bug!("Got a wide pointer where a scalar was expected"),
}
}
@@ -93,6 +101,42 @@
pub layout: TyLayout<'tcx>,
}
+// `Tag: Copy` because some methods on `Scalar` consume them by value
+impl<Tag: Copy> std::fmt::Display for ImmTy<'tcx, Tag> {
+ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match &self.imm {
+ Immediate::Scalar(ScalarMaybeUndef::Scalar(s)) => match s.to_bits(self.layout.size) {
+ Ok(s) => {
+ match self.layout.ty.kind {
+ ty::Int(_) => return write!(
+ fmt, "{}",
+ super::sign_extend(s, self.layout.size) as i128,
+ ),
+ ty::Uint(_) => return write!(fmt, "{}", s),
+ ty::Bool if s == 0 => return fmt.write_str("false"),
+ ty::Bool if s == 1 => return fmt.write_str("true"),
+ ty::Char => if let Some(c) =
+ u32::try_from(s).ok().and_then(std::char::from_u32) {
+ return write!(fmt, "{}", c);
+ },
+ ty::Float(ast::FloatTy::F32) => if let Ok(u) = u32::try_from(s) {
+ return write!(fmt, "{}", f32::from_bits(u));
+ },
+ ty::Float(ast::FloatTy::F64) => if let Ok(u) = u64::try_from(s) {
+ return write!(fmt, "{}", f64::from_bits(u));
+ },
+ _ => {},
+ }
+ write!(fmt, "{:x}", s)
+ },
+ Err(_) => fmt.write_str("{pointer}"),
+ },
+ Immediate::Scalar(ScalarMaybeUndef::Undef) => fmt.write_str("{undef}"),
+ Immediate::ScalarPair(..) => fmt.write_str("{wide pointer or tuple}"),
+ }
+ }
+}
+
impl<'tcx, Tag> ::std::ops::Deref for ImmTy<'tcx, Tag> {
type Target = Immediate<Tag>;
#[inline(always)]
@@ -324,7 +368,7 @@
Ok(self.read_immediate(op)?.to_scalar_or_undef())
}
- // Turn the MPlace into a string (must already be dereferenced!)
+ // Turn the wide MPlace into a string (must already be dereferenced!)
pub fn read_str(
&self,
mplace: MPlaceTy<'tcx, M::PointerTag>,
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index f34c311..a600eb1 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -125,7 +125,7 @@
Self::from_scalar_ptr(ptr.into(), align)
}
- /// Turn a mplace into a (thin or fat) pointer, as a reference, pointing to the same space.
+ /// Turn a mplace into a (thin or wide) pointer, as a reference, pointing to the same space.
/// This is the inverse of `ref_to_mplace`.
#[inline(always)]
pub fn to_ref(self) -> Immediate<Tag> {
@@ -278,7 +278,7 @@
M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation<Tag, M::AllocExtra>)>,
M::AllocExtra: AllocationExtra<Tag>,
{
- /// Take a value, which represents a (thin or fat) reference, and make it a place.
+ /// Take a value, which represents a (thin or wide) reference, and make it a place.
/// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`.
///
/// Only call this if you are sure the place is "valid" (aligned and inbounds), or do not
@@ -649,20 +649,28 @@
use rustc::mir::PlaceBase;
let mut place_ty = match &place.base {
- PlaceBase::Local(mir::RETURN_PLACE) => match self.frame().return_place {
- Some(return_place) => {
- // We use our layout to verify our assumption; caller will validate
- // their layout on return.
- PlaceTy {
- place: *return_place,
- layout: self.layout_of(
- self.subst_from_frame_and_normalize_erasing_regions(
- self.frame().body.return_ty()
- )
- )?,
- }
+ PlaceBase::Local(mir::RETURN_PLACE) => {
+ // `return_place` has the *caller* layout, but we want to use our
+ // `layout to verify our assumption. The caller will validate
+ // their layout on return.
+ PlaceTy {
+ place: match self.frame().return_place {
+ Some(p) => *p,
+ // Even if we don't have a return place, we sometimes need to
+ // create this place, but any attempt to read from / write to it
+ // (even a ZST read/write) needs to error, so let us make this
+ // a NULL place.
+ //
+ // FIXME: Ideally we'd make sure that the place projections also
+ // bail out.
+ None => Place::null(&*self),
+ },
+ layout: self.layout_of(
+ self.subst_from_frame_and_normalize_erasing_regions(
+ self.frame().body.return_ty()
+ )
+ )?,
}
- None => throw_unsup!(InvalidNullPointerUsage),
},
PlaceBase::Local(local) => PlaceTy {
// This works even for dead/uninitialized locals; we check further when writing
@@ -684,6 +692,7 @@
}
/// Write a scalar to a place
+ #[inline(always)]
pub fn write_scalar(
&mut self,
val: impl Into<ScalarMaybeUndef<M::PointerTag>>,
@@ -789,8 +798,8 @@
// to handle padding properly, which is only correct if we never look at this data with the
// wrong type.
- let ptr = match self.check_mplace_access(dest, None)
- .expect("places should be checked on creation")
+ // Invalid places are a thing: the return place of a diverging function
+ let ptr = match self.check_mplace_access(dest, None)?
{
Some(ptr) => ptr,
None => return Ok(()), // zero-sized access
@@ -1031,18 +1040,39 @@
MPlaceTy::from_aligned_ptr(ptr, layout)
}
+ /// Returns a wide MPlace.
+ pub fn allocate_str(
+ &mut self,
+ str: &str,
+ kind: MemoryKind<M::MemoryKinds>,
+ ) -> MPlaceTy<'tcx, M::PointerTag> {
+ let ptr = self.memory.allocate_static_bytes(str.as_bytes(), kind);
+ let meta = Scalar::from_uint(str.len() as u128, self.pointer_size());
+ let mplace = MemPlace {
+ ptr: ptr.into(),
+ align: Align::from_bytes(1).unwrap(),
+ meta: Some(meta),
+ };
+
+ let layout = self.layout_of(self.tcx.mk_static_str()).unwrap();
+ MPlaceTy { mplace, layout }
+ }
+
pub fn write_discriminant_index(
&mut self,
variant_index: VariantIdx,
dest: PlaceTy<'tcx, M::PointerTag>,
) -> InterpResult<'tcx> {
- let variant_scalar = Scalar::from_u32(variant_index.as_u32()).into();
+
+ // Layout computation excludes uninhabited variants from consideration
+ // therefore there's no way to represent those variants in the given layout.
+ if dest.layout.for_variant(self, variant_index).abi.is_uninhabited() {
+ throw_ub!(Unreachable);
+ }
match dest.layout.variants {
layout::Variants::Single { index } => {
- if index != variant_index {
- throw_ub!(InvalidDiscriminant(variant_scalar));
- }
+ assert_eq!(index, variant_index);
}
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Tag,
@@ -1050,9 +1080,9 @@
discr_index,
..
} => {
- if !dest.layout.ty.variant_range(*self.tcx).unwrap().contains(&variant_index) {
- throw_ub!(InvalidDiscriminant(variant_scalar));
- }
+ // No need to validate that the discriminant here because the
+ // `TyLayout::for_variant()` call earlier already checks the variant is valid.
+
let discr_val =
dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val;
@@ -1075,9 +1105,9 @@
discr_index,
..
} => {
- if !variant_index.as_usize() < dest.layout.ty.ty_adt_def().unwrap().variants.len() {
- throw_ub!(InvalidDiscriminant(variant_scalar));
- }
+ // No need to validate that the discriminant here because the
+ // `TyLayout::for_variant()` call earlier already checks the variant is valid.
+
if variant_index != dataful_variant {
let variants_start = niche_variants.start().as_u32();
let variant_index_relative = variant_index.as_u32()
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index d749333..55b9427 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -157,9 +157,9 @@
}
BinaryOp(bin_op, ref left, ref right) => {
- let layout = if binop_left_homogeneous(bin_op) { Some(dest.layout) } else { None };
+ let layout = binop_left_homogeneous(bin_op).then_some(dest.layout);
let left = self.read_immediate(self.eval_operand(left, layout)?)?;
- let layout = if binop_right_homogeneous(bin_op) { Some(left.layout) } else { None };
+ let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
let right = self.read_immediate(self.eval_operand(right, layout)?)?;
self.binop_ignore_overflow(
bin_op,
@@ -172,7 +172,7 @@
CheckedBinaryOp(bin_op, ref left, ref right) => {
// Due to the extra boolean in the result, we can never reuse the `dest.layout`.
let left = self.read_immediate(self.eval_operand(left, None)?)?;
- let layout = if binop_right_homogeneous(bin_op) { Some(left.layout) } else { None };
+ let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
let right = self.read_immediate(self.eval_operand(right, layout)?)?;
self.binop_with_overflow(
bin_op,
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 50cd318..b8dc15f 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -7,8 +7,8 @@
use rustc_target::spec::abi::Abi;
use super::{
- GlobalId, InterpResult, PointerArithmetic,
- InterpCx, Machine, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal,
+ GlobalId, InterpResult, InterpCx, Machine,
+ OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal,
};
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
@@ -115,40 +115,14 @@
expected,
ref msg,
target,
- ..
+ cleanup,
} => {
let cond_val = self.read_immediate(self.eval_operand(cond, None)?)?
.to_scalar()?.to_bool()?;
if expected == cond_val {
self.go_to_block(target);
} else {
- // Compute error message
- use rustc::mir::interpret::PanicInfo::*;
- return Err(match msg {
- BoundsCheck { ref len, ref index } => {
- let len = self
- .read_immediate(self.eval_operand(len, None)?)
- .expect("can't eval len")
- .to_scalar()?
- .to_bits(self.memory.pointer_size())? as u64;
- let index = self
- .read_immediate(self.eval_operand(index, None)?)
- .expect("can't eval index")
- .to_scalar()?
- .to_bits(self.memory.pointer_size())? as u64;
- err_panic!(BoundsCheck { len, index })
- }
- Overflow(op) => err_panic!(Overflow(*op)),
- OverflowNeg => err_panic!(OverflowNeg),
- DivisionByZero => err_panic!(DivisionByZero),
- RemainderByZero => err_panic!(RemainderByZero),
- ResumedAfterReturn(generator_kind)
- => err_panic!(ResumedAfterReturn(*generator_kind)),
- ResumedAfterPanic(generator_kind)
- => err_panic!(ResumedAfterPanic(*generator_kind)),
- Panic { .. } => bug!("`Panic` variant cannot occur in MIR"),
- }
- .into());
+ M::assert_panic(self, terminator.source_info.span, msg, cleanup)?;
}
}
@@ -164,15 +138,21 @@
return Ok(())
},
+ // It is UB to ever encounter this.
+ Unreachable => throw_ub!(Unreachable),
+
+ // These should never occur for MIR we actually run.
+ DropAndReplace { .. } |
+ FalseEdges { .. } |
+ FalseUnwind { .. } =>
+ bug!("{:#?} should have been eliminated by MIR pass", terminator.kind),
+
+ // These are not (yet) supported. It is unclear if they even can occur in
+ // MIR that we actually run.
Yield { .. } |
GeneratorDrop |
- DropAndReplace { .. } |
- Abort => unimplemented!("{:#?}", terminator.kind),
- FalseEdges { .. } => bug!("should have been eliminated by\
- `simplify_branches` mir pass"),
- FalseUnwind { .. } => bug!("should have been eliminated by\
- `simplify_branches` mir pass"),
- Unreachable => throw_ub!(Unreachable),
+ Abort =>
+ throw_unsup_format!("Unsupported terminator kind: {:#?}", terminator.kind),
}
Ok(())
@@ -286,20 +266,8 @@
ty::InstanceDef::DropGlue(..) |
ty::InstanceDef::CloneShim(..) |
ty::InstanceDef::Item(_) => {
- // If this function is a `const fn` then as an optimization we can query this
- // evaluation immediately.
- //
- // For the moment we only do this for functions which take no arguments
- // (or all arguments are ZSTs) so that we don't memoize too much.
- if self.tcx.is_const_fn_raw(instance.def.def_id()) &&
- args.iter().all(|a| a.layout.is_zst())
- {
- let gid = GlobalId { instance, promoted: None };
- return self.eval_const_fn_call(gid, ret);
- }
-
// We need MIR for this fn
- let body = match M::find_fn(self, instance, args, ret, unwind)? {
+ let body = match M::find_mir_or_eval_fn(self, instance, args, ret, unwind)? {
Some(body) => body,
None => return Ok(()),
};
@@ -465,7 +433,8 @@
/// Evaluate a const function where all arguments (if any) are zero-sized types.
/// The evaluation is memoized thanks to the query system.
- fn eval_const_fn_call(
+ // FIXME: Consider moving this to `const_eval.rs`.
+ pub (crate) fn eval_const_fn_call(
&mut self,
gid: GlobalId<'tcx>,
ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs
index 3a7f47a..efa0d26 100644
--- a/src/librustc_mir/interpret/traits.rs
+++ b/src/librustc_mir/interpret/traits.rs
@@ -67,7 +67,7 @@
// allocation is correctly aligned as we created it above. Also we're only offsetting by
// multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`.
let vtable_alloc = self.memory.get_raw_mut(vtable.alloc_id)?;
- vtable_alloc.write_ptr_sized(tcx, vtable, Scalar::Ptr(drop).into())?;
+ vtable_alloc.write_ptr_sized(tcx, vtable, drop.into())?;
let size_ptr = vtable.offset(ptr_size, tcx)?;
vtable_alloc.write_ptr_sized(tcx, size_ptr, Scalar::from_uint(size, ptr_size).into())?;
@@ -87,7 +87,7 @@
// We cannot use `vtable_allic` as we are creating fn ptrs in this loop.
let method_ptr = vtable.offset(ptr_size * (3 + i as u64), tcx)?;
self.memory.get_raw_mut(vtable.alloc_id)?
- .write_ptr_sized(tcx, method_ptr, Scalar::Ptr(fn_ptr).into())?;
+ .write_ptr_sized(tcx, method_ptr, fn_ptr.into())?;
}
}
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index cca7670..42b72b6 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -8,6 +8,7 @@
#![feature(in_band_lifetimes)]
#![feature(inner_deref)]
#![feature(slice_patterns)]
+#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(crate_visibility_modifier)]
@@ -27,8 +28,8 @@
#![feature(associated_type_bounds)]
#![feature(range_is_empty)]
#![feature(stmt_expr_attributes)]
-#![feature(bool_to_option)]
#![feature(trait_alias)]
+#![feature(matches_macro)]
#![recursion_limit="256"]
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index a4c4c7f..93a7671 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -741,23 +741,21 @@
}
match instance.def {
- ty::InstanceDef::Intrinsic(def_id) => {
+ ty::InstanceDef::Virtual(..) |
+ ty::InstanceDef::Intrinsic(_) => {
if !is_direct_call {
- bug!("intrinsic {:?} being reified", def_id);
+ bug!("{:?} being reified", instance);
}
}
- ty::InstanceDef::VtableShim(..) |
- ty::InstanceDef::ReifyShim(..) |
- ty::InstanceDef::Virtual(..) |
ty::InstanceDef::DropGlue(_, None) => {
- // Don't need to emit shim if we are calling directly.
+ // Don't need to emit noop drop glue if we are calling directly.
if !is_direct_call {
output.push(create_fn_mono_item(instance));
}
}
- ty::InstanceDef::DropGlue(_, Some(_)) => {
- output.push(create_fn_mono_item(instance));
- }
+ ty::InstanceDef::DropGlue(_, Some(_)) |
+ ty::InstanceDef::VtableShim(..) |
+ ty::InstanceDef::ReifyShim(..) |
ty::InstanceDef::ClosureOnceShim { .. } |
ty::InstanceDef::Item(..) |
ty::InstanceDef::FnPtrShim(..) |
@@ -1255,7 +1253,7 @@
body: &body,
output,
param_substs: instance.substs,
- }.visit_body(&body);
+ }.visit_body(body);
}
fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String {
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index 42f0877..591f220 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -761,11 +761,7 @@
.iter()
.map(|part| part.data.as_symbol());
- let volatile_suffix = if volatile {
- Some("volatile")
- } else {
- None
- };
+ let volatile_suffix = volatile.then_some("volatile");
name_builder.build_cgu_name(def_path.krate, components, volatile_suffix)
}).clone()
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 08af271..5b208dd 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -26,7 +26,7 @@
providers.mir_shims = make_shim;
}
-fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
+fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx BodyCache<'tcx> {
debug!("make_shim({:?})", instance);
let mut result = match instance {
@@ -35,7 +35,7 @@
ty::InstanceDef::VtableShim(def_id) => {
build_call_shim(
tcx,
- def_id,
+ instance,
Adjustment::DerefMove,
CallKind::Direct(def_id),
None,
@@ -60,27 +60,27 @@
build_call_shim(
tcx,
- def_id,
+ instance,
adjustment,
CallKind::Indirect,
Some(arg_tys)
)
}
// We are generating a call back to our def-id, which the
- // codegen backend knows to turn to an actual virtual call.
- ty::InstanceDef::Virtual(def_id, _) |
- // ...or we are generating a direct call to a function for which indirect calls must be
- // codegen'd differently than direct ones (example: #[track_caller])
+ // codegen backend knows to turn to an actual call, be it
+ // a virtual call, or a direct call to a function for which
+ // indirect calls must be codegen'd differently than direct ones
+ // (such as `#[track_caller]`).
ty::InstanceDef::ReifyShim(def_id) => {
build_call_shim(
tcx,
- def_id,
+ instance,
Adjustment::Identity,
CallKind::Direct(def_id),
None
)
}
- ty::InstanceDef::ClosureOnceShim { call_once } => {
+ ty::InstanceDef::ClosureOnceShim { call_once: _ } => {
let fn_mut = tcx.lang_items().fn_mut_trait().unwrap();
let call_mut = tcx
.associated_items(fn_mut)
@@ -89,7 +89,7 @@
build_call_shim(
tcx,
- call_once,
+ instance,
Adjustment::RefMut,
CallKind::Direct(call_mut),
None
@@ -109,6 +109,9 @@
bug!("builtin clone shim {:?} not supported", instance)
}
}
+ ty::InstanceDef::Virtual(..) => {
+ bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance)
+ }
ty::InstanceDef::Intrinsic(_) => {
bug!("creating shims from intrinsics ({:?}) is unsupported", instance)
}
@@ -125,6 +128,7 @@
debug!("make_shim({:?}) = {:?}", instance, result);
+ result.ensure_predecessors();
tcx.arena.alloc(result)
}
@@ -164,7 +168,9 @@
.collect()
}
-fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>) -> Body<'tcx> {
+fn build_drop_shim<'tcx>(
+ tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>
+) -> BodyCache<'tcx> {
debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
// Check if this is a generator, if so, return the drop glue for it
@@ -196,15 +202,14 @@
block(&mut blocks, TerminatorKind::Goto { target: return_block });
block(&mut blocks, TerminatorKind::Return);
- let mut body = new_body(
+ let body = new_body(
blocks,
- IndexVec::from_elem_n(
- SourceScopeData { span, parent_scope: None }, 1
- ),
local_decls_for_sig(&sig, span),
sig.inputs().len(),
span);
+ let mut body = BodyCache::new(body);
+
if let Some(..) = ty {
// The first argument (index 0), but add 1 for the return value.
let dropee_ptr = Place::from(Local::new(1+0));
@@ -244,15 +249,16 @@
fn new_body<'tcx>(
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
- source_scopes: IndexVec<SourceScope, SourceScopeData>,
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
arg_count: usize,
span: Span,
) -> Body<'tcx> {
Body::new(
basic_blocks,
- source_scopes,
- ClearCrossCrate::Clear,
+ IndexVec::from_elem_n(
+ SourceScopeData { span, parent_scope: None, local_data: ClearCrossCrate::Clear },
+ 1,
+ ),
local_decls,
IndexVec::new(),
arg_count,
@@ -316,7 +322,7 @@
}
/// Builds a `Clone::clone` shim for `self_ty`. Here, `def_id` is `Clone::clone`.
-fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
+fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> BodyCache<'tcx> {
debug!("build_clone_shim(def_id={:?})", def_id);
let param_env = tcx.param_env(def_id);
@@ -345,7 +351,7 @@
}
};
- builder.into_mir()
+ BodyCache::new(builder.into_mir())
}
struct CloneShimBuilder<'tcx> {
@@ -380,9 +386,6 @@
fn into_mir(self) -> Body<'tcx> {
new_body(
self.blocks,
- IndexVec::from_elem_n(
- SourceScopeData { span: self.span, parent_scope: None }, 1
- ),
self.local_decls,
self.sig.inputs().len(),
self.span,
@@ -697,7 +700,7 @@
}
}
-/// Builds a "call" shim for `def_id`. The shim calls the
+/// Builds a "call" shim for `instance`. The shim calls the
/// function specified by `call_kind`, first adjusting its first
/// argument according to `rcvr_adjustment`.
///
@@ -705,17 +708,30 @@
/// function will be untupled as these types.
fn build_call_shim<'tcx>(
tcx: TyCtxt<'tcx>,
- def_id: DefId,
+ instance: ty::InstanceDef<'tcx>,
rcvr_adjustment: Adjustment,
call_kind: CallKind,
untuple_args: Option<&[Ty<'tcx>]>,
-) -> Body<'tcx> {
- debug!("build_call_shim(def_id={:?}, rcvr_adjustment={:?}, \
+) -> BodyCache<'tcx> {
+ debug!("build_call_shim(instance={:?}, rcvr_adjustment={:?}, \
call_kind={:?}, untuple_args={:?})",
- def_id, rcvr_adjustment, call_kind, untuple_args);
+ instance, rcvr_adjustment, call_kind, untuple_args);
+ let def_id = instance.def_id();
let sig = tcx.fn_sig(def_id);
- let sig = tcx.erase_late_bound_regions(&sig);
+ let mut sig = tcx.erase_late_bound_regions(&sig);
+
+ // FIXME(eddyb) avoid having this snippet both here and in
+ // `Instance::fn_sig` (introduce `InstanceDef::fn_sig`?).
+ if let ty::InstanceDef::VtableShim(..) = instance {
+ // Modify fn(self, ...) to fn(self: *mut Self, ...)
+ let mut inputs_and_output = sig.inputs_and_output.to_vec();
+ let self_arg = &mut inputs_and_output[0];
+ debug_assert!(tcx.generics_of(def_id).has_self && *self_arg == tcx.types.self_param);
+ *self_arg = tcx.mk_mut_ptr(*self_arg);
+ sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output);
+ }
+
let span = tcx.def_span(def_id);
debug!("build_call_shim: sig={:?}", sig);
@@ -730,14 +746,7 @@
let rcvr = match rcvr_adjustment {
Adjustment::Identity => Operand::Move(rcvr_l),
Adjustment::Deref => Operand::Copy(tcx.mk_place_deref(rcvr_l)),
- Adjustment::DerefMove => {
- // fn(Self, ...) -> fn(*mut Self, ...)
- let arg_ty = local_decls[rcvr_arg].ty;
- debug_assert!(tcx.generics_of(def_id).has_self && arg_ty == tcx.types.self_param);
- local_decls[rcvr_arg].ty = tcx.mk_mut_ptr(arg_ty);
-
- Operand::Move(tcx.mk_place_deref(rcvr_l))
- }
+ Adjustment::DerefMove => Operand::Move(tcx.mk_place_deref(rcvr_l)),
Adjustment::RefMut => {
// let rcvr = &mut rcvr;
let ref_rcvr = local_decls.push(temp_decl(
@@ -836,9 +845,6 @@
let mut body = new_body(
blocks,
- IndexVec::from_elem_n(
- SourceScopeData { span, parent_scope: None }, 1
- ),
local_decls,
sig.inputs().len(),
span,
@@ -847,10 +853,10 @@
if let Abi::RustCall = sig.abi {
body.spread_arg = Some(Local::new(sig.inputs().len()));
}
- body
+ BodyCache::new(body)
}
-pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> {
+pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &BodyCache<'_> {
debug_assert!(tcx.is_constructor(ctor_id));
let span = tcx.hir().span_if_local(ctor_id)
@@ -919,9 +925,6 @@
let body = new_body(
IndexVec::from_elem_n(start_block, 1),
- IndexVec::from_elem_n(
- SourceScopeData { span, parent_scope: None }, 1
- ),
local_decls,
sig.inputs().len(),
span,
@@ -937,5 +940,7 @@
|_, _| Ok(()),
);
+ let mut body = BodyCache::new(body);
+ body.ensure_predecessors();
tcx.arena.alloc(body)
}
diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs
index bf3df1a..35238e2 100644
--- a/src/librustc_mir/transform/add_call_guards.rs
+++ b/src/librustc_mir/transform/add_call_guards.rs
@@ -31,15 +31,16 @@
*/
impl<'tcx> MirPass<'tcx> for AddCallGuards {
- fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(
+ &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+ ) {
self.add_call_guards(body);
}
}
impl AddCallGuards {
- pub fn add_call_guards(&self, body: &mut Body<'_>) {
- let pred_count: IndexVec<_, _> =
- body.predecessors().iter().map(|ps| ps.len()).collect();
+ pub fn add_call_guards(&self, body: &mut BodyCache<'_>) {
+ let pred_count: IndexVec<_, _> = body.predecessors().iter().map(|ps| ps.len()).collect();
// We need a place to store the new blocks generated
let mut new_blocks = Vec::new();
diff --git a/src/librustc_mir/transform/add_moves_for_packed_drops.rs b/src/librustc_mir/transform/add_moves_for_packed_drops.rs
index 052631d..98c6a5e 100644
--- a/src/librustc_mir/transform/add_moves_for_packed_drops.rs
+++ b/src/librustc_mir/transform/add_moves_for_packed_drops.rs
@@ -40,13 +40,15 @@
pub struct AddMovesForPackedDrops;
impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
debug!("add_moves_for_packed_drops({:?} @ {:?})", src, body.span);
add_moves_for_packed_drops(tcx, body, src.def_id());
}
}
-pub fn add_moves_for_packed_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, def_id: DefId) {
+pub fn add_moves_for_packed_drops<'tcx>(
+ tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>, def_id: DefId
+) {
let patch = add_moves_for_packed_drops_patch(tcx, body, def_id);
patch.apply(body);
}
diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs
index b56a1b2..e6ad37a 100644
--- a/src/librustc_mir/transform/add_retag.rs
+++ b/src/librustc_mir/transform/add_retag.rs
@@ -59,7 +59,7 @@
}
impl<'tcx> MirPass<'tcx> for AddRetag {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
if !tcx.sess.opts.debugging_opts.mir_emit_retag {
return;
}
diff --git a/src/librustc_mir/transform/check_consts/mod.rs b/src/librustc_mir/transform/check_consts/mod.rs
index 4d00aaf..82ffafb 100644
--- a/src/librustc_mir/transform/check_consts/mod.rs
+++ b/src/librustc_mir/transform/check_consts/mod.rs
@@ -20,7 +20,7 @@
/// Information about the item currently being const-checked, as well as a reference to the global
/// context.
pub struct Item<'mir, 'tcx> {
- pub body: &'mir mir::Body<'tcx>,
+ pub body: mir::ReadOnlyBodyCache<'mir, 'tcx>,
pub tcx: TyCtxt<'tcx>,
pub def_id: DefId,
pub param_env: ty::ParamEnv<'tcx>,
@@ -31,7 +31,7 @@
pub fn new(
tcx: TyCtxt<'tcx>,
def_id: DefId,
- body: &'mir mir::Body<'tcx>,
+ body: mir::ReadOnlyBodyCache<'mir, 'tcx>,
) -> Self {
let param_env = tcx.param_env(def_id);
let const_kind = ConstKind::for_item(tcx, def_id);
@@ -77,7 +77,12 @@
let mode = match tcx.hir().body_owner_kind(hir_id) {
HirKind::Closure => return None,
- HirKind::Fn if tcx.is_const_fn(def_id) => ConstKind::ConstFn,
+ // Note: this is deliberately checking for `is_const_fn_raw`, as the `is_const_fn`
+ // checks take into account the `rustc_const_unstable` attribute combined with enabled
+ // feature gates. Otherwise, const qualification would _not check_ whether this
+ // function body follows the `const fn` rules, as an unstable `const fn` would
+ // be considered "not const". More details are available in issue #67053.
+ HirKind::Fn if tcx.is_const_fn_raw(def_id) => ConstKind::ConstFn,
HirKind::Fn => return None,
HirKind::Const => ConstKind::Const,
diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs
index a4f12a4..393ae94 100644
--- a/src/librustc_mir/transform/check_consts/ops.rs
+++ b/src/librustc_mir/transform/check_consts/ops.rs
@@ -1,7 +1,6 @@
//! Concrete error types for all operations which may be invalid in a certain const context.
use rustc::hir::def_id::DefId;
-use rustc::mir::BorrowKind;
use rustc::session::config::nightly_options;
use rustc::ty::TyCtxt;
use syntax::feature_gate::feature_err;
@@ -181,38 +180,53 @@
}
#[derive(Debug)]
-pub struct MutBorrow(pub BorrowKind);
-impl NonConstOp for MutBorrow {
+pub struct CellBorrow;
+impl NonConstOp for CellBorrow {
fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
- let kind = self.0;
- if let BorrowKind::Mut { .. } = kind {
- let mut err = struct_span_err!(item.tcx.sess, span, E0017,
- "references in {}s may only refer \
- to immutable values", item.const_kind());
- err.span_label(span, format!("{}s require immutable values",
- item.const_kind()));
- if item.tcx.sess.teach(&err.get_code().unwrap()) {
- err.note("References in statics and constants may only refer \
- to immutable values.\n\n\
- Statics are shared everywhere, and if they refer to \
- mutable data one might violate memory safety since \
- holding multiple mutable references to shared data \
- is not allowed.\n\n\
- If you really want global mutable state, try using \
- static mut or a global UnsafeCell.");
- }
- err.emit();
- } else {
- span_err!(item.tcx.sess, span, E0492,
- "cannot borrow a constant which may contain \
- interior mutability, create a static instead");
+ span_err!(item.tcx.sess, span, E0492,
+ "cannot borrow a constant which may contain \
+ interior mutability, create a static instead");
+ }
+}
+
+#[derive(Debug)]
+pub struct MutBorrow;
+impl NonConstOp for MutBorrow {
+ fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
+ Some(tcx.features().const_mut_refs)
+ }
+
+ fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
+ let mut err = feature_err(
+ &item.tcx.sess.parse_sess,
+ sym::const_mut_refs,
+ span,
+ &format!("references in {}s may only refer \
+ to immutable values", item.const_kind())
+ );
+ err.span_label(span, format!("{}s require immutable values",
+ item.const_kind()));
+ if item.tcx.sess.teach(&err.get_code().unwrap()) {
+ err.note("References in statics and constants may only refer \
+ to immutable values.\n\n\
+ Statics are shared everywhere, and if they refer to \
+ mutable data one might violate memory safety since \
+ holding multiple mutable references to shared data \
+ is not allowed.\n\n\
+ If you really want global mutable state, try using \
+ static mut or a global UnsafeCell.");
}
+ err.emit();
}
}
#[derive(Debug)]
pub struct MutDeref;
-impl NonConstOp for MutDeref {}
+impl NonConstOp for MutDeref {
+ fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
+ Some(tcx.features().const_mut_refs)
+ }
+}
#[derive(Debug)]
pub struct Panic;
@@ -327,22 +341,6 @@
}
#[derive(Debug)]
-pub struct Transmute;
-impl NonConstOp for Transmute {
- fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
- Some(tcx.features().const_transmute)
- }
-
- fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
- feature_err(
- &item.tcx.sess.parse_sess, sym::const_transmute, span,
- &format!("The use of std::mem::transmute() is gated in {}s", item.const_kind())
- )
- .emit();
- }
-}
-
-#[derive(Debug)]
pub struct UnionAccess;
impl NonConstOp for UnionAccess {
fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool {
diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs
index 9ed1ca7..223a5f8 100644
--- a/src/librustc_mir/transform/check_consts/qualifs.rs
+++ b/src/librustc_mir/transform/check_consts/qualifs.rs
@@ -5,7 +5,7 @@
use rustc::hir::def_id::DefId;
use syntax_pos::DUMMY_SP;
-use super::{ConstKind, Item as ConstCx};
+use super::Item as ConstCx;
pub fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> ConstQualifs {
ConstQualifs {
@@ -33,9 +33,10 @@
/// of the type.
fn in_any_value_of_ty(_cx: &ConstCx<'_, 'tcx>, _ty: Ty<'tcx>) -> bool;
- fn in_static(_cx: &ConstCx<'_, 'tcx>, _def_id: DefId) -> bool {
- // FIXME(eddyb) should we do anything here for value properties?
- false
+ fn in_static(cx: &ConstCx<'_, 'tcx>, def_id: DefId) -> bool {
+ // `mir_const_qualif` does return the qualifs in the final value of a `static`, so we could
+ // use value-based qualification here, but we shouldn't do this without a good reason.
+ Self::in_any_value_of_ty(cx, cx.tcx.type_of(def_id))
}
fn in_projection_structurally(
@@ -50,7 +51,7 @@
});
let qualif = base_qualif && Self::in_any_value_of_ty(
cx,
- Place::ty_from(place.base, proj_base, cx.body, cx.tcx)
+ Place::ty_from(place.base, proj_base, *cx.body, cx.tcx)
.projection_ty(cx.tcx, elem)
.ty,
);
@@ -154,7 +155,7 @@
// Special-case reborrows to be more like a copy of the reference.
if let &[ref proj_base @ .., elem] = place.projection.as_ref() {
if ProjectionElem::Deref == elem {
- let base_ty = Place::ty_from(&place.base, proj_base, cx.body, cx.tcx).ty;
+ let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty;
if let ty::Ref(..) = base_ty.kind {
return Self::in_place(cx, per_local, PlaceRef {
base: &place.base,
@@ -217,38 +218,10 @@
rvalue: &Rvalue<'tcx>,
) -> bool {
match *rvalue {
- // Returning `true` for `Rvalue::Ref` indicates the borrow isn't
- // allowed in constants (and the `Checker` will error), and/or it
- // won't be promoted, due to `&mut ...` or interior mutability.
- Rvalue::Ref(_, kind, ref place) => {
- let ty = place.ty(cx.body, cx.tcx).ty;
-
- if let BorrowKind::Mut { .. } = kind {
- // In theory, any zero-sized value could be borrowed
- // mutably without consequences.
- match ty.kind {
- // Inside a `static mut`, &mut [...] is also allowed.
- | ty::Array(..)
- | ty::Slice(_)
- if cx.const_kind == Some(ConstKind::StaticMut)
- => {},
-
- // FIXME(eddyb): We only return false for `&mut []` outside a const
- // context which seems unnecessary given that this is merely a ZST.
- | ty::Array(_, len)
- if len.try_eval_usize(cx.tcx, cx.param_env) == Some(0)
- && cx.const_kind == None
- => {},
-
- _ => return true,
- }
- }
- }
-
Rvalue::Aggregate(ref kind, _) => {
if let AggregateKind::Adt(def, ..) = **kind {
if Some(def.did) == cx.tcx.lang_items().unsafe_cell_type() {
- let ty = rvalue.ty(cx.body, cx.tcx);
+ let ty = rvalue.ty(*cx.body, cx.tcx);
assert_eq!(Self::in_any_value_of_ty(cx, ty), true);
return true;
}
diff --git a/src/librustc_mir/transform/check_consts/resolver.rs b/src/librustc_mir/transform/check_consts/resolver.rs
index 8909ef7..cb54248 100644
--- a/src/librustc_mir/transform/check_consts/resolver.rs
+++ b/src/librustc_mir/transform/check_consts/resolver.rs
@@ -77,7 +77,7 @@
args: &[mir::Operand<'tcx>],
return_place: &mir::Place<'tcx>,
) {
- let return_ty = return_place.ty(self.item.body, self.item.tcx).ty;
+ let return_ty = return_place.ty(*self.item.body, self.item.tcx).ty;
let qualif = Q::in_call(
self.item,
&|l| self.qualifs_per_local.contains(l),
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index 829d9ee..7170857 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -8,7 +8,6 @@
use rustc::ty::cast::CastTy;
use rustc::ty::{self, TyCtxt};
use rustc_index::bit_set::BitSet;
-use rustc_target::spec::abi::Abi;
use rustc_error_codes::*;
use syntax::symbol::sym;
use syntax_pos::Span;
@@ -23,13 +22,6 @@
use super::resolver::FlowSensitiveAnalysis;
use super::{ConstKind, Item, Qualif, is_lang_panic_fn};
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum CheckOpResult {
- Forbidden,
- Unleashed,
- Allowed,
-}
-
pub type IndirectlyMutableResults<'mir, 'tcx> =
old_dataflow::DataflowResultsCursor<'mir, 'tcx, IndirectlyMutableLocals<'mir, 'tcx>>;
@@ -46,9 +38,9 @@
) -> Self {
let analysis = FlowSensitiveAnalysis::new(q, item);
let results =
- dataflow::Engine::new(item.tcx, item.body, item.def_id, dead_unwinds, analysis)
+ dataflow::Engine::new(item.tcx, &item.body, item.def_id, dead_unwinds, analysis)
.iterate_to_fixpoint();
- let cursor = dataflow::ResultsCursor::new(item.body, results);
+ let cursor = dataflow::ResultsCursor::new(item.body.body(), results);
let mut in_any_value_of_ty = BitSet::new_empty(item.body.local_decls.len());
for (local, decl) in item.body.local_decls.iter_enumerated() {
@@ -149,17 +141,6 @@
/// The span of the current statement.
span: Span,
-
- /// True if the local was assigned the result of an illegal borrow (`ops::MutBorrow`).
- ///
- /// This is used to hide errors from {re,}borrowing the newly-assigned local, instead pointing
- /// the user to the place where the illegal borrow occurred. This set is only populated once an
- /// error has been emitted, so it will never cause an erroneous `mir::Body` to pass validation.
- ///
- /// FIXME(ecstaticmorse): assert at the end of checking that if `tcx.has_errors() == false`,
- /// this set is empty. Note that if we start removing locals from
- /// `derived_from_illegal_borrow`, just checking at the end won't be enough.
- derived_from_illegal_borrow: BitSet<Local>,
}
impl Deref for Validator<'_, 'mir, 'tcx> {
@@ -190,17 +171,17 @@
let indirectly_mutable = old_dataflow::do_dataflow(
item.tcx,
- item.body,
+ &*item.body,
item.def_id,
&item.tcx.get_attrs(item.def_id),
&dead_unwinds,
- old_dataflow::IndirectlyMutableLocals::new(item.tcx, item.body, item.param_env),
+ old_dataflow::IndirectlyMutableLocals::new(item.tcx, item.body.body(), item.param_env),
|_, local| old_dataflow::DebugFormatted::new(&local),
);
let indirectly_mutable = old_dataflow::DataflowResultsCursor::new(
indirectly_mutable,
- item.body,
+ item.body.body(),
);
let qualifs = Qualifs {
@@ -213,7 +194,6 @@
span: item.body.span,
item,
qualifs,
- derived_from_illegal_borrow: BitSet::new_empty(item.body.local_decls.len()),
}
}
@@ -221,13 +201,13 @@
let Item { tcx, body, def_id, const_kind, .. } = *self.item;
let use_min_const_fn_checks =
- tcx.is_min_const_fn(def_id)
+ (const_kind == Some(ConstKind::ConstFn) && tcx.is_min_const_fn(def_id))
&& !tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you;
if use_min_const_fn_checks {
// Enforce `min_const_fn` for stable `const fn`s.
use crate::transform::qualify_min_const_fn::is_min_const_fn;
- if let Err((span, err)) = is_min_const_fn(tcx, def_id, body) {
+ if let Err((span, err)) = is_min_const_fn(tcx, def_id, &body) {
error_min_const_fn_violation(tcx, span, err);
return;
}
@@ -249,7 +229,7 @@
if should_check_for_sync {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
- check_return_ty_is_sync(tcx, body, hir_id);
+ check_return_ty_is_sync(tcx, &body, hir_id);
}
}
@@ -258,15 +238,15 @@
}
/// Emits an error at the given `span` if an expression cannot be evaluated in the current
- /// context. Returns `Forbidden` if an error was emitted.
- pub fn check_op_spanned<O>(&mut self, op: O, span: Span) -> CheckOpResult
+ /// context.
+ pub fn check_op_spanned<O>(&mut self, op: O, span: Span)
where
O: NonConstOp
{
trace!("check_op: op={:?}", op);
if op.is_allowed_in_item(self) {
- return CheckOpResult::Allowed;
+ return;
}
// If an operation is supported in miri (and is not already controlled by a feature gate) it
@@ -276,20 +256,19 @@
if is_unleashable && self.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
self.tcx.sess.span_warn(span, "skipping const checks");
- return CheckOpResult::Unleashed;
+ return;
}
op.emit_error(self, span);
- CheckOpResult::Forbidden
}
/// Emits an error if an expression cannot be evaluated in the current context.
- pub fn check_op(&mut self, op: impl NonConstOp) -> CheckOpResult {
+ pub fn check_op(&mut self, op: impl NonConstOp) {
let span = self.span;
self.check_op_spanned(op, span)
}
- fn check_static(&mut self, def_id: DefId, span: Span) -> CheckOpResult {
+ fn check_static(&mut self, def_id: DefId, span: Span) {
let is_thread_local = self.tcx.has_attr(def_id, sym::thread_local);
if is_thread_local {
self.check_op_spanned(ops::ThreadLocalAccess, span)
@@ -322,20 +301,9 @@
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
trace!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location);
- // Check nested operands and places.
+ // Special-case reborrows to be more like a copy of a reference.
if let Rvalue::Ref(_, kind, ref place) = *rvalue {
- // Special-case reborrows to be more like a copy of a reference.
- let mut reborrow_place = None;
- if let &[ref proj_base @ .., elem] = place.projection.as_ref() {
- if elem == ProjectionElem::Deref {
- let base_ty = Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty;
- if let ty::Ref(..) = base_ty.kind {
- reborrow_place = Some(proj_base);
- }
- }
- }
-
- if let Some(proj) = reborrow_place {
+ if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) {
let ctx = match kind {
BorrowKind::Shared => PlaceContext::NonMutatingUse(
NonMutatingUseContext::SharedBorrow,
@@ -351,14 +319,13 @@
),
};
self.visit_place_base(&place.base, ctx, location);
- self.visit_projection(&place.base, proj, ctx, location);
- } else {
- self.super_rvalue(rvalue, location);
+ self.visit_projection(&place.base, reborrowed_proj, ctx, location);
+ return;
}
- } else {
- self.super_rvalue(rvalue, location);
}
+ self.super_rvalue(rvalue, location);
+
match *rvalue {
Rvalue::Use(_) |
Rvalue::Repeat(..) |
@@ -369,11 +336,68 @@
Rvalue::Cast(CastKind::Pointer(_), ..) |
Rvalue::Discriminant(..) |
Rvalue::Len(_) |
- Rvalue::Ref(..) |
Rvalue::Aggregate(..) => {}
+ | Rvalue::Ref(_, kind @ BorrowKind::Mut { .. }, ref place)
+ | Rvalue::Ref(_, kind @ BorrowKind::Unique, ref place)
+ => {
+ let ty = place.ty(*self.body, self.tcx).ty;
+ let is_allowed = match ty.kind {
+ // Inside a `static mut`, `&mut [...]` is allowed.
+ ty::Array(..) | ty::Slice(_) if self.const_kind() == ConstKind::StaticMut
+ => true,
+
+ // FIXME(ecstaticmorse): We could allow `&mut []` inside a const context given
+ // that this is merely a ZST and it is already eligible for promotion.
+ // This may require an RFC?
+ /*
+ ty::Array(_, len) if len.try_eval_usize(cx.tcx, cx.param_env) == Some(0)
+ => true,
+ */
+
+ _ => false,
+ };
+
+ if !is_allowed {
+ if let BorrowKind::Mut{ .. } = kind {
+ self.check_op(ops::MutBorrow);
+ } else {
+ self.check_op(ops::CellBorrow);
+ }
+ }
+ }
+
+ // At the moment, `PlaceBase::Static` is only used for promoted MIR.
+ | Rvalue::Ref(_, BorrowKind::Shared, ref place)
+ | Rvalue::Ref(_, BorrowKind::Shallow, ref place)
+ if matches!(place.base, PlaceBase::Static(_))
+ => bug!("Saw a promoted during const-checking, which must run before promotion"),
+
+ | Rvalue::Ref(_, kind @ BorrowKind::Shared, ref place)
+ | Rvalue::Ref(_, kind @ BorrowKind::Shallow, ref place)
+ => {
+ // FIXME: Change the `in_*` methods to take a `FnMut` so we don't have to manually
+ // seek the cursors beforehand.
+ self.qualifs.has_mut_interior.cursor.seek_before(location);
+ self.qualifs.indirectly_mutable.seek(location);
+
+ let borrowed_place_has_mut_interior = HasMutInterior::in_place(
+ &self.item,
+ &|local| self.qualifs.has_mut_interior_eager_seek(local),
+ place.as_ref(),
+ );
+
+ if borrowed_place_has_mut_interior {
+ if let BorrowKind::Mut{ .. } = kind {
+ self.check_op(ops::MutBorrow);
+ } else {
+ self.check_op(ops::CellBorrow);
+ }
+ }
+ }
+
Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
- let operand_ty = operand.ty(self.body, self.tcx);
+ let operand_ty = operand.ty(*self.body, self.tcx);
let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
@@ -384,7 +408,7 @@
}
Rvalue::BinaryOp(op, ref lhs, _) => {
- if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind {
+ if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(*self.body, self.tcx).kind {
assert!(op == BinOp::Eq || op == BinOp::Ne ||
op == BinOp::Le || op == BinOp::Lt ||
op == BinOp::Ge || op == BinOp::Gt ||
@@ -435,59 +459,6 @@
}
}
}
-
- fn visit_assign(&mut self, dest: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
- trace!("visit_assign: dest={:?} rvalue={:?} location={:?}", dest, rvalue, location);
-
- // Error on mutable borrows or shared borrows of values with interior mutability.
- //
- // This replicates the logic at the start of `assign` in the old const checker. Note that
- // it depends on `HasMutInterior` being set for mutable borrows as well as values with
- // interior mutability.
- if let Rvalue::Ref(_, kind, ref borrowed_place) = *rvalue {
- // FIXME: Change the `in_*` methods to take a `FnMut` so we don't have to manually seek
- // the cursors beforehand.
- self.qualifs.has_mut_interior.cursor.seek_before(location);
- self.qualifs.indirectly_mutable.seek(location);
-
- let rvalue_has_mut_interior = HasMutInterior::in_rvalue(
- &self.item,
- &|local| self.qualifs.has_mut_interior_eager_seek(local),
- rvalue,
- );
-
- if rvalue_has_mut_interior {
- let is_derived_from_illegal_borrow = match borrowed_place.as_local() {
- // If an unprojected local was borrowed and its value was the result of an
- // illegal borrow, suppress this error and mark the result of this borrow as
- // illegal as well.
- Some(borrowed_local)
- if self.derived_from_illegal_borrow.contains(borrowed_local) =>
- {
- true
- }
-
- // Otherwise proceed normally: check the legality of a mutable borrow in this
- // context.
- _ => self.check_op(ops::MutBorrow(kind)) == CheckOpResult::Forbidden,
- };
-
- // When the target of the assignment is a local with no projections, mark it as
- // derived from an illegal borrow if necessary.
- //
- // FIXME: should we also clear `derived_from_illegal_borrow` when a local is
- // assigned a new value?
- if is_derived_from_illegal_borrow {
- if let Some(dest) = dest.as_local() {
- self.derived_from_illegal_borrow.insert(dest);
- }
- }
- }
- }
-
- self.super_assign(dest, rvalue, location);
- }
-
fn visit_projection_elem(
&mut self,
place_base: &PlaceBase<'tcx>,
@@ -510,7 +481,7 @@
match elem {
ProjectionElem::Deref => {
- let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty;
+ let base_ty = Place::ty_from(place_base, proj_base, *self.body, self.tcx).ty;
if let ty::RawPtr(_) = base_ty.kind {
if proj_base.is_empty() {
if let (PlaceBase::Local(local), []) = (place_base, proj_base) {
@@ -534,7 +505,7 @@
ProjectionElem::Subslice {..} |
ProjectionElem::Field(..) |
ProjectionElem::Index(_) => {
- let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty;
+ let base_ty = Place::ty_from(place_base, proj_base, *self.body, self.tcx).ty;
match base_ty.ty_adt_def() {
Some(def) if def.is_union() => {
self.check_op(ops::UnionAccess);
@@ -583,7 +554,7 @@
match kind {
TerminatorKind::Call { func, .. } => {
- let fn_ty = func.ty(self.body, self.tcx);
+ let fn_ty = func.ty(*self.body, self.tcx);
let def_id = match fn_ty.kind {
ty::FnDef(def_id, _) => def_id,
@@ -599,23 +570,6 @@
};
// At this point, we are calling a function whose `DefId` is known...
-
- if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = self.tcx.fn_sig(def_id).abi() {
- assert!(!self.tcx.is_const_fn(def_id));
-
- if self.tcx.item_name(def_id) == sym::transmute {
- self.check_op(ops::Transmute);
- return;
- }
-
- // To preserve the current semantics, we return early, allowing all
- // intrinsics (except `transmute`) to pass unchecked to miri.
- //
- // FIXME: We should keep a whitelist of allowed intrinsics (or at least a
- // blacklist of unimplemented ones) and fail here instead.
- return;
- }
-
if self.tcx.is_const_fn(def_id) {
return;
}
@@ -644,7 +598,7 @@
// Check to see if the type of this place can ever have a drop impl. If not, this
// `Drop` terminator is frivolous.
let ty_needs_drop = dropped_place
- .ty(self.body, self.tcx)
+ .ty(*self.body, self.tcx)
.ty
.needs_drop(self.tcx, self.param_env);
@@ -724,3 +678,36 @@
}
});
}
+
+fn place_as_reborrow(
+ tcx: TyCtxt<'tcx>,
+ body: &Body<'tcx>,
+ place: &'a Place<'tcx>,
+) -> Option<&'a [PlaceElem<'tcx>]> {
+ place
+ .projection
+ .split_last()
+ .and_then(|(outermost, inner)| {
+ if outermost != &ProjectionElem::Deref {
+ return None;
+ }
+
+ // A borrow of a `static` also looks like `&(*_1)` in the MIR, but `_1` is a `const`
+ // that points to the allocation for the static. Don't treat these as reborrows.
+ if let PlaceBase::Local(local) = place.base {
+ if body.local_decls[local].is_ref_to_static() {
+ return None;
+ }
+ }
+
+ // Ensure the type being derefed is a reference and not a raw pointer.
+ //
+ // This is sufficient to prevent an access to a `static mut` from being marked as a
+ // reborrow, even if the check above were to disappear.
+ let inner_ty = Place::ty_from(&place.base, inner, body, tcx).ty;
+ match inner_ty.kind {
+ ty::Ref(..) => Some(inner),
+ _ => None,
+ }
+ })
+}
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index b7cc4e9..284285c 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -1,6 +1,4 @@
use rustc_data_structures::fx::FxHashSet;
-use rustc_index::vec::IndexVec;
-use rustc_data_structures::sync::Lrc;
use rustc::ty::query::Providers;
use rustc::ty::{self, TyCtxt};
@@ -24,7 +22,6 @@
body: &'a Body<'tcx>,
const_context: bool,
min_const_fn: bool,
- source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
violations: Vec<UnsafetyViolation>,
source_info: SourceInfo,
tcx: TyCtxt<'tcx>,
@@ -39,7 +36,6 @@
const_context: bool,
min_const_fn: bool,
body: &'a Body<'tcx>,
- source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Self {
@@ -51,7 +47,6 @@
body,
const_context,
min_const_fn,
- source_scope_local_data,
violations: vec![],
source_info: SourceInfo {
span: body.span,
@@ -219,8 +214,11 @@
if context.is_borrow() {
if util::is_disaligned(self.tcx, self.body, self.param_env, place) {
let source_info = self.source_info;
- let lint_root =
- self.source_scope_local_data[source_info.scope].lint_root;
+ let lint_root = self.body.source_scopes[source_info.scope]
+ .local_data
+ .as_ref()
+ .assert_crate_local()
+ .lint_root;
self.register_violations(&[UnsafetyViolation {
source_info,
description: Symbol::intern("borrow of packed field"),
@@ -346,7 +344,11 @@
fn register_violations(&mut self,
violations: &[UnsafetyViolation],
unsafe_blocks: &[(hir::HirId, bool)]) {
- let safety = self.source_scope_local_data[self.source_info.scope].safety;
+ let safety = self.body.source_scopes[self.source_info.scope]
+ .local_data
+ .as_ref()
+ .assert_crate_local()
+ .safety;
let within_unsafe = match safety {
// `unsafe` blocks are required in safe code
Safety::Safe => {
@@ -516,17 +518,6 @@
// `mir_built` force this.
let body = &tcx.mir_built(def_id).borrow();
- let source_scope_local_data = match body.source_scope_local_data {
- ClearCrossCrate::Set(ref data) => data,
- ClearCrossCrate::Clear => {
- debug!("unsafety_violations: {:?} - remote, skipping", def_id);
- return UnsafetyCheckResult {
- violations: Lrc::new([]),
- unsafe_blocks: Lrc::new([])
- }
- }
- };
-
let param_env = tcx.param_env(def_id);
let id = tcx.hir().as_local_hir_id(def_id).unwrap();
@@ -536,9 +527,10 @@
hir::BodyOwnerKind::Const |
hir::BodyOwnerKind::Static(_) => (true, false),
};
- let mut checker = UnsafetyChecker::new(
- const_context, min_const_fn,
- body, source_scope_local_data, tcx, param_env);
+ let mut checker = UnsafetyChecker::new(const_context, min_const_fn, body, tcx, param_env);
+ // mir_built ensures that body has a computed cache, so we don't (and can't) attempt to
+ // recompute it here.
+ let body = body.unwrap_read_only();
checker.visit_body(body);
check_unused_unsafe(tcx, def_id, &checker.used_unsafe, &mut checker.inherited_blocks);
@@ -666,7 +658,7 @@
let mut unsafe_blocks: Vec<_> = unsafe_blocks.into_iter().collect();
unsafe_blocks.sort_by_cached_key(|(hir_id, _)| tcx.hir().hir_to_node_id(*hir_id));
let used_unsafe: FxHashSet<_> = unsafe_blocks.iter()
- .flat_map(|&&(id, used)| if used { Some(id) } else { None })
+ .flat_map(|&&(id, used)| used.then_some(id))
.collect();
for &(block_id, is_used) in unsafe_blocks {
if !is_used {
diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs
index 4fd4fe4..d9dd7c9 100644
--- a/src/librustc_mir/transform/cleanup_post_borrowck.rs
+++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs
@@ -16,7 +16,7 @@
//! [`FakeRead`]: rustc::mir::StatementKind::FakeRead
//! [`Nop`]: rustc::mir::StatementKind::Nop
-use rustc::mir::{BorrowKind, Rvalue, Location, Body};
+use rustc::mir::{BodyCache, BorrowKind, Rvalue, Location};
use rustc::mir::{Statement, StatementKind};
use rustc::mir::visit::MutVisitor;
use rustc::ty::TyCtxt;
@@ -29,7 +29,9 @@
}
impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(
+ &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+ ) {
let mut delete = DeleteNonCodegenStatements { tcx };
delete.visit_body(body);
}
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 0fe7530..95de635 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -7,9 +7,10 @@
use rustc::hir::def::DefKind;
use rustc::hir::def_id::DefId;
use rustc::mir::{
- AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, Local, UnOp,
- StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate, SourceInfo,
- BinOp, SourceScope, SourceScopeLocalData, LocalDecl, BasicBlock, RETURN_PLACE,
+ AggregateKind, Constant, Location, Place, PlaceBase, Body, BodyCache, Operand, Local, UnOp,
+ Rvalue, StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate,
+ SourceInfo, BinOp, SourceScope, SourceScopeData, LocalDecl, BasicBlock, ReadOnlyBodyCache,
+ read_only, RETURN_PLACE
};
use rustc::mir::visit::{
Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext,
@@ -41,7 +42,9 @@
pub struct ConstProp;
impl<'tcx> MirPass<'tcx> for ConstProp {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(
+ &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+ ) {
// will be evaluated by miri and produce its errors there
if source.promoted.is_some() {
return;
@@ -74,17 +77,10 @@
trace!("ConstProp starting for {:?}", source.def_id());
- // Steal some data we need from `body`.
- let source_scope_local_data = std::mem::replace(
- &mut body.source_scope_local_data,
- ClearCrossCrate::Clear
- );
-
let dummy_body =
&Body::new(
body.basic_blocks().clone(),
- Default::default(),
- ClearCrossCrate::Clear,
+ body.source_scopes.clone(),
body.local_decls.clone(),
Default::default(),
body.arg_count,
@@ -99,21 +95,13 @@
// That would require an uniform one-def no-mutation analysis
// and RPO (or recursing when needing the value of a local).
let mut optimization_finder = ConstPropagator::new(
- body,
+ read_only!(body),
dummy_body,
- source_scope_local_data,
tcx,
source
);
optimization_finder.visit_body(body);
- // put back the data we stole from `mir`
- let source_scope_local_data = optimization_finder.release_stolen_data();
- std::mem::replace(
- &mut body.source_scope_local_data,
- source_scope_local_data
- );
-
trace!("ConstProp done for {:?}", source.def_id());
}
}
@@ -140,7 +128,7 @@
false
}
- fn find_fn(
+ fn find_mir_or_eval_fn(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_instance: ty::Instance<'tcx>,
_args: &[OpTy<'tcx>],
@@ -171,6 +159,15 @@
throw_unsup!(ConstPropUnsupported("calling intrinsics isn't supported in ConstProp"));
}
+ fn assert_panic(
+ _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+ _span: Span,
+ _msg: &rustc::mir::interpret::AssertMessage<'tcx>,
+ _unwind: Option<rustc::mir::BasicBlock>,
+ ) -> InterpResult<'tcx> {
+ bug!("panics terminators are not evaluated in ConstProp");
+ }
+
fn ptr_to_int(
_mem: &Memory<'mir, 'tcx, Self>,
_ptr: Pointer,
@@ -197,7 +194,7 @@
}
#[inline(always)]
- fn tag_allocation<'b>(
+ fn init_allocation_extra<'b>(
_memory_extra: &(),
_id: AllocId,
alloc: Cow<'b, Allocation>,
@@ -267,7 +264,9 @@
source: MirSource<'tcx>,
can_const_prop: IndexVec<Local, bool>,
param_env: ParamEnv<'tcx>,
- source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
+ // FIXME(eddyb) avoid cloning these two fields more than once,
+ // by accessing them through `ecx` instead.
+ source_scopes: IndexVec<SourceScope, SourceScopeData>,
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
ret: Option<OpTy<'tcx, ()>>,
}
@@ -297,9 +296,8 @@
impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
fn new(
- body: &Body<'tcx>,
+ body: ReadOnlyBodyCache<'_, 'tcx>,
dummy_body: &'mir Body<'tcx>,
- source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
tcx: TyCtxt<'tcx>,
source: MirSource<'tcx>,
) -> ConstPropagator<'mir, 'tcx> {
@@ -337,17 +335,15 @@
source,
param_env,
can_const_prop,
- source_scope_local_data,
+ // FIXME(eddyb) avoid cloning these two fields more than once,
+ // by accessing them through `ecx` instead.
+ source_scopes: body.source_scopes.clone(),
//FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
local_decls: body.local_decls.clone(),
ret: ret.map(Into::into),
}
}
- fn release_stolen_data(self) -> ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>> {
- self.source_scope_local_data
- }
-
fn get_const(&self, local: Local) -> Option<Const<'tcx>> {
if local == RETURN_PLACE {
// Try to read the return place as an immediate so that if it is representable as a
@@ -377,14 +373,11 @@
F: FnOnce(&mut Self) -> InterpResult<'tcx, T>,
{
self.ecx.tcx.span = source_info.span;
- let lint_root = match self.source_scope_local_data {
- ClearCrossCrate::Set(ref ivs) => {
- //FIXME(#51314): remove this check
- if source_info.scope.index() >= ivs.len() {
- return None;
- }
- ivs[source_info.scope].lint_root
- },
+ // FIXME(eddyb) move this to the `Panic(_)` error case, so that
+ // `f(self)` is always called, and that the only difference when the
+ // scope's `local_data` is missing, is that the lint isn't emitted.
+ let lint_root = match &self.source_scopes[source_info.scope].local_data {
+ ClearCrossCrate::Set(data) => data.lint_root,
ClearCrossCrate::Clear => return None,
};
let r = match f(self) {
@@ -396,7 +389,7 @@
InterpError::*
};
match error.kind {
- Exit(_) => bug!("the CTFE program cannot exit"),
+ MachineStop(_) => bug!("ConstProp does not stop"),
// Some error shouldn't come up because creating them causes
// an allocation, which we should avoid. When that happens,
@@ -525,8 +518,8 @@
let right_size = r.layout.size;
let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
if r_bits.ok().map_or(false, |b| b >= left_bits as u128) {
- let source_scope_local_data = match self.source_scope_local_data {
- ClearCrossCrate::Set(ref data) => data,
+ let lint_root = match &self.source_scopes[source_info.scope].local_data {
+ ClearCrossCrate::Set(data) => data.lint_root,
ClearCrossCrate::Clear => return None,
};
let dir = if *op == BinOp::Shr {
@@ -534,10 +527,9 @@
} else {
"left"
};
- let hir_id = source_scope_local_data[source_info.scope].lint_root;
self.tcx.lint_hir(
::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
- hir_id,
+ lint_root,
span,
&format!("attempt to shift {} with overflow", dir));
return None;
@@ -698,7 +690,7 @@
impl CanConstProp {
/// returns true if `local` can be propagated
- fn check(body: &Body<'_>) -> IndexVec<Local, bool> {
+ fn check(body: ReadOnlyBodyCache<'_, '_>) -> IndexVec<Local, bool> {
let mut cpv = CanConstProp {
can_const_prop: IndexVec::from_elem(true, &body.local_decls),
found_assignment: IndexVec::from_elem(false, &body.local_decls),
diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs
index 4c26fea..5e4caf2 100644
--- a/src/librustc_mir/transform/copy_prop.rs
+++ b/src/librustc_mir/transform/copy_prop.rs
@@ -19,7 +19,10 @@
//! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the
//! future.
-use rustc::mir::{Constant, Local, LocalKind, Location, Place, Body, Operand, Rvalue, StatementKind};
+use rustc::mir::{
+ Constant, Local, LocalKind, Location, Place, Body, BodyCache, Operand, Rvalue,
+ StatementKind, read_only
+};
use rustc::mir::visit::MutVisitor;
use rustc::ty::TyCtxt;
use crate::transform::{MirPass, MirSource};
@@ -28,7 +31,9 @@
pub struct CopyPropagation;
impl<'tcx> MirPass<'tcx> for CopyPropagation {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(
+ &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+ ) {
// We only run when the MIR optimization level is > 1.
// This avoids a slow pass, and messing up debug info.
if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 {
@@ -37,10 +42,10 @@
let mut def_use_analysis = DefUseAnalysis::new(body);
loop {
- def_use_analysis.analyze(body);
+ def_use_analysis.analyze(read_only!(body));
if eliminate_self_assignments(body, &def_use_analysis) {
- def_use_analysis.analyze(body);
+ def_use_analysis.analyze(read_only!(body));
}
let mut changed = false;
@@ -97,7 +102,10 @@
let maybe_action = match operand {
Operand::Copy(ref src_place) |
Operand::Move(ref src_place) => {
- Action::local_copy(&body, &def_use_analysis, src_place)
+ Action::local_copy(
+ &body,
+ &def_use_analysis,
+ src_place)
}
Operand::Constant(ref src_constant) => {
Action::constant(src_constant)
@@ -126,8 +134,8 @@
}
}
- changed =
- action.perform(body, &def_use_analysis, dest_local, location, tcx) || changed;
+ changed = action.perform(body, &def_use_analysis, dest_local, location, tcx)
+ || changed;
// FIXME(pcwalton): Update the use-def chains to delete the instructions instead of
// regenerating the chains.
break
@@ -242,7 +250,7 @@
}
fn perform(self,
- body: &mut Body<'tcx>,
+ body: &mut BodyCache<'tcx>,
def_use_analysis: &DefUseAnalysis,
dest_local: Local,
location: Location,
@@ -270,7 +278,8 @@
}
// Replace all uses of the destination local with the source local.
- def_use_analysis.replace_all_defs_and_uses_with(dest_local, body, src_local, tcx);
+ def_use_analysis
+ .replace_all_defs_and_uses_with(dest_local, body, src_local, tcx);
// Finally, zap the now-useless assignment instruction.
debug!(" Deleting assignment");
diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs
index cdde9e1..933936e 100644
--- a/src/librustc_mir/transform/deaggregator.rs
+++ b/src/librustc_mir/transform/deaggregator.rs
@@ -6,7 +6,9 @@
pub struct Deaggregator;
impl<'tcx> MirPass<'tcx> for Deaggregator {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(
+ &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+ ) {
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
let local_decls = &*local_decls;
for bb in basic_blocks {
diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs
index ed0eff9..13b3bb6 100644
--- a/src/librustc_mir/transform/dump_mir.rs
+++ b/src/librustc_mir/transform/dump_mir.rs
@@ -5,7 +5,7 @@
use std::fs::File;
use std::io;
-use rustc::mir::Body;
+use rustc::mir::{Body, BodyCache};
use rustc::session::config::{OutputFilenames, OutputType};
use rustc::ty::TyCtxt;
use crate::transform::{MirPass, MirSource};
@@ -18,8 +18,9 @@
Cow::Borrowed(self.0)
}
- fn run_pass(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut Body<'tcx>) {
- }
+ fn run_pass(
+ &self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut BodyCache<'tcx>
+ ) {}
}
pub struct Disambiguator {
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index f91a08b..42daba9 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -21,7 +21,7 @@
pub struct ElaborateDrops;
impl<'tcx> MirPass<'tcx> for ElaborateDrops {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
debug!("elaborate_drops({:?} @ {:?})", src, body.span);
let def_id = src.def_id();
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index b30e2de..882e674 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -62,7 +62,7 @@
pub struct EraseRegions;
impl<'tcx> MirPass<'tcx> for EraseRegions {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
EraseRegionsVisitor::new(tcx).visit_body(body);
}
}
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 5d88629..e55737e 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -368,7 +368,7 @@
VariantIdx::new(RETURNED) // state for returned
};
data.statements.push(self.set_discr(state, source_info));
- data.terminator.as_mut().unwrap().kind = TerminatorKind::Return;
+ data.terminator_mut().kind = TerminatorKind::Return;
}
self.super_basic_block_data(block, data);
@@ -378,7 +378,7 @@
fn make_generator_state_argument_indirect<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
- body: &mut Body<'tcx>,
+ body: &mut BodyCache<'tcx>,
) {
let gen_ty = body.local_decls.raw[1].ty;
@@ -401,7 +401,7 @@
DerefArgVisitor { tcx }.visit_body(body);
}
-fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>) {
let ref_gen_ty = body.local_decls.raw[1].ty;
let pin_did = tcx.lang_items().pin_type().unwrap();
@@ -418,7 +418,7 @@
fn replace_result_variable<'tcx>(
ret_ty: Ty<'tcx>,
- body: &mut Body<'tcx>,
+ body: &mut BodyCache<'tcx>,
tcx: TyCtxt<'tcx>,
) -> Local {
let source_info = source_info(body);
@@ -481,20 +481,21 @@
fn locals_live_across_suspend_points(
tcx: TyCtxt<'tcx>,
- body: &Body<'tcx>,
+ body: ReadOnlyBodyCache<'_, 'tcx>,
source: MirSource<'tcx>,
movable: bool,
) -> LivenessInfo {
let dead_unwinds = BitSet::new_empty(body.basic_blocks().len());
let def_id = source.def_id();
+ let body_ref: &Body<'_> = &body;
// Calculate when MIR locals have live storage. This gives us an upper bound of their
// lifetimes.
- let storage_live_analysis = MaybeStorageLive::new(body);
+ let storage_live_analysis = MaybeStorageLive::new(body_ref);
let storage_live_results =
- do_dataflow(tcx, body, def_id, &[], &dead_unwinds, storage_live_analysis,
+ do_dataflow(tcx, body_ref, def_id, &[], &dead_unwinds, storage_live_analysis,
|bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
- let mut storage_live_cursor = DataflowResultsCursor::new(&storage_live_results, body);
+ let mut storage_live_cursor = DataflowResultsCursor::new(&storage_live_results, body_ref);
// Find the MIR locals which do not use StorageLive/StorageDead statements.
// The storage of these locals are always live.
@@ -503,19 +504,20 @@
// Calculate the MIR locals which have been previously
// borrowed (even if they are still active).
- let borrowed_locals_analysis = HaveBeenBorrowedLocals::new(body);
+ let borrowed_locals_analysis = HaveBeenBorrowedLocals::new(body_ref);
let borrowed_locals_results =
- do_dataflow(tcx, body, def_id, &[], &dead_unwinds, borrowed_locals_analysis,
+ do_dataflow(tcx, body_ref, def_id, &[], &dead_unwinds, borrowed_locals_analysis,
|bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
- let mut borrowed_locals_cursor = DataflowResultsCursor::new(&borrowed_locals_results, body);
+ let mut borrowed_locals_cursor = DataflowResultsCursor::new(&borrowed_locals_results, body_ref);
// Calculate the MIR locals that we actually need to keep storage around
// for.
let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_results);
let requires_storage_results =
- do_dataflow(tcx, body, def_id, &[], &dead_unwinds, requires_storage_analysis,
+ do_dataflow(tcx, body_ref, def_id, &[], &dead_unwinds, requires_storage_analysis,
|bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
- let mut requires_storage_cursor = DataflowResultsCursor::new(&requires_storage_results, body);
+ let mut requires_storage_cursor
+ = DataflowResultsCursor::new(&requires_storage_results, body_ref);
// Calculate the liveness of MIR locals ignoring borrows.
let mut live_locals = liveness::LiveVarSet::new_empty(body.local_decls.len());
@@ -526,7 +528,7 @@
tcx,
"generator_liveness",
source,
- body,
+ body_ref,
&liveness,
);
@@ -593,7 +595,7 @@
.collect();
let storage_conflicts = compute_storage_conflicts(
- body,
+ body_ref,
&live_locals,
&ignored,
requires_storage_results);
@@ -749,7 +751,7 @@
upvars: &Vec<Ty<'tcx>>,
interior: Ty<'tcx>,
movable: bool,
- body: &mut Body<'tcx>,
+ body: &mut BodyCache<'tcx>,
) -> (
FxHashMap<Local, (Ty<'tcx>, VariantIdx, usize)>,
GeneratorLayout<'tcx>,
@@ -758,7 +760,7 @@
// Use a liveness analysis to compute locals which are live across a suspension point
let LivenessInfo {
live_locals, live_locals_at_suspension_points, storage_conflicts, storage_liveness
- } = locals_live_across_suspend_points(tcx, body, source, movable);
+ } = locals_live_across_suspend_points(tcx, read_only!(body), source, movable);
// Erase regions from the types passed in from typeck so we can compare them with
// MIR types
@@ -828,7 +830,7 @@
}
fn insert_switch<'tcx>(
- body: &mut Body<'tcx>,
+ body: &mut BodyCache<'tcx>,
cases: Vec<(usize, BasicBlock)>,
transform: &TransformVisitor<'tcx>,
default: TerminatorKind<'tcx>,
@@ -859,7 +861,9 @@
}
}
-fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut Body<'tcx>) {
+fn elaborate_generator_drops<'tcx>(
+ tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut BodyCache<'tcx>
+) {
use crate::util::elaborate_drops::{elaborate_drop, Unwind};
use crate::util::patch::MirPatch;
use crate::shim::DropShimElaborator;
@@ -872,7 +876,7 @@
let gen = self_arg();
let mut elaborator = DropShimElaborator {
- body: body,
+ body,
patch: MirPatch::new(body),
tcx,
param_env
@@ -924,9 +928,9 @@
def_id: DefId,
source: MirSource<'tcx>,
gen_ty: Ty<'tcx>,
- body: &Body<'tcx>,
+ body: &mut BodyCache<'tcx>,
drop_clean: BasicBlock,
-) -> Body<'tcx> {
+) -> BodyCache<'tcx> {
let mut body = body.clone();
let source_info = source_info(&body);
@@ -992,7 +996,9 @@
body
}
-fn insert_term_block<'tcx>(body: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock {
+fn insert_term_block<'tcx>(
+ body: &mut BodyCache<'tcx>, kind: TerminatorKind<'tcx>
+) -> BasicBlock {
let term_block = BasicBlock::new(body.basic_blocks().len());
let source_info = source_info(body);
body.basic_blocks_mut().push(BasicBlockData {
@@ -1008,7 +1014,7 @@
fn insert_panic_block<'tcx>(
tcx: TyCtxt<'tcx>,
- body: &mut Body<'tcx>,
+ body: &mut BodyCache<'tcx>,
message: AssertMessage<'tcx>,
) -> BasicBlock {
let assert_block = BasicBlock::new(body.basic_blocks().len());
@@ -1042,7 +1048,7 @@
transform: TransformVisitor<'tcx>,
def_id: DefId,
source: MirSource<'tcx>,
- body: &mut Body<'tcx>,
+ body: &mut BodyCache<'tcx>,
) {
// Poison the generator when it unwinds
for block in body.basic_blocks_mut() {
@@ -1095,7 +1101,7 @@
}
}
-fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
+fn insert_clean_drop(body: &mut BodyCache<'_>) -> BasicBlock {
let return_block = insert_term_block(body, TerminatorKind::Return);
// Create a block to destroy an unresumed generators. This can only destroy upvars.
@@ -1119,7 +1125,7 @@
}
fn create_cases<'tcx, F>(
- body: &mut Body<'tcx>,
+ body: &mut BodyCache<'tcx>,
transform: &TransformVisitor<'tcx>,
target: F,
) -> Vec<(usize, BasicBlock)>
@@ -1163,7 +1169,9 @@
}
impl<'tcx> MirPass<'tcx> for StateTransform {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(
+ &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+ ) {
let yield_ty = if let Some(yield_ty) = body.yield_ty {
yield_ty
} else {
@@ -1252,12 +1260,12 @@
// Create a copy of our MIR and use it to create the drop shim for the generator
let drop_shim = create_generator_drop_shim(tcx,
- &transform,
- def_id,
- source,
- gen_ty,
- &body,
- drop_clean);
+ &transform,
+ def_id,
+ source,
+ gen_ty,
+ body,
+ drop_clean);
body.generator_drop = Some(box drop_shim);
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 867673b..79cb7fb 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -38,7 +38,9 @@
}
impl<'tcx> MirPass<'tcx> for Inline {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(
+ &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+ ) {
if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
Inliner { tcx, source }.run_pass(body);
}
@@ -51,7 +53,7 @@
}
impl Inliner<'tcx> {
- fn run_pass(&self, caller_body: &mut Body<'tcx>) {
+ fn run_pass(&self, caller_body: &mut BodyCache<'tcx>) {
// Keep a queue of callsites to try inlining on. We take
// advantage of the fact that queries detect cycles here to
// allow us to try and fetch the fully optimized MIR of a
@@ -75,9 +77,9 @@
{
for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated() {
if let Some(callsite) = self.get_valid_function_call(bb,
- bb_data,
- caller_body,
- param_env) {
+ bb_data,
+ caller_body,
+ param_env) {
callsites.push_back(callsite);
}
}
@@ -136,7 +138,8 @@
debug!("attempting to inline callsite {:?} - success", callsite);
// Add callsites from inlined function
- for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated().skip(start) {
+ for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated().skip(start)
+ {
if let Some(new_callsite) = self.get_valid_function_call(bb,
bb_data,
caller_body,
@@ -377,8 +380,8 @@
fn inline_call(&self,
callsite: CallSite<'tcx>,
- caller_body: &mut Body<'tcx>,
- mut callee_body: Body<'tcx>) -> bool {
+ caller_body: &mut BodyCache<'tcx>,
+ mut callee_body: BodyCache<'tcx>) -> bool {
let terminator = caller_body[callsite.bb].terminator.take().unwrap();
match terminator.kind {
// FIXME: Handle inlining of diverging calls
@@ -391,9 +394,14 @@
for mut scope in callee_body.source_scopes.iter().cloned() {
if scope.parent_scope.is_none() {
scope.parent_scope = Some(callsite.location.scope);
+ // FIXME(eddyb) is this really needed?
+ // (also note that it's always overwritten below)
scope.span = callee_body.span;
}
+ // FIXME(eddyb) this doesn't seem right at all.
+ // The inlined source scopes should probably be annotated as
+ // such, but also contain all of the original information.
scope.span = callsite.location.span;
let idx = caller_body.source_scopes.push(scope);
@@ -440,7 +448,7 @@
BorrowKind::Mut { allow_two_phase_borrow: false },
destination.0);
- let ty = dest.ty(caller_body, self.tcx);
+ let ty = dest.ty(&**caller_body, self.tcx);
let temp = LocalDecl::new_temp(ty, callsite.location.span);
@@ -509,7 +517,7 @@
&self,
args: Vec<Operand<'tcx>>,
callsite: &CallSite<'tcx>,
- caller_body: &mut Body<'tcx>,
+ caller_body: &mut BodyCache<'tcx>,
) -> Vec<Local> {
let tcx = self.tcx;
@@ -538,12 +546,14 @@
// and the vector is `[closure_ref, tmp0, tmp1, tmp2]`.
if tcx.is_closure(callsite.callee) {
let mut args = args.into_iter();
- let self_ = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body);
- let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body);
+ let self_
+ = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body);
+ let tuple
+ = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body);
assert!(args.next().is_none());
let tuple = Place::from(tuple);
- let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_body, tcx).ty.kind {
+ let tuple_tys = if let ty::Tuple(s) = tuple.ty(&**caller_body, tcx).ty.kind {
s
} else {
bug!("Closure arguments are not passed as a tuple");
@@ -580,7 +590,7 @@
&self,
arg: Operand<'tcx>,
callsite: &CallSite<'tcx>,
- caller_body: &mut Body<'tcx>,
+ caller_body: &mut BodyCache<'tcx>,
) -> Local {
// FIXME: Analysis of the usage of the arguments to avoid
// unnecessary temporaries.
@@ -598,7 +608,7 @@
// Otherwise, create a temporary for the arg
let arg = Rvalue::Use(arg);
- let ty = arg.ty(caller_body, self.tcx);
+ let ty = arg.ty(&**caller_body, self.tcx);
let arg_tmp = LocalDecl::new_temp(ty, callsite.location.span);
let arg_tmp = caller_body.local_decls.push(arg_tmp);
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index a567ed6..bd237b5 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -1,7 +1,8 @@
//! Performs various peephole optimizations.
use rustc::mir::{
- Constant, Location, Place, PlaceBase, PlaceRef, Body, Operand, ProjectionElem, Rvalue, Local
+ Constant, Location, Place, PlaceBase, PlaceRef, Body, BodyCache, Operand, ProjectionElem,
+ Rvalue, Local, read_only
};
use rustc::mir::visit::{MutVisitor, Visitor};
use rustc::ty::{self, TyCtxt};
@@ -13,7 +14,7 @@
pub struct InstCombine;
impl<'tcx> MirPass<'tcx> for InstCombine {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
// We only run when optimizing MIR (at any level).
if tcx.sess.opts.debugging_opts.mir_opt_level == 0 {
return
@@ -23,8 +24,9 @@
// read-only so that we can do global analyses on the MIR in the process (e.g.
// `Place::ty()`).
let optimizations = {
+ let read_only_cache = read_only!(body);
let mut optimization_finder = OptimizationFinder::new(body, tcx);
- optimization_finder.visit_body(body);
+ optimization_finder.visit_body(read_only_cache);
optimization_finder.optimizations
};
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 2b2b529..df4cb76 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -1,7 +1,7 @@
use crate::{build, shim};
use rustc_index::vec::IndexVec;
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc::mir::{Body, MirPhase, Promoted, ConstQualifs};
+use rustc::mir::{BodyCache, MirPhase, Promoted, ConstQualifs};
use rustc::ty::{TyCtxt, InstanceDef, TypeFoldable};
use rustc::ty::query::Providers;
use rustc::ty::steal::Steal;
@@ -97,7 +97,7 @@
tcx.arena.alloc(set)
}
-fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<Body<'_>> {
+fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<BodyCache<'_>> {
let mir = build::mir_build(tcx, def_id);
tcx.alloc_steal_mir(mir)
}
@@ -144,12 +144,12 @@
default_name::<Self>()
}
- fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>);
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>);
}
pub fn run_passes(
tcx: TyCtxt<'tcx>,
- body: &mut Body<'tcx>,
+ body: &mut BodyCache<'tcx>,
instance: InstanceDef<'tcx>,
promoted: Option<Promoted>,
mir_phase: MirPhase,
@@ -205,7 +205,7 @@
}
let item = check_consts::Item {
- body,
+ body: body.unwrap_read_only(),
tcx,
def_id,
const_kind,
@@ -220,7 +220,7 @@
validator.qualifs_in_return_place().into()
}
-fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<Body<'_>> {
+fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<BodyCache<'_>> {
// Unsafety check uses the raw mir, so make sure it is run
let _ = tcx.unsafety_check_result(def_id);
@@ -231,13 +231,14 @@
&rustc_peek::SanityCheck,
&uniform_array_move_out::UniformArrayMoveOut,
]);
+ body.ensure_predecessors();
tcx.alloc_steal_mir(body)
}
fn mir_validated(
tcx: TyCtxt<'tcx>,
def_id: DefId,
-) -> (&'tcx Steal<Body<'tcx>>, &'tcx Steal<IndexVec<Promoted, Body<'tcx>>>) {
+) -> (&'tcx Steal<BodyCache<'tcx>>, &'tcx Steal<IndexVec<Promoted, BodyCache<'tcx>>>) {
// Ensure that we compute the `mir_const_qualif` for constants at
// this point, before we steal the mir-const result.
let _ = tcx.mir_const_qualif(def_id);
@@ -249,13 +250,14 @@
&promote_pass,
&simplify::SimplifyCfg::new("qualify-consts"),
]);
+
let promoted = promote_pass.promoted_fragments.into_inner();
(tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted))
}
fn run_optimization_passes<'tcx>(
tcx: TyCtxt<'tcx>,
- body: &mut Body<'tcx>,
+ body: &mut BodyCache<'tcx>,
def_id: DefId,
promoted: Option<Promoted>,
) {
@@ -317,7 +319,7 @@
]);
}
-fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> {
+fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &BodyCache<'_> {
if tcx.is_constructor(def_id) {
// There's no reason to run all of the MIR passes on constructors when
// we can just output the MIR we want directly. This also saves const
@@ -333,10 +335,11 @@
let (body, _) = tcx.mir_validated(def_id);
let mut body = body.steal();
run_optimization_passes(tcx, &mut body, def_id, None);
+ body.ensure_predecessors();
tcx.arena.alloc(body)
}
-fn promoted_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
+fn promoted_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &IndexVec<Promoted, BodyCache<'_>> {
if tcx.is_constructor(def_id) {
return tcx.intern_promoted(IndexVec::new());
}
@@ -347,6 +350,7 @@
for (p, mut body) in promoted.iter_enumerated_mut() {
run_optimization_passes(tcx, &mut body, def_id, Some(p));
+ body.ensure_predecessors();
}
tcx.intern_promoted(promoted)
diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs
index fbd14d9..5e1d29d 100644
--- a/src/librustc_mir/transform/no_landing_pads.rs
+++ b/src/librustc_mir/transform/no_landing_pads.rs
@@ -17,12 +17,12 @@
}
impl<'tcx> MirPass<'tcx> for NoLandingPads<'tcx> {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
no_landing_pads(tcx, body)
}
}
-pub fn no_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+pub fn no_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>) {
if tcx.sess.no_landing_pads() {
NoLandingPads::new(tcx).visit_body(body);
}
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index cc6108c..c758ccf 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -41,11 +41,11 @@
/// newly created `StaticKind::Promoted`.
#[derive(Default)]
pub struct PromoteTemps<'tcx> {
- pub promoted_fragments: Cell<IndexVec<Promoted, Body<'tcx>>>,
+ pub promoted_fragments: Cell<IndexVec<Promoted, BodyCache<'tcx>>>,
}
impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
// There's not really any point in promoting errorful MIR.
//
// This does not include MIR that failed const-checking, which we still try to promote.
@@ -63,7 +63,8 @@
let mut rpo = traversal::reverse_postorder(body);
let (temps, all_candidates) = collect_temps_and_candidates(tcx, body, &mut rpo);
- let promotable_candidates = validate_candidates(tcx, body, def_id, &temps, &all_candidates);
+ let promotable_candidates
+ = validate_candidates(tcx, read_only!(body), def_id, &temps, &all_candidates);
let promoted = promote_candidates(def_id, body, tcx, temps, promotable_candidates);
self.promoted_fragments.set(promoted);
@@ -346,10 +347,14 @@
while let [proj_base @ .., elem] = place_projection {
// FIXME(eddyb) this is probably excessive, with
// the exception of `union` member accesses.
- let ty =
- Place::ty_from(&place.base, proj_base, self.body, self.tcx)
- .projection_ty(self.tcx, elem)
- .ty;
+ let ty = Place::ty_from(
+ &place.base,
+ proj_base,
+ *self.body,
+ self.tcx
+ )
+ .projection_ty(self.tcx, elem)
+ .ty;
if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) {
has_mut_interior = false;
break;
@@ -368,7 +373,7 @@
}
if let BorrowKind::Mut { .. } = kind {
- let ty = place.ty(self.body, self.tcx).ty;
+ let ty = place.ty(*self.body, self.tcx).ty;
// In theory, any zero-sized value could be borrowed
// mutably without consequences. However, only &mut []
@@ -517,7 +522,7 @@
ProjectionElem::Field(..) => {
if self.const_kind.is_none() {
let base_ty =
- Place::ty_from(place.base, proj_base, self.body, self.tcx).ty;
+ Place::ty_from(place.base, proj_base, *self.body, self.tcx).ty;
if let Some(def) = base_ty.ty_adt_def() {
// No promotion of union field accesses.
if def.is_union() {
@@ -566,7 +571,7 @@
fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> {
match *rvalue {
Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) if self.const_kind.is_none() => {
- let operand_ty = operand.ty(self.body, self.tcx);
+ let operand_ty = operand.ty(*self.body, self.tcx);
let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
match (cast_in, cast_out) {
@@ -580,7 +585,7 @@
}
Rvalue::BinaryOp(op, ref lhs, _) if self.const_kind.is_none() => {
- if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind {
+ if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(*self.body, self.tcx).kind {
assert!(op == BinOp::Eq || op == BinOp::Ne ||
op == BinOp::Le || op == BinOp::Lt ||
op == BinOp::Ge || op == BinOp::Gt ||
@@ -615,7 +620,7 @@
Rvalue::Ref(_, kind, place) => {
if let BorrowKind::Mut { .. } = kind {
- let ty = place.ty(self.body, self.tcx).ty;
+ let ty = place.ty(*self.body, self.tcx).ty;
// In theory, any zero-sized value could be borrowed
// mutably without consequences. However, only &mut []
@@ -642,7 +647,7 @@
let mut place = place.as_ref();
if let [proj_base @ .., ProjectionElem::Deref] = &place.projection {
let base_ty =
- Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty;
+ Place::ty_from(&place.base, proj_base, *self.body, self.tcx).ty;
if let ty::Ref(..) = base_ty.kind {
place = PlaceRef {
base: &place.base,
@@ -668,7 +673,7 @@
while let [proj_base @ .., elem] = place_projection {
// FIXME(eddyb) this is probably excessive, with
// the exception of `union` member accesses.
- let ty = Place::ty_from(place.base, proj_base, self.body, self.tcx)
+ let ty = Place::ty_from(place.base, proj_base, *self.body, self.tcx)
.projection_ty(self.tcx, elem)
.ty;
if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) {
@@ -701,7 +706,7 @@
callee: &Operand<'tcx>,
args: &[Operand<'tcx>],
) -> Result<(), Unpromotable> {
- let fn_ty = callee.ty(self.body, self.tcx);
+ let fn_ty = callee.ty(*self.body, self.tcx);
if !self.explicit && self.const_kind.is_none() {
if let ty::FnDef(def_id, _) = fn_ty.kind {
@@ -737,7 +742,7 @@
// FIXME(eddyb) remove the differences for promotability in `static`, `const`, `const fn`.
pub fn validate_candidates(
tcx: TyCtxt<'tcx>,
- body: &Body<'tcx>,
+ body: ReadOnlyBodyCache<'_, 'tcx>,
def_id: DefId,
temps: &IndexVec<Local, TempState>,
candidates: &[Candidate],
@@ -770,8 +775,8 @@
struct Promoter<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- source: &'a mut Body<'tcx>,
- promoted: Body<'tcx>,
+ source: &'a mut BodyCache<'tcx>,
+ promoted: BodyCache<'tcx>,
temps: &'a mut IndexVec<Local, TempState>,
/// If true, all nested temps are also kept in the
@@ -919,7 +924,7 @@
def_id: DefId,
candidate: Candidate,
next_promoted_id: usize,
- ) -> Option<Body<'tcx>> {
+ ) -> Option<BodyCache<'tcx>> {
let mut operand = {
let promoted = &mut self.promoted;
let promoted_id = Promoted::new(next_promoted_id);
@@ -1040,11 +1045,11 @@
pub fn promote_candidates<'tcx>(
def_id: DefId,
- body: &mut Body<'tcx>,
+ body: &mut BodyCache<'tcx>,
tcx: TyCtxt<'tcx>,
mut temps: IndexVec<Local, TempState>,
candidates: Vec<Candidate>,
-) -> IndexVec<Promoted, Body<'tcx>> {
+) -> IndexVec<Promoted, BodyCache<'tcx>> {
// Visit candidates in reverse, in case they're nested.
debug!("promote_candidates({:?})", candidates);
@@ -1076,12 +1081,11 @@
).collect();
let promoter = Promoter {
- promoted: Body::new(
+ promoted: BodyCache::new(Body::new(
IndexVec::new(),
// FIXME: maybe try to filter this to avoid blowing up
// memory usage?
body.source_scopes.clone(),
- body.source_scope_local_data.clone(),
initial_locals,
IndexVec::new(),
0,
@@ -1089,7 +1093,7 @@
body.span,
vec![],
body.generator_kind,
- ),
+ )),
tcx,
source: body,
temps: &mut temps,
@@ -1146,11 +1150,11 @@
crate fn should_suggest_const_in_array_repeat_expressions_attribute<'tcx>(
tcx: TyCtxt<'tcx>,
mir_def_id: DefId,
- body: &Body<'tcx>,
+ body: ReadOnlyBodyCache<'_, 'tcx>,
operand: &Operand<'tcx>,
) -> bool {
- let mut rpo = traversal::reverse_postorder(body);
- let (temps, _) = collect_temps_and_candidates(tcx, body, &mut rpo);
+ let mut rpo = traversal::reverse_postorder(&body);
+ let (temps, _) = collect_temps_and_candidates(tcx, &body, &mut rpo);
let validator = Validator {
item: Item::new(tcx, mir_def_id, body),
temps: &temps,
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index e40d6a5..cf2e130 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -2,7 +2,6 @@
use rustc::hir;
use rustc::mir::*;
use rustc::ty::{self, Predicate, Ty, TyCtxt, adjustment::{PointerCast}};
-use rustc_target::spec::abi;
use std::borrow::Cow;
use syntax_pos::Span;
use syntax::symbol::{sym, Symbol};
@@ -80,10 +79,14 @@
fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> McfResult {
for ty in ty.walk() {
match ty.kind {
- ty::Ref(_, _, hir::Mutability::Mutable) => return Err((
- span,
- "mutable references in const fn are unstable".into(),
- )),
+ ty::Ref(_, _, hir::Mutability::Mutable) => {
+ if !tcx.features().const_mut_refs {
+ return Err((
+ span,
+ "mutable references in const fn are unstable".into(),
+ ))
+ }
+ }
ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
ty::FnPtr(..) => {
if !tcx.const_fn_is_allowed_fn_ptr(fn_def_id) {
@@ -356,18 +359,8 @@
} => {
let fn_ty = func.ty(body, tcx);
if let ty::FnDef(def_id, _) = fn_ty.kind {
-
- // some intrinsics are waved through if called inside the
- // standard library. Users never need to call them directly
- match tcx.fn_sig(def_id).abi() {
- abi::Abi::RustIntrinsic => if !is_intrinsic_whitelisted(tcx, def_id) {
- return Err((
- span,
- "can only call a curated list of intrinsics in `min_const_fn`".into(),
- ))
- },
- abi::Abi::Rust if tcx.is_min_const_fn(def_id) => {},
- abi::Abi::Rust => return Err((
+ if !tcx.is_min_const_fn(def_id) {
+ return Err((
span,
format!(
"can only call other `const fn` within a `const fn`, \
@@ -375,14 +368,7 @@
func,
)
.into(),
- )),
- abi => return Err((
- span,
- format!(
- "cannot call functions with `{}` abi in `min_const_fn`",
- abi,
- ).into(),
- )),
+ ));
}
check_operand(tcx, func, span, def_id, body)?;
@@ -409,35 +395,3 @@
},
}
}
-
-/// Returns `true` if the `def_id` refers to an intrisic which we've whitelisted
-/// for being called from stable `const fn`s (`min_const_fn`).
-///
-/// Adding more intrinsics requires sign-off from @rust-lang/lang.
-fn is_intrinsic_whitelisted(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
- match &*tcx.item_name(def_id).as_str() {
- | "size_of"
- | "min_align_of"
- | "needs_drop"
- // Arithmetic:
- | "add_with_overflow" // ~> .overflowing_add
- | "sub_with_overflow" // ~> .overflowing_sub
- | "mul_with_overflow" // ~> .overflowing_mul
- | "wrapping_add" // ~> .wrapping_add
- | "wrapping_sub" // ~> .wrapping_sub
- | "wrapping_mul" // ~> .wrapping_mul
- | "saturating_add" // ~> .saturating_add
- | "saturating_sub" // ~> .saturating_sub
- | "unchecked_shl" // ~> .wrapping_shl
- | "unchecked_shr" // ~> .wrapping_shr
- | "rotate_left" // ~> .rotate_left
- | "rotate_right" // ~> .rotate_right
- | "ctpop" // ~> .count_ones
- | "ctlz" // ~> .leading_zeros
- | "cttz" // ~> .trailing_zeros
- | "bswap" // ~> .swap_bytes
- | "bitreverse" // ~> .reverse_bits
- => true,
- _ => false,
- }
-}
diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs
index 130393e..c636aba 100644
--- a/src/librustc_mir/transform/remove_noop_landing_pads.rs
+++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs
@@ -9,7 +9,7 @@
/// code for these.
pub struct RemoveNoopLandingPads;
-pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>) {
if tcx.sess.no_landing_pads() {
return
}
@@ -19,7 +19,7 @@
}
impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
remove_noop_landing_pads(tcx, body);
}
}
@@ -84,7 +84,7 @@
}
}
- fn remove_nop_landing_pads(&self, body: &mut Body<'_>) {
+ fn remove_nop_landing_pads(&self, body: &mut BodyCache<'_>) {
// make sure there's a single resume block
let resume_block = {
let patch = MirPatch::new(body);
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index aada764..794ced1 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -5,7 +5,7 @@
use rustc::ty::{self, TyCtxt, Ty};
use rustc::hir::def_id::DefId;
-use rustc::mir::{self, Body, Location, Local};
+use rustc::mir::{self, Body, BodyCache, Location, Local};
use rustc_index::bit_set::BitSet;
use crate::transform::{MirPass, MirSource};
@@ -26,7 +26,7 @@
pub struct SanityCheck;
impl<'tcx> MirPass<'tcx> for SanityCheck {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
let def_id = src.def_id();
if !tcx.has_attr(def_id, sym::rustc_mir) {
debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
@@ -64,10 +64,20 @@
sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_uninits);
}
if has_rustc_mir_with(&attributes, sym::rustc_peek_definite_init).is_some() {
- sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_def_inits);
+ sanity_check_via_rustc_peek(
+ tcx,
+ body,
+ def_id,
+ &attributes,
+ &flow_def_inits);
}
if has_rustc_mir_with(&attributes, sym::rustc_peek_indirectly_mutable).is_some() {
- sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_indirectly_mut);
+ sanity_check_via_rustc_peek(
+ tcx,
+ body,
+ def_id,
+ &attributes,
+ &flow_indirectly_mut);
}
if has_rustc_mir_with(&attributes, sym::stop_after_dataflow).is_some() {
tcx.sess.fatal("stop_after_dataflow ended compilation");
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index c9185d1..900752d 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -43,7 +43,7 @@
}
}
-pub fn simplify_cfg(body: &mut Body<'_>) {
+pub fn simplify_cfg(body: &mut BodyCache<'_>) {
CfgSimplifier::new(body).simplify();
remove_dead_blocks(body);
@@ -56,7 +56,9 @@
Cow::Borrowed(&self.label)
}
- fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(
+ &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+ ) {
debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body);
simplify_cfg(body);
}
@@ -68,7 +70,7 @@
}
impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
- pub fn new(body: &'a mut Body<'tcx>) -> Self {
+ pub fn new(body: &'a mut BodyCache<'tcx>) -> Self {
let mut pred_count = IndexVec::from_elem(0u32, body.basic_blocks());
// we can't use mir.predecessors() here because that counts
@@ -124,8 +126,9 @@
changed |= inner_changed;
}
- self.basic_blocks[bb].statements.extend(new_stmts);
- self.basic_blocks[bb].terminator = Some(terminator);
+ let data = &mut self.basic_blocks[bb];
+ data.statements.extend(new_stmts);
+ data.terminator = Some(terminator);
changed |= inner_changed;
}
@@ -259,7 +262,7 @@
}
}
-pub fn remove_dead_blocks(body: &mut Body<'_>) {
+pub fn remove_dead_blocks(body: &mut BodyCache<'_>) {
let mut seen = BitSet::new_empty(body.basic_blocks().len());
for (bb, _) in traversal::preorder(body) {
seen.insert(bb.index());
@@ -273,8 +276,8 @@
for alive_index in seen.iter() {
replacements[alive_index] = BasicBlock::new(used_blocks);
if alive_index != used_blocks {
- // Swap the next alive block data with the current available slot. Since alive_index is
- // non-decreasing this is a valid operation.
+ // Swap the next alive block data with the current available slot. Since
+ // alive_index is non-decreasing this is a valid operation.
basic_blocks.raw.swap(alive_index, used_blocks);
}
used_blocks += 1;
@@ -292,14 +295,17 @@
pub struct SimplifyLocals;
impl<'tcx> MirPass<'tcx> for SimplifyLocals {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(
+ &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+ ) {
trace!("running SimplifyLocals on {:?}", source);
let locals = {
+ let read_only_cache = read_only!(body);
let mut marker = DeclMarker {
locals: BitSet::new_empty(body.local_decls.len()),
body,
};
- marker.visit_body(body);
+ marker.visit_body(read_only_cache);
// Return pointer and arguments are always live
marker.locals.insert(RETURN_PLACE);
for arg in body.args_iter() {
diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs
index 0a50966..c8d0f37 100644
--- a/src/librustc_mir/transform/simplify_branches.rs
+++ b/src/librustc_mir/transform/simplify_branches.rs
@@ -19,7 +19,7 @@
Cow::Borrowed(&self.label)
}
- fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
let param_env = tcx.param_env(src.def_id());
for block in body.basic_blocks_mut() {
let terminator = block.terminator_mut();
diff --git a/src/librustc_mir/transform/simplify_try.rs b/src/librustc_mir/transform/simplify_try.rs
index 9dc5daa..2235de9 100644
--- a/src/librustc_mir/transform/simplify_try.rs
+++ b/src/librustc_mir/transform/simplify_try.rs
@@ -33,7 +33,7 @@
pub struct SimplifyArmIdentity;
impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
- fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
for bb in basic_blocks {
// Need 3 statements:
@@ -151,7 +151,7 @@
pub struct SimplifyBranchSame;
impl<'tcx> MirPass<'tcx> for SimplifyBranchSame {
- fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
let mut did_remove_blocks = false;
let bbs = body.basic_blocks_mut();
for bb_idx in bbs.indices() {
diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs
index 28f68ac..3fc76ef 100644
--- a/src/librustc_mir/transform/uniform_array_move_out.rs
+++ b/src/librustc_mir/transform/uniform_array_move_out.rs
@@ -37,12 +37,14 @@
pub struct UniformArrayMoveOut;
impl<'tcx> MirPass<'tcx> for UniformArrayMoveOut {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
let mut patch = MirPatch::new(body);
let param_env = tcx.param_env(src.def_id());
{
- let mut visitor = UniformArrayMoveOutVisitor{body, patch: &mut patch, tcx, param_env};
- visitor.visit_body(body);
+ let read_only_cache = read_only!(body);
+ let mut visitor
+ = UniformArrayMoveOutVisitor{ body, patch: &mut patch, tcx, param_env};
+ visitor.visit_body(read_only_cache);
}
patch.apply(body);
}
@@ -184,15 +186,16 @@
}
impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
let mut patch = MirPatch::new(body);
let param_env = tcx.param_env(src.def_id());
{
+ let read_only_cache = read_only!(body);
let mut visitor = RestoreDataCollector {
locals_use: IndexVec::from_elem(LocalUse::new(), &body.local_decls),
candidates: vec![],
};
- visitor.visit_body(body);
+ visitor.visit_body(read_only_cache);
for candidate in &visitor.candidates {
let statement = &body[candidate.block].statements[candidate.statement_index];
@@ -217,8 +220,12 @@
let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2);
let opt_size = opt_src_place.and_then(|src_place| {
- let src_ty =
- Place::ty_from(src_place.base, src_place.projection, body, tcx).ty;
+ let src_ty = Place::ty_from(
+ src_place.base,
+ src_place.projection,
+ &**body,
+ tcx
+ ).ty;
if let ty::Array(_, ref size_o) = src_ty.kind {
size_o.try_eval_usize(tcx, param_env)
} else {
diff --git a/src/librustc_mir/transform/uninhabited_enum_branching.rs b/src/librustc_mir/transform/uninhabited_enum_branching.rs
index a6c18ae..26081d9 100644
--- a/src/librustc_mir/transform/uninhabited_enum_branching.rs
+++ b/src/librustc_mir/transform/uninhabited_enum_branching.rs
@@ -2,7 +2,8 @@
use crate::transform::{MirPass, MirSource};
use rustc::mir::{
- BasicBlock, BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, TerminatorKind,
+ BasicBlock, BasicBlockData, Body, BodyCache, Local, Operand, Rvalue, StatementKind,
+ TerminatorKind,
};
use rustc::ty::layout::{Abi, TyLayout, Variants};
use rustc::ty::{Ty, TyCtxt};
@@ -28,7 +29,7 @@
// Only bother checking blocks which terminate by switching on a local.
if let Some(local) = get_discriminant_local(&terminator.kind) {
let stmt_before_term = (block_data.statements.len() > 0)
- .then_with(|| &block_data.statements[block_data.statements.len() - 1].kind);
+ .then(|| &block_data.statements[block_data.statements.len() - 1].kind);
if let Some(StatementKind::Assign(box (l, Rvalue::Discriminant(place)))) = stmt_before_term
{
@@ -58,14 +59,14 @@
.iter_enumerated()
.filter_map(|(idx, layout)| {
(layout.abi != Abi::Uninhabited)
- .then_with(|| ty.discriminant_for_variant(tcx, idx).unwrap().val)
+ .then(|| ty.discriminant_for_variant(tcx, idx).unwrap().val)
})
.collect(),
}
}
impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
if source.promoted.is_some() {
return;
}
diff --git a/src/librustc_mir/util/collect_writes.rs b/src/librustc_mir/util/collect_writes.rs
index c8804df..f94bea2 100644
--- a/src/librustc_mir/util/collect_writes.rs
+++ b/src/librustc_mir/util/collect_writes.rs
@@ -1,5 +1,5 @@
use rustc::mir::{Local, Location};
-use rustc::mir::Body;
+use rustc::mir::ReadOnlyBodyCache;
use rustc::mir::visit::PlaceContext;
use rustc::mir::visit::Visitor;
@@ -9,10 +9,10 @@
fn find_assignments(&self, local: Local) -> Vec<Location>;
}
-impl<'tcx> FindAssignments for Body<'tcx>{
+impl<'a, 'tcx> FindAssignments for ReadOnlyBodyCache<'a, 'tcx>{
fn find_assignments(&self, local: Local) -> Vec<Location>{
let mut visitor = FindLocalAssignmentVisitor{ needle: local, locations: vec![]};
- visitor.visit_body(self);
+ visitor.visit_body(*self);
visitor.locations
}
}
diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs
index 1611cad..1907e9b 100644
--- a/src/librustc_mir/util/def_use.rs
+++ b/src/librustc_mir/util/def_use.rs
@@ -1,6 +1,6 @@
//! Def-use analysis.
-use rustc::mir::{Body, Local, Location, PlaceElem, VarDebugInfo};
+use rustc::mir::{Body, BodyCache, Local, Location, PlaceElem, ReadOnlyBodyCache, VarDebugInfo};
use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor};
use rustc::ty::TyCtxt;
use rustc_index::vec::IndexVec;
@@ -30,7 +30,7 @@
}
}
- pub fn analyze(&mut self, body: &Body<'_>) {
+ pub fn analyze(&mut self, body: ReadOnlyBodyCache<'_, '_>) {
self.clear();
let mut finder = DefUseFinder {
@@ -55,11 +55,11 @@
fn mutate_defs_and_uses(
&self,
local: Local,
- body: &mut Body<'tcx>,
+ body: &mut BodyCache<'tcx>,
new_local: Local,
tcx: TyCtxt<'tcx>,
) {
- let mut visitor = MutateUseVisitor::new(local, new_local, body, tcx);
+ let mut visitor = MutateUseVisitor::new(local, new_local, tcx);
let info = &self.info[local];
for place_use in &info.defs_and_uses {
visitor.visit_location(body, place_use.location)
@@ -73,7 +73,7 @@
// FIXME(pcwalton): this should update the def-use chains.
pub fn replace_all_defs_and_uses_with(&self,
local: Local,
- body: &mut Body<'tcx>,
+ body: &mut BodyCache<'tcx>,
new_local: Local,
tcx: TyCtxt<'tcx>) {
self.mutate_defs_and_uses(local, body, new_local, tcx)
@@ -156,7 +156,6 @@
fn new(
query: Local,
new_local: Local,
- _: &Body<'tcx>,
tcx: TyCtxt<'tcx>,
) -> MutateUseVisitor<'tcx> {
MutateUseVisitor { query, new_local, tcx }
diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs
index 3a7ec9f..a44d401 100644
--- a/src/librustc_mir/util/graphviz.rs
+++ b/src/librustc_mir/util/graphviz.rs
@@ -202,7 +202,7 @@
}
for var_debug_info in &body.var_debug_info {
- write!(w, r#"debug {} => {};<br align="left"/>"#,
+ write!(w, r#"debug {} => {};<br align="left"/>"#,
var_debug_info.name, escape(&var_debug_info.place))?;
}
diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs
index 63e4af0..3349753 100644
--- a/src/librustc_mir/util/liveness.rs
+++ b/src/librustc_mir/util/liveness.rs
@@ -57,7 +57,7 @@
/// Computes which local variables are live within the given function
/// `mir`, including drops.
pub fn liveness_of_locals(
- body: &Body<'_>,
+ body: ReadOnlyBodyCache<'_, '_>,
) -> LivenessResult {
let num_live_vars = body.local_decls.len();
@@ -83,8 +83,9 @@
// FIXME(ecstaticmorse): Reverse post-order on the reverse CFG may generate a better iteration
// order when cycles are present, but the overhead of computing the reverse CFG may outweigh
// any benefits. Benchmark this and find out.
- let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks().len());
- for (bb, _) in traversal::postorder(body) {
+ let mut dirty_queue: WorkQueue<BasicBlock>
+ = WorkQueue::with_none(body.basic_blocks().len());
+ for (bb, _) in traversal::postorder(&body) {
dirty_queue.insert(bb);
}
diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs
index a5f7e54..47bb0b6 100644
--- a/src/librustc_mir/util/patch.rs
+++ b/src/librustc_mir/util/patch.rs
@@ -127,7 +127,7 @@
self.make_nop.push(loc);
}
- pub fn apply(self, body: &mut Body<'tcx>) {
+ pub fn apply(self, body: &mut BodyCache<'tcx>) {
debug!("MirPatch: make nops at: {:?}", self.make_nop);
for loc in self.make_nop {
body.make_statement_nop(loc);
diff --git a/src/librustc_parse/Cargo.toml b/src/librustc_parse/Cargo.toml
index 95b3256..fb5cb74 100644
--- a/src/librustc_parse/Cargo.toml
+++ b/src/librustc_parse/Cargo.toml
@@ -12,12 +12,11 @@
[dependencies]
bitflags = "1.0"
log = "0.4"
-syntax_pos = { path = "../libsyntax_pos" }
-syntax = { path = "../libsyntax" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_feature = { path = "../librustc_feature" }
rustc_lexer = { path = "../librustc_lexer" }
-rustc_target = { path = "../librustc_target" }
-smallvec = { version = "1.0", features = ["union", "may_dangle"] }
+rustc_errors = { path = "../librustc_errors" }
rustc_error_codes = { path = "../librustc_error_codes" }
+smallvec = { version = "1.0", features = ["union", "may_dangle"] }
+syntax_pos = { path = "../libsyntax_pos" }
+syntax = { path = "../libsyntax" }
diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs
index 26e51e8..1e9203f 100644
--- a/src/librustc_parse/config.rs
+++ b/src/librustc_parse/config.rs
@@ -8,20 +8,21 @@
//!
//! [#64197]: https://github.com/rust-lang/rust/issues/64197
-use crate::validate_attr;
+use crate::{parse_in, validate_attr};
use rustc_feature::Features;
+use rustc_errors::Applicability;
use syntax::attr::HasAttrs;
use syntax::feature_gate::{feature_err, get_features};
use syntax::attr;
-use syntax::ast;
+use syntax::ast::{self, Attribute, AttrItem, MetaItem};
use syntax::edition::Edition;
use syntax::mut_visit::*;
use syntax::ptr::P;
use syntax::sess::ParseSess;
use syntax::util::map_in_place::MapInPlace;
+use syntax_pos::Span;
use syntax_pos::symbol::sym;
-use errors::Applicability;
use smallvec::SmallVec;
/// A folder that strips out items that do not belong in the current configuration.
@@ -72,10 +73,15 @@
}
}
+const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
+const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
+ <https://doc.rust-lang.org/reference/conditional-compilation.html\
+ #the-cfg_attr-attribute>";
+
impl<'a> StripUnconfigured<'a> {
pub fn configure<T: HasAttrs>(&mut self, mut node: T) -> Option<T> {
self.process_cfg_attrs(&mut node);
- if self.in_cfg(node.attrs()) { Some(node) } else { None }
+ self.in_cfg(node.attrs()).then_some(node)
}
/// Parse and expand all `cfg_attr` attributes into a list of attributes
@@ -97,34 +103,14 @@
/// Gives a compiler warning when the `cfg_attr` contains no attributes and
/// is in the original source file. Gives a compiler error if the syntax of
/// the attribute is incorrect.
- fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec<ast::Attribute> {
+ fn process_cfg_attr(&mut self, attr: Attribute) -> Vec<Attribute> {
if !attr.has_name(sym::cfg_attr) {
return vec![attr];
}
- if attr.get_normal_item().tokens.is_empty() {
- self.sess.span_diagnostic
- .struct_span_err(
- attr.span,
- "malformed `cfg_attr` attribute input",
- ).span_suggestion(
- attr.span,
- "missing condition and attribute",
- "#[cfg_attr(condition, attribute, other_attribute, ...)]".to_owned(),
- Applicability::HasPlaceholders,
- ).note("for more information, visit \
- <https://doc.rust-lang.org/reference/conditional-compilation.html\
- #the-cfg_attr-attribute>")
- .emit();
- return vec![];
- }
- let res = crate::parse_in_attr(self.sess, &attr, |p| p.parse_cfg_attr());
- let (cfg_predicate, expanded_attrs) = match res {
- Ok(result) => result,
- Err(mut e) => {
- e.emit();
- return vec![];
- }
+ let (cfg_predicate, expanded_attrs) = match self.parse_cfg_attr(&attr) {
+ None => return vec![],
+ Some(r) => r,
};
// Lint on zero attributes in source.
@@ -135,24 +121,56 @@
// At this point we know the attribute is considered used.
attr::mark_used(&attr);
- if attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
- // We call `process_cfg_attr` recursively in case there's a
- // `cfg_attr` inside of another `cfg_attr`. E.g.
- // `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
- expanded_attrs.into_iter()
- .flat_map(|(item, span)| self.process_cfg_attr(attr::mk_attr_from_item(
- attr.style,
- item,
- span,
- )))
- .collect()
- } else {
- vec![]
+ if !attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
+ return vec![];
}
+
+ // We call `process_cfg_attr` recursively in case there's a
+ // `cfg_attr` inside of another `cfg_attr`. E.g.
+ // `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
+ expanded_attrs
+ .into_iter()
+ .flat_map(|(item, span)| {
+ let attr = attr::mk_attr_from_item(attr.style, item, span);
+ self.process_cfg_attr(attr)
+ })
+ .collect()
+ }
+
+ fn parse_cfg_attr(&self, attr: &Attribute) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> {
+ match attr.get_normal_item().args {
+ ast::MacArgs::Delimited(dspan, delim, ref tts) if !tts.is_empty() => {
+ let msg = "wrong `cfg_attr` delimiters";
+ validate_attr::check_meta_bad_delim(self.sess, dspan, delim, msg);
+ match parse_in(self.sess, tts.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) {
+ Ok(r) => return Some(r),
+ Err(mut e) => e
+ .help(&format!("the valid syntax is `{}`", CFG_ATTR_GRAMMAR_HELP))
+ .note(CFG_ATTR_NOTE_REF)
+ .emit(),
+ }
+ }
+ _ => self.error_malformed_cfg_attr_missing(attr.span),
+ }
+ None
+ }
+
+ fn error_malformed_cfg_attr_missing(&self, span: Span) {
+ self.sess
+ .span_diagnostic
+ .struct_span_err(span, "malformed `cfg_attr` attribute input")
+ .span_suggestion(
+ span,
+ "missing condition and attribute",
+ CFG_ATTR_GRAMMAR_HELP.to_string(),
+ Applicability::HasPlaceholders,
+ )
+ .note(CFG_ATTR_NOTE_REF)
+ .emit();
}
/// Determines if a node with the given attributes should be included in this configuration.
- pub fn in_cfg(&self, attrs: &[ast::Attribute]) -> bool {
+ pub fn in_cfg(&self, attrs: &[Attribute]) -> bool {
attrs.iter().all(|attr| {
if !is_cfg(attr) {
return true;
@@ -199,7 +217,7 @@
}
/// Visit attributes on expression and statements (but not attributes on items in blocks).
- fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) {
+ fn visit_expr_attrs(&mut self, attrs: &[Attribute]) {
// flag the offending attributes
for attr in attrs.iter() {
self.maybe_emit_expr_attr_err(attr);
@@ -207,7 +225,7 @@
}
/// If attributes are not allowed on expressions, emit an error for `attr`
- pub fn maybe_emit_expr_attr_err(&self, attr: &ast::Attribute) {
+ pub fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) {
let mut err = feature_err(self.sess,
sym::stmt_expr_attributes,
@@ -350,7 +368,7 @@
}
}
-fn is_cfg(attr: &ast::Attribute) -> bool {
+fn is_cfg(attr: &Attribute) -> bool {
attr.check_name(sym::cfg)
}
@@ -359,8 +377,8 @@
pub fn process_configure_mod(
sess: &ParseSess,
cfg_mods: bool,
- attrs: &[ast::Attribute],
-) -> (bool, Vec<ast::Attribute>) {
+ attrs: &[Attribute],
+) -> (bool, Vec<Attribute>) {
// Don't perform gated feature checking.
let mut strip_unconfigured = StripUnconfigured { sess, features: None };
let mut attrs = attrs.to_owned();
diff --git a/src/librustc_parse/lexer/mod.rs b/src/librustc_parse/lexer/mod.rs
index 5de63cb..ddcfea1 100644
--- a/src/librustc_parse/lexer/mod.rs
+++ b/src/librustc_parse/lexer/mod.rs
@@ -1,16 +1,15 @@
-use syntax::token::{self, Token, TokenKind};
-use syntax::sess::ParseSess;
-use syntax::symbol::{sym, Symbol};
-use syntax::util::comments;
-
-use errors::{FatalError, DiagnosticBuilder};
-use syntax_pos::{BytePos, Pos, Span};
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::{FatalError, DiagnosticBuilder};
use rustc_lexer::Base;
use rustc_lexer::unescape;
+use syntax::token::{self, Token, TokenKind};
+use syntax::sess::ParseSess;
+use syntax::util::comments;
+use syntax_pos::symbol::{sym, Symbol};
+use syntax_pos::{BytePos, Pos, Span};
use std::char;
use std::convert::TryInto;
-use rustc_data_structures::sync::Lrc;
use log::debug;
mod tokentrees;
diff --git a/src/librustc_parse/lexer/tokentrees.rs b/src/librustc_parse/lexer/tokentrees.rs
index 1353591..5791c63 100644
--- a/src/librustc_parse/lexer/tokentrees.rs
+++ b/src/librustc_parse/lexer/tokentrees.rs
@@ -1,13 +1,11 @@
-use rustc_data_structures::fx::FxHashMap;
-use syntax_pos::Span;
-
use super::{StringReader, UnmatchedBrace};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::PResult;
use syntax::print::pprust::token_to_string;
use syntax::token::{self, Token};
use syntax::tokenstream::{DelimSpan, IsJoint::{self, *}, TokenStream, TokenTree, TreeAndJoint};
-
-use errors::PResult;
+use syntax_pos::Span;
impl<'a> StringReader<'a> {
crate fn into_token_trees(self) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
diff --git a/src/librustc_parse/lexer/unicode_chars.rs b/src/librustc_parse/lexer/unicode_chars.rs
index 6eb995b..edfebc7 100644
--- a/src/librustc_parse/lexer/unicode_chars.rs
+++ b/src/librustc_parse/lexer/unicode_chars.rs
@@ -2,9 +2,9 @@
// http://www.unicode.org/Public/security/10.0.0/confusables.txt
use super::StringReader;
-use errors::{Applicability, DiagnosticBuilder};
-use syntax_pos::{BytePos, Pos, Span, symbol::kw};
use crate::token;
+use rustc_errors::{Applicability, DiagnosticBuilder};
+use syntax_pos::{BytePos, Pos, Span, symbol::kw};
#[rustfmt::skip] // for line breaks
const UNICODE_ARRAY: &[(char, &str, char)] = &[
diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs
index 1215c7a..faff386 100644
--- a/src/librustc_parse/lib.rs
+++ b/src/librustc_parse/lib.rs
@@ -1,5 +1,6 @@
//! The main parser interface.
+#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
use syntax::ast;
@@ -8,7 +9,7 @@
use syntax::token::{self, Nonterminal};
use syntax::tokenstream::{self, TokenStream, TokenTree};
-use errors::{PResult, FatalError, Level, Diagnostic};
+use rustc_errors::{PResult, FatalError, Level, Diagnostic};
use rustc_data_structures::sync::Lrc;
use syntax_pos::{Span, SourceFile, FileName};
@@ -53,7 +54,7 @@
macro_rules! panictry_buffer {
($handler:expr, $e:expr) => ({
use std::result::Result::{Ok, Err};
- use errors::FatalError;
+ use rustc_errors::FatalError;
match $e {
Ok(e) => e,
Err(errs) => {
@@ -270,19 +271,13 @@
}
/// Runs the given subparser `f` on the tokens of the given `attr`'s item.
-pub fn parse_in_attr<'a, T>(
+pub fn parse_in<'a, T>(
sess: &'a ParseSess,
- attr: &ast::Attribute,
+ tts: TokenStream,
+ name: &'static str,
mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> PResult<'a, T> {
- let mut parser = Parser::new(
- sess,
- attr.get_normal_item().tokens.clone(),
- None,
- false,
- false,
- Some("attribute"),
- );
+ let mut parser = Parser::new(sess, tts, None, false, false, Some(name));
let result = f(&mut parser)?;
if parser.token != token::Eof {
parser.unexpected()?;
@@ -409,7 +404,7 @@
brackets.push(stream);
}
- brackets.push(item.tokens.clone());
+ brackets.push(item.args.outer_tokens());
// The span we list here for `#` and for `[ ... ]` are both wrong in
// that it encompasses more than each token, but it hopefully is "good
diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs
index 524b551..00fd6b8 100644
--- a/src/librustc_parse/parser/attr.rs
+++ b/src/librustc_parse/parser/attr.rs
@@ -1,11 +1,10 @@
use super::{SeqSep, Parser, TokenType, PathStyle};
+use rustc_errors::PResult;
use syntax::attr;
use syntax::ast;
use syntax::util::comments;
-use syntax::token::{self, Nonterminal, DelimToken};
-use syntax::tokenstream::{TokenStream, TokenTree};
+use syntax::token::{self, Nonterminal};
use syntax_pos::{Span, Symbol};
-use errors::PResult;
use log::debug;
@@ -181,31 +180,8 @@
item
} else {
let path = self.parse_path(PathStyle::Mod)?;
- let tokens = if self.check(&token::OpenDelim(DelimToken::Paren)) ||
- self.check(&token::OpenDelim(DelimToken::Bracket)) ||
- self.check(&token::OpenDelim(DelimToken::Brace)) {
- self.parse_token_tree().into()
- } else if self.eat(&token::Eq) {
- let eq = TokenTree::token(token::Eq, self.prev_span);
- let mut is_interpolated_expr = false;
- if let token::Interpolated(nt) = &self.token.kind {
- if let token::NtExpr(..) = **nt {
- is_interpolated_expr = true;
- }
- }
- let token_tree = if is_interpolated_expr {
- // We need to accept arbitrary interpolated expressions to continue
- // supporting things like `doc = $expr` that work on stable.
- // Non-literal interpolated expressions are rejected after expansion.
- self.parse_token_tree()
- } else {
- self.parse_unsuffixed_lit()?.token_tree()
- };
- TokenStream::new(vec![eq.into(), token_tree.into()])
- } else {
- TokenStream::default()
- };
- ast::AttrItem { path, tokens }
+ let args = self.parse_attr_args()?;
+ ast::AttrItem { path, args }
})
}
@@ -244,7 +220,7 @@
Ok(attrs)
}
- fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> {
+ crate fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> {
let lit = self.parse_lit()?;
debug!("checking if {:?} is unusuffixed", lit);
@@ -262,25 +238,36 @@
/// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited.
pub fn parse_cfg_attr(&mut self) -> PResult<'a, (ast::MetaItem, Vec<(ast::AttrItem, Span)>)> {
- self.expect(&token::OpenDelim(token::Paren))?;
-
let cfg_predicate = self.parse_meta_item()?;
self.expect(&token::Comma)?;
// Presumably, the majority of the time there will only be one attr.
let mut expanded_attrs = Vec::with_capacity(1);
-
- while !self.check(&token::CloseDelim(token::Paren)) {
- let lo = self.token.span.lo();
+ while self.token.kind != token::Eof {
+ let lo = self.token.span;
let item = self.parse_attr_item()?;
- expanded_attrs.push((item, self.prev_span.with_lo(lo)));
- self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Paren)])?;
+ expanded_attrs.push((item, lo.to(self.prev_span)));
+ if !self.eat(&token::Comma) {
+ break;
+ }
}
- self.expect(&token::CloseDelim(token::Paren))?;
Ok((cfg_predicate, expanded_attrs))
}
+ /// Matches `COMMASEP(meta_item_inner)`.
+ crate fn parse_meta_seq_top(&mut self) -> PResult<'a, Vec<ast::NestedMetaItem>> {
+ // Presumably, the majority of the time there will only be one attr.
+ let mut nmis = Vec::with_capacity(1);
+ while self.token.kind != token::Eof {
+ nmis.push(self.parse_meta_item_inner()?);
+ if !self.eat(&token::Comma) {
+ break;
+ }
+ }
+ Ok(nmis)
+ }
+
/// Matches the following grammar (per RFC 1559).
///
/// meta_item : PATH ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index da8bf89..ba125ca 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -1,25 +1,22 @@
use super::{BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType, SeqSep, Parser};
-use syntax::ast::{
- self, Param, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind,
- Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind,
-};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::{self, PResult, Applicability, DiagnosticBuilder, Handler, pluralize};
+use rustc_error_codes::*;
+use syntax::ast::{self, Param, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item};
+use syntax::ast::{ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind};
use syntax::token::{self, TokenKind, token_can_begin_expr};
use syntax::print::pprust;
use syntax::ptr::P;
-use syntax::symbol::{kw, sym};
use syntax::ThinVec;
use syntax::util::parser::AssocOp;
use syntax::struct_span_err;
-
-use errors::{PResult, Applicability, DiagnosticBuilder, pluralize};
-use rustc_data_structures::fx::FxHashSet;
+use syntax_pos::symbol::{kw, sym};
use syntax_pos::{Span, DUMMY_SP, MultiSpan, SpanSnippetError};
+
use log::{debug, trace};
use std::mem;
-use rustc_error_codes::*;
-
const TURBOFISH: &'static str = "use `::<...>` instead of `<...>` to specify type arguments";
/// Creates a placeholder argument.
@@ -61,10 +58,10 @@
}
impl Error {
- fn span_err<S: Into<MultiSpan>>(
+ fn span_err(
self,
- sp: S,
- handler: &errors::Handler,
+ sp: impl Into<MultiSpan>,
+ handler: &Handler,
) -> DiagnosticBuilder<'_> {
match self {
Error::FileNotFoundForModule {
@@ -212,7 +209,7 @@
self.sess.span_diagnostic.span_bug(sp, m)
}
- pub(super) fn diagnostic(&self) -> &'a errors::Handler {
+ pub(super) fn diagnostic(&self) -> &'a Handler {
&self.sess.span_diagnostic
}
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index 43c740f..3cd4988 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -4,23 +4,20 @@
use super::diagnostics::Error;
use crate::maybe_recover_from_interpolated_ty_qpath;
-use syntax::ast::{
- self, DUMMY_NODE_ID, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode,
- Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm, Ty, TyKind,
- FunctionRetTy, Param, FnDecl, BinOpKind, BinOp, UnOp, Mac, AnonConst, Field, Lit,
-};
+use rustc_data_structures::thin_vec::ThinVec;
+use rustc_errors::{PResult, Applicability};
+use syntax::ast::{self, DUMMY_NODE_ID, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode};
+use syntax::ast::{Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm, Ty, TyKind};
+use syntax::ast::{FunctionRetTy, Param, FnDecl, BinOpKind, BinOp, UnOp, Mac, AnonConst, Field, Lit};
use syntax::token::{self, Token, TokenKind};
use syntax::print::pprust;
use syntax::ptr::P;
-use syntax::source_map::{self, Span};
use syntax::util::classify;
use syntax::util::literal::LitError;
use syntax::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par};
-use syntax_pos::symbol::{kw, sym};
-use syntax_pos::Symbol;
-use errors::{PResult, Applicability};
+use syntax_pos::source_map::{self, Span};
+use syntax_pos::symbol::{kw, sym, Symbol};
use std::mem;
-use rustc_data_structures::thin_vec::ThinVec;
/// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
/// dropped into the token stream, which happens while parsing the result of
@@ -922,13 +919,11 @@
// `!`, as an operator, is prefix, so we know this isn't that.
if self.eat(&token::Not) {
// MACRO INVOCATION expression
- let (delim, tts) = self.expect_delimited_token_tree()?;
+ let args = self.parse_mac_args()?;
hi = self.prev_span;
ex = ExprKind::Mac(Mac {
path,
- tts,
- delim,
- span: lo.to(hi),
+ args,
prior_type_ascription: self.last_type_ascription,
});
} else if self.check(&token::OpenDelim(token::Brace)) {
diff --git a/src/librustc_parse/parser/generics.rs b/src/librustc_parse/parser/generics.rs
index ba5eafc..32819cc 100644
--- a/src/librustc_parse/parser/generics.rs
+++ b/src/librustc_parse/parser/generics.rs
@@ -1,11 +1,11 @@
use super::Parser;
+use rustc_errors::PResult;
use syntax::ast::{self, WhereClause, GenericParam, GenericParamKind, GenericBounds, Attribute};
use syntax::token;
use syntax::source_map::DUMMY_SP;
use syntax_pos::symbol::{kw, sym};
-use errors::PResult;
impl<'a> Parser<'a> {
/// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index a0669a2..c3e5b39 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -3,27 +3,26 @@
use crate::maybe_whole;
+use rustc_errors::{PResult, Applicability, DiagnosticBuilder, StashKey};
+use rustc_error_codes::*;
use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item};
use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, Variant, VariantData, StructField};
-use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
+use syntax::ast::{Mac, MacArgs, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::ThinVec;
use syntax::token;
-use syntax::tokenstream::{TokenTree, TokenStream};
-use syntax::source_map::{self, respan, Span};
+use syntax::tokenstream::{DelimSpan, TokenTree, TokenStream};
use syntax::struct_span_err;
use syntax_pos::BytePos;
+use syntax_pos::source_map::{self, respan, Span};
use syntax_pos::symbol::{kw, sym, Symbol};
-use rustc_error_codes::*;
-
use log::debug;
use std::mem;
-use errors::{PResult, Applicability, DiagnosticBuilder, StashKey};
pub(super) type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute>>);
@@ -432,22 +431,18 @@
let prev_span = self.prev_span;
self.complain_if_pub_macro(&visibility.node, prev_span);
- let mac_lo = self.token.span;
-
// Item macro
let path = self.parse_path(PathStyle::Mod)?;
self.expect(&token::Not)?;
- let (delim, tts) = self.expect_delimited_token_tree()?;
- if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
+ let args = self.parse_mac_args()?;
+ if args.need_semicolon() && !self.eat(&token::Semi) {
self.report_invalid_macro_expansion_item();
}
let hi = self.prev_span;
let mac = Mac {
path,
- tts,
- delim,
- span: mac_lo.to(hi),
+ args,
prior_type_ascription: self.last_type_ascription,
};
let item =
@@ -500,7 +495,6 @@
if self.token.is_path_start() &&
!(self.is_async_fn() && self.token.span.rust_2015()) {
let prev_span = self.prev_span;
- let lo = self.token.span;
let path = self.parse_path(PathStyle::Mod)?;
if path.segments.len() == 1 {
@@ -518,16 +512,14 @@
*at_end = true;
// eat a matched-delimiter token tree:
- let (delim, tts) = self.expect_delimited_token_tree()?;
- if delim != MacDelimiter::Brace {
+ let args = self.parse_mac_args()?;
+ if args.need_semicolon() {
self.expect_semi()?;
}
Ok(Some(Mac {
path,
- tts,
- delim,
- span: lo.to(self.prev_span),
+ args,
prior_type_ascription: self.last_type_ascription,
}))
} else {
@@ -1332,7 +1324,7 @@
let (variants, _) = self.parse_delim_comma_seq(
token::Brace,
- |p| p.parse_enum_item(),
+ |p| p.parse_enum_variant(),
).map_err(|e| {
self.recover_stmt();
e
@@ -1344,7 +1336,7 @@
Ok((id, ItemKind::Enum(enum_definition, generics), None))
}
- fn parse_enum_item(&mut self) -> PResult<'a, Option<Variant>> {
+ fn parse_enum_variant(&mut self) -> PResult<'a, Option<Variant>> {
let variant_attrs = self.parse_outer_attributes()?;
let vlo = self.token.span;
@@ -1624,33 +1616,31 @@
vis: &Visibility,
lo: Span
) -> PResult<'a, Option<P<Item>>> {
- let token_lo = self.token.span;
let (ident, def) = if self.eat_keyword(kw::Macro) {
let ident = self.parse_ident()?;
- let tokens = if self.check(&token::OpenDelim(token::Brace)) {
- match self.parse_token_tree() {
- TokenTree::Delimited(_, _, tts) => tts,
- _ => unreachable!(),
- }
+ let body = if self.check(&token::OpenDelim(token::Brace)) {
+ self.parse_mac_args()?
} else if self.check(&token::OpenDelim(token::Paren)) {
- let args = self.parse_token_tree();
+ let params = self.parse_token_tree();
+ let pspan = params.span();
let body = if self.check(&token::OpenDelim(token::Brace)) {
self.parse_token_tree()
} else {
- self.unexpected()?;
- unreachable!()
+ return self.unexpected();
};
- TokenStream::new(vec![
- args.into(),
- TokenTree::token(token::FatArrow, token_lo.to(self.prev_span)).into(),
+ let bspan = body.span();
+ let tokens = TokenStream::new(vec![
+ params.into(),
+ TokenTree::token(token::FatArrow, pspan.between(bspan)).into(),
body.into(),
- ])
+ ]);
+ let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi());
+ P(MacArgs::Delimited(dspan, MacDelimiter::Brace, tokens))
} else {
- self.unexpected()?;
- unreachable!()
+ return self.unexpected();
};
- (ident, ast::MacroDef { tokens: tokens.into(), legacy: false })
+ (ident, ast::MacroDef { body, legacy: false })
} else if self.check_keyword(sym::macro_rules) &&
self.look_ahead(1, |t| *t == token::Not) &&
self.look_ahead(2, |t| t.is_ident()) {
@@ -1660,12 +1650,12 @@
self.bump();
let ident = self.parse_ident()?;
- let (delim, tokens) = self.expect_delimited_token_tree()?;
- if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
+ let body = self.parse_mac_args()?;
+ if body.need_semicolon() && !self.eat(&token::Semi) {
self.report_invalid_macro_expansion_item();
}
- (ident, ast::MacroDef { tokens, legacy: true })
+ (ident, ast::MacroDef { body, legacy: true })
} else {
return Ok(None);
};
@@ -1737,9 +1727,10 @@
/// Checks if current token is one of tokens which cannot be nested like `kw::Enum`. In case
/// it is, we try to parse the item and report error about nested types.
fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
- if self.token.is_keyword(kw::Enum) ||
+ if (self.token.is_keyword(kw::Enum) ||
self.token.is_keyword(kw::Struct) ||
- self.token.is_keyword(kw::Union)
+ self.token.is_keyword(kw::Union))
+ && self.look_ahead(1, |t| t.is_ident())
{
let kw_token = self.token.clone();
let kw_str = pprust::token_to_string(&kw_token);
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index ea76737..07e99cf 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -14,23 +14,20 @@
use crate::{Directory, DirectoryOwnership};
use crate::lexer::UnmatchedBrace;
-use syntax::ast::{
- self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, StrLit,
- IsAsync, MacDelimiter, Mutability, Visibility, VisibilityKind, Unsafety,
-};
-
+use rustc_errors::{PResult, Applicability, DiagnosticBuilder, FatalError};
+use rustc_data_structures::thin_vec::ThinVec;
+use syntax::ast::{self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, StrLit};
+use syntax::ast::{IsAsync, MacArgs, MacDelimiter, Mutability, Visibility, VisibilityKind, Unsafety};
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::token::{self, Token, TokenKind, DelimToken};
use syntax::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
use syntax::sess::ParseSess;
-use syntax::source_map::respan;
use syntax::struct_span_err;
use syntax::util::comments::{doc_comment_style, strip_doc_comment_decoration};
+use syntax_pos::source_map::respan;
use syntax_pos::symbol::{kw, sym, Symbol};
use syntax_pos::{Span, BytePos, DUMMY_SP, FileName};
-use rustc_data_structures::thin_vec::ThinVec;
-use errors::{PResult, Applicability, DiagnosticBuilder, FatalError};
use log::debug;
use std::borrow::Cow;
@@ -1010,27 +1007,49 @@
}
}
- fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, TokenStream)> {
- let delim = match self.token.kind {
- token::OpenDelim(delim) => delim,
- _ => {
- let msg = "expected open delimiter";
- let mut err = self.fatal(msg);
- err.span_label(self.token.span, msg);
- return Err(err)
+ fn parse_mac_args(&mut self) -> PResult<'a, P<MacArgs>> {
+ self.parse_mac_args_common(true).map(P)
+ }
+
+ fn parse_attr_args(&mut self) -> PResult<'a, MacArgs> {
+ self.parse_mac_args_common(false)
+ }
+
+ fn parse_mac_args_common(&mut self, delimited_only: bool) -> PResult<'a, MacArgs> {
+ Ok(if self.check(&token::OpenDelim(DelimToken::Paren)) ||
+ self.check(&token::OpenDelim(DelimToken::Bracket)) ||
+ self.check(&token::OpenDelim(DelimToken::Brace)) {
+ match self.parse_token_tree() {
+ TokenTree::Delimited(dspan, delim, tokens) =>
+ // We've confirmed above that there is a delimiter so unwrapping is OK.
+ MacArgs::Delimited(dspan, MacDelimiter::from_token(delim).unwrap(), tokens),
+ _ => unreachable!(),
}
- };
- let tts = match self.parse_token_tree() {
- TokenTree::Delimited(_, _, tts) => tts,
- _ => unreachable!(),
- };
- let delim = match delim {
- token::Paren => MacDelimiter::Parenthesis,
- token::Bracket => MacDelimiter::Bracket,
- token::Brace => MacDelimiter::Brace,
- token::NoDelim => self.bug("unexpected no delimiter"),
- };
- Ok((delim, tts.into()))
+ } else if !delimited_only {
+ if self.eat(&token::Eq) {
+ let eq_span = self.prev_span;
+ let mut is_interpolated_expr = false;
+ if let token::Interpolated(nt) = &self.token.kind {
+ if let token::NtExpr(..) = **nt {
+ is_interpolated_expr = true;
+ }
+ }
+ let token_tree = if is_interpolated_expr {
+ // We need to accept arbitrary interpolated expressions to continue
+ // supporting things like `doc = $expr` that work on stable.
+ // Non-literal interpolated expressions are rejected after expansion.
+ self.parse_token_tree()
+ } else {
+ self.parse_unsuffixed_lit()?.token_tree()
+ };
+
+ MacArgs::Eq(eq_span, token_tree.into())
+ } else {
+ MacArgs::Empty
+ }
+ } else {
+ return self.unexpected();
+ })
}
fn parse_or_use_outer_attributes(
diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs
index 59d7c2b..3777e17 100644
--- a/src/librustc_parse/parser/module.rs
+++ b/src/librustc_parse/parser/module.rs
@@ -4,13 +4,12 @@
use crate::{new_sub_parser_from_file, DirectoryOwnership};
+use rustc_errors::PResult;
use syntax::attr;
use syntax::ast::{self, Ident, Attribute, ItemKind, Mod, Crate};
use syntax::token::{self, TokenKind};
-use syntax::source_map::{SourceMap, Span, DUMMY_SP, FileName};
-
+use syntax_pos::source_map::{SourceMap, Span, DUMMY_SP, FileName};
use syntax_pos::symbol::sym;
-use errors::PResult;
use std::path::{self, Path, PathBuf};
@@ -212,13 +211,13 @@
// `./<id>.rs` and `./<id>/mod.rs`.
let relative_prefix_string;
let relative_prefix = if let Some(ident) = relative {
- relative_prefix_string = format!("{}{}", ident, path::MAIN_SEPARATOR);
+ relative_prefix_string = format!("{}{}", ident.name, path::MAIN_SEPARATOR);
&relative_prefix_string
} else {
""
};
- let mod_name = id.to_string();
+ let mod_name = id.name.to_string();
let default_path_str = format!("{}{}.rs", relative_prefix, mod_name);
let secondary_path_str = format!("{}{}{}mod.rs",
relative_prefix, mod_name, path::MAIN_SEPARATOR);
diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs
index b068a4f..42ece96 100644
--- a/src/librustc_parse/parser/pat.rs
+++ b/src/librustc_parse/parser/pat.rs
@@ -1,5 +1,6 @@
use super::{Parser, PathStyle};
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
+use rustc_errors::{PResult, Applicability, DiagnosticBuilder};
use syntax::ast::{self, Attribute, Pat, PatKind, FieldPat, RangeEnd, RangeSyntax, Mac};
use syntax::ast::{BindingMode, Ident, Mutability, Path, QSelf, Expr, ExprKind};
use syntax::mut_visit::{noop_visit_pat, noop_visit_mac, MutVisitor};
@@ -7,9 +8,8 @@
use syntax::print::pprust;
use syntax::ThinVec;
use syntax::token;
-use syntax::source_map::{respan, Span, Spanned};
+use syntax_pos::source_map::{respan, Span, Spanned};
use syntax_pos::symbol::{kw, sym};
-use errors::{PResult, Applicability, DiagnosticBuilder};
type Expected = Option<&'static str>;
@@ -338,7 +338,7 @@
(None, self.parse_path(PathStyle::Expr)?)
};
match self.token.kind {
- token::Not if qself.is_none() => self.parse_pat_mac_invoc(lo, path)?,
+ token::Not if qself.is_none() => self.parse_pat_mac_invoc(path)?,
token::DotDotDot | token::DotDotEq | token::DotDot => {
self.parse_pat_range_starting_with_path(lo, qself, path)?
}
@@ -593,14 +593,12 @@
}
/// Parse macro invocation
- fn parse_pat_mac_invoc(&mut self, lo: Span, path: Path) -> PResult<'a, PatKind> {
+ fn parse_pat_mac_invoc(&mut self, path: Path) -> PResult<'a, PatKind> {
self.bump();
- let (delim, tts) = self.expect_delimited_token_tree()?;
+ let args = self.parse_mac_args()?;
let mac = Mac {
path,
- tts,
- delim,
- span: lo.to(self.prev_span),
+ args,
prior_type_ascription: self.last_type_ascription,
};
Ok(PatKind::Mac(mac))
diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs
index 6830744..5334fc4 100644
--- a/src/librustc_parse/parser/path.rs
+++ b/src/librustc_parse/parser/path.rs
@@ -1,15 +1,15 @@
use super::{Parser, TokenType};
use crate::maybe_whole;
+use rustc_errors::{PResult, Applicability, pluralize};
use syntax::ast::{self, QSelf, Path, PathSegment, Ident, ParenthesizedArgs, AngleBracketedArgs};
use syntax::ast::{AnonConst, GenericArg, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
use syntax::ThinVec;
use syntax::token::{self, Token};
-use syntax::source_map::{Span, BytePos};
+use syntax_pos::source_map::{Span, BytePos};
use syntax_pos::symbol::{kw, sym};
use std::mem;
use log::debug;
-use errors::{PResult, Applicability, pluralize};
/// Specifies how to parse a path.
#[derive(Copy, Clone, PartialEq)]
@@ -108,42 +108,6 @@
Ok(Path { segments, span: lo.to(self.prev_span) })
}
- /// Like `parse_path`, but also supports parsing `Word` meta items into paths for
- /// backwards-compatibility. This is used when parsing derive macro paths in `#[derive]`
- /// attributes.
- fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, Path> {
- let meta_ident = match self.token.kind {
- token::Interpolated(ref nt) => match **nt {
- token::NtMeta(ref item) => match item.tokens.is_empty() {
- true => Some(item.path.clone()),
- false => None,
- },
- _ => None,
- },
- _ => None,
- };
- if let Some(path) = meta_ident {
- self.bump();
- return Ok(path);
- }
- self.parse_path(style)
- }
-
- /// Parse a list of paths inside `#[derive(path_0, ..., path_n)]`.
- pub fn parse_derive_paths(&mut self) -> PResult<'a, Vec<Path>> {
- self.expect(&token::OpenDelim(token::Paren))?;
- let mut list = Vec::new();
- while !self.eat(&token::CloseDelim(token::Paren)) {
- let path = self.parse_path_allowing_meta(PathStyle::Mod)?;
- list.push(path);
- if !self.eat(&token::Comma) {
- self.expect(&token::CloseDelim(token::Paren))?;
- break
- }
- }
- Ok(list)
- }
-
pub(super) fn parse_path_segments(
&mut self,
segments: &mut Vec<PathSegment>,
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index a5f2069..943b6ec 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -6,18 +6,18 @@
use crate::maybe_whole;
use crate::DirectoryOwnership;
+use rustc_errors::{PResult, Applicability};
use syntax::ThinVec;
use syntax::ptr::P;
use syntax::ast;
use syntax::ast::{DUMMY_NODE_ID, Stmt, StmtKind, Local, Block, BlockCheckMode, Expr, ExprKind};
-use syntax::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac, MacDelimiter};
+use syntax::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac};
use syntax::util::classify;
use syntax::token;
-use syntax::source_map::{respan, Span};
-use syntax::symbol::{kw, sym};
+use syntax_pos::source_map::{respan, Span};
+use syntax_pos::symbol::{kw, sym};
use std::mem;
-use errors::{PResult, Applicability};
impl<'a> Parser<'a> {
/// Parses a statement. This stops just before trailing semicolons on everything but items.
@@ -93,10 +93,11 @@
}));
}
- let (delim, tts) = self.expect_delimited_token_tree()?;
+ let args = self.parse_mac_args()?;
+ let delim = args.delim();
let hi = self.prev_span;
- let style = if delim == MacDelimiter::Brace {
+ let style = if delim == token::Brace {
MacStmtStyle::Braces
} else {
MacStmtStyle::NoBraces
@@ -104,12 +105,10 @@
let mac = Mac {
path,
- tts,
- delim,
- span: lo.to(hi),
+ args,
prior_type_ascription: self.last_type_ascription,
};
- let kind = if delim == MacDelimiter::Brace ||
+ let kind = if delim == token::Brace ||
self.token == token::Semi || self.token == token::Eof {
StmtKind::Mac(P((mac, style, attrs.into())))
}
@@ -130,7 +129,7 @@
self.warn_missing_semicolon();
StmtKind::Mac(P((mac, style, attrs.into())))
} else {
- let e = self.mk_expr(mac.span, ExprKind::Mac(mac), ThinVec::new());
+ let e = self.mk_expr(lo.to(hi), ExprKind::Mac(mac), ThinVec::new());
let e = self.maybe_recover_from_bad_qpath(e, true)?;
let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs
index 8e6bc29..84ffef6 100644
--- a/src/librustc_parse/parser/ty.rs
+++ b/src/librustc_parse/parser/ty.rs
@@ -3,19 +3,17 @@
use crate::{maybe_whole, maybe_recover_from_interpolated_ty_qpath};
+use rustc_errors::{PResult, Applicability, pluralize};
+use rustc_error_codes::*;
use syntax::ptr::P;
use syntax::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam, Lifetime, Ident};
use syntax::ast::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef};
use syntax::ast::{Mutability, AnonConst, Mac};
use syntax::token::{self, Token};
-use syntax::source_map::Span;
use syntax::struct_span_fatal;
+use syntax_pos::source_map::Span;
use syntax_pos::symbol::kw;
-use errors::{PResult, Applicability, pluralize};
-
-use rustc_error_codes::*;
-
/// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
/// `IDENT<<u8 as Trait>::AssocTy>`.
///
@@ -177,12 +175,10 @@
let path = self.parse_path(PathStyle::Type)?;
if self.eat(&token::Not) {
// Macro invocation in type position
- let (delim, tts) = self.expect_delimited_token_tree()?;
+ let args = self.parse_mac_args()?;
let mac = Mac {
path,
- tts,
- delim,
- span: lo.to(self.prev_span),
+ args,
prior_type_ascription: self.last_type_ascription,
};
TyKind::Mac(mac)
diff --git a/src/librustc_parse/validate_attr.rs b/src/librustc_parse/validate_attr.rs
index a3c9e26..94d3fe7 100644
--- a/src/librustc_parse/validate_attr.rs
+++ b/src/librustc_parse/validate_attr.rs
@@ -1,12 +1,13 @@
//! Meta-syntax validation logic of attributes for post-expansion.
-use errors::{PResult, Applicability};
+use crate::parse_in;
+
+use rustc_errors::{PResult, Applicability};
use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
-use syntax::ast::{self, Attribute, AttrKind, Ident, MetaItem, MetaItemKind};
+use syntax::ast::{self, Attribute, AttrKind, Ident, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
use syntax::attr::mk_name_value_item_str;
-use syntax::early_buffered_lints::BufferedEarlyLintId;
-use syntax::token;
-use syntax::tokenstream::TokenTree;
+use syntax::early_buffered_lints::ILL_FORMED_ATTRIBUTE_INPUT;
+use syntax::tokenstream::DelimSpan;
use syntax::sess::ParseSess;
use syntax_pos::{Symbol, sym};
@@ -19,11 +20,9 @@
// `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
Some((name, _, template, _)) if name != sym::rustc_dummy =>
check_builtin_attribute(sess, attr, name, template),
- _ => if let Some(TokenTree::Token(token)) = attr.get_normal_item().tokens.trees().next() {
- if token == token::Eq {
- // All key-value attributes are restricted to meta-item syntax.
- parse_meta(sess, attr).map_err(|mut err| err.emit()).ok();
- }
+ _ => if let MacArgs::Eq(..) = attr.get_normal_item().args {
+ // All key-value attributes are restricted to meta-item syntax.
+ parse_meta(sess, attr).map_err(|mut err| err.emit()).ok();
}
}
}
@@ -31,9 +30,20 @@
pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> {
Ok(match attr.kind {
AttrKind::Normal(ref item) => MetaItem {
- path: item.path.clone(),
- kind: super::parse_in_attr(sess, attr, |p| p.parse_meta_item_kind())?,
span: attr.span,
+ path: item.path.clone(),
+ kind: match &attr.get_normal_item().args {
+ MacArgs::Empty => MetaItemKind::Word,
+ MacArgs::Eq(_, t) => {
+ let v = parse_in(sess, t.clone(), "name value", |p| p.parse_unsuffixed_lit())?;
+ MetaItemKind::NameValue(v)
+ }
+ MacArgs::Delimited(dspan, delim, t) => {
+ check_meta_bad_delim(sess, *dspan, *delim, "wrong meta list delimiters");
+ let nmis = parse_in(sess, t.clone(), "meta list", |p| p.parse_meta_seq_top())?;
+ MetaItemKind::List(nmis)
+ }
+ }
},
AttrKind::DocComment(comment) => {
mk_name_value_item_str(Ident::new(sym::doc, attr.span), comment, attr.span)
@@ -41,6 +51,24 @@
})
}
+crate fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) {
+ if let ast::MacDelimiter::Parenthesis = delim {
+ return;
+ }
+
+ sess.span_diagnostic
+ .struct_span_err(span.entire(), msg)
+ .multipart_suggestion(
+ "the delimiters should be `(` and `)`",
+ vec![
+ (span.open, "(".to_string()),
+ (span.close, ")".to_string()),
+ ],
+ Applicability::MachineApplicable,
+ )
+ .emit();
+}
+
/// Checks that the given meta-item is compatible with this `AttributeTemplate`.
fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaItemKind) -> bool {
match meta {
@@ -97,7 +125,7 @@
}
if should_warn(name) {
sess.buffer_lint(
- BufferedEarlyLintId::IllFormedAttributeInput,
+ &ILL_FORMED_ATTRIBUTE_INPUT,
meta.span,
ast::CRATE_NODE_ID,
&msg,
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 5a29a56..29cfee8 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -737,14 +737,6 @@
|this| visit::walk_enum_def(this, enum_definition, generics, item_id))
}
- fn visit_mac(&mut self, mac: &Mac) {
- // when a new macro kind is added but the author forgets to set it up for expansion
- // because that's the only part that won't cause a compiler error
- self.session.diagnostic()
- .span_bug(mac.span, "macro invocation missed in expansion; did you forget to override \
- the relevant `fold_*()` method in `PlaceholderExpander`?");
- }
-
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
if let ImplItemKind::Method(ref sig, _) = ii.kind {
self.check_fn_decl(&sig.decl);
diff --git a/src/librustc_plugin_impl/lib.rs b/src/librustc_plugin_impl/lib.rs
index f4e90b7..5c4ea39 100644
--- a/src/librustc_plugin_impl/lib.rs
+++ b/src/librustc_plugin_impl/lib.rs
@@ -10,10 +10,16 @@
#![feature(nll)]
-#![recursion_limit="256"]
+use rustc::lint::LintStore;
-pub use registry::Registry;
-
-pub mod registry;
-pub mod load;
pub mod build;
+pub mod load;
+
+/// Structure used to register plugins.
+///
+/// A plugin registrar function takes an `&mut Registry` and should call
+/// methods to register its plugins.
+pub struct Registry<'a> {
+ /// The `LintStore` allows plugins to register new lints.
+ pub lint_store: &'a mut LintStore,
+}
diff --git a/src/librustc_plugin_impl/load.rs b/src/librustc_plugin_impl/load.rs
index 31b3b07..0bd9107 100644
--- a/src/librustc_plugin_impl/load.rs
+++ b/src/librustc_plugin_impl/load.rs
@@ -3,33 +3,21 @@
use rustc::middle::cstore::MetadataLoader;
use rustc::session::Session;
use rustc_metadata::locator;
-use crate::registry::Registry;
+use crate::Registry;
use std::borrow::ToOwned;
use std::env;
use std::mem;
use std::path::PathBuf;
-use syntax::ast;
+use syntax::ast::{Crate, Ident};
use syntax::struct_span_err;
-use syntax::symbol::{Symbol, kw, sym};
-use syntax_pos::{Span, DUMMY_SP};
+use syntax::symbol::sym;
+use syntax_pos::Span;
use rustc_error_codes::*;
/// Pointer to a registrar function.
-pub type PluginRegistrarFun =
- fn(&mut Registry<'_>);
-
-pub struct PluginRegistrar {
- pub fun: PluginRegistrarFun,
- pub args: Vec<ast::NestedMetaItem>,
-}
-
-struct PluginLoader<'a> {
- sess: &'a Session,
- metadata_loader: &'a dyn MetadataLoader,
- plugins: Vec<PluginRegistrar>,
-}
+type PluginRegistrarFn = fn(&mut Registry<'_>);
fn call_malformed_plugin_attribute(sess: &Session, span: Span) {
struct_span_err!(sess, span, E0498, "malformed `plugin` attribute")
@@ -40,98 +28,76 @@
/// Read plugin metadata and dynamically load registrar functions.
pub fn load_plugins(sess: &Session,
metadata_loader: &dyn MetadataLoader,
- krate: &ast::Crate,
- addl_plugins: Option<Vec<String>>) -> Vec<PluginRegistrar> {
- let mut loader = PluginLoader { sess, metadata_loader, plugins: Vec::new() };
+ krate: &Crate) -> Vec<PluginRegistrarFn> {
+ let mut plugins = Vec::new();
- // do not report any error now. since crate attributes are
- // not touched by expansion, every use of plugin without
- // the feature enabled will result in an error later...
- if sess.features_untracked().plugin {
- for attr in &krate.attrs {
- if !attr.check_name(sym::plugin) {
- continue;
- }
+ for attr in &krate.attrs {
+ if !attr.check_name(sym::plugin) {
+ continue;
+ }
- let plugins = match attr.meta_item_list() {
- Some(xs) => xs,
- None => continue,
- };
-
- for plugin in plugins {
- // plugins must have a name and can't be key = value
- let name = plugin.name_or_empty();
- if name != kw::Invalid && !plugin.is_value_str() {
- let args = plugin.meta_item_list().map(ToOwned::to_owned);
- loader.load_plugin(plugin.span(), name, args.unwrap_or_default());
- } else {
- call_malformed_plugin_attribute(sess, attr.span);
- }
+ for plugin in attr.meta_item_list().unwrap_or_default() {
+ match plugin.ident() {
+ Some(ident) if plugin.is_word() =>
+ load_plugin(&mut plugins, sess, metadata_loader, ident),
+ _ => call_malformed_plugin_attribute(sess, plugin.span()),
}
}
}
- if let Some(plugins) = addl_plugins {
- for plugin in plugins {
- loader.load_plugin(DUMMY_SP, Symbol::intern(&plugin), vec![]);
- }
- }
-
- loader.plugins
+ plugins
}
-impl<'a> PluginLoader<'a> {
- fn load_plugin(&mut self, span: Span, name: Symbol, args: Vec<ast::NestedMetaItem>) {
- let registrar = locator::find_plugin_registrar(self.sess, self.metadata_loader, span, name);
+fn load_plugin(plugins: &mut Vec<PluginRegistrarFn>,
+ sess: &Session,
+ metadata_loader: &dyn MetadataLoader,
+ ident: Ident) {
+ let registrar = locator::find_plugin_registrar(sess, metadata_loader, ident.span, ident.name);
- if let Some((lib, disambiguator)) = registrar {
- let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator);
- let fun = self.dylink_registrar(span, lib, symbol);
- self.plugins.push(PluginRegistrar {
- fun,
- args,
- });
- }
+ if let Some((lib, disambiguator)) = registrar {
+ let symbol = sess.generate_plugin_registrar_symbol(disambiguator);
+ let fun = dylink_registrar(sess, ident.span, lib, symbol);
+ plugins.push(fun);
}
+}
- // Dynamically link a registrar function into the compiler process.
- fn dylink_registrar(&mut self,
- span: Span,
- path: PathBuf,
- symbol: String) -> PluginRegistrarFun {
- use rustc_metadata::dynamic_lib::DynamicLibrary;
+// Dynamically link a registrar function into the compiler process.
+fn dylink_registrar(sess: &Session,
+ span: Span,
+ path: PathBuf,
+ symbol: String) -> PluginRegistrarFn {
+ use rustc_metadata::dynamic_lib::DynamicLibrary;
- // Make sure the path contains a / or the linker will search for it.
- let path = env::current_dir().unwrap().join(&path);
+ // Make sure the path contains a / or the linker will search for it.
+ let path = env::current_dir().unwrap().join(&path);
- let lib = match DynamicLibrary::open(Some(&path)) {
- Ok(lib) => lib,
- // this is fatal: there are almost certainly macros we need
- // inside this crate, so continue would spew "macro undefined"
- // errors
- Err(err) => {
- self.sess.span_fatal(span, &err)
- }
- };
-
- unsafe {
- let registrar =
- match lib.symbol(&symbol) {
- Ok(registrar) => {
- mem::transmute::<*mut u8,PluginRegistrarFun>(registrar)
- }
- // again fatal if we can't register macros
- Err(err) => {
- self.sess.span_fatal(span, &err)
- }
- };
-
- // Intentionally leak the dynamic library. We can't ever unload it
- // since the library can make things that will live arbitrarily long
- // (e.g., an @-box cycle or a thread).
- mem::forget(lib);
-
- registrar
+ let lib = match DynamicLibrary::open(Some(&path)) {
+ Ok(lib) => lib,
+ // this is fatal: there are almost certainly macros we need
+ // inside this crate, so continue would spew "macro undefined"
+ // errors
+ Err(err) => {
+ sess.span_fatal(span, &err)
}
+ };
+
+ unsafe {
+ let registrar =
+ match lib.symbol(&symbol) {
+ Ok(registrar) => {
+ mem::transmute::<*mut u8, PluginRegistrarFn>(registrar)
+ }
+ // again fatal if we can't register macros
+ Err(err) => {
+ sess.span_fatal(span, &err)
+ }
+ };
+
+ // Intentionally leak the dynamic library. We can't ever unload it
+ // since the library can make things that will live arbitrarily long
+ // (e.g., an @-box cycle or a thread).
+ mem::forget(lib);
+
+ registrar
}
}
diff --git a/src/librustc_plugin_impl/registry.rs b/src/librustc_plugin_impl/registry.rs
deleted file mode 100644
index bc684d5..0000000
--- a/src/librustc_plugin_impl/registry.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-//! Used by plugin crates to tell `rustc` about the plugins they provide.
-
-use rustc::lint::LintStore;
-use rustc::session::Session;
-use syntax::ast;
-use syntax_pos::Span;
-
-use std::borrow::ToOwned;
-
-/// Structure used to register plugins.
-///
-/// A plugin registrar function takes an `&mut Registry` and should call
-/// methods to register its plugins.
-///
-/// This struct has public fields and other methods for use by `rustc`
-/// itself. They are not documented here, and plugin authors should
-/// not use them.
-pub struct Registry<'a> {
- /// Compiler session. Useful if you want to emit diagnostic messages
- /// from the plugin registrar.
- pub sess: &'a Session,
-
- /// The `LintStore` allows plugins to register new lints.
- pub lint_store: &'a mut LintStore,
-
- #[doc(hidden)]
- pub args_hidden: Option<Vec<ast::NestedMetaItem>>,
-
- #[doc(hidden)]
- pub krate_span: Span,
-
- #[doc(hidden)]
- pub llvm_passes: Vec<String>,
-}
-
-impl<'a> Registry<'a> {
- #[doc(hidden)]
- pub fn new(sess: &'a Session, lint_store: &'a mut LintStore, krate_span: Span) -> Registry<'a> {
- Registry {
- sess,
- lint_store,
- args_hidden: None,
- krate_span,
- llvm_passes: vec![],
- }
- }
-
- /// Gets the plugin's arguments, if any.
- ///
- /// These are specified inside the `plugin` crate attribute as
- ///
- /// ```no_run
- /// #![plugin(my_plugin_name(... args ...))]
- /// ```
- ///
- /// Returns empty slice in case the plugin was loaded
- /// with `--extra-plugins`
- pub fn args(&self) -> &[ast::NestedMetaItem] {
- self.args_hidden.as_ref().map(|v| &v[..]).unwrap_or(&[])
- }
-
- /// Register an LLVM pass.
- ///
- /// Registration with LLVM itself is handled through static C++ objects with
- /// constructors. This method simply adds a name to the list of passes to
- /// execute.
- pub fn register_llvm_pass(&mut self, name: &str) {
- self.llvm_passes.push(name.to_owned());
- }
-}
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 4dcafb6..8dd45f5 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -422,11 +422,7 @@
Scope::MacroUsePrelude => {
suggestions.extend(this.macro_use_prelude.iter().filter_map(|(name, binding)| {
let res = binding.res();
- if filter_fn(res) {
- Some(TypoSuggestion::from_res(*name, res))
- } else {
- None
- }
+ filter_fn(res).then_some(TypoSuggestion::from_res(*name, res))
}));
}
Scope::BuiltinAttrs => {
@@ -440,11 +436,7 @@
Scope::ExternPrelude => {
suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| {
let res = Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX));
- if filter_fn(res) {
- Some(TypoSuggestion::from_res(ident.name, res))
- } else {
- None
- }
+ filter_fn(res).then_some(TypoSuggestion::from_res(ident.name, res))
}));
}
Scope::ToolPrelude => {
@@ -467,11 +459,7 @@
suggestions.extend(
primitive_types.iter().flat_map(|(name, prim_ty)| {
let res = Res::PrimTy(*prim_ty);
- if filter_fn(res) {
- Some(TypoSuggestion::from_res(*name, res))
- } else {
- None
- }
+ filter_fn(res).then_some(TypoSuggestion::from_res(*name, res))
})
)
}
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 666c482..4f95d6f 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -496,11 +496,7 @@
GenericParamKind::Lifetime { .. } => None,
GenericParamKind::Type { ref default, .. } => {
found_default |= default.is_some();
- if found_default {
- Some((Ident::with_dummy_span(param.ident.name), Res::Err))
- } else {
- None
- }
+ found_default.then_some((Ident::with_dummy_span(param.ident.name), Res::Err))
}
}));
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index be36e02..31f59e4 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -9,6 +9,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
#![feature(label_break_value)]
#![feature(nll)]
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 5bec5b5..396d948 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -1515,14 +1515,6 @@
}
}
- fn visit_mac(&mut self, mac: &'l ast::Mac) {
- // These shouldn't exist in the AST at this point, log a span bug.
- span_bug!(
- mac.span,
- "macro invocation should have been expanded out of AST"
- );
- }
-
fn visit_pat(&mut self, p: &'l ast::Pat) {
self.process_macro_use(p.span);
self.process_pat(p);
diff --git a/src/librustc_session/Cargo.toml b/src/librustc_session/Cargo.toml
new file mode 100644
index 0000000..dbbb4b9
--- /dev/null
+++ b/src/librustc_session/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_session"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+name = "rustc_session"
+path = "lib.rs"
+
+[dependencies]
+log = "0.4"
+rustc_errors = { path = "../librustc_errors" }
+rustc_feature = { path = "../librustc_feature" }
+rustc_target = { path = "../librustc_target" }
+rustc_serialize = { path = "../libserialize", package = "serialize" }
+rustc_data_structures = { path = "../librustc_data_structures" }
+syntax_pos = { path = "../libsyntax_pos" }
+rustc_index = { path = "../librustc_index" }
+rustc_fs_util = { path = "../librustc_fs_util" }
+num_cpus = "1.0"
diff --git a/src/librustc/dep_graph/cgu_reuse_tracker.rs b/src/librustc_session/cgu_reuse_tracker.rs
similarity index 95%
rename from src/librustc/dep_graph/cgu_reuse_tracker.rs
rename to src/librustc_session/cgu_reuse_tracker.rs
index 13f6f95..193cf01 100644
--- a/src/librustc/dep_graph/cgu_reuse_tracker.rs
+++ b/src/librustc_session/cgu_reuse_tracker.rs
@@ -2,10 +2,10 @@
//! compilation. This is used for incremental compilation tests and debug
//! output.
-use crate::session::Session;
use rustc_data_structures::fx::FxHashMap;
use std::sync::{Arc, Mutex};
use syntax_pos::Span;
+use log::debug;
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub enum CguReuse {
@@ -94,7 +94,7 @@
}
}
- pub fn check_expected_reuse(&self, sess: &Session) {
+ pub fn check_expected_reuse(&self, diag: &rustc_errors::Handler) {
if let Some(ref data) = self.data {
let data = data.lock().unwrap();
@@ -120,14 +120,14 @@
actual_reuse,
at_least,
expected_reuse);
- sess.span_err(error_span.0, &msg);
+ diag.span_err(error_span.0, &msg);
}
} else {
let msg = format!("CGU-reuse for `{}` (mangled: `{}`) was \
not recorded",
cgu_user_name,
cgu_name);
- sess.span_fatal(error_span.0, &msg);
+ diag.span_fatal(error_span.0, &msg).raise();
}
}
}
diff --git a/src/librustc/session/code_stats.rs b/src/librustc_session/code_stats.rs
similarity index 100%
rename from src/librustc/session/code_stats.rs
rename to src/librustc_session/code_stats.rs
diff --git a/src/librustc/session/config.rs b/src/librustc_session/config.rs
similarity index 97%
rename from src/librustc/session/config.rs
rename to src/librustc_session/config.rs
index fbfae72..58113bb 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc_session/config.rs
@@ -2,24 +2,24 @@
//! command-line options.
use crate::lint;
-use crate::middle::cstore;
-use crate::session::{early_error, early_warn, Session};
-use crate::session::search_paths::SearchPath;
+use crate::utils::NativeLibraryKind;
+use crate::{early_error, early_warn, Session};
+use crate::search_paths::SearchPath;
use rustc_data_structures::fx::FxHashSet;
-use rustc_feature::UnstableFeatures;
+use rustc_data_structures::impl_stable_hash_via_hash;
use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
use rustc_target::spec::{Target, TargetTriple};
-use syntax;
-use syntax::ast;
-use syntax::source_map::{FileName, FilePathMapping};
-use syntax::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION};
-use syntax::symbol::{sym, Symbol};
+use syntax_pos::source_map::{FileName, FilePathMapping};
+use syntax_pos::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION};
+use syntax_pos::symbol::{sym, Symbol};
+use rustc_feature::UnstableFeatures;
+use crate::parse::CrateConfig;
-use errors::emitter::HumanReadableErrorType;
-use errors::{ColorConfig, FatalError, Handler};
+use rustc_errors::emitter::HumanReadableErrorType;
+use rustc_errors::{ColorConfig, FatalError, Handler};
use getopts;
@@ -47,6 +47,17 @@
Thread,
}
+impl fmt::Display for Sanitizer {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match *self {
+ Sanitizer::Address => "address".fmt(f),
+ Sanitizer::Leak => "leak".fmt(f),
+ Sanitizer::Memory => "memory".fmt(f),
+ Sanitizer::Thread => "thread".fmt(f),
+ }
+ }
+}
+
impl FromStr for Sanitizer {
type Err = ();
fn from_str(s: &str) -> Result<Sanitizer, ()> {
@@ -337,7 +348,7 @@
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => ({
if $sub_hashes.insert(stringify!($opt_name),
$opt_expr as &dyn dep_tracking::DepTrackingHash).is_some() {
- bug!("duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name))
+ panic!("duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name))
}
});
}
@@ -404,7 +415,7 @@
describe_lints: bool [UNTRACKED],
output_types: OutputTypes [TRACKED],
search_paths: Vec<SearchPath> [UNTRACKED],
- libs: Vec<(String, Option<String>, Option<cstore::NativeLibraryKind>)> [TRACKED],
+ libs: Vec<(String, Option<String>, Option<NativeLibraryKind>)> [TRACKED],
maybe_sysroot: Option<PathBuf> [UNTRACKED],
target_triple: TargetTriple [TRACKED],
@@ -690,7 +701,7 @@
impl_stable_hash_via_hash!(EntryFnType);
-#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, HashStable)]
+#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
pub enum CrateType {
Executable,
Dylib,
@@ -700,6 +711,8 @@
ProcMacro,
}
+impl_stable_hash_via_hash!(CrateType);
+
#[derive(Clone, Hash)]
pub enum Passes {
Some(Vec<String>),
@@ -770,7 +783,7 @@
value, $outputname,
key, type_desc))
}
- (None, None) => bug!()
+ (None, None) => panic!()
}
}
found = true;
@@ -1364,8 +1377,6 @@
"enable queries of the dependency graph for regression testing"),
no_analysis: bool = (false, parse_bool, [UNTRACKED],
"parse and expand the source, but run no analysis"),
- extra_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED],
- "load extra plugins"),
unstable_options: bool = (false, parse_bool, [UNTRACKED],
"adds unstable command line options to rustc interface"),
force_overflow_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
@@ -1526,7 +1537,7 @@
CrateType::Rlib
}
-pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
+pub fn default_configuration(sess: &Session) -> CrateConfig {
let end = &sess.target.target.target_endian;
let arch = &sess.target.target.arch;
let wordsz = &sess.target.target.target_pointer_width;
@@ -1582,6 +1593,10 @@
}
}
}
+ if let Some(s) = &sess.opts.debugging_opts.sanitizer {
+ let symbol = Symbol::intern(&s.to_string());
+ ret.insert((sym::sanitize, Some(symbol)));
+ }
if sess.opts.debug_assertions {
ret.insert((Symbol::intern("debug_assertions"), None));
}
@@ -1594,13 +1609,13 @@
/// Converts the crate `cfg!` configuration from `String` to `Symbol`.
/// `rustc_interface::interface::Config` accepts this in the compiler configuration,
/// but the symbol interner is not yet set up then, so we must convert it later.
-pub fn to_crate_config(cfg: FxHashSet<(String, Option<String>)>) -> ast::CrateConfig {
+pub fn to_crate_config(cfg: FxHashSet<(String, Option<String>)>) -> CrateConfig {
cfg.into_iter()
.map(|(a, b)| (Symbol::intern(&a), b.map(|b| Symbol::intern(&b))))
.collect()
}
-pub fn build_configuration(sess: &Session, mut user_cfg: ast::CrateConfig) -> ast::CrateConfig {
+pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateConfig {
// Combine the configuration requested by the session (command line) with
// some default and generated configuration items.
let default_cfg = default_configuration(sess);
@@ -2366,7 +2381,7 @@
fn parse_libs(
matches: &getopts::Matches,
error_format: ErrorOutputType,
-) -> Vec<(String, Option<String>, Option<cstore::NativeLibraryKind>)> {
+) -> Vec<(String, Option<String>, Option<NativeLibraryKind>)> {
matches
.opt_strs("l")
.into_iter()
@@ -2377,10 +2392,12 @@
let kind = parts.next().unwrap();
let (name, kind) = match (parts.next(), kind) {
(None, name) => (name, None),
- (Some(name), "dylib") => (name, Some(cstore::NativeUnknown)),
- (Some(name), "framework") => (name, Some(cstore::NativeFramework)),
- (Some(name), "static") => (name, Some(cstore::NativeStatic)),
- (Some(name), "static-nobundle") => (name, Some(cstore::NativeStaticNobundle)),
+ (Some(name), "dylib") => (name, Some(NativeLibraryKind::NativeUnknown)),
+ (Some(name), "framework") => (name, Some(NativeLibraryKind::NativeFramework)),
+ (Some(name), "static") => (name, Some(NativeLibraryKind::NativeStatic)),
+ (Some(name), "static-nobundle") => {
+ (name, Some(NativeLibraryKind::NativeStaticNobundle))
+ }
(_, s) => {
early_error(
error_format,
@@ -2392,7 +2409,8 @@
);
}
};
- if kind == Some(cstore::NativeStaticNobundle) && !nightly_options::is_nightly_build() {
+ if kind == Some(NativeLibraryKind::NativeStaticNobundle) &&
+ !nightly_options::is_nightly_build() {
early_error(
error_format,
&format!(
@@ -2703,7 +2721,7 @@
use getopts;
use rustc_feature::UnstableFeatures;
use super::{ErrorOutputType, OptionStability, RustcOptGroup};
- use crate::session::early_error;
+ use crate::early_error;
pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool {
is_nightly_build()
@@ -2842,7 +2860,7 @@
/// how the hash should be calculated when adding a new command-line argument.
mod dep_tracking {
use crate::lint;
- use crate::middle::cstore;
+ use crate::utils::NativeLibraryKind;
use std::collections::BTreeMap;
use std::hash::Hash;
use std::path::PathBuf;
@@ -2850,9 +2868,9 @@
use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes,
Passes, Sanitizer, LtoCli, LinkerPluginLto, SwitchWithOptPath,
SymbolManglingVersion};
- use rustc_feature::UnstableFeatures;
use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel, TargetTriple};
- use syntax::edition::Edition;
+ use syntax_pos::edition::Edition;
+ use rustc_feature::UnstableFeatures;
pub trait DepTrackingHash {
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType);
@@ -2900,7 +2918,7 @@
impl_dep_tracking_hash_via_hash!(Option<RelroLevel>);
impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
impl_dep_tracking_hash_via_hash!(Option<PathBuf>);
- impl_dep_tracking_hash_via_hash!(Option<cstore::NativeLibraryKind>);
+ impl_dep_tracking_hash_via_hash!(Option<NativeLibraryKind>);
impl_dep_tracking_hash_via_hash!(CrateType);
impl_dep_tracking_hash_via_hash!(MergeFunctions);
impl_dep_tracking_hash_via_hash!(PanicStrategy);
@@ -2911,7 +2929,7 @@
impl_dep_tracking_hash_via_hash!(DebugInfo);
impl_dep_tracking_hash_via_hash!(UnstableFeatures);
impl_dep_tracking_hash_via_hash!(OutputTypes);
- impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind);
+ impl_dep_tracking_hash_via_hash!(NativeLibraryKind);
impl_dep_tracking_hash_via_hash!(Sanitizer);
impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
impl_dep_tracking_hash_via_hash!(TargetTriple);
@@ -2927,7 +2945,7 @@
impl_dep_tracking_hash_for_sortable_vec_of!((
String,
Option<String>,
- Option<cstore::NativeLibraryKind>
+ Option<NativeLibraryKind>
));
impl_dep_tracking_hash_for_sortable_vec_of!((String, u64));
impl_dep_tracking_hash_for_sortable_vec_of!(Sanitizer);
diff --git a/src/librustc/session/filesearch.rs b/src/librustc_session/filesearch.rs
similarity index 96%
rename from src/librustc/session/filesearch.rs
rename to src/librustc_session/filesearch.rs
index cf09d45..a0bdc6a 100644
--- a/src/librustc/session/filesearch.rs
+++ b/src/librustc_session/filesearch.rs
@@ -7,8 +7,9 @@
use std::fs;
use std::path::{Path, PathBuf};
-use crate::session::search_paths::{SearchPath, PathKind};
+use crate::search_paths::{SearchPath, PathKind};
use rustc_fs_util::fix_windows_verbatim_for_gcc;
+use log::debug;
#[derive(Copy, Clone)]
pub enum FileMatch {
@@ -124,7 +125,7 @@
// gcc chokes on verbatim paths which fs::canonicalize generates
// so we try to avoid those kinds of paths.
Ok(canon) => Some(fix_windows_verbatim_for_gcc(&canon)),
- Err(e) => bug!("failed to get realpath: {}", e),
+ Err(e) => panic!("failed to get realpath: {}", e),
}
})
}
@@ -133,7 +134,7 @@
Ok(exe) => {
match canonicalize(Some(exe)) {
Some(mut p) => { p.pop(); p.pop(); p },
- None => bug!("can't determine value for sysroot")
+ None => panic!("can't determine value for sysroot")
}
}
Err(ref e) => panic!(format!("failed to get current_exe: {}", e))
diff --git a/src/librustc_session/lib.rs b/src/librustc_session/lib.rs
new file mode 100644
index 0000000..9d7c231
--- /dev/null
+++ b/src/librustc_session/lib.rs
@@ -0,0 +1,21 @@
+#![feature(test)]
+
+// Use the test crate here so we depend on getopts through it. This allow tools to link to both
+// librustc_session and libtest.
+extern crate test as _;
+extern crate getopts;
+
+pub mod cgu_reuse_tracker;
+pub mod utils;
+#[macro_use]
+pub mod lint;
+pub mod node_id;
+pub mod parse;
+
+mod code_stats;
+pub mod config;
+pub mod filesearch;
+pub mod search_paths;
+
+mod session;
+pub use session::*;
diff --git a/src/librustc_session/lint.rs b/src/librustc_session/lint.rs
new file mode 100644
index 0000000..faa6a7a
--- /dev/null
+++ b/src/librustc_session/lint.rs
@@ -0,0 +1,254 @@
+use syntax_pos::{MultiSpan, Symbol, sym};
+use syntax_pos::edition::Edition;
+use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher};
+pub use self::Level::*;
+use crate::node_id::NodeId;
+
+/// Setting for how to handle a lint.
+#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
+pub enum Level {
+ Allow, Warn, Deny, Forbid,
+}
+
+rustc_data_structures::impl_stable_hash_via_hash!(Level);
+
+impl Level {
+ /// Converts a level to a lower-case string.
+ pub fn as_str(self) -> &'static str {
+ match self {
+ Level::Allow => "allow",
+ Level::Warn => "warn",
+ Level::Deny => "deny",
+ Level::Forbid => "forbid",
+ }
+ }
+
+ /// Converts a lower-case string to a level.
+ pub fn from_str(x: &str) -> Option<Level> {
+ match x {
+ "allow" => Some(Level::Allow),
+ "warn" => Some(Level::Warn),
+ "deny" => Some(Level::Deny),
+ "forbid" => Some(Level::Forbid),
+ _ => None,
+ }
+ }
+
+ /// Converts a symbol to a level.
+ pub fn from_symbol(x: Symbol) -> Option<Level> {
+ match x {
+ sym::allow => Some(Level::Allow),
+ sym::warn => Some(Level::Warn),
+ sym::deny => Some(Level::Deny),
+ sym::forbid => Some(Level::Forbid),
+ _ => None,
+ }
+ }
+}
+
+/// Specification of a single lint.
+#[derive(Copy, Clone, Debug)]
+pub struct Lint {
+ /// A string identifier for the lint.
+ ///
+ /// This identifies the lint in attributes and in command-line arguments.
+ /// In those contexts it is always lowercase, but this field is compared
+ /// in a way which is case-insensitive for ASCII characters. This allows
+ /// `declare_lint!()` invocations to follow the convention of upper-case
+ /// statics without repeating the name.
+ ///
+ /// The name is written with underscores, e.g., "unused_imports".
+ /// On the command line, underscores become dashes.
+ pub name: &'static str,
+
+ /// Default level for the lint.
+ pub default_level: Level,
+
+ /// Description of the lint or the issue it detects.
+ ///
+ /// e.g., "imports that are never used"
+ pub desc: &'static str,
+
+ /// Starting at the given edition, default to the given lint level. If this is `None`, then use
+ /// `default_level`.
+ pub edition_lint_opts: Option<(Edition, Level)>,
+
+ /// `true` if this lint is reported even inside expansions of external macros.
+ pub report_in_external_macro: bool,
+
+ pub future_incompatible: Option<FutureIncompatibleInfo>,
+
+ pub is_plugin: bool,
+}
+
+/// Extra information for a future incompatibility lint.
+#[derive(Copy, Clone, Debug)]
+pub struct FutureIncompatibleInfo {
+ /// e.g., a URL for an issue/PR/RFC or error code
+ pub reference: &'static str,
+ /// If this is an edition fixing lint, the edition in which
+ /// this lint becomes obsolete
+ pub edition: Option<Edition>,
+}
+
+impl Lint {
+ pub const fn default_fields_for_macro() -> Self {
+ Lint {
+ name: "",
+ default_level: Level::Forbid,
+ desc: "",
+ edition_lint_opts: None,
+ is_plugin: false,
+ report_in_external_macro: false,
+ future_incompatible: None,
+ }
+ }
+
+ /// Gets the lint's name, with ASCII letters converted to lowercase.
+ pub fn name_lower(&self) -> String {
+ self.name.to_ascii_lowercase()
+ }
+
+ pub fn default_level(&self, edition: Edition) -> Level {
+ self.edition_lint_opts
+ .filter(|(e, _)| *e <= edition)
+ .map(|(_, l)| l)
+ .unwrap_or(self.default_level)
+ }
+}
+
+/// Identifies a lint known to the compiler.
+#[derive(Clone, Copy, Debug)]
+pub struct LintId {
+ // Identity is based on pointer equality of this field.
+ pub lint: &'static Lint,
+}
+
+impl PartialEq for LintId {
+ fn eq(&self, other: &LintId) -> bool {
+ std::ptr::eq(self.lint, other.lint)
+ }
+}
+
+impl Eq for LintId { }
+
+impl std::hash::Hash for LintId {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ let ptr = self.lint as *const Lint;
+ ptr.hash(state);
+ }
+}
+
+impl LintId {
+ /// Gets the `LintId` for a `Lint`.
+ pub fn of(lint: &'static Lint) -> LintId {
+ LintId {
+ lint,
+ }
+ }
+
+ pub fn lint_name_raw(&self) -> &'static str {
+ self.lint.name
+ }
+
+ /// Gets the name of the lint.
+ pub fn to_string(&self) -> String {
+ self.lint.name_lower()
+ }
+}
+
+impl<HCX> HashStable<HCX> for LintId {
+ #[inline]
+ fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
+ self.lint_name_raw().hash_stable(hcx, hasher);
+ }
+}
+
+impl<HCX> ToStableHashKey<HCX> for LintId {
+ type KeyType = &'static str;
+
+ #[inline]
+ fn to_stable_hash_key(&self, _: &HCX) -> &'static str {
+ self.lint_name_raw()
+ }
+}
+
+/// Stores buffered lint info which can later be passed to `librustc`.
+pub struct BufferedEarlyLint {
+ /// The span of code that we are linting on.
+ pub span: MultiSpan,
+
+ /// The lint message.
+ pub msg: String,
+
+ /// The `NodeId` of the AST node that generated the lint.
+ pub id: NodeId,
+
+ /// A lint Id that can be passed to `rustc::lint::Lint::from_parser_lint_id`.
+ pub lint_id: &'static Lint,
+}
+
+/// Declares a static item of type `&'static Lint`.
+#[macro_export]
+macro_rules! declare_lint {
+ ($vis: vis $NAME: ident, $Level: ident, $desc: expr) => (
+ $crate::declare_lint!(
+ $vis $NAME, $Level, $desc,
+ );
+ );
+ ($vis: vis $NAME: ident, $Level: ident, $desc: expr,
+ $(@future_incompatible = $fi:expr;)? $($v:ident),*) => (
+ $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
+ name: stringify!($NAME),
+ default_level: $crate::lint::$Level,
+ desc: $desc,
+ edition_lint_opts: None,
+ is_plugin: false,
+ $($v: true,)*
+ $(future_incompatible: Some($fi),)*
+ ..$crate::lint::Lint::default_fields_for_macro()
+ };
+ );
+ ($vis: vis $NAME: ident, $Level: ident, $desc: expr,
+ $lint_edition: expr => $edition_level: ident
+ ) => (
+ $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
+ name: stringify!($NAME),
+ default_level: $crate::lint::$Level,
+ desc: $desc,
+ edition_lint_opts: Some(($lint_edition, $crate::lint::Level::$edition_level)),
+ report_in_external_macro: false,
+ is_plugin: false,
+ };
+ );
+}
+
+#[macro_export]
+macro_rules! declare_tool_lint {
+ (
+ $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level: ident, $desc: expr
+ ) => (
+ $crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, false}
+ );
+ (
+ $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
+ report_in_external_macro: $rep:expr
+ ) => (
+ $crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, $rep}
+ );
+ (
+ $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
+ $external:expr
+ ) => (
+ $(#[$attr])*
+ $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
+ name: &concat!(stringify!($tool), "::", stringify!($NAME)),
+ default_level: $crate::lint::$Level,
+ desc: $desc,
+ edition_lint_opts: None,
+ report_in_external_macro: $external,
+ future_incompatible: None,
+ is_plugin: true,
+ };
+ );
+}
diff --git a/src/librustc_session/node_id.rs b/src/librustc_session/node_id.rs
new file mode 100644
index 0000000..7b14db2
--- /dev/null
+++ b/src/librustc_session/node_id.rs
@@ -0,0 +1,39 @@
+use std::fmt;
+use rustc_index::vec::Idx;
+use rustc_serialize::{Encoder, Decoder};
+use syntax_pos::ExpnId;
+
+rustc_index::newtype_index! {
+ pub struct NodeId {
+ ENCODABLE = custom
+ DEBUG_FORMAT = "NodeId({})"
+ }
+}
+
+impl NodeId {
+ pub fn placeholder_from_expn_id(expn_id: ExpnId) -> Self {
+ NodeId::from_u32(expn_id.as_u32())
+ }
+
+ pub fn placeholder_to_expn_id(self) -> ExpnId {
+ ExpnId::from_u32(self.as_u32())
+ }
+}
+
+impl fmt::Display for NodeId {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(&self.as_u32(), f)
+ }
+}
+
+impl rustc_serialize::UseSpecializedEncodable for NodeId {
+ fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+ s.emit_u32(self.as_u32())
+ }
+}
+
+impl rustc_serialize::UseSpecializedDecodable for NodeId {
+ fn default_decode<D: Decoder>(d: &mut D) -> Result<NodeId, D::Error> {
+ d.read_u32().map(NodeId::from_u32)
+ }
+}
diff --git a/src/libsyntax/sess.rs b/src/librustc_session/parse.rs
similarity index 92%
rename from src/libsyntax/sess.rs
rename to src/librustc_session/parse.rs
index aa9217c..09442f2 100644
--- a/src/libsyntax/sess.rs
+++ b/src/librustc_session/parse.rs
@@ -1,10 +1,10 @@
//! Contains `ParseSess` which holds state living beyond what one `Parser` might.
//! It also serves as an input to the parser itself.
-use crate::ast::{CrateConfig, NodeId};
-use crate::early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId};
+use crate::node_id::NodeId;
+use crate::lint::BufferedEarlyLint;
-use errors::{Applicability, emitter::SilentEmitter, Handler, ColorConfig, DiagnosticBuilder};
+use rustc_errors::{Applicability, emitter::SilentEmitter, Handler, ColorConfig, DiagnosticBuilder};
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
use rustc_data_structures::sync::{Lrc, Lock, Once};
use rustc_feature::UnstableFeatures;
@@ -16,6 +16,10 @@
use std::path::PathBuf;
use std::str;
+/// The set of keys (and, optionally, values) that define the compilation
+/// environment of the crate, used to drive conditional compilation.
+pub type CrateConfig = FxHashSet<(Symbol, Option<Symbol>)>;
+
/// Collected spans during parsing for places where a certain feature was
/// used and should be feature gated accordingly in `check_crate`.
#[derive(Default)]
@@ -137,7 +141,7 @@
pub fn buffer_lint(
&self,
- lint_id: BufferedEarlyLintId,
+ lint_id: &'static crate::lint::Lint,
span: impl Into<MultiSpan>,
id: NodeId,
msg: &str,
diff --git a/src/librustc/session/search_paths.rs b/src/librustc_session/search_paths.rs
similarity index 90%
rename from src/librustc/session/search_paths.rs
rename to src/librustc_session/search_paths.rs
index 949dad7..b9f2ae7 100644
--- a/src/librustc/session/search_paths.rs
+++ b/src/librustc_session/search_paths.rs
@@ -1,6 +1,6 @@
use std::path::{Path, PathBuf};
-use crate::session::{early_error, config};
-use crate::session::filesearch::make_target_lib_path;
+use crate::{early_error, config};
+use crate::filesearch::make_target_lib_path;
#[derive(Clone, Debug)]
pub struct SearchPath {
@@ -9,7 +9,7 @@
pub files: Vec<PathBuf>,
}
-#[derive(PartialEq, Clone, Copy, Debug, HashStable)]
+#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq)]
pub enum PathKind {
Native,
Crate,
@@ -19,6 +19,8 @@
All,
}
+rustc_data_structures::impl_stable_hash_via_hash!(PathKind);
+
impl PathKind {
pub fn matches(&self, kind: PathKind) -> bool {
match (self, kind) {
diff --git a/src/librustc/session/mod.rs b/src/librustc_session/session.rs
similarity index 95%
rename from src/librustc/session/mod.rs
rename to src/librustc_session/session.rs
index 74ba83d..150d207 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc_session/session.rs
@@ -1,36 +1,38 @@
-pub use self::code_stats::{DataTypeKind, SizeKind, FieldInfo, VariantInfo};
-use self::code_stats::CodeStats;
+pub use crate::code_stats::{DataTypeKind, SizeKind, FieldInfo, VariantInfo};
+use crate::code_stats::CodeStats;
-use crate::dep_graph::cgu_reuse_tracker::CguReuseTracker;
+use crate::cgu_reuse_tracker::CguReuseTracker;
use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use crate::lint;
-use crate::session::config::{OutputType, PrintRequest, Sanitizer, SwitchWithOptPath};
-use crate::session::search_paths::{PathKind, SearchPath};
-use crate::util::nodemap::{FxHashMap, FxHashSet};
-use crate::util::common::{duration_to_secs_str, ErrorReported};
+use crate::filesearch;
+use crate::config::{self, OutputType, PrintRequest, Sanitizer, SwitchWithOptPath};
+use crate::search_paths::{PathKind, SearchPath};
+use crate::utils::duration_to_secs_str;
+use rustc_errors::ErrorReported;
use rustc_data_structures::base_n;
use rustc_data_structures::sync::{
self, Lrc, Lock, OneThread, Once, AtomicU64, AtomicUsize, Ordering,
Ordering::SeqCst,
};
+use rustc_data_structures::impl_stable_hash_via_hash;
-use errors::{DiagnosticBuilder, DiagnosticId, Applicability};
-use errors::emitter::{Emitter, EmitterWriter};
-use errors::emitter::HumanReadableErrorType;
-use errors::annotate_snippet_emitter_writer::{AnnotateSnippetEmitterWriter};
-use syntax::edition::Edition;
-use errors::json::JsonEmitter;
-use syntax::source_map;
-use syntax::sess::ParseSess;
+use rustc_errors::{DiagnosticBuilder, DiagnosticId, Applicability};
+use rustc_errors::emitter::{Emitter, EmitterWriter};
+use rustc_errors::emitter::HumanReadableErrorType;
+use rustc_errors::annotate_snippet_emitter_writer::{AnnotateSnippetEmitterWriter};
+use syntax_pos::edition::Edition;
+use rustc_errors::json::JsonEmitter;
+use syntax_pos::source_map;
+use crate::parse::ParseSess;
use syntax_pos::{MultiSpan, Span};
use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple};
use rustc_data_structures::flock;
-use rustc_data_structures::jobserver;
+use rustc_data_structures::jobserver::{self, Client};
use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef};
-use ::jobserver::Client;
use std;
use std::cell::{self, RefCell};
@@ -42,11 +44,6 @@
use std::time::Duration;
use std::sync::Arc;
-mod code_stats;
-pub mod config;
-pub mod filesearch;
-pub mod search_paths;
-
pub struct OptimizationFuel {
/// If `-zfuel=crate=n` is specified, initially set to `n`, otherwise `0`.
remaining: u64,
@@ -76,7 +73,6 @@
/// (sub)diagnostics that have been set once, but should not be set again,
/// in order to avoid redundantly verbose output (Issue #24690, #44953).
pub one_time_diagnostics: Lock<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
- pub plugin_llvm_passes: OneThread<RefCell<Vec<String>>>,
pub crate_types: Once<Vec<config::CrateType>>,
/// The `crate_disambiguator` is constructed out of all the `-C metadata`
/// arguments passed to the compiler. Its value together with the crate-name
@@ -336,7 +332,7 @@
self.diagnostic().span_note_without_error(sp, msg)
}
- pub fn diagnostic(&self) -> &errors::Handler {
+ pub fn diagnostic(&self) -> &rustc_errors::Handler {
&self.parse_sess.span_diagnostic
}
@@ -681,7 +677,7 @@
if let IncrCompSession::NotInitialized = *incr_comp_session {
} else {
- bug!(
+ panic!(
"Trying to initialize IncrCompSession `{:?}`",
*incr_comp_session
)
@@ -699,7 +695,7 @@
if let IncrCompSession::Active { .. } = *incr_comp_session {
} else {
- bug!(
+ panic!(
"trying to finalize `IncrCompSession` `{:?}`",
*incr_comp_session
);
@@ -720,7 +716,7 @@
..
} => session_directory.clone(),
IncrCompSession::InvalidBecauseOfErrors { .. } => return,
- _ => bug!(
+ _ => panic!(
"trying to invalidate `IncrCompSession` `{:?}`",
*incr_comp_session
),
@@ -737,7 +733,7 @@
cell::Ref::map(
incr_comp_session,
|incr_comp_session| match *incr_comp_session {
- IncrCompSession::NotInitialized => bug!(
+ IncrCompSession::NotInitialized => panic!(
"trying to get session directory from `IncrCompSession`: {:?}",
*incr_comp_session,
),
@@ -756,11 +752,7 @@
}
pub fn incr_comp_session_dir_opt(&self) -> Option<cell::Ref<'_, PathBuf>> {
- if self.opts.incremental.is_some() {
- Some(self.incr_comp_session_dir())
- } else {
- None
- }
+ self.opts.incremental.as_ref().map(|_| self.incr_comp_session_dir())
}
pub fn print_perf_stats(&self) {
@@ -917,7 +909,7 @@
pub fn build_session(
sopts: config::Options,
local_crate_source_file: Option<PathBuf>,
- registry: errors::registry::Registry,
+ registry: rustc_errors::registry::Registry,
) -> Session {
let file_path_mapping = sopts.file_path_mapping();
@@ -933,7 +925,7 @@
fn default_emitter(
sopts: &config::Options,
- registry: errors::registry::Registry,
+ registry: rustc_errors::registry::Registry,
source_map: &Lrc<source_map::SourceMap>,
emitter_dest: Option<Box<dyn Write + Send>>,
) -> Box<dyn Emitter + sync::Send> {
@@ -1002,7 +994,7 @@
pub fn build_session_with_source_map(
sopts: config::Options,
local_crate_source_file: Option<PathBuf>,
- registry: errors::registry::Registry,
+ registry: rustc_errors::registry::Registry,
source_map: Lrc<source_map::SourceMap>,
diagnostics_output: DiagnosticOutput,
lint_caps: FxHashMap<lint::LintId, lint::Level>,
@@ -1033,9 +1025,9 @@
};
let emitter = default_emitter(&sopts, registry, &source_map, write_dest);
- let diagnostic_handler = errors::Handler::with_emitter_and_flags(
+ let diagnostic_handler = rustc_errors::Handler::with_emitter_and_flags(
emitter,
- errors::HandlerFlags {
+ rustc_errors::HandlerFlags {
can_emit_warnings,
treat_err_as_bug,
report_delayed_bugs,
@@ -1057,7 +1049,7 @@
fn build_session_(
sopts: config::Options,
local_crate_source_file: Option<PathBuf>,
- span_diagnostic: errors::Handler,
+ span_diagnostic: rustc_errors::Handler,
source_map: Lrc<source_map::SourceMap>,
driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
) -> Session {
@@ -1083,8 +1075,9 @@
None
}
}
- }
- else { None };
+ } else {
+ None
+ };
let host_triple = TargetTriple::from_triple(config::host_triple());
let host = Target::search(&host_triple).unwrap_or_else(|e|
@@ -1149,7 +1142,6 @@
local_crate_source_file,
working_dir,
one_time_diagnostics: Default::default(),
- plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())),
crate_types: Once::new(),
crate_disambiguator: Once::new(),
features: Once::new(),
@@ -1283,9 +1275,9 @@
config::ErrorOutputType::Json { pretty, json_rendered } =>
Box::new(JsonEmitter::basic(pretty, json_rendered, false)),
};
- let handler = errors::Handler::with_emitter(true, None, emitter);
+ let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
handler.struct_fatal(msg).emit();
- errors::FatalError.raise();
+ rustc_errors::FatalError.raise();
}
pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
@@ -1297,7 +1289,7 @@
config::ErrorOutputType::Json { pretty, json_rendered } =>
Box::new(JsonEmitter::basic(pretty, json_rendered, false)),
};
- let handler = errors::Handler::with_emitter(true, None, emitter);
+ let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
handler.struct_warn(msg).emit();
}
diff --git a/src/librustc_session/utils.rs b/src/librustc_session/utils.rs
new file mode 100644
index 0000000..ad59339
--- /dev/null
+++ b/src/librustc_session/utils.rs
@@ -0,0 +1,25 @@
+// Hack up our own formatting for the duration to make it easier for scripts
+// to parse (always use the same number of decimal places and the same unit).
+pub fn duration_to_secs_str(dur: std::time::Duration) -> String {
+ const NANOS_PER_SEC: f64 = 1_000_000_000.0;
+ let secs = dur.as_secs() as f64 +
+ dur.subsec_nanos() as f64 / NANOS_PER_SEC;
+
+ format!("{:.3}", secs)
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+pub enum NativeLibraryKind {
+ /// native static library (.a archive)
+ NativeStatic,
+ /// native static library, which doesn't get bundled into .rlibs
+ NativeStaticNobundle,
+ /// macOS-specific
+ NativeFramework,
+ /// Windows dynamic library without import library.
+ NativeRawDylib,
+ /// default way to specify a dynamic library
+ NativeUnknown,
+}
+
+rustc_data_structures::impl_stable_hash_via_hash!(NativeLibraryKind);
diff --git a/src/librustc_target/abi/call/aarch64.rs b/src/librustc_target/abi/call/aarch64.rs
index 45fe475..06c001e 100644
--- a/src/librustc_target/abi/call/aarch64.rs
+++ b/src/librustc_target/abi/call/aarch64.rs
@@ -20,14 +20,7 @@
RegKind::Vector => size.bits() == 64 || size.bits() == 128
};
- if valid_unit {
- Some(Uniform {
- unit,
- total: size
- })
- } else {
- None
- }
+ valid_unit.then_some(Uniform { unit, total: size })
})
}
diff --git a/src/librustc_target/abi/call/arm.rs b/src/librustc_target/abi/call/arm.rs
index ff929f3..36971c1 100644
--- a/src/librustc_target/abi/call/arm.rs
+++ b/src/librustc_target/abi/call/arm.rs
@@ -21,14 +21,7 @@
RegKind::Vector => size.bits() == 64 || size.bits() == 128
};
- if valid_unit {
- Some(Uniform {
- unit,
- total: size
- })
- } else {
- None
- }
+ valid_unit.then_some(Uniform { unit, total: size })
})
}
diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs
index 3a3ad76..5119464 100644
--- a/src/librustc_target/abi/call/mod.rs
+++ b/src/librustc_target/abi/call/mod.rs
@@ -416,11 +416,7 @@
// i686-pc-windows-msvc, it results in wrong stack offsets.
// attrs.pointee_align = Some(self.layout.align.abi);
- let extra_attrs = if self.layout.is_unsized() {
- Some(ArgAttributes::new())
- } else {
- None
- };
+ let extra_attrs = self.layout.is_unsized().then_some(ArgAttributes::new());
self.mode = PassMode::Indirect(attrs, extra_attrs);
}
@@ -492,7 +488,12 @@
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Conv {
+ // General language calling conventions, for which every target
+ // should have its own backend (e.g. LLVM) support.
C,
+ Rust,
+
+ // Target-specific calling conventions.
ArmAapcs,
diff --git a/src/librustc_target/abi/call/powerpc64.rs b/src/librustc_target/abi/call/powerpc64.rs
index f967a83..fe45948 100644
--- a/src/librustc_target/abi/call/powerpc64.rs
+++ b/src/librustc_target/abi/call/powerpc64.rs
@@ -32,14 +32,7 @@
RegKind::Vector => arg.layout.size.bits() == 128
};
- if valid_unit {
- Some(Uniform {
- unit,
- total: arg.layout.size
- })
- } else {
- None
- }
+ valid_unit.then_some(Uniform { unit, total: arg.layout.size })
})
}
diff --git a/src/librustc_target/abi/call/sparc64.rs b/src/librustc_target/abi/call/sparc64.rs
index fe2c427..32be7b8 100644
--- a/src/librustc_target/abi/call/sparc64.rs
+++ b/src/librustc_target/abi/call/sparc64.rs
@@ -20,14 +20,7 @@
RegKind::Vector => arg.layout.size.bits() == 128
};
- if valid_unit {
- Some(Uniform {
- unit,
- total: arg.layout.size
- })
- } else {
- None
- }
+ valid_unit.then_some(Uniform { unit, total: arg.layout.size })
})
}
diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs
index 5582eaf..6a1498e 100644
--- a/src/librustc_target/lib.rs
+++ b/src/librustc_target/lib.rs
@@ -10,6 +10,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(box_syntax)]
+#![feature(bool_to_option)]
#![feature(nll)]
#![feature(slice_patterns)]
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index 2907625..693cf75 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -803,6 +803,9 @@
/// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers
pub llvm_abiname: String,
+
+ /// Whether or not RelaxElfRelocation flag will be passed to the linker
+ pub relax_elf_relocations: bool,
}
impl Default for TargetOptions {
@@ -890,6 +893,7 @@
merge_functions: MergeFunctions::Aliases,
target_mcount: "mcount".to_string(),
llvm_abiname: "".to_string(),
+ relax_elf_relocations: false,
}
}
}
@@ -1207,6 +1211,7 @@
key!(merge_functions, MergeFunctions)?;
key!(target_mcount);
key!(llvm_abiname);
+ key!(relax_elf_relocations, bool);
if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -1426,6 +1431,7 @@
target_option_val!(merge_functions);
target_option_val!(target_mcount);
target_option_val!(llvm_abiname);
+ target_option_val!(relax_elf_relocations);
if default.abi_blacklist != self.options.abi_blacklist {
d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
diff --git a/src/librustc_target/spec/wasm32_base.rs b/src/librustc_target/spec/wasm32_base.rs
index 6f00245..e18a9e6 100644
--- a/src/librustc_target/spec/wasm32_base.rs
+++ b/src/librustc_target/spec/wasm32_base.rs
@@ -140,6 +140,9 @@
has_elf_tls: true,
tls_model: "local-exec".to_string(),
+ // gdb scripts don't work on wasm blobs
+ emit_debug_gdb_scripts: false,
+
.. Default::default()
}
}
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 7c24c88..dbcd77b 100644
--- a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
+++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
@@ -1,35 +1,31 @@
use std::iter;
-use super::{LinkerFlavor, PanicStrategy, Target, TargetOptions};
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};
pub fn target() -> Result<Target, String> {
const PRE_LINK_ARGS: &[&str] = &[
- "-Wl,--as-needed",
- "-Wl,-z,noexecstack",
- "-m64",
- "-fuse-ld=gold",
- "-nostdlib",
- "-shared",
- "-Wl,-e,sgx_entry",
- "-Wl,-Bstatic",
- "-Wl,--gc-sections",
- "-Wl,-z,text",
- "-Wl,-z,norelro",
- "-Wl,--rosegment",
- "-Wl,--no-undefined",
- "-Wl,--error-unresolved-symbols",
- "-Wl,--no-undefined-version",
- "-Wl,-Bsymbolic",
- "-Wl,--export-dynamic",
+ "--as-needed",
+ "--eh-frame-hdr",
+ "-z" , "noexecstack",
+ "-e","sgx_entry",
+ "-Bstatic",
+ "--gc-sections",
+ "-z","text",
+ "-z","norelro",
+ "--no-undefined",
+ "--error-unresolved-symbols",
+ "--no-undefined-version",
+ "-Bsymbolic",
+ "--export-dynamic",
// The following symbols are needed by libunwind, which is linked after
// libstd. Make sure they're included in the link.
- "-Wl,-u,__rust_abort",
- "-Wl,-u,__rust_c_alloc",
- "-Wl,-u,__rust_c_dealloc",
- "-Wl,-u,__rust_print_err",
- "-Wl,-u,__rust_rwlock_rdlock",
- "-Wl,-u,__rust_rwlock_unlock",
- "-Wl,-u,__rust_rwlock_wrlock",
+ "-u","__rust_abort",
+ "-u","__rust_c_alloc",
+ "-u","__rust_c_dealloc",
+ "-u","__rust_print_err",
+ "-u","__rust_rwlock_rdlock",
+ "-u","__rust_rwlock_unlock",
+ "-u","__rust_rwlock_wrlock"
];
const EXPORT_SYMBOLS: &[&str] = &[
@@ -50,18 +46,20 @@
dynamic_linking: false,
executables: true,
linker_is_gnu: true,
+ linker: Some("rust-lld".to_owned()),
max_atomic_width: Some(64),
panic_strategy: PanicStrategy::Unwind,
cpu: "x86-64".into(),
features: "+rdrnd,+rdseed".into(),
position_independent_executables: true,
pre_link_args: iter::once((
- LinkerFlavor::Gcc,
+ LinkerFlavor::Lld(LldFlavor::Ld),
PRE_LINK_ARGS.iter().cloned().map(String::from).collect(),
))
.collect(),
post_link_objects: vec!["libunwind.a".into()],
override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(String::from).collect()),
+ relax_elf_relocations: true,
..Default::default()
};
Ok(Target {
@@ -74,7 +72,7 @@
target_vendor: "fortanix".into(),
data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".into(),
arch: "x86_64".into(),
- linker_flavor: LinkerFlavor::Gcc,
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
options: opts,
})
}
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 901a219..253fc55 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1284,6 +1284,10 @@
augment_error(&mut err);
}
+ if let Some(expr) = expression {
+ fcx.emit_coerce_suggestions(&mut err, expr, found, expected);
+ }
+
// Error possibly reported in `check_assign` so avoid emitting error again.
err.emit_unless(expression.filter(|e| fcx.is_assign_to_bool(e, expected))
.is_some());
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 4331d44..16a55d2 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -15,6 +15,22 @@
use super::method::probe;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+
+ pub fn emit_coerce_suggestions(
+ &self,
+ err: &mut DiagnosticBuilder<'_>,
+ expr: &hir::Expr,
+ expr_ty: Ty<'tcx>,
+ expected: Ty<'tcx>
+ ) {
+ self.annotate_expected_due_to_let_ty(err, expr);
+ self.suggest_compatible_variants(err, expr, expected, expr_ty);
+ self.suggest_ref_or_into(err, expr, expected, expr_ty);
+ self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
+ self.suggest_missing_await(err, expr, expected, expr_ty);
+ }
+
+
// Requires that the two types unify, and prints an error message if
// they don't.
pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
@@ -65,13 +81,13 @@
}
}
- pub fn demand_eqtype_pat(
+ pub fn demand_eqtype_pat_diag(
&self,
cause_span: Span,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
match_expr_span: Option<Span>,
- ) {
+ ) -> Option<DiagnosticBuilder<'tcx>> {
let cause = if let Some(span) = match_expr_span {
self.cause(
cause_span,
@@ -80,9 +96,19 @@
} else {
self.misc(cause_span)
};
- self.demand_eqtype_with_origin(&cause, expected, actual).map(|mut err| err.emit());
+ self.demand_eqtype_with_origin(&cause, expected, actual)
}
+ pub fn demand_eqtype_pat(
+ &self,
+ cause_span: Span,
+ expected: Ty<'tcx>,
+ actual: Ty<'tcx>,
+ match_expr_span: Option<Span>,
+ ) {
+ self.demand_eqtype_pat_diag(cause_span, expected, actual, match_expr_span)
+ .map(|mut err| err.emit());
+ }
pub fn demand_coerce(&self,
expr: &hir::Expr,
@@ -127,11 +153,7 @@
return (expected, None)
}
- self.annotate_expected_due_to_let_ty(&mut err, expr);
- self.suggest_compatible_variants(&mut err, expr, expected, expr_ty);
- self.suggest_ref_or_into(&mut err, expr, expected, expr_ty);
- self.suggest_boxing_when_appropriate(&mut err, expr, expected, expr_ty);
- self.suggest_missing_await(&mut err, expr, expected, expr_ty);
+ self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected);
(expected, Some(err))
}
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 4766360..5bfc60c 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -582,11 +582,21 @@
// If this is a break with a value, we need to type-check
// the expression. Get an expected type from the loop context.
let opt_coerce_to = {
+ // We should release `enclosing_breakables` before the `check_expr_with_hint`
+ // below, so can't move this block of code to the enclosing scope and share
+ // `ctxt` with the second `encloding_breakables` borrow below.
let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
- enclosing_breakables.find_breakable(target_id)
- .coerce
- .as_ref()
- .map(|coerce| coerce.expected_ty())
+ match enclosing_breakables.opt_find_breakable(target_id) {
+ Some(ctxt) =>
+ ctxt.coerce.as_ref().map(|coerce| coerce.expected_ty()),
+ None => { // Avoid ICE when `break` is inside a closure (#65383).
+ self.tcx.sess.delay_span_bug(
+ expr.span,
+ "break was outside loop, but no error was emitted",
+ );
+ return tcx.types.err;
+ }
+ }
};
// If the loop context is not a `loop { }`, then break with
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 9f034e65..b967c6e 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -336,6 +336,7 @@
(1, vec![param(0), param(0)], param(0)),
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" =>
(1, vec![param(0), param(0)], param(0)),
+ "float_to_int_approx_unchecked" => (2, vec![ param(0) ], param(1)),
"assume" => (0, vec![tcx.types.bool], tcx.mk_unit()),
"likely" => (0, vec![tcx.types.bool], tcx.types.bool),
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 9717190..9923081 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -1105,11 +1105,7 @@
r.map(|mut pick| {
pick.autoderefs = step.autoderefs;
pick.autoref = Some(mutbl);
- pick.unsize = if step.unsize {
- Some(self_ty)
- } else {
- None
- };
+ pick.unsize = step.unsize.then_some(self_ty);
pick
})
})
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index c7a0190..a956aba 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4584,8 +4584,6 @@
pointing_at_return_type = self.suggest_missing_return_type(
err, &fn_decl, expected, found, can_suggest);
}
- self.suggest_ref_or_into(err, expr, expected, found);
- self.suggest_boxing_when_appropriate(err, expr, expected, found);
pointing_at_return_type
}
@@ -4957,7 +4955,9 @@
ty: expected,
}));
let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate);
+ debug!("suggest_missing_await: trying obligation {:?}", obligation);
if self.infcx.predicate_may_hold(&obligation) {
+ debug!("suggest_missing_await: obligation held: {:?}", obligation);
if let Ok(code) = self.sess().source_map().span_to_snippet(sp) {
err.span_suggestion(
sp,
@@ -4965,7 +4965,11 @@
format!("{}.await", code),
Applicability::MaybeIncorrect,
);
+ } else {
+ debug!("suggest_missing_await: no snippet for {:?}", sp);
}
+ } else {
+ debug!("suggest_missing_await: obligation did not hold: {:?}", obligation)
}
}
}
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 9dd3bc6..71d1cd8 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -703,7 +703,10 @@
let pat_ty = pat_ty.fn_sig(tcx).output();
let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
- self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span);
+ // Type-check the tuple struct pattern against the expected type.
+ let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, match_arm_pat_span);
+ let had_err = diag.is_some();
+ diag.map(|mut err| err.emit());
// Type-check subpatterns.
if subpats.len() == variant.fields.len()
@@ -721,7 +724,7 @@
}
} else {
// Pattern has wrong number of fields.
- self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected);
+ self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected, had_err);
on_error();
return tcx.types.err;
}
@@ -734,8 +737,9 @@
res: Res,
qpath: &hir::QPath,
subpats: &'tcx [P<Pat>],
- fields: &[ty::FieldDef],
- expected: Ty<'tcx>
+ fields: &'tcx [ty::FieldDef],
+ expected: Ty<'tcx>,
+ had_err: bool,
) {
let subpats_ending = pluralize!(subpats.len());
let fields_ending = pluralize!(fields.len());
@@ -763,9 +767,12 @@
// More generally, the expected type wants a tuple variant with one field of an
// N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern
// with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`.
- let missing_parenthesis = match expected.kind {
- ty::Adt(_, substs) if fields.len() == 1 => {
- let field_ty = fields[0].ty(self.tcx, substs);
+ let missing_parenthesis = match (&expected.kind, fields, had_err) {
+ // #67037: only do this if we could sucessfully type-check the expected type against
+ // the tuple struct pattern. Otherwise the substs could get out of range on e.g.,
+ // `let P() = U;` where `P != U` with `struct P<T>(T);`.
+ (ty::Adt(_, substs), [field], false) => {
+ let field_ty = self.field_ty(pat_span, field, substs);
match field_ty.kind {
ty::Tuple(_) => field_ty.tuple_fields().count() == subpats.len(),
_ => false,
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 3002459..c5a6c07 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -114,11 +114,7 @@
};
let infer_kind = if let UpvarSubsts::Closure(closure_substs) = substs {
- if self.closure_kind(closure_def_id, closure_substs).is_none() {
- Some(closure_substs)
- } else {
- None
- }
+ self.closure_kind(closure_def_id, closure_substs).is_none().then_some(closure_substs)
} else {
None
};
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index c606fea..6a6294b 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -59,6 +59,7 @@
#![allow(non_camel_case_types)]
+#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(crate_visibility_modifier)]
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 078948c..fb2cce3 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -209,6 +209,9 @@
impl ops::BitAndAssign for Cfg {
fn bitand_assign(&mut self, other: Cfg) {
+ if *self == other {
+ return;
+ }
match (self, other) {
(&mut Cfg::False, _) | (_, Cfg::True) => {},
(s, Cfg::False) => *s = Cfg::False,
@@ -238,6 +241,9 @@
impl ops::BitOrAssign for Cfg {
fn bitor_assign(&mut self, other: Cfg) {
+ if *self == other {
+ return;
+ }
match (self, other) {
(&mut Cfg::True, _) | (_, Cfg::False) => {},
(s, Cfg::True) => *s = Cfg::True,
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 4b5fc7c..7ee1054 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -482,7 +482,7 @@
match cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())) {
LoadedMacro::MacroDef(def, _) => {
let matchers: hir::HirVec<Span> = if let ast::ItemKind::MacroDef(ref def) = def.kind {
- let tts: Vec<_> = def.stream().into_trees().collect();
+ let tts: Vec<_> = def.body.inner_tokens().into_trees().collect();
tts.chunks(4).map(|arm| arm[0].span()).collect()
} else {
unreachable!()
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index b5c1a77..e245764 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -644,10 +644,9 @@
themes.appendChild(but);
}});"#,
as_json(&themes));
- write(cx.dst.join(&format!("theme{}.js", cx.shared.resource_suffix)),
- theme_js.as_bytes()
- )?;
-
+ write_minify(&cx.shared.fs, cx.path("theme.js"),
+ &theme_js,
+ options.enable_minification)?;
write_minify(&cx.shared.fs, cx.path("main.js"),
static_files::MAIN_JS,
options.enable_minification)?;
@@ -715,19 +714,13 @@
path: &Path,
krate: &str,
key: &str,
- for_search_index: bool,
- ) -> io::Result<(Vec<String>, Vec<String>, Vec<String>)> {
+ ) -> io::Result<(Vec<String>, Vec<String>)> {
let mut ret = Vec::new();
let mut krates = Vec::new();
- let mut variables = Vec::new();
if path.exists() {
for line in BufReader::new(File::open(path)?).lines() {
let line = line?;
- if for_search_index && line.starts_with("var R") {
- variables.push(line.clone());
- continue;
- }
if !line.starts_with(key) {
continue;
}
@@ -741,7 +734,7 @@
.unwrap_or_else(|| String::new()));
}
}
- Ok((ret, krates, variables))
+ Ok((ret, krates))
}
fn show_item(item: &IndexItem, krate: &str) -> String {
@@ -756,7 +749,7 @@
let dst = cx.dst.join(&format!("aliases{}.js", cx.shared.resource_suffix));
{
- let (mut all_aliases, _, _) = try_err!(collect(&dst, &krate.name, "ALIASES", false), &dst);
+ let (mut all_aliases, _) = try_err!(collect(&dst, &krate.name, "ALIASES"), &dst);
let mut output = String::with_capacity(100);
for (alias, items) in &cx.cache.aliases {
if items.is_empty() {
@@ -853,9 +846,7 @@
}
let dst = cx.dst.join(&format!("source-files{}.js", cx.shared.resource_suffix));
- let (mut all_sources, _krates, _) = try_err!(collect(&dst, &krate.name, "sourcesIndex",
- false),
- &dst);
+ let (mut all_sources, _krates) = try_err!(collect(&dst, &krate.name, "sourcesIndex"), &dst);
all_sources.push(format!("sourcesIndex[\"{}\"] = {};",
&krate.name,
hierarchy.to_json_string()));
@@ -867,23 +858,18 @@
// Update the search index
let dst = cx.dst.join(&format!("search-index{}.js", cx.shared.resource_suffix));
- let (mut all_indexes, mut krates, variables) = try_err!(collect(&dst,
- &krate.name,
- "searchIndex",
- true), &dst);
+ let (mut all_indexes, mut krates) = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst);
all_indexes.push(search_index);
// Sort the indexes by crate so the file will be generated identically even
// with rustdoc running in parallel.
all_indexes.sort();
{
- let mut v = String::from("var N=null,E=\"\",T=\"t\",U=\"u\",searchIndex={};\n");
- v.push_str(&minify_replacer(
- &format!("{}\n{}", variables.join(""), all_indexes.join("\n")),
- options.enable_minification));
+ let mut v = String::from("var searchIndex={};\n");
+ v.push_str(&all_indexes.join("\n"));
// "addSearchOptions" has to be called first so the crate filtering can be set before the
// search might start (if it's set into the URL for example).
- v.push_str("addSearchOptions(searchIndex);initSearch(searchIndex);");
+ v.push_str("\naddSearchOptions(searchIndex);initSearch(searchIndex);");
cx.shared.fs.write(&dst, &v)?;
}
if options.enable_index_page {
@@ -981,9 +967,8 @@
remote_item_type,
remote_path[remote_path.len() - 1]));
- let (mut all_implementors, _, _) = try_err!(collect(&mydst, &krate.name, "implementors",
- false),
- &mydst);
+ let (mut all_implementors, _) = try_err!(collect(&mydst, &krate.name, "implementors"),
+ &mydst);
all_implementors.push(implementors);
// Sort the implementors by crate so the file will be generated
// identically even with rustdoc running in parallel.
@@ -1020,68 +1005,6 @@
}
}
-fn minify_replacer(
- contents: &str,
- enable_minification: bool,
-) -> String {
- use minifier::js::{simple_minify, Keyword, ReservedChar, Token, Tokens};
-
- if enable_minification {
- let tokens: Tokens<'_> = simple_minify(contents)
- .into_iter()
- .filter(|(f, next)| {
- // We keep backlines.
- minifier::js::clean_token_except(f, next, &|c: &Token<'_>| {
- c.get_char() != Some(ReservedChar::Backline)
- })
- })
- .map(|(f, _)| {
- minifier::js::replace_token_with(f, &|t: &Token<'_>| {
- match *t {
- Token::Keyword(Keyword::Null) => Some(Token::Other("N")),
- Token::String(s) => {
- let s = &s[1..s.len() -1]; // The quotes are included
- if s.is_empty() {
- Some(Token::Other("E"))
- } else if s == "t" {
- Some(Token::Other("T"))
- } else if s == "u" {
- Some(Token::Other("U"))
- } else {
- None
- }
- }
- _ => None,
- }
- })
- })
- .collect::<Vec<_>>()
- .into();
- let o = tokens.apply(|f| {
- // We add a backline after the newly created variables.
- minifier::js::aggregate_strings_into_array_with_separation_filter(
- f,
- "R",
- Token::Char(ReservedChar::Backline),
- // This closure prevents crates' names from being aggregated.
- //
- // The point here is to check if the string is preceded by '[' and
- // "searchIndex". If so, it means this is a crate name and that it
- // shouldn't be aggregated.
- |tokens, pos| {
- pos < 2 ||
- !tokens[pos - 1].eq_char(ReservedChar::OpenBracket) ||
- tokens[pos - 2].get_other() != Some("searchIndex")
- }
- )
- })
- .to_string();
- format!("{}\n", o)
- } else {
- format!("{}\n", contents)
- }
-}
-
#[derive(Debug, Eq, PartialEq, Hash)]
struct ItemEntry {
url: String,
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index cc0f470..49a9cb0 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -1221,7 +1221,7 @@
// then an exact path match
path.indexOf(keys[i]) > -1 ||
// next if there is a parent, check for exact parent match
- (parent !== undefined &&
+ (parent !== undefined && parent.name !== undefined &&
parent.name.toLowerCase().indexOf(keys[i]) > -1) ||
// lastly check to see if the name was a levenshtein match
levenshtein(name, keys[i]) <= MAX_LEV_DISTANCE)) {
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index c55911a..a22e162 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -54,7 +54,7 @@
hermit-abi = { version = "0.1", features = ['rustc-dep-of-std'] }
[target.wasm32-wasi.dependencies]
-wasi = { version = "0.7.0", features = ['rustc-dep-of-std', 'alloc'] }
+wasi = { version = "0.9.0", features = ['rustc-dep-of-std'], default-features = false }
[features]
default = ["std_detect_file_io", "std_detect_dlsym_getauxval"]
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index e5cf022..a109e38 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -2339,8 +2339,10 @@
let filename = &tmpdir.join("file_that_does_not_exist.txt");
let result = File::open(filename);
- #[cfg(unix)]
+ #[cfg(all(unix, not(target_os = "vxworks")))]
error!(result, "No such file or directory");
+ #[cfg(target_os = "vxworks")]
+ error!(result, "no such file or directory");
#[cfg(windows)]
error!(result, 2); // ERROR_FILE_NOT_FOUND
}
@@ -2352,8 +2354,10 @@
let result = fs::remove_file(filename);
- #[cfg(unix)]
+ #[cfg(all(unix, not(target_os = "vxworks")))]
error!(result, "No such file or directory");
+ #[cfg(target_os = "vxworks")]
+ error!(result, "no such file or directory");
#[cfg(windows)]
error!(result, 2); // ERROR_FILE_NOT_FOUND
}
@@ -2553,7 +2557,10 @@
check!(fs::set_permissions(filename, fs::Permissions::from_mode(0o1777)));
let metadata1 = check!(fs::metadata(filename));
+ #[cfg(all(unix, not(target_os = "vxworks")))]
assert_eq!(mask & metadata1.permissions().mode(), 0o1777);
+ #[cfg(target_os = "vxworks")]
+ assert_eq!(mask & metadata1.permissions().mode(), 0o0777);
}
#[test]
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 20c1c5c..a1a33ba 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -987,7 +987,6 @@
/// #![feature(io_slice_advance)]
///
/// use std::io::IoSliceMut;
- /// use std::mem;
/// use std::ops::Deref;
///
/// let mut buf1 = [1; 8];
@@ -1000,7 +999,7 @@
/// ][..];
///
/// // Mark 10 bytes as read.
- /// bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 10);
+ /// bufs = IoSliceMut::advance(bufs, 10);
/// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
/// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
/// ```
@@ -1090,20 +1089,19 @@
/// #![feature(io_slice_advance)]
///
/// use std::io::IoSlice;
- /// use std::mem;
/// use std::ops::Deref;
///
- /// let mut buf1 = [1; 8];
- /// let mut buf2 = [2; 16];
- /// let mut buf3 = [3; 8];
+ /// let buf1 = [1; 8];
+ /// let buf2 = [2; 16];
+ /// let buf3 = [3; 8];
/// let mut bufs = &mut [
- /// IoSlice::new(&mut buf1),
- /// IoSlice::new(&mut buf2),
- /// IoSlice::new(&mut buf3),
+ /// IoSlice::new(&buf1),
+ /// IoSlice::new(&buf2),
+ /// IoSlice::new(&buf3),
/// ][..];
///
/// // Mark 10 bytes as written.
- /// bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 10);
+ /// bufs = IoSlice::advance(bufs, 10);
/// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
/// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
#[unstable(feature = "io_slice_advance", issue = "62726")]
@@ -2415,7 +2413,6 @@
use crate::cmp;
use crate::io::prelude::*;
use crate::io::{self, IoSlice, IoSliceMut};
- use crate::mem;
use crate::ops::Deref;
#[test]
@@ -2731,26 +2728,26 @@
][..];
// Only in a single buffer..
- bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 1);
+ bufs = IoSliceMut::advance(bufs, 1);
assert_eq!(bufs[0].deref(), [1; 7].as_ref());
assert_eq!(bufs[1].deref(), [2; 16].as_ref());
assert_eq!(bufs[2].deref(), [3; 8].as_ref());
// Removing a buffer, leaving others as is.
- bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 7);
+ bufs = IoSliceMut::advance(bufs, 7);
assert_eq!(bufs[0].deref(), [2; 16].as_ref());
assert_eq!(bufs[1].deref(), [3; 8].as_ref());
// Removing a buffer and removing from the next buffer.
- bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 18);
+ bufs = IoSliceMut::advance(bufs, 18);
assert_eq!(bufs[0].deref(), [3; 6].as_ref());
}
#[test]
fn io_slice_mut_advance_empty_slice() {
- let mut empty_bufs = &mut [][..];
+ let empty_bufs = &mut [][..];
// Shouldn't panic.
- IoSliceMut::advance(&mut empty_bufs, 1);
+ IoSliceMut::advance(empty_bufs, 1);
}
#[test]
@@ -2759,48 +2756,48 @@
let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..];
// Going beyond the total length should be ok.
- bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 9);
+ bufs = IoSliceMut::advance(bufs, 9);
assert!(bufs.is_empty());
}
#[test]
fn io_slice_advance() {
- let mut buf1 = [1; 8];
- let mut buf2 = [2; 16];
- let mut buf3 = [3; 8];
+ let buf1 = [1; 8];
+ let buf2 = [2; 16];
+ let buf3 = [3; 8];
let mut bufs =
- &mut [IoSlice::new(&mut buf1), IoSlice::new(&mut buf2), IoSlice::new(&mut buf3)][..];
+ &mut [IoSlice::new(&buf1), IoSlice::new(&buf2), IoSlice::new(&buf3)][..];
// Only in a single buffer..
- bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 1);
+ bufs = IoSlice::advance(bufs, 1);
assert_eq!(bufs[0].deref(), [1; 7].as_ref());
assert_eq!(bufs[1].deref(), [2; 16].as_ref());
assert_eq!(bufs[2].deref(), [3; 8].as_ref());
// Removing a buffer, leaving others as is.
- bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 7);
+ bufs = IoSlice::advance(bufs, 7);
assert_eq!(bufs[0].deref(), [2; 16].as_ref());
assert_eq!(bufs[1].deref(), [3; 8].as_ref());
// Removing a buffer and removing from the next buffer.
- bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 18);
+ bufs = IoSlice::advance(bufs, 18);
assert_eq!(bufs[0].deref(), [3; 6].as_ref());
}
#[test]
fn io_slice_advance_empty_slice() {
- let mut empty_bufs = &mut [][..];
+ let empty_bufs = &mut [][..];
// Shouldn't panic.
- IoSlice::advance(&mut empty_bufs, 1);
+ IoSlice::advance(empty_bufs, 1);
}
#[test]
fn io_slice_advance_beyond_total_length() {
- let mut buf1 = [1; 8];
- let mut bufs = &mut [IoSlice::new(&mut buf1)][..];
+ let buf1 = [1; 8];
+ let mut bufs = &mut [IoSlice::new(&buf1)][..];
// Going beyond the total length should be ok.
- bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 9);
+ bufs = IoSlice::advance(bufs, 9);
assert!(bufs.is_empty());
}
}
diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs
index b0baf36..5b7bef9 100644
--- a/src/libstd/keyword_docs.rs
+++ b/src/libstd/keyword_docs.rs
@@ -812,9 +812,50 @@
//
/// Control flow based on pattern matching.
///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// `match` can be used to run code conditionally. Every pattern must
+/// be handled exhaustively either explicitly or by using wildcards like
+/// `_` in the `match`. Since `match` is an expression, values can also be
+/// returned.
///
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// ```rust
+/// let opt = Option::None::<usize>;
+/// let x = match opt {
+/// Some(int) => int,
+/// None => 10,
+/// };
+/// assert_eq!(x, 10);
+///
+/// let a_number = Option::Some(10);
+/// match a_number {
+/// Some(x) if x <= 5 => println!("0 to 5 num = {}", x),
+/// Some(x @ 6..=10) => println!("6 to 10 num = {}", x),
+/// None => panic!(),
+/// // all other numbers
+/// _ => panic!(),
+/// }
+/// ```
+///
+/// `match` can be used to gain access to the inner members of an enum
+/// and use them directly.
+///
+/// ```rust
+/// enum Outer {
+/// Double(Option<u8>, Option<String>),
+/// Single(Option<u8>),
+/// Empty
+/// }
+///
+/// let get_inner = Outer::Double(None, Some(String::new()));
+/// match get_inner {
+/// Outer::Double(None, Some(st)) => println!("{}", st),
+/// Outer::Single(opt) => println!("{:?}", opt),
+/// _ => panic!(),
+/// }
+/// ```
+///
+/// For more information on `match` and matching in general, see the [Reference].
+///
+/// [Reference]: ../reference/expressions/match-expr.html
mod match_keyword { }
#[doc(keyword = "mod")]
@@ -831,10 +872,35 @@
//
/// Capture a [closure]'s environment by value.
///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// `move` converts any variables captured by reference or mutable reference
+/// to owned by value variables. The three [`Fn` trait]'s mirror the ways to capture
+/// variables, when `move` is used, the closures is represented by the `FnOnce` trait.
///
-/// [closure]: ../book/second-edition/ch13-01-closures.html
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// ```rust
+/// let capture = "hello";
+/// let closure = move || {
+/// println!("rust says {}", capture);
+/// };
+/// ```
+///
+/// `move` is often used when [threads] are involved.
+///
+/// ```rust
+/// let x = 5;
+///
+/// std::thread::spawn(move || {
+/// println!("captured {} by value", x)
+/// }).join().unwrap();
+///
+/// // x is no longer available
+/// ```
+///
+/// For more information on the `move` keyword, see the [closure]'s section
+/// of the Rust book or the [threads] section
+///
+/// [`Fn` trait]: ../std/ops/trait.Fn.html
+/// [closure]: ../book/ch13-01-closures.html
+/// [threads]: ../book/ch16-01-threads.html#using-move-closures-with-threads
mod move_keyword { }
#[doc(keyword = "mut")]
diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs
index 8106d1c..686fa8c 100644
--- a/src/libstd/net/parser.rs
+++ b/src/libstd/net/parser.rs
@@ -44,19 +44,6 @@
self.read_atomically(move |p| cb(p).filter(|_| p.is_eof()))
}
- // Return result of first successful parser
- fn read_or<T>(
- &mut self,
- parsers: &mut [Box<dyn FnMut(&mut Parser<'_>) -> Option<T> + 'static>],
- ) -> Option<T> {
- for pf in parsers {
- if let Some(r) = self.read_atomically(|p: &mut Parser<'_>| pf(p)) {
- return Some(r);
- }
- }
- None
- }
-
// Apply 3 parsers sequentially
fn read_seq_3<A, B, C, PA, PB, PC>(&mut self, pa: PA, pb: PB, pc: PC) -> Option<(A, B, C)>
where
@@ -235,9 +222,8 @@
}
fn read_ip_addr(&mut self) -> Option<IpAddr> {
- let ipv4_addr = |p: &mut Parser<'_>| p.read_ipv4_addr().map(IpAddr::V4);
- let ipv6_addr = |p: &mut Parser<'_>| p.read_ipv6_addr().map(IpAddr::V6);
- self.read_or(&mut [Box::new(ipv4_addr), Box::new(ipv6_addr)])
+ self.read_ipv4_addr().map(IpAddr::V4)
+ .or_else(|| self.read_ipv6_addr().map(IpAddr::V6))
}
fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> {
@@ -268,9 +254,8 @@
}
fn read_socket_addr(&mut self) -> Option<SocketAddr> {
- let v4 = |p: &mut Parser<'_>| p.read_socket_addr_v4().map(SocketAddr::V4);
- let v6 = |p: &mut Parser<'_>| p.read_socket_addr_v6().map(SocketAddr::V6);
- self.read_or(&mut [Box::new(v4), Box::new(v6)])
+ self.read_socket_addr_v4().map(SocketAddr::V4)
+ .or_else(|| self.read_socket_addr_v6().map(SocketAddr::V6))
}
}
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 87c2318..e90da69 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -143,10 +143,8 @@
#[must_use = "if unused the Mutex will immediately unlock"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct MutexGuard<'a, T: ?Sized + 'a> {
- // funny underscores due to how Deref/DerefMut currently work (they
- // disregard field privacy).
- __lock: &'a Mutex<T>,
- __poison: poison::Guard,
+ lock: &'a Mutex<T>,
+ poison: poison::Guard,
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -417,8 +415,8 @@
unsafe fn new(lock: &'mutex Mutex<T>) -> LockResult<MutexGuard<'mutex, T>> {
poison::map_result(lock.poison.borrow(), |guard| {
MutexGuard {
- __lock: lock,
- __poison: guard,
+ lock: lock,
+ poison: guard,
}
})
}
@@ -429,14 +427,14 @@
type Target = T;
fn deref(&self) -> &T {
- unsafe { &*self.__lock.data.get() }
+ unsafe { &*self.lock.data.get() }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for MutexGuard<'_, T> {
fn deref_mut(&mut self) -> &mut T {
- unsafe { &mut *self.__lock.data.get() }
+ unsafe { &mut *self.lock.data.get() }
}
}
@@ -445,8 +443,8 @@
#[inline]
fn drop(&mut self) {
unsafe {
- self.__lock.poison.done(&self.__poison);
- self.__lock.inner.raw_unlock();
+ self.lock.poison.done(&self.poison);
+ self.lock.inner.raw_unlock();
}
}
}
@@ -466,11 +464,11 @@
}
pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
- &guard.__lock.inner
+ &guard.lock.inner
}
pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag {
- &guard.__lock.poison
+ &guard.lock.poison
}
#[cfg(all(test, not(target_os = "emscripten")))]
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index b1b56f3..c217291 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -87,7 +87,7 @@
#[must_use = "if unused the RwLock will immediately unlock"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
- __lock: &'a RwLock<T>,
+ lock: &'a RwLock<T>,
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -108,8 +108,8 @@
#[must_use = "if unused the RwLock will immediately unlock"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
- __lock: &'a RwLock<T>,
- __poison: poison::Guard,
+ lock: &'a RwLock<T>,
+ poison: poison::Guard,
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -465,7 +465,7 @@
-> LockResult<RwLockReadGuard<'rwlock, T>> {
poison::map_result(lock.poison.borrow(), |_| {
RwLockReadGuard {
- __lock: lock,
+ lock: lock,
}
})
}
@@ -476,8 +476,8 @@
-> LockResult<RwLockWriteGuard<'rwlock, T>> {
poison::map_result(lock.poison.borrow(), |guard| {
RwLockWriteGuard {
- __lock: lock,
- __poison: guard,
+ lock: lock,
+ poison: guard,
}
})
}
@@ -487,7 +487,7 @@
impl<T: fmt::Debug> fmt::Debug for RwLockReadGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RwLockReadGuard")
- .field("lock", &self.__lock)
+ .field("lock", &self.lock)
.finish()
}
}
@@ -503,7 +503,7 @@
impl<T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RwLockWriteGuard")
- .field("lock", &self.__lock)
+ .field("lock", &self.lock)
.finish()
}
}
@@ -520,7 +520,7 @@
type Target = T;
fn deref(&self) -> &T {
- unsafe { &*self.__lock.data.get() }
+ unsafe { &*self.lock.data.get() }
}
}
@@ -529,29 +529,29 @@
type Target = T;
fn deref(&self) -> &T {
- unsafe { &*self.__lock.data.get() }
+ unsafe { &*self.lock.data.get() }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
fn deref_mut(&mut self) -> &mut T {
- unsafe { &mut *self.__lock.data.get() }
+ unsafe { &mut *self.lock.data.get() }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
fn drop(&mut self) {
- unsafe { self.__lock.inner.read_unlock(); }
+ unsafe { self.lock.inner.read_unlock(); }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Drop for RwLockWriteGuard<'_, T> {
fn drop(&mut self) {
- self.__lock.poison.done(&self.__poison);
- unsafe { self.__lock.inner.write_unlock(); }
+ self.lock.poison.done(&self.poison);
+ unsafe { self.lock.inner.write_unlock(); }
}
}
diff --git a/src/libstd/sys/unix/ext/mod.rs b/src/libstd/sys/unix/ext/mod.rs
index ccbac1a..78a3fd0 100644
--- a/src/libstd/sys/unix/ext/mod.rs
+++ b/src/libstd/sys/unix/ext/mod.rs
@@ -15,11 +15,13 @@
//! use std::fs::File;
//! use std::os::unix::prelude::*;
//!
-//! fn main() {
-//! let f = File::create("foo.txt").unwrap();
+//! fn main() -> std::io::Result<()> {
+//! let f = File::create("foo.txt")?;
//! let fd = f.as_raw_fd();
//!
//! // use fd with native unix bindings
+//!
+//! Ok(())
//! }
//! ```
diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs
index 42edd5d..5177cce 100644
--- a/src/libstd/sys/unix/ext/net.rs
+++ b/src/libstd/sys/unix/ext/net.rs
@@ -142,9 +142,12 @@
/// ```no_run
/// use std::os::unix::net::UnixListener;
///
- /// let socket = UnixListener::bind("/tmp/sock").unwrap();
- /// let addr = socket.local_addr().expect("Couldn't get local address");
- /// assert_eq!(addr.is_unnamed(), false);
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixListener::bind("/tmp/sock")?;
+ /// let addr = socket.local_addr().expect("Couldn't get local address");
+ /// assert_eq!(addr.is_unnamed(), false);
+ /// Ok(())
+ /// }
/// ```
///
/// An unnamed address:
@@ -152,9 +155,12 @@
/// ```
/// use std::os::unix::net::UnixDatagram;
///
- /// let socket = UnixDatagram::unbound().unwrap();
- /// let addr = socket.local_addr().expect("Couldn't get local address");
- /// assert_eq!(addr.is_unnamed(), true);
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixDatagram::unbound()?;
+ /// let addr = socket.local_addr().expect("Couldn't get local address");
+ /// assert_eq!(addr.is_unnamed(), true);
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn is_unnamed(&self) -> bool {
@@ -175,9 +181,12 @@
/// use std::os::unix::net::UnixListener;
/// use std::path::Path;
///
- /// let socket = UnixListener::bind("/tmp/sock").unwrap();
- /// let addr = socket.local_addr().expect("Couldn't get local address");
- /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock")));
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixListener::bind("/tmp/sock")?;
+ /// let addr = socket.local_addr().expect("Couldn't get local address");
+ /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock")));
+ /// Ok(())
+ /// }
/// ```
///
/// Without a pathname:
@@ -185,9 +194,12 @@
/// ```
/// use std::os::unix::net::UnixDatagram;
///
- /// let socket = UnixDatagram::unbound().unwrap();
- /// let addr = socket.local_addr().expect("Couldn't get local address");
- /// assert_eq!(addr.as_pathname(), None);
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixDatagram::unbound()?;
+ /// let addr = socket.local_addr().expect("Couldn't get local address");
+ /// assert_eq!(addr.as_pathname(), None);
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn as_pathname(&self) -> Option<&Path> {
@@ -247,11 +259,14 @@
/// use std::os::unix::net::UnixStream;
/// use std::io::prelude::*;
///
-/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap();
-/// stream.write_all(b"hello world").unwrap();
-/// let mut response = String::new();
-/// stream.read_to_string(&mut response).unwrap();
-/// println!("{}", response);
+/// fn main() -> std::io::Result<()> {
+/// let mut stream = UnixStream::connect("/path/to/my/socket")?;
+/// stream.write_all(b"hello world")?;
+/// let mut response = String::new();
+/// stream.read_to_string(&mut response)?;
+/// println!("{}", response);
+/// Ok(())
+/// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub struct UnixStream(Socket);
@@ -336,8 +351,11 @@
/// ```no_run
/// use std::os::unix::net::UnixStream;
///
- /// let socket = UnixStream::connect("/tmp/sock").unwrap();
- /// let sock_copy = socket.try_clone().expect("Couldn't clone socket");
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixStream::connect("/tmp/sock")?;
+ /// let sock_copy = socket.try_clone().expect("Couldn't clone socket");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn try_clone(&self) -> io::Result<UnixStream> {
@@ -351,8 +369,11 @@
/// ```no_run
/// use std::os::unix::net::UnixStream;
///
- /// let socket = UnixStream::connect("/tmp/sock").unwrap();
- /// let addr = socket.local_addr().expect("Couldn't get local address");
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixStream::connect("/tmp/sock")?;
+ /// let addr = socket.local_addr().expect("Couldn't get local address");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn local_addr(&self) -> io::Result<SocketAddr> {
@@ -366,8 +387,11 @@
/// ```no_run
/// use std::os::unix::net::UnixStream;
///
- /// let socket = UnixStream::connect("/tmp/sock").unwrap();
- /// let addr = socket.peer_addr().expect("Couldn't get peer address");
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixStream::connect("/tmp/sock")?;
+ /// let addr = socket.peer_addr().expect("Couldn't get peer address");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
@@ -391,8 +415,11 @@
/// use std::os::unix::net::UnixStream;
/// use std::time::Duration;
///
- /// let socket = UnixStream::connect("/tmp/sock").unwrap();
- /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixStream::connect("/tmp/sock")?;
+ /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
+ /// Ok(())
+ /// }
/// ```
///
/// An [`Err`] is returned if the zero [`Duration`] is passed to this
@@ -403,10 +430,13 @@
/// use std::os::unix::net::UnixStream;
/// use std::time::Duration;
///
- /// let socket = UnixStream::connect("/tmp/sock").unwrap();
- /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
- /// let err = result.unwrap_err();
- /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixStream::connect("/tmp/sock")?;
+ /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+ /// let err = result.unwrap_err();
+ /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
@@ -430,8 +460,12 @@
/// use std::os::unix::net::UnixStream;
/// use std::time::Duration;
///
- /// let socket = UnixStream::connect("/tmp/sock").unwrap();
- /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixStream::connect("/tmp/sock")?;
+ /// socket.set_write_timeout(Some(Duration::new(1, 0)))
+ /// .expect("Couldn't set write timeout");
+ /// Ok(())
+ /// }
/// ```
///
/// An [`Err`] is returned if the zero [`Duration`] is passed to this
@@ -442,10 +476,13 @@
/// use std::net::UdpSocket;
/// use std::time::Duration;
///
- /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
- /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
- /// let err = result.unwrap_err();
- /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UdpSocket::bind("127.0.0.1:34254")?;
+ /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+ /// let err = result.unwrap_err();
+ /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
@@ -460,9 +497,12 @@
/// use std::os::unix::net::UnixStream;
/// use std::time::Duration;
///
- /// let socket = UnixStream::connect("/tmp/sock").unwrap();
- /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
- /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0)));
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixStream::connect("/tmp/sock")?;
+ /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
+ /// assert_eq!(socket.read_timeout()?, Some(Duration::new(1, 0)));
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
@@ -477,9 +517,13 @@
/// use std::os::unix::net::UnixStream;
/// use std::time::Duration;
///
- /// let socket = UnixStream::connect("/tmp/sock").unwrap();
- /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
- /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0)));
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixStream::connect("/tmp/sock")?;
+ /// socket.set_write_timeout(Some(Duration::new(1, 0)))
+ /// .expect("Couldn't set write timeout");
+ /// assert_eq!(socket.write_timeout()?, Some(Duration::new(1, 0)));
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
@@ -493,8 +537,11 @@
/// ```no_run
/// use std::os::unix::net::UnixStream;
///
- /// let socket = UnixStream::connect("/tmp/sock").unwrap();
- /// socket.set_nonblocking(true).expect("Couldn't set nonblocking");
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixStream::connect("/tmp/sock")?;
+ /// socket.set_nonblocking(true).expect("Couldn't set nonblocking");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
@@ -508,9 +555,12 @@
/// ```no_run
/// use std::os::unix::net::UnixStream;
///
- /// let socket = UnixStream::connect("/tmp/sock").unwrap();
- /// if let Ok(Some(err)) = socket.take_error() {
- /// println!("Got error: {:?}", err);
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixStream::connect("/tmp/sock")?;
+ /// if let Ok(Some(err)) = socket.take_error() {
+ /// println!("Got error: {:?}", err);
+ /// }
+ /// Ok(())
/// }
/// ```
///
@@ -535,8 +585,11 @@
/// use std::os::unix::net::UnixStream;
/// use std::net::Shutdown;
///
- /// let socket = UnixStream::connect("/tmp/sock").unwrap();
- /// socket.shutdown(Shutdown::Both).expect("shutdown function failed");
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixStream::connect("/tmp/sock")?;
+ /// socket.shutdown(Shutdown::Both).expect("shutdown function failed");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
@@ -697,20 +750,23 @@
/// // ...
/// }
///
-/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+/// fn main() -> std::io::Result<()> {
+/// let listener = UnixListener::bind("/path/to/the/socket")?;
///
-/// // accept connections and process them, spawning a new thread for each one
-/// for stream in listener.incoming() {
-/// match stream {
-/// Ok(stream) => {
-/// /* connection succeeded */
-/// thread::spawn(|| handle_client(stream));
-/// }
-/// Err(err) => {
-/// /* connection failed */
-/// break;
+/// // accept connections and process them, spawning a new thread for each one
+/// for stream in listener.incoming() {
+/// match stream {
+/// Ok(stream) => {
+/// /* connection succeeded */
+/// thread::spawn(|| handle_client(stream));
+/// }
+/// Err(err) => {
+/// /* connection failed */
+/// break;
+/// }
/// }
/// }
+/// Ok(())
/// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
@@ -773,11 +829,14 @@
/// ```no_run
/// use std::os::unix::net::UnixListener;
///
- /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+ /// fn main() -> std::io::Result<()> {
+ /// let listener = UnixListener::bind("/path/to/the/socket")?;
///
- /// match listener.accept() {
- /// Ok((socket, addr)) => println!("Got a client: {:?}", addr),
- /// Err(e) => println!("accept function failed: {:?}", e),
+ /// match listener.accept() {
+ /// Ok((socket, addr)) => println!("Got a client: {:?}", addr),
+ /// Err(e) => println!("accept function failed: {:?}", e),
+ /// }
+ /// Ok(())
/// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
@@ -800,9 +859,11 @@
/// ```no_run
/// use std::os::unix::net::UnixListener;
///
- /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
- ///
- /// let listener_copy = listener.try_clone().expect("try_clone failed");
+ /// fn main() -> std::io::Result<()> {
+ /// let listener = UnixListener::bind("/path/to/the/socket")?;
+ /// let listener_copy = listener.try_clone().expect("try_clone failed");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn try_clone(&self) -> io::Result<UnixListener> {
@@ -816,9 +877,11 @@
/// ```no_run
/// use std::os::unix::net::UnixListener;
///
- /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
- ///
- /// let addr = listener.local_addr().expect("Couldn't get local address");
+ /// fn main() -> std::io::Result<()> {
+ /// let listener = UnixListener::bind("/path/to/the/socket")?;
+ /// let addr = listener.local_addr().expect("Couldn't get local address");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn local_addr(&self) -> io::Result<SocketAddr> {
@@ -832,9 +895,11 @@
/// ```no_run
/// use std::os::unix::net::UnixListener;
///
- /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
- ///
- /// listener.set_nonblocking(true).expect("Couldn't set non blocking");
+ /// fn main() -> std::io::Result<()> {
+ /// let listener = UnixListener::bind("/path/to/the/socket")?;
+ /// listener.set_nonblocking(true).expect("Couldn't set non blocking");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
@@ -848,10 +913,13 @@
/// ```no_run
/// use std::os::unix::net::UnixListener;
///
- /// let listener = UnixListener::bind("/tmp/sock").unwrap();
+ /// fn main() -> std::io::Result<()> {
+ /// let listener = UnixListener::bind("/tmp/sock")?;
///
- /// if let Ok(Some(err)) = listener.take_error() {
- /// println!("Got error: {:?}", err);
+ /// if let Ok(Some(err)) = listener.take_error() {
+ /// println!("Got error: {:?}", err);
+ /// }
+ /// Ok(())
/// }
/// ```
///
@@ -880,17 +948,20 @@
/// // ...
/// }
///
- /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+ /// fn main() -> std::io::Result<()> {
+ /// let listener = UnixListener::bind("/path/to/the/socket")?;
///
- /// for stream in listener.incoming() {
- /// match stream {
- /// Ok(stream) => {
- /// thread::spawn(|| handle_client(stream));
- /// }
- /// Err(err) => {
- /// break;
+ /// for stream in listener.incoming() {
+ /// match stream {
+ /// Ok(stream) => {
+ /// thread::spawn(|| handle_client(stream));
+ /// }
+ /// Err(err) => {
+ /// break;
+ /// }
/// }
/// }
+ /// Ok(())
/// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
@@ -947,17 +1018,20 @@
/// // ...
/// }
///
-/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+/// fn main() -> std::io::Result<()> {
+/// let listener = UnixListener::bind("/path/to/the/socket")?;
///
-/// for stream in listener.incoming() {
-/// match stream {
-/// Ok(stream) => {
-/// thread::spawn(|| handle_client(stream));
-/// }
-/// Err(err) => {
-/// break;
+/// for stream in listener.incoming() {
+/// match stream {
+/// Ok(stream) => {
+/// thread::spawn(|| handle_client(stream));
+/// }
+/// Err(err) => {
+/// break;
+/// }
/// }
/// }
+/// Ok(())
/// }
/// ```
#[derive(Debug)]
@@ -986,11 +1060,14 @@
/// ```no_run
/// use std::os::unix::net::UnixDatagram;
///
-/// let socket = UnixDatagram::bind("/path/to/my/socket").unwrap();
-/// socket.send_to(b"hello world", "/path/to/other/socket").unwrap();
-/// let mut buf = [0; 100];
-/// let (count, address) = socket.recv_from(&mut buf).unwrap();
-/// println!("socket {:?} sent {:?}", address, &buf[..count]);
+/// fn main() -> std::io::Result<()> {
+/// let socket = UnixDatagram::bind("/path/to/my/socket")?;
+/// socket.send_to(b"hello world", "/path/to/other/socket")?;
+/// let mut buf = [0; 100];
+/// let (count, address) = socket.recv_from(&mut buf)?;
+/// println!("socket {:?} sent {:?}", address, &buf[..count]);
+/// Ok(())
+/// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub struct UnixDatagram(Socket);
@@ -1099,14 +1176,17 @@
/// ```no_run
/// use std::os::unix::net::UnixDatagram;
///
- /// let sock = UnixDatagram::unbound().unwrap();
- /// match sock.connect("/path/to/the/socket") {
- /// Ok(sock) => sock,
- /// Err(e) => {
- /// println!("Couldn't connect: {:?}", e);
- /// return
- /// }
- /// };
+ /// fn main() -> std::io::Result<()> {
+ /// let sock = UnixDatagram::unbound()?;
+ /// match sock.connect("/path/to/the/socket") {
+ /// Ok(sock) => sock,
+ /// Err(e) => {
+ /// println!("Couldn't connect: {:?}", e);
+ /// return Err(e)
+ /// }
+ /// };
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
@@ -1133,9 +1213,11 @@
/// ```no_run
/// use std::os::unix::net::UnixDatagram;
///
- /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap();
- ///
- /// let sock_copy = sock.try_clone().expect("try_clone failed");
+ /// fn main() -> std::io::Result<()> {
+ /// let sock = UnixDatagram::bind("/path/to/the/socket")?;
+ /// let sock_copy = sock.try_clone().expect("try_clone failed");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn try_clone(&self) -> io::Result<UnixDatagram> {
@@ -1149,9 +1231,11 @@
/// ```no_run
/// use std::os::unix::net::UnixDatagram;
///
- /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap();
- ///
- /// let addr = sock.local_addr().expect("Couldn't get local address");
+ /// fn main() -> std::io::Result<()> {
+ /// let sock = UnixDatagram::bind("/path/to/the/socket")?;
+ /// let addr = sock.local_addr().expect("Couldn't get local address");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn local_addr(&self) -> io::Result<SocketAddr> {
@@ -1169,10 +1253,13 @@
/// ```no_run
/// use std::os::unix::net::UnixDatagram;
///
- /// let sock = UnixDatagram::unbound().unwrap();
- /// sock.connect("/path/to/the/socket").unwrap();
+ /// fn main() -> std::io::Result<()> {
+ /// let sock = UnixDatagram::unbound()?;
+ /// sock.connect("/path/to/the/socket")?;
///
- /// let addr = sock.peer_addr().expect("Couldn't get peer address");
+ /// let addr = sock.peer_addr().expect("Couldn't get peer address");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
@@ -1189,11 +1276,12 @@
/// ```no_run
/// use std::os::unix::net::UnixDatagram;
///
- /// let sock = UnixDatagram::unbound().unwrap();
- /// let mut buf = vec![0; 10];
- /// match sock.recv_from(buf.as_mut_slice()) {
- /// Ok((size, sender)) => println!("received {} bytes from {:?}", size, sender),
- /// Err(e) => println!("recv_from function failed: {:?}", e),
+ /// fn main() -> std::io::Result<()> {
+ /// let sock = UnixDatagram::unbound()?;
+ /// let mut buf = vec![0; 10];
+ /// let (size, sender) = sock.recv_from(buf.as_mut_slice())?;
+ /// println!("received {} bytes from {:?}", size, sender);
+ /// Ok(())
/// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
@@ -1229,9 +1317,12 @@
/// ```no_run
/// use std::os::unix::net::UnixDatagram;
///
- /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap();
- /// let mut buf = vec![0; 10];
- /// sock.recv(buf.as_mut_slice()).expect("recv function failed");
+ /// fn main() -> std::io::Result<()> {
+ /// let sock = UnixDatagram::bind("/path/to/the/socket")?;
+ /// let mut buf = vec![0; 10];
+ /// sock.recv(buf.as_mut_slice()).expect("recv function failed");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
@@ -1247,8 +1338,11 @@
/// ```no_run
/// use std::os::unix::net::UnixDatagram;
///
- /// let sock = UnixDatagram::unbound().unwrap();
- /// sock.send_to(b"omelette au fromage", "/some/sock").expect("send_to function failed");
+ /// fn main() -> std::io::Result<()> {
+ /// let sock = UnixDatagram::unbound()?;
+ /// sock.send_to(b"omelette au fromage", "/some/sock").expect("send_to function failed");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> {
@@ -1280,9 +1374,12 @@
/// ```no_run
/// use std::os::unix::net::UnixDatagram;
///
- /// let sock = UnixDatagram::unbound().unwrap();
- /// sock.connect("/some/sock").expect("Couldn't connect");
- /// sock.send(b"omelette au fromage").expect("send_to function failed");
+ /// fn main() -> std::io::Result<()> {
+ /// let sock = UnixDatagram::unbound()?;
+ /// sock.connect("/some/sock").expect("Couldn't connect");
+ /// sock.send(b"omelette au fromage").expect("send_to function failed");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
@@ -1307,8 +1404,12 @@
/// use std::os::unix::net::UnixDatagram;
/// use std::time::Duration;
///
- /// let sock = UnixDatagram::unbound().unwrap();
- /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed");
+ /// fn main() -> std::io::Result<()> {
+ /// let sock = UnixDatagram::unbound()?;
+ /// sock.set_read_timeout(Some(Duration::new(1, 0)))
+ /// .expect("set_read_timeout function failed");
+ /// Ok(())
+ /// }
/// ```
///
/// An [`Err`] is returned if the zero [`Duration`] is passed to this
@@ -1319,10 +1420,13 @@
/// use std::os::unix::net::UnixDatagram;
/// use std::time::Duration;
///
- /// let socket = UnixDatagram::unbound().unwrap();
- /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
- /// let err = result.unwrap_err();
- /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixDatagram::unbound()?;
+ /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+ /// let err = result.unwrap_err();
+ /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
@@ -1346,9 +1450,12 @@
/// use std::os::unix::net::UnixDatagram;
/// use std::time::Duration;
///
- /// let sock = UnixDatagram::unbound().unwrap();
- /// sock.set_write_timeout(Some(Duration::new(1, 0)))
- /// .expect("set_write_timeout function failed");
+ /// fn main() -> std::io::Result<()> {
+ /// let sock = UnixDatagram::unbound()?;
+ /// sock.set_write_timeout(Some(Duration::new(1, 0)))
+ /// .expect("set_write_timeout function failed");
+ /// Ok(())
+ /// }
/// ```
///
/// An [`Err`] is returned if the zero [`Duration`] is passed to this
@@ -1359,10 +1466,13 @@
/// use std::os::unix::net::UnixDatagram;
/// use std::time::Duration;
///
- /// let socket = UnixDatagram::unbound().unwrap();
- /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
- /// let err = result.unwrap_err();
- /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+ /// fn main() -> std::io::Result<()> {
+ /// let socket = UnixDatagram::unbound()?;
+ /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+ /// let err = result.unwrap_err();
+ /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
@@ -1377,9 +1487,13 @@
/// use std::os::unix::net::UnixDatagram;
/// use std::time::Duration;
///
- /// let sock = UnixDatagram::unbound().unwrap();
- /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed");
- /// assert_eq!(sock.read_timeout().unwrap(), Some(Duration::new(1, 0)));
+ /// fn main() -> std::io::Result<()> {
+ /// let sock = UnixDatagram::unbound()?;
+ /// sock.set_read_timeout(Some(Duration::new(1, 0)))
+ /// .expect("set_read_timeout function failed");
+ /// assert_eq!(sock.read_timeout()?, Some(Duration::new(1, 0)));
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
@@ -1394,10 +1508,13 @@
/// use std::os::unix::net::UnixDatagram;
/// use std::time::Duration;
///
- /// let sock = UnixDatagram::unbound().unwrap();
- /// sock.set_write_timeout(Some(Duration::new(1, 0)))
- /// .expect("set_write_timeout function failed");
- /// assert_eq!(sock.write_timeout().unwrap(), Some(Duration::new(1, 0)));
+ /// fn main() -> std::io::Result<()> {
+ /// let sock = UnixDatagram::unbound()?;
+ /// sock.set_write_timeout(Some(Duration::new(1, 0)))
+ /// .expect("set_write_timeout function failed");
+ /// assert_eq!(sock.write_timeout()?, Some(Duration::new(1, 0)));
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
@@ -1411,8 +1528,11 @@
/// ```
/// use std::os::unix::net::UnixDatagram;
///
- /// let sock = UnixDatagram::unbound().unwrap();
- /// sock.set_nonblocking(true).expect("set_nonblocking function failed");
+ /// fn main() -> std::io::Result<()> {
+ /// let sock = UnixDatagram::unbound()?;
+ /// sock.set_nonblocking(true).expect("set_nonblocking function failed");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
@@ -1426,9 +1546,12 @@
/// ```no_run
/// use std::os::unix::net::UnixDatagram;
///
- /// let sock = UnixDatagram::unbound().unwrap();
- /// if let Ok(Some(err)) = sock.take_error() {
- /// println!("Got error: {:?}", err);
+ /// fn main() -> std::io::Result<()> {
+ /// let sock = UnixDatagram::unbound()?;
+ /// if let Ok(Some(err)) = sock.take_error() {
+ /// println!("Got error: {:?}", err);
+ /// }
+ /// Ok(())
/// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
@@ -1448,8 +1571,11 @@
/// use std::os::unix::net::UnixDatagram;
/// use std::net::Shutdown;
///
- /// let sock = UnixDatagram::unbound().unwrap();
- /// sock.shutdown(Shutdown::Both).expect("shutdown function failed");
+ /// fn main() -> std::io::Result<()> {
+ /// let sock = UnixDatagram::unbound()?;
+ /// sock.shutdown(Shutdown::Both).expect("shutdown function failed");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
diff --git a/src/libstd/sys/vxworks/ext/mod.rs b/src/libstd/sys/vxworks/ext/mod.rs
index 251a198..8fa9bd9 100644
--- a/src/libstd/sys/vxworks/ext/mod.rs
+++ b/src/libstd/sys/vxworks/ext/mod.rs
@@ -18,4 +18,7 @@
#[doc(no_inline)]
#[stable(feature = "rust1", since = "1.0.0")]
pub use super::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
+ #[doc(no_inline)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub use super::process::ExitStatusExt;
}
diff --git a/src/libstd/sys/vxworks/os.rs b/src/libstd/sys/vxworks/os.rs
index baa6c42..71e1d16 100644
--- a/src/libstd/sys/vxworks/os.rs
+++ b/src/libstd/sys/vxworks/os.rs
@@ -11,14 +11,12 @@
use crate::ptr;
use crate::slice;
use crate::str;
-use crate::sys_common::mutex::Mutex;
+use crate::sys_common::mutex::{Mutex, MutexGuard};
use crate::sys::cvt;
/*use sys::fd; this one is probably important */
use crate::vec;
const TMPBUF_SZ: usize = 128;
-static ENV_LOCK: Mutex = Mutex::new();
-
// This is a terrible fix
use crate::sys::os_str::Buf;
@@ -200,11 +198,18 @@
&mut environ
}
+pub unsafe fn env_lock() -> MutexGuard<'static> {
+ // We never call `ENV_LOCK.init()`, so it is UB to attempt to
+ // acquire this mutex reentrantly!
+ static ENV_LOCK: Mutex = Mutex::new();
+ ENV_LOCK.lock()
+}
+
/// Returns a vector of (variable, value) byte-vector pairs for all the
/// environment variables of the current process.
pub fn env() -> Env {
unsafe {
- let _guard = ENV_LOCK.lock();
+ let _guard = env_lock();
let mut environ = *environ();
if environ == ptr::null() {
panic!("os::env() failure getting env string from OS: {}",
@@ -244,7 +249,7 @@
// always None as well
let k = CString::new(k.as_bytes())?;
unsafe {
- let _guard = ENV_LOCK.lock();
+ let _guard = env_lock();
let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
let ret = if s.is_null() {
None
@@ -260,7 +265,7 @@
let v = CString::new(v.as_bytes())?;
unsafe {
- let _guard = ENV_LOCK.lock();
+ let _guard = env_lock();
cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ())
}
}
@@ -269,7 +274,7 @@
let nbuf = CString::new(n.as_bytes())?;
unsafe {
- let _guard = ENV_LOCK.lock();
+ let _guard = env_lock();
cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ())
}
}
diff --git a/src/libstd/sys/vxworks/process/process_vxworks.rs b/src/libstd/sys/vxworks/process/process_vxworks.rs
index 7446471..79bfd770 100644
--- a/src/libstd/sys/vxworks/process/process_vxworks.rs
+++ b/src/libstd/sys/vxworks/process/process_vxworks.rs
@@ -15,6 +15,7 @@
-> io::Result<(Process, StdioPipes)> {
use crate::sys::{cvt_r};
const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";
+ let envp = self.capture_env();
if self.saw_nul() {
return Err(io::Error::new(ErrorKind::InvalidInput,
@@ -52,12 +53,19 @@
t!(cvt(libc::chdir(cwd.as_ptr())));
}
+ let c_envp = envp.as_ref().map(|c| c.as_ptr())
+ .unwrap_or_else(|| *sys::os::environ() as *const _);
+ let stack_size = thread::min_stack();
+
+ // ensure that access to the environment is synchronized
+ let _lock = sys::os::env_lock();
+
let ret = libc::rtpSpawn(
self.get_argv()[0], // executing program
self.get_argv().as_ptr() as *mut *const c_char, // argv
- *sys::os::environ() as *mut *const c_char,
+ c_envp as *mut *const c_char,
100 as c_int, // initial priority
- thread::min_stack(), // initial stack size.
+ stack_size, // initial stack size.
0, // options
0 // task options
);
diff --git a/src/libstd/sys/wasi/args.rs b/src/libstd/sys/wasi/args.rs
index 3280c49..02aa68d 100644
--- a/src/libstd/sys/wasi/args.rs
+++ b/src/libstd/sys/wasi/args.rs
@@ -1,15 +1,11 @@
-use crate::ffi::OsString;
+use crate::ffi::{CStr, OsStr, OsString};
use crate::marker::PhantomData;
-use crate::os::wasi::ffi::OsStringExt;
+use crate::os::wasi::ffi::OsStrExt;
use crate::vec;
-use ::wasi::wasi_unstable as wasi;
+pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
-}
-
-pub unsafe fn cleanup() {
-}
+pub unsafe fn cleanup() {}
pub struct Args {
iter: vec::IntoIter<OsString>,
@@ -18,17 +14,25 @@
/// Returns the command line arguments
pub fn args() -> Args {
- let buf = wasi::args_sizes_get().and_then(|args_sizes| {
- let mut buf = Vec::with_capacity(args_sizes.get_count());
- wasi::args_get(args_sizes, |arg| {
- let arg = OsString::from_vec(arg.to_vec());
- buf.push(arg);
- })?;
- Ok(buf)
- }).unwrap_or(vec![]);
Args {
- iter: buf.into_iter(),
- _dont_send_or_sync_me: PhantomData
+ iter: maybe_args().unwrap_or(Vec::new()).into_iter(),
+ _dont_send_or_sync_me: PhantomData,
+ }
+}
+
+fn maybe_args() -> Option<Vec<OsString>> {
+ unsafe {
+ let (argc, buf_size) = wasi::args_sizes_get().ok()?;
+ let mut argv = Vec::with_capacity(argc);
+ let mut buf = Vec::with_capacity(buf_size);
+ wasi::args_get(argv.as_mut_ptr(), buf.as_mut_ptr()).ok()?;
+ argv.set_len(argc);
+ let mut ret = Vec::with_capacity(argc);
+ for ptr in argv {
+ let s = CStr::from_ptr(ptr.cast());
+ ret.push(OsStr::from_bytes(s.to_bytes()).to_owned());
+ }
+ Some(ret)
}
}
diff --git a/src/libstd/sys/wasi/ext/fs.rs b/src/libstd/sys/wasi/ext/fs.rs
index 9fa4abf..92d0e60 100644
--- a/src/libstd/sys/wasi/ext/fs.rs
+++ b/src/libstd/sys/wasi/ext/fs.rs
@@ -4,12 +4,10 @@
use crate::fs::{self, File, Metadata, OpenOptions};
use crate::io::{self, IoSlice, IoSliceMut};
-use crate::os::wasi::ffi::OsStrExt;
use crate::path::{Path, PathBuf};
+use crate::sys::fs::osstr2str;
use crate::sys_common::{AsInner, AsInnerMut, FromInner};
-use ::wasi::wasi_unstable as wasi;
-
/// WASI-specific extensions to [`File`].
///
/// [`File`]: ../../../../std/fs/struct.File.html
@@ -49,62 +47,62 @@
/// Returns the current position within the file.
///
- /// This corresponds to the `__wasi_fd_tell` syscall and is similar to
+ /// This corresponds to the `fd_tell` syscall and is similar to
/// `seek` where you offset 0 bytes from the current position.
fn tell(&self) -> io::Result<u64>;
/// Adjust the flags associated with this file.
///
- /// This corresponds to the `__wasi_fd_fdstat_set_flags` syscall.
+ /// This corresponds to the `fd_fdstat_set_flags` syscall.
fn fdstat_set_flags(&self, flags: u16) -> io::Result<()>;
/// Adjust the rights associated with this file.
///
- /// This corresponds to the `__wasi_fd_fdstat_set_rights` syscall.
+ /// This corresponds to the `fd_fdstat_set_rights` syscall.
fn fdstat_set_rights(&self, rights: u64, inheriting: u64) -> io::Result<()>;
/// Provide file advisory information on a file descriptor.
///
- /// This corresponds to the `__wasi_fd_advise` syscall.
+ /// This corresponds to the `fd_advise` syscall.
fn advise(&self, offset: u64, len: u64, advice: u8) -> io::Result<()>;
/// Force the allocation of space in a file.
///
- /// This corresponds to the `__wasi_fd_allocate` syscall.
+ /// This corresponds to the `fd_allocate` syscall.
fn allocate(&self, offset: u64, len: u64) -> io::Result<()>;
/// Create a directory.
///
- /// This corresponds to the `__wasi_path_create_directory` syscall.
+ /// This corresponds to the `path_create_directory` syscall.
fn create_directory<P: AsRef<Path>>(&self, dir: P) -> io::Result<()>;
/// Read the contents of a symbolic link.
///
- /// This corresponds to the `__wasi_path_readlink` syscall.
+ /// This corresponds to the `path_readlink` syscall.
fn read_link<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf>;
/// Return the attributes of a file or directory.
///
- /// This corresponds to the `__wasi_path_filestat_get` syscall.
+ /// This corresponds to the `path_filestat_get` syscall.
fn metadata_at<P: AsRef<Path>>(&self, lookup_flags: u32, path: P) -> io::Result<Metadata>;
/// Unlink a file.
///
- /// This corresponds to the `__wasi_path_unlink_file` syscall.
+ /// This corresponds to the `path_unlink_file` syscall.
fn remove_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()>;
/// Remove a directory.
///
- /// This corresponds to the `__wasi_path_remove_directory` syscall.
+ /// This corresponds to the `path_remove_directory` syscall.
fn remove_directory<P: AsRef<Path>>(&self, path: P) -> io::Result<()>;
}
-// FIXME: bind __wasi_fd_fdstat_get - need to define a custom return type
-// FIXME: bind __wasi_fd_readdir - can't return `ReadDir` since we only have entry name
-// FIXME: bind __wasi_fd_filestat_set_times maybe? - on crates.io for unix
-// FIXME: bind __wasi_path_filestat_set_times maybe? - on crates.io for unix
-// FIXME: bind __wasi_poll_oneoff maybe? - probably should wait for I/O to settle
-// FIXME: bind __wasi_random_get maybe? - on crates.io for unix
+// FIXME: bind fd_fdstat_get - need to define a custom return type
+// FIXME: bind fd_readdir - can't return `ReadDir` since we only have entry name
+// FIXME: bind fd_filestat_set_times maybe? - on crates.io for unix
+// FIXME: bind path_filestat_set_times maybe? - on crates.io for unix
+// FIXME: bind poll_oneoff maybe? - probably should wait for I/O to settle
+// FIXME: bind random_get maybe? - on crates.io for unix
impl FileExt for fs::File {
fn read_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
@@ -136,9 +134,7 @@
}
fn create_directory<P: AsRef<Path>>(&self, dir: P) -> io::Result<()> {
- self.as_inner()
- .fd()
- .create_directory(dir.as_ref().as_os_str().as_bytes())
+ self.as_inner().fd().create_directory(osstr2str(dir.as_ref().as_ref())?)
}
fn read_link<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf> {
@@ -151,15 +147,11 @@
}
fn remove_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
- self.as_inner()
- .fd()
- .unlink_file(path.as_ref().as_os_str().as_bytes())
+ self.as_inner().fd().unlink_file(osstr2str(path.as_ref().as_ref())?)
}
fn remove_directory<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
- self.as_inner()
- .fd()
- .remove_directory(path.as_ref().as_os_str().as_bytes())
+ self.as_inner().fd().remove_directory(osstr2str(path.as_ref().as_ref())?)
}
}
@@ -167,10 +159,10 @@
///
/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
pub trait OpenOptionsExt {
- /// Pass custom `dirflags` argument to `__wasi_path_open`.
+ /// Pass custom `dirflags` argument to `path_open`.
///
/// This option configures the `dirflags` argument to the
- /// `__wasi_path_open` syscall which `OpenOptions` will eventually call. The
+ /// `path_open` syscall which `OpenOptions` will eventually call. The
/// `dirflags` argument configures how the file is looked up, currently
/// primarily affecting whether symlinks are followed or not.
///
@@ -188,31 +180,31 @@
fn directory(&mut self, dir: bool) -> &mut Self;
/// Indicates whether `__WASI_FDFLAG_DSYNC` is passed in the `fs_flags`
- /// field of `__wasi_path_open`.
+ /// field of `path_open`.
///
/// This option is by default `false`
fn dsync(&mut self, dsync: bool) -> &mut Self;
/// Indicates whether `__WASI_FDFLAG_NONBLOCK` is passed in the `fs_flags`
- /// field of `__wasi_path_open`.
+ /// field of `path_open`.
///
/// This option is by default `false`
fn nonblock(&mut self, nonblock: bool) -> &mut Self;
/// Indicates whether `__WASI_FDFLAG_RSYNC` is passed in the `fs_flags`
- /// field of `__wasi_path_open`.
+ /// field of `path_open`.
///
/// This option is by default `false`
fn rsync(&mut self, rsync: bool) -> &mut Self;
/// Indicates whether `__WASI_FDFLAG_SYNC` is passed in the `fs_flags`
- /// field of `__wasi_path_open`.
+ /// field of `path_open`.
///
/// This option is by default `false`
fn sync(&mut self, sync: bool) -> &mut Self;
/// Indicates the value that should be passed in for the `fs_rights_base`
- /// parameter of `__wasi_path_open`.
+ /// parameter of `path_open`.
///
/// This option defaults based on the `read` and `write` configuration of
/// this `OpenOptions` builder. If this method is called, however, the
@@ -220,7 +212,7 @@
fn fs_rights_base(&mut self, rights: u64) -> &mut Self;
/// Indicates the value that should be passed in for the
- /// `fs_rights_inheriting` parameter of `__wasi_path_open`.
+ /// `fs_rights_inheriting` parameter of `path_open`.
///
/// The default for this option is the same value as what will be passed
/// for the `fs_rights_base` parameter but if this method is called then
@@ -229,7 +221,7 @@
/// Open a file or directory.
///
- /// This corresponds to the `__wasi_path_open` syscall.
+ /// This corresponds to the `path_open` syscall.
fn open_at<P: AsRef<Path>>(&self, file: &File, path: P) -> io::Result<File>;
}
@@ -284,38 +276,38 @@
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
pub trait MetadataExt {
- /// Returns the `st_dev` field of the internal `__wasi_filestat_t`
+ /// Returns the `st_dev` field of the internal `filestat_t`
fn dev(&self) -> u64;
- /// Returns the `st_ino` field of the internal `__wasi_filestat_t`
+ /// Returns the `st_ino` field of the internal `filestat_t`
fn ino(&self) -> u64;
- /// Returns the `st_nlink` field of the internal `__wasi_filestat_t`
- fn nlink(&self) -> u32;
- /// Returns the `st_atim` field of the internal `__wasi_filestat_t`
+ /// Returns the `st_nlink` field of the internal `filestat_t`
+ fn nlink(&self) -> u64;
+ /// Returns the `st_atim` field of the internal `filestat_t`
fn atim(&self) -> u64;
- /// Returns the `st_mtim` field of the internal `__wasi_filestat_t`
+ /// Returns the `st_mtim` field of the internal `filestat_t`
fn mtim(&self) -> u64;
- /// Returns the `st_ctim` field of the internal `__wasi_filestat_t`
+ /// Returns the `st_ctim` field of the internal `filestat_t`
fn ctim(&self) -> u64;
}
impl MetadataExt for fs::Metadata {
fn dev(&self) -> u64 {
- self.as_inner().as_wasi().st_dev
+ self.as_inner().as_wasi().dev
}
fn ino(&self) -> u64 {
- self.as_inner().as_wasi().st_ino
+ self.as_inner().as_wasi().ino
}
- fn nlink(&self) -> u32 {
- self.as_inner().as_wasi().st_nlink
+ fn nlink(&self) -> u64 {
+ self.as_inner().as_wasi().nlink
}
fn atim(&self) -> u64 {
- self.as_inner().as_wasi().st_atim
+ self.as_inner().as_wasi().atim
}
fn mtim(&self) -> u64 {
- self.as_inner().as_wasi().st_mtim
+ self.as_inner().as_wasi().mtim
}
fn ctim(&self) -> u64 {
- self.as_inner().as_wasi().st_ctim
+ self.as_inner().as_wasi().ctim
}
}
@@ -355,7 +347,7 @@
///
/// [`fs::DirEntry`]: ../../../../std/fs/struct.DirEntry.html
pub trait DirEntryExt {
- /// Returns the underlying `d_ino` field of the `__wasi_dirent_t`
+ /// Returns the underlying `d_ino` field of the `dirent_t`
fn ino(&self) -> u64;
}
@@ -367,7 +359,7 @@
/// Create a hard link.
///
-/// This corresponds to the `__wasi_path_link` syscall.
+/// This corresponds to the `path_link` syscall.
pub fn link<P: AsRef<Path>, U: AsRef<Path>>(
old_fd: &File,
old_flags: u32,
@@ -377,15 +369,15 @@
) -> io::Result<()> {
old_fd.as_inner().fd().link(
old_flags,
- old_path.as_ref().as_os_str().as_bytes(),
+ osstr2str(old_path.as_ref().as_ref())?,
new_fd.as_inner().fd(),
- new_path.as_ref().as_os_str().as_bytes(),
+ osstr2str(new_path.as_ref().as_ref())?,
)
}
/// Rename a file or directory.
///
-/// This corresponds to the `__wasi_path_rename` syscall.
+/// This corresponds to the `path_rename` syscall.
pub fn rename<P: AsRef<Path>, U: AsRef<Path>>(
old_fd: &File,
old_path: P,
@@ -393,22 +385,21 @@
new_path: U,
) -> io::Result<()> {
old_fd.as_inner().fd().rename(
- old_path.as_ref().as_os_str().as_bytes(),
+ osstr2str(old_path.as_ref().as_ref())?,
new_fd.as_inner().fd(),
- new_path.as_ref().as_os_str().as_bytes(),
+ osstr2str(new_path.as_ref().as_ref())?,
)
}
/// Create a symbolic link.
///
-/// This corresponds to the `__wasi_path_symlink` syscall.
+/// This corresponds to the `path_symlink` syscall.
pub fn symlink<P: AsRef<Path>, U: AsRef<Path>>(
old_path: P,
fd: &File,
new_path: U,
) -> io::Result<()> {
- fd.as_inner().fd().symlink(
- old_path.as_ref().as_os_str().as_bytes(),
- new_path.as_ref().as_os_str().as_bytes(),
- )
+ fd.as_inner()
+ .fd()
+ .symlink(osstr2str(old_path.as_ref().as_ref())?, osstr2str(new_path.as_ref().as_ref())?)
}
diff --git a/src/libstd/sys/wasi/ext/io.rs b/src/libstd/sys/wasi/ext/io.rs
index f1839df..f678b71 100644
--- a/src/libstd/sys/wasi/ext/io.rs
+++ b/src/libstd/sys/wasi/ext/io.rs
@@ -8,8 +8,6 @@
use crate::net;
use crate::sys_common::{AsInner, FromInner, IntoInner};
-use ::wasi::wasi_unstable as wasi;
-
/// Raw file descriptors.
pub type RawFd = u32;
@@ -127,18 +125,18 @@
impl AsRawFd for io::Stdin {
fn as_raw_fd(&self) -> RawFd {
- wasi::STDIN_FD
+ sys::stdio::Stdin.as_raw_fd()
}
}
impl AsRawFd for io::Stdout {
fn as_raw_fd(&self) -> RawFd {
- wasi::STDOUT_FD
+ sys::stdio::Stdout.as_raw_fd()
}
}
impl AsRawFd for io::Stderr {
fn as_raw_fd(&self) -> RawFd {
- wasi::STDERR_FD
+ sys::stdio::Stderr.as_raw_fd()
}
}
diff --git a/src/libstd/sys/wasi/fd.rs b/src/libstd/sys/wasi/fd.rs
index 5b7a867..00327c1 100644
--- a/src/libstd/sys/wasi/fd.rs
+++ b/src/libstd/sys/wasi/fd.rs
@@ -1,40 +1,31 @@
#![allow(dead_code)]
+use super::err2io;
use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
use crate::mem;
use crate::net::Shutdown;
-use super::err2io;
-use ::wasi::wasi_unstable as wasi;
#[derive(Debug)]
pub struct WasiFd {
fd: wasi::Fd,
}
-fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::IoVec] {
- assert_eq!(
- mem::size_of::<IoSliceMut<'_>>(),
- mem::size_of::<wasi::IoVec>()
- );
- assert_eq!(
- mem::align_of::<IoSliceMut<'_>>(),
- mem::align_of::<wasi::IoVec>()
- );
+fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] {
+ assert_eq!(mem::size_of::<IoSliceMut<'_>>(), mem::size_of::<wasi::Iovec>());
+ assert_eq!(mem::align_of::<IoSliceMut<'_>>(), mem::align_of::<wasi::Iovec>());
/// SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout
- unsafe { mem::transmute(a) }
+ unsafe {
+ mem::transmute(a)
+ }
}
-fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::CIoVec] {
- assert_eq!(
- mem::size_of::<IoSlice<'_>>(),
- mem::size_of::<wasi::CIoVec>()
- );
- assert_eq!(
- mem::align_of::<IoSlice<'_>>(),
- mem::align_of::<wasi::CIoVec>()
- );
+fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] {
+ assert_eq!(mem::size_of::<IoSlice<'_>>(), mem::size_of::<wasi::Ciovec>());
+ assert_eq!(mem::align_of::<IoSlice<'_>>(), mem::align_of::<wasi::Ciovec>());
/// SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout
- unsafe { mem::transmute(a) }
+ unsafe {
+ mem::transmute(a)
+ }
}
impl WasiFd {
@@ -87,7 +78,7 @@
// FIXME: __wasi_fd_fdstat_get
- pub fn set_flags(&self, flags: wasi::FdFlags) -> io::Result<()> {
+ pub fn set_flags(&self, flags: wasi::Fdflags) -> io::Result<()> {
unsafe { wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) }
}
@@ -107,31 +98,30 @@
unsafe { wasi::fd_allocate(self.fd, offset, len).map_err(err2io) }
}
- pub fn create_directory(&self, path: &[u8]) -> io::Result<()> {
+ pub fn create_directory(&self, path: &str) -> io::Result<()> {
unsafe { wasi::path_create_directory(self.fd, path).map_err(err2io) }
}
pub fn link(
&self,
- old_flags: wasi::LookupFlags,
- old_path: &[u8],
+ old_flags: wasi::Lookupflags,
+ old_path: &str,
new_fd: &WasiFd,
- new_path: &[u8],
+ new_path: &str,
) -> io::Result<()> {
unsafe {
- wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path)
- .map_err(err2io)
+ wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path).map_err(err2io)
}
}
pub fn open(
&self,
- dirflags: wasi::LookupFlags,
- path: &[u8],
- oflags: wasi::OFlags,
+ dirflags: wasi::Lookupflags,
+ path: &str,
+ oflags: wasi::Oflags,
fs_rights_base: wasi::Rights,
fs_rights_inheriting: wasi::Rights,
- fs_flags: wasi::FdFlags,
+ fs_flags: wasi::Fdflags,
) -> io::Result<WasiFd> {
unsafe {
wasi::path_open(
@@ -142,25 +132,25 @@
fs_rights_base,
fs_rights_inheriting,
fs_flags,
- ).map(|fd| WasiFd::from_raw(fd)).map_err(err2io)
+ )
+ .map(|fd| WasiFd::from_raw(fd))
+ .map_err(err2io)
}
}
- pub fn readdir(&self, buf: &mut [u8], cookie: wasi::DirCookie) -> io::Result<usize> {
- unsafe { wasi::fd_readdir(self.fd, buf, cookie).map_err(err2io) }
+ pub fn readdir(&self, buf: &mut [u8], cookie: wasi::Dircookie) -> io::Result<usize> {
+ unsafe { wasi::fd_readdir(self.fd, buf.as_mut_ptr(), buf.len(), cookie).map_err(err2io) }
}
- pub fn readlink(&self, path: &[u8], buf: &mut [u8]) -> io::Result<usize> {
- unsafe { wasi::path_readlink(self.fd, path, buf).map_err(err2io) }
+ pub fn readlink(&self, path: &str, buf: &mut [u8]) -> io::Result<usize> {
+ unsafe { wasi::path_readlink(self.fd, path, buf.as_mut_ptr(), buf.len()).map_err(err2io) }
}
- pub fn rename(&self, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8]) -> io::Result<()> {
- unsafe {
- wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io)
- }
+ pub fn rename(&self, old_path: &str, new_fd: &WasiFd, new_path: &str) -> io::Result<()> {
+ unsafe { wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io) }
}
- pub fn filestat_get(&self) -> io::Result<wasi::FileStat> {
+ pub fn filestat_get(&self) -> io::Result<wasi::Filestat> {
unsafe { wasi::fd_filestat_get(self.fd).map_err(err2io) }
}
@@ -168,11 +158,9 @@
&self,
atim: wasi::Timestamp,
mtim: wasi::Timestamp,
- fstflags: wasi::FstFlags,
+ fstflags: wasi::Fstflags,
) -> io::Result<()> {
- unsafe {
- wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags).map_err(err2io)
- }
+ unsafe { wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags).map_err(err2io) }
}
pub fn filestat_set_size(&self, size: u64) -> io::Result<()> {
@@ -181,61 +169,55 @@
pub fn path_filestat_get(
&self,
- flags: wasi::LookupFlags,
- path: &[u8],
- ) -> io::Result<wasi::FileStat> {
+ flags: wasi::Lookupflags,
+ path: &str,
+ ) -> io::Result<wasi::Filestat> {
unsafe { wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) }
}
pub fn path_filestat_set_times(
&self,
- flags: wasi::LookupFlags,
- path: &[u8],
+ flags: wasi::Lookupflags,
+ path: &str,
atim: wasi::Timestamp,
mtim: wasi::Timestamp,
- fstflags: wasi::FstFlags,
+ fstflags: wasi::Fstflags,
) -> io::Result<()> {
unsafe {
- wasi::path_filestat_set_times(
- self.fd,
- flags,
- path,
- atim,
- mtim,
- fstflags,
- ).map_err(err2io)
+ wasi::path_filestat_set_times(self.fd, flags, path, atim, mtim, fstflags)
+ .map_err(err2io)
}
}
- pub fn symlink(&self, old_path: &[u8], new_path: &[u8]) -> io::Result<()> {
+ pub fn symlink(&self, old_path: &str, new_path: &str) -> io::Result<()> {
unsafe { wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) }
}
- pub fn unlink_file(&self, path: &[u8]) -> io::Result<()> {
+ pub fn unlink_file(&self, path: &str) -> io::Result<()> {
unsafe { wasi::path_unlink_file(self.fd, path).map_err(err2io) }
}
- pub fn remove_directory(&self, path: &[u8]) -> io::Result<()> {
+ pub fn remove_directory(&self, path: &str) -> io::Result<()> {
unsafe { wasi::path_remove_directory(self.fd, path).map_err(err2io) }
}
pub fn sock_recv(
&self,
ri_data: &mut [IoSliceMut<'_>],
- ri_flags: wasi::RiFlags,
- ) -> io::Result<(usize, wasi::RoFlags)> {
+ ri_flags: wasi::Riflags,
+ ) -> io::Result<(usize, wasi::Roflags)> {
unsafe { wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(err2io) }
}
- pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::SiFlags) -> io::Result<usize> {
+ pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::Siflags) -> io::Result<usize> {
unsafe { wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(err2io) }
}
pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> {
let how = match how {
- Shutdown::Read => wasi::SHUT_RD,
- Shutdown::Write => wasi::SHUT_WR,
- Shutdown::Both => wasi::SHUT_WR | wasi::SHUT_RD,
+ Shutdown::Read => wasi::SDFLAGS_RD,
+ Shutdown::Write => wasi::SDFLAGS_WR,
+ Shutdown::Both => wasi::SDFLAGS_WR | wasi::SDFLAGS_RD,
};
unsafe { wasi::sock_shutdown(self.fd, how).map_err(err2io) }
}
diff --git a/src/libstd/sys/wasi/fs.rs b/src/libstd/sys/wasi/fs.rs
index 4113f6a..fad092e 100644
--- a/src/libstd/sys/wasi/fs.rs
+++ b/src/libstd/sys/wasi/fs.rs
@@ -15,20 +15,18 @@
pub use crate::sys_common::fs::copy;
pub use crate::sys_common::fs::remove_dir_all;
-use ::wasi::wasi_unstable as wasi;
-
pub struct File {
fd: WasiFd,
}
#[derive(Clone)]
pub struct FileAttr {
- meta: wasi::FileStat,
+ meta: wasi::Filestat,
}
pub struct ReadDir {
inner: Arc<ReadDirInner>,
- cookie: Option<wasi::DirCookie>,
+ cookie: Option<wasi::Dircookie>,
buf: Vec<u8>,
offset: usize,
cap: usize,
@@ -49,9 +47,9 @@
pub struct OpenOptions {
read: bool,
write: bool,
- dirflags: wasi::LookupFlags,
- fdflags: wasi::FdFlags,
- oflags: wasi::OFlags,
+ dirflags: wasi::Lookupflags,
+ fdflags: wasi::Fdflags,
+ oflags: wasi::Oflags,
rights_base: Option<wasi::Rights>,
rights_inheriting: Option<wasi::Rights>,
}
@@ -63,7 +61,7 @@
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
pub struct FileType {
- bits: wasi::FileType,
+ bits: wasi::Filetype,
}
#[derive(Debug)]
@@ -71,7 +69,7 @@
impl FileAttr {
pub fn size(&self) -> u64 {
- self.meta.st_size
+ self.meta.size
}
pub fn perm(&self) -> FilePermissions {
@@ -80,24 +78,22 @@
}
pub fn file_type(&self) -> FileType {
- FileType {
- bits: self.meta.st_filetype,
- }
+ FileType { bits: self.meta.filetype }
}
pub fn modified(&self) -> io::Result<SystemTime> {
- Ok(SystemTime::from_wasi_timestamp(self.meta.st_mtim))
+ Ok(SystemTime::from_wasi_timestamp(self.meta.mtim))
}
pub fn accessed(&self) -> io::Result<SystemTime> {
- Ok(SystemTime::from_wasi_timestamp(self.meta.st_atim))
+ Ok(SystemTime::from_wasi_timestamp(self.meta.atim))
}
pub fn created(&self) -> io::Result<SystemTime> {
- Ok(SystemTime::from_wasi_timestamp(self.meta.st_ctim))
+ Ok(SystemTime::from_wasi_timestamp(self.meta.ctim))
}
- pub fn as_wasi(&self) -> &wasi::FileStat {
+ pub fn as_wasi(&self) -> &wasi::Filestat {
&self.meta
}
}
@@ -125,7 +121,7 @@
self.bits == wasi::FILETYPE_SYMBOLIC_LINK
}
- pub fn bits(&self) -> wasi::FileType {
+ pub fn bits(&self) -> wasi::Filetype {
self.bits
}
}
@@ -177,8 +173,7 @@
continue;
}
let (dirent, data) = data.split_at(dirent_size);
- let dirent =
- unsafe { ptr::read_unaligned(dirent.as_ptr() as *const wasi::Dirent) };
+ let dirent = unsafe { ptr::read_unaligned(dirent.as_ptr() as *const wasi::Dirent) };
// If the file name was truncated, then we need to reinvoke
// `readdir` so we truncate our buffer to start over and reread this
@@ -224,17 +219,11 @@
}
pub fn metadata(&self) -> io::Result<FileAttr> {
- metadata_at(
- &self.inner.dir.fd,
- 0,
- OsStr::from_bytes(&self.name).as_ref(),
- )
+ metadata_at(&self.inner.dir.fd, 0, OsStr::from_bytes(&self.name).as_ref())
}
pub fn file_type(&self) -> io::Result<FileType> {
- Ok(FileType {
- bits: self.meta.d_type,
- })
+ Ok(FileType { bits: self.meta.d_type })
}
pub fn ino(&self) -> wasi::Inode {
@@ -245,7 +234,7 @@
impl OpenOptions {
pub fn new() -> OpenOptions {
let mut base = OpenOptions::default();
- base.dirflags = wasi::LOOKUP_SYMLINK_FOLLOW;
+ base.dirflags = wasi::LOOKUPFLAGS_SYMLINK_FOLLOW;
return base;
}
@@ -258,23 +247,23 @@
}
pub fn truncate(&mut self, truncate: bool) {
- self.oflag(wasi::O_TRUNC, truncate);
+ self.oflag(wasi::OFLAGS_TRUNC, truncate);
}
pub fn create(&mut self, create: bool) {
- self.oflag(wasi::O_CREAT, create);
+ self.oflag(wasi::OFLAGS_CREAT, create);
}
pub fn create_new(&mut self, create_new: bool) {
- self.oflag(wasi::O_EXCL, create_new);
- self.oflag(wasi::O_CREAT, create_new);
+ self.oflag(wasi::OFLAGS_EXCL, create_new);
+ self.oflag(wasi::OFLAGS_CREAT, create_new);
}
pub fn directory(&mut self, directory: bool) {
- self.oflag(wasi::O_DIRECTORY, directory);
+ self.oflag(wasi::OFLAGS_DIRECTORY, directory);
}
- fn oflag(&mut self, bit: wasi::OFlags, set: bool) {
+ fn oflag(&mut self, bit: wasi::Oflags, set: bool) {
if set {
self.oflags |= bit;
} else {
@@ -283,26 +272,26 @@
}
pub fn append(&mut self, set: bool) {
- self.fdflag(wasi::FDFLAG_APPEND, set);
+ self.fdflag(wasi::FDFLAGS_APPEND, set);
}
pub fn dsync(&mut self, set: bool) {
- self.fdflag(wasi::FDFLAG_DSYNC, set);
+ self.fdflag(wasi::FDFLAGS_DSYNC, set);
}
pub fn nonblock(&mut self, set: bool) {
- self.fdflag(wasi::FDFLAG_NONBLOCK, set);
+ self.fdflag(wasi::FDFLAGS_NONBLOCK, set);
}
pub fn rsync(&mut self, set: bool) {
- self.fdflag(wasi::FDFLAG_RSYNC, set);
+ self.fdflag(wasi::FDFLAGS_RSYNC, set);
}
pub fn sync(&mut self, set: bool) {
- self.fdflag(wasi::FDFLAG_SYNC, set);
+ self.fdflag(wasi::FDFLAGS_SYNC, set);
}
- fn fdflag(&mut self, bit: wasi::FdFlags, set: bool) {
+ fn fdflag(&mut self, bit: wasi::Fdflags, set: bool) {
if set {
self.fdflags |= bit;
} else {
@@ -330,36 +319,36 @@
// based on that.
let mut base = 0;
if self.read {
- base |= wasi::RIGHT_FD_READ;
- base |= wasi::RIGHT_FD_READDIR;
+ base |= wasi::RIGHTS_FD_READ;
+ base |= wasi::RIGHTS_FD_READDIR;
}
if self.write {
- base |= wasi::RIGHT_FD_WRITE;
- base |= wasi::RIGHT_FD_DATASYNC;
- base |= wasi::RIGHT_FD_ALLOCATE;
- base |= wasi::RIGHT_FD_FILESTAT_SET_SIZE;
+ base |= wasi::RIGHTS_FD_WRITE;
+ base |= wasi::RIGHTS_FD_DATASYNC;
+ base |= wasi::RIGHTS_FD_ALLOCATE;
+ base |= wasi::RIGHTS_FD_FILESTAT_SET_SIZE;
}
// FIXME: some of these should probably be read-only or write-only...
- base |= wasi::RIGHT_FD_ADVISE;
- base |= wasi::RIGHT_FD_FDSTAT_SET_FLAGS;
- base |= wasi::RIGHT_FD_FILESTAT_SET_TIMES;
- base |= wasi::RIGHT_FD_SEEK;
- base |= wasi::RIGHT_FD_SYNC;
- base |= wasi::RIGHT_FD_TELL;
- base |= wasi::RIGHT_PATH_CREATE_DIRECTORY;
- base |= wasi::RIGHT_PATH_CREATE_FILE;
- base |= wasi::RIGHT_PATH_FILESTAT_GET;
- base |= wasi::RIGHT_PATH_LINK_SOURCE;
- base |= wasi::RIGHT_PATH_LINK_TARGET;
- base |= wasi::RIGHT_PATH_OPEN;
- base |= wasi::RIGHT_PATH_READLINK;
- base |= wasi::RIGHT_PATH_REMOVE_DIRECTORY;
- base |= wasi::RIGHT_PATH_RENAME_SOURCE;
- base |= wasi::RIGHT_PATH_RENAME_TARGET;
- base |= wasi::RIGHT_PATH_SYMLINK;
- base |= wasi::RIGHT_PATH_UNLINK_FILE;
- base |= wasi::RIGHT_POLL_FD_READWRITE;
+ base |= wasi::RIGHTS_FD_ADVISE;
+ base |= wasi::RIGHTS_FD_FDSTAT_SET_FLAGS;
+ base |= wasi::RIGHTS_FD_FILESTAT_SET_TIMES;
+ base |= wasi::RIGHTS_FD_SEEK;
+ base |= wasi::RIGHTS_FD_SYNC;
+ base |= wasi::RIGHTS_FD_TELL;
+ base |= wasi::RIGHTS_PATH_CREATE_DIRECTORY;
+ base |= wasi::RIGHTS_PATH_CREATE_FILE;
+ base |= wasi::RIGHTS_PATH_FILESTAT_GET;
+ base |= wasi::RIGHTS_PATH_LINK_SOURCE;
+ base |= wasi::RIGHTS_PATH_LINK_TARGET;
+ base |= wasi::RIGHTS_PATH_OPEN;
+ base |= wasi::RIGHTS_PATH_READLINK;
+ base |= wasi::RIGHTS_PATH_REMOVE_DIRECTORY;
+ base |= wasi::RIGHTS_PATH_RENAME_SOURCE;
+ base |= wasi::RIGHTS_PATH_RENAME_TARGET;
+ base |= wasi::RIGHTS_PATH_SYMLINK;
+ base |= wasi::RIGHTS_PATH_UNLINK_FILE;
+ base |= wasi::RIGHTS_POLL_FD_READWRITE;
return base;
}
@@ -368,14 +357,14 @@
self.rights_inheriting.unwrap_or_else(|| self.rights_base())
}
- pub fn lookup_flags(&mut self, flags: wasi::LookupFlags) {
+ pub fn lookup_flags(&mut self, flags: wasi::Lookupflags) {
self.dirflags = flags;
}
}
impl File {
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
- let (dir, file) = open_parent(path, wasi::RIGHT_PATH_OPEN)?;
+ let (dir, file) = open_parent(path, wasi::RIGHTS_PATH_OPEN)?;
open_at(&dir, &file, opts)
}
@@ -387,11 +376,7 @@
self.fd.filestat_get().map(|meta| FileAttr { meta })
}
- pub fn metadata_at(
- &self,
- flags: wasi::LookupFlags,
- path: &Path,
- ) -> io::Result<FileAttr> {
+ pub fn metadata_at(&self, flags: wasi::Lookupflags, path: &Path) -> io::Result<FileAttr> {
metadata_at(&self.fd, flags, path)
}
@@ -457,11 +442,7 @@
impl FromInner<u32> for File {
fn from_inner(fd: u32) -> File {
- unsafe {
- File {
- fd: WasiFd::from_raw(fd),
- }
- }
+ unsafe { File { fd: WasiFd::from_raw(fd) } }
}
}
@@ -471,16 +452,14 @@
}
pub fn mkdir(&self, p: &Path) -> io::Result<()> {
- let (dir, file) = open_parent(p, wasi::RIGHT_PATH_CREATE_DIRECTORY)?;
- dir.create_directory(file.as_os_str().as_bytes())
+ let (dir, file) = open_parent(p, wasi::RIGHTS_PATH_CREATE_DIRECTORY)?;
+ dir.create_directory(osstr2str(file.as_ref())?)
}
}
impl fmt::Debug for File {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("File")
- .field("fd", &self.fd.as_raw())
- .finish()
+ f.debug_struct("File").field("fd", &self.fd.as_raw()).finish()
}
}
@@ -494,26 +473,19 @@
buf: vec![0; 128],
offset: 0,
cap: 0,
- inner: Arc::new(ReadDirInner {
- dir,
- root: p.to_path_buf(),
- }),
+ inner: Arc::new(ReadDirInner { dir, root: p.to_path_buf() }),
})
}
pub fn unlink(p: &Path) -> io::Result<()> {
- let (dir, file) = open_parent(p, wasi::RIGHT_PATH_UNLINK_FILE)?;
- dir.unlink_file(file.as_os_str().as_bytes())
+ let (dir, file) = open_parent(p, wasi::RIGHTS_PATH_UNLINK_FILE)?;
+ dir.unlink_file(osstr2str(file.as_ref())?)
}
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
- let (old, old_file) = open_parent(old, wasi::RIGHT_PATH_RENAME_SOURCE)?;
- let (new, new_file) = open_parent(new, wasi::RIGHT_PATH_RENAME_TARGET)?;
- old.rename(
- old_file.as_os_str().as_bytes(),
- &new,
- new_file.as_os_str().as_bytes(),
- )
+ let (old, old_file) = open_parent(old, wasi::RIGHTS_PATH_RENAME_SOURCE)?;
+ let (new, new_file) = open_parent(new, wasi::RIGHTS_PATH_RENAME_TARGET)?;
+ old.rename(osstr2str(old_file.as_ref())?, &new, osstr2str(new_file.as_ref())?)
}
pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> {
@@ -523,12 +495,12 @@
}
pub fn rmdir(p: &Path) -> io::Result<()> {
- let (dir, file) = open_parent(p, wasi::RIGHT_PATH_REMOVE_DIRECTORY)?;
- dir.remove_directory(file.as_os_str().as_bytes())
+ let (dir, file) = open_parent(p, wasi::RIGHTS_PATH_REMOVE_DIRECTORY)?;
+ dir.remove_directory(osstr2str(file.as_ref())?)
}
pub fn readlink(p: &Path) -> io::Result<PathBuf> {
- let (dir, file) = open_parent(p, wasi::RIGHT_PATH_READLINK)?;
+ let (dir, file) = open_parent(p, wasi::RIGHTS_PATH_READLINK)?;
read_link(&dir, &file)
}
@@ -549,7 +521,7 @@
// Now that we have an initial guess of how big to make our buffer, call
// `readlink` in a loop until it fails or reports it filled fewer bytes than
// we asked for, indicating we got everything.
- let file = file.as_os_str().as_bytes();
+ let file = osstr2str(file.as_ref())?;
let mut destination = vec![0u8; initial_size];
loop {
let len = fd.readlink(file, &mut destination)?;
@@ -564,38 +536,34 @@
}
pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
- let (dst, dst_file) = open_parent(dst, wasi::RIGHT_PATH_SYMLINK)?;
- dst.symlink(src.as_os_str().as_bytes(), dst_file.as_os_str().as_bytes())
+ let (dst, dst_file) = open_parent(dst, wasi::RIGHTS_PATH_SYMLINK)?;
+ dst.symlink(osstr2str(src.as_ref())?, osstr2str(dst_file.as_ref())?)
}
pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
- let (src, src_file) = open_parent(src, wasi::RIGHT_PATH_LINK_SOURCE)?;
- let (dst, dst_file) = open_parent(dst, wasi::RIGHT_PATH_LINK_TARGET)?;
+ let (src, src_file) = open_parent(src, wasi::RIGHTS_PATH_LINK_SOURCE)?;
+ let (dst, dst_file) = open_parent(dst, wasi::RIGHTS_PATH_LINK_TARGET)?;
src.link(
- wasi::LOOKUP_SYMLINK_FOLLOW,
- src_file.as_os_str().as_bytes(),
+ wasi::LOOKUPFLAGS_SYMLINK_FOLLOW,
+ osstr2str(src_file.as_ref())?,
&dst,
- dst_file.as_os_str().as_bytes(),
+ osstr2str(dst_file.as_ref())?,
)
}
pub fn stat(p: &Path) -> io::Result<FileAttr> {
- let (dir, file) = open_parent(p, wasi::RIGHT_PATH_FILESTAT_GET)?;
- metadata_at(&dir, wasi::LOOKUP_SYMLINK_FOLLOW, &file)
+ let (dir, file) = open_parent(p, wasi::RIGHTS_PATH_FILESTAT_GET)?;
+ metadata_at(&dir, wasi::LOOKUPFLAGS_SYMLINK_FOLLOW, &file)
}
pub fn lstat(p: &Path) -> io::Result<FileAttr> {
- let (dir, file) = open_parent(p, wasi::RIGHT_PATH_FILESTAT_GET)?;
+ let (dir, file) = open_parent(p, wasi::RIGHTS_PATH_FILESTAT_GET)?;
metadata_at(&dir, 0, &file)
}
-fn metadata_at(
- fd: &WasiFd,
- flags: wasi::LookupFlags,
- path: &Path,
-) -> io::Result<FileAttr> {
- fd.path_filestat_get(flags, path.as_os_str().as_bytes())
- .map(|meta| FileAttr { meta })
+fn metadata_at(fd: &WasiFd, flags: wasi::Lookupflags, path: &Path) -> io::Result<FileAttr> {
+ let meta = fd.path_filestat_get(flags, osstr2str(path.as_ref())?)?;
+ Ok(FileAttr { meta })
}
pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
@@ -607,7 +575,7 @@
fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result<File> {
let fd = fd.open(
opts.dirflags,
- path.as_os_str().as_bytes(),
+ osstr2str(path.as_ref())?,
opts.oflags,
opts.rights_base(),
opts.rights_inheriting(),
@@ -643,10 +611,7 @@
///
/// Note that this can fail if `p` doesn't look like it can be opened relative
/// to any preopened file descriptor.
-fn open_parent(
- p: &Path,
- rights: wasi::Rights,
-) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
+fn open_parent(p: &Path, rights: wasi::Rights) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
let p = CString::new(p.as_os_str().as_bytes())?;
unsafe {
let mut ret = ptr::null();
@@ -671,3 +636,7 @@
return Ok((ManuallyDrop::new(WasiFd::from_raw(fd as u32)), path));
}
}
+
+pub fn osstr2str(f: &OsStr) -> io::Result<&str> {
+ f.to_str().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "input must be utf-8"))
+}
diff --git a/src/libstd/sys/wasi/io.rs b/src/libstd/sys/wasi/io.rs
index 4be92fa..41a6e97 100644
--- a/src/libstd/sys/wasi/io.rs
+++ b/src/libstd/sys/wasi/io.rs
@@ -1,12 +1,9 @@
use crate::marker::PhantomData;
use crate::slice;
-use ::wasi::wasi_unstable as wasi;
-use core::ffi::c_void;
-
#[repr(transparent)]
pub struct IoSlice<'a> {
- vec: wasi::CIoVec,
+ vec: wasi::Ciovec,
_p: PhantomData<&'a [u8]>,
}
@@ -14,8 +11,8 @@
#[inline]
pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
IoSlice {
- vec: wasi::CIoVec {
- buf: buf.as_ptr() as *const c_void,
+ vec: wasi::Ciovec {
+ buf: buf.as_ptr(),
buf_len: buf.len(),
},
_p: PhantomData,
@@ -44,7 +41,7 @@
#[repr(transparent)]
pub struct IoSliceMut<'a> {
- vec: wasi::IoVec,
+ vec: wasi::Iovec,
_p: PhantomData<&'a mut [u8]>,
}
@@ -52,8 +49,8 @@
#[inline]
pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
IoSliceMut {
- vec: wasi::IoVec {
- buf: buf.as_mut_ptr() as *mut c_void,
+ vec: wasi::Iovec {
+ buf: buf.as_mut_ptr(),
buf_len: buf.len()
},
_p: PhantomData,
diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs
index 517e3be..83f98a1 100644
--- a/src/libstd/sys/wasi/mod.rs
+++ b/src/libstd/sys/wasi/mod.rs
@@ -17,7 +17,6 @@
use crate::io as std_io;
use crate::mem;
use crate::os::raw::c_char;
-use ::wasi::wasi_unstable as wasi;
pub mod alloc;
pub mod args;
@@ -72,25 +71,21 @@
if errno > u16::max_value() as i32 || errno < 0 {
return Other;
}
- let code = match wasi::Error::new(errno as u16) {
- Some(code) => code,
- None => return Other,
- };
- match code {
- wasi::ECONNREFUSED => ConnectionRefused,
- wasi::ECONNRESET => ConnectionReset,
- wasi::EPERM | wasi::EACCES => PermissionDenied,
- wasi::EPIPE => BrokenPipe,
- wasi::ENOTCONN => NotConnected,
- wasi::ECONNABORTED => ConnectionAborted,
- wasi::EADDRNOTAVAIL => AddrNotAvailable,
- wasi::EADDRINUSE => AddrInUse,
- wasi::ENOENT => NotFound,
- wasi::EINTR => Interrupted,
- wasi::EINVAL => InvalidInput,
- wasi::ETIMEDOUT => TimedOut,
- wasi::EEXIST => AlreadyExists,
- wasi::EAGAIN => WouldBlock,
+ match errno as u16 {
+ wasi::ERRNO_CONNREFUSED => ConnectionRefused,
+ wasi::ERRNO_CONNRESET => ConnectionReset,
+ wasi::ERRNO_PERM | wasi::ERRNO_ACCES => PermissionDenied,
+ wasi::ERRNO_PIPE => BrokenPipe,
+ wasi::ERRNO_NOTCONN => NotConnected,
+ wasi::ERRNO_CONNABORTED => ConnectionAborted,
+ wasi::ERRNO_ADDRNOTAVAIL => AddrNotAvailable,
+ wasi::ERRNO_ADDRINUSE => AddrInUse,
+ wasi::ERRNO_NOENT => NotFound,
+ wasi::ERRNO_INTR => Interrupted,
+ wasi::ERRNO_INVAL => InvalidInput,
+ wasi::ERRNO_TIMEDOUT => TimedOut,
+ wasi::ERRNO_EXIST => AlreadyExists,
+ wasi::ERRNO_AGAIN => WouldBlock,
_ => Other,
}
}
@@ -116,16 +111,13 @@
pub fn hashmap_random_keys() -> (u64, u64) {
let mut ret = (0u64, 0u64);
unsafe {
- let base = &mut ret as *mut (u64, u64) as *mut core::ffi::c_void;
+ let base = &mut ret as *mut (u64, u64) as *mut u8;
let len = mem::size_of_val(&ret);
- let ret = wasi::raw::__wasi_random_get(base, len);
- if ret != 0 {
- panic!("__wasi_random_get failure")
- }
+ wasi::random_get(base, len).expect("random_get failure");
}
return ret
}
fn err2io(err: wasi::Error) -> std_io::Error {
- std_io::Error::from_raw_os_error(err.get() as i32)
+ std_io::Error::from_raw_os_error(err.raw_error().into())
}
diff --git a/src/libstd/sys/wasi/stdio.rs b/src/libstd/sys/wasi/stdio.rs
index 1d57b99..1d53884 100644
--- a/src/libstd/sys/wasi/stdio.rs
+++ b/src/libstd/sys/wasi/stdio.rs
@@ -2,8 +2,6 @@
use crate::mem::ManuallyDrop;
use crate::sys::fd::WasiFd;
-use ::wasi::wasi_unstable as wasi;
-
pub struct Stdin;
pub struct Stdout;
pub struct Stderr;
@@ -18,8 +16,11 @@
}
pub fn read_vectored(&self, data: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
- ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDIN_FD) })
- .read(data)
+ ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).read(data)
+ }
+
+ pub fn as_raw_fd(&self) -> u32 {
+ 0
}
}
@@ -33,13 +34,16 @@
}
pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
- ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDOUT_FD) })
- .write(data)
+ ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data)
}
pub fn flush(&self) -> io::Result<()> {
Ok(())
}
+
+ pub fn as_raw_fd(&self) -> u32 {
+ 1
+ }
}
impl Stderr {
@@ -52,13 +56,16 @@
}
pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
- ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDERR_FD) })
- .write(data)
+ ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data)
}
pub fn flush(&self) -> io::Result<()> {
Ok(())
}
+
+ pub fn as_raw_fd(&self) -> u32 {
+ 2
+ }
}
impl io::Write for Stderr {
@@ -74,7 +81,7 @@
pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
pub fn is_ebadf(err: &io::Error) -> bool {
- err.raw_os_error() == Some(wasi::EBADF.get() as i32)
+ err.raw_os_error() == Some(wasi::ERRNO_BADF.into())
}
pub fn panic_output() -> Option<impl io::Write> {
diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs
index 6ce4142..0986759 100644
--- a/src/libstd/sys/wasi/thread.rs
+++ b/src/libstd/sys/wasi/thread.rs
@@ -4,22 +4,18 @@
use crate::sys::{unsupported, Void};
use crate::time::Duration;
-use ::wasi::wasi_unstable as wasi;
-
pub struct Thread(Void);
pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
impl Thread {
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
- pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>)
- -> io::Result<Thread>
- {
+ pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>) -> io::Result<Thread> {
unsupported()
}
pub fn yield_now() {
- let ret = wasi::sched_yield();
+ let ret = unsafe { wasi::sched_yield() };
debug_assert_eq!(ret, Ok(()));
}
@@ -33,32 +29,30 @@
const USERDATA: wasi::Userdata = 0x0123_45678;
- let clock = wasi::raw::__wasi_subscription_u_clock_t {
- identifier: 0,
- clock_id: wasi::CLOCK_MONOTONIC,
+ let clock = wasi::SubscriptionClock {
+ id: wasi::CLOCKID_MONOTONIC,
timeout: nanos as u64,
precision: 0,
flags: 0,
};
- let in_ = [wasi::Subscription {
+ let in_ = wasi::Subscription {
userdata: USERDATA,
- type_: wasi::EVENTTYPE_CLOCK,
- u: wasi::raw::__wasi_subscription_u { clock: clock },
- }];
- let (res, event) = unsafe {
- let mut out: [wasi::Event; 1] = mem::zeroed();
- let res = wasi::poll_oneoff(&in_, &mut out);
- (res, out[0])
+ r#type: wasi::EVENTTYPE_CLOCK,
+ u: wasi::SubscriptionU { clock },
};
- match (res, event) {
- (Ok(1), wasi::Event {
- userdata: USERDATA,
- error: 0,
- type_: wasi::EVENTTYPE_CLOCK,
- ..
- }) => {}
- _ => panic!("thread::sleep(): unexpected result of poll_oneoff"),
+ unsafe {
+ let mut event: wasi::Event = mem::zeroed();
+ let res = wasi::poll_oneoff(&in_, &mut event, 1);
+ match (res, event) {
+ (
+ Ok(1),
+ wasi::Event {
+ userdata: USERDATA, error: 0, r#type: wasi::EVENTTYPE_CLOCK, ..
+ },
+ ) => {}
+ _ => panic!("thread::sleep(): unexpected result of poll_oneoff"),
+ }
}
}
@@ -69,6 +63,10 @@
pub mod guard {
pub type Guard = !;
- pub unsafe fn current() -> Option<Guard> { None }
- pub unsafe fn init() -> Option<Guard> { None }
+ pub unsafe fn current() -> Option<Guard> {
+ None
+ }
+ pub unsafe fn init() -> Option<Guard> {
+ None
+ }
}
diff --git a/src/libstd/sys/wasi/time.rs b/src/libstd/sys/wasi/time.rs
index 4394a22..80ec317 100644
--- a/src/libstd/sys/wasi/time.rs
+++ b/src/libstd/sys/wasi/time.rs
@@ -1,5 +1,4 @@
use crate::time::Duration;
-use ::wasi::wasi_unstable as wasi;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct Instant(Duration);
@@ -10,19 +9,18 @@
pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
fn current_time(clock: u32) -> Duration {
- let ts = wasi::clock_time_get(
- clock,
- 1, // precision... seems ignored though?
- ).unwrap();
- Duration::new(
- (ts / 1_000_000_000) as u64,
- (ts % 1_000_000_000) as u32,
- )
+ let ts = unsafe {
+ wasi::clock_time_get(
+ clock, 1, // precision... seems ignored though?
+ )
+ .unwrap()
+ };
+ Duration::new((ts / 1_000_000_000) as u64, (ts % 1_000_000_000) as u32)
}
impl Instant {
pub fn now() -> Instant {
- Instant(current_time(wasi::CLOCK_MONOTONIC))
+ Instant(current_time(wasi::CLOCKID_MONOTONIC))
}
pub const fn zero() -> Instant {
@@ -48,15 +46,14 @@
impl SystemTime {
pub fn now() -> SystemTime {
- SystemTime(current_time(wasi::CLOCK_REALTIME))
+ SystemTime(current_time(wasi::CLOCKID_REALTIME))
}
pub fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime {
SystemTime(Duration::from_nanos(ts))
}
- pub fn sub_time(&self, other: &SystemTime)
- -> Result<Duration, Duration> {
+ pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
}
diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs
index 32f4011..2f2f285 100644
--- a/src/libstd/sys/windows/net.rs
+++ b/src/libstd/sys/windows/net.rs
@@ -100,7 +100,7 @@
c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT) {
c::INVALID_SOCKET => {
match c::WSAGetLastError() {
- c::WSAEPROTOTYPE => {
+ c::WSAEPROTOTYPE | c::WSAEINVAL => {
match c::WSASocketW(fam, ty, 0, ptr::null_mut(), 0,
c::WSA_FLAG_OVERLAPPED) {
c::INVALID_SOCKET => Err(last_error()),
@@ -199,7 +199,7 @@
c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT) {
c::INVALID_SOCKET => {
match c::WSAGetLastError() {
- c::WSAEPROTOTYPE => {
+ c::WSAEPROTOTYPE | c::WSAEINVAL => {
match c::WSASocketW(info.iAddressFamily,
info.iSocketType,
info.iProtocol,
diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml
index 085c176..8a00bcb 100644
--- a/src/libsyntax/Cargo.toml
+++ b/src/libsyntax/Cargo.toml
@@ -24,3 +24,4 @@
rustc_macros = { path = "../librustc_macros" }
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
rustc_error_codes = { path = "../librustc_error_codes" }
+rustc_session = { path = "../librustc_session" }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 512f43c..75ddf10 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -27,12 +27,11 @@
use crate::ptr::P;
use crate::source_map::{dummy_spanned, respan, Spanned};
use crate::token::{self, DelimToken};
-use crate::tokenstream::TokenStream;
+use crate::tokenstream::{TokenStream, TokenTree, DelimSpan};
use syntax_pos::symbol::{kw, sym, Symbol};
-use syntax_pos::{Span, DUMMY_SP, ExpnId};
+use syntax_pos::{Span, DUMMY_SP};
-use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::thin_vec::ThinVec;
@@ -40,6 +39,7 @@
use rustc_serialize::{self, Decoder, Encoder};
use rustc_macros::HashStable_Generic;
+use std::iter;
use std::fmt;
#[cfg(test)]
@@ -267,46 +267,7 @@
}
}
-// hack to ensure that we don't try to access the private parts of `NodeId` in this module
-mod node_id_inner {
- use rustc_index::vec::Idx;
- rustc_index::newtype_index! {
- pub struct NodeId {
- ENCODABLE = custom
- DEBUG_FORMAT = "NodeId({})"
- }
- }
-}
-
-pub use node_id_inner::NodeId;
-
-impl NodeId {
- pub fn placeholder_from_expn_id(expn_id: ExpnId) -> Self {
- NodeId::from_u32(expn_id.as_u32())
- }
-
- pub fn placeholder_to_expn_id(self) -> ExpnId {
- ExpnId::from_u32(self.as_u32())
- }
-}
-
-impl fmt::Display for NodeId {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Display::fmt(&self.as_u32(), f)
- }
-}
-
-impl rustc_serialize::UseSpecializedEncodable for NodeId {
- fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_u32(self.as_u32())
- }
-}
-
-impl rustc_serialize::UseSpecializedDecodable for NodeId {
- fn default_decode<D: Decoder>(d: &mut D) -> Result<NodeId, D::Error> {
- d.read_u32().map(NodeId::from_u32)
- }
-}
+pub use rustc_session::node_id::NodeId;
/// `NodeId` used to represent the root of the crate.
pub const CRATE_NODE_ID: NodeId = NodeId::from_u32_const(0);
@@ -469,9 +430,7 @@
pub rhs_ty: P<Ty>,
}
-/// The set of `MetaItem`s that define the compilation environment of the crate,
-/// used to drive conditional compilation.
-pub type CrateConfig = FxHashSet<(Name, Option<Symbol>)>;
+pub use rustc_session::parse::CrateConfig;
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Crate {
@@ -1372,34 +1331,89 @@
Movable,
}
-/// Represents a macro invocation. The `Path` indicates which macro
-/// is being invoked, and the vector of token-trees contains the source
-/// of the macro invocation.
-///
-/// N.B., the additional ident for a `macro_rules`-style macro is actually
-/// stored in the enclosing item.
+/// Represents a macro invocation. The `path` indicates which macro
+/// is being invoked, and the `args` are arguments passed to it.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Mac {
pub path: Path,
- pub delim: MacDelimiter,
- pub tts: TokenStream,
- pub span: Span,
+ pub args: P<MacArgs>,
pub prior_type_ascription: Option<(Span, bool)>,
}
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
+impl Mac {
+ pub fn span(&self) -> Span {
+ self.path.span.to(self.args.span().unwrap_or(self.path.span))
+ }
+}
+
+/// Arguments passed to an attribute or a function-like macro.
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+pub enum MacArgs {
+ /// No arguments - `#[attr]`.
+ Empty,
+ /// Delimited arguments - `#[attr()/[]/{}]` or `mac!()/[]/{}`.
+ Delimited(DelimSpan, MacDelimiter, TokenStream),
+ /// Arguments of a key-value attribute - `#[attr = "value"]`.
+ Eq(
+ /// Span of the `=` token.
+ Span,
+ /// Token stream of the "value".
+ TokenStream,
+ ),
+}
+
+impl MacArgs {
+ pub fn delim(&self) -> DelimToken {
+ match self {
+ MacArgs::Delimited(_, delim, _) => delim.to_token(),
+ MacArgs::Empty | MacArgs::Eq(..) => token::NoDelim,
+ }
+ }
+
+ pub fn span(&self) -> Option<Span> {
+ match *self {
+ MacArgs::Empty => None,
+ MacArgs::Delimited(dspan, ..) => Some(dspan.entire()),
+ MacArgs::Eq(eq_span, ref tokens) => Some(eq_span.to(tokens.span().unwrap_or(eq_span))),
+ }
+ }
+
+ /// Tokens inside the delimiters or after `=`.
+ /// Proc macros see these tokens, for example.
+ pub fn inner_tokens(&self) -> TokenStream {
+ match self {
+ MacArgs::Empty => TokenStream::default(),
+ MacArgs::Delimited(.., tokens) |
+ MacArgs::Eq(.., tokens) => tokens.clone(),
+ }
+ }
+
+ /// Tokens together with the delimiters or `=`.
+ /// Use of this method generally means that something suboptimal or hacky is happening.
+ pub fn outer_tokens(&self) -> TokenStream {
+ match *self {
+ MacArgs::Empty => TokenStream::default(),
+ MacArgs::Delimited(dspan, delim, ref tokens) =>
+ TokenTree::Delimited(dspan, delim.to_token(), tokens.clone()).into(),
+ MacArgs::Eq(eq_span, ref tokens) => iter::once(TokenTree::token(token::Eq, eq_span))
+ .chain(tokens.trees()).collect(),
+ }
+ }
+
+ /// Whether a macro with these arguments needs a semicolon
+ /// when used as a standalone item or statement.
+ pub fn need_semicolon(&self) -> bool {
+ !matches!(self, MacArgs::Delimited(_, MacDelimiter::Brace ,_))
+ }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
pub enum MacDelimiter {
Parenthesis,
Bracket,
Brace,
}
-impl Mac {
- pub fn stream(&self) -> TokenStream {
- self.tts.clone()
- }
-}
-
impl MacDelimiter {
crate fn to_token(self) -> DelimToken {
match self {
@@ -1408,22 +1422,25 @@
MacDelimiter::Brace => DelimToken::Brace,
}
}
+
+ pub fn from_token(delim: DelimToken) -> Option<MacDelimiter> {
+ match delim {
+ token::Paren => Some(MacDelimiter::Parenthesis),
+ token::Bracket => Some(MacDelimiter::Bracket),
+ token::Brace => Some(MacDelimiter::Brace),
+ token::NoDelim => None,
+ }
+ }
}
/// Represents a macro definition.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct MacroDef {
- pub tokens: TokenStream,
+ pub body: P<MacArgs>,
/// `true` if macro was defined with `macro_rules`.
pub legacy: bool,
}
-impl MacroDef {
- pub fn stream(&self) -> TokenStream {
- self.tokens.clone().into()
- }
-}
-
// Clippy uses Hash and PartialEq
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq, HashStable_Generic)]
pub enum StrStyle {
@@ -2323,7 +2340,7 @@
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
pub struct AttrItem {
pub path: Path,
- pub tokens: TokenStream,
+ pub args: MacArgs,
}
/// Metadata associated with an item.
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index 29eff5c..079a0f6 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -10,7 +10,7 @@
use crate::ast;
use crate::ast::{AttrItem, AttrId, AttrKind, AttrStyle, Name, Ident, Path, PathSegment};
-use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem};
+use crate::ast::{MacArgs, MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem};
use crate::ast::{Lit, LitKind, Expr, Item, Local, Stmt, StmtKind, GenericParam};
use crate::mut_visit::visit_clobber;
use crate::source_map::{BytePos, Spanned};
@@ -198,7 +198,7 @@
pub fn is_word(&self) -> bool {
if let AttrKind::Normal(item) = &self.kind {
- item.tokens.is_empty()
+ matches!(item.args, MacArgs::Empty)
} else {
false
}
@@ -278,17 +278,9 @@
impl AttrItem {
pub fn meta(&self, span: Span) -> Option<MetaItem> {
- let mut tokens = self.tokens.trees().peekable();
Some(MetaItem {
path: self.path.clone(),
- kind: if let Some(kind) = MetaItemKind::from_tokens(&mut tokens) {
- if tokens.peek().is_some() {
- return None;
- }
- kind
- } else {
- return None;
- },
+ kind: MetaItemKind::from_mac_args(&self.args)?,
span,
})
}
@@ -362,8 +354,8 @@
AttrId(id)
}
-pub fn mk_attr(style: AttrStyle, path: Path, tokens: TokenStream, span: Span) -> Attribute {
- mk_attr_from_item(style, AttrItem { path, tokens }, span)
+pub fn mk_attr(style: AttrStyle, path: Path, args: MacArgs, span: Span) -> Attribute {
+ mk_attr_from_item(style, AttrItem { path, args }, span)
}
pub fn mk_attr_from_item(style: AttrStyle, item: AttrItem, span: Span) -> Attribute {
@@ -377,12 +369,12 @@
/// Returns an inner attribute with the given value and span.
pub fn mk_attr_inner(item: MetaItem) -> Attribute {
- mk_attr(AttrStyle::Inner, item.path, item.kind.tokens(item.span), item.span)
+ mk_attr(AttrStyle::Inner, item.path, item.kind.mac_args(item.span), item.span)
}
/// Returns an outer attribute with the given value and span.
pub fn mk_attr_outer(item: MetaItem) -> Attribute {
- mk_attr(AttrStyle::Outer, item.path, item.kind.tokens(item.span), item.span)
+ mk_attr(AttrStyle::Outer, item.path, item.kind.mac_args(item.span), item.span)
}
pub fn mk_doc_comment(style: AttrStyle, comment: Symbol, span: Span) -> Attribute {
@@ -520,7 +512,26 @@
}
impl MetaItemKind {
- pub fn token_trees_and_joints(&self, span: Span) -> Vec<TreeAndJoint> {
+ pub fn mac_args(&self, span: Span) -> MacArgs {
+ match self {
+ MetaItemKind::Word => MacArgs::Empty,
+ MetaItemKind::NameValue(lit) => MacArgs::Eq(span, lit.token_tree().into()),
+ MetaItemKind::List(list) => {
+ let mut tts = Vec::new();
+ for (i, item) in list.iter().enumerate() {
+ if i > 0 {
+ tts.push(TokenTree::token(token::Comma, span).into());
+ }
+ tts.extend(item.token_trees_and_joints())
+ }
+ MacArgs::Delimited(
+ DelimSpan::from_single(span), MacDelimiter::Parenthesis, TokenStream::new(tts)
+ )
+ }
+ }
+ }
+
+ fn token_trees_and_joints(&self, span: Span) -> Vec<TreeAndJoint> {
match *self {
MetaItemKind::Word => vec![],
MetaItemKind::NameValue(ref lit) => {
@@ -548,33 +559,8 @@
}
}
- // Premature conversions of `TokenTree`s to `TokenStream`s can hurt
- // performance. Do not use this function if `token_trees_and_joints()` can
- // be used instead.
- pub fn tokens(&self, span: Span) -> TokenStream {
- TokenStream::new(self.token_trees_and_joints(span))
- }
-
- fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItemKind>
- where I: Iterator<Item = TokenTree>,
- {
- let delimited = match tokens.peek().cloned() {
- Some(TokenTree::Token(token)) if token == token::Eq => {
- tokens.next();
- return if let Some(TokenTree::Token(token)) = tokens.next() {
- Lit::from_token(&token).ok().map(MetaItemKind::NameValue)
- } else {
- None
- };
- }
- Some(TokenTree::Delimited(_, delim, ref tts)) if delim == token::Paren => {
- tokens.next();
- tts.clone()
- }
- _ => return Some(MetaItemKind::Word),
- };
-
- let mut tokens = delimited.into_trees().peekable();
+ fn list_from_tokens(tokens: TokenStream) -> Option<MetaItemKind> {
+ let mut tokens = tokens.into_trees().peekable();
let mut result = Vec::new();
while let Some(..) = tokens.peek() {
let item = NestedMetaItem::from_tokens(&mut tokens)?;
@@ -586,6 +572,47 @@
}
Some(MetaItemKind::List(result))
}
+
+ fn name_value_from_tokens(
+ tokens: &mut impl Iterator<Item = TokenTree>,
+ ) -> Option<MetaItemKind> {
+ match tokens.next() {
+ Some(TokenTree::Token(token)) =>
+ Lit::from_token(&token).ok().map(MetaItemKind::NameValue),
+ _ => None,
+ }
+ }
+
+ fn from_mac_args(args: &MacArgs) -> Option<MetaItemKind> {
+ match args {
+ MacArgs::Delimited(_, MacDelimiter::Parenthesis, tokens) =>
+ MetaItemKind::list_from_tokens(tokens.clone()),
+ MacArgs::Delimited(..) => None,
+ MacArgs::Eq(_, tokens) => {
+ assert!(tokens.len() == 1);
+ MetaItemKind::name_value_from_tokens(&mut tokens.trees())
+ }
+ MacArgs::Empty => Some(MetaItemKind::Word),
+ }
+ }
+
+ fn from_tokens(
+ tokens: &mut iter::Peekable<impl Iterator<Item = TokenTree>>,
+ ) -> Option<MetaItemKind> {
+ match tokens.peek() {
+ Some(TokenTree::Delimited(_, token::Paren, inner_tokens)) => {
+ let inner_tokens = inner_tokens.clone();
+ tokens.next();
+ MetaItemKind::list_from_tokens(inner_tokens)
+ }
+ Some(TokenTree::Delimited(..)) => None,
+ Some(TokenTree::Token(Token { kind: token::Eq, .. })) => {
+ tokens.next();
+ MetaItemKind::name_value_from_tokens(tokens)
+ }
+ _ => Some(MetaItemKind::Word),
+ }
+ }
}
impl NestedMetaItem {
diff --git a/src/libsyntax/early_buffered_lints.rs b/src/libsyntax/early_buffered_lints.rs
index 5cc953b..2c32894 100644
--- a/src/libsyntax/early_buffered_lints.rs
+++ b/src/libsyntax/early_buffered_lints.rs
@@ -3,28 +3,28 @@
//! Since we cannot have a dependency on `librustc`, we implement some types here that are somewhat
//! redundant. Later, these types can be converted to types for use by the rest of the compiler.
-use crate::ast::NodeId;
-use syntax_pos::MultiSpan;
+use rustc_session::lint::FutureIncompatibleInfo;
+use rustc_session::declare_lint;
+pub use rustc_session::lint::BufferedEarlyLint;
-/// Since we cannot import `LintId`s from `rustc::lint`, we define some Ids here which can later be
-/// passed to `rustc::lint::Lint::from_parser_lint_id` to get a `rustc::lint::Lint`.
-pub enum BufferedEarlyLintId {
- IllFormedAttributeInput,
- MetaVariableMisuse,
- IncompleteInclude,
+declare_lint! {
+ pub ILL_FORMED_ATTRIBUTE_INPUT,
+ Deny,
+ "ill-formed attribute inputs that were previously accepted and used in practice",
+ @future_incompatible = FutureIncompatibleInfo {
+ reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
+ edition: None,
+ };
}
-/// Stores buffered lint info which can later be passed to `librustc`.
-pub struct BufferedEarlyLint {
- /// The span of code that we are linting on.
- pub span: MultiSpan,
+declare_lint! {
+ pub META_VARIABLE_MISUSE,
+ Allow,
+ "possible meta-variable misuse at macro definition"
+}
- /// The lint message.
- pub msg: String,
-
- /// The `NodeId` of the AST node that generated the lint.
- pub id: NodeId,
-
- /// A lint Id that can be passed to `rustc::lint::Lint::from_parser_lint_id`.
- pub lint_id: BufferedEarlyLintId,
+declare_lint! {
+ pub INCOMPLETE_INCLUDE,
+ Deny,
+ "trailing content in included file"
}
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 3d4a5d6..3617380 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -7,11 +7,13 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
test(attr(deny(warnings))))]
+#![feature(bool_to_option)]
#![feature(box_syntax)]
#![feature(const_fn)]
#![feature(const_transmute)]
#![feature(crate_visibility_modifier)]
#![feature(label_break_value)]
+#![feature(matches_macro)]
#![feature(nll)]
#![feature(try_trait)]
#![feature(slice_patterns)]
@@ -101,7 +103,7 @@
pub mod show_span;
pub use syntax_pos::edition;
pub use syntax_pos::symbol;
-pub mod sess;
+pub use rustc_session::parse as sess;
pub mod token;
pub mod tokenstream;
pub mod visit;
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index fbe2821..8889e5d 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -359,6 +359,26 @@
vis.visit_fn_decl(decl);
}
+// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
+pub fn visit_mac_args<T: MutVisitor>(args: &mut MacArgs, vis: &mut T) {
+ match args {
+ MacArgs::Empty => {}
+ MacArgs::Delimited(dspan, _delim, tokens) => {
+ visit_delim_span(dspan, vis);
+ vis.visit_tts(tokens);
+ }
+ MacArgs::Eq(eq_span, tokens) => {
+ vis.visit_span(eq_span);
+ vis.visit_tts(tokens);
+ }
+ }
+}
+
+pub fn visit_delim_span<T: MutVisitor>(dspan: &mut DelimSpan, vis: &mut T) {
+ vis.visit_span(&mut dspan.open);
+ vis.visit_span(&mut dspan.close);
+}
+
pub fn noop_flat_map_field_pattern<T: MutVisitor>(
mut fp: FieldPat,
vis: &mut T,
@@ -550,9 +570,9 @@
pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
let Attribute { kind, id: _, style: _, span } = attr;
match kind {
- AttrKind::Normal(AttrItem { path, tokens }) => {
+ AttrKind::Normal(AttrItem { path, args }) => {
vis.visit_path(path);
- vis.visit_tts(tokens);
+ visit_mac_args(args, vis);
}
AttrKind::DocComment(_) => {}
}
@@ -560,15 +580,14 @@
}
pub fn noop_visit_mac<T: MutVisitor>(mac: &mut Mac, vis: &mut T) {
- let Mac { path, delim: _, tts, span, prior_type_ascription: _ } = mac;
+ let Mac { path, args, prior_type_ascription: _ } = mac;
vis.visit_path(path);
- vis.visit_tts(tts);
- vis.visit_span(span);
+ visit_mac_args(args, vis);
}
pub fn noop_visit_macro_def<T: MutVisitor>(macro_def: &mut MacroDef, vis: &mut T) {
- let MacroDef { tokens, legacy: _ } = macro_def;
- vis.visit_tts(tokens);
+ let MacroDef { body, legacy: _ } = macro_def;
+ visit_mac_args(body, vis);
}
pub fn noop_visit_meta_list_item<T: MutVisitor>(li: &mut NestedMetaItem, vis: &mut T) {
@@ -682,9 +701,9 @@
token::NtIdent(ident, _is_raw) => vis.visit_ident(ident),
token::NtLifetime(ident) => vis.visit_ident(ident),
token::NtLiteral(expr) => vis.visit_expr(expr),
- token::NtMeta(AttrItem { path, tokens }) => {
+ token::NtMeta(AttrItem { path, args }) => {
vis.visit_path(path);
- vis.visit_tts(tokens);
+ visit_mac_args(args, vis);
}
token::NtPath(path) => vis.visit_path(path),
token::NtTT(tt) => vis.visit_tt(tt),
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 0d2e8dd..b2e8d85 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1,6 +1,6 @@
use crate::ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
use crate::ast::{SelfKind, GenericBound, TraitBoundModifier};
-use crate::ast::{Attribute, MacDelimiter, GenericArg};
+use crate::ast::{Attribute, GenericArg, MacArgs};
use crate::util::parser::{self, AssocOp, Fixity};
use crate::util::comments;
use crate::attr;
@@ -317,7 +317,7 @@
}
fn token_to_string_ext(token: &Token, convert_dollar_crate: bool) -> String {
- let convert_dollar_crate = if convert_dollar_crate { Some(token.span) } else { None };
+ let convert_dollar_crate = convert_dollar_crate.then_some(token.span);
token_kind_to_string_ext(&token.kind, convert_dollar_crate)
}
@@ -639,17 +639,22 @@
fn print_attr_item(&mut self, item: &ast::AttrItem, span: Span) {
self.ibox(0);
- match item.tokens.trees().next() {
- Some(TokenTree::Delimited(_, delim, tts)) => {
- self.print_mac_common(
- Some(MacHeader::Path(&item.path)), false, None, delim, tts, true, span
- );
- }
- tree => {
+ match &item.args {
+ MacArgs::Delimited(_, delim, tokens) => self.print_mac_common(
+ Some(MacHeader::Path(&item.path)),
+ false,
+ None,
+ delim.to_token(),
+ tokens.clone(),
+ true,
+ span,
+ ),
+ MacArgs::Empty | MacArgs::Eq(..) => {
self.print_path(&item.path, false, 0);
- if tree.is_some() {
+ if let MacArgs::Eq(_, tokens) = &item.args {
self.space();
- self.print_tts(item.tokens.clone(), true);
+ self.word_space("=");
+ self.print_tts(tokens.clone(), true);
}
}
}
@@ -1097,9 +1102,8 @@
}
ast::ForeignItemKind::Macro(ref m) => {
self.print_mac(m);
- match m.delim {
- MacDelimiter::Brace => {},
- _ => self.s.word(";")
+ if m.args.need_semicolon() {
+ self.s.word(";");
}
}
}
@@ -1361,9 +1365,8 @@
}
ast::ItemKind::Mac(ref mac) => {
self.print_mac(mac);
- match mac.delim {
- MacDelimiter::Brace => {}
- _ => self.s.word(";"),
+ if mac.args.need_semicolon() {
+ self.s.word(";");
}
}
ast::ItemKind::MacroDef(ref macro_def) => {
@@ -1377,8 +1380,8 @@
Some(MacHeader::Keyword(kw)),
has_bang,
Some(item.ident),
- DelimToken::Brace,
- macro_def.stream(),
+ macro_def.body.delim(),
+ macro_def.body.inner_tokens(),
true,
item.span,
);
@@ -1578,9 +1581,8 @@
}
ast::TraitItemKind::Macro(ref mac) => {
self.print_mac(mac);
- match mac.delim {
- MacDelimiter::Brace => {}
- _ => self.s.word(";"),
+ if mac.args.need_semicolon() {
+ self.s.word(";");
}
}
}
@@ -1608,9 +1610,8 @@
}
ast::ImplItemKind::Macro(ref mac) => {
self.print_mac(mac);
- match mac.delim {
- MacDelimiter::Brace => {}
- _ => self.s.word(";"),
+ if mac.args.need_semicolon() {
+ self.s.word(";");
}
}
}
@@ -1775,10 +1776,10 @@
Some(MacHeader::Path(&m.path)),
true,
None,
- m.delim.to_token(),
- m.stream(),
+ m.args.delim(),
+ m.args.inner_tokens(),
true,
- m.span,
+ m.span(),
);
}
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index 6a0523d..491b9a9 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -225,6 +225,14 @@
self.0.len()
}
+ pub fn span(&self) -> Option<Span> {
+ match &**self.0 {
+ [] => None,
+ [(tt, _)] => Some(tt.span()),
+ [(tt_start, _), .., (tt_end, _)] => Some(tt_start.span().to(tt_end.span())),
+ }
+ }
+
pub fn from_streams(mut streams: SmallVec<[TokenStream; 2]>) -> TokenStream {
match streams.len() {
0 => TokenStream::default(),
diff --git a/src/libsyntax/util/lev_distance.rs b/src/libsyntax/util/lev_distance.rs
index 4127a8c..efb3c23 100644
--- a/src/libsyntax/util/lev_distance.rs
+++ b/src/libsyntax/util/lev_distance.rs
@@ -77,6 +77,6 @@
if let Some(candidate) = case_insensitive_match {
Some(candidate) // exact case insensitive match has a higher priority
} else {
- if let Some((candidate, _)) = levenstein_match { Some(candidate) } else { None }
+ levenstein_match.map(|(candidate, _)| candidate)
}
}
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 5ff337f..4ee09b4 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -841,11 +841,19 @@
pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) {
match attr.kind {
- AttrKind::Normal(ref item) => visitor.visit_tts(item.tokens.clone()),
+ AttrKind::Normal(ref item) => walk_mac_args(visitor, &item.args),
AttrKind::DocComment(_) => {}
}
}
+pub fn walk_mac_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a MacArgs) {
+ match args {
+ MacArgs::Empty => {}
+ MacArgs::Delimited(_dspan, _delim, tokens) => visitor.visit_tts(tokens.clone()),
+ MacArgs::Eq(_eq_span, tokens) => visitor.visit_tts(tokens.clone()),
+ }
+}
+
pub fn walk_tt<'a, V: Visitor<'a>>(visitor: &mut V, tt: TokenTree) {
match tt {
TokenTree::Token(token) => visitor.visit_token(token),
diff --git a/src/libsyntax_expand/base.rs b/src/libsyntax_expand/base.rs
index 50b69f1..a4449ca 100644
--- a/src/libsyntax_expand/base.rs
+++ b/src/libsyntax_expand/base.rs
@@ -924,7 +924,6 @@
}
pub fn source_map(&self) -> &'a SourceMap { self.parse_sess.source_map() }
pub fn parse_sess(&self) -> &'a ParseSess { self.parse_sess }
- pub fn cfg(&self) -> &ast::CrateConfig { &self.parse_sess.config }
pub fn call_site(&self) -> Span {
self.current_expansion.id.expn_data().call_site
}
diff --git a/src/libsyntax_expand/expand.rs b/src/libsyntax_expand/expand.rs
index a6ced14..9bfedb3 100644
--- a/src/libsyntax_expand/expand.rs
+++ b/src/libsyntax_expand/expand.rs
@@ -11,7 +11,7 @@
use rustc_parse::parser::Parser;
use rustc_parse::validate_attr;
use syntax::ast::{self, AttrItem, Block, Ident, LitKind, NodeId, PatKind, Path};
-use syntax::ast::{MacStmtStyle, StmtKind, ItemKind};
+use syntax::ast::{MacArgs, MacStmtStyle, StmtKind, ItemKind};
use syntax::attr::{self, HasAttrs, is_builtin_attr};
use syntax::source_map::respan;
use syntax::feature_gate::{self, feature_err};
@@ -597,13 +597,13 @@
InvocationKind::Bang { mac, .. } => match ext {
SyntaxExtensionKind::Bang(expander) => {
self.gate_proc_macro_expansion_kind(span, fragment_kind);
- let tok_result = expander.expand(self.cx, span, mac.stream());
+ let tok_result = expander.expand(self.cx, span, mac.args.inner_tokens());
self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span)
}
SyntaxExtensionKind::LegacyBang(expander) => {
let prev = self.cx.current_expansion.prior_type_ascription;
self.cx.current_expansion.prior_type_ascription = mac.prior_type_ascription;
- let tok_result = expander.expand(self.cx, span, mac.stream());
+ let tok_result = expander.expand(self.cx, span, mac.args.inner_tokens());
let result = if let Some(result) = fragment_kind.make_from(tok_result) {
result
} else {
@@ -642,8 +642,11 @@
=> panic!("unexpected annotatable"),
})), DUMMY_SP).into();
let item = attr.unwrap_normal_item();
- let input = self.extract_proc_macro_attr_input(item.tokens, span);
- let tok_result = expander.expand(self.cx, span, input, item_tok);
+ if let MacArgs::Eq(..) = item.args {
+ self.cx.span_err(span, "key-value macro attributes are not supported");
+ }
+ let tok_result =
+ expander.expand(self.cx, span, item.args.inner_tokens(), item_tok);
self.parse_ast_fragment(tok_result, fragment_kind, &item.path, span)
}
SyntaxExtensionKind::LegacyAttr(expander) => {
@@ -687,23 +690,6 @@
}
}
- fn extract_proc_macro_attr_input(&self, tokens: TokenStream, span: Span) -> TokenStream {
- let mut trees = tokens.trees();
- match trees.next() {
- Some(TokenTree::Delimited(_, _, tts)) => {
- if trees.next().is_none() {
- return tts.into()
- }
- }
- Some(TokenTree::Token(..)) => {}
- None => return TokenStream::default(),
- }
- self.cx.span_err(span, "custom attribute invocations must be \
- of the form `#[foo]` or `#[foo(..)]`, the macro name must only be \
- followed by a delimiter token");
- TokenStream::default()
- }
-
fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
let kind = match item {
Annotatable::Item(item) => match &item.kind {
@@ -1560,7 +1546,7 @@
let meta = attr::mk_list_item(Ident::with_dummy_span(sym::doc), items);
*at = attr::Attribute {
kind: ast::AttrKind::Normal(
- AttrItem { path: meta.path, tokens: meta.kind.tokens(meta.span) },
+ AttrItem { path: meta.path, args: meta.kind.mac_args(meta.span) },
),
span: at.span,
id: at.id,
diff --git a/src/libsyntax_expand/mbe/macro_check.rs b/src/libsyntax_expand/mbe/macro_check.rs
index 837e04a..dfc8d69 100644
--- a/src/libsyntax_expand/mbe/macro_check.rs
+++ b/src/libsyntax_expand/mbe/macro_check.rs
@@ -107,7 +107,7 @@
use crate::mbe::{KleeneToken, TokenTree};
use syntax::ast::NodeId;
-use syntax::early_buffered_lints::BufferedEarlyLintId;
+use syntax::early_buffered_lints::META_VARIABLE_MISUSE;
use syntax::token::{DelimToken, Token, TokenKind};
use syntax::sess::ParseSess;
use syntax::symbol::{kw, sym};
@@ -623,5 +623,5 @@
}
fn buffer_lint(sess: &ParseSess, span: MultiSpan, node_id: NodeId, message: &str) {
- sess.buffer_lint(BufferedEarlyLintId::MetaVariableMisuse, span, node_id, message);
+ sess.buffer_lint(&META_VARIABLE_MISUSE, span, node_id, message);
}
diff --git a/src/libsyntax_expand/mbe/macro_rules.rs b/src/libsyntax_expand/mbe/macro_rules.rs
index b191527..e3c3655 100644
--- a/src/libsyntax_expand/mbe/macro_rules.rs
+++ b/src/libsyntax_expand/mbe/macro_rules.rs
@@ -318,8 +318,8 @@
let tt_spec = ast::Ident::new(sym::tt, def.span);
// Parse the macro_rules! invocation
- let body = match def.kind {
- ast::ItemKind::MacroDef(ref body) => body,
+ let (is_legacy, body) = match &def.kind {
+ ast::ItemKind::MacroDef(macro_def) => (macro_def.legacy, macro_def.body.inner_tokens()),
_ => unreachable!(),
};
@@ -338,7 +338,7 @@
mbe::TokenTree::MetaVarDecl(def.span, rhs_nm, tt_spec),
],
separator: Some(Token::new(
- if body.legacy { token::Semi } else { token::Comma },
+ if is_legacy { token::Semi } else { token::Comma },
def.span,
)),
kleene: mbe::KleeneToken::new(mbe::KleeneOp::OneOrMore, def.span),
@@ -350,7 +350,7 @@
DelimSpan::dummy(),
Lrc::new(mbe::SequenceRepetition {
tts: vec![mbe::TokenTree::token(
- if body.legacy { token::Semi } else { token::Comma },
+ if is_legacy { token::Semi } else { token::Comma },
def.span,
)],
separator: None,
@@ -360,7 +360,7 @@
),
];
- let argument_map = match parse(sess, body.stream(), &argument_gram, None, true) {
+ let argument_map = match parse(sess, body, &argument_gram, None, true) {
Success(m) => m,
Failure(token, msg) => {
let s = parse_failure_msg(&token);
@@ -435,7 +435,7 @@
// that is not lint-checked and trigger the "failed to process buffered lint here" bug.
valid &= macro_check::check_meta_variables(sess, ast::CRATE_NODE_ID, def.span, &lhses, &rhses);
- let (transparency, transparency_error) = attr::find_transparency(&def.attrs, body.legacy);
+ let (transparency, transparency_error) = attr::find_transparency(&def.attrs, is_legacy);
match transparency_error {
Some(TransparencyError::UnknownTransparency(value, span)) =>
diag.span_err(span, &format!("unknown macro transparency: `{}`", value)),
diff --git a/src/libsyntax_expand/mbe/transcribe.rs b/src/libsyntax_expand/mbe/transcribe.rs
index 4092d4b..a115766 100644
--- a/src/libsyntax_expand/mbe/transcribe.rs
+++ b/src/libsyntax_expand/mbe/transcribe.rs
@@ -30,13 +30,6 @@
}
}
-impl Marker {
- fn visit_delim_span(&mut self, dspan: &mut DelimSpan) {
- self.visit_span(&mut dspan.open);
- self.visit_span(&mut dspan.close);
- }
-}
-
/// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`).
enum Frame {
Delimited { forest: Lrc<mbe::Delimited>, idx: usize, span: DelimSpan },
@@ -271,7 +264,7 @@
// jump back out of the Delimited, pop the result_stack and add the new results back to
// the previous results (from outside the Delimited).
mbe::TokenTree::Delimited(mut span, delimited) => {
- marker.visit_delim_span(&mut span);
+ mut_visit::visit_delim_span(&mut span, &mut marker);
stack.push(Frame::Delimited { forest: delimited, idx: 0, span });
result_stack.push(mem::take(&mut result));
}
diff --git a/src/libsyntax_expand/parse/tests.rs b/src/libsyntax_expand/parse/tests.rs
index 08950dd..30e83c1 100644
--- a/src/libsyntax_expand/parse/tests.rs
+++ b/src/libsyntax_expand/parse/tests.rs
@@ -272,7 +272,7 @@
"foo!( fn main() { body } )".to_string(), &sess).unwrap();
let tts: Vec<_> = match expr.kind {
- ast::ExprKind::Mac(ref mac) => mac.stream().trees().collect(),
+ ast::ExprKind::Mac(ref mac) => mac.args.inner_tokens().trees().collect(),
_ => panic!("not a macro"),
};
diff --git a/src/libsyntax_expand/placeholders.rs b/src/libsyntax_expand/placeholders.rs
index 6cbe8c1..74ade1d 100644
--- a/src/libsyntax_expand/placeholders.rs
+++ b/src/libsyntax_expand/placeholders.rs
@@ -3,7 +3,6 @@
use syntax::ast;
use syntax::source_map::{DUMMY_SP, dummy_spanned};
-use syntax::tokenstream::TokenStream;
use syntax::mut_visit::*;
use syntax::ptr::P;
use syntax::ThinVec;
@@ -17,9 +16,7 @@
fn mac_placeholder() -> ast::Mac {
ast::Mac {
path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
- tts: TokenStream::default().into(),
- delim: ast::MacDelimiter::Brace,
- span: DUMMY_SP,
+ args: P(ast::MacArgs::Empty),
prior_type_ascription: None,
}
}
diff --git a/src/libsyntax_expand/proc_macro.rs b/src/libsyntax_expand/proc_macro.rs
index 099cf0a..520488c 100644
--- a/src/libsyntax_expand/proc_macro.rs
+++ b/src/libsyntax_expand/proc_macro.rs
@@ -1,7 +1,7 @@
use crate::base::{self, *};
use crate::proc_macro_server;
-use syntax::ast::{self, ItemKind};
+use syntax::ast::{self, ItemKind, MetaItemKind, NestedMetaItem};
use syntax::errors::{Applicability, FatalError};
use syntax::symbol::sym;
use syntax::token;
@@ -171,34 +171,71 @@
if !attr.has_name(sym::derive) {
return true;
}
- if !attr.is_meta_item_list() {
- cx.struct_span_err(attr.span, "malformed `derive` attribute input")
- .span_suggestion(
- attr.span,
- "missing traits to be derived",
- "#[derive(Trait1, Trait2, ...)]".to_owned(),
- Applicability::HasPlaceholders,
- ).emit();
- return false;
- }
- let parse_derive_paths = |attr: &ast::Attribute| {
- if attr.get_normal_item().tokens.is_empty() {
- return Ok(Vec::new());
+ // 1) First let's ensure that it's a meta item.
+ let nmis = match attr.meta_item_list() {
+ None => {
+ cx.struct_span_err(attr.span, "malformed `derive` attribute input")
+ .span_suggestion(
+ attr.span,
+ "missing traits to be derived",
+ "#[derive(Trait1, Trait2, ...)]".to_owned(),
+ Applicability::HasPlaceholders,
+ )
+ .emit();
+ return false;
}
- rustc_parse::parse_in_attr(cx.parse_sess, attr, |p| p.parse_derive_paths())
+ Some(x) => x,
};
- match parse_derive_paths(attr) {
- Ok(traits) => {
- result.extend(traits);
- true
- }
- Err(mut e) => {
- e.emit();
- false
- }
- }
+ let mut error_reported_filter_map = false;
+ let mut error_reported_map = false;
+ let traits = nmis
+ .into_iter()
+ // 2) Moreover, let's ensure we have a path and not `#[derive("foo")]`.
+ .filter_map(|nmi| match nmi {
+ NestedMetaItem::Literal(lit) => {
+ error_reported_filter_map = true;
+ cx.struct_span_err(lit.span, "expected path to a trait, found literal")
+ .help("for example, write `#[derive(Debug)]` for `Debug`")
+ .emit();
+ None
+ }
+ NestedMetaItem::MetaItem(mi) => Some(mi),
+ })
+ // 3) Finally, we only accept `#[derive($path_0, $path_1, ..)]`
+ // but not e.g. `#[derive($path_0 = "value", $path_1(abc))]`.
+ // In this case we can still at least determine that the user
+ // wanted this trait to be derived, so let's keep it.
+ .map(|mi| {
+ let mut traits_dont_accept = |title, action| {
+ error_reported_map = true;
+ let sp = mi.span.with_lo(mi.path.span.hi());
+ cx.struct_span_err(sp, title)
+ .span_suggestion(
+ sp,
+ action,
+ String::new(),
+ Applicability::MachineApplicable,
+ )
+ .emit();
+ };
+ match &mi.kind {
+ MetaItemKind::List(..) => traits_dont_accept(
+ "traits in `#[derive(...)]` don't accept arguments",
+ "remove the arguments",
+ ),
+ MetaItemKind::NameValue(..) => traits_dont_accept(
+ "traits in `#[derive(...)]` don't accept values",
+ "remove the value",
+ ),
+ MetaItemKind::Word => {}
+ }
+ mi.path
+ });
+
+ result.extend(traits);
+ !error_reported_filter_map && !error_reported_map
});
result
}
diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs
index c4f3c03..c788d06 100644
--- a/src/libsyntax_ext/assert.rs
+++ b/src/libsyntax_ext/assert.rs
@@ -6,7 +6,7 @@
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::symbol::{sym, Symbol};
-use syntax::tokenstream::{TokenStream, TokenTree};
+use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree};
use syntax_expand::base::*;
use syntax_pos::{Span, DUMMY_SP};
@@ -26,19 +26,19 @@
// `core::panic` and `std::panic` are different macros, so we use call-site
// context to pick up whichever is currently in scope.
let sp = cx.with_call_site_ctxt(sp);
+ let tokens = custom_message.unwrap_or_else(|| {
+ TokenStream::from(TokenTree::token(
+ TokenKind::lit(token::Str, Symbol::intern(&format!(
+ "assertion failed: {}",
+ pprust::expr_to_string(&cond_expr).escape_debug()
+ )), None),
+ DUMMY_SP,
+ ))
+ });
+ let args = P(MacArgs::Delimited(DelimSpan::from_single(sp), MacDelimiter::Parenthesis, tokens));
let panic_call = Mac {
path: Path::from_ident(Ident::new(sym::panic, sp)),
- tts: custom_message.unwrap_or_else(|| {
- TokenStream::from(TokenTree::token(
- TokenKind::lit(token::Str, Symbol::intern(&format!(
- "assertion failed: {}",
- pprust::expr_to_string(&cond_expr).escape_debug()
- )), None),
- DUMMY_SP,
- ))
- }).into(),
- delim: MacDelimiter::Parenthesis,
- span: sp,
+ args,
prior_type_ascription: None,
};
let if_expr = cx.expr_if(
diff --git a/src/libsyntax_ext/cmdline_attrs.rs b/src/libsyntax_ext/cmdline_attrs.rs
index 5c3009c..98cf8a3 100644
--- a/src/libsyntax_ext/cmdline_attrs.rs
+++ b/src/libsyntax_ext/cmdline_attrs.rs
@@ -16,7 +16,7 @@
);
let start_span = parser.token.span;
- let AttrItem { path, tokens } = panictry!(parser.parse_attr_item());
+ let AttrItem { path, args } = panictry!(parser.parse_attr_item());
let end_span = parser.token.span;
if parser.token != token::Eof {
parse_sess.span_diagnostic
@@ -24,7 +24,7 @@
continue;
}
- krate.attrs.push(mk_attr(AttrStyle::Inner, path, tokens, start_span.to(end_span)));
+ krate.attrs.push(mk_attr(AttrStyle::Inner, path, args, start_span.to(end_span)));
}
krate
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index b6bf2f8..5bd84b4 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -340,14 +340,12 @@
fn find_type_parameters(
ty: &ast::Ty,
ty_param_names: &[ast::Name],
- span: Span,
cx: &ExtCtxt<'_>,
) -> Vec<P<ast::Ty>> {
use syntax::visit;
struct Visitor<'a, 'b> {
cx: &'a ExtCtxt<'b>,
- span: Span,
ty_param_names: &'a [ast::Name],
types: Vec<P<ast::Ty>>,
}
@@ -366,18 +364,11 @@
}
fn visit_mac(&mut self, mac: &ast::Mac) {
- let span = mac.span.with_ctxt(self.span.ctxt());
- self.cx.span_err(span, "`derive` cannot be used on items with type macros");
+ self.cx.span_err(mac.span(), "`derive` cannot be used on items with type macros");
}
}
- let mut visitor = Visitor {
- ty_param_names,
- types: Vec::new(),
- span,
- cx,
- };
-
+ let mut visitor = Visitor { cx, ty_param_names, types: Vec::new() };
visit::Visitor::visit_ty(&mut visitor, ty);
visitor.types
@@ -605,7 +596,7 @@
.collect();
for field_ty in field_tys {
- let tys = find_type_parameters(&field_ty, &ty_param_names, self.span, cx);
+ let tys = find_type_parameters(&field_ty, &ty_param_names, cx);
for ty in tys {
// if we have already handled this type, skip it
diff --git a/src/libsyntax_ext/format_foreign.rs b/src/libsyntax_ext/format_foreign.rs
index 3d4f827..0d1d292 100644
--- a/src/libsyntax_ext/format_foreign.rs
+++ b/src/libsyntax_ext/format_foreign.rs
@@ -95,12 +95,12 @@
};
// Has a special form in Rust for numbers.
- let fill = if c_zero { Some("0") } else { None };
+ let fill = c_zero.then_some("0");
- let align = if c_left { Some("<") } else { None };
+ let align = c_left.then_some("<");
// Rust doesn't have an equivalent to the `' '` flag.
- let sign = if c_plus { Some("+") } else { None };
+ let sign = c_plus.then_some("+");
// Not *quite* the same, depending on the type...
let alt = c_alt;
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index b9287d2..55c7f3f 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -3,6 +3,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
#![feature(decl_macro)]
#![feature(nll)]
diff --git a/src/libsyntax_ext/source_util.rs b/src/libsyntax_ext/source_util.rs
index 3d27af2..4aab68d 100644
--- a/src/libsyntax_ext/source_util.rs
+++ b/src/libsyntax_ext/source_util.rs
@@ -5,7 +5,7 @@
use syntax::symbol::Symbol;
use syntax::token;
use syntax::tokenstream::TokenStream;
-use syntax::early_buffered_lints::BufferedEarlyLintId;
+use syntax::early_buffered_lints::INCOMPLETE_INCLUDE;
use syntax_expand::panictry;
use syntax_expand::base::{self, *};
@@ -101,7 +101,7 @@
let r = panictry!(self.p.parse_expr());
if self.p.token != token::Eof {
self.p.sess.buffer_lint(
- BufferedEarlyLintId::IncompleteInclude,
+ &INCOMPLETE_INCLUDE,
self.p.token.span,
ast::CRATE_NODE_ID,
"include macro expected single expression in source",
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 7d43c3c..e8f7a12 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -121,6 +121,7 @@
abi_vectorcall,
abi_x86_interrupt,
aborts,
+ add_with_overflow,
advanced_slice_patterns,
adx_target_feature,
alias,
@@ -171,12 +172,16 @@
box_patterns,
box_syntax,
braced_empty_structs,
+ bswap,
+ bitreverse,
C,
+ caller_location,
cdylib,
cfg,
cfg_attr,
cfg_attr_multi,
cfg_doctest,
+ cfg_sanitize,
cfg_target_feature,
cfg_target_has_atomic,
cfg_target_thread_local,
@@ -208,6 +213,7 @@
const_indexing,
const_in_array_repeat_expressions,
const_let,
+ const_mut_refs,
const_panic,
const_raw_ptr_deref,
const_raw_ptr_to_usize_cast,
@@ -225,6 +231,11 @@
crate_name,
crate_type,
crate_visibility_modifier,
+ ctpop,
+ cttz,
+ cttz_nonzero,
+ ctlz,
+ ctlz_nonzero,
custom_attribute,
custom_derive,
custom_inner_attributes,
@@ -279,6 +290,7 @@
Err,
Eq,
Equal,
+ enclosing_scope,
except,
exclusive_range_pattern,
exhaustive_integer_patterns,
@@ -429,6 +441,7 @@
member_constraints,
message,
meta,
+ min_align_of,
min_const_fn,
min_const_unsafe_fn,
mips_target_feature,
@@ -438,11 +451,13 @@
more_struct_aliases,
move_val_init,
movbe_target_feature,
+ mul_with_overflow,
must_use,
naked,
naked_functions,
name,
needs_allocator,
+ needs_drop,
needs_panic_runtime,
negate_unsigned,
never,
@@ -518,6 +533,7 @@
poll_with_tls_context,
powerpc_target_feature,
precise_pointer_size_matching,
+ pref_align_of,
prelude,
prelude_import,
primitive,
@@ -534,6 +550,7 @@
proc_macro_non_items,
proc_macro_path_invoc,
profiler_runtime,
+ ptr_offset_from,
pub_restricted,
pushpop_unsafe,
quad_precision_float,
@@ -569,6 +586,8 @@
Return,
rhs,
rlib,
+ rotate_left,
+ rotate_right,
rt,
rtm_target_feature,
rust,
@@ -634,15 +653,21 @@
rust_eh_unwind_resume,
rust_oom,
rvalue_static_promotion,
+ sanitize,
sanitizer_runtime,
+ saturating_add,
+ saturating_sub,
_Self,
self_in_typedefs,
self_struct_ctor,
should_panic,
simd,
+ simd_extract,
simd_ffi,
+ simd_insert,
since,
size,
+ size_of,
slice_patterns,
slicing_syntax,
soft,
@@ -670,6 +695,7 @@
structural_match,
struct_variant,
sty,
+ sub_with_overflow,
suggestion,
target_feature,
target_has_atomic,
@@ -705,6 +731,8 @@
Ty,
ty,
type_alias_impl_trait,
+ type_id,
+ type_name,
TyCtxt,
TyKind,
type_alias_enum_variants,
@@ -717,6 +745,8 @@
u64,
u8,
unboxed_closures,
+ unchecked_shl,
+ unchecked_shr,
underscore_const_names,
underscore_imports,
underscore_lifetimes,
@@ -750,6 +780,9 @@
while_let,
windows,
windows_subsystem,
+ wrapping_add,
+ wrapping_sub,
+ wrapping_mul,
Yield,
}
}
@@ -837,12 +870,18 @@
impl fmt::Debug for Ident {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if self.is_raw_guess() {
+ write!(f, "r#")?;
+ }
write!(f, "{}{:?}", self.name, self.span.ctxt())
}
}
impl fmt::Display for Ident {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if self.is_raw_guess() {
+ write!(f, "r#")?;
+ }
fmt::Display::fmt(&self.name, f)
}
}
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 7647978..0097558 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -24,6 +24,7 @@
#![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))]
#![feature(rustc_private)]
#![feature(nll)]
+#![feature(bool_to_option)]
#![feature(set_stdio)]
#![feature(panic_unwind)]
#![feature(staged_api)]
@@ -562,11 +563,7 @@
None
};
- let start = if report_time {
- Some(Instant::now())
- } else {
- None
- };
+ let start = report_time.then(Instant::now);
let result = catch_unwind(AssertUnwindSafe(testfn));
let exec_time = start.map(|start| {
let duration = start.elapsed();
@@ -597,11 +594,7 @@
let args = env::args().collect::<Vec<_>>();
let current_exe = &args[0];
- let start = if report_time {
- Some(Instant::now())
- } else {
- None
- };
+ let start = report_time.then(Instant::now);
let output = match Command::new(current_exe)
.env(SECONDARY_TEST_INVOKER_VAR, desc.name.as_slice())
.output() {
diff --git a/src/llvm-project b/src/llvm-project
index de1a7db..2cb4100 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit de1a7dbf6c6b34f56e65732d45970ff27a8e84bf
+Subproject commit 2cb41005ed5c4747b10d2bf01d8779d3bb4ae32d
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index a116ed2..6698e5d 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -101,11 +101,13 @@
}
extern "C" LLVMPassRef LLVMRustCreateMemorySanitizerPass(int TrackOrigins, bool Recover) {
-#if LLVM_VERSION_GE(8, 0)
+#if LLVM_VERSION_GE(9, 0)
const bool CompileKernel = false;
return wrap(createMemorySanitizerLegacyPassPass(
MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel}));
+#elif LLVM_VERSION_GE(8, 0)
+ return wrap(createMemorySanitizerLegacyPassPass(TrackOrigins, Recover));
#else
return wrap(createMemorySanitizerPass(TrackOrigins, Recover));
#endif
@@ -393,7 +395,8 @@
bool TrapUnreachable,
bool Singlethread,
bool AsmComments,
- bool EmitStackSizeSection) {
+ bool EmitStackSizeSection,
+ bool RelaxELFRelocations) {
auto OptLevel = fromRust(RustOptLevel);
auto RM = fromRust(RustReloc);
@@ -418,6 +421,7 @@
Options.MCOptions.AsmVerbose = AsmComments;
Options.MCOptions.PreserveAsmComments = AsmComments;
Options.MCOptions.ABIName = ABIStr;
+ Options.RelaxELFRelocations = RelaxELFRelocations;
if (TrapUnreachable) {
// Tell LLVM to codegen `unreachable` into an explicit trap instruction.
@@ -449,9 +453,7 @@
LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel,
bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO,
const char* PGOGenPath, const char* PGOUsePath) {
-#if LLVM_VERSION_GE(7, 0)
unwrap(PMBR)->MergeFunctions = MergeFunctions;
-#endif
unwrap(PMBR)->SLPVectorize = SLPVectorize;
unwrap(PMBR)->OptLevel = fromRust(OptLevel);
unwrap(PMBR)->LoopVectorize = LoopVectorize;
@@ -558,12 +560,8 @@
return LLVMRustResult::Failure;
}
-#if LLVM_VERSION_GE(7, 0)
buffer_ostream BOS(OS);
unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, false);
-#else
- unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
-#endif
PM->run(*unwrap(M));
// Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
@@ -660,46 +658,11 @@
}
};
-class RustPrintModulePass : public ModulePass {
- raw_ostream* OS;
- DemangleFn Demangle;
-public:
- static char ID;
- RustPrintModulePass() : ModulePass(ID), OS(nullptr), Demangle(nullptr) {}
- RustPrintModulePass(raw_ostream &OS, DemangleFn Demangle)
- : ModulePass(ID), OS(&OS), Demangle(Demangle) {}
-
- bool runOnModule(Module &M) override {
- RustAssemblyAnnotationWriter AW(Demangle);
-
- M.print(*OS, &AW, false);
-
- return false;
- }
-
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesAll();
- }
-
- static StringRef name() { return "RustPrintModulePass"; }
-};
-
} // namespace
-namespace llvm {
- void initializeRustPrintModulePassPass(PassRegistry&);
-}
-
-char RustPrintModulePass::ID = 0;
-INITIALIZE_PASS(RustPrintModulePass, "print-rust-module",
- "Print rust module to stderr", false, false)
-
extern "C" LLVMRustResult
-LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
- const char *Path, DemangleFn Demangle) {
- llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
+LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) {
std::string ErrorInfo;
-
std::error_code EC;
raw_fd_ostream OS(Path, EC, sys::fs::F_None);
if (EC)
@@ -709,11 +672,9 @@
return LLVMRustResult::Failure;
}
+ RustAssemblyAnnotationWriter AAW(Demangle);
formatted_raw_ostream FOS(OS);
-
- PM->add(new RustPrintModulePass(FOS, Demangle));
-
- PM->run(*unwrap(M));
+ unwrap(M)->print(FOS, &AAW);
return LLVMRustResult::Success;
}
@@ -847,9 +808,7 @@
StringMap<FunctionImporter::ExportSetTy> ExportLists;
StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries;
-#if LLVM_VERSION_GE(7, 0)
LLVMRustThinLTOData() : Index(/* HaveGVs = */ false) {}
-#endif
};
// Just an argument to the `LLVMRustCreateThinLTOData` function below.
@@ -920,7 +879,6 @@
// combined index
//
// This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
-#if LLVM_VERSION_GE(7, 0)
auto deadIsPrevailing = [&](GlobalValue::GUID G) {
return PrevailingType::Unknown;
};
@@ -933,9 +891,6 @@
#else
computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols, deadIsPrevailing);
#endif
-#else
- computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols);
-#endif
ComputeCrossModuleImport(
Ret->Index,
Ret->ModuleToDefinedGVSummaries,
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index e6c45b8..720928e 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -88,11 +88,7 @@
}
extern "C" unsigned int LLVMRustGetInstructionCount(LLVMModuleRef M) {
-#if LLVM_VERSION_GE(7, 0)
return unwrap(M)->getInstructionCount();
-#else
- report_fatal_error("Module::getInstructionCount not available before LLVM 7");
-#endif
}
extern "C" void LLVMRustSetLastError(const char *Err) {
@@ -133,8 +129,9 @@
}
extern "C" LLVMValueRef
-LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, LLVMTypeRef Ty) {
- return wrap(unwrap(M)->getOrInsertGlobal(Name, unwrap(Ty)));
+LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
+ StringRef NameRef(Name, NameLen);
+ return wrap(unwrap(M)->getOrInsertGlobal(NameRef, unwrap(Ty)));
}
extern "C" LLVMValueRef
@@ -761,14 +758,10 @@
LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
LLVMMetadataRef Elements, const char *UniqueId) {
-#if LLVM_VERSION_GE(7, 0)
return wrap(Builder->createVariantPart(
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
DINodeArray(unwrapDI<MDTuple>(Elements)), UniqueId));
-#else
- abort();
-#endif
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
@@ -787,7 +780,6 @@
const char *Name, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
-#if LLVM_VERSION_GE(7, 0)
llvm::ConstantInt* D = nullptr;
if (Discriminant) {
D = unwrap<llvm::ConstantInt>(Discriminant);
@@ -796,12 +788,6 @@
unwrapDI<DIFile>(File), LineNo,
SizeInBits, AlignInBits, OffsetInBits, D,
fromRust(Flags), unwrapDI<DIType>(Ty)));
-#else
- return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope), Name,
- unwrapDI<DIFile>(File), LineNo,
- SizeInBits, AlignInBits, OffsetInBits,
- fromRust(Flags), unwrapDI<DIType>(Ty)));
-#endif
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
@@ -911,18 +897,10 @@
LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
uint32_t AlignInBits, LLVMMetadataRef Elements,
LLVMMetadataRef ClassTy, bool IsScoped) {
-#if LLVM_VERSION_GE(7, 0)
return wrap(Builder->createEnumerationType(
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
unwrapDI<DIType>(ClassTy), "", IsScoped));
-#else
- // Ignore IsScoped on older LLVM.
- return wrap(Builder->createEnumerationType(
- unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
- SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
- unwrapDI<DIType>(ClassTy), ""));
-#endif
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
@@ -1275,34 +1253,20 @@
LLVMValueRef Dst, unsigned DstAlign,
LLVMValueRef Src, unsigned SrcAlign,
LLVMValueRef Size, bool IsVolatile) {
-#if LLVM_VERSION_GE(7, 0)
return wrap(unwrap(B)->CreateMemCpy(
unwrap(Dst), DstAlign,
unwrap(Src), SrcAlign,
unwrap(Size), IsVolatile));
-#else
- unsigned Align = std::min(DstAlign, SrcAlign);
- return wrap(unwrap(B)->CreateMemCpy(
- unwrap(Dst), unwrap(Src),
- unwrap(Size), Align, IsVolatile));
-#endif
}
extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
LLVMValueRef Dst, unsigned DstAlign,
LLVMValueRef Src, unsigned SrcAlign,
LLVMValueRef Size, bool IsVolatile) {
-#if LLVM_VERSION_GE(7, 0)
return wrap(unwrap(B)->CreateMemMove(
unwrap(Dst), DstAlign,
unwrap(Src), SrcAlign,
unwrap(Size), IsVolatile));
-#else
- unsigned Align = std::min(DstAlign, SrcAlign);
- return wrap(unwrap(B)->CreateMemMove(
- unwrap(Dst), unwrap(Src),
- unwrap(Size), Align, IsVolatile));
-#endif
}
extern "C" LLVMValueRef
@@ -1324,11 +1288,12 @@
}
extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
- const char *Name) {
+ const char *Name, size_t NameLen) {
Triple TargetTriple(unwrap(M)->getTargetTriple());
GlobalObject *GV = unwrap<GlobalObject>(V);
if (!TargetTriple.isOSBinFormatMachO()) {
- GV->setComdat(unwrap(M)->getOrInsertComdat(Name));
+ StringRef NameRef(Name, NameLen);
+ GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
}
}
diff --git a/src/test/codegen/align-enum.rs b/src/test/codegen/align-enum.rs
index 4241fce..72447fb 100644
--- a/src/test/codegen/align-enum.rs
+++ b/src/test/codegen/align-enum.rs
@@ -1,6 +1,5 @@
// compile-flags: -C no-prepopulate-passes
// ignore-tidy-linelength
-// min-llvm-version 7.0
#![crate_type = "lib"]
diff --git a/src/test/codegen/align-struct.rs b/src/test/codegen/align-struct.rs
index c0d6a0c..5e29032 100644
--- a/src/test/codegen/align-struct.rs
+++ b/src/test/codegen/align-struct.rs
@@ -1,6 +1,5 @@
// compile-flags: -C no-prepopulate-passes
// ignore-tidy-linelength
-// min-llvm-version 7.0
#![crate_type = "lib"]
diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs
index e0843f5..7d65ad1 100644
--- a/src/test/codegen/consts.rs
+++ b/src/test/codegen/consts.rs
@@ -1,6 +1,5 @@
// compile-flags: -C no-prepopulate-passes
// ignore-tidy-linelength
-// min-llvm-version 7.0
#![crate_type = "lib"]
diff --git a/src/test/codegen/gdb_debug_script_load.rs b/src/test/codegen/gdb_debug_script_load.rs
index 2e8dc7b..178269f 100644
--- a/src/test/codegen/gdb_debug_script_load.rs
+++ b/src/test/codegen/gdb_debug_script_load.rs
@@ -1,6 +1,8 @@
// ignore-tidy-linelength
// ignore-windows
// ignore-macos
+// ignore-wasm
+// ignore-emscripten
// compile-flags: -g -C no-prepopulate-passes
diff --git a/src/test/codegen/packed.rs b/src/test/codegen/packed.rs
index 3c8ff39..f3f5202 100644
--- a/src/test/codegen/packed.rs
+++ b/src/test/codegen/packed.rs
@@ -1,6 +1,5 @@
// ignore-tidy-linelength
// compile-flags: -C no-prepopulate-passes
-// min-llvm-version 7.0
#![crate_type = "lib"]
diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs
index 87f29f6..99f3464 100644
--- a/src/test/codegen/repeat-trusted-len.rs
+++ b/src/test/codegen/repeat-trusted-len.rs
@@ -1,6 +1,5 @@
// compile-flags: -O
// ignore-tidy-linelength
-// min-llvm-version 7.0
#![crate_type = "lib"]
diff --git a/src/test/codegen/set-discriminant-invalid.rs b/src/test/codegen/set-discriminant-invalid.rs
new file mode 100644
index 0000000..d9614f0
--- /dev/null
+++ b/src/test/codegen/set-discriminant-invalid.rs
@@ -0,0 +1,43 @@
+// compile-flags: -C opt-level=0
+#![crate_type = "lib"]
+
+pub enum ApiError {}
+#[allow(dead_code)]
+pub struct TokioError {
+ b: bool,
+}
+pub enum Error {
+ Api {
+ source: ApiError,
+ },
+ Ethereum,
+ Tokio {
+ source: TokioError,
+ },
+}
+struct Api;
+impl IntoError<Error> for Api
+{
+ type Source = ApiError;
+ // CHECK-LABEL: @into_error
+ // CHECK: llvm.trap()
+ // Also check the next two instructions to make sure we do not match against `trap`
+ // elsewhere in the code.
+ // CHECK-NEXT: load
+ // CHECK-NEXT: ret
+ #[no_mangle]
+ fn into_error(self, error: Self::Source) -> Error {
+ Error::Api {
+ source: (|v| v)(error),
+ }
+ }
+}
+
+pub trait IntoError<E>
+{
+ /// The underlying error
+ type Source;
+
+ /// Combine the information to produce the error
+ fn into_error(self, source: Self::Source) -> E;
+}
diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs
index 7b9b1ae..4e0abed 100644
--- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs
+++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs
@@ -1,5 +1,3 @@
-// min-llvm-version 7.0
-
// compile-flags: -C no-prepopulate-passes
#![crate_type = "lib"]
diff --git a/src/test/codegen/stores.rs b/src/test/codegen/stores.rs
index 64143ae..4ea003e 100644
--- a/src/test/codegen/stores.rs
+++ b/src/test/codegen/stores.rs
@@ -1,6 +1,5 @@
// compile-flags: -C no-prepopulate-passes
// ignore-tidy-linelength
-// min-llvm-version 7.0
#![crate_type = "lib"]
diff --git a/src/test/compile-fail/consts/const-fn-error.rs b/src/test/compile-fail/consts/const-fn-error.rs
index 1a4fc72..5d26059 100644
--- a/src/test/compile-fail/consts/const-fn-error.rs
+++ b/src/test/compile-fail/consts/const-fn-error.rs
@@ -6,7 +6,7 @@
let mut sum = 0;
for i in 0..x {
//~^ ERROR E0015
- //~| ERROR E0017
+ //~| ERROR E0658
//~| ERROR E0080
//~| ERROR E0744
//~| ERROR E0019
diff --git a/src/test/incremental/issue-61323.rs b/src/test/incremental/issue-61323.rs
new file mode 100644
index 0000000..448ce36
--- /dev/null
+++ b/src/test/incremental/issue-61323.rs
@@ -0,0 +1,15 @@
+// revisions: rpass cfail
+
+enum A {
+ //[cfail]~^ ERROR 3:1: 3:7: recursive type `A` has infinite size [E0072]
+ B(C),
+}
+
+#[cfg(rpass)]
+struct C(Box<A>);
+
+#[cfg(cfail)]
+struct C(A);
+//[cfail]~^ ERROR 12:1: 12:13: recursive type `C` has infinite size [E0072]
+
+fn main() {}
diff --git a/src/test/mir-opt/inline-closure-borrows-arg.rs b/src/test/mir-opt/inline-closure-borrows-arg.rs
index b5bfeef..768f495 100644
--- a/src/test/mir-opt/inline-closure-borrows-arg.rs
+++ b/src/test/mir-opt/inline-closure-borrows-arg.rs
@@ -21,8 +21,8 @@
// debug _t => _1;
// debug q => _2;
// let mut _0: i32;
-// let _3: [closure@HirId { owner: DefIndex(4), local_id: 31 }];
-// let mut _4: &[closure@HirId { owner: DefIndex(4), local_id: 31 }];
+// let _3: [closure@foo<T>::{{closure}}#0];
+// let mut _4: &[closure@foo<T>::{{closure}}#0];
// let mut _5: (&i32, &i32);
// let mut _6: &i32;
// let mut _7: &i32;
@@ -40,7 +40,7 @@
// }
// bb0: {
// ...
-// _3 = [closure@HirId { owner: DefIndex(4), local_id: 31 }];
+// _3 = [closure@foo::<T>::{{closure}}#0];
// ...
// _4 = &_3;
// ...
diff --git a/src/test/mir-opt/inline-closure-captures.rs b/src/test/mir-opt/inline-closure-captures.rs
index e73dbe4..e000a41 100644
--- a/src/test/mir-opt/inline-closure-captures.rs
+++ b/src/test/mir-opt/inline-closure-captures.rs
@@ -17,10 +17,10 @@
// debug t => _1;
// debug q => _2;
// let mut _0: (i32, T);
-// let _3: [closure@HirId { owner: DefIndex(4), local_id: 15 } q:&i32, t:&T];
+// let _3: [closure@foo<T>::{{closure}}#0 q:&i32, t:&T];
// let mut _4: &i32;
// let mut _5: &T;
-// let mut _6: &[closure@HirId { owner: DefIndex(4), local_id: 15 } q:&i32, t:&T];
+// let mut _6: &[closure@foo<T>::{{closure}}#0 q:&i32, t:&T];
// let mut _7: (i32,);
// let mut _8: i32;
// let mut _11: i32;
@@ -39,7 +39,7 @@
// _4 = &_2;
// ...
// _5 = &_1;
-// _3 = [closure@HirId { owner: DefIndex(4), local_id: 15 }] { q: move _4, t: move _5 };
+// _3 = [closure@foo::<T>::{{closure}}#0] { q: move _4, t: move _5 };
// ...
// _6 = &_3;
// ...
diff --git a/src/test/mir-opt/inline-closure.rs b/src/test/mir-opt/inline-closure.rs
index ddf027f..bd36e77 100644
--- a/src/test/mir-opt/inline-closure.rs
+++ b/src/test/mir-opt/inline-closure.rs
@@ -17,8 +17,8 @@
// debug _t => _1;
// debug q => _2;
// let mut _0: i32;
-// let _3: [closure@HirId { owner: DefIndex(4), local_id: 15 }];
-// let mut _4: &[closure@HirId { owner: DefIndex(4), local_id: 15 }];
+// let _3: [closure@foo<T>::{{closure}}#0];
+// let mut _4: &[closure@foo<T>::{{closure}}#0];
// let mut _5: (i32, i32);
// let mut _6: i32;
// let mut _7: i32;
@@ -33,7 +33,7 @@
// }
// bb0: {
// ...
-// _3 = [closure@HirId { owner: DefIndex(4), local_id: 15 }];
+// _3 = [closure@foo::<T>::{{closure}}#0];
// ...
// _4 = &_3;
// ...
diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs
index 96b848e..3299544 100644
--- a/src/test/mir-opt/retag.rs
+++ b/src/test/mir-opt/retag.rs
@@ -100,7 +100,7 @@
// }
// END rustc.main.EraseRegions.after.mir
// START rustc.main-{{closure}}.EraseRegions.after.mir
-// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(13), local_id: 72 }], _2: &i32) -> &i32 {
+// fn main::{{closure}}#0(_1: &[closure@main::{{closure}}#0], _2: &i32) -> &i32 {
// ...
// bb0: {
// Retag([fn entry] _1);
diff --git a/src/test/run-make-fulldeps/emit-stack-sizes/Makefile b/src/test/run-make-fulldeps/emit-stack-sizes/Makefile
index 604fc46..d270289 100644
--- a/src/test/run-make-fulldeps/emit-stack-sizes/Makefile
+++ b/src/test/run-make-fulldeps/emit-stack-sizes/Makefile
@@ -2,7 +2,6 @@
# ignore-windows
# ignore-macos
-# min-llvm-version 6.0
#
# This feature only works when the output object format is ELF so we ignore
# macOS and Windows
diff --git a/src/test/rustdoc-ui/issue-61732.rs b/src/test/rustdoc-ui/issue-61732.rs
new file mode 100644
index 0000000..d4835c0
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61732.rs
@@ -0,0 +1,4 @@
+// This previously triggered an ICE.
+
+pub(in crate::r#mod) fn main() {}
+//~^ ERROR expected module, found unresolved item
diff --git a/src/test/rustdoc-ui/issue-61732.stderr b/src/test/rustdoc-ui/issue-61732.stderr
new file mode 100644
index 0000000..6c8ba48
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61732.stderr
@@ -0,0 +1,11 @@
+error[E0577]: expected module, found unresolved item `crate::r#mod`
+ --> $DIR/issue-61732.rs:3:8
+ |
+LL | pub(in crate::r#mod) fn main() {}
+ | ^^^^^^^^^^^^ not a module
+
+error: Compilation failed, aborting rustdoc
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0577`.
diff --git a/src/test/rustdoc/duplicate-cfg.rs b/src/test/rustdoc/duplicate-cfg.rs
new file mode 100644
index 0000000..505d6ee
--- /dev/null
+++ b/src/test/rustdoc/duplicate-cfg.rs
@@ -0,0 +1,15 @@
+#![crate_name = "foo"]
+#![feature(doc_cfg)]
+
+// @has 'foo/index.html'
+// @!has '-' '//*[@class="stab portability"]' 'feature="sync" and'
+// @has '-' '//*[@class="stab portability"]' 'feature="sync"'
+#[doc(cfg(feature = "sync"))]
+#[doc(cfg(feature = "sync"))]
+pub struct Foo;
+
+#[doc(cfg(feature = "sync"))]
+pub mod bar {
+ #[doc(cfg(feature = "sync"))]
+ pub struct Bar;
+}
diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
index 68ea10f..e9ef58f 100644
--- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
+++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
@@ -1,8 +1,8 @@
#![feature(box_syntax, plugin, plugin_registrar, rustc_private)]
#![crate_type = "dylib"]
-#[macro_use]
-extern crate rustc;
+#[macro_use] extern crate rustc;
+#[macro_use] extern crate rustc_session;
extern crate rustc_driver;
extern crate syntax;
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
index 6874c92..118ba17 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
@@ -2,8 +2,8 @@
#![feature(plugin_registrar, rustc_private)]
#![feature(box_syntax)]
-
#[macro_use] extern crate rustc;
+#[macro_use] extern crate rustc_session;
extern crate rustc_driver;
extern crate syntax;
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
index 1cd3e7b..49ca43d 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
@@ -4,6 +4,7 @@
#![feature(box_syntax)]
#[macro_use] extern crate rustc;
+#[macro_use] extern crate rustc_session;
extern crate rustc_driver;
extern crate syntax;
diff --git a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
index cb793b4..839c65a 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
@@ -4,8 +4,8 @@
#![feature(box_syntax, rustc_private)]
// Load rustc as a plugin to get macros.
-#[macro_use]
-extern crate rustc;
+#[macro_use] extern crate rustc;
+#[macro_use] extern crate rustc_session;
extern crate rustc_driver;
use rustc::hir;
diff --git a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
index 40c37eb..bb96dba 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
@@ -6,8 +6,8 @@
extern crate syntax;
// Load rustc as a plugin to get macros
-#[macro_use]
-extern crate rustc;
+#[macro_use] extern crate rustc;
+#[macro_use] extern crate rustc_session;
extern crate rustc_driver;
use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, LintArray};
diff --git a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
index 67135d5..1704909 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
@@ -4,8 +4,8 @@
extern crate syntax;
// Load rustc as a plugin to get macros
-#[macro_use]
-extern crate rustc;
+#[macro_use] extern crate rustc;
+#[macro_use] extern crate rustc_session;
extern crate rustc_driver;
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass, LintId};
diff --git a/src/test/ui-fulldeps/auxiliary/llvm-pass-plugin.rs b/src/test/ui-fulldeps/auxiliary/llvm-pass-plugin.rs
deleted file mode 100644
index 2ff1c2e..0000000
--- a/src/test/ui-fulldeps/auxiliary/llvm-pass-plugin.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// force-host
-
-#![feature(plugin_registrar)]
-#![feature(rustc_private)]
-
-extern crate rustc;
-extern crate rustc_driver;
-
-use rustc_driver::plugin::Registry;
-
-#[plugin_registrar]
-pub fn plugin_registrar(reg: &mut Registry) {
- // This pass is built in to LLVM.
- //
- // Normally, we would name a pass that was registered through
- // C++ static object constructors in the same .so file as the
- // plugin registrar.
- reg.register_llvm_pass("gvn");
-}
diff --git a/src/test/ui/feature-gates/feature-gate-plugin.rs b/src/test/ui-fulldeps/feature-gate-plugin.rs
similarity index 60%
rename from src/test/ui/feature-gates/feature-gate-plugin.rs
rename to src/test/ui-fulldeps/feature-gate-plugin.rs
index 8904ec0..85eaf53 100644
--- a/src/test/ui/feature-gates/feature-gate-plugin.rs
+++ b/src/test/ui-fulldeps/feature-gate-plugin.rs
@@ -1,6 +1,7 @@
-// Test that `#![plugin(...)]` attribute is gated by `plugin` feature gate
+// aux-build:empty-plugin.rs
+// ignore-stage1
-#![plugin(foo)]
+#![plugin(empty_plugin)]
//~^ ERROR compiler plugins are deprecated
//~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated
diff --git a/src/test/ui/feature-gates/feature-gate-plugin.stderr b/src/test/ui-fulldeps/feature-gate-plugin.stderr
similarity index 67%
rename from src/test/ui/feature-gates/feature-gate-plugin.stderr
rename to src/test/ui-fulldeps/feature-gate-plugin.stderr
index f89ddf9..c922325 100644
--- a/src/test/ui/feature-gates/feature-gate-plugin.stderr
+++ b/src/test/ui-fulldeps/feature-gate-plugin.stderr
@@ -1,17 +1,17 @@
error[E0658]: compiler plugins are deprecated
- --> $DIR/feature-gate-plugin.rs:3:1
+ --> $DIR/feature-gate-plugin.rs:4:1
|
-LL | #![plugin(foo)]
- | ^^^^^^^^^^^^^^^
+LL | #![plugin(empty_plugin)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29597
= help: add `#![feature(plugin)]` to the crate attributes to enable
warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
- --> $DIR/feature-gate-plugin.rs:3:1
+ --> $DIR/feature-gate-plugin.rs:4:1
|
-LL | #![plugin(foo)]
- | ^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
+LL | #![plugin(empty_plugin)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
|
= note: `#[warn(deprecated)]` on by default
diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs
index 0bfb32c..7ce2a1d 100644
--- a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs
+++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs
@@ -4,9 +4,11 @@
#![deny(rustc::lint_pass_impl_without_macro)]
extern crate rustc;
+extern crate rustc_session;
use rustc::lint::{LintArray, LintPass};
-use rustc::{declare_lint, declare_lint_pass, impl_lint_pass};
+use rustc::{declare_lint_pass, impl_lint_pass};
+use rustc_session::declare_lint;
declare_lint! {
pub TEST_LINT,
diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
index 0dbdf4f..ad8670c 100644
--- a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
+++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
@@ -1,5 +1,5 @@
error: implementing `LintPass` by hand
- --> $DIR/lint_pass_impl_without_macro.rs:19:6
+ --> $DIR/lint_pass_impl_without_macro.rs:21:6
|
LL | impl LintPass for Foo {
| ^^^^^^^^
@@ -12,7 +12,7 @@
= help: try using `declare_lint_pass!` or `impl_lint_pass!` instead
error: implementing `LintPass` by hand
- --> $DIR/lint_pass_impl_without_macro.rs:29:14
+ --> $DIR/lint_pass_impl_without_macro.rs:31:14
|
LL | impl LintPass for Custom {
| ^^^^^^^^
diff --git a/src/test/ui-fulldeps/lint-plugin-cmdline-load.rs b/src/test/ui-fulldeps/lint-plugin-cmdline-load.rs
index fd68153..0bd95df 100644
--- a/src/test/ui-fulldeps/lint-plugin-cmdline-load.rs
+++ b/src/test/ui-fulldeps/lint-plugin-cmdline-load.rs
@@ -1,9 +1,9 @@
-// run-pass
+// check-pass
// aux-build:lint-plugin-test.rs
// ignore-stage1
-// compile-flags: -Z extra-plugins=lint_plugin_test
+// compile-flags: -Z crate-attr=plugin(lint_plugin_test)
-#![allow(dead_code)]
+#![feature(plugin)]
fn lintme() { } //~ WARNING item is named 'lintme'
diff --git a/src/test/ui-fulldeps/lint-plugin-cmdline-load.stderr b/src/test/ui-fulldeps/lint-plugin-cmdline-load.stderr
index 5a6b354..1263a0e 100644
--- a/src/test/ui-fulldeps/lint-plugin-cmdline-load.stderr
+++ b/src/test/ui-fulldeps/lint-plugin-cmdline-load.stderr
@@ -1,3 +1,11 @@
+warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
+ --> <crate attribute>:1:1
+ |
+LL | plugin(lint_plugin_test)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
+ |
+ = note: `#[warn(deprecated)]` on by default
+
warning: item is named 'lintme'
--> $DIR/lint-plugin-cmdline-load.rs:8:1
|
diff --git a/src/test/ui-fulldeps/llvm-pass-plugin.rs b/src/test/ui-fulldeps/llvm-pass-plugin.rs
deleted file mode 100644
index fa5cbc1..0000000
--- a/src/test/ui-fulldeps/llvm-pass-plugin.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-// aux-build:llvm-pass-plugin.rs
-// ignore-stage1
-
-#![feature(plugin)]
-#![plugin(llvm_pass_plugin)] //~ WARNING compiler plugins are deprecated
-
-pub fn main() { }
diff --git a/src/test/ui-fulldeps/llvm-pass-plugin.stderr b/src/test/ui-fulldeps/llvm-pass-plugin.stderr
deleted file mode 100644
index 61b53bb..0000000
--- a/src/test/ui-fulldeps/llvm-pass-plugin.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
- --> $DIR/llvm-pass-plugin.rs:6:1
- |
-LL | #![plugin(llvm_pass_plugin)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
- |
- = note: `#[warn(deprecated)]` on by default
-
diff --git a/src/test/ui-fulldeps/macro-crate-multi-decorator.rs b/src/test/ui-fulldeps/macro-crate-multi-decorator.rs
index e396cf0..f21617b 100644
--- a/src/test/ui-fulldeps/macro-crate-multi-decorator.rs
+++ b/src/test/ui-fulldeps/macro-crate-multi-decorator.rs
@@ -1,9 +1,4 @@
-// run-pass
-
-#![allow(plugin_as_library)]
-#![allow(dead_code)]
-#![allow(unused_variables)]
-#![allow(unused_imports)]
+// check-pass
// aux-build:macro-crate-test.rs
// ignore-stage1
diff --git a/src/test/ui-fulldeps/plugin-args-1.rs b/src/test/ui-fulldeps/plugin-args-1.rs
deleted file mode 100644
index 1865819..0000000
--- a/src/test/ui-fulldeps/plugin-args-1.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// check-pass
-// aux-build:empty-plugin.rs
-// ignore-stage1
-
-#![feature(plugin)]
-#![plugin(empty_plugin)] //~ WARNING compiler plugins are deprecated
-
-fn main() {}
diff --git a/src/test/ui-fulldeps/plugin-args-1.stderr b/src/test/ui-fulldeps/plugin-args-1.stderr
deleted file mode 100644
index 4e82961..0000000
--- a/src/test/ui-fulldeps/plugin-args-1.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
- --> $DIR/plugin-args-1.rs:6:1
- |
-LL | #![plugin(empty_plugin)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
- |
- = note: `#[warn(deprecated)]` on by default
-
diff --git a/src/test/ui-fulldeps/plugin-args-2.rs b/src/test/ui-fulldeps/plugin-args-2.rs
deleted file mode 100644
index c4bd191..0000000
--- a/src/test/ui-fulldeps/plugin-args-2.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// check-pass
-// aux-build:empty-plugin.rs
-// ignore-stage1
-
-#![feature(plugin)]
-#![plugin(empty_plugin())] //~ WARNING compiler plugins are deprecated
-
-fn main() {}
diff --git a/src/test/ui-fulldeps/plugin-args-2.stderr b/src/test/ui-fulldeps/plugin-args-2.stderr
deleted file mode 100644
index 92bd69b..0000000
--- a/src/test/ui-fulldeps/plugin-args-2.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
- --> $DIR/plugin-args-2.rs:6:1
- |
-LL | #![plugin(empty_plugin())]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
- |
- = note: `#[warn(deprecated)]` on by default
-
diff --git a/src/test/ui-fulldeps/plugin-args-3.rs b/src/test/ui-fulldeps/plugin-args-3.rs
deleted file mode 100644
index c8818cc..0000000
--- a/src/test/ui-fulldeps/plugin-args-3.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// check-pass
-// aux-build:empty-plugin.rs
-// ignore-stage1
-
-#![feature(plugin)]
-#![plugin(empty_plugin(hello(there), how(are="you")))] //~ WARNING compiler plugins are deprecated
-
-fn main() {}
diff --git a/src/test/ui-fulldeps/plugin-args-3.stderr b/src/test/ui-fulldeps/plugin-args-3.stderr
deleted file mode 100644
index 278853e..0000000
--- a/src/test/ui-fulldeps/plugin-args-3.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
- --> $DIR/plugin-args-3.rs:6:1
- |
-LL | #![plugin(empty_plugin(hello(there), how(are="you")))]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
- |
- = note: `#[warn(deprecated)]` on by default
-
diff --git a/src/test/ui-fulldeps/plugin-args.rs b/src/test/ui-fulldeps/plugin-args.rs
new file mode 100644
index 0000000..488f2b7
--- /dev/null
+++ b/src/test/ui-fulldeps/plugin-args.rs
@@ -0,0 +1,9 @@
+// aux-build:empty-plugin.rs
+// ignore-stage1
+
+#![feature(plugin)]
+#![plugin(empty_plugin(args))]
+//~^ ERROR malformed `plugin` attribute
+//~| WARNING compiler plugins are deprecated
+
+fn main() {}
diff --git a/src/test/ui-fulldeps/plugin-args.stderr b/src/test/ui-fulldeps/plugin-args.stderr
new file mode 100644
index 0000000..2b9094c
--- /dev/null
+++ b/src/test/ui-fulldeps/plugin-args.stderr
@@ -0,0 +1,16 @@
+error[E0498]: malformed `plugin` attribute
+ --> $DIR/plugin-args.rs:5:11
+ |
+LL | #![plugin(empty_plugin(args))]
+ | ^^^^^^^^^^^^^^^^^^ malformed attribute
+
+warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
+ --> $DIR/plugin-args.rs:5:1
+ |
+LL | #![plugin(empty_plugin(args))]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
+ |
+ = note: `#[warn(deprecated)]` on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui-fulldeps/plugin-as-extern-crate.rs b/src/test/ui-fulldeps/plugin-as-extern-crate.rs
index fa7826c..f231efc 100644
--- a/src/test/ui-fulldeps/plugin-as-extern-crate.rs
+++ b/src/test/ui-fulldeps/plugin-as-extern-crate.rs
@@ -1,11 +1,10 @@
+// check-pass
// aux-build:empty-plugin.rs
// ignore-cross-compile
//
// empty_plugin will not compile on a cross-compiled target because
// libsyntax is not compiled for it.
-#![deny(plugin_as_library)]
+extern crate empty_plugin; // OK, plugin crates are still crates
-extern crate empty_plugin; //~ ERROR compiler plugin used as an ordinary library
-
-fn main() { }
+fn main() {}
diff --git a/src/test/ui-fulldeps/plugin-as-extern-crate.stderr b/src/test/ui-fulldeps/plugin-as-extern-crate.stderr
deleted file mode 100644
index d2fbb5d..0000000
--- a/src/test/ui-fulldeps/plugin-as-extern-crate.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: compiler plugin used as an ordinary library
- --> $DIR/plugin-as-extern-crate.rs:9:1
- |
-LL | extern crate empty_plugin;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: lint level defined here
- --> $DIR/plugin-as-extern-crate.rs:7:9
- |
-LL | #![deny(plugin_as_library)]
- | ^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr
index 9be44c7..c6d9a61 100644
--- a/src/test/ui/anonymous-higher-ranked-lifetime.stderr
+++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr
@@ -121,3 +121,4 @@
error: aborting due to 11 previous errors
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
index 627609c..3e39c8a 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
@@ -9,13 +9,21 @@
|
LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> {
| ^^
- = note: ...so that the expression is assignable:
- expected Type<'_>
- found Type<'a>
+note: ...so that the expression is assignable
+ --> $DIR/project-fn-ret-invariant.rs:48:13
+ |
+LL | bar(foo, x)
+ | ^
+ = note: expected `Type<'_>`
+ found `Type<'a>`
= note: but, the lifetime must be valid for the static lifetime...
- = note: ...so that the expression is assignable:
- expected Type<'static>
- found Type<'_>
+note: ...so that the expression is assignable
+ --> $DIR/project-fn-ret-invariant.rs:48:4
+ |
+LL | bar(foo, x)
+ | ^^^^^^^^^^^
+ = note: expected `Type<'static>`
+ found `Type<'_>`
error: aborting due to previous error
diff --git a/src/test/ui/async-await/suggest-missing-await.fixed b/src/test/ui/async-await/suggest-missing-await.fixed
index 7c02a90..1ec59d9 100644
--- a/src/test/ui/async-await/suggest-missing-await.fixed
+++ b/src/test/ui/async-await/suggest-missing-await.fixed
@@ -16,4 +16,15 @@
//~| SUGGESTION x.await
}
+async fn dummy() {}
+
+#[allow(unused)]
+async fn suggest_await_in_async_fn_return() {
+ dummy().await;
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP try adding a semicolon
+ //~| HELP consider using `.await` here
+ //~| SUGGESTION dummy().await
+}
+
fn main() {}
diff --git a/src/test/ui/async-await/suggest-missing-await.rs b/src/test/ui/async-await/suggest-missing-await.rs
index 91abd44..70cc1f1 100644
--- a/src/test/ui/async-await/suggest-missing-await.rs
+++ b/src/test/ui/async-await/suggest-missing-await.rs
@@ -16,4 +16,15 @@
//~| SUGGESTION x.await
}
+async fn dummy() {}
+
+#[allow(unused)]
+async fn suggest_await_in_async_fn_return() {
+ dummy()
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP try adding a semicolon
+ //~| HELP consider using `.await` here
+ //~| SUGGESTION dummy().await
+}
+
fn main() {}
diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr
index 7a635a3..7ab0244 100644
--- a/src/test/ui/async-await/suggest-missing-await.stderr
+++ b/src/test/ui/async-await/suggest-missing-await.stderr
@@ -10,6 +10,23 @@
= note: expected type `u32`
found opaque type `impl std::future::Future`
-error: aborting due to previous error
+error[E0308]: mismatched types
+ --> $DIR/suggest-missing-await.rs:23:5
+ |
+LL | dummy()
+ | ^^^^^^^ expected `()`, found opaque type
+ |
+ = note: expected unit type `()`
+ found opaque type `impl std::future::Future`
+help: try adding a semicolon
+ |
+LL | dummy();
+ | ^
+help: consider using `.await` here
+ |
+LL | dummy().await
+ |
+
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/async-await/try-on-option-in-async.stderr b/src/test/ui/async-await/try-on-option-in-async.stderr
index 7d31f60..46f8f41 100644
--- a/src/test/ui/async-await/try-on-option-in-async.stderr
+++ b/src/test/ui/async-await/try-on-option-in-async.stderr
@@ -1,8 +1,14 @@
error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> $DIR/try-on-option-in-async.rs:8:9
|
-LL | x?;
- | ^^ cannot use the `?` operator in an async block that returns `{integer}`
+LL | async {
+ | ___________-
+LL | | let x: Option<u32> = None;
+LL | | x?;
+ | | ^^ cannot use the `?` operator in an async block that returns `{integer}`
+LL | | 22
+LL | | }.await
+ | |_____- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `{integer}`
= note: required by `std::ops::Try::from_error`
@@ -10,8 +16,14 @@
error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> $DIR/try-on-option-in-async.rs:16:9
|
-LL | x?;
- | ^^ cannot use the `?` operator in an async closure that returns `u32`
+LL | let async_closure = async || {
+ | __________________________________-
+LL | | let x: Option<u32> = None;
+LL | | x?;
+ | | ^^ cannot use the `?` operator in an async closure that returns `u32`
+LL | | 22_u32
+LL | | };
+ | |_____- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `u32`
= note: required by `std::ops::Try::from_error`
@@ -19,8 +31,14 @@
error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> $DIR/try-on-option-in-async.rs:25:5
|
-LL | x?;
- | ^^ cannot use the `?` operator in an async function that returns `u32`
+LL | async fn an_async_function() -> u32 {
+ | _____________________________________-
+LL | | let x: Option<u32> = None;
+LL | | x?;
+ | | ^^ cannot use the `?` operator in an async function that returns `u32`
+LL | | 22
+LL | | }
+ | |_- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `u32`
= note: required by `std::ops::Try::from_error`
diff --git a/src/test/ui/c-variadic/variadic-ffi-4.stderr b/src/test/ui/c-variadic/variadic-ffi-4.stderr
index c80ed5e..cd4cd8b 100644
--- a/src/test/ui/c-variadic/variadic-ffi-4.stderr
+++ b/src/test/ui/c-variadic/variadic-ffi-4.stderr
@@ -49,9 +49,13 @@
|
LL | let _ = ap.with_copy(|ap| { ap });
| ^^^^^^^^^^^
- = note: ...so that the expression is assignable:
- expected core::ffi::VaList<'_, '_>
- found core::ffi::VaList<'_, '_>
+note: ...so that the expression is assignable
+ --> $DIR/variadic-ffi-4.rs:16:33
+ |
+LL | let _ = ap.with_copy(|ap| { ap });
+ | ^^
+ = note: expected `core::ffi::VaList<'_, '_>`
+ found `core::ffi::VaList<'_, '_>`
note: but, the lifetime must be valid for the method call at 16:13...
--> $DIR/variadic-ffi-4.rs:16:13
|
diff --git a/src/test/ui/check-static-immutable-mut-slices.stderr b/src/test/ui/check-static-immutable-mut-slices.stderr
index 4f4bf16..39da824 100644
--- a/src/test/ui/check-static-immutable-mut-slices.stderr
+++ b/src/test/ui/check-static-immutable-mut-slices.stderr
@@ -1,9 +1,12 @@
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
--> $DIR/check-static-immutable-mut-slices.rs:3:37
|
LL | static TEST: &'static mut [isize] = &mut [];
| ^^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0017`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr
index a6b52b2..7141c04 100644
--- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr
+++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr
@@ -39,3 +39,4 @@
error: aborting due to 3 previous errors
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr
index a154442..0033395 100644
--- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr
+++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr
@@ -77,4 +77,5 @@
error: aborting due to 5 previous errors
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0308, E0631.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr b/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr
index 9fbe95a..1c6564e 100644
--- a/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr
+++ b/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr
@@ -13,3 +13,4 @@
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr
index 91d26ef..2f2871e 100644
--- a/src/test/ui/closures/issue-41366.stderr
+++ b/src/test/ui/closures/issue-41366.stderr
@@ -19,4 +19,5 @@
error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0271`.
+Some errors have detailed explanations: E0271, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/conditional-compilation/cfg-attr-parse.rs b/src/test/ui/conditional-compilation/cfg-attr-parse.rs
index 93aef72..8ca31c1 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-parse.rs
+++ b/src/test/ui/conditional-compilation/cfg-attr-parse.rs
@@ -1,11 +1,11 @@
// Parse `cfg_attr` with varying numbers of attributes and trailing commas
// Completely empty `cfg_attr` input
-#[cfg_attr()] //~ error: expected identifier, found `)`
+#[cfg_attr()] //~ error: malformed `cfg_attr` attribute input
struct NoConfigurationPredicate;
// Zero attributes, zero trailing comma (comma manatory here)
-#[cfg_attr(all())] //~ error: expected `,`, found `)`
+#[cfg_attr(all())] //~ error: expected `,`, found end of `cfg_attr`
struct A0C0;
// Zero attributes, one trailing comma
@@ -40,4 +40,16 @@
#[cfg_attr(all(), must_use, deprecated,,)] //~ ERROR expected identifier
struct A2C2;
+// Wrong delimiter `[`
+#[cfg_attr[all(),,]]
+//~^ ERROR wrong `cfg_attr` delimiters
+//~| ERROR expected identifier, found `,`
+struct BracketZero;
+
+// Wrong delimiter `{`
+#[cfg_attr{all(),,}]
+//~^ ERROR wrong `cfg_attr` delimiters
+//~| ERROR expected identifier, found `,`
+struct BraceZero;
+
fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-parse.stderr b/src/test/ui/conditional-compilation/cfg-attr-parse.stderr
index 3dfbd6d..3a590d3 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-parse.stderr
+++ b/src/test/ui/conditional-compilation/cfg-attr-parse.stderr
@@ -1,32 +1,86 @@
-error: expected identifier, found `)`
- --> $DIR/cfg-attr-parse.rs:4:12
+error: malformed `cfg_attr` attribute input
+ --> $DIR/cfg-attr-parse.rs:4:1
|
LL | #[cfg_attr()]
- | ^ expected identifier
+ | ^^^^^^^^^^^^^ help: missing condition and attribute: `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
-error: expected `,`, found `)`
+error: expected `,`, found end of `cfg_attr` input
--> $DIR/cfg-attr-parse.rs:8:17
|
LL | #[cfg_attr(all())]
| ^ expected `,`
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
error: expected identifier, found `,`
--> $DIR/cfg-attr-parse.rs:16:18
|
LL | #[cfg_attr(all(),,)]
| ^ expected identifier
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
error: expected identifier, found `,`
--> $DIR/cfg-attr-parse.rs:28:28
|
LL | #[cfg_attr(all(), must_use,,)]
| ^ expected identifier
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
error: expected identifier, found `,`
--> $DIR/cfg-attr-parse.rs:40:40
|
LL | #[cfg_attr(all(), must_use, deprecated,,)]
| ^ expected identifier
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
-error: aborting due to 5 previous errors
+error: wrong `cfg_attr` delimiters
+ --> $DIR/cfg-attr-parse.rs:44:11
+ |
+LL | #[cfg_attr[all(),,]]
+ | ^^^^^^^^^
+ |
+help: the delimiters should be `(` and `)`
+ |
+LL | #[cfg_attr(all(),,)]
+ | ^ ^
+
+error: expected identifier, found `,`
+ --> $DIR/cfg-attr-parse.rs:44:18
+ |
+LL | #[cfg_attr[all(),,]]
+ | ^ expected identifier
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+
+error: wrong `cfg_attr` delimiters
+ --> $DIR/cfg-attr-parse.rs:50:11
+ |
+LL | #[cfg_attr{all(),,}]
+ | ^^^^^^^^^
+ |
+help: the delimiters should be `(` and `)`
+ |
+LL | #[cfg_attr(all(),,)]
+ | ^ ^
+
+error: expected identifier, found `,`
+ --> $DIR/cfg-attr-parse.rs:50:18
+ |
+LL | #[cfg_attr{all(),,}]
+ | ^ expected identifier
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+
+error: aborting due to 9 previous errors
diff --git a/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.rs b/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.rs
new file mode 100644
index 0000000..bdcf537
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.rs
@@ -0,0 +1,6 @@
+#![feature(core_intrinsics)]
+fn main() {
+ // Test that calls to intrinsics are never promoted
+ let x: &'static usize =
+ &std::intrinsics::size_of::<i32>(); //~ ERROR temporary value dropped while borrowed
+}
diff --git a/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr b/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr
new file mode 100644
index 0000000..78143042e
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr
@@ -0,0 +1,13 @@
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/const-eval-intrinsic-promotion.rs:5:10
+ |
+LL | let x: &'static usize =
+ | -------------- type annotation requires that borrow lasts for `'static`
+LL | &std::intrinsics::size_of::<i32>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+LL | }
+ | - temporary value is freed at the end of this statement
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-eval/issue-65394.stderr b/src/test/ui/consts/const-eval/issue-65394.stderr
index acf5cba..54b3507 100644
--- a/src/test/ui/consts/const-eval/issue-65394.stderr
+++ b/src/test/ui/consts/const-eval/issue-65394.stderr
@@ -1,8 +1,11 @@
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/issue-65394.rs:8:13
|
LL | let r = &mut x;
| ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/issue-65394.rs:7:9
@@ -12,5 +15,5 @@
error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0017, E0493.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0493, E0658.
+For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs
index 7c6a574..6469a65 100644
--- a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs
+++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs
@@ -7,7 +7,7 @@
const extern fn bar() {
unsafe {
regular_in_block();
- //~^ ERROR: cannot call functions with `"C"` abi in `min_const_fn`
+ //~^ ERROR: can only call other `const fn` within a `const fn`
}
}
@@ -16,7 +16,7 @@
const extern fn foo() {
unsafe {
regular();
- //~^ ERROR: cannot call functions with `"C"` abi in `min_const_fn`
+ //~^ ERROR: can only call other `const fn` within a `const fn`
}
}
diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr
index d8bdf0a..eed279e 100644
--- a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr
+++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr
@@ -1,4 +1,4 @@
-error[E0723]: cannot call functions with `"C"` abi in `min_const_fn`
+error[E0723]: can only call other `const fn` within a `const fn`, but `const regular_in_block` is not stable as `const fn`
--> $DIR/const-extern-fn-call-extern-fn.rs:9:9
|
LL | regular_in_block();
@@ -7,7 +7,7 @@
= note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
= help: add `#![feature(const_fn)]` to the crate attributes to enable
-error[E0723]: cannot call functions with `"C"` abi in `min_const_fn`
+error[E0723]: can only call other `const fn` within a `const fn`, but `const regular` is not stable as `const fn`
--> $DIR/const-extern-fn-call-extern-fn.rs:18:9
|
LL | regular();
diff --git a/src/test/ui/consts/const-multi-ref.rs b/src/test/ui/consts/const-multi-ref.rs
index 498e99e..5e2be0d 100644
--- a/src/test/ui/consts/const-multi-ref.rs
+++ b/src/test/ui/consts/const-multi-ref.rs
@@ -1,11 +1,24 @@
-const _X: i32 = {
- let mut a = 5;
- let p = &mut a; //~ ERROR references in constants may only refer to immutable values
+// Ensure that we point the user to the erroneous borrow but not to any subsequent borrows of that
+// initial one.
- let reborrow = {p}; //~ ERROR references in constants may only refer to immutable values
+const _: i32 = {
+ let mut a = 5;
+ let p = &mut a; //~ ERROR references in constants may only refer to immutable values
+
+ let reborrow = {p};
let pp = &reborrow;
let ppp = &pp;
***ppp
};
+const _: std::cell::Cell<i32> = {
+ let mut a = std::cell::Cell::new(5);
+ let p = &a; //~ ERROR cannot borrow a constant which may contain interior mutability
+
+ let reborrow = {p};
+ let pp = &reborrow;
+ let ppp = &pp;
+ a
+};
+
fn main() {}
diff --git a/src/test/ui/consts/const-multi-ref.stderr b/src/test/ui/consts/const-multi-ref.stderr
index 9e525ef..0809c77 100644
--- a/src/test/ui/consts/const-multi-ref.stderr
+++ b/src/test/ui/consts/const-multi-ref.stderr
@@ -1,15 +1,19 @@
-error[E0017]: references in constants may only refer to immutable values
- --> $DIR/const-multi-ref.rs:3:13
+error[E0658]: references in constants may only refer to immutable values
+ --> $DIR/const-multi-ref.rs:6:13
|
LL | let p = &mut a;
| ^^^^^^ constants require immutable values
-
-error[E0017]: references in constants may only refer to immutable values
- --> $DIR/const-multi-ref.rs:5:21
|
-LL | let reborrow = {p};
- | ^ constants require immutable values
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+ --> $DIR/const-multi-ref.rs:16:13
+ |
+LL | let p = &a;
+ | ^^
error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0492, E0658.
+For more information about an error, try `rustc --explain E0492`.
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
new file mode 100644
index 0000000..99006a2
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
@@ -0,0 +1,36 @@
+// run-pass
+
+#![feature(const_mut_refs)]
+
+struct Foo {
+ x: usize
+}
+
+const fn foo() -> Foo {
+ Foo { x: 0 }
+}
+
+impl Foo {
+ const fn bar(&mut self) -> usize {
+ self.x = 1;
+ self.x
+ }
+
+}
+
+const fn baz(foo: &mut Foo) -> usize {
+ let x = &mut foo.x;
+ *x = 2;
+ *x
+}
+
+const fn bazz(foo: &mut Foo) -> usize {
+ foo.x = 3;
+ foo.x
+}
+
+fn main() {
+ let _: [(); foo().bar()] = [(); 1];
+ let _: [(); baz(&mut foo())] = [(); 2];
+ let _: [(); bazz(&mut foo())] = [(); 3];
+}
diff --git a/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs
new file mode 100644
index 0000000..2207599
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs
@@ -0,0 +1,7 @@
+fn main() {
+ foo(&mut 5);
+}
+
+const fn foo(x: &mut i32) -> i32 { //~ ERROR mutable references in const fn are unstable
+ *x + 1
+}
diff --git a/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr
new file mode 100644
index 0000000..4fae119
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr
@@ -0,0 +1,12 @@
+error[E0723]: mutable references in const fn are unstable
+ --> $DIR/feature-gate-const_mut_refs.rs:5:14
+ |
+LL | const fn foo(x: &mut i32) -> i32 {
+ | ^
+ |
+ = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
+ = help: add `#![feature(const_fn)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr
index 53b960b..7852874 100644
--- a/src/test/ui/consts/const_let_assign3.stderr
+++ b/src/test/ui/consts/const_let_assign3.stderr
@@ -4,17 +4,23 @@
LL | self.state = x;
| ^^^^^^^^^^^^^^
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/const_let_assign3.rs:16:5
|
LL | s.foo(3);
| ^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/const_let_assign3.rs:22:13
|
LL | let y = &mut x;
| ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0019]: constant contains unimplemented expression type
--> $DIR/const_let_assign3.rs:24:5
@@ -24,5 +30,5 @@
error: aborting due to 4 previous errors
-Some errors have detailed explanations: E0017, E0019.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0019, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/issue-66787.rs b/src/test/ui/consts/issue-66787.rs
new file mode 100644
index 0000000..612b795
--- /dev/null
+++ b/src/test/ui/consts/issue-66787.rs
@@ -0,0 +1,39 @@
+// build-pass
+// compile-flags: --crate-type lib
+
+// Regression test for ICE which occurred when const propagating an enum with three variants
+// one of which is uninhabited.
+
+pub enum ApiError {}
+#[allow(dead_code)]
+pub struct TokioError {
+ b: bool,
+}
+pub enum Error {
+ Api {
+ source: ApiError,
+ },
+ Ethereum,
+ Tokio {
+ source: TokioError,
+ },
+}
+struct Api;
+impl IntoError<Error> for Api
+{
+ type Source = ApiError;
+ fn into_error(self, error: Self::Source) -> Error {
+ Error::Api {
+ source: (|v| v)(error),
+ }
+ }
+}
+
+pub trait IntoError<E>
+{
+ /// The underlying error
+ type Source;
+
+ /// Combine the information to produce the error
+ fn into_error(self, source: Self::Source) -> E;
+}
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.rs b/src/test/ui/consts/miri_unleashed/mutable_const.rs
index 44b4084..972f595 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_const.rs
+++ b/src/test/ui/consts/miri_unleashed/mutable_const.rs
@@ -1,6 +1,7 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
#![feature(const_raw_ptr_deref)]
+#![feature(const_mut_refs)]
#![deny(const_err)]
use std::cell::UnsafeCell;
@@ -12,9 +13,7 @@
const MUTATING_BEHIND_RAW: () = {
// Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
unsafe {
- *MUTABLE_BEHIND_RAW = 99 //~ WARN skipping const checks
- //~^ ERROR any use of this value will cause an error
- //~^^ tried to modify constant memory
+ *MUTABLE_BEHIND_RAW = 99 //~ ERROR any use of this value will cause an error
}
};
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.stderr b/src/test/ui/consts/miri_unleashed/mutable_const.stderr
index 757f0ff..9daca76 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_const.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_const.stderr
@@ -1,30 +1,23 @@
warning: skipping const checks
- --> $DIR/mutable_const.rs:9:38
+ --> $DIR/mutable_const.rs:10:38
|
LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
| ^^^^^^^^^^^^^^^^^^^^
-warning: skipping const checks
- --> $DIR/mutable_const.rs:15:9
- |
-LL | *MUTABLE_BEHIND_RAW = 99
- | ^^^^^^^^^^^^^^^^^^^^^^^^
-
error: any use of this value will cause an error
- --> $DIR/mutable_const.rs:15:9
+ --> $DIR/mutable_const.rs:16:9
|
LL | / const MUTATING_BEHIND_RAW: () = {
LL | | // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
LL | | unsafe {
LL | | *MUTABLE_BEHIND_RAW = 99
| | ^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify constant memory
-... |
LL | | }
LL | | };
| |__-
|
note: lint level defined here
- --> $DIR/mutable_const.rs:4:9
+ --> $DIR/mutable_const.rs:5:9
|
LL | #![deny(const_err)]
| ^^^^^^^^^
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references.rs b/src/test/ui/consts/miri_unleashed/mutable_references.rs
index 59dafcb..fe3c4ee 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references.rs
+++ b/src/test/ui/consts/miri_unleashed/mutable_references.rs
@@ -1,20 +1,22 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
+#![feature(const_mut_refs)]
#![allow(const_err)]
use std::cell::UnsafeCell;
// a test demonstrating what things we could allow with a smarter const qualification
+// this is fine because is not possible to mutate through an immutable reference.
static FOO: &&mut u32 = &&mut 42;
-//~^ WARN: skipping const checks
+// this is fine because accessing an immutable static `BAR` is equivalent to accessing `*&BAR`
+// which puts the mutable reference behind an immutable one.
static BAR: &mut () = &mut ();
-//~^ WARN: skipping const checks
struct Foo<T>(T);
+// this is fine for the same reason as `BAR`.
static BOO: &mut Foo<()> = &mut Foo(());
-//~^ WARN: skipping const checks
struct Meh {
x: &'static UnsafeCell<i32>,
@@ -27,8 +29,8 @@
//~^ WARN: skipping const checks
};
+// this is fine for the same reason as `BAR`.
static OH_YES: &mut i32 = &mut 42;
-//~^ WARN: skipping const checks
fn main() {
unsafe {
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references.stderr b/src/test/ui/consts/miri_unleashed/mutable_references.stderr
index b9c0af3..3e1300c 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_references.stderr
@@ -1,35 +1,11 @@
warning: skipping const checks
- --> $DIR/mutable_references.rs:8:26
- |
-LL | static FOO: &&mut u32 = &&mut 42;
- | ^^^^^^^
-
-warning: skipping const checks
- --> $DIR/mutable_references.rs:11:23
- |
-LL | static BAR: &mut () = &mut ();
- | ^^^^^^^
-
-warning: skipping const checks
- --> $DIR/mutable_references.rs:16:28
- |
-LL | static BOO: &mut Foo<()> = &mut Foo(());
- | ^^^^^^^^^^^^
-
-warning: skipping const checks
- --> $DIR/mutable_references.rs:26:8
+ --> $DIR/mutable_references.rs:28:8
|
LL | x: &UnsafeCell::new(42),
| ^^^^^^^^^^^^^^^^^^^^
-warning: skipping const checks
- --> $DIR/mutable_references.rs:30:27
- |
-LL | static OH_YES: &mut i32 = &mut 42;
- | ^^^^^^^
-
error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item
- --> $DIR/mutable_references.rs:37:5
+ --> $DIR/mutable_references.rs:39:5
|
LL | *OH_YES = 99;
| ^^^^^^^^^^^^ cannot assign
diff --git a/src/test/ui/consts/miri_unleashed/read_from_static.rs b/src/test/ui/consts/miri_unleashed/read_from_static.rs
new file mode 100644
index 0000000..821c501
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/read_from_static.rs
@@ -0,0 +1,11 @@
+// run-pass
+// compile-flags: -Zunleash-the-miri-inside-of-you
+#![feature(const_mut_refs)]
+#![allow(const_err)]
+
+static OH_YES: &mut i32 = &mut 42;
+
+fn main() {
+ // Make sure `OH_YES` can be read.
+ assert_eq!(*OH_YES, 42);
+}
diff --git a/src/test/ui/consts/projection_qualif.mut_refs.stderr b/src/test/ui/consts/projection_qualif.mut_refs.stderr
new file mode 100644
index 0000000..2353877
--- /dev/null
+++ b/src/test/ui/consts/projection_qualif.mut_refs.stderr
@@ -0,0 +1,12 @@
+error[E0658]: dereferencing raw pointers in constants is unstable
+ --> $DIR/projection_qualif.rs:11:18
+ |
+LL | unsafe { *b = 5; }
+ | ^^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/51911
+ = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/projection_qualif.rs b/src/test/ui/consts/projection_qualif.rs
index dedb7db..cfe8e7f 100644
--- a/src/test/ui/consts/projection_qualif.rs
+++ b/src/test/ui/consts/projection_qualif.rs
@@ -1,11 +1,15 @@
+// revisions: stock mut_refs
+
+#![cfg_attr(mut_refs, feature(const_mut_refs))]
+
use std::cell::Cell;
const FOO: &u32 = {
let mut a = 42;
{
- let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
+ let b: *mut u32 = &mut a; //[stock]~ ERROR may only refer to immutable values
unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
- //~^ contains unimplemented expression
+ //[stock]~^ contains unimplemented expression
}
&{a}
};
diff --git a/src/test/ui/consts/projection_qualif.stderr b/src/test/ui/consts/projection_qualif.stderr
deleted file mode 100644
index 0efb6bf..0000000
--- a/src/test/ui/consts/projection_qualif.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error[E0017]: references in constants may only refer to immutable values
- --> $DIR/projection_qualif.rs:6:27
- |
-LL | let b: *mut u32 = &mut a;
- | ^^^^^^ constants require immutable values
-
-error[E0658]: dereferencing raw pointers in constants is unstable
- --> $DIR/projection_qualif.rs:7:18
- |
-LL | unsafe { *b = 5; }
- | ^^^^^^
- |
- = note: for more information, see https://github.com/rust-lang/rust/issues/51911
- = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
-
-error[E0019]: constant contains unimplemented expression type
- --> $DIR/projection_qualif.rs:7:18
- |
-LL | unsafe { *b = 5; }
- | ^^^^^^
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0017, E0019, E0658.
-For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/consts/projection_qualif.stock.stderr b/src/test/ui/consts/projection_qualif.stock.stderr
new file mode 100644
index 0000000..472d260
--- /dev/null
+++ b/src/test/ui/consts/projection_qualif.stock.stderr
@@ -0,0 +1,28 @@
+error[E0658]: references in constants may only refer to immutable values
+ --> $DIR/projection_qualif.rs:10:27
+ |
+LL | let b: *mut u32 = &mut a;
+ | ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: dereferencing raw pointers in constants is unstable
+ --> $DIR/projection_qualif.rs:11:18
+ |
+LL | unsafe { *b = 5; }
+ | ^^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/51911
+ = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
+
+error[E0019]: constant contains unimplemented expression type
+ --> $DIR/projection_qualif.rs:11:18
+ |
+LL | unsafe { *b = 5; }
+ | ^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0019, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr
new file mode 100644
index 0000000..b43fbc8
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr
@@ -0,0 +1,9 @@
+error[E0080]: could not evaluate static initializer
+ --> $DIR/static_mut_containing_mut_ref2.rs:7:45
+ |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify a static's initial value from another static's initializer
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs
index ef378fa..74162fb 100644
--- a/src/test/ui/consts/static_mut_containing_mut_ref2.rs
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs
@@ -1,7 +1,12 @@
+// revisions: stock mut_refs
+
+#![cfg_attr(mut_refs, feature(const_mut_refs))]
+
static mut STDERR_BUFFER_SPACE: u8 = 0;
pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
-//~^ ERROR references in statics may only refer to immutable values
-//~| ERROR static contains unimplemented expression type
+//[mut_refs]~^ ERROR could not evaluate static initializer
+//[stock]~^^ ERROR references in statics may only refer to immutable values
+//[stock]~| ERROR static contains unimplemented expression type
fn main() {}
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr
deleted file mode 100644
index ca691b0..0000000
--- a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0017]: references in statics may only refer to immutable values
- --> $DIR/static_mut_containing_mut_ref2.rs:3:46
- |
-LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values
-
-error[E0019]: static contains unimplemented expression type
- --> $DIR/static_mut_containing_mut_ref2.rs:3:45
- |
-LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0017, E0019.
-For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr
new file mode 100644
index 0000000..430cef9
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr
@@ -0,0 +1,19 @@
+error[E0658]: references in statics may only refer to immutable values
+ --> $DIR/static_mut_containing_mut_ref2.rs:7:46
+ |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/static_mut_containing_mut_ref2.rs:7:45
+ |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0019, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.rs b/src/test/ui/consts/unstable-const-fn-in-libcore.rs
new file mode 100644
index 0000000..cad1516
--- /dev/null
+++ b/src/test/ui/consts/unstable-const-fn-in-libcore.rs
@@ -0,0 +1,29 @@
+// This is a non-regression test for const-qualification of unstable items in libcore
+// as explained in issue #67053.
+// const-qualification could miss some `const fn`s if they were unstable and the feature
+// gate was not enabled in libcore.
+
+#![stable(feature = "core", since = "1.6.0")]
+#![feature(const_if_match)]
+#![feature(rustc_const_unstable)]
+#![feature(staged_api)]
+
+enum Opt<T> {
+ Some(T),
+ None,
+}
+
+impl<T> Opt<T> {
+ #[rustc_const_unstable(feature = "foo")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
+ //~^ ERROR destructors cannot be evaluated at compile-time
+ //~| ERROR destructors cannot be evaluated at compile-time
+ match self {
+ Opt::Some(t) => t,
+ Opt::None => f(), //~ ERROR E0015
+ }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr
new file mode 100644
index 0000000..a8455ce
--- /dev/null
+++ b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr
@@ -0,0 +1,22 @@
+error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+ --> $DIR/unstable-const-fn-in-libcore.rs:24:26
+ |
+LL | Opt::None => f(),
+ | ^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+ --> $DIR/unstable-const-fn-in-libcore.rs:19:53
+ |
+LL | const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
+ | ^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+ --> $DIR/unstable-const-fn-in-libcore.rs:19:47
+ |
+LL | const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
+ | ^^^^ constant functions cannot evaluate destructors
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0015, E0493.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/enum/union-in-enum.rs b/src/test/ui/enum/union-in-enum.rs
new file mode 100644
index 0000000..048913e
--- /dev/null
+++ b/src/test/ui/enum/union-in-enum.rs
@@ -0,0 +1,13 @@
+// This test checks that the union keyword
+// is accepted as the name of an enum variant
+// when not followed by an identifier
+// This special case exists because `union` is a contextual keyword.
+
+#![allow(warnings)]
+
+// check-pass
+
+enum A { union }
+enum B { union {} }
+enum C { union() }
+fn main(){}
diff --git a/src/test/ui/error-codes/E0017.rs b/src/test/ui/error-codes/E0017.rs
index 94b6587..64be411 100644
--- a/src/test/ui/error-codes/E0017.rs
+++ b/src/test/ui/error-codes/E0017.rs
@@ -1,8 +1,11 @@
static X: i32 = 1;
const C: i32 = 2;
+static mut M: i32 = 3;
-const CR: &'static mut i32 = &mut C; //~ ERROR E0017
-static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
+const CR: &'static mut i32 = &mut C; //~ ERROR E0658
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658
+ //~| ERROR E0019
//~| ERROR cannot borrow
-static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017
+static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0658
+static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR E0658
fn main() {}
diff --git a/src/test/ui/error-codes/E0017.stderr b/src/test/ui/error-codes/E0017.stderr
index 47863f0..9a87195 100644
--- a/src/test/ui/error-codes/E0017.stderr
+++ b/src/test/ui/error-codes/E0017.stderr
@@ -1,28 +1,52 @@
-error[E0017]: references in constants may only refer to immutable values
- --> $DIR/E0017.rs:4:30
+error[E0658]: references in constants may only refer to immutable values
+ --> $DIR/E0017.rs:5:30
|
LL | const CR: &'static mut i32 = &mut C;
| ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-error[E0017]: references in statics may only refer to immutable values
- --> $DIR/E0017.rs:5:39
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/E0017.rs:6:39
+ |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+ | ^^^^^^
+
+error[E0658]: references in statics may only refer to immutable values
+ --> $DIR/E0017.rs:6:39
|
LL | static STATIC_REF: &'static mut i32 = &mut X;
| ^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0596]: cannot borrow immutable static item `X` as mutable
- --> $DIR/E0017.rs:5:39
+ --> $DIR/E0017.rs:6:39
|
LL | static STATIC_REF: &'static mut i32 = &mut X;
| ^^^^^^ cannot borrow as mutable
-error[E0017]: references in statics may only refer to immutable values
- --> $DIR/E0017.rs:7:38
+error[E0658]: references in statics may only refer to immutable values
+ --> $DIR/E0017.rs:9:38
|
LL | static CONST_REF: &'static mut i32 = &mut C;
| ^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-error: aborting due to 4 previous errors
+error[E0658]: references in statics may only refer to immutable values
+ --> $DIR/E0017.rs:10:52
+ |
+LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M };
+ | ^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-Some errors have detailed explanations: E0017, E0596.
-For more information about an error, try `rustc --explain E0017`.
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0019, E0596, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/error-codes/E0388.rs b/src/test/ui/error-codes/E0388.rs
index 3aa4ac9..5954e34 100644
--- a/src/test/ui/error-codes/E0388.rs
+++ b/src/test/ui/error-codes/E0388.rs
@@ -1,9 +1,10 @@
static X: i32 = 1;
const C: i32 = 2;
-const CR: &'static mut i32 = &mut C; //~ ERROR E0017
-static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
+const CR: &'static mut i32 = &mut C; //~ ERROR E0658
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658
//~| ERROR cannot borrow
-static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017
+ //~| ERROR E0019
+static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0658
fn main() {}
diff --git a/src/test/ui/error-codes/E0388.stderr b/src/test/ui/error-codes/E0388.stderr
index b52d526..986307d 100644
--- a/src/test/ui/error-codes/E0388.stderr
+++ b/src/test/ui/error-codes/E0388.stderr
@@ -1,14 +1,26 @@
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/E0388.rs:4:30
|
LL | const CR: &'static mut i32 = &mut C;
| ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-error[E0017]: references in statics may only refer to immutable values
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/E0388.rs:5:39
+ |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+ | ^^^^^^
+
+error[E0658]: references in statics may only refer to immutable values
--> $DIR/E0388.rs:5:39
|
LL | static STATIC_REF: &'static mut i32 = &mut X;
| ^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0596]: cannot borrow immutable static item `X` as mutable
--> $DIR/E0388.rs:5:39
@@ -16,13 +28,16 @@
LL | static STATIC_REF: &'static mut i32 = &mut X;
| ^^^^^^ cannot borrow as mutable
-error[E0017]: references in statics may only refer to immutable values
- --> $DIR/E0388.rs:7:38
+error[E0658]: references in statics may only refer to immutable values
+ --> $DIR/E0388.rs:8:38
|
LL | static CONST_REF: &'static mut i32 = &mut C;
| ^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
-Some errors have detailed explanations: E0017, E0596.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0019, E0596, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/feature-gates/feature-gate-cfg_sanitize.rs b/src/test/ui/feature-gates/feature-gate-cfg_sanitize.rs
new file mode 100644
index 0000000..c3e7cc9
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-cfg_sanitize.rs
@@ -0,0 +1,3 @@
+#[cfg(not(sanitize = "thread"))]
+//~^ `cfg(sanitize)` is experimental
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-cfg_sanitize.stderr b/src/test/ui/feature-gates/feature-gate-cfg_sanitize.stderr
new file mode 100644
index 0000000..f67a0d8
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-cfg_sanitize.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `cfg(sanitize)` is experimental and subject to change
+ --> $DIR/feature-gate-cfg_sanitize.rs:1:11
+ |
+LL | #[cfg(not(sanitize = "thread"))]
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/39699
+ = help: add `#![feature(cfg_sanitize)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-const_transmute.rs b/src/test/ui/feature-gates/feature-gate-const_transmute.rs
index 6a5bbec..da53264 100644
--- a/src/test/ui/feature-gates/feature-gate-const_transmute.rs
+++ b/src/test/ui/feature-gates/feature-gate-const_transmute.rs
@@ -4,6 +4,6 @@
struct Foo(u32);
const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
-//~^ ERROR The use of std::mem::transmute() is gated in constants
+//~^ ERROR `std::intrinsics::transmute` is not yet stable as a const fn
fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-const_transmute.stderr b/src/test/ui/feature-gates/feature-gate-const_transmute.stderr
index 41b653d..772e8d2 100644
--- a/src/test/ui/feature-gates/feature-gate-const_transmute.stderr
+++ b/src/test/ui/feature-gates/feature-gate-const_transmute.stderr
@@ -1,12 +1,10 @@
-error[E0658]: The use of std::mem::transmute() is gated in constants
+error: `std::intrinsics::transmute` is not yet stable as a const fn
--> $DIR/feature-gate-const_transmute.rs:6:38
|
LL | const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
| ^^^^^^^^^^^^^^^^^^^^^^
|
- = note: for more information, see https://github.com/rust-lang/rust/issues/53605
= help: add `#![feature(const_transmute)]` to the crate attributes to enable
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
index b388f38..ca61fb0 100644
--- a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
+++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
@@ -4,7 +4,10 @@
LL | fn bar(x: usize) -> Option<usize> {
| ------------- expected `std::option::Option<usize>` because of return type
LL | return x;
- | ^ expected enum `std::option::Option`, found `usize`
+ | ^
+ | |
+ | expected enum `std::option::Option`, found `usize`
+ | help: try using a variant of the expected enum: `Some(x)`
|
= note: expected enum `std::option::Option<usize>`
found type `usize`
diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
index 5e80c67..3300293 100644
--- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
+++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
@@ -9,13 +9,21 @@
|
LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
| ^^
- = note: ...so that the expression is assignable:
- expected std::boxed::Box<dyn std::fmt::Debug>
- found std::boxed::Box<(dyn std::fmt::Debug + 'a)>
+note: ...so that the expression is assignable
+ --> $DIR/dyn-trait.rs:20:16
+ |
+LL | static_val(x);
+ | ^
+ = note: expected `std::boxed::Box<dyn std::fmt::Debug>`
+ found `std::boxed::Box<(dyn std::fmt::Debug + 'a)>`
= note: but, the lifetime must be valid for the static lifetime...
- = note: ...so that the types are compatible:
- expected StaticTrait
- found StaticTrait
+note: ...so that the types are compatible
+ --> $DIR/dyn-trait.rs:20:5
+ |
+LL | static_val(x);
+ | ^^^^^^^^^^
+ = note: expected `StaticTrait`
+ found `StaticTrait`
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-10536.rs b/src/test/ui/issues/issue-10536.rs
index 111078a..f536d8f 100644
--- a/src/test/ui/issues/issue-10536.rs
+++ b/src/test/ui/issues/issue-10536.rs
@@ -11,9 +11,9 @@
pub fn main() {
foo!();
- assert!({one! two()}); //~ ERROR expected open delimiter
+ assert!({one! two()}); //~ ERROR expected one of `(`, `[`, or `{`, found `two`
// regardless of whether nested macro_rules works, the following should at
// least throw a conventional error.
- assert!({one! two}); //~ ERROR expected open delimiter
+ assert!({one! two}); //~ ERROR expected one of `(`, `[`, or `{`, found `two`
}
diff --git a/src/test/ui/issues/issue-10536.stderr b/src/test/ui/issues/issue-10536.stderr
index 73f9481..cc04844 100644
--- a/src/test/ui/issues/issue-10536.stderr
+++ b/src/test/ui/issues/issue-10536.stderr
@@ -1,14 +1,14 @@
-error: expected open delimiter
+error: expected one of `(`, `[`, or `{`, found `two`
--> $DIR/issue-10536.rs:14:19
|
LL | assert!({one! two()});
- | ^^^ expected open delimiter
+ | ^^^ expected one of `(`, `[`, or `{`
-error: expected open delimiter
+error: expected one of `(`, `[`, or `{`, found `two`
--> $DIR/issue-10536.rs:18:19
|
LL | assert!({one! two});
- | ^^^ expected open delimiter
+ | ^^^ expected one of `(`, `[`, or `{`
error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-16683.stderr b/src/test/ui/issues/issue-16683.stderr
index b663e21..99700f2 100644
--- a/src/test/ui/issues/issue-16683.stderr
+++ b/src/test/ui/issues/issue-16683.stderr
@@ -21,9 +21,13 @@
|
LL | trait T<'a> {
| ^^
- = note: ...so that the types are compatible:
- expected &'a Self
- found &Self
+note: ...so that the types are compatible
+ --> $DIR/issue-16683.rs:4:14
+ |
+LL | self.a();
+ | ^
+ = note: expected `&'a Self`
+ found `&Self`
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-17718-const-bad-values.stderr b/src/test/ui/issues/issue-17718-const-bad-values.stderr
index 8d875d3..7e4a62a 100644
--- a/src/test/ui/issues/issue-17718-const-bad-values.stderr
+++ b/src/test/ui/issues/issue-17718-const-bad-values.stderr
@@ -1,8 +1,11 @@
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/issue-17718-const-bad-values.rs:1:34
|
LL | const C1: &'static mut [usize] = &mut [];
| ^^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0013]: constants cannot refer to statics, use a constant instead
--> $DIR/issue-17718-const-bad-values.rs:5:46
@@ -10,13 +13,16 @@
LL | const C2: &'static mut usize = unsafe { &mut S };
| ^
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/issue-17718-const-bad-values.rs:5:41
|
LL | const C2: &'static mut usize = unsafe { &mut S };
| ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error: aborting due to 3 previous errors
-Some errors have detailed explanations: E0013, E0017.
+Some errors have detailed explanations: E0013, E0658.
For more information about an error, try `rustc --explain E0013`.
diff --git a/src/test/ui/issues/issue-17758.stderr b/src/test/ui/issues/issue-17758.stderr
index adcbb62..adfc3f508 100644
--- a/src/test/ui/issues/issue-17758.stderr
+++ b/src/test/ui/issues/issue-17758.stderr
@@ -22,9 +22,13 @@
|
LL | trait Foo<'a> {
| ^^
- = note: ...so that the types are compatible:
- expected &'a Self
- found &Self
+note: ...so that the types are compatible
+ --> $DIR/issue-17758.rs:7:14
+ |
+LL | self.foo();
+ | ^^^
+ = note: expected `&'a Self`
+ found `&Self`
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr
index 13c9c09..c7fd134 100644
--- a/src/test/ui/issues/issue-20831-debruijn.stderr
+++ b/src/test/ui/issues/issue-20831-debruijn.stderr
@@ -88,9 +88,19 @@
|
LL | impl<'a> Publisher<'a> for MyStruct<'a> {
| ^^
- = note: ...so that the types are compatible:
- expected Publisher<'_>
- found Publisher<'_>
+note: ...so that the types are compatible
+ --> $DIR/issue-20831-debruijn.rs:28:5
+ |
+LL | / fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | | // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |
+... |
+LL | | self.sub = t;
+LL | | }
+ | |_____^
+ = note: expected `Publisher<'_>`
+ found `Publisher<'_>`
error: aborting due to 3 previous errors
diff --git a/src/test/ui/issues/issue-43623.stderr b/src/test/ui/issues/issue-43623.stderr
index 2c57b85..d90eb53 100644
--- a/src/test/ui/issues/issue-43623.stderr
+++ b/src/test/ui/issues/issue-43623.stderr
@@ -25,4 +25,5 @@
error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0271`.
+Some errors have detailed explanations: E0271, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/issues/issue-46604.rs b/src/test/ui/issues/issue-46604.rs
index 4f1ad38..e1967eb 100644
--- a/src/test/ui/issues/issue-46604.rs
+++ b/src/test/ui/issues/issue-46604.rs
@@ -1,4 +1,4 @@
-static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //~ ERROR E0017
+static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //~ ERROR E0658
fn write<T: AsRef<[u8]>>(buffer: T) { }
fn main() {
diff --git a/src/test/ui/issues/issue-46604.stderr b/src/test/ui/issues/issue-46604.stderr
index c72f580..32c7ecb 100644
--- a/src/test/ui/issues/issue-46604.stderr
+++ b/src/test/ui/issues/issue-46604.stderr
@@ -1,8 +1,11 @@
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
--> $DIR/issue-46604.rs:1:25
|
LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];
| ^^^^^^^^^^^^^^^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item
--> $DIR/issue-46604.rs:6:5
@@ -12,5 +15,5 @@
error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0017, E0594.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0594, E0658.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
index aef6dc5..9ca983d 100644
--- a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
+++ b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
@@ -2,13 +2,18 @@
--> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
|
LL | missing_discourses()?
- | ^^^^^^^^^^^^^^^^^^^^-
- | | |
- | | help: try removing this `?`
- | expected enum `std::result::Result`, found `isize`
+ | ^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found `isize`
|
= note: expected enum `std::result::Result<isize, ()>`
found type `isize`
+help: try removing this `?`
+ |
+LL | missing_discourses()
+ | --
+help: try using a variant of the expected enum
+ |
+LL | Ok(missing_discourses()?)
+ |
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-52213.stderr b/src/test/ui/issues/issue-52213.stderr
index b79a5dd..a8960f7 100644
--- a/src/test/ui/issues/issue-52213.stderr
+++ b/src/test/ui/issues/issue-52213.stderr
@@ -9,9 +9,13 @@
|
LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T {
| ^^
- = note: ...so that the types are compatible:
- expected (&&(T,),)
- found (&&'a (T,),)
+note: ...so that the types are compatible
+ --> $DIR/issue-52213.rs:2:11
+ |
+LL | match (&t,) {
+ | ^^^^^
+ = note: expected `(&&(T,),)`
+ found `(&&'a (T,),)`
note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 1:27...
--> $DIR/issue-52213.rs:1:27
|
diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/issues/issue-55796.stderr
index 7b910f5..b8cafdc 100644
--- a/src/test/ui/issues/issue-55796.stderr
+++ b/src/test/ui/issues/issue-55796.stderr
@@ -15,9 +15,13 @@
LL | Box::new(self.out_edges(u).map(|e| e.target()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
- = note: ...so that the expression is assignable:
- expected std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>
- found std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>
+note: ...so that the expression is assignable
+ --> $DIR/issue-55796.rs:16:9
+ |
+LL | Box::new(self.out_edges(u).map(|e| e.target()))
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: expected `std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>`
+ found `std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>`
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> $DIR/issue-55796.rs:21:9
@@ -36,9 +40,13 @@
LL | Box::new(self.in_edges(u).map(|e| e.target()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
- = note: ...so that the expression is assignable:
- expected std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>
- found std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>
+note: ...so that the expression is assignable
+ --> $DIR/issue-55796.rs:21:9
+ |
+LL | Box::new(self.in_edges(u).map(|e| e.target()))
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: expected `std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>`
+ found `std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>`
error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-59756.rs b/src/test/ui/issues/issue-59756.rs
index cccae39..d6df059 100644
--- a/src/test/ui/issues/issue-59756.rs
+++ b/src/test/ui/issues/issue-59756.rs
@@ -1,4 +1,8 @@
// run-rustfix
+// ignore-test
+//
+// FIXME: Re-enable this test once we support choosing
+// between multiple mutually exclusive suggestions for the same span
#![allow(warnings)]
diff --git a/src/test/ui/issues/issue-59756.stderr b/src/test/ui/issues/issue-59756.stderr
index 150916c..9066e57 100644
--- a/src/test/ui/issues/issue-59756.stderr
+++ b/src/test/ui/issues/issue-59756.stderr
@@ -2,13 +2,18 @@
--> $DIR/issue-59756.rs:13:5
|
LL | foo()?
- | ^^^^^-
- | | |
- | | help: try removing this `?`
- | expected enum `std::result::Result`, found struct `A`
+ | ^^^^^^ expected enum `std::result::Result`, found struct `A`
|
= note: expected enum `std::result::Result<A, B>`
found struct `A`
+help: try removing this `?`
+ |
+LL | foo()
+ | --
+help: try using a variant of the expected enum
+ |
+LL | Ok(foo()?)
+ |
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr
index 69c1d85..d13dcd5 100644
--- a/src/test/ui/issues/issue-60283.stderr
+++ b/src/test/ui/issues/issue-60283.stderr
@@ -27,4 +27,5 @@
error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0271`.
+Some errors have detailed explanations: E0271, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/issues/issue-65634-raw-ident-suggestion.rs b/src/test/ui/issues/issue-65634-raw-ident-suggestion.rs
new file mode 100644
index 0000000..b928510
--- /dev/null
+++ b/src/test/ui/issues/issue-65634-raw-ident-suggestion.rs
@@ -0,0 +1,22 @@
+#![allow(non_camel_case_types)]
+
+trait r#async {
+ fn r#struct(&self) {
+ println!("async");
+ }
+}
+
+trait r#await {
+ fn r#struct(&self) {
+ println!("await");
+ }
+}
+
+struct r#fn {}
+
+impl r#async for r#fn {}
+impl r#await for r#fn {}
+
+fn main() {
+ r#fn {}.r#struct(); //~ ERROR multiple applicable items in scope
+}
diff --git a/src/test/ui/issues/issue-65634-raw-ident-suggestion.stderr b/src/test/ui/issues/issue-65634-raw-ident-suggestion.stderr
new file mode 100644
index 0000000..c7bb653
--- /dev/null
+++ b/src/test/ui/issues/issue-65634-raw-ident-suggestion.stderr
@@ -0,0 +1,22 @@
+error[E0034]: multiple applicable items in scope
+ --> $DIR/issue-65634-raw-ident-suggestion.rs:21:13
+ |
+LL | r#fn {}.r#struct();
+ | ^^^^^^^^ multiple `r#struct` found
+ |
+note: candidate #1 is defined in an impl of the trait `async` for the type `r#fn`
+ --> $DIR/issue-65634-raw-ident-suggestion.rs:4:5
+ |
+LL | fn r#struct(&self) {
+ | ^^^^^^^^^^^^^^^^^^
+ = help: to disambiguate the method call, write `async::r#struct(r#fn {})` instead
+note: candidate #2 is defined in an impl of the trait `await` for the type `r#fn`
+ --> $DIR/issue-65634-raw-ident-suggestion.rs:10:5
+ |
+LL | fn r#struct(&self) {
+ | ^^^^^^^^^^^^^^^^^^
+ = help: to disambiguate the method call, write `await::r#struct(r#fn {})` instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/issues/issue-66702-break-outside-loop-val.rs b/src/test/ui/issues/issue-66702-break-outside-loop-val.rs
new file mode 100644
index 0000000..bd3c00d
--- /dev/null
+++ b/src/test/ui/issues/issue-66702-break-outside-loop-val.rs
@@ -0,0 +1,7 @@
+// Breaks with values inside closures used to ICE (#66863)
+
+fn main() {
+ 'some_label: loop {
+ || break 'some_label (); //~ ERROR: `break` inside of a closure
+ }
+}
diff --git a/src/test/ui/issues/issue-66702-break-outside-loop-val.stderr b/src/test/ui/issues/issue-66702-break-outside-loop-val.stderr
new file mode 100644
index 0000000..83bde97
--- /dev/null
+++ b/src/test/ui/issues/issue-66702-break-outside-loop-val.stderr
@@ -0,0 +1,11 @@
+error[E0267]: `break` inside of a closure
+ --> $DIR/issue-66702-break-outside-loop-val.rs:5:12
+ |
+LL | || break 'some_label ();
+ | -- ^^^^^^^^^^^^^^^^^^^^ cannot `break` inside of a closure
+ | |
+ | enclosing closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0267`.
diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs
new file mode 100644
index 0000000..44bd645
--- /dev/null
+++ b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs
@@ -0,0 +1,21 @@
+// Regression test for #67037.
+//
+// In type checking patterns, E0023 occurs when the tuple pattern and the expected
+// tuple pattern have different number of fields. For example, as below, `P()`,
+// the tuple struct pattern, has 0 fields, but requires 1 field.
+//
+// In emitting E0023, we try to see if this is a case of e.g., `Some(a, b, c)` but where
+// the scrutinee was of type `Some((a, b, c))`, and suggest that parenthesis be added.
+//
+// However, we did not account for the expected type being different than the tuple pattern type.
+// This caused an issue when the tuple pattern type (`P<T>`) was generic.
+// Specifically, we tried deriving the 0th field's type using the `substs` of the expected type.
+// When attempting to substitute `T`, there was no such substitution, so "out of range" occured.
+
+struct U {} // 0 type parameters offered
+struct P<T>(T); // 1 type parameter wanted
+
+fn main() {
+ let P() = U {}; //~ ERROR mismatched types
+ //~^ ERROR this pattern has 0 fields, but the corresponding tuple struct has 1 field
+}
diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
new file mode 100644
index 0000000..521dd02
--- /dev/null
+++ b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs:19:9
+ |
+LL | let P() = U {};
+ | ^^^ expected struct `U`, found struct `P`
+ |
+ = note: expected struct `U`
+ found struct `P<_>`
+
+error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 1 field
+ --> $DIR/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs:19:9
+ |
+LL | struct P<T>(T); // 1 type parameter wanted
+ | --------------- tuple struct defined here
+...
+LL | let P() = U {};
+ | ^^^ expected 1 field, found 0
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0023, E0308.
+For more information about an error, try `rustc --explain E0023`.
diff --git a/src/test/ui/malformed/malformed-derive-entry.rs b/src/test/ui/malformed/malformed-derive-entry.rs
index a6d8863..77fa2f5 100644
--- a/src/test/ui/malformed/malformed-derive-entry.rs
+++ b/src/test/ui/malformed/malformed-derive-entry.rs
@@ -1,7 +1,11 @@
-#[derive(Copy(Bad))] //~ ERROR expected one of `)`, `,`, or `::`, found `(`
+#[derive(Copy(Bad))]
+//~^ ERROR traits in `#[derive(...)]` don't accept arguments
+//~| ERROR the trait bound
struct Test1;
-#[derive(Copy="bad")] //~ ERROR expected one of `)`, `,`, or `::`, found `=`
+#[derive(Copy="bad")]
+//~^ ERROR traits in `#[derive(...)]` don't accept values
+//~| ERROR the trait bound
struct Test2;
#[derive] //~ ERROR malformed `derive` attribute input
diff --git a/src/test/ui/malformed/malformed-derive-entry.stderr b/src/test/ui/malformed/malformed-derive-entry.stderr
index 8d750b6..1f1ee39 100644
--- a/src/test/ui/malformed/malformed-derive-entry.stderr
+++ b/src/test/ui/malformed/malformed-derive-entry.stderr
@@ -1,20 +1,33 @@
-error: expected one of `)`, `,`, or `::`, found `(`
+error: traits in `#[derive(...)]` don't accept arguments
--> $DIR/malformed-derive-entry.rs:1:14
|
LL | #[derive(Copy(Bad))]
- | ^ expected one of `)`, `,`, or `::`
+ | ^^^^^ help: remove the arguments
-error: expected one of `)`, `,`, or `::`, found `=`
- --> $DIR/malformed-derive-entry.rs:4:14
+error: traits in `#[derive(...)]` don't accept values
+ --> $DIR/malformed-derive-entry.rs:6:14
|
LL | #[derive(Copy="bad")]
- | ^ expected one of `)`, `,`, or `::`
+ | ^^^^^^ help: remove the value
error: malformed `derive` attribute input
- --> $DIR/malformed-derive-entry.rs:7:1
+ --> $DIR/malformed-derive-entry.rs:11:1
|
LL | #[derive]
| ^^^^^^^^^ help: missing traits to be derived: `#[derive(Trait1, Trait2, ...)]`
-error: aborting due to 3 previous errors
+error[E0277]: the trait bound `Test1: std::clone::Clone` is not satisfied
+ --> $DIR/malformed-derive-entry.rs:1:10
+ |
+LL | #[derive(Copy(Bad))]
+ | ^^^^ the trait `std::clone::Clone` is not implemented for `Test1`
+error[E0277]: the trait bound `Test2: std::clone::Clone` is not satisfied
+ --> $DIR/malformed-derive-entry.rs:6:10
+ |
+LL | #[derive(Copy="bad")]
+ | ^^^^ the trait `std::clone::Clone` is not implemented for `Test2`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/malformed/malformed-meta-delim.rs b/src/test/ui/malformed/malformed-meta-delim.rs
new file mode 100644
index 0000000..5b1614b
--- /dev/null
+++ b/src/test/ui/malformed/malformed-meta-delim.rs
@@ -0,0 +1,11 @@
+fn main() {}
+
+#[allow { foo_lint } ]
+//~^ ERROR wrong meta list delimiters
+//~| HELP the delimiters should be `(` and `)`
+fn delim_brace() {}
+
+#[allow [ foo_lint ] ]
+//~^ ERROR wrong meta list delimiters
+//~| HELP the delimiters should be `(` and `)`
+fn delim_bracket() {}
diff --git a/src/test/ui/malformed/malformed-meta-delim.stderr b/src/test/ui/malformed/malformed-meta-delim.stderr
new file mode 100644
index 0000000..407193d
--- /dev/null
+++ b/src/test/ui/malformed/malformed-meta-delim.stderr
@@ -0,0 +1,24 @@
+error: wrong meta list delimiters
+ --> $DIR/malformed-meta-delim.rs:3:9
+ |
+LL | #[allow { foo_lint } ]
+ | ^^^^^^^^^^^^
+ |
+help: the delimiters should be `(` and `)`
+ |
+LL | #[allow ( foo_lint ) ]
+ | ^ ^
+
+error: wrong meta list delimiters
+ --> $DIR/malformed-meta-delim.rs:8:9
+ |
+LL | #[allow [ foo_lint ] ]
+ | ^^^^^^^^^^^^
+ |
+help: the delimiters should be `(` and `)`
+ |
+LL | #[allow ( foo_lint ) ]
+ | ^ ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/malformed/malformed-plugin-1.stderr b/src/test/ui/malformed/malformed-plugin-1.stderr
index 3860864..2a4f772 100644
--- a/src/test/ui/malformed/malformed-plugin-1.stderr
+++ b/src/test/ui/malformed/malformed-plugin-1.stderr
@@ -2,7 +2,7 @@
--> $DIR/malformed-plugin-1.rs:2:1
|
LL | #![plugin]
- | ^^^^^^^^^^ help: must be of the form: `#[plugin(name|name(args))]`
+ | ^^^^^^^^^^ help: must be of the form: `#[plugin(name)]`
warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
--> $DIR/malformed-plugin-1.rs:2:1
diff --git a/src/test/ui/malformed/malformed-plugin-2.stderr b/src/test/ui/malformed/malformed-plugin-2.stderr
index e4bca93..fe116a4 100644
--- a/src/test/ui/malformed/malformed-plugin-2.stderr
+++ b/src/test/ui/malformed/malformed-plugin-2.stderr
@@ -2,7 +2,7 @@
--> $DIR/malformed-plugin-2.rs:2:1
|
LL | #![plugin="bleh"]
- | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[plugin(name|name(args))]`
+ | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[plugin(name)]`
warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
--> $DIR/malformed-plugin-2.rs:2:1
diff --git a/src/test/ui/malformed/malformed-plugin-3.stderr b/src/test/ui/malformed/malformed-plugin-3.stderr
index 7393072..4af933c 100644
--- a/src/test/ui/malformed/malformed-plugin-3.stderr
+++ b/src/test/ui/malformed/malformed-plugin-3.stderr
@@ -1,8 +1,8 @@
error[E0498]: malformed `plugin` attribute
- --> $DIR/malformed-plugin-3.rs:2:1
+ --> $DIR/malformed-plugin-3.rs:2:11
|
LL | #![plugin(foo="bleh")]
- | ^^^^^^^^^^^^^^^^^^^^^^ malformed attribute
+ | ^^^^^^^^^^ malformed attribute
warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
--> $DIR/malformed-plugin-3.rs:2:1
diff --git a/src/test/ui/malformed/malformed-special-attrs.rs b/src/test/ui/malformed/malformed-special-attrs.rs
index e67fbdd..05b7ebe 100644
--- a/src/test/ui/malformed/malformed-special-attrs.rs
+++ b/src/test/ui/malformed/malformed-special-attrs.rs
@@ -1,7 +1,7 @@
#[cfg_attr] //~ ERROR malformed `cfg_attr` attribute
struct S1;
-#[cfg_attr = ""] //~ ERROR expected `(`, found `=`
+#[cfg_attr = ""] //~ ERROR malformed `cfg_attr` attribute
struct S2;
#[derive] //~ ERROR malformed `derive` attribute
diff --git a/src/test/ui/malformed/malformed-special-attrs.stderr b/src/test/ui/malformed/malformed-special-attrs.stderr
index 319c05e..6f535e0 100644
--- a/src/test/ui/malformed/malformed-special-attrs.stderr
+++ b/src/test/ui/malformed/malformed-special-attrs.stderr
@@ -6,11 +6,13 @@
|
= note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
-error: expected `(`, found `=`
- --> $DIR/malformed-special-attrs.rs:4:12
+error: malformed `cfg_attr` attribute input
+ --> $DIR/malformed-special-attrs.rs:4:1
|
LL | #[cfg_attr = ""]
- | ^ expected `(`
+ | ^^^^^^^^^^^^^^^^ help: missing condition and attribute: `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
error: malformed `derive` attribute input
--> $DIR/malformed-special-attrs.rs:7:1
diff --git a/src/test/ui/mismatched_types/E0631.stderr b/src/test/ui/mismatched_types/E0631.stderr
index 88c1efd..06f5c05 100644
--- a/src/test/ui/mismatched_types/E0631.stderr
+++ b/src/test/ui/mismatched_types/E0631.stderr
@@ -46,3 +46,4 @@
error: aborting due to 4 previous errors
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr
index c208187..c731306 100644
--- a/src/test/ui/mismatched_types/abridged.stderr
+++ b/src/test/ui/mismatched_types/abridged.stderr
@@ -26,7 +26,10 @@
LL | fn b() -> Option<Foo> {
| ----------- expected `std::option::Option<Foo>` because of return type
LL | Foo { bar: 1 }
- | ^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `Foo`
+ | ^^^^^^^^^^^^^^
+ | |
+ | expected enum `std::option::Option`, found struct `Foo`
+ | help: try using a variant of the expected enum: `Some(Foo { bar: 1 })`
|
= note: expected enum `std::option::Option<Foo>`
found struct `Foo`
@@ -37,7 +40,10 @@
LL | fn c() -> Result<Foo, Bar> {
| ---------------- expected `std::result::Result<Foo, Bar>` because of return type
LL | Foo { bar: 1 }
- | ^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `Foo`
+ | ^^^^^^^^^^^^^^
+ | |
+ | expected enum `std::result::Result`, found struct `Foo`
+ | help: try using a variant of the expected enum: `Ok(Foo { bar: 1 })`
|
= note: expected enum `std::result::Result<Foo, Bar>`
found struct `Foo`
diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
index 85cad61..ed50282 100644
--- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -45,4 +45,5 @@
error: aborting due to 5 previous errors
-For more information about this error, try `rustc --explain E0271`.
+Some errors have detailed explanations: E0271, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr
index fd2b9f3..f3874c0 100644
--- a/src/test/ui/mismatched_types/closure-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-mismatch.stderr
@@ -24,4 +24,5 @@
error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0271`.
+Some errors have detailed explanations: E0271, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr
index 1a82dd5..88c9266 100644
--- a/src/test/ui/mismatched_types/fn-variance-1.stderr
+++ b/src/test/ui/mismatched_types/fn-variance-1.stderr
@@ -24,3 +24,4 @@
error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr
index 72f3220..da018aa 100644
--- a/src/test/ui/mismatched_types/issue-36053-2.stderr
+++ b/src/test/ui/mismatched_types/issue-36053-2.stderr
@@ -18,4 +18,5 @@
error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0599`.
+Some errors have detailed explanations: E0599, E0631.
+For more information about an error, try `rustc --explain E0599`.
diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
index 2daf478..3c999f2 100644
--- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
+++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
@@ -12,3 +12,4 @@
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
index 1f15ce5c..3d79ff0 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -4,9 +4,9 @@
LL | let mut closure = expect_sig(|p, y| *p = y);
| ^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:4 ~ escape_argument_callee[317d]::test[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: test::{{closure}}#0 with closure substs [
i16,
- for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't0)) i32)),
+ for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) mut &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) i32)),
]
error: lifetime may not live long enough
@@ -30,7 +30,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:3 ~ escape_argument_callee[317d]::test[0]) with substs []
+ = note: defining type: test
error: aborting due to previous error
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr
index 610a4ae..37f04af 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr
@@ -4,9 +4,9 @@
LL | let mut closure = expect_sig(|p, y| *p = y);
| ^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:4 ~ escape_argument[317d]::test[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: test::{{closure}}#0 with closure substs [
i16,
- for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) i32)),
+ for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) mut &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32, &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32)),
]
note: No external requirements
@@ -21,7 +21,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:3 ~ escape_argument[317d]::test[0]) with substs []
+ = note: defining type: test
error[E0597]: `y` does not live long enough
--> $DIR/escape-argument.rs:27:25
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
index 7c4d48c..810c028 100644
--- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
@@ -4,7 +4,7 @@
LL | let mut closure1 = || p = &y;
| ^^^^^^^^^
|
- = note: defining type: DefId(0:5 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: test::{{closure}}#0::{{closure}}#0 with closure substs [
i16,
extern "rust-call" fn(()),
&'_#1r i32,
@@ -23,7 +23,7 @@
LL | | };
| |_________^
|
- = note: defining type: DefId(0:4 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: test::{{closure}}#0 with closure substs [
i16,
extern "rust-call" fn(()),
&'_#1r i32,
@@ -44,7 +44,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:3 ~ escape_upvar_nested[317d]::test[0]) with substs []
+ = note: defining type: test
error[E0597]: `y` does not live long enough
--> $DIR/escape-upvar-nested.rs:21:40
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
index 4446486..bf04276 100644
--- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
@@ -4,7 +4,7 @@
LL | let mut closure = || p = &y;
| ^^^^^^^^^
|
- = note: defining type: DefId(0:4 ~ escape_upvar_ref[317d]::test[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: test::{{closure}}#0 with closure substs [
i16,
extern "rust-call" fn(()),
&'_#1r i32,
@@ -25,7 +25,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:3 ~ escape_upvar_ref[317d]::test[0]) with substs []
+ = note: defining type: test
error[E0597]: `y` does not live long enough
--> $DIR/escape-upvar-ref.rs:23:35
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
index 43406c0..4e3aa35 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -8,9 +8,9 @@
LL | | },
| |_________^
|
- = note: defining type: DefId(0:18 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: supply::{{closure}}#0 with closure substs [
i16,
- for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>)),
+ for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)),
]
= note: late-bound region is '_#4r
= note: late-bound region is '_#5r
@@ -39,7 +39,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:14 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]) with substs []
+ = note: defining type: supply
error: aborting due to previous error
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
index 6f5b813..cd61b8b 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -9,9 +9,9 @@
LL | | });
| |_____^
|
- = note: defining type: DefId(0:16 ~ propagate_approximated_ref[317d]::supply[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: supply::{{closure}}#0 with closure substs [
i16,
- for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) u32>)),
+ for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>)),
]
= note: late-bound region is '_#3r
= note: late-bound region is '_#4r
@@ -30,7 +30,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:13 ~ propagate_approximated_ref[317d]::supply[0]) with substs []
+ = note: defining type: supply
error: lifetime may not live long enough
--> $DIR/propagate-approximated-ref.rs:45:9
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
index 5ebc22d..259140c 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -8,9 +8,9 @@
LL | | })
| |_____^
|
- = note: defining type: DefId(0:9 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: case1::{{closure}}#0 with closure substs [
i32,
- for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>)),
+ for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>)),
]
error[E0521]: borrowed data escapes outside of closure
@@ -35,7 +35,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:8 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]) with substs []
+ = note: defining type: case1
note: External requirements
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:35:15
@@ -46,9 +46,9 @@
LL | | })
| |_____^
|
- = note: defining type: DefId(0:11 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: case2::{{closure}}#0 with closure substs [
i32,
- for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>)),
+ for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>)),
]
= note: number of external vids: 2
= note: where '_#1r: '_#0r
@@ -65,7 +65,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:10 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]) with substs []
+ = note: defining type: case2
error[E0597]: `a` does not live long enough
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:30:26
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
index 5ebf8e2..b3dd682 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -10,9 +10,9 @@
LL | | });
| |_____^
|
- = note: defining type: DefId(0:16 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: supply::{{closure}}#0 with closure substs [
i16,
- for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't2)) u32>)),
+ for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t1)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t2)) u32>)),
]
= note: late-bound region is '_#2r
= note: late-bound region is '_#3r
@@ -31,7 +31,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:13 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]) with substs []
+ = note: defining type: supply
error[E0521]: borrowed data escapes outside of function
--> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:32:5
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
index 91caa42..ab12d08 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -10,9 +10,9 @@
LL | | });
| |_____^
|
- = note: defining type: DefId(0:16 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: supply::{{closure}}#0 with closure substs [
i16,
- for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't0)) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) u32>)),
+ for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>)),
]
= note: late-bound region is '_#3r
= note: late-bound region is '_#4r
@@ -31,7 +31,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:13 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]) with substs []
+ = note: defining type: supply
error[E0521]: borrowed data escapes outside of function
--> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:35:5
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
index 243c8b1..b2209e9 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -9,9 +9,9 @@
LL | | });
| |_____^
|
- = note: defining type: DefId(0:16 ~ propagate_approximated_val[317d]::test[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: test::{{closure}}#0 with closure substs [
i16,
- for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>)),
+ for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)),
]
= note: late-bound region is '_#3r
= note: late-bound region is '_#4r
@@ -30,7 +30,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:13 ~ propagate_approximated_val[317d]::test[0]) with substs []
+ = note: defining type: test
error: lifetime may not live long enough
--> $DIR/propagate-approximated-val.rs:38:9
diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
index c5468e7..55ee515 100644
--- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
@@ -8,9 +8,9 @@
LL | | },
| |_________^
|
- = note: defining type: DefId(0:14 ~ propagate_despite_same_free_region[317d]::supply[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: supply::{{closure}}#0 with closure substs [
i16,
- for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>)),
+ for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)),
]
= note: late-bound region is '_#3r
= note: number of external vids: 4
@@ -28,5 +28,5 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:12 ~ propagate_despite_same_free_region[317d]::supply[0]) with substs []
+ = note: defining type: supply
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
index bf43c89..1c29af8 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -9,9 +9,9 @@
LL | | });
| |_____^
|
- = note: defining type: DefId(0:16 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: supply::{{closure}}#0 with closure substs [
i16,
- for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>)),
+ for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)),
]
= note: late-bound region is '_#2r
= note: late-bound region is '_#3r
@@ -39,7 +39,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:13 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]) with substs []
+ = note: defining type: supply
error: aborting due to previous error
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
index 569bae9..afa0e9f 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -9,9 +9,9 @@
LL | | });
| |_____^
|
- = note: defining type: DefId(0:16 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: supply::{{closure}}#0 with closure substs [
i16,
- for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) u32>)),
+ for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>)),
]
= note: late-bound region is '_#3r
= note: late-bound region is '_#4r
@@ -39,7 +39,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:13 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]) with substs []
+ = note: defining type: supply
error: aborting due to previous error
diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
index 0d62265..0dbb530 100644
--- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
@@ -11,9 +11,7 @@
LL | | });
| |_____^
|
- = note: defining type: DefId(0:14 ~ propagate_from_trait_match[317d]::supply[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- T,
+ = note: defining type: supply::<'_#1r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((T,)),
]
@@ -32,10 +30,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:11 ~ propagate_from_trait_match[317d]::supply[0]) with substs [
- '_#1r,
- T,
- ]
+ = note: defining type: supply::<'_#1r, T>
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/propagate-from-trait-match.rs:32:36
diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
index 00c56a7..ca794d9 100644
--- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
+++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
@@ -4,9 +4,9 @@
LL | expect_sig(|a, b| b); // ought to return `a`
| ^^^^^^^^
|
- = note: defining type: DefId(0:4 ~ return_wrong_bound_region[317d]::test[0]::{{closure}}[0]) with closure substs [
+ = note: defining type: test::{{closure}}#0 with closure substs [
i16,
- for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) i32,
+ for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed('r)) i32,
]
error: lifetime may not live long enough
@@ -27,7 +27,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:3 ~ return_wrong_bound_region[317d]::test[0]) with substs []
+ = note: defining type: test
error: aborting due to previous error
diff --git a/src/test/ui/nll/issue-55394.stderr b/src/test/ui/nll/issue-55394.stderr
index 714a63b..69a6ab0 100644
--- a/src/test/ui/nll/issue-55394.stderr
+++ b/src/test/ui/nll/issue-55394.stderr
@@ -21,9 +21,13 @@
|
LL | impl Foo<'_> {
| ^^
- = note: ...so that the expression is assignable:
- expected Foo<'_>
- found Foo<'_>
+note: ...so that the expression is assignable
+ --> $DIR/issue-55394.rs:9:9
+ |
+LL | Foo { bar }
+ | ^^^^^^^^^^^
+ = note: expected `Foo<'_>`
+ found `Foo<'_>`
error: aborting due to previous error
diff --git a/src/test/ui/nll/normalization-bounds-error.stderr b/src/test/ui/nll/normalization-bounds-error.stderr
index 3a152fb..58f2067 100644
--- a/src/test/ui/nll/normalization-bounds-error.stderr
+++ b/src/test/ui/nll/normalization-bounds-error.stderr
@@ -14,9 +14,13 @@
|
LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
| ^^
- = note: ...so that the types are compatible:
- expected Visitor<'d>
- found Visitor<'_>
+note: ...so that the types are compatible
+ --> $DIR/normalization-bounds-error.rs:12:1
+ |
+LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: expected `Visitor<'d>`
+ found `Visitor<'_>`
error: aborting due to previous error
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
index dd61023..c825227 100644
--- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
@@ -4,9 +4,7 @@
LL | with_signature(x, |mut y| Box::new(y.next()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:13 ~ projection_no_regions_closure[317d]::no_region[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- T,
+ = note: defining type: no_region::<'_#1r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>,
]
@@ -25,10 +23,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:10 ~ projection_no_regions_closure[317d]::no_region[0]) with substs [
- '_#1r,
- T,
- ]
+ = note: defining type: no_region::<'_#1r, T>
error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
--> $DIR/projection-no-regions-closure.rs:25:23
@@ -44,9 +39,7 @@
LL | with_signature(x, |mut y| Box::new(y.next()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:17 ~ projection_no_regions_closure[317d]::correct_region[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- T,
+ = note: defining type: correct_region::<'_#1r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>,
]
@@ -64,10 +57,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:14 ~ projection_no_regions_closure[317d]::correct_region[0]) with substs [
- '_#1r,
- T,
- ]
+ = note: defining type: correct_region::<'_#1r, T>
note: External requirements
--> $DIR/projection-no-regions-closure.rs:42:23
@@ -75,10 +65,7 @@
LL | with_signature(x, |mut y| Box::new(y.next()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:22 ~ projection_no_regions_closure[317d]::wrong_region[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- T,
+ = note: defining type: wrong_region::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>,
]
@@ -97,11 +84,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:18 ~ projection_no_regions_closure[317d]::wrong_region[0]) with substs [
- '_#1r,
- '_#2r,
- T,
- ]
+ = note: defining type: wrong_region::<'_#1r, '_#2r, T>
error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
--> $DIR/projection-no-regions-closure.rs:42:23
@@ -117,10 +100,7 @@
LL | with_signature(x, |mut y| Box::new(y.next()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:27 ~ projection_no_regions_closure[317d]::outlives_region[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- T,
+ = note: defining type: outlives_region::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>,
]
@@ -139,11 +119,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:23 ~ projection_no_regions_closure[317d]::outlives_region[0]) with substs [
- '_#1r,
- '_#2r,
- T,
- ]
+ = note: defining type: outlives_region::<'_#1r, '_#2r, T>
error: aborting due to 2 previous errors
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
index d33f672..7226c52 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
@@ -4,9 +4,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:19 ~ projection_one_region_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- T,
+ = note: defining type: no_relationships_late::<'_#1r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
]
@@ -27,10 +25,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:15 ~ projection_one_region_closure[317d]::no_relationships_late[0]) with substs [
- '_#1r,
- T,
- ]
+ = note: defining type: no_relationships_late::<'_#1r, T>
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/projection-one-region-closure.rs:45:29
@@ -38,7 +33,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0:15 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(16), 'a))`...
+ = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0:15 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(DefId(0:16 ~ projection_one_region_closure[317d]::no_relationships_late[0]::'a[0]), 'a))`...
error: lifetime may not live long enough
--> $DIR/projection-one-region-closure.rs:45:39
@@ -59,10 +54,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:24 ~ projection_one_region_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- T,
+ = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
]
@@ -82,11 +74,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:20 ~ projection_one_region_closure[317d]::no_relationships_early[0]) with substs [
- '_#1r,
- '_#2r,
- T,
- ]
+ = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/projection-one-region-closure.rs:56:29
@@ -115,10 +103,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:29 ~ projection_one_region_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- T,
+ = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
]
@@ -137,11 +122,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:25 ~ projection_one_region_closure[317d]::projection_outlives[0]) with substs [
- '_#1r,
- '_#2r,
- T,
- ]
+ = note: defining type: projection_outlives::<'_#1r, '_#2r, T>
note: External requirements
--> $DIR/projection-one-region-closure.rs:80:29
@@ -149,10 +130,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:34 ~ projection_one_region_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- T,
+ = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
]
@@ -172,11 +150,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:30 ~ projection_one_region_closure[317d]::elements_outlive[0]) with substs [
- '_#1r,
- '_#2r,
- T,
- ]
+ = note: defining type: elements_outlive::<'_#1r, '_#2r, T>
error: aborting due to 4 previous errors
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
index 0be25de..655995c 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
@@ -4,9 +4,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:19 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- T,
+ = note: defining type: no_relationships_late::<'_#1r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
]
@@ -26,10 +24,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:15 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]) with substs [
- '_#1r,
- T,
- ]
+ = note: defining type: no_relationships_late::<'_#1r, T>
error: lifetime may not live long enough
--> $DIR/projection-one-region-trait-bound-closure.rs:37:39
@@ -50,10 +45,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:24 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- T,
+ = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
]
@@ -72,11 +64,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:20 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_early[0]) with substs [
- '_#1r,
- '_#2r,
- T,
- ]
+ = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>
error: lifetime may not live long enough
--> $DIR/projection-one-region-trait-bound-closure.rs:47:39
@@ -97,10 +85,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:29 ~ projection_one_region_trait_bound_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- T,
+ = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
]
@@ -119,11 +104,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:25 ~ projection_one_region_trait_bound_closure[317d]::projection_outlives[0]) with substs [
- '_#1r,
- '_#2r,
- T,
- ]
+ = note: defining type: projection_outlives::<'_#1r, '_#2r, T>
note: External requirements
--> $DIR/projection-one-region-trait-bound-closure.rs:69:29
@@ -131,10 +112,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:34 ~ projection_one_region_trait_bound_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- T,
+ = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
]
@@ -153,11 +131,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:30 ~ projection_one_region_trait_bound_closure[317d]::elements_outlive[0]) with substs [
- '_#1r,
- '_#2r,
- T,
- ]
+ = note: defining type: elements_outlive::<'_#1r, '_#2r, T>
note: External requirements
--> $DIR/projection-one-region-trait-bound-closure.rs:81:29
@@ -165,9 +139,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:38 ~ projection_one_region_trait_bound_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- T,
+ = note: defining type: one_region::<'_#1r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
]
@@ -186,10 +158,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:35 ~ projection_one_region_trait_bound_closure[317d]::one_region[0]) with substs [
- '_#1r,
- T,
- ]
+ = note: defining type: one_region::<'_#1r, T>
error: aborting due to 2 previous errors
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
index 9cc2e50..2fb07b9 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
@@ -4,9 +4,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:19 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- T,
+ = note: defining type: no_relationships_late::<'_#1r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
]
@@ -23,10 +21,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:15 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_late[0]) with substs [
- '_#1r,
- T,
- ]
+ = note: defining type: no_relationships_late::<'_#1r, T>
note: No external requirements
--> $DIR/projection-one-region-trait-bound-static-closure.rs:45:29
@@ -34,10 +29,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:24 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- T,
+ = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
]
@@ -54,11 +46,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:20 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_early[0]) with substs [
- '_#1r,
- '_#2r,
- T,
- ]
+ = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>
note: No external requirements
--> $DIR/projection-one-region-trait-bound-static-closure.rs:64:29
@@ -66,10 +54,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:29 ~ projection_one_region_trait_bound_static_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- T,
+ = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
]
@@ -86,11 +71,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:25 ~ projection_one_region_trait_bound_static_closure[317d]::projection_outlives[0]) with substs [
- '_#1r,
- '_#2r,
- T,
- ]
+ = note: defining type: projection_outlives::<'_#1r, '_#2r, T>
note: No external requirements
--> $DIR/projection-one-region-trait-bound-static-closure.rs:73:29
@@ -98,10 +79,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:34 ~ projection_one_region_trait_bound_static_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- T,
+ = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
]
@@ -118,11 +96,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:30 ~ projection_one_region_trait_bound_static_closure[317d]::elements_outlive[0]) with substs [
- '_#1r,
- '_#2r,
- T,
- ]
+ = note: defining type: elements_outlive::<'_#1r, '_#2r, T>
note: No external requirements
--> $DIR/projection-one-region-trait-bound-static-closure.rs:85:29
@@ -130,9 +104,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:38 ~ projection_one_region_trait_bound_static_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- T,
+ = note: defining type: one_region::<'_#1r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
]
@@ -149,8 +121,5 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:35 ~ projection_one_region_trait_bound_static_closure[317d]::one_region[0]) with substs [
- '_#1r,
- T,
- ]
+ = note: defining type: one_region::<'_#1r, T>
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
index ed548a3..501a55e3 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
@@ -4,10 +4,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:22 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- T,
+ = note: defining type: no_relationships_late::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
]
@@ -27,11 +24,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:17 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]) with substs [
- '_#1r,
- '_#2r,
- T,
- ]
+ = note: defining type: no_relationships_late::<'_#1r, '_#2r, T>
error[E0309]: the associated type `<T as Anything<'_#5r, '_#6r>>::AssocType` may not live long enough
--> $DIR/projection-two-region-trait-bound-closure.rs:38:29
@@ -39,7 +32,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = help: consider adding an explicit lifetime bound `<T as Anything<'_#5r, '_#6r>>::AssocType: ReFree(DefId(0:17 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(18), 'a))`...
+ = help: consider adding an explicit lifetime bound `<T as Anything<'_#5r, '_#6r>>::AssocType: ReFree(DefId(0:17 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(DefId(0:18 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]::'a[0]), 'a))`...
note: External requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:48:29
@@ -47,11 +40,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:28 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- '_#3r,
- T,
+ = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
]
@@ -70,12 +59,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:23 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_early[0]) with substs [
- '_#1r,
- '_#2r,
- '_#3r,
- T,
- ]
+ = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T>
error[E0309]: the associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
--> $DIR/projection-two-region-trait-bound-closure.rs:48:29
@@ -91,11 +75,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:34 ~ projection_two_region_trait_bound_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- '_#3r,
- T,
+ = note: defining type: projection_outlives::<'_#1r, '_#2r, '_#3r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
]
@@ -114,12 +94,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:29 ~ projection_two_region_trait_bound_closure[317d]::projection_outlives[0]) with substs [
- '_#1r,
- '_#2r,
- '_#3r,
- T,
- ]
+ = note: defining type: projection_outlives::<'_#1r, '_#2r, '_#3r, T>
note: External requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:70:29
@@ -127,11 +102,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:40 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive1[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- '_#3r,
- T,
+ = note: defining type: elements_outlive1::<'_#1r, '_#2r, '_#3r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
]
@@ -150,12 +121,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:35 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive1[0]) with substs [
- '_#1r,
- '_#2r,
- '_#3r,
- T,
- ]
+ = note: defining type: elements_outlive1::<'_#1r, '_#2r, '_#3r, T>
note: External requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:79:29
@@ -163,11 +129,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:46 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive2[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- '_#3r,
- T,
+ = note: defining type: elements_outlive2::<'_#1r, '_#2r, '_#3r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
]
@@ -186,12 +148,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:41 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive2[0]) with substs [
- '_#1r,
- '_#2r,
- '_#3r,
- T,
- ]
+ = note: defining type: elements_outlive2::<'_#1r, '_#2r, '_#3r, T>
note: External requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:87:29
@@ -199,9 +156,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:51 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- T,
+ = note: defining type: two_regions::<'_#1r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
]
@@ -221,10 +176,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:47 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]) with substs [
- '_#1r,
- T,
- ]
+ = note: defining type: two_regions::<'_#1r, T>
error: lifetime may not live long enough
--> $DIR/projection-two-region-trait-bound-closure.rs:87:29
@@ -245,10 +197,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:56 ~ projection_two_region_trait_bound_closure[317d]::two_regions_outlive[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- T,
+ = note: defining type: two_regions_outlive::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
]
@@ -267,11 +216,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:52 ~ projection_two_region_trait_bound_closure[317d]::two_regions_outlive[0]) with substs [
- '_#1r,
- '_#2r,
- T,
- ]
+ = note: defining type: two_regions_outlive::<'_#1r, '_#2r, T>
note: External requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:109:29
@@ -279,9 +224,7 @@
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:60 ~ projection_two_region_trait_bound_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- T,
+ = note: defining type: one_region::<'_#1r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
]
@@ -300,10 +243,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:57 ~ projection_two_region_trait_bound_closure[317d]::one_region[0]) with substs [
- '_#1r,
- T,
- ]
+ = note: defining type: one_region::<'_#1r, T>
error: aborting due to 3 previous errors
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
index fd8d891..db0bca1 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
@@ -4,10 +4,9 @@
LL | twice(cell, value, |a, b| invoke(a, b));
| ^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:11 ~ ty_param_closure_approximate_lower_bound[317d]::generic[0]::{{closure}}[0]) with closure substs [
- T,
+ = note: defining type: generic::<T>::{{closure}}#0 with closure substs [
i16,
- for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) T)),
+ for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed('s)) T)),
]
= note: number of external vids: 2
= note: where T: '_#1r
@@ -21,9 +20,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:9 ~ ty_param_closure_approximate_lower_bound[317d]::generic[0]) with substs [
- T,
- ]
+ = note: defining type: generic::<T>
note: External requirements
--> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24
@@ -31,10 +28,9 @@
LL | twice(cell, value, |a, b| invoke(a, b));
| ^^^^^^^^^^^^^^^^^^^
|
- = note: defining type: DefId(0:15 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]::{{closure}}[0]) with closure substs [
- T,
+ = note: defining type: generic_fail::<T>::{{closure}}#0 with closure substs [
i16,
- for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) T)),
+ for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed('s)) T)),
]
= note: late-bound region is '_#2r
= note: number of external vids: 3
@@ -49,9 +45,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:12 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]) with substs [
- T,
- ]
+ = note: defining type: generic_fail::<T>
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24
@@ -59,7 +53,7 @@
LL | twice(cell, value, |a, b| invoke(a, b));
| ^^^^^^^^^^^^^^^^^^^
|
- = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0:12 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(crate0:DefIndex(13), 'a))`...
+ = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0:12 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(DefId(0:13 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]::'a[0]), 'a))`...
error: aborting due to previous error
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
index 7c8dc94..0021d73 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
@@ -4,9 +4,7 @@
LL | with_signature(x, |y| y)
| ^^^^^
|
- = note: defining type: DefId(0:11 ~ ty_param_closure_outlives_from_return_type[317d]::no_region[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- T,
+ = note: defining type: no_region::<'_#1r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn std::fmt::Debug + '_#2r)>,
]
@@ -25,10 +23,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:8 ~ ty_param_closure_outlives_from_return_type[317d]::no_region[0]) with substs [
- '_#1r,
- T,
- ]
+ = note: defining type: no_region::<'_#1r, T>
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
index 97b84d1..46fef8e 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
@@ -11,8 +11,7 @@
LL | | })
| |_____^
|
- = note: defining type: DefId(0:14 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]::{{closure}}[0]) with closure substs [
- T,
+ = note: defining type: no_region::<T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#1r ()>, T)),
]
@@ -32,9 +31,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:11 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]) with substs [
- T,
- ]
+ = note: defining type: no_region::<T>
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26
@@ -49,7 +46,7 @@
LL | | })
| |_____^
|
- = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0:11 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(12), 'a))`...
+ = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0:11 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(DefId(0:12 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]::'a[0]), 'a))`...
note: External requirements
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:43:26
@@ -64,9 +61,7 @@
LL | | })
| |_____^
|
- = note: defining type: DefId(0:18 ~ ty_param_closure_outlives_from_where_clause[317d]::correct_region[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- T,
+ = note: defining type: correct_region::<'_#1r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
]
@@ -85,10 +80,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:15 ~ ty_param_closure_outlives_from_where_clause[317d]::correct_region[0]) with substs [
- '_#1r,
- T,
- ]
+ = note: defining type: correct_region::<'_#1r, T>
note: External requirements
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26
@@ -101,9 +93,7 @@
LL | | })
| |_____^
|
- = note: defining type: DefId(0:23 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- T,
+ = note: defining type: wrong_region::<'_#1r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
]
@@ -123,10 +113,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:19 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]) with substs [
- '_#1r,
- T,
- ]
+ = note: defining type: wrong_region::<'_#1r, T>
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26
@@ -139,7 +126,7 @@
LL | | })
| |_____^
|
- = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0:19 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(20), 'a))`...
+ = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0:19 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(DefId(0:20 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]::'a[0]), 'a))`...
note: External requirements
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:77:26
@@ -151,10 +138,7 @@
LL | | })
| |_____^
|
- = note: defining type: DefId(0:28 ~ ty_param_closure_outlives_from_where_clause[317d]::outlives_region[0]::{{closure}}[0]) with closure substs [
- '_#1r,
- '_#2r,
- T,
+ = note: defining type: outlives_region::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
i32,
extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
]
@@ -173,11 +157,7 @@
LL | | }
| |_^
|
- = note: defining type: DefId(0:24 ~ ty_param_closure_outlives_from_where_clause[317d]::outlives_region[0]) with substs [
- '_#1r,
- '_#2r,
- T,
- ]
+ = note: defining type: outlives_region::<'_#1r, '_#2r, T>
error: aborting due to 2 previous errors
diff --git a/src/test/ui/nll/type-alias-free-regions.stderr b/src/test/ui/nll/type-alias-free-regions.stderr
index 6986389..5191dec 100644
--- a/src/test/ui/nll/type-alias-free-regions.stderr
+++ b/src/test/ui/nll/type-alias-free-regions.stderr
@@ -11,17 +11,25 @@
LL | | C { f: b }
LL | | }
| |_____^
- = note: ...so that the expression is assignable:
- expected std::boxed::Box<std::boxed::Box<&isize>>
- found std::boxed::Box<std::boxed::Box<&isize>>
+note: ...so that the expression is assignable
+ --> $DIR/type-alias-free-regions.rs:17:16
+ |
+LL | C { f: b }
+ | ^
+ = note: expected `std::boxed::Box<std::boxed::Box<&isize>>`
+ found `std::boxed::Box<std::boxed::Box<&isize>>`
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 15:6...
--> $DIR/type-alias-free-regions.rs:15:6
|
LL | impl<'a> FromBox<'a> for C<'a> {
| ^^
- = note: ...so that the expression is assignable:
- expected C<'a>
- found C<'_>
+note: ...so that the expression is assignable
+ --> $DIR/type-alias-free-regions.rs:17:9
+ |
+LL | C { f: b }
+ | ^^^^^^^^^^
+ = note: expected `C<'a>`
+ found `C<'_>`
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> $DIR/type-alias-free-regions.rs:27:16
@@ -36,17 +44,25 @@
LL | | C { f: Box::new(b.0) }
LL | | }
| |_____^
- = note: ...so that the expression is assignable:
- expected std::boxed::Box<&isize>
- found std::boxed::Box<&isize>
+note: ...so that the expression is assignable
+ --> $DIR/type-alias-free-regions.rs:27:25
+ |
+LL | C { f: Box::new(b.0) }
+ | ^^^
+ = note: expected `std::boxed::Box<&isize>`
+ found `std::boxed::Box<&isize>`
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 25:6...
--> $DIR/type-alias-free-regions.rs:25:6
|
LL | impl<'a> FromTuple<'a> for C<'a> {
| ^^
- = note: ...so that the expression is assignable:
- expected C<'a>
- found C<'_>
+note: ...so that the expression is assignable
+ --> $DIR/type-alias-free-regions.rs:27:9
+ |
+LL | C { f: Box::new(b.0) }
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ = note: expected `C<'a>`
+ found `C<'_>`
error: aborting due to 2 previous errors
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
index 4ebd991..37be450 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
@@ -9,9 +9,13 @@
|
LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
| ^^
- = note: ...so that the types are compatible:
- expected Foo<'_>
- found Foo<'a>
+note: ...so that the types are compatible
+ --> $DIR/constant-in-expr-inherent-1.rs:8:5
+ |
+LL | <Foo<'a>>::C
+ | ^^^^^^^^^^^^
+ = note: expected `Foo<'_>`
+ found `Foo<'a>`
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that reference does not outlive borrowed content
--> $DIR/constant-in-expr-inherent-1.rs:8:5
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
index d61659e..4ee3284 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
@@ -9,9 +9,13 @@
|
LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 {
| ^^
- = note: ...so that the types are compatible:
- expected Foo<'_>
- found Foo<'a>
+note: ...so that the types are compatible
+ --> $DIR/constant-in-expr-trait-item-3.rs:10:5
+ |
+LL | T::C
+ | ^^^^
+ = note: expected `Foo<'_>`
+ found `Foo<'a>`
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that reference does not outlive borrowed content
--> $DIR/constant-in-expr-trait-item-3.rs:10:5
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr
index d66322c..1952ee8 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr
+++ b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr
@@ -19,9 +19,13 @@
|
LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
| ^^
- = note: ...so that the expression is assignable:
- expected &'b (dyn SomeTrait + 'b)
- found &dyn SomeTrait
+note: ...so that the expression is assignable
+ --> $DIR/object-lifetime-default-elision.rs:71:5
+ |
+LL | ss
+ | ^^
+ = note: expected `&'b (dyn SomeTrait + 'b)`
+ found `&dyn SomeTrait`
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> $DIR/object-lifetime-default-elision.rs:71:5
@@ -44,9 +48,13 @@
|
LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
| ^^
- = note: ...so that the expression is assignable:
- expected &'b (dyn SomeTrait + 'b)
- found &dyn SomeTrait
+note: ...so that the expression is assignable
+ --> $DIR/object-lifetime-default-elision.rs:71:5
+ |
+LL | ss
+ | ^^
+ = note: expected `&'b (dyn SomeTrait + 'b)`
+ found `&dyn SomeTrait`
error: aborting due to 2 previous errors
diff --git a/src/test/ui/on-unimplemented/enclosing-scope.rs b/src/test/ui/on-unimplemented/enclosing-scope.rs
new file mode 100644
index 0000000..881bff6
--- /dev/null
+++ b/src/test/ui/on-unimplemented/enclosing-scope.rs
@@ -0,0 +1,27 @@
+// Test scope annotations from `enclosing_scope` parameter
+
+#![feature(rustc_attrs)]
+
+#[rustc_on_unimplemented(enclosing_scope="in this scope")]
+trait Trait{}
+
+struct Foo;
+
+fn f<T: Trait>(x: T) {}
+
+fn main() {
+ let x = || {
+ f(Foo{}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+ let y = || {
+ f(Foo{}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+ };
+ };
+
+ {
+ {
+ f(Foo{}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+ }
+ }
+
+ f(Foo{}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+}
diff --git a/src/test/ui/on-unimplemented/enclosing-scope.stderr b/src/test/ui/on-unimplemented/enclosing-scope.stderr
new file mode 100644
index 0000000..092e560
--- /dev/null
+++ b/src/test/ui/on-unimplemented/enclosing-scope.stderr
@@ -0,0 +1,66 @@
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+ --> $DIR/enclosing-scope.rs:14:11
+ |
+LL | fn f<T: Trait>(x: T) {}
+ | - ----- required by this bound in `f`
+...
+LL | let x = || {
+ | _____________-
+LL | | f(Foo{});
+ | | ^^^^^ the trait `Trait` is not implemented for `Foo`
+LL | | let y = || {
+LL | | f(Foo{});
+LL | | };
+LL | | };
+ | |_____- in this scope
+
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+ --> $DIR/enclosing-scope.rs:16:15
+ |
+LL | fn f<T: Trait>(x: T) {}
+ | - ----- required by this bound in `f`
+...
+LL | let y = || {
+ | _________________-
+LL | | f(Foo{});
+ | | ^^^^^ the trait `Trait` is not implemented for `Foo`
+LL | | };
+ | |_________- in this scope
+
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+ --> $DIR/enclosing-scope.rs:22:15
+ |
+LL | fn f<T: Trait>(x: T) {}
+ | - ----- required by this bound in `f`
+LL |
+LL | / fn main() {
+LL | | let x = || {
+LL | | f(Foo{});
+LL | | let y = || {
+... |
+LL | | f(Foo{});
+ | | ^^^^^ the trait `Trait` is not implemented for `Foo`
+... |
+LL | | f(Foo{});
+LL | | }
+ | |_- in this scope
+
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+ --> $DIR/enclosing-scope.rs:26:7
+ |
+LL | fn f<T: Trait>(x: T) {}
+ | - ----- required by this bound in `f`
+LL |
+LL | / fn main() {
+LL | | let x = || {
+LL | | f(Foo{});
+LL | | let y = || {
+... |
+LL | | f(Foo{});
+ | | ^^^^^ the trait `Trait` is not implemented for `Foo`
+LL | | }
+ | |_- in this scope
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/on-unimplemented/expected-comma-found-token.rs b/src/test/ui/on-unimplemented/expected-comma-found-token.rs
index 77c0ea1..8fb34f2 100644
--- a/src/test/ui/on-unimplemented/expected-comma-found-token.rs
+++ b/src/test/ui/on-unimplemented/expected-comma-found-token.rs
@@ -6,7 +6,7 @@
#[rustc_on_unimplemented(
message="the message"
- label="the label" //~ ERROR expected one of `)` or `,`, found `label`
+ label="the label" //~ ERROR expected `,`, found `label`
)]
trait T {}
diff --git a/src/test/ui/on-unimplemented/expected-comma-found-token.stderr b/src/test/ui/on-unimplemented/expected-comma-found-token.stderr
index 2e1d484..048b72e 100644
--- a/src/test/ui/on-unimplemented/expected-comma-found-token.stderr
+++ b/src/test/ui/on-unimplemented/expected-comma-found-token.stderr
@@ -1,11 +1,8 @@
-error: expected one of `)` or `,`, found `label`
+error: expected `,`, found `label`
--> $DIR/expected-comma-found-token.rs:9:5
|
LL | message="the message"
- | -
- | |
- | expected one of `)` or `,`
- | help: missing `,`
+ | - expected `,`
LL | label="the label"
| ^^^^^ unexpected token
diff --git a/src/test/ui/or-patterns/exhaustiveness-pass.rs b/src/test/ui/or-patterns/exhaustiveness-pass.rs
index 62a8517..ce0fe6f 100644
--- a/src/test/ui/or-patterns/exhaustiveness-pass.rs
+++ b/src/test/ui/or-patterns/exhaustiveness-pass.rs
@@ -6,35 +6,40 @@
// We wrap patterns in a tuple because top-level or-patterns are special-cased for now.
fn main() {
// Get the fatal error out of the way
- match (0u8,) {
+ match (0,) {
(0 | _,) => {}
//~^ ERROR or-patterns are not fully implemented yet
}
- match (0u8,) {
+ match (0,) {
(1 | 2,) => {}
_ => {}
}
- match (0u8,) {
- (1 | 1,) => {} // FIXME(or_patterns): redundancy not detected for now.
- _ => {}
- }
- match (0u8, 0u8) {
+ match (0, 0) {
(1 | 2, 3 | 4) => {}
(1, 2) => {}
- (2, 1) => {}
+ (3, 1) => {}
_ => {}
}
match (Some(0u8),) {
(None | Some(0 | 1),) => {}
(Some(2..=255),) => {}
}
- match ((0u8,),) {
+ match ((0,),) {
((0 | 1,) | (2 | 3,),) => {},
((_,),) => {},
}
match (&[0u8][..],) {
([] | [0 | 1..=255] | [_, ..],) => {},
}
+
+ match ((0, 0),) {
+ ((0, 0) | (0, 1),) => {}
+ _ => {}
+ }
+ match ((0, 0),) {
+ ((0, 0) | (1, 0),) => {}
+ _ => {}
+ }
}
diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
index 2cd8ca2..860c7a1 100644
--- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
+++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
@@ -48,4 +48,32 @@
((1..=4,),) => {}, //~ ERROR unreachable pattern
_ => {},
}
+
+ match (0,) {
+ (1
+ | 1,) => {} //~ ERROR unreachable
+ _ => {}
+ }
+ match [0; 2] {
+ [0
+ | 0 //~ ERROR unreachable
+ , 0
+ | 0] => {} //~ ERROR unreachable
+ _ => {}
+ }
+ match &[][..] {
+ [0] => {}
+ [0, _] => {}
+ [0, _, _] => {}
+ [1, ..] => {}
+ [1 //~ ERROR unreachable
+ | 2, ..] => {}
+ _ => {}
+ }
+ match Some(0) {
+ Some(0) => {}
+ Some(0 //~ ERROR unreachable
+ | 1) => {}
+ _ => {}
+ }
}
diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
index a4d55d8..87f69a4 100644
--- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
+++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
@@ -70,11 +70,41 @@
LL | ((1..=4,),) => {},
| ^^^^^^^^^^^
+error: unreachable pattern
+ --> $DIR/exhaustiveness-unreachable-pattern.rs:54:12
+ |
+LL | | 1,) => {}
+ | ^
+
+error: unreachable pattern
+ --> $DIR/exhaustiveness-unreachable-pattern.rs:61:15
+ |
+LL | | 0] => {}
+ | ^
+
+error: unreachable pattern
+ --> $DIR/exhaustiveness-unreachable-pattern.rs:59:15
+ |
+LL | | 0
+ | ^
+
+error: unreachable pattern
+ --> $DIR/exhaustiveness-unreachable-pattern.rs:69:10
+ |
+LL | [1
+ | ^
+
+error: unreachable pattern
+ --> $DIR/exhaustiveness-unreachable-pattern.rs:75:14
+ |
+LL | Some(0
+ | ^
+
error: or-patterns are not fully implemented yet
--> $DIR/exhaustiveness-unreachable-pattern.rs:10:10
|
LL | (0 | _,) => {}
| ^^^^^
-error: aborting due to 12 previous errors
+error: aborting due to 17 previous errors
diff --git a/src/test/ui/parser/macro-bad-delimiter-ident.rs b/src/test/ui/parser/macro-bad-delimiter-ident.rs
index 13dec95..f461f06 100644
--- a/src/test/ui/parser/macro-bad-delimiter-ident.rs
+++ b/src/test/ui/parser/macro-bad-delimiter-ident.rs
@@ -1,3 +1,3 @@
fn main() {
- foo! bar < //~ ERROR expected open delimiter
+ foo! bar < //~ ERROR expected one of `(`, `[`, or `{`, found `bar`
}
diff --git a/src/test/ui/parser/macro-bad-delimiter-ident.stderr b/src/test/ui/parser/macro-bad-delimiter-ident.stderr
index e97839a..f2365fe 100644
--- a/src/test/ui/parser/macro-bad-delimiter-ident.stderr
+++ b/src/test/ui/parser/macro-bad-delimiter-ident.stderr
@@ -1,8 +1,8 @@
-error: expected open delimiter
+error: expected one of `(`, `[`, or `{`, found `bar`
--> $DIR/macro-bad-delimiter-ident.rs:2:10
|
LL | foo! bar <
- | ^^^ expected open delimiter
+ | ^^^ expected one of `(`, `[`, or `{`
error: aborting due to previous error
diff --git a/src/test/ui/parser/raw/raw-literal-keywords.rs b/src/test/ui/parser/raw/raw-literal-keywords.rs
index bf9cbcd..a986980 100644
--- a/src/test/ui/parser/raw/raw-literal-keywords.rs
+++ b/src/test/ui/parser/raw/raw-literal-keywords.rs
@@ -11,11 +11,11 @@
}
fn test_if_2() {
- let _ = r#if; //~ ERROR cannot find value `if` in this scope
+ let _ = r#if; //~ ERROR cannot find value `r#if` in this scope
}
fn test_struct_2() {
- let _ = r#struct; //~ ERROR cannot find value `struct` in this scope
+ let _ = r#struct; //~ ERROR cannot find value `r#struct` in this scope
}
fn test_union_2() {
diff --git a/src/test/ui/parser/raw/raw-literal-keywords.stderr b/src/test/ui/parser/raw/raw-literal-keywords.stderr
index fd8eda3..f7b6c89 100644
--- a/src/test/ui/parser/raw/raw-literal-keywords.stderr
+++ b/src/test/ui/parser/raw/raw-literal-keywords.stderr
@@ -16,13 +16,13 @@
LL | r#union Test;
| ^^^^ expected one of 8 possible tokens
-error[E0425]: cannot find value `if` in this scope
+error[E0425]: cannot find value `r#if` in this scope
--> $DIR/raw-literal-keywords.rs:14:13
|
LL | let _ = r#if;
| ^^^^ not found in this scope
-error[E0425]: cannot find value `struct` in this scope
+error[E0425]: cannot find value `r#struct` in this scope
--> $DIR/raw-literal-keywords.rs:18:13
|
LL | let _ = r#struct;
diff --git a/src/test/ui/pattern/usefulness/top-level-alternation.rs b/src/test/ui/pattern/usefulness/top-level-alternation.rs
new file mode 100644
index 0000000..4b47b97
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/top-level-alternation.rs
@@ -0,0 +1,56 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+ while let 0..=2 | 1 = 0 {} //~ ERROR unreachable pattern
+ if let 0..=2 | 1 = 0 {} //~ ERROR unreachable pattern
+
+ match 0u8 {
+ 0
+ | 0 => {} //~ ERROR unreachable pattern
+ _ => {}
+ }
+ match Some(0u8) {
+ Some(0)
+ | Some(0) => {} //~ ERROR unreachable pattern
+ _ => {}
+ }
+ match (0u8, 0u8) {
+ (0, _) | (_, 0) => {}
+ (0, 0) => {} //~ ERROR unreachable pattern
+ (1, 1) => {}
+ _ => {}
+ }
+ match (0u8, 0u8) {
+ (0, 1) | (2, 3) => {}
+ (0, 3) => {}
+ (2, 1) => {}
+ _ => {}
+ }
+ match (0u8, 0u8) {
+ (_, 0) | (_, 1) => {}
+ _ => {}
+ }
+ match (0u8, 0u8) {
+ (0, _) | (1, _) => {}
+ _ => {}
+ }
+ match Some(0u8) {
+ None | Some(_) => {}
+ _ => {} //~ ERROR unreachable pattern
+ }
+ match Some(0u8) {
+ None | Some(_) => {}
+ Some(_) => {} //~ ERROR unreachable pattern
+ None => {} //~ ERROR unreachable pattern
+ }
+ match Some(0u8) {
+ Some(_) => {}
+ None => {}
+ None | Some(_) => {} //~ ERROR unreachable pattern
+ }
+ match 0u8 {
+ 1 | 2 => {},
+ 1..=2 => {}, //~ ERROR unreachable pattern
+ _ => {},
+ }
+}
diff --git a/src/test/ui/pattern/usefulness/top-level-alternation.stderr b/src/test/ui/pattern/usefulness/top-level-alternation.stderr
new file mode 100644
index 0000000..7c7c4fc
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/top-level-alternation.stderr
@@ -0,0 +1,68 @@
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:4:23
+ |
+LL | while let 0..=2 | 1 = 0 {}
+ | ^
+ |
+note: lint level defined here
+ --> $DIR/top-level-alternation.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:5:20
+ |
+LL | if let 0..=2 | 1 = 0 {}
+ | ^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:9:15
+ |
+LL | | 0 => {}
+ | ^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:14:15
+ |
+LL | | Some(0) => {}
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:19:9
+ |
+LL | (0, 0) => {}
+ | ^^^^^^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:39:9
+ |
+LL | _ => {}
+ | ^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:43:9
+ |
+LL | Some(_) => {}
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:44:9
+ |
+LL | None => {}
+ | ^^^^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:49:9
+ |
+LL | None | Some(_) => {}
+ | ^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:53:9
+ |
+LL | 1..=2 => {},
+ | ^^^^^
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/proc-macro/proc-macro-gates.rs b/src/test/ui/proc-macro/proc-macro-gates.rs
index 0096a84..591c1e0 100644
--- a/src/test/ui/proc-macro/proc-macro-gates.rs
+++ b/src/test/ui/proc-macro/proc-macro-gates.rs
@@ -18,7 +18,7 @@
//~| ERROR: non-builtin inner attributes are unstable
}
-#[empty_attr = "y"] //~ ERROR: must only be followed by a delimiter token
+#[empty_attr = "y"] //~ ERROR: key-value macro attributes are not supported
fn _test3() {}
fn attrs() {
diff --git a/src/test/ui/proc-macro/proc-macro-gates.stderr b/src/test/ui/proc-macro/proc-macro-gates.stderr
index 14a4f8c..e939434 100644
--- a/src/test/ui/proc-macro/proc-macro-gates.stderr
+++ b/src/test/ui/proc-macro/proc-macro-gates.stderr
@@ -34,7 +34,7 @@
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
-error: custom attribute invocations must be of the form `#[foo]` or `#[foo(..)]`, the macro name must only be followed by a delimiter token
+error: key-value macro attributes are not supported
--> $DIR/proc-macro-gates.rs:21:1
|
LL | #[empty_attr = "y"]
diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr
index cd6f0ea..a77e920 100644
--- a/src/test/ui/proc-macro/span-preservation.stderr
+++ b/src/test/ui/proc-macro/span-preservation.stderr
@@ -14,6 +14,11 @@
LL | match x {
LL | Some(x) => { return x },
| ^ expected `usize`, found `isize`
+ |
+help: you can convert an `isize` to `usize` and panic if the converted value wouldn't fit
+ |
+LL | Some(x) => { return x.try_into().unwrap() },
+ | ^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/span-preservation.rs:33:22
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
index 14934d6..e889651 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
@@ -34,17 +34,25 @@
|
LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
| ^^
- = note: ...so that the expression is assignable:
- expected &[u8]
- found &'a [u8]
+note: ...so that the expression is assignable
+ --> $DIR/region-object-lifetime-in-coercion.rs:26:14
+ |
+LL | Box::new(v)
+ | ^
+ = note: expected `&[u8]`
+ found `&'a [u8]`
note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 25:9...
--> $DIR/region-object-lifetime-in-coercion.rs:25:9
|
LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
| ^^
- = note: ...so that the expression is assignable:
- expected std::boxed::Box<(dyn Foo + 'b)>
- found std::boxed::Box<dyn Foo>
+note: ...so that the expression is assignable
+ --> $DIR/region-object-lifetime-in-coercion.rs:26:5
+ |
+LL | Box::new(v)
+ | ^^^^^^^^^^^
+ = note: expected `std::boxed::Box<(dyn Foo + 'b)>`
+ found `std::boxed::Box<dyn Foo>`
error: aborting due to 4 previous errors
diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr
index a636c9e..865e967 100644
--- a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr
+++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr
@@ -9,9 +9,13 @@
|
LL | impl<'a> Foo<'static> for &'a i32 {
| ^^
- = note: ...so that the types are compatible:
- expected Foo<'static>
- found Foo<'static>
+note: ...so that the types are compatible
+ --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10
+ |
+LL | impl<'a> Foo<'static> for &'a i32 {
+ | ^^^^^^^^^^^^
+ = note: expected `Foo<'static>`
+ found `Foo<'static>`
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `&i32` will meet its required lifetime bounds
--> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10
@@ -30,9 +34,13 @@
|
LL | impl<'a,'b> Foo<'b> for &'a i64 {
| ^^
- = note: ...so that the types are compatible:
- expected Foo<'b>
- found Foo<'_>
+note: ...so that the types are compatible
+ --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13
+ |
+LL | impl<'a,'b> Foo<'b> for &'a i64 {
+ | ^^^^^^^
+ = note: expected `Foo<'b>`
+ found `Foo<'_>`
note: but, the lifetime must be valid for the lifetime `'b` as defined on the impl at 19:9...
--> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:9
|
diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr
index 81256e3..6a34871 100644
--- a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr
+++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr
@@ -9,9 +9,13 @@
|
LL | impl<'a> Foo for &'a i32 {
| ^^
- = note: ...so that the types are compatible:
- expected Foo
- found Foo
+note: ...so that the types are compatible
+ --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10
+ |
+LL | impl<'a> Foo for &'a i32 {
+ | ^^^
+ = note: expected `Foo`
+ found `Foo`
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `&i32` will meet its required lifetime bounds
--> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10
diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr
index 8e473da..28873ab 100644
--- a/src/test/ui/regions/regions-close-object-into-object-2.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr
@@ -15,9 +15,13 @@
LL | box B(&*v) as Box<dyn X>
| ^^^
= note: but, the lifetime must be valid for the static lifetime...
- = note: ...so that the expression is assignable:
- expected std::boxed::Box<(dyn X + 'static)>
- found std::boxed::Box<dyn X>
+note: ...so that the expression is assignable
+ --> $DIR/regions-close-object-into-object-2.rs:10:5
+ |
+LL | box B(&*v) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: expected `std::boxed::Box<(dyn X + 'static)>`
+ found `std::boxed::Box<dyn X>`
error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr
index c80d13e..449a5b5 100644
--- a/src/test/ui/regions/regions-close-object-into-object-4.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr
@@ -15,9 +15,13 @@
LL | box B(&*v) as Box<dyn X>
| ^^^
= note: but, the lifetime must be valid for the static lifetime...
- = note: ...so that the expression is assignable:
- expected std::boxed::Box<(dyn X + 'static)>
- found std::boxed::Box<dyn X>
+note: ...so that the expression is assignable
+ --> $DIR/regions-close-object-into-object-4.rs:10:5
+ |
+LL | box B(&*v) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: expected `std::boxed::Box<(dyn X + 'static)>`
+ found `std::boxed::Box<dyn X>`
error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr
index ef21316..b2a7afa 100644
--- a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr
+++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr
@@ -19,9 +19,13 @@
|
LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'c> {
| ^^
- = note: ...so that the expression is assignable:
- expected std::boxed::Box<(dyn SomeTrait + 'c)>
- found std::boxed::Box<dyn SomeTrait>
+note: ...so that the expression is assignable
+ --> $DIR/regions-close-over-type-parameter-multiple.rs:20:5
+ |
+LL | box v as Box<dyn SomeTrait + 'a>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: expected `std::boxed::Box<(dyn SomeTrait + 'c)>`
+ found `std::boxed::Box<dyn SomeTrait>`
error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-creating-enums4.stderr b/src/test/ui/regions/regions-creating-enums4.stderr
index 12b8978..58f74e4 100644
--- a/src/test/ui/regions/regions-creating-enums4.stderr
+++ b/src/test/ui/regions/regions-creating-enums4.stderr
@@ -9,17 +9,25 @@
|
LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> {
| ^^
- = note: ...so that the expression is assignable:
- expected &Ast<'_>
- found &Ast<'a>
+note: ...so that the expression is assignable
+ --> $DIR/regions-creating-enums4.rs:7:14
+ |
+LL | Ast::Add(x, y)
+ | ^
+ = note: expected `&Ast<'_>`
+ found `&Ast<'a>`
note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 6:19...
--> $DIR/regions-creating-enums4.rs:6:19
|
LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> {
| ^^
- = note: ...so that the expression is assignable:
- expected Ast<'b>
- found Ast<'_>
+note: ...so that the expression is assignable
+ --> $DIR/regions-creating-enums4.rs:7:5
+ |
+LL | Ast::Add(x, y)
+ | ^^^^^^^^^^^^^^
+ = note: expected `Ast<'b>`
+ found `Ast<'_>`
error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-escape-method.stderr b/src/test/ui/regions/regions-escape-method.stderr
index b93dd0d..ffc2a259 100644
--- a/src/test/ui/regions/regions-escape-method.stderr
+++ b/src/test/ui/regions/regions-escape-method.stderr
@@ -9,9 +9,13 @@
|
LL | s.f(|p| p)
| ^^^^^
- = note: ...so that the expression is assignable:
- expected &i32
- found &i32
+note: ...so that the expression is assignable
+ --> $DIR/regions-escape-method.rs:15:13
+ |
+LL | s.f(|p| p)
+ | ^
+ = note: expected `&i32`
+ found `&i32`
note: but, the lifetime must be valid for the method call at 15:5...
--> $DIR/regions-escape-method.rs:15:5
|
diff --git a/src/test/ui/regions/regions-escape-via-trait-or-not.stderr b/src/test/ui/regions/regions-escape-via-trait-or-not.stderr
index a6b165e..9082346 100644
--- a/src/test/ui/regions/regions-escape-via-trait-or-not.stderr
+++ b/src/test/ui/regions/regions-escape-via-trait-or-not.stderr
@@ -9,9 +9,13 @@
|
LL | with(|o| o)
| ^^^^^
- = note: ...so that the expression is assignable:
- expected &isize
- found &isize
+note: ...so that the expression is assignable
+ --> $DIR/regions-escape-via-trait-or-not.rs:18:14
+ |
+LL | with(|o| o)
+ | ^
+ = note: expected `&isize`
+ found `&isize`
note: but, the lifetime must be valid for the expression at 18:5...
--> $DIR/regions-escape-via-trait-or-not.rs:18:5
|
diff --git a/src/test/ui/regions/regions-nested-fns.stderr b/src/test/ui/regions/regions-nested-fns.stderr
index f4eb5c8..8fce160 100644
--- a/src/test/ui/regions/regions-nested-fns.stderr
+++ b/src/test/ui/regions/regions-nested-fns.stderr
@@ -29,9 +29,18 @@
LL | | return z;
LL | | }));
| |_____^
- = note: ...so that the types are compatible:
- expected &isize
- found &isize
+note: ...so that the types are compatible
+ --> $DIR/regions-nested-fns.rs:13:76
+ |
+LL | ignore::< Box<dyn for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+ | ____________________________________________________________________________^
+LL | | if false { return x; }
+LL | | if false { return ay; }
+LL | | return z;
+LL | | }));
+ | |_____^
+ = note: expected `&isize`
+ found `&isize`
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> $DIR/regions-nested-fns.rs:14:27
diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
index d29fd80..8a600d2 100644
--- a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
+++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
@@ -17,9 +17,16 @@
|
LL | fn bar<'a, 'b>()
| ^^
- = note: ...so that the types are compatible:
- expected Project<'a, 'b>
- found Project<'_, '_>
+note: ...so that the types are compatible
+ --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+ |
+LL | / fn bar<'a, 'b>()
+LL | | where <() as Project<'a, 'b>>::Item : Eq
+LL | | {
+LL | | }
+ | |_^
+ = note: expected `Project<'a, 'b>`
+ found `Project<'_, '_>`
error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-ret-borrowed-1.stderr b/src/test/ui/regions/regions-ret-borrowed-1.stderr
index 4907667..2895a0c 100644
--- a/src/test/ui/regions/regions-ret-borrowed-1.stderr
+++ b/src/test/ui/regions/regions-ret-borrowed-1.stderr
@@ -9,9 +9,13 @@
|
LL | with(|o| o)
| ^^^^^
- = note: ...so that the expression is assignable:
- expected &isize
- found &isize
+note: ...so that the expression is assignable
+ --> $DIR/regions-ret-borrowed-1.rs:10:14
+ |
+LL | with(|o| o)
+ | ^
+ = note: expected `&isize`
+ found `&isize`
note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 9:14...
--> $DIR/regions-ret-borrowed-1.rs:9:14
|
diff --git a/src/test/ui/regions/regions-ret-borrowed.stderr b/src/test/ui/regions/regions-ret-borrowed.stderr
index eb1ade2..b74f10f 100644
--- a/src/test/ui/regions/regions-ret-borrowed.stderr
+++ b/src/test/ui/regions/regions-ret-borrowed.stderr
@@ -9,9 +9,13 @@
|
LL | with(|o| o)
| ^^^^^
- = note: ...so that the expression is assignable:
- expected &isize
- found &isize
+note: ...so that the expression is assignable
+ --> $DIR/regions-ret-borrowed.rs:13:14
+ |
+LL | with(|o| o)
+ | ^
+ = note: expected `&isize`
+ found `&isize`
note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 12:14...
--> $DIR/regions-ret-borrowed.rs:12:14
|
diff --git a/src/test/ui/regions/regions-trait-object-subtyping.stderr b/src/test/ui/regions/regions-trait-object-subtyping.stderr
index ef69f25..58b79d2 100644
--- a/src/test/ui/regions/regions-trait-object-subtyping.stderr
+++ b/src/test/ui/regions/regions-trait-object-subtyping.stderr
@@ -36,9 +36,13 @@
|
LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy {
| ^^
- = note: ...so that the expression is assignable:
- expected &'b mut (dyn Dummy + 'b)
- found &mut (dyn Dummy + 'b)
+note: ...so that the expression is assignable
+ --> $DIR/regions-trait-object-subtyping.rs:15:5
+ |
+LL | x
+ | ^
+ = note: expected `&'b mut (dyn Dummy + 'b)`
+ found `&mut (dyn Dummy + 'b)`
error[E0308]: mismatched types
--> $DIR/regions-trait-object-subtyping.rs:22:5
diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr
index e55f023..527babb 100644
--- a/src/test/ui/reject-specialized-drops-8142.stderr
+++ b/src/test/ui/reject-specialized-drops-8142.stderr
@@ -105,9 +105,13 @@
|
LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
| ^^^
- = note: ...so that the types are compatible:
- expected W<'l1, 'l2>
- found W<'_, '_>
+note: ...so that the types are compatible
+ --> $DIR/reject-specialized-drops-8142.rs:54:1
+ |
+LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: expected `W<'l1, 'l2>`
+ found `W<'_, '_>`
error: aborting due to 8 previous errors
diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
index f24ea05..1143bdd 100644
--- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
@@ -575,8 +575,17 @@
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> $DIR/disallowed-positions.rs:46:8
|
-LL | if (let 0 = 0)? {}
- | ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
+LL | / fn nested_within_if_expr() {
+LL | | if &let 0 = 0 {}
+LL | |
+LL | |
+... |
+LL | | if (let 0 = 0)? {}
+ | | ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
+... |
+LL | | if let true = let true = true {}
+LL | | }
+ | |_- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `()`
= note: required by `std::ops::Try::from_error`
@@ -754,8 +763,17 @@
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> $DIR/disallowed-positions.rs:110:11
|
-LL | while (let 0 = 0)? {}
- | ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
+LL | / fn nested_within_while_expr() {
+LL | | while &let 0 = 0 {}
+LL | |
+LL | |
+... |
+LL | | while (let 0 = 0)? {}
+ | | ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
+... |
+LL | | while let true = let true = true {}
+LL | | }
+ | |_- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `()`
= note: required by `std::ops::Try::from_error`
@@ -924,8 +942,17 @@
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> $DIR/disallowed-positions.rs:183:5
|
-LL | (let 0 = 0)?;
- | ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
+LL | / fn outside_if_and_while_expr() {
+LL | | &let 0 = 0;
+LL | |
+LL | | !let 0 = 0;
+... |
+LL | | (let 0 = 0)?;
+ | | ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
+... |
+LL | |
+LL | | }
+ | |_- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `()`
= note: required by `std::ops::Try::from_error`
diff --git a/src/test/ui/sanitize-cfg.rs b/src/test/ui/sanitize-cfg.rs
new file mode 100644
index 0000000..9c19854
--- /dev/null
+++ b/src/test/ui/sanitize-cfg.rs
@@ -0,0 +1,26 @@
+// Verifies that when compiling with -Zsanitizer=option,
+// the `#[cfg(sanitize = "option")]` attribute is configured.
+
+// needs-sanitizer-support
+// only-linux
+// only-x86_64
+// check-pass
+// revisions: address leak memory thread
+//[address]compile-flags: -Zsanitizer=address --cfg address
+//[leak]compile-flags: -Zsanitizer=leak --cfg leak
+//[memory]compile-flags: -Zsanitizer=memory --cfg memory
+//[thread]compile-flags: -Zsanitizer=thread --cfg thread
+
+#![feature(cfg_sanitize)]
+
+#[cfg(all(sanitize = "address", address))]
+fn main() {}
+
+#[cfg(all(sanitize = "leak", leak))]
+fn main() {}
+
+#[cfg(all(sanitize = "memory", memory))]
+fn main() {}
+
+#[cfg(all(sanitize = "thread", thread))]
+fn main() {}
diff --git a/src/test/ui/simd/simd-intrinsic-float-minmax.rs b/src/test/ui/simd/simd-intrinsic-float-minmax.rs
index dd5551d2..5f0aa11 100644
--- a/src/test/ui/simd/simd-intrinsic-float-minmax.rs
+++ b/src/test/ui/simd/simd-intrinsic-float-minmax.rs
@@ -1,6 +1,5 @@
// run-pass
// ignore-emscripten
-// min-llvm-version 7.0
// Test that the simd_f{min,max} intrinsics produce the correct results.
diff --git a/src/test/ui/span/macro-ty-params.rs b/src/test/ui/span/macro-ty-params.rs
index b077d59..713b9eb 100644
--- a/src/test/ui/span/macro-ty-params.rs
+++ b/src/test/ui/span/macro-ty-params.rs
@@ -10,5 +10,4 @@
foo::<T>!(); //~ ERROR generic arguments in macro path
foo::<>!(); //~ ERROR generic arguments in macro path
m!(Default<>); //~ ERROR generic arguments in macro path
- //~^ ERROR unexpected generic arguments in path
}
diff --git a/src/test/ui/span/macro-ty-params.stderr b/src/test/ui/span/macro-ty-params.stderr
index 39b3edc..21683b2 100644
--- a/src/test/ui/span/macro-ty-params.stderr
+++ b/src/test/ui/span/macro-ty-params.stderr
@@ -10,17 +10,11 @@
LL | foo::<>!();
| ^^
-error: unexpected generic arguments in path
- --> $DIR/macro-ty-params.rs:12:8
- |
-LL | m!(Default<>);
- | ^^^^^^^^^
-
error: generic arguments in macro path
--> $DIR/macro-ty-params.rs:12:15
|
LL | m!(Default<>);
| ^^
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
diff --git a/src/test/ui/suggestions/raw-name-use-suggestion.rs b/src/test/ui/suggestions/raw-name-use-suggestion.rs
index 6c01383..0a8073c 100644
--- a/src/test/ui/suggestions/raw-name-use-suggestion.rs
+++ b/src/test/ui/suggestions/raw-name-use-suggestion.rs
@@ -5,5 +5,5 @@
fn main() {
foo::let(); //~ ERROR expected identifier, found keyword `let`
- r#break(); //~ ERROR cannot find function `break` in this scope
+ r#break(); //~ ERROR cannot find function `r#break` in this scope
}
diff --git a/src/test/ui/suggestions/raw-name-use-suggestion.stderr b/src/test/ui/suggestions/raw-name-use-suggestion.stderr
index 58eb87c..62b7631 100644
--- a/src/test/ui/suggestions/raw-name-use-suggestion.stderr
+++ b/src/test/ui/suggestions/raw-name-use-suggestion.stderr
@@ -20,7 +20,7 @@
LL | foo::r#let();
| ^^^^^
-error[E0425]: cannot find function `break` in this scope
+error[E0425]: cannot find function `r#break` in this scope
--> $DIR/raw-name-use-suggestion.rs:8:5
|
LL | r#break();
diff --git a/src/test/ui/tail-typeck.stderr b/src/test/ui/tail-typeck.stderr
index eeeb258..69f8ffa 100644
--- a/src/test/ui/tail-typeck.stderr
+++ b/src/test/ui/tail-typeck.stderr
@@ -5,6 +5,11 @@
| ----- ^^^ expected `isize`, found `usize`
| |
| expected `isize` because of return type
+ |
+help: you can convert an `usize` to `isize` and panic if the converted value wouldn't fit
+ |
+LL | fn f() -> isize { return g().try_into().unwrap(); }
+ | ^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/target-feature/gate.rs b/src/test/ui/target-feature/gate.rs
index bc7f7ca..2d51cab 100644
--- a/src/test/ui/target-feature/gate.rs
+++ b/src/test/ui/target-feature/gate.rs
@@ -25,7 +25,6 @@
// gate-test-movbe_target_feature
// gate-test-rtm_target_feature
// gate-test-f16c_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 05dbc6e..423a893 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
- --> $DIR/gate.rs:30:18
+ --> $DIR/gate.rs:29:18
|
LL | #[target_feature(enable = "avx512bw")]
| ^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/traits/cycle-cache-err-60010.stderr b/src/test/ui/traits/cycle-cache-err-60010.stderr
index f439de8..295845b 100644
--- a/src/test/ui/traits/cycle-cache-err-60010.stderr
+++ b/src/test/ui/traits/cycle-cache-err-60010.stderr
@@ -6,7 +6,7 @@
|
= note: required because of the requirements on the impl of `Query<RootDatabase>` for `ParseQuery`
-error[E0275]: overflow evaluating the requirement `RootDatabase: SourceDatabase`
+error[E0275]: overflow evaluating the requirement `Runtime<RootDatabase>: std::panic::RefUnwindSafe`
--> $DIR/cycle-cache-err-60010.rs:31:5
|
LL | type Storage;
@@ -17,6 +17,8 @@
LL | type Storage = SalsaStorage;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
+ = note: required because it appears within the type `RootDatabase`
+ = note: required because of the requirements on the impl of `SourceDatabase` for `RootDatabase`
= note: required because of the requirements on the impl of `Query<RootDatabase>` for `ParseQuery`
= note: required because it appears within the type `SalsaStorage`
diff --git a/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr
index 88c9c47..9fdcd4d 100644
--- a/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr
+++ b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr
@@ -14,9 +14,13 @@
|
LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
| ^^
- = note: ...so that the types are compatible:
- expected T1<'a>
- found T1<'_>
+note: ...so that the types are compatible
+ --> $DIR/trait-impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:13
+ |
+LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
+ | ^^^^^^^^^^
+ = note: expected `T1<'a>`
+ found `T1<'_>`
error: aborting due to previous error
diff --git a/src/test/ui/try-on-option-diagnostics.stderr b/src/test/ui/try-on-option-diagnostics.stderr
index 4dd515e..ce3aca3 100644
--- a/src/test/ui/try-on-option-diagnostics.stderr
+++ b/src/test/ui/try-on-option-diagnostics.stderr
@@ -1,8 +1,13 @@
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> $DIR/try-on-option-diagnostics.rs:7:5
|
-LL | x?;
- | ^^ cannot use the `?` operator in a function that returns `u32`
+LL | / fn a_function() -> u32 {
+LL | | let x: Option<u32> = None;
+LL | | x?;
+ | | ^^ cannot use the `?` operator in a function that returns `u32`
+LL | | 22
+LL | | }
+ | |_- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `u32`
= note: required by `std::ops::Try::from_error`
@@ -10,8 +15,14 @@
error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> $DIR/try-on-option-diagnostics.rs:14:9
|
-LL | x?;
- | ^^ cannot use the `?` operator in a closure that returns `{integer}`
+LL | let a_closure = || {
+ | _____________________-
+LL | | let x: Option<u32> = None;
+LL | | x?;
+ | | ^^ cannot use the `?` operator in a closure that returns `{integer}`
+LL | | 22
+LL | | };
+ | |_____- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `{integer}`
= note: required by `std::ops::Try::from_error`
diff --git a/src/test/ui/try-on-option.stderr b/src/test/ui/try-on-option.stderr
index db5046f..07615b5 100644
--- a/src/test/ui/try-on-option.stderr
+++ b/src/test/ui/try-on-option.stderr
@@ -10,8 +10,13 @@
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> $DIR/try-on-option.rs:13:5
|
-LL | x?;
- | ^^ cannot use the `?` operator in a function that returns `u32`
+LL | / fn bar() -> u32 {
+LL | | let x: Option<u32> = None;
+LL | | x?;
+ | | ^^ cannot use the `?` operator in a function that returns `u32`
+LL | | 22
+LL | | }
+ | |_- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `u32`
= note: required by `std::ops::Try::from_error`
diff --git a/src/test/ui/try-operator-on-main.stderr b/src/test/ui/try-operator-on-main.stderr
index d2f1a04..d8ba264 100644
--- a/src/test/ui/try-operator-on-main.stderr
+++ b/src/test/ui/try-operator-on-main.stderr
@@ -1,8 +1,15 @@
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> $DIR/try-operator-on-main.rs:9:5
|
-LL | std::fs::File::open("foo")?;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
+LL | / fn main() {
+LL | | // error for a `Try` type on a non-`Try` fn
+LL | | std::fs::File::open("foo")?;
+ | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
+LL | |
+... |
+LL | | try_trait_generic::<()>();
+LL | | }
+ | |_- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `()`
= note: required by `std::ops::Try::from_error`
diff --git a/src/test/ui/type/type-check-defaults.rs b/src/test/ui/type/type-check-defaults.rs
index 5748c9b..5380fae 100644
--- a/src/test/ui/type/type-check-defaults.rs
+++ b/src/test/ui/type/type-check-defaults.rs
@@ -4,9 +4,9 @@
struct Foo<T, U: FromIterator<T>>(T, U);
struct WellFormed<Z = Foo<i32, i32>>(Z);
-//~^ ERROR a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+//~^ ERROR a value of type `i32` cannot be built from an iterator over elements of type `i32`
struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
-//~^ ERROR a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+//~^ ERROR a value of type `i32` cannot be built from an iterator over elements of type `i32`
struct Bounds<T:Copy=String>(T);
//~^ ERROR the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr
index 6802bc3..6f84b37 100644
--- a/src/test/ui/type/type-check-defaults.stderr
+++ b/src/test/ui/type/type-check-defaults.stderr
@@ -1,21 +1,21 @@
-error[E0277]: a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+error[E0277]: a value of type `i32` cannot be built from an iterator over elements of type `i32`
--> $DIR/type-check-defaults.rs:6:19
|
LL | struct Foo<T, U: FromIterator<T>>(T, U);
| ---------------------------------------- required by `Foo`
LL | struct WellFormed<Z = Foo<i32, i32>>(Z);
- | ^ a collection of type `i32` cannot be built from `std::iter::Iterator<Item=i32>`
+ | ^ value of type `i32` cannot be built from `std::iter::Iterator<Item=i32>`
|
= help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
-error[E0277]: a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+error[E0277]: a value of type `i32` cannot be built from an iterator over elements of type `i32`
--> $DIR/type-check-defaults.rs:8:27
|
LL | struct Foo<T, U: FromIterator<T>>(T, U);
| ---------------------------------------- required by `Foo`
...
LL | struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
- | ^ a collection of type `i32` cannot be built from `std::iter::Iterator<Item=i32>`
+ | ^ value of type `i32` cannot be built from `std::iter::Iterator<Item=i32>`
|
= help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
diff --git a/src/test/ui/type/type-dependent-def-issue-49241.rs b/src/test/ui/type/type-dependent-def-issue-49241.rs
index 5ad50ff..a25e3ba 100644
--- a/src/test/ui/type/type-dependent-def-issue-49241.rs
+++ b/src/test/ui/type/type-dependent-def-issue-49241.rs
@@ -3,5 +3,5 @@
const l: usize = v.count(); //~ ERROR attempt to use a non-constant value in a constant
let s: [u32; l] = v.into_iter().collect();
//~^ ERROR evaluation of constant value failed
- //~^^ ERROR a collection of type
+ //~^^ ERROR a value of type
}
diff --git a/src/test/ui/type/type-dependent-def-issue-49241.stderr b/src/test/ui/type/type-dependent-def-issue-49241.stderr
index 851004d..18a69c5 100644
--- a/src/test/ui/type/type-dependent-def-issue-49241.stderr
+++ b/src/test/ui/type/type-dependent-def-issue-49241.stderr
@@ -10,11 +10,11 @@
LL | let s: [u32; l] = v.into_iter().collect();
| ^ referenced constant has errors
-error[E0277]: a collection of type `[u32; _]` cannot be built from an iterator over elements of type `{integer}`
+error[E0277]: a value of type `[u32; _]` cannot be built from an iterator over elements of type `{integer}`
--> $DIR/type-dependent-def-issue-49241.rs:4:37
|
LL | let s: [u32; l] = v.into_iter().collect();
- | ^^^^^^^ a collection of type `[u32; _]` cannot be built from `std::iter::Iterator<Item={integer}>`
+ | ^^^^^^^ value of type `[u32; _]` cannot be built from `std::iter::Iterator<Item={integer}>`
|
= help: the trait `std::iter::FromIterator<{integer}>` is not implemented for `[u32; _]`
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
index d0475bf..e6029e0d 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
@@ -18,9 +18,13 @@
LL | Box::new(items.iter())
| ^^^^^
= note: but, the lifetime must be valid for the static lifetime...
- = note: ...so that the expression is assignable:
- expected std::boxed::Box<(dyn std::iter::Iterator<Item = &T> + 'static)>
- found std::boxed::Box<dyn std::iter::Iterator<Item = &T>>
+note: ...so that the expression is assignable
+ --> $DIR/dyn-trait-underscore.rs:8:5
+ |
+LL | Box::new(items.iter())
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ = note: expected `std::boxed::Box<(dyn std::iter::Iterator<Item = &T> + 'static)>`
+ found `std::boxed::Box<dyn std::iter::Iterator<Item = &T>>`
error: aborting due to previous error
diff --git a/src/test/ui/wrong-ret-type.stderr b/src/test/ui/wrong-ret-type.stderr
index 440620f..c1274bd 100644
--- a/src/test/ui/wrong-ret-type.stderr
+++ b/src/test/ui/wrong-ret-type.stderr
@@ -5,6 +5,11 @@
| ----- ^ expected `usize`, found `isize`
| |
| expected `usize` because of return type
+ |
+help: you can convert an `isize` to `usize` and panic if the converted value wouldn't fit
+ |
+LL | fn mk_int() -> usize { let i: isize = 3; return i.try_into().unwrap(); }
+ | ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/tools/cargo b/src/tools/cargo
index 750cb14..626f0f4 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 750cb1482e4d0e74822cded7ab8b3c677ed8b041
+Subproject commit 626f0f40efd32e6b3dbade50cd53fdfaa08446ba
diff --git a/src/tools/clippy b/src/tools/clippy
index 7b8e829..374db5c 160000
--- a/src/tools/clippy
+++ b/src/tools/clippy
@@ -1 +1 @@
-Subproject commit 7b8e8293d08d298579470f9d6c74731043c6601a
+Subproject commit 374db5c0b7a8ebc92ecb35ee21e11961da6c754d
diff --git a/src/tools/miri b/src/tools/miri
index 3bf51f5..a0ba079 160000
--- a/src/tools/miri
+++ b/src/tools/miri
@@ -1 +1 @@
-Subproject commit 3bf51f591f7ffdd45f51cd1d42a4002482af2bd5
+Subproject commit a0ba079b6af0f8c07c33dd8af72a51c997e58967