Rollup merge of #72393 - Aaron1011:feature/rewrite-collect-tokens, r=petrochenkov
Rewrite `Parser::collect_tokens`
The previous implementation did not work when called on an opening
delimiter, or when called re-entrantly from the same `TokenCursor` stack
depth.
I'm not sure how to test this apart from https://github.com/rust-lang/rust/pull/72287
diff --git a/Cargo.lock b/Cargo.lock
index d81fd6e..6ce5458 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -213,6 +213,7 @@
"lazy_static 1.4.0",
"libc",
"num_cpus",
+ "opener",
"pretty_assertions",
"serde",
"serde_json",
@@ -2327,6 +2328,9 @@
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6a04cb71e910d0034815600180f62a95bf6e67942d7ab52a166a68c7d7e9cd0"
+dependencies = [
+ "parking_lot 0.9.0",
+]
[[package]]
name = "opaque-debug"
@@ -3791,6 +3795,7 @@
"libc",
"log",
"measureme",
+ "once_cell",
"parking_lot 0.10.2",
"rustc-hash",
"rustc-rayon",
diff --git a/config.toml.example b/config.toml.example
index ffe907c..cf8fe4e 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -312,11 +312,11 @@
# Whether or not debug assertions are enabled for the compiler and standard
# library.
-#debug-assertions = false
+#debug-assertions = debug
# Whether or not debug assertions are enabled for the standard library.
# Overrides the `debug-assertions` option, if defined.
-#debug-assertions-std = false
+#debug-assertions-std = debug-assertions
# Debuginfo level for most of Rust code, corresponds to the `-C debuginfo=N` option of `rustc`.
# `0` - no debug info
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index f7856f6..c4918d7 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -48,6 +48,7 @@
lazy_static = "1.3.0"
time = "0.1"
ignore = "0.4.10"
+opener = "0.4"
[target.'cfg(windows)'.dependencies.winapi]
version = "0.3"
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 4bc81a7..5489b1b 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -503,7 +503,7 @@
Subcommand::Check { ref paths } => (Kind::Check, &paths[..]),
Subcommand::Clippy { ref paths } => (Kind::Clippy, &paths[..]),
Subcommand::Fix { ref paths } => (Kind::Fix, &paths[..]),
- Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]),
+ Subcommand::Doc { ref paths, .. } => (Kind::Doc, &paths[..]),
Subcommand::Test { ref paths, .. } => (Kind::Test, &paths[..]),
Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]),
Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]),
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index c56114f..b399911 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -773,7 +773,8 @@
// Ensure that `libLLVM.so` ends up in the newly build compiler directory,
// so that it can be found when the newly built `rustc` is run.
- dist::maybe_install_llvm_dylib(builder, target_compiler.host, &sysroot);
+ dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
+ dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
// Link the compiler binary itself into place
let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index c4bca4a..5e966d7 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -514,7 +514,7 @@
// components like the llvm tools and LLD. LLD is included below and
// tools/LLDB come later, so let's just throw it in the rustc
// component for now.
- maybe_install_llvm_dylib(builder, host, image);
+ maybe_install_llvm_runtime(builder, host, image);
// Copy over lld if it's there
if builder.config.lld_enabled {
@@ -2228,27 +2228,18 @@
}
}
-// Maybe add libLLVM.so to the lib-dir. It will only have been built if
-// LLVM tools are linked dynamically.
-//
-// We add this to both the libdir of the rustc binary itself (for it to load at
-// runtime) and also to the target directory so it can find it at link-time.
-//
-// Note: This function does no yet support Windows but we also don't support
-// linking LLVM tools dynamically on Windows yet.
-pub fn maybe_install_llvm_dylib(builder: &Builder<'_>, target: Interned<String>, sysroot: &Path) {
+/// Maybe add libLLVM.so to the given destination lib-dir. It will only have
+/// been built if LLVM tools are linked dynamically.
+///
+/// Note: This function does not yet support Windows, but we also don't support
+/// linking LLVM tools dynamically on Windows yet.
+fn maybe_install_llvm(builder: &Builder<'_>, target: Interned<String>, dst_libdir: &Path) {
let src_libdir = builder.llvm_out(target).join("lib");
- let dst_libdir1 = sysroot.join("lib/rustlib").join(&*target).join("lib");
- let dst_libdir2 =
- sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target }));
- t!(fs::create_dir_all(&dst_libdir1));
- t!(fs::create_dir_all(&dst_libdir2));
if target.contains("apple-darwin") {
let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
if llvm_dylib_path.exists() {
- builder.install(&llvm_dylib_path, &dst_libdir1, 0o644);
- builder.install(&llvm_dylib_path, &dst_libdir2, 0o644);
+ builder.install(&llvm_dylib_path, dst_libdir, 0o644);
}
return;
}
@@ -2262,11 +2253,23 @@
panic!("dist: Error calling canonicalize path `{}`: {}", llvm_dylib_path.display(), e);
});
- builder.install(&llvm_dylib_path, &dst_libdir1, 0o644);
- builder.install(&llvm_dylib_path, &dst_libdir2, 0o644);
+ builder.install(&llvm_dylib_path, dst_libdir, 0o644);
}
}
+/// Maybe add libLLVM.so to the target lib-dir for linking.
+pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: Interned<String>, sysroot: &Path) {
+ let dst_libdir = sysroot.join("lib/rustlib").join(&*target).join("lib");
+ maybe_install_llvm(builder, target, &dst_libdir);
+}
+
+/// Maybe add libLLVM.so to the runtime lib-dir for rustc itself.
+pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: Interned<String>, sysroot: &Path) {
+ let dst_libdir =
+ sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target }));
+ maybe_install_llvm(builder, target, &dst_libdir);
+}
+
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct LlvmTools {
pub target: Interned<String>,
@@ -2314,6 +2317,12 @@
builder.install(&exe, &dst_bindir, 0o755);
}
+ // Copy libLLVM.so to the target lib dir as well, so the RPATH like
+ // `$ORIGIN/../lib` can find it. It may also be used as a dependency
+ // of `rustc-dev` to support the inherited `-lLLVM` when using the
+ // compiler libraries.
+ maybe_install_llvm_target(builder, target, &image);
+
// Prepare the overlay
let overlay = tmp.join("llvm-tools-overlay");
drop(fs::remove_dir_all(&overlay));
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 7eab92d..5c01c5e 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -70,6 +70,35 @@
RustdocBook, "src/doc/rustdoc", "rustdoc";
);
+fn open(builder: &Builder<'_>, path: impl AsRef<Path>) {
+ if builder.config.dry_run || !builder.config.cmd.open() {
+ return;
+ }
+
+ let path = path.as_ref();
+ builder.info(&format!("Opening doc {}", path.display()));
+ if let Err(err) = opener::open(path) {
+ builder.info(&format!("{}\n", err));
+ }
+}
+
+// "src/libstd" -> ["src", "libstd"]
+//
+// Used for deciding whether a particular step is one requested by the user on
+// the `x.py doc` command line, which determines whether `--open` will open that
+// page.
+fn components_simplified(path: &PathBuf) -> Vec<&str> {
+ path.iter().map(|component| component.to_str().unwrap_or("???")).collect()
+}
+
+fn is_explicit_request(builder: &Builder<'_>, path: &str) -> bool {
+ builder
+ .paths
+ .iter()
+ .map(components_simplified)
+ .any(|requested| requested.iter().copied().eq(path.split("/")))
+}
+
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct UnstableBook {
target: Interned<String>,
@@ -200,6 +229,12 @@
invoke_rustdoc(builder, compiler, target, path);
}
+
+ if is_explicit_request(builder, "src/doc/book") {
+ let out = builder.doc_out(target);
+ let index = out.join("book").join("index.html");
+ open(builder, &index);
+ }
}
}
@@ -338,6 +373,13 @@
}
builder.run(&mut cmd);
}
+
+ // We open doc/index.html as the default if invoked as `x.py doc --open`
+ // with no particular explicit doc requested (e.g. src/libcore).
+ if builder.paths.is_empty() || is_explicit_request(builder, "src/doc") {
+ let index = out.join("index.html");
+ open(builder, &index);
+ }
}
}
@@ -418,10 +460,25 @@
builder.run(&mut cargo.into());
};
- for krate in &["alloc", "core", "std", "proc_macro", "test"] {
+ let krates = ["alloc", "core", "std", "proc_macro", "test"];
+ for krate in &krates {
run_cargo_rustdoc_for(krate);
}
builder.cp_r(&my_out, &out);
+
+ // Look for src/libstd, src/libcore etc in the `x.py doc` arguments and
+ // open the corresponding rendered docs.
+ for path in builder.paths.iter().map(components_simplified) {
+ if path.get(0) == Some(&"src")
+ && path.get(1).map_or(false, |dir| dir.starts_with("lib"))
+ {
+ let requested_crate = &path[1][3..];
+ if krates.contains(&requested_crate) {
+ let index = out.join(requested_crate).join("index.html");
+ open(builder, &index);
+ }
+ }
+ }
}
}
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 646b9e0..cfaa43f 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -61,6 +61,7 @@
},
Doc {
paths: Vec<PathBuf>,
+ open: bool,
},
Test {
paths: Vec<PathBuf>,
@@ -248,6 +249,9 @@
"bench" => {
opts.optmulti("", "test-args", "extra arguments", "ARGS");
}
+ "doc" => {
+ opts.optflag("", "open", "open the docs in a browser");
+ }
"clean" => {
opts.optflag("", "all", "clean all build artifacts");
}
@@ -404,6 +408,7 @@
./x.py doc src/doc/book
./x.py doc src/doc/nomicon
./x.py doc src/doc/book src/libstd
+ ./x.py doc src/libstd --open
If no arguments are passed then everything is documented:
@@ -479,7 +484,7 @@
},
},
"bench" => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") },
- "doc" => Subcommand::Doc { paths },
+ "doc" => Subcommand::Doc { paths, open: matches.opt_present("open") },
"clean" => {
if !paths.is_empty() {
println!("\nclean does not take a path argument\n");
@@ -613,6 +618,13 @@
_ => None,
}
}
+
+ pub fn open(&self) -> bool {
+ match *self {
+ Subcommand::Doc { open, .. } => open,
+ _ => false,
+ }
+ }
}
fn split(s: &[String]) -> Vec<String> {
diff --git a/src/ci/scripts/install-msys2-packages.sh b/src/ci/scripts/install-msys2-packages.sh
index 8fefddd..ff7479c 100755
--- a/src/ci/scripts/install-msys2-packages.sh
+++ b/src/ci/scripts/install-msys2-packages.sh
@@ -6,17 +6,6 @@
source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
if isWindows; then
- # FIXME(mati865): temporary workaround until chocolatey updates their MSYS2
- base_url='https://ci-mirrors.rust-lang.org/rustc/msys2-repo/msys/x86_64'
- curl ${base_url}/libzstd-1.4.4-2-x86_64.pkg.tar.xz -o libzstd-1.4.4-2-x86_64.pkg.tar.xz
- curl ${base_url}/pacman-5.2.1-6-x86_64.pkg.tar.xz -o pacman-5.2.1-6-x86_64.pkg.tar.xz
- curl ${base_url}/zstd-1.4.4-2-x86_64.pkg.tar.xz -o zstd-1.4.4-2-x86_64.pkg.tar.xz
- pacman -U --noconfirm libzstd-1.4.4-2-x86_64.pkg.tar.xz pacman-5.2.1-6-x86_64.pkg.tar.xz \
- zstd-1.4.4-2-x86_64.pkg.tar.xz
- rm libzstd-1.4.4-2-x86_64.pkg.tar.xz pacman-5.2.1-6-x86_64.pkg.tar.xz \
- zstd-1.4.4-2-x86_64.pkg.tar.xz
- pacman -Sy
-
pacman -S --noconfirm --needed base-devel ca-certificates make diffutils tar \
binutils
diff --git a/src/ci/scripts/install-msys2.sh b/src/ci/scripts/install-msys2.sh
index b94eb5f..3c3b500 100755
--- a/src/ci/scripts/install-msys2.sh
+++ b/src/ci/scripts/install-msys2.sh
@@ -17,9 +17,8 @@
msys2.nupkg
curl -sSL https://packages.chocolatey.org/chocolatey-core.extension.1.3.5.1.nupkg > \
chocolatey-core.extension.nupkg
- # FIXME(mati865): remove `/NoUpdate` once chocolatey updates MSYS2
choco install -s . msys2 \
- --params="/InstallDir:$(ciCheckoutPath)/msys2 /NoPath /NoUpdate" -y --no-progress
+ --params="/InstallDir:$(ciCheckoutPath)/msys2 /NoPath" -y --no-progress
rm msys2.nupkg chocolatey-core.extension.nupkg
mkdir -p "$(ciCheckoutPath)/msys2/home/${USERNAME}"
ciCommandAddPath "$(ciCheckoutPath)/msys2/usr/bin"
diff --git a/src/libcore/future/into_future.rs b/src/libcore/future/into_future.rs
new file mode 100644
index 0000000..4020c25
--- /dev/null
+++ b/src/libcore/future/into_future.rs
@@ -0,0 +1,27 @@
+use crate::future::Future;
+
+/// Conversion into a `Future`.
+#[unstable(feature = "into_future", issue = "67644")]
+pub trait IntoFuture {
+ /// The output that the future will produce on completion.
+ #[unstable(feature = "into_future", issue = "67644")]
+ type Output;
+
+ /// Which kind of future are we turning this into?
+ #[unstable(feature = "into_future", issue = "67644")]
+ type Future: Future<Output = Self::Output>;
+
+ /// Creates a future from a value.
+ #[unstable(feature = "into_future", issue = "67644")]
+ fn into_future(self) -> Self::Future;
+}
+
+#[unstable(feature = "into_future", issue = "67644")]
+impl<F: Future> IntoFuture for F {
+ type Output = F::Output;
+ type Future = F;
+
+ fn into_future(self) -> Self::Future {
+ self
+ }
+}
diff --git a/src/libcore/future/mod.rs b/src/libcore/future/mod.rs
index b5a1029..6f6009b 100644
--- a/src/libcore/future/mod.rs
+++ b/src/libcore/future/mod.rs
@@ -10,12 +10,16 @@
};
mod future;
+mod into_future;
mod pending;
mod ready;
#[stable(feature = "futures_api", since = "1.36.0")]
pub use self::future::Future;
+#[unstable(feature = "into_future", issue = "67644")]
+pub use into_future::IntoFuture;
+
#[unstable(feature = "future_readiness_fns", issue = "70921")]
pub use pending::{pending, Pending};
#[unstable(feature = "future_readiness_fns", issue = "70921")]
diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs
index f7ea7eb..01c9744 100644
--- a/src/libcore/mem/maybe_uninit.rs
+++ b/src/libcore/mem/maybe_uninit.rs
@@ -20,9 +20,9 @@
/// # #![allow(invalid_value)]
/// use std::mem::{self, MaybeUninit};
///
-/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior!
+/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! ⚠️
/// // The equivalent code with `MaybeUninit<&i32>`:
-/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior!
+/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior! ⚠️
/// ```
///
/// This is exploited by the compiler for various optimizations, such as eliding
@@ -35,9 +35,9 @@
/// # #![allow(invalid_value)]
/// use std::mem::{self, MaybeUninit};
///
-/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior!
+/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️
/// // The equivalent code with `MaybeUninit<bool>`:
-/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior!
+/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️
/// ```
///
/// Moreover, uninitialized memory is special in that the compiler knows that
@@ -49,9 +49,9 @@
/// # #![allow(invalid_value)]
/// use std::mem::{self, MaybeUninit};
///
-/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior!
+/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️
/// // The equivalent code with `MaybeUninit<i32>`:
-/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior!
+/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️
/// ```
/// (Notice that the rules around uninitialized integers are not finalized yet, but
/// until they are, it is advisable to avoid them.)
@@ -348,7 +348,7 @@
/// let x = MaybeUninit::<(u8, NotZero)>::zeroed();
/// let x = unsafe { x.assume_init() };
/// // Inside a pair, we create a `NotZero` that does not have a valid discriminant.
- /// // This is undefined behavior.
+ /// // This is undefined behavior. ⚠️
/// ```
#[stable(feature = "maybe_uninit", since = "1.36.0")]
#[inline]
@@ -400,7 +400,7 @@
///
/// let x = MaybeUninit::<Vec<u32>>::uninit();
/// let x_vec = unsafe { &*x.as_ptr() };
- /// // We have created a reference to an uninitialized vector! This is undefined behavior.
+ /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️
/// ```
///
/// (Notice that the rules around references to uninitialized data are not finalized yet, but
@@ -437,7 +437,7 @@
///
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
/// let x_vec = unsafe { &mut *x.as_mut_ptr() };
- /// // We have created a reference to an uninitialized vector! This is undefined behavior.
+ /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️
/// ```
///
/// (Notice that the rules around references to uninitialized data are not finalized yet, but
@@ -489,7 +489,7 @@
///
/// let x = MaybeUninit::<Vec<u32>>::uninit();
/// let x_init = unsafe { x.assume_init() };
- /// // `x` had not been initialized yet, so this last line caused undefined behavior.
+ /// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️
/// ```
#[stable(feature = "maybe_uninit", since = "1.36.0")]
#[inline(always)]
@@ -553,7 +553,7 @@
/// x.write(Some(vec![0,1,2]));
/// let x1 = unsafe { x.read() };
/// let x2 = unsafe { x.read() };
- /// // We now created two copies of the same vector, leading to a double-free when
+ /// // We now created two copies of the same vector, leading to a double-free ⚠️ when
/// // they both get dropped!
/// ```
#[unstable(feature = "maybe_uninit_extra", issue = "63567")]
@@ -603,7 +603,7 @@
///
/// let x = MaybeUninit::<Vec<u32>>::uninit();
/// let x_vec: &Vec<u32> = unsafe { x.get_ref() };
- /// // We have created a reference to an uninitialized vector! This is undefined behavior.
+ /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️
/// ```
///
/// ```rust,no_run
@@ -686,7 +686,7 @@
/// unsafe {
/// *b.get_mut() = true;
/// // We have created a (mutable) reference to an uninitialized `bool`!
- /// // This is undefined behavior.
+ /// // This is undefined behavior. ⚠️
/// }
/// ```
///
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index 774ecd9..6f5bf7a 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -139,10 +139,12 @@
//! otherwise invalidating the memory used to store the data is restricted, too.
//! Concretely, for pinned data you have to maintain the invariant
//! that *its memory will not get invalidated or repurposed from the moment it gets pinned until
-//! when [`drop`] is called*. Memory can be invalidated by deallocation, but also by
+//! when [`drop`] is called*. Only once [`drop`] returns or panics, the memory may be reused.
+//!
+//! Memory can be "invalidated" by deallocation, but also by
//! replacing a [`Some(v)`] by [`None`], or calling [`Vec::set_len`] to "kill" some elements
//! off of a vector. It can be repurposed by using [`ptr::write`] to overwrite it without
-//! calling the destructor first.
+//! calling the destructor first. None of this is allowed for pinned data without calling [`drop`].
//!
//! This is exactly the kind of guarantee that the intrusive linked list from the previous
//! section needs to function correctly.
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 9582ac3..b5ce165 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -5740,7 +5740,8 @@
/// and it must be properly aligned. This means in particular:
///
/// * The entire memory range of this slice must be contained within a single allocated object!
-/// Slices can never span across multiple allocated objects.
+/// Slices can never span across multiple allocated objects. See [below](#incorrect-usage)
+/// for an example incorrectly not taking this into account.
/// * `data` must be non-null and aligned even for zero-length slices. One
/// reason for this is that enum layout optimizations may rely on references
/// (including slices of any length) being aligned and non-null to distinguish
@@ -5773,6 +5774,34 @@
/// assert_eq!(slice[0], 42);
/// ```
///
+/// ### Incorrect usage
+///
+/// The following `join_slices` function is **unsound** ⚠️
+///
+/// ```rust,no_run
+/// use std::slice;
+///
+/// fn join_slices<'a, T>(fst: &'a [T], snd: &'a [T]) -> &'a [T] {
+/// let fst_end = fst.as_ptr().wrapping_add(fst.len());
+/// let snd_start = snd.as_ptr();
+/// assert_eq!(fst_end, snd_start, "Slices must be contiguous!");
+/// unsafe {
+/// // The assertion above ensures `fst` and `snd` are contiguous, but they might
+/// // still be contained within _different allocated objects_, in which case
+/// // creating this slice is undefined behavior.
+/// slice::from_raw_parts(fst.as_ptr(), fst.len() + snd.len())
+/// }
+/// }
+///
+/// fn main() {
+/// // `a` and `b` are different allocated objects...
+/// let a = 42;
+/// let b = 27;
+/// // ... which may nevertheless be laid out contiguously in memory: | a | b |
+/// let _ = join_slices(slice::from_ref(&a), slice::from_ref(&b)); // UB
+/// }
+/// ```
+///
/// [valid]: ../../std/ptr/index.html#safety
/// [`NonNull::dangling()`]: ../../std/ptr/struct.NonNull.html#method.dangling
/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index f11401b..2d5bd7e 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -39,6 +39,7 @@
#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
pub use diagnostic::{Diagnostic, Level, MultiSpan};
+use std::cmp::Ordering;
use std::ops::{Bound, RangeBounds};
use std::path::PathBuf;
use std::str::FromStr;
@@ -420,6 +421,20 @@
#[unstable(feature = "proc_macro_span", issue = "54725")]
impl !Sync for LineColumn {}
+#[unstable(feature = "proc_macro_span", issue = "54725")]
+impl Ord for LineColumn {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.line.cmp(&other.line).then(self.column.cmp(&other.column))
+ }
+}
+
+#[unstable(feature = "proc_macro_span", issue = "54725")]
+impl PartialOrd for LineColumn {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
/// The source file of a given `Span`.
#[unstable(feature = "proc_macro_span", issue = "54725")]
#[derive(Clone)]
diff --git a/src/libproc_macro/tests/test.rs b/src/libproc_macro/tests/test.rs
new file mode 100644
index 0000000..331b330
--- /dev/null
+++ b/src/libproc_macro/tests/test.rs
@@ -0,0 +1,12 @@
+#![feature(proc_macro_span)]
+
+use proc_macro::LineColumn;
+
+#[test]
+fn test_line_column_ord() {
+ let line0_column0 = LineColumn { line: 0, column: 0 };
+ let line0_column1 = LineColumn { line: 0, column: 1 };
+ let line1_column0 = LineColumn { line: 1, column: 0 };
+ assert!(line0_column0 < line0_column1);
+ assert!(line0_column1 < line1_column0);
+}
diff --git a/src/librustc_ast/tokenstream.rs b/src/librustc_ast/tokenstream.rs
index 916a5ff..075aaa7 100644
--- a/src/librustc_ast/tokenstream.rs
+++ b/src/librustc_ast/tokenstream.rs
@@ -21,6 +21,8 @@
use rustc_span::{Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};
+use log::debug;
+
use std::{iter, mem};
/// When the main rust parser encounters a syntax-extension invocation, it
@@ -338,8 +340,71 @@
true
}
- let mut t1 = self.trees().filter(semantic_tree);
- let mut t2 = other.trees().filter(semantic_tree);
+ // When comparing two `TokenStream`s, we ignore the `IsJoint` information.
+ //
+ // However, `rustc_parse::lexer::tokentrees::TokenStreamBuilder` will
+ // use `Token.glue` on adjacent tokens with the proper `IsJoint`.
+ // Since we are ignoreing `IsJoint`, a 'glued' token (e.g. `BinOp(Shr)`)
+ // and its 'split'/'unglued' compoenents (e.g. `Gt, Gt`) are equivalent
+ // when determining if two `TokenStream`s are 'probably equal'.
+ //
+ // Therefore, we use `break_two_token_op` to convert all tokens
+ // to the 'unglued' form (if it exists). This ensures that two
+ // `TokenStream`s which differ only in how their tokens are glued
+ // will be considered 'probably equal', which allows us to keep spans.
+ //
+ // This is important when the original `TokenStream` contained
+ // extra spaces (e.g. `f :: < Vec < _ > > ( ) ;'). These extra spaces
+ // will be omitted when we pretty-print, which can cause the original
+ // and reparsed `TokenStream`s to differ in the assignment of `IsJoint`,
+ // leading to some tokens being 'glued' together in one stream but not
+ // the other. See #68489 for more details.
+ fn break_tokens(tree: TokenTree) -> impl Iterator<Item = TokenTree> {
+ // In almost all cases, we should have either zero or one levels
+ // of 'unglueing'. However, in some unusual cases, we may need
+ // to iterate breaking tokens mutliple times. For example:
+ // '[BinOpEq(Shr)] => [Gt, Ge] -> [Gt, Gt, Eq]'
+ let mut token_trees: SmallVec<[_; 2]>;
+ if let TokenTree::Token(token) = &tree {
+ let mut out = SmallVec::<[_; 2]>::new();
+ out.push(token.clone());
+ // Iterate to fixpoint:
+ // * We start off with 'out' containing our initial token, and `temp` empty
+ // * If we are able to break any tokens in `out`, then `out` will have
+ // at least one more element than 'temp', so we will try to break tokens
+ // again.
+ // * If we cannot break any tokens in 'out', we are done
+ loop {
+ let mut temp = SmallVec::<[_; 2]>::new();
+ let mut changed = false;
+
+ for token in out.into_iter() {
+ if let Some((first, second)) = token.kind.break_two_token_op() {
+ temp.push(Token::new(first, DUMMY_SP));
+ temp.push(Token::new(second, DUMMY_SP));
+ changed = true;
+ } else {
+ temp.push(token);
+ }
+ }
+ out = temp;
+ if !changed {
+ break;
+ }
+ }
+ token_trees = out.into_iter().map(|t| TokenTree::Token(t)).collect();
+ if token_trees.len() != 1 {
+ debug!("break_tokens: broke {:?} to {:?}", tree, token_trees);
+ }
+ } else {
+ token_trees = SmallVec::new();
+ token_trees.push(tree);
+ }
+ token_trees.into_iter()
+ }
+
+ let mut t1 = self.trees().filter(semantic_tree).flat_map(break_tokens);
+ let mut t2 = other.trees().filter(semantic_tree).flat_map(break_tokens);
for (t1, t2) in t1.by_ref().zip(t2.by_ref()) {
if !t1.probably_equal_for_proc_macro(&t2) {
return false;
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index 2cf81af..5d98fde 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -269,7 +269,7 @@
let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering");
LoweringContext {
- crate_root: sess.parse_sess.injected_crate_name.try_get().copied(),
+ crate_root: sess.parse_sess.injected_crate_name.get().copied(),
sess,
resolver,
nt_to_tokenstream,
@@ -688,7 +688,7 @@
) -> Span {
span.fresh_expansion(ExpnData {
allow_internal_unstable,
- ..ExpnData::default(ExpnKind::Desugaring(reason), span, self.sess.edition())
+ ..ExpnData::default(ExpnKind::Desugaring(reason), span, self.sess.edition(), None)
})
}
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index 421c6ac..a4e17a5f 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -367,8 +367,8 @@
pub fn provide_extern(providers: &mut Providers<'_>) {
providers.wasm_import_module_map = |tcx, cnum| {
- // Build up a map from DefId to a `NativeLibrary` structure, where
- // `NativeLibrary` internally contains information about
+ // Build up a map from DefId to a `NativeLib` structure, where
+ // `NativeLib` internally contains information about
// `#[link(wasm_import_module = "...")]` for example.
let native_libs = tcx.native_libraries(cnum);
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 6ed9cd6..57e018b 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -6,7 +6,6 @@
use crate::base;
use crate::common;
use crate::consts;
-use crate::context::all_outputs_are_pic_executables;
use crate::llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic};
use crate::llvm_util;
use crate::type_::Type;
@@ -150,7 +149,6 @@
let features = features.join(",");
let features = CString::new(features).unwrap();
let abi = SmallCStr::new(&sess.target.target.options.llvm_abiname);
- let pic_is_pie = all_outputs_are_pic_executables(sess);
let trap_unreachable = sess.target.target.options.trap_unreachable;
let emit_stack_size_section = sess.opts.debugging_opts.emit_stack_sizes;
@@ -174,7 +172,6 @@
reloc_model,
opt_level,
use_softfp,
- pic_is_pie,
ffunction_sections,
fdata_sections,
trap_unreachable,
diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs
index e5f7347..3e17a51 100644
--- a/src/librustc_codegen_llvm/base.rs
+++ b/src/librustc_codegen_llvm/base.rs
@@ -100,7 +100,7 @@
tcx: TyCtxt<'tcx>,
cgu_name: Symbol,
) -> (ModuleCodegen<ModuleLlvm>, u64) {
- let prof_timer = tcx.prof.generic_activity("codegen_module");
+ let prof_timer = tcx.prof.generic_activity_with_arg("codegen_module", cgu_name.to_string());
let start_time = Instant::now();
let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx);
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 01f90ca..4c810a3 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -97,17 +97,6 @@
}
}
-/// PIE is potentially more effective than PIC, but can only be used in executables.
-/// If all our outputs are executables, then we can relax PIC to PIE when producing object code.
-/// If the list of crate types is not yet known we conservatively return `false`.
-pub fn all_outputs_are_pic_executables(sess: &Session) -> bool {
- sess.relocation_model() == RelocModel::Pic
- && sess
- .crate_types
- .try_get()
- .map_or(false, |crate_types| crate_types.iter().all(|ty| *ty == CrateType::Executable))
-}
-
fn strip_function_ptr_alignment(data_layout: String) -> String {
// FIXME: Make this more general.
data_layout.replace("-Fi8-", "-")
@@ -183,10 +172,11 @@
if sess.relocation_model() == RelocModel::Pic {
llvm::LLVMRustSetModulePICLevel(llmod);
- }
-
- if all_outputs_are_pic_executables(sess) {
- llvm::LLVMRustSetModulePIELevel(llmod);
+ // PIE is potentially more effective than PIC, but can only be used in executables.
+ // If all our outputs are executables, then we can relax PIC to PIE.
+ if sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) {
+ llvm::LLVMRustSetModulePIELevel(llmod);
+ }
}
// If skipping the PLT is enabled, we need to add some module metadata
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index fb9a27e..0cce0b2 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -447,7 +447,6 @@
unsafe {
llvm::LLVMRustDIBuilderCreateSubroutineType(
DIB(cx),
- unknown_file_metadata(cx),
create_DIArray(DIB(cx), &signature_metadata[..]),
)
},
@@ -635,14 +634,12 @@
// anything reading the debuginfo for a recursive
// type is going to see *something* weird - the only
// question is what exactly it will see.
- let (size, align) = cx.size_and_align_of(t);
let name = "<recur_type>";
llvm::LLVMRustDIBuilderCreateBasicType(
DIB(cx),
name.as_ptr().cast(),
name.len(),
- size.bits(),
- align.bits() as u32,
+ cx.size_of(t).bits(),
DW_ATE_unsigned,
)
}
@@ -841,14 +838,12 @@
_ => bug!("debuginfo::basic_type_metadata - `t` is invalid type"),
};
- let (size, align) = cx.size_and_align_of(t);
let ty_metadata = unsafe {
llvm::LLVMRustDIBuilderCreateBasicType(
DIB(cx),
name.as_ptr().cast(),
name.len(),
- size.bits(),
- align.bits() as u32,
+ cx.size_of(t).bits(),
encoding,
)
};
@@ -2187,9 +2182,6 @@
name.as_ptr().cast(),
name.len(),
actual_type_metadata,
- unknown_file_metadata(cx),
- 0,
- 0,
))
})
} else {
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 8c9a2c0..8c58084 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -252,7 +252,7 @@
let function_type_metadata = unsafe {
let fn_signature = get_function_signature(self, fn_abi);
- llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), file_metadata, fn_signature)
+ llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), fn_signature)
};
// Find the enclosing function, in case this is a closure.
@@ -265,8 +265,7 @@
// name if necessary.
let generics = self.tcx().generics_of(enclosing_fn_def_id);
let substs = instance.substs.truncate_to(self.tcx(), generics);
- let template_parameters =
- get_template_parameters(self, &generics, substs, file_metadata, &mut name);
+ let template_parameters = get_template_parameters(self, &generics, substs, &mut name);
// Get the linkage_name, which is just the symbol name
let linkage_name = mangled_name_of_instance(self, instance);
@@ -388,7 +387,6 @@
cx: &CodegenCx<'ll, 'tcx>,
generics: &ty::Generics,
substs: SubstsRef<'tcx>,
- file_metadata: &'ll DIFile,
name_to_append_suffix_to: &mut String,
) -> &'ll DIArray {
if substs.types().next().is_none() {
@@ -429,9 +427,6 @@
name.as_ptr().cast(),
name.len(),
actual_type_metadata,
- file_metadata,
- 0,
- 0,
))
})
} else {
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index 9cb0f0e..3fb7ff3 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -1655,7 +1655,6 @@
pub fn LLVMRustDIBuilderCreateSubroutineType(
Builder: &DIBuilder<'a>,
- File: &'a DIFile,
ParameterTypes: &'a DIArray,
) -> &'a DICompositeType;
@@ -1682,7 +1681,6 @@
Name: *const c_char,
NameLen: size_t,
SizeInBits: u64,
- AlignInBits: u32,
Encoding: c_uint,
) -> &'a DIBasicType;
@@ -1880,9 +1878,6 @@
Name: *const c_char,
NameLen: size_t,
Ty: &'a DIType,
- File: &'a DIFile,
- LineNo: c_uint,
- ColumnNo: c_uint,
) -> &'a DITemplateTypeParameter;
pub fn LLVMRustDIBuilderCreateNameSpace(
@@ -1948,7 +1943,6 @@
Reloc: RelocModel,
Level: CodeGenOptLevel,
UseSoftFP: bool,
- PositionIndependentExecutable: bool,
FunctionSections: bool,
DataSections: bool,
TrapUnreachable: bool,
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index 286d363..67a2251 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -170,6 +170,7 @@
("fp16", Some(sym::aarch64_target_feature)),
("rcpc", Some(sym::aarch64_target_feature)),
("dotprod", Some(sym::aarch64_target_feature)),
+ ("tme", Some(sym::aarch64_target_feature)),
("v8.1a", Some(sym::aarch64_target_feature)),
("v8.2a", Some(sym::aarch64_target_feature)),
("v8.3a", Some(sym::aarch64_target_feature)),
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index aa4b51f..9a7c490 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -1,12 +1,13 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_fs_util::fix_windows_verbatim_for_gcc;
use rustc_hir::def_id::CrateNum;
-use rustc_middle::middle::cstore::{EncodedMetadata, LibSource, NativeLibrary, NativeLibraryKind};
+use rustc_middle::middle::cstore::{EncodedMetadata, LibSource, NativeLib};
use rustc_middle::middle::dependency_format::Linkage;
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo};
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, Sanitizer};
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
use rustc_session::search_paths::PathKind;
+use rustc_session::utils::NativeLibKind;
/// For all the linkers we support, and information they might
/// need out of the shared crate context before we get rid of it.
use rustc_session::{filesearch, Session};
@@ -52,7 +53,7 @@
) {
let _timer = sess.timer("link_binary");
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
- for &crate_type in sess.crate_types.borrow().iter() {
+ for &crate_type in sess.crate_types().iter() {
// Ignore executable crates if we have -Z no-codegen, as they will error.
if (sess.opts.debugging_opts.no_codegen || !sess.opts.output_types.should_codegen())
&& !output_metadata
@@ -183,6 +184,7 @@
"x86_64" => Some("x64".to_string()),
"x86" => Some("x86".to_string()),
"aarch64" => Some("arm64".to_string()),
+ "arm" => Some("arm".to_string()),
_ => None,
};
if let Some(ref a) = arch {
@@ -327,11 +329,12 @@
// metadata of the rlib we're generating somehow.
for lib in codegen_results.crate_info.used_libraries.iter() {
match lib.kind {
- NativeLibraryKind::NativeStatic => {}
- NativeLibraryKind::NativeStaticNobundle
- | NativeLibraryKind::NativeFramework
- | NativeLibraryKind::NativeRawDylib
- | NativeLibraryKind::NativeUnknown => continue,
+ NativeLibKind::StaticBundle => {}
+ NativeLibKind::StaticNoBundle
+ | NativeLibKind::Dylib
+ | NativeLibKind::Framework
+ | NativeLibKind::RawDylib
+ | NativeLibKind::Unspecified => continue,
}
if let Some(name) = lib.name {
ab.add_native_library(name);
@@ -430,7 +433,7 @@
// object files come from where and selectively skip them.
let skip_object_files = native_libs
.iter()
- .any(|lib| lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib));
+ .any(|lib| lib.kind == NativeLibKind::StaticBundle && !relevant_lib(sess, lib));
ab.add_rlib(
path,
&name.as_str(),
@@ -872,11 +875,8 @@
// If we're only producing artifacts that are archives, no need to preserve
// the objects as they're losslessly contained inside the archives.
- let output_linked = sess
- .crate_types
- .borrow()
- .iter()
- .any(|&x| x != CrateType::Rlib && x != CrateType::Staticlib);
+ let output_linked =
+ sess.crate_types().iter().any(|&x| x != CrateType::Rlib && x != CrateType::Staticlib);
if !output_linked {
return false;
}
@@ -907,26 +907,28 @@
StaticlibBase,
}
-fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary]) {
+fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) {
let lib_args: Vec<_> = all_native_libs
.iter()
.filter(|l| relevant_lib(sess, l))
.filter_map(|lib| {
let name = lib.name?;
match lib.kind {
- NativeLibraryKind::NativeStaticNobundle | NativeLibraryKind::NativeUnknown => {
+ NativeLibKind::StaticNoBundle
+ | NativeLibKind::Dylib
+ | NativeLibKind::Unspecified => {
if sess.target.target.options.is_like_msvc {
Some(format!("{}.lib", name))
} else {
Some(format!("-l{}", name))
}
}
- NativeLibraryKind::NativeFramework => {
+ NativeLibKind::Framework => {
// ld-only syntax, since there are no frameworks in MSVC
Some(format!("-framework {}", name))
}
// These are included, no need to print them
- NativeLibraryKind::NativeStatic | NativeLibraryKind::NativeRawDylib => None,
+ NativeLibKind::StaticBundle | NativeLibKind::RawDylib => None,
}
})
.collect();
@@ -1696,11 +1698,11 @@
None => continue,
};
match lib.kind {
- NativeLibraryKind::NativeUnknown => cmd.link_dylib(name),
- NativeLibraryKind::NativeFramework => cmd.link_framework(name),
- NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(name),
- NativeLibraryKind::NativeStatic => cmd.link_whole_staticlib(name, &search_path),
- NativeLibraryKind::NativeRawDylib => {
+ NativeLibKind::Dylib | NativeLibKind::Unspecified => cmd.link_dylib(name),
+ NativeLibKind::Framework => cmd.link_framework(name),
+ NativeLibKind::StaticNoBundle => cmd.link_staticlib(name),
+ NativeLibKind::StaticBundle => cmd.link_whole_staticlib(name, &search_path),
+ NativeLibKind::RawDylib => {
// FIXME(#58713): Proper handling for raw dylibs.
bug!("raw_dylib feature not yet implemented");
}
@@ -1890,7 +1892,7 @@
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
let skip_native = native_libs
.iter()
- .any(|lib| lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib));
+ .any(|lib| lib.kind == NativeLibKind::StaticBundle && !relevant_lib(sess, lib));
if (!are_upstream_rust_objects_already_included(sess)
|| ignored_for_lto(sess, &codegen_results.crate_info, cnum))
@@ -2032,9 +2034,9 @@
continue;
}
match lib.kind {
- NativeLibraryKind::NativeUnknown => cmd.link_dylib(name),
- NativeLibraryKind::NativeFramework => cmd.link_framework(name),
- NativeLibraryKind::NativeStaticNobundle => {
+ NativeLibKind::Dylib | NativeLibKind::Unspecified => cmd.link_dylib(name),
+ NativeLibKind::Framework => cmd.link_framework(name),
+ NativeLibKind::StaticNoBundle => {
// Link "static-nobundle" native libs only if the crate they originate from
// is being linked statically to the current crate. If it's linked dynamically
// or is an rlib already included via some other dylib crate, the symbols from
@@ -2046,8 +2048,8 @@
// ignore statically included native libraries here as we've
// already included them when we included the rust library
// previously
- NativeLibraryKind::NativeStatic => {}
- NativeLibraryKind::NativeRawDylib => {
+ NativeLibKind::StaticBundle => {}
+ NativeLibKind::RawDylib => {
// FIXME(#58713): Proper handling for raw dylibs.
bug!("raw_dylib feature not yet implemented");
}
@@ -2056,7 +2058,7 @@
}
}
-fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool {
+fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
match lib.cfg {
Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, None),
None => true,
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index ee5bcf4..49de8c5 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -44,8 +44,7 @@
LinkerInfo {
exports: tcx
.sess
- .crate_types
- .borrow()
+ .crate_types()
.iter()
.map(|&c| (c, exported_symbols(tcx, c)))
.collect(),
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index c0272e1..970d13b 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -18,7 +18,7 @@
use rustc_session::config::{CrateType, Sanitizer};
pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
- crates_export_threshold(&tcx.sess.crate_types.borrow())
+ crates_export_threshold(&tcx.sess.crate_types())
}
fn crate_export_threshold(crate_type: CrateType) -> SymbolExportLevel {
@@ -212,7 +212,7 @@
}));
}
- if tcx.sess.crate_types.borrow().contains(&CrateType::Dylib) {
+ if tcx.sess.crate_types().contains(&CrateType::Dylib) {
let symbol_name = metadata_symbol_name(tcx);
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 53dfe7c..9e03c28 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -142,8 +142,22 @@
let emit_obj = if !should_emit_obj {
EmitObj::None
} else if sess.target.target.options.obj_is_bitcode
- || sess.opts.cg.linker_plugin_lto.enabled()
+ || (sess.opts.cg.linker_plugin_lto.enabled() && !no_builtins)
{
+ // This case is selected if the target uses objects as bitcode, or
+ // if linker plugin LTO is enabled. In the linker plugin LTO case
+ // the assumption is that the final link-step will read the bitcode
+ // and convert it to object code. This may be done by either the
+ // native linker or rustc itself.
+ //
+ // Note, however, that the linker-plugin-lto requested here is
+ // explicitly ignored for `#![no_builtins]` crates. These crates are
+ // specifically ignored by rustc's LTO passes and wouldn't work if
+ // loaded into the linker. These crates define symbols that LLVM
+ // lowers intrinsics to, and these symbol dependencies aren't known
+ // until after codegen. As a result any crate marked
+ // `#![no_builtins]` is assumed to not participate in LTO and
+ // instead goes on to generate object code.
EmitObj::Bitcode
} else if need_bitcode_in_object(sess) {
EmitObj::ObjectCode(BitcodeSection::Full)
@@ -368,7 +382,7 @@
fn need_bitcode_in_object(sess: &Session) -> bool {
let requested_for_rlib = sess.opts.cg.embed_bitcode
- && sess.crate_types.borrow().contains(&CrateType::Rlib)
+ && sess.crate_types().contains(&CrateType::Rlib)
&& sess.opts.output_types.contains_key(&OutputType::Exe);
let forced_by_target = sess.target.target.options.forces_embed_bitcode;
requested_for_rlib || forced_by_target
@@ -977,7 +991,7 @@
};
let cgcx = CodegenContext::<B> {
backend: backend.clone(),
- crate_types: sess.crate_types.borrow().clone(),
+ crate_types: sess.crate_types().to_vec(),
each_linked_rlib_for_lto,
lto: sess.lto(),
no_landing_pads: sess.panic_strategy() == PanicStrategy::Abort,
@@ -1798,7 +1812,7 @@
);
tcx.sess.target.target.options.is_like_msvc &&
- tcx.sess.crate_types.borrow().iter().any(|ct| *ct == CrateType::Rlib) &&
+ tcx.sess.crate_types().iter().any(|ct| *ct == CrateType::Rlib) &&
// ThinLTO can't handle this workaround in all cases, so we don't
// emit the `__imp_` symbols. Instead we make them unnecessary by disallowing
// dynamic linking when linker plugin LTO is enabled.
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index 29398db..5b14258 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -44,6 +44,7 @@
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_session::cgu_reuse_tracker::CguReuse;
use rustc_session::config::{self, EntryFnType};
+use rustc_session::utils::NativeLibKind;
use rustc_session::Session;
use rustc_span::Span;
use rustc_symbol_mangling::test as symbol_names_test;
@@ -895,7 +896,7 @@
.native_libraries(krate)
.iter()
.filter(|lib| {
- if lib.kind != cstore::NativeLibraryKind::NativeUnknown {
+ if !matches!(lib.kind, NativeLibKind::Dylib | NativeLibKind::Unspecified) {
return false;
}
let cfg = match lib.cfg {
@@ -947,7 +948,7 @@
match compute_per_cgu_lto_type(
&tcx.sess.lto(),
&tcx.sess.opts,
- &tcx.sess.crate_types.borrow(),
+ &tcx.sess.crate_types(),
ModuleKind::Regular,
) {
ComputedLtoType::No => CguReuse::PostLto,
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index 7dc09b5..bd37218 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -24,7 +24,7 @@
use rustc_hir::def_id::CrateNum;
use rustc_hir::LangItem;
use rustc_middle::dep_graph::WorkProduct;
-use rustc_middle::middle::cstore::{CrateSource, LibSource, NativeLibrary};
+use rustc_middle::middle::cstore::{CrateSource, LibSource, NativeLib};
use rustc_middle::middle::dependency_format::Dependencies;
use rustc_middle::ty::query::Providers;
use rustc_session::config::{OutputFilenames, OutputType, RUST_CGU_EXT};
@@ -112,9 +112,9 @@
pub compiler_builtins: Option<CrateNum>,
pub profiler_runtime: Option<CrateNum>,
pub is_no_builtins: FxHashSet<CrateNum>,
- pub native_libraries: FxHashMap<CrateNum, Lrc<Vec<NativeLibrary>>>,
+ pub native_libraries: FxHashMap<CrateNum, Lrc<Vec<NativeLib>>>,
pub crate_name: FxHashMap<CrateNum, String>,
- pub used_libraries: Lrc<Vec<NativeLibrary>>,
+ pub used_libraries: Lrc<Vec<NativeLib>>,
pub link_args: Lrc<Vec<String>>,
pub used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>,
pub used_crates_static: Vec<(CrateNum, LibSource)>,
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 81ad032..6772122 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -15,6 +15,7 @@
log = "0.4"
jobserver_crate = { version = "0.1.13", package = "jobserver" }
lazy_static = "1"
+once_cell = { version = "1", features = ["parking_lot"] }
rustc_serialize = { path = "../libserialize", package = "serialize" }
graphviz = { path = "../libgraphviz" }
cfg-if = "0.1.2"
diff --git a/src/librustc_data_structures/flock.rs b/src/librustc_data_structures/flock.rs
index 2a0139f..9383be4 100644
--- a/src/librustc_data_structures/flock.rs
+++ b/src/librustc_data_structures/flock.rs
@@ -7,18 +7,22 @@
#![allow(non_camel_case_types)]
#![allow(nonstandard_style)]
+use std::fs::{File, OpenOptions};
use std::io;
use std::path::Path;
cfg_if! {
- if #[cfg(unix)] {
- use std::ffi::{CString, OsStr};
- use std::mem;
+ // We use `flock` rather than `fcntl` on Linux, because WSL1 does not support
+ // `fcntl`-style advisory locks properly (rust-lang/rust#72157).
+ //
+ // For other Unix targets we still use `fcntl` because it's more portable than
+ // `flock`.
+ if #[cfg(target_os = "linux")] {
use std::os::unix::prelude::*;
#[derive(Debug)]
pub struct Lock {
- fd: libc::c_int,
+ _file: File,
}
impl Lock {
@@ -27,23 +31,56 @@
create: bool,
exclusive: bool)
-> io::Result<Lock> {
- let os: &OsStr = p.as_ref();
- let buf = CString::new(os.as_bytes()).unwrap();
- let open_flags = if create {
- libc::O_RDWR | libc::O_CREAT
+ let file = OpenOptions::new()
+ .read(true)
+ .write(true)
+ .create(create)
+ .mode(libc::S_IRWXU as u32)
+ .open(p)?;
+
+ let mut operation = if exclusive {
+ libc::LOCK_EX
} else {
- libc::O_RDWR
+ libc::LOCK_SH
};
-
- let fd = unsafe {
- libc::open(buf.as_ptr(), open_flags,
- libc::S_IRWXU as libc::c_int)
- };
-
- if fd < 0 {
- return Err(io::Error::last_os_error());
+ if !wait {
+ operation |= libc::LOCK_NB
}
+ let ret = unsafe { libc::flock(file.as_raw_fd(), operation) };
+ if ret == -1 {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(Lock { _file: file })
+ }
+ }
+ }
+
+ // Note that we don't need a Drop impl to execute `flock(fd, LOCK_UN)`. Lock acquired by
+ // `flock` is associated with the file descriptor and closing the file release it
+ // automatically.
+ } else if #[cfg(unix)] {
+ use std::mem;
+ use std::os::unix::prelude::*;
+
+ #[derive(Debug)]
+ pub struct Lock {
+ file: File,
+ }
+
+ impl Lock {
+ pub fn new(p: &Path,
+ wait: bool,
+ create: bool,
+ exclusive: bool)
+ -> io::Result<Lock> {
+ let file = OpenOptions::new()
+ .read(true)
+ .write(true)
+ .create(create)
+ .mode(libc::S_IRWXU as u32)
+ .open(p)?;
+
let lock_type = if exclusive {
libc::F_WRLCK
} else {
@@ -58,14 +95,12 @@
let cmd = if wait { libc::F_SETLKW } else { libc::F_SETLK };
let ret = unsafe {
- libc::fcntl(fd, cmd, &flock)
+ libc::fcntl(file.as_raw_fd(), cmd, &flock)
};
if ret == -1 {
- let err = io::Error::last_os_error();
- unsafe { libc::close(fd); }
- Err(err)
+ Err(io::Error::last_os_error())
} else {
- Ok(Lock { fd })
+ Ok(Lock { file })
}
}
}
@@ -79,15 +114,13 @@
flock.l_len = 0;
unsafe {
- libc::fcntl(self.fd, libc::F_SETLK, &flock);
- libc::close(self.fd);
+ libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock);
}
}
}
} else if #[cfg(windows)] {
use std::mem;
use std::os::windows::prelude::*;
- use std::fs::{File, OpenOptions};
use winapi::um::minwinbase::{OVERLAPPED, LOCKFILE_FAIL_IMMEDIATELY, LOCKFILE_EXCLUSIVE_LOCK};
use winapi::um::fileapi::LockFileEx;
diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs
index 9051b17..39afb3d 100644
--- a/src/librustc_data_structures/sync.rs
+++ b/src/librustc_data_structures/sync.rs
@@ -20,7 +20,6 @@
use crate::owning_ref::{Erased, OwningRef};
use std::collections::HashMap;
use std::hash::{BuildHasher, Hash};
-use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
pub use std::sync::atomic::Ordering;
@@ -230,6 +229,8 @@
pub use std::cell::RefMut as LockGuard;
pub use std::cell::RefMut as MappedLockGuard;
+ pub use once_cell::unsync::OnceCell;
+
use std::cell::RefCell as InnerRwLock;
use std::cell::RefCell as InnerLock;
@@ -313,6 +314,8 @@
pub use parking_lot::MutexGuard as LockGuard;
pub use parking_lot::MappedMutexGuard as MappedLockGuard;
+ pub use once_cell::sync::OnceCell;
+
pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64};
pub use crossbeam_utils::atomic::AtomicCell;
@@ -432,134 +435,6 @@
}
}
-/// A type whose inner value can be written once and then will stay read-only
-// This contains a PhantomData<T> since this type conceptually owns a T outside the Mutex once
-// initialized. This ensures that Once<T> is Sync only if T is. If we did not have PhantomData<T>
-// we could send a &Once<Cell<bool>> to multiple threads and call `get` on it to get access
-// to &Cell<bool> on those threads.
-pub struct Once<T>(Lock<Option<T>>, PhantomData<T>);
-
-impl<T> Once<T> {
- /// Creates an Once value which is uninitialized
- #[inline(always)]
- pub fn new() -> Self {
- Once(Lock::new(None), PhantomData)
- }
-
- /// Consumes the value and returns Some(T) if it was initialized
- #[inline(always)]
- pub fn into_inner(self) -> Option<T> {
- self.0.into_inner()
- }
-
- /// Tries to initialize the inner value to `value`.
- /// Returns `None` if the inner value was uninitialized and `value` was consumed setting it
- /// otherwise if the inner value was already set it returns `value` back to the caller
- #[inline]
- pub fn try_set(&self, value: T) -> Option<T> {
- let mut lock = self.0.lock();
- if lock.is_some() {
- return Some(value);
- }
- *lock = Some(value);
- None
- }
-
- /// Tries to initialize the inner value to `value`.
- /// Returns `None` if the inner value was uninitialized and `value` was consumed setting it
- /// otherwise if the inner value was already set it asserts that `value` is equal to the inner
- /// value and then returns `value` back to the caller
- #[inline]
- pub fn try_set_same(&self, value: T) -> Option<T>
- where
- T: Eq,
- {
- let mut lock = self.0.lock();
- if let Some(ref inner) = *lock {
- assert!(*inner == value);
- return Some(value);
- }
- *lock = Some(value);
- None
- }
-
- /// Tries to initialize the inner value to `value` and panics if it was already initialized
- #[inline]
- pub fn set(&self, value: T) {
- assert!(self.try_set(value).is_none());
- }
-
- /// Initializes the inner value if it wasn't already done by calling the provided closure. It
- /// ensures that no-one else can access the value in the mean time by holding a lock for the
- /// duration of the closure.
- /// A reference to the inner value is returned.
- #[inline]
- pub fn init_locking<F: FnOnce() -> T>(&self, f: F) -> &T {
- {
- let mut lock = self.0.lock();
- if lock.is_none() {
- *lock = Some(f());
- }
- }
-
- self.borrow()
- }
-
- /// Tries to initialize the inner value by calling the closure without ensuring that no-one
- /// else can access it. This mean when this is called from multiple threads, multiple
- /// closures may concurrently be computing a value which the inner value should take.
- /// Only one of these closures are used to actually initialize the value.
- /// If some other closure already set the value,
- /// we return the value our closure computed wrapped in a `Option`.
- /// If our closure set the value, `None` is returned.
- /// If the value is already initialized, the closure is not called and `None` is returned.
- #[inline]
- pub fn init_nonlocking<F: FnOnce() -> T>(&self, f: F) -> Option<T> {
- if self.0.lock().is_some() { None } else { self.try_set(f()) }
- }
-
- /// Tries to initialize the inner value by calling the closure without ensuring that no-one
- /// else can access it. This mean when this is called from multiple threads, multiple
- /// closures may concurrently be computing a value which the inner value should take.
- /// Only one of these closures are used to actually initialize the value.
- /// If some other closure already set the value, we assert that it our closure computed
- /// a value equal to the value already set and then
- /// we return the value our closure computed wrapped in a `Option`.
- /// If our closure set the value, `None` is returned.
- /// If the value is already initialized, the closure is not called and `None` is returned.
- #[inline]
- pub fn init_nonlocking_same<F: FnOnce() -> T>(&self, f: F) -> Option<T>
- where
- T: Eq,
- {
- if self.0.lock().is_some() { None } else { self.try_set_same(f()) }
- }
-
- /// Tries to get a reference to the inner value, returns `None` if it is not yet initialized
- #[inline(always)]
- pub fn try_get(&self) -> Option<&T> {
- let lock = &*self.0.lock();
- if let Some(ref inner) = *lock {
- // This is safe since we won't mutate the inner value
- unsafe { Some(&*(inner as *const T)) }
- } else {
- None
- }
- }
-
- /// Gets reference to the inner value, panics if it is not yet initialized
- #[inline(always)]
- pub fn get(&self) -> &T {
- self.try_get().expect("value was not set")
- }
-
- /// Gets reference to the inner value, panics if it is not yet initialized
- #[inline(always)]
- pub fn borrow(&self) -> &T {
- self.get()
- }
-}
-
#[derive(Debug)]
pub struct Lock<T>(InnerLock<T>);
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 6847b17..68ce93d 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -586,7 +586,7 @@
if let Input::File(file) = compiler.input() {
// FIXME: #![crate_type] and #![crate_name] support not implemented yet
let attrs = vec![];
- sess.crate_types.set(collect_crate_types(sess, &attrs));
+ sess.init_crate_types(collect_crate_types(sess, &attrs));
let outputs = compiler.build_output_filenames(&sess, &attrs);
let rlink_data = fs::read_to_string(file).unwrap_or_else(|err| {
sess.fatal(&format!("failed to read rlink file: {}", err));
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index a443b8f..0a21eb8 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -396,7 +396,7 @@
annotation.pp_ann(),
false,
parse.edition,
- parse.injected_crate_name.try_get().is_some(),
+ parse.injected_crate_name.get().is_some(),
)
})
} else {
@@ -438,7 +438,7 @@
annotation.pp_ann(),
true,
parse.edition,
- parse.injected_crate_name.try_get().is_some(),
+ parse.injected_crate_name.get().is_some(),
)
})
}
diff --git a/src/librustc_error_codes/error_codes/E0590.md b/src/librustc_error_codes/error_codes/E0590.md
index df7aa4f..11005b8 100644
--- a/src/librustc_error_codes/error_codes/E0590.md
+++ b/src/librustc_error_codes/error_codes/E0590.md
@@ -1,13 +1,17 @@
-`break` or `continue` must include a label when used in the condition of a
-`while` loop.
+`break` or `continue` keywords were used in a condition of a `while` loop
+without a label.
-Example of erroneous code:
+Erroneous code code:
```compile_fail,E0590
while break {}
```
+`break` or `continue` must include a label when used in the condition of a
+`while` loop.
+
To fix this, add a label specifying which loop is being broken out of:
+
```
'foo: while break 'foo {}
```
diff --git a/src/librustc_error_codes/error_codes/E0593.md b/src/librustc_error_codes/error_codes/E0593.md
index b32923a..1902d73 100644
--- a/src/librustc_error_codes/error_codes/E0593.md
+++ b/src/librustc_error_codes/error_codes/E0593.md
@@ -11,3 +11,14 @@
foo(|y| { });
}
```
+
+You have to provide the same number of arguments as expected by the `Fn`-based
+type. So to fix the previous example, we need to remove the `y` argument:
+
+```
+fn foo<F: Fn()>(x: F) { }
+
+fn main() {
+ foo(|| { }); // ok!
+}
+```
diff --git a/src/librustc_error_codes/error_codes/E0599.md b/src/librustc_error_codes/error_codes/E0599.md
index c44e605..5b1590b 100644
--- a/src/librustc_error_codes/error_codes/E0599.md
+++ b/src/librustc_error_codes/error_codes/E0599.md
@@ -9,3 +9,18 @@
x.chocolate(); // error: no method named `chocolate` found for type `Mouth`
// in the current scope
```
+
+In this case, you need to implement the `chocolate` method to fix the error:
+
+```
+struct Mouth;
+
+impl Mouth {
+ fn chocolate(&self) { // We implement the `chocolate` method here.
+ println!("Hmmm! I love chocolate!");
+ }
+}
+
+let x = Mouth;
+x.chocolate(); // ok!
+```
diff --git a/src/librustc_error_codes/error_codes/E0600.md b/src/librustc_error_codes/error_codes/E0600.md
index 172e2a3..356006c 100644
--- a/src/librustc_error_codes/error_codes/E0600.md
+++ b/src/librustc_error_codes/error_codes/E0600.md
@@ -1,6 +1,6 @@
An unary operator was used on a type which doesn't implement it.
-Example of erroneous code:
+Erroneous code example:
```compile_fail,E0600
enum Question {
diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index fe5bf6f..0137080 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -13,6 +13,7 @@
use rustc_errors::{DiagnosticBuilder, ErrorReported};
use rustc_parse::{self, parser, MACRO_ARGUMENTS};
use rustc_session::parse::ParseSess;
+use rustc_span::def_id::DefId;
use rustc_span::edition::Edition;
use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
use rustc_span::source_map::SourceMap;
@@ -857,7 +858,13 @@
SyntaxExtension::default(SyntaxExtensionKind::NonMacroAttr { mark_used }, edition)
}
- pub fn expn_data(&self, parent: ExpnId, call_site: Span, descr: Symbol) -> ExpnData {
+ pub fn expn_data(
+ &self,
+ parent: ExpnId,
+ call_site: Span,
+ descr: Symbol,
+ macro_def_id: Option<DefId>,
+ ) -> ExpnData {
ExpnData {
kind: ExpnKind::Macro(self.macro_kind(), descr),
parent,
@@ -867,6 +874,7 @@
allow_internal_unsafe: self.allow_internal_unsafe,
local_inner_macros: self.local_inner_macros,
edition: self.edition,
+ macro_def_id,
}
}
}
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index 485c514..b505302 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -988,6 +988,7 @@
ExpnKind::Macro(MacroKind::Attr, sym::derive),
item.span(),
self.cx.parse_sess.edition,
+ None,
)
}),
_ => None,
diff --git a/src/librustc_infer/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs
index 5551b56..c2dae6b 100644
--- a/src/librustc_infer/infer/canonical/canonicalizer.rs
+++ b/src/librustc_infer/infer/canonical/canonicalizer.rs
@@ -332,7 +332,6 @@
ty::ReStatic
| ty::ReEarlyBound(..)
| ty::ReFree(_)
- | ty::ReScope(_)
| ty::ReEmpty(_)
| ty::RePlaceholder(..)
| ty::ReErased => self.canonicalize_region_mode.canonicalize_free_region(self, r),
diff --git a/src/librustc_infer/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs
index c7a7cf8..23c9eeb 100644
--- a/src/librustc_infer/infer/canonical/query_response.rs
+++ b/src/librustc_infer/infer/canonical/query_response.rs
@@ -25,7 +25,7 @@
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
-use rustc_middle::ty::{self, BoundVar, Const, Ty, TyCtxt};
+use rustc_middle::ty::{self, BoundVar, Const, ToPredicate, Ty, TyCtxt};
use std::fmt::Debug;
impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
@@ -532,12 +532,14 @@
cause.clone(),
param_env,
match k1.unpack() {
- GenericArgKind::Lifetime(r1) => ty::Predicate::RegionOutlives(
+ GenericArgKind::Lifetime(r1) => ty::PredicateKind::RegionOutlives(
ty::Binder::bind(ty::OutlivesPredicate(r1, r2)),
- ),
- GenericArgKind::Type(t1) => {
- ty::Predicate::TypeOutlives(ty::Binder::bind(ty::OutlivesPredicate(t1, r2)))
- }
+ )
+ .to_predicate(self.tcx),
+ GenericArgKind::Type(t1) => ty::PredicateKind::TypeOutlives(ty::Binder::bind(
+ ty::OutlivesPredicate(t1, r2),
+ ))
+ .to_predicate(self.tcx),
GenericArgKind::Const(..) => {
// Consts cannot outlive one another, so we don't expect to
// ecounter this branch.
@@ -664,9 +666,10 @@
self.obligations.push(Obligation {
cause: self.cause.clone(),
param_env: self.param_env,
- predicate: ty::Predicate::RegionOutlives(ty::Binder::dummy(ty::OutlivesPredicate(
+ predicate: ty::PredicateKind::RegionOutlives(ty::Binder::dummy(ty::OutlivesPredicate(
sup, sub,
- ))),
+ )))
+ .to_predicate(self.infcx.tcx),
recursion_depth: 0,
});
}
diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs
index 3467457..70a2122 100644
--- a/src/librustc_infer/infer/combine.rs
+++ b/src/librustc_infer/infer/combine.rs
@@ -39,7 +39,7 @@
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{IntType, UintType};
use rustc_span::{Span, DUMMY_SP};
@@ -307,7 +307,7 @@
self.obligations.push(Obligation::new(
self.trace.cause.clone(),
self.param_env,
- ty::Predicate::WellFormed(b_ty),
+ ty::PredicateKind::WellFormed(b_ty).to_predicate(self.infcx.tcx),
));
}
@@ -398,11 +398,15 @@
b: &'tcx ty::Const<'tcx>,
) {
let predicate = if a_is_expected {
- ty::Predicate::ConstEquate(a, b)
+ ty::PredicateKind::ConstEquate(a, b)
} else {
- ty::Predicate::ConstEquate(b, a)
+ ty::PredicateKind::ConstEquate(b, a)
};
- self.obligations.push(Obligation::new(self.trace.cause.clone(), self.param_env, predicate));
+ self.obligations.push(Obligation::new(
+ self.trace.cause.clone(),
+ self.param_env,
+ predicate.to_predicate(self.tcx()),
+ ));
}
}
@@ -615,7 +619,6 @@
| ty::ReVar(..)
| ty::ReEmpty(_)
| ty::ReStatic
- | ty::ReScope(..)
| ty::ReEarlyBound(..)
| ty::ReFree(..) => {
// see common code below
diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs
index a8d6c01..cc479aa 100644
--- a/src/librustc_infer/infer/error_reporting/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/mod.rs
@@ -61,7 +61,6 @@
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::Node;
-use rustc_middle::middle::region;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{
self,
@@ -81,58 +80,12 @@
pub(super) fn note_and_explain_region(
tcx: TyCtxt<'tcx>,
- region_scope_tree: ®ion::ScopeTree,
err: &mut DiagnosticBuilder<'_>,
prefix: &str,
region: ty::Region<'tcx>,
suffix: &str,
) {
let (description, span) = match *region {
- ty::ReScope(scope) => {
- let new_string;
- let unknown_scope =
- || format!("{}unknown scope: {:?}{}. Please report a bug.", prefix, scope, suffix);
- let span = scope.span(tcx, region_scope_tree);
- let hir_id = scope.hir_id(region_scope_tree);
- let tag = match hir_id.and_then(|hir_id| tcx.hir().find(hir_id)) {
- Some(Node::Block(_)) => "block",
- Some(Node::Expr(expr)) => match expr.kind {
- hir::ExprKind::Call(..) => "call",
- hir::ExprKind::MethodCall(..) => "method call",
- hir::ExprKind::Match(.., hir::MatchSource::IfLetDesugar { .. }) => "if let",
- hir::ExprKind::Match(.., hir::MatchSource::WhileLetDesugar) => "while let",
- hir::ExprKind::Match(.., hir::MatchSource::ForLoopDesugar) => "for",
- hir::ExprKind::Match(..) => "match",
- _ => "expression",
- },
- Some(Node::Stmt(_)) => "statement",
- Some(Node::Item(it)) => item_scope_tag(&it),
- Some(Node::TraitItem(it)) => trait_item_scope_tag(&it),
- Some(Node::ImplItem(it)) => impl_item_scope_tag(&it),
- Some(_) | None => {
- err.span_note(span, &unknown_scope());
- return;
- }
- };
- let scope_decorated_tag = match scope.data {
- region::ScopeData::Node => tag,
- region::ScopeData::CallSite => "scope of call-site for function",
- region::ScopeData::Arguments => "scope of function body",
- region::ScopeData::Destruction => {
- new_string = format!("destruction scope surrounding {}", tag);
- &new_string[..]
- }
- region::ScopeData::Remainder(first_statement_index) => {
- new_string = format!(
- "block suffix following statement {}",
- first_statement_index.index()
- );
- &new_string[..]
- }
- };
- explain_span(tcx, scope_decorated_tag, span)
- }
-
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
msg_span_from_free_region(tcx, region)
}
@@ -284,7 +237,6 @@
pub fn unexpected_hidden_region_diagnostic(
tcx: TyCtxt<'tcx>,
- region_scope_tree: Option<®ion::ScopeTree>,
span: Span,
hidden_ty: Ty<'tcx>,
hidden_region: ty::Region<'tcx>,
@@ -297,64 +249,56 @@
);
// Explain the region we are capturing.
- if let ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) = hidden_region {
- // Assuming regionck succeeded (*), we ought to always be
- // capturing *some* region from the fn header, and hence it
- // ought to be free. So under normal circumstances, we will go
- // down this path which gives a decent human readable
- // explanation.
- //
- // (*) if not, the `tainted_by_errors` field would be set to
- // `Some(ErrorReported)` in any case, so we wouldn't be here at all.
- note_and_explain_free_region(
- tcx,
- &mut err,
- &format!("hidden type `{}` captures ", hidden_ty),
- hidden_region,
- "",
- );
- } else {
- // Ugh. This is a painful case: the hidden region is not one
- // that we can easily summarize or explain. This can happen
- // in a case like
- // `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
- //
- // ```
- // fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
- // if condition() { a } else { b }
- // }
- // ```
- //
- // Here the captured lifetime is the intersection of `'a` and
- // `'b`, which we can't quite express.
-
- if let Some(region_scope_tree) = region_scope_tree {
- // If the `region_scope_tree` is available, this is being
- // invoked from the "region inferencer error". We can at
- // least report a really cryptic error for now.
- note_and_explain_region(
+ match hidden_region {
+ ty::ReEmpty(ty::UniverseIndex::ROOT) => {
+ // All lifetimes shorter than the function body are `empty` in
+ // lexical region resolution. The default explanation of "an empty
+ // lifetime" isn't really accurate here.
+ let message = format!(
+ "hidden type `{}` captures lifetime smaller than the function body",
+ hidden_ty
+ );
+ err.span_note(span, &message);
+ }
+ ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) => {
+ // Assuming regionck succeeded (*), we ought to always be
+ // capturing *some* region from the fn header, and hence it
+ // ought to be free. So under normal circumstances, we will go
+ // down this path which gives a decent human readable
+ // explanation.
+ //
+ // (*) if not, the `tainted_by_errors` field would be set to
+ // `Some(ErrorReported)` in any case, so we wouldn't be here at all.
+ note_and_explain_free_region(
tcx,
- region_scope_tree,
&mut err,
&format!("hidden type `{}` captures ", hidden_ty),
hidden_region,
"",
);
- } else {
- // If the `region_scope_tree` is *unavailable*, this is
- // being invoked by the code that comes *after* region
- // inferencing. This is a bug, as the region inferencer
- // ought to have noticed the failed constraint and invoked
- // error reporting, which in turn should have prevented us
- // from getting trying to infer the hidden type
- // completely.
- tcx.sess.delay_span_bug(
- span,
- &format!(
- "hidden type captures unexpected lifetime `{:?}` \
- but no region inference failure",
- hidden_region,
- ),
+ }
+ _ => {
+ // Ugh. This is a painful case: the hidden region is not one
+ // that we can easily summarize or explain. This can happen
+ // in a case like
+ // `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
+ //
+ // ```
+ // fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
+ // if condition() { a } else { b }
+ // }
+ // ```
+ //
+ // Here the captured lifetime is the intersection of `'a` and
+ // `'b`, which we can't quite express.
+
+ // We can at least report a really cryptic error for now.
+ note_and_explain_region(
+ tcx,
+ &mut err,
+ &format!("hidden type `{}` captures ", hidden_ty),
+ hidden_region,
+ "",
);
}
}
@@ -363,11 +307,7 @@
}
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
- pub fn report_region_errors(
- &self,
- region_scope_tree: ®ion::ScopeTree,
- errors: &Vec<RegionResolutionError<'tcx>>,
- ) {
+ pub fn report_region_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>) {
debug!("report_region_errors(): {} errors to start", errors.len());
// try to pre-process the errors, which will group some of them
@@ -390,17 +330,14 @@
// general bit of code that displays the error information
RegionResolutionError::ConcreteFailure(origin, sub, sup) => {
if sub.is_placeholder() || sup.is_placeholder() {
- self.report_placeholder_failure(region_scope_tree, origin, sub, sup)
- .emit();
+ self.report_placeholder_failure(origin, sub, sup).emit();
} else {
- self.report_concrete_failure(region_scope_tree, origin, sub, sup)
- .emit();
+ self.report_concrete_failure(origin, sub, sup).emit();
}
}
RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => {
self.report_generic_bound_failure(
- region_scope_tree,
origin.span(),
Some(origin),
param_ty,
@@ -417,29 +354,12 @@
sup_r,
) => {
if sub_r.is_placeholder() {
- self.report_placeholder_failure(
- region_scope_tree,
- sub_origin,
- sub_r,
- sup_r,
- )
- .emit();
+ self.report_placeholder_failure(sub_origin, sub_r, sup_r).emit();
} else if sup_r.is_placeholder() {
- self.report_placeholder_failure(
- region_scope_tree,
- sup_origin,
- sub_r,
- sup_r,
- )
- .emit();
+ self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
} else {
self.report_sub_sup_conflict(
- region_scope_tree,
- var_origin,
- sub_origin,
- sub_r,
- sup_origin,
- sup_r,
+ var_origin, sub_origin, sub_r, sup_origin, sup_r,
);
}
}
@@ -460,13 +380,7 @@
// value.
let sub_r = self.tcx.mk_region(ty::ReEmpty(var_universe));
- self.report_placeholder_failure(
- region_scope_tree,
- sup_origin,
- sub_r,
- sup_r,
- )
- .emit();
+ self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
}
RegionResolutionError::MemberConstraintFailure {
@@ -477,7 +391,6 @@
let hidden_ty = self.resolve_vars_if_possible(&hidden_ty);
unexpected_hidden_region_diagnostic(
self.tcx,
- Some(region_scope_tree),
span,
hidden_ty,
member_region,
@@ -1754,19 +1667,16 @@
pub fn report_generic_bound_failure(
&self,
- region_scope_tree: ®ion::ScopeTree,
span: Span,
origin: Option<SubregionOrigin<'tcx>>,
bound_kind: GenericKind<'tcx>,
sub: Region<'tcx>,
) {
- self.construct_generic_bound_failure(region_scope_tree, span, origin, bound_kind, sub)
- .emit();
+ self.construct_generic_bound_failure(span, origin, bound_kind, sub).emit();
}
pub fn construct_generic_bound_failure(
&self,
- region_scope_tree: ®ion::ScopeTree,
span: Span,
origin: Option<SubregionOrigin<'tcx>>,
bound_kind: GenericKind<'tcx>,
@@ -1918,7 +1828,6 @@
));
note_and_explain_region(
self.tcx,
- region_scope_tree,
&mut err,
&format!("{} must be valid for ", labeled_user_string),
sub,
@@ -1936,7 +1845,6 @@
fn report_sub_sup_conflict(
&self,
- region_scope_tree: ®ion::ScopeTree,
var_origin: RegionVariableOrigin,
sub_origin: SubregionOrigin<'tcx>,
sub_region: Region<'tcx>,
@@ -1947,7 +1855,6 @@
note_and_explain_region(
self.tcx,
- region_scope_tree,
&mut err,
"first, the lifetime cannot outlive ",
sup_region,
@@ -1973,7 +1880,6 @@
if sub_expected == sup_expected && sub_found == sup_found {
note_and_explain_region(
self.tcx,
- region_scope_tree,
&mut err,
"...but the lifetime must also be valid for ",
sub_region,
@@ -1995,7 +1901,6 @@
note_and_explain_region(
self.tcx,
- region_scope_tree,
&mut err,
"but, the lifetime must be valid for ",
sub_region,
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs
index 2aed3d9..efe5268 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs
@@ -8,7 +8,6 @@
mod different_lifetimes;
mod find_anon_type;
mod named_anon_conflict;
-mod outlives_closure;
mod placeholder_error;
mod static_impl_trait;
mod trait_impl_difference;
@@ -57,7 +56,6 @@
ErrorReported
})
.or_else(|| self.try_report_anon_anon_conflict())
- .or_else(|| self.try_report_outlives_closure())
.or_else(|| self.try_report_static_impl_trait())
.or_else(|| self.try_report_impl_not_conforming_to_trait())
}
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/outlives_closure.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/outlives_closure.rs
deleted file mode 100644
index fc858a4..0000000
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/outlives_closure.rs
+++ /dev/null
@@ -1,117 +0,0 @@
-//! Error Reporting for Anonymous Region Lifetime Errors
-//! where both the regions are anonymous.
-
-use crate::infer::error_reporting::nice_region_error::NiceRegionError;
-use crate::infer::lexical_region_resolve::RegionResolutionError::SubSupConflict;
-use crate::infer::SubregionOrigin;
-use rustc_errors::ErrorReported;
-use rustc_hir::{Expr, ExprKind::Closure, Node};
-use rustc_middle::ty::RegionKind;
-
-impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
- /// Print the error message for lifetime errors when binding escapes a closure.
- ///
- /// Consider a case where we have
- ///
- /// ```no_run
- /// fn with_int<F>(f: F) where F: FnOnce(&isize) {
- /// let x = 3;
- /// f(&x);
- /// }
- /// fn main() {
- /// let mut x = None;
- /// with_int(|y| x = Some(y));
- /// }
- /// ```
- ///
- /// the output will be
- ///
- /// ```text
- /// let mut x = None;
- /// ----- borrowed data cannot be stored into here...
- /// with_int(|y| x = Some(y));
- /// --- ^ cannot be stored outside of its closure
- /// |
- /// ...because it cannot outlive this closure
- /// ```
- pub(super) fn try_report_outlives_closure(&self) -> Option<ErrorReported> {
- if let Some(SubSupConflict(_, origin, ref sub_origin, _, ref sup_origin, sup_region)) =
- self.error
- {
- // #45983: when trying to assign the contents of an argument to a binding outside of a
- // closure, provide a specific message pointing this out.
- if let (
- &SubregionOrigin::BindingTypeIsNotValidAtDecl(ref external_span),
- &RegionKind::ReFree(ref free_region),
- ) = (&sub_origin, sup_region)
- {
- let hir = &self.tcx().hir();
- if let Some(def_id) = free_region.scope.as_local() {
- let hir_id = hir.as_local_hir_id(def_id);
- if let Node::Expr(Expr { kind: Closure(_, _, _, closure_span, None), .. }) =
- hir.get(hir_id)
- {
- let sup_sp = sup_origin.span();
- let origin_sp = origin.span();
- let mut err = self.tcx().sess.struct_span_err(
- sup_sp,
- "borrowed data cannot be stored outside of its closure",
- );
- err.span_label(sup_sp, "cannot be stored outside of its closure");
- if origin_sp == sup_sp || origin_sp.contains(sup_sp) {
- // // sup_sp == origin.span():
- //
- // let mut x = None;
- // ----- borrowed data cannot be stored into here...
- // with_int(|y| x = Some(y));
- // --- ^ cannot be stored outside of its closure
- // |
- // ...because it cannot outlive this closure
- //
- // // origin.contains(&sup_sp):
- //
- // let mut f: Option<&u32> = None;
- // ----- borrowed data cannot be stored into here...
- // closure_expecting_bound(|x: &'x u32| {
- // ------------ ... because it cannot outlive this closure
- // f = Some(x);
- // ^ cannot be stored outside of its closure
- err.span_label(
- *external_span,
- "borrowed data cannot be stored into here...",
- );
- err.span_label(
- *closure_span,
- "...because it cannot outlive this closure",
- );
- } else {
- // FIXME: the wording for this case could be much improved
- //
- // let mut lines_to_use: Vec<&CrateId> = Vec::new();
- // - cannot infer an appropriate lifetime...
- // let push_id = |installed_id: &CrateId| {
- // ------- ------------------------ borrowed data cannot outlive this closure
- // |
- // ...so that variable is valid at time of its declaration
- // lines_to_use.push(installed_id);
- // ^^^^^^^^^^^^ cannot be stored outside of its closure
- err.span_label(origin_sp, "cannot infer an appropriate lifetime...");
- err.span_label(
- *external_span,
- "...so that variable is valid at time of its \
- declaration",
- );
- err.span_label(
- *closure_span,
- "borrowed data cannot outlive this closure",
- );
- }
- err.emit();
- return Some(ErrorReported);
- }
- }
- }
- }
- None
- }
-}
diff --git a/src/librustc_infer/infer/error_reporting/note.rs b/src/librustc_infer/infer/error_reporting/note.rs
index 81f3783..8fbb89d 100644
--- a/src/librustc_infer/infer/error_reporting/note.rs
+++ b/src/librustc_infer/infer/error_reporting/note.rs
@@ -1,7 +1,6 @@
use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt};
use crate::infer::{self, InferCtxt, SubregionOrigin};
use rustc_errors::{struct_span_err, DiagnosticBuilder};
-use rustc_middle::middle::region;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{self, Region};
@@ -38,65 +37,12 @@
let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
err.span_note(span, &format!("...so that closure can access `{}`", var_name));
}
- infer::InfStackClosure(span) => {
- err.span_note(span, "...so that closure does not outlive its stack frame");
- }
- infer::InvokeClosure(span) => {
- err.span_note(span, "...so that closure is not invoked outside its lifetime");
- }
- infer::DerefPointer(span) => {
- err.span_note(span, "...so that pointer is not dereferenced outside its lifetime");
- }
- infer::ClosureCapture(span, id) => {
- err.span_note(
- span,
- &format!(
- "...so that captured variable `{}` does not outlive the \
- enclosing closure",
- self.tcx.hir().name(id)
- ),
- );
- }
- infer::IndexSlice(span) => {
- err.span_note(span, "...so that slice is not indexed outside the lifetime");
- }
infer::RelateObjectBound(span) => {
err.span_note(span, "...so that it can be closed over into an object");
}
- infer::CallRcvr(span) => {
- err.span_note(span, "...so that method receiver is valid for the method call");
- }
- infer::CallArg(span) => {
- err.span_note(span, "...so that argument is valid for the call");
- }
infer::CallReturn(span) => {
err.span_note(span, "...so that return value is valid for the call");
}
- infer::Operand(span) => {
- err.span_note(span, "...so that operand is valid for operation");
- }
- infer::AddrOf(span) => {
- err.span_note(span, "...so that reference is valid at the time of borrow");
- }
- infer::AutoBorrow(span) => {
- err.span_note(span, "...so that auto-reference is valid at the time of borrow");
- }
- infer::ExprTypeIsNotInScope(t, span) => {
- err.span_note(
- span,
- &format!(
- "...so type `{}` of expression is valid during the \
- expression",
- self.ty_to_string(t)
- ),
- );
- }
- infer::BindingTypeIsNotValidAtDecl(span) => {
- err.span_note(span, "...so that variable is valid at time of its declaration");
- }
- infer::ParameterInScope(_, span) => {
- err.span_note(span, "...so that a type/lifetime parameter is in scope here");
- }
infer::DataBorrowed(ty, span) => {
err.span_note(
span,
@@ -126,25 +72,12 @@
),
);
}
- infer::RelateDefaultParamBound(span, t) => {
- err.span_note(
- span,
- &format!(
- "...so that type parameter instantiated with `{}`, will \
- meet its declared lifetime bounds",
- self.ty_to_string(t)
- ),
- );
- }
infer::RelateRegionParamBound(span) => {
err.span_note(
span,
"...so that the declared lifetime parameter bounds are satisfied",
);
}
- infer::SafeDestructor(span) => {
- err.span_note(span, "...so that references are valid when the destructor runs");
- }
infer::CompareImplMethodObligation { span, .. } => {
err.span_note(
span,
@@ -157,7 +90,6 @@
pub(super) fn report_concrete_failure(
&self,
- region_scope_tree: ®ion::ScopeTree,
origin: SubregionOrigin<'tcx>,
sub: Region<'tcx>,
sup: Region<'tcx>,
@@ -166,10 +98,9 @@
infer::Subtype(box trace) => {
let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
let mut err = self.report_and_explain_type_error(trace, &terr);
- note_and_explain_region(self.tcx, region_scope_tree, &mut err, "", sup, "...");
+ note_and_explain_region(self.tcx, &mut err, "", sup, "...");
note_and_explain_region(
self.tcx,
- region_scope_tree,
&mut err,
"...does not necessarily outlive ",
sub,
@@ -187,7 +118,6 @@
);
note_and_explain_region(
self.tcx,
- region_scope_tree,
&mut err,
"...the reference is valid for ",
sub,
@@ -195,7 +125,6 @@
);
note_and_explain_region(
self.tcx,
- region_scope_tree,
&mut err,
"...but the borrowed content is only valid for ",
sup,
@@ -215,7 +144,6 @@
);
note_and_explain_region(
self.tcx,
- region_scope_tree,
&mut err,
"...the borrowed pointer is valid for ",
sub,
@@ -223,7 +151,6 @@
);
note_and_explain_region(
self.tcx,
- region_scope_tree,
&mut err,
&format!("...but `{}` is only valid for ", var_name),
sup,
@@ -231,106 +158,6 @@
);
err
}
- infer::InfStackClosure(span) => {
- let mut err =
- struct_span_err!(self.tcx.sess, span, E0314, "closure outlives stack frame");
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "...the closure must be valid for ",
- sub,
- "...",
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "...but the closure's stack frame is only valid \
- for ",
- sup,
- "",
- );
- err
- }
- infer::InvokeClosure(span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0315,
- "cannot invoke closure outside of its lifetime"
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "the closure is only valid for ",
- sup,
- "",
- );
- err
- }
- infer::DerefPointer(span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0473,
- "dereference of reference outside its lifetime"
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "the reference is only valid for ",
- sup,
- "",
- );
- err
- }
- infer::ClosureCapture(span, id) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0474,
- "captured variable `{}` does not outlive the \
- enclosing closure",
- self.tcx.hir().name(id)
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "captured variable is valid for ",
- sup,
- "",
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "closure is valid for ",
- sub,
- "",
- );
- err
- }
- infer::IndexSlice(span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0475,
- "index of slice outside its lifetime"
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "the slice is only valid for ",
- sup,
- "",
- );
- err
- }
infer::RelateObjectBound(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
@@ -339,17 +166,9 @@
"lifetime of the source pointer does not outlive \
lifetime bound of the object type"
);
+ note_and_explain_region(self.tcx, &mut err, "object type is valid for ", sub, "");
note_and_explain_region(
self.tcx,
- region_scope_tree,
- &mut err,
- "object type is valid for ",
- sub,
- "",
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
&mut err,
"source pointer is only valid for ",
sup,
@@ -367,22 +186,10 @@
self.ty_to_string(ty)
);
match *sub {
- ty::ReStatic => note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "type must satisfy ",
- sub,
- "",
- ),
- _ => note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "type must outlive ",
- sub,
- "",
- ),
+ ty::ReStatic => {
+ note_and_explain_region(self.tcx, &mut err, "type must satisfy ", sub, "")
+ }
+ _ => note_and_explain_region(self.tcx, &mut err, "type must outlive ", sub, ""),
}
err
}
@@ -391,7 +198,6 @@
struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
note_and_explain_region(
self.tcx,
- region_scope_tree,
&mut err,
"lifetime parameter instantiated with ",
sup,
@@ -399,7 +205,6 @@
);
note_and_explain_region(
self.tcx,
- region_scope_tree,
&mut err,
"but lifetime parameter must outlive ",
sub,
@@ -407,61 +212,6 @@
);
err
}
- infer::RelateDefaultParamBound(span, ty) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0479,
- "the type `{}` (provided as the value of a type \
- parameter) is not valid at this point",
- self.ty_to_string(ty)
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "type must outlive ",
- sub,
- "",
- );
- err
- }
- infer::CallRcvr(span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0480,
- "lifetime of method receiver does not outlive the \
- method call"
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "the receiver is only valid for ",
- sup,
- "",
- );
- err
- }
- infer::CallArg(span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0481,
- "lifetime of function argument does not outlive \
- the function call"
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "the function argument is only valid for ",
- sup,
- "",
- );
- err
- }
infer::CallReturn(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
@@ -472,7 +222,6 @@
);
note_and_explain_region(
self.tcx,
- region_scope_tree,
&mut err,
"the return value is only valid for ",
sup,
@@ -480,140 +229,6 @@
);
err
}
- infer::Operand(span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0483,
- "lifetime of operand does not outlive the \
- operation"
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "the operand is only valid for ",
- sup,
- "",
- );
- err
- }
- infer::AddrOf(span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0484,
- "reference is not valid at the time of borrow"
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "the borrow is only valid for ",
- sup,
- "",
- );
- err
- }
- infer::AutoBorrow(span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0485,
- "automatically reference is not valid at the time \
- of borrow"
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "the automatic borrow is only valid for ",
- sup,
- "",
- );
- err
- }
- infer::ExprTypeIsNotInScope(t, span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0486,
- "type of expression contains references that are \
- not valid during the expression: `{}`",
- self.ty_to_string(t)
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "type is only valid for ",
- sup,
- "",
- );
- err
- }
- infer::SafeDestructor(span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0487,
- "unsafe use of destructor: destructor might be \
- called while references are dead"
- );
- // FIXME (22171): terms "super/subregion" are suboptimal
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "superregion: ",
- sup,
- "",
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "subregion: ",
- sub,
- "",
- );
- err
- }
- infer::BindingTypeIsNotValidAtDecl(span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0488,
- "lifetime of variable does not enclose its \
- declaration"
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "the variable is only valid for ",
- sup,
- "",
- );
- err
- }
- infer::ParameterInScope(_, span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0489,
- "type/lifetime parameter not in scope here"
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "the parameter is only valid for ",
- sub,
- "",
- );
- err
- }
infer::DataBorrowed(ty, span) => {
let mut err = struct_span_err!(
self.tcx.sess,
@@ -622,22 +237,8 @@
"a value of type `{}` is borrowed for too long",
self.ty_to_string(ty)
);
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "the type is valid for ",
- sub,
- "",
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
- &mut err,
- "but the borrow lasts for ",
- sup,
- "",
- );
+ note_and_explain_region(self.tcx, &mut err, "the type is valid for ", sub, "");
+ note_and_explain_region(self.tcx, &mut err, "but the borrow lasts for ", sup, "");
err
}
infer::ReferenceOutlivesReferent(ty, span) => {
@@ -648,17 +249,9 @@
"in type `{}`, reference has a longer lifetime than the data it references",
self.ty_to_string(ty)
);
+ note_and_explain_region(self.tcx, &mut err, "the pointer is valid for ", sub, "");
note_and_explain_region(
self.tcx,
- region_scope_tree,
- &mut err,
- "the pointer is valid for ",
- sub,
- "",
- );
- note_and_explain_region(
- self.tcx,
- region_scope_tree,
&mut err,
"but the referenced data is only valid for ",
sup,
@@ -683,7 +276,6 @@
pub(super) fn report_placeholder_failure(
&self,
- region_scope_tree: ®ion::ScopeTree,
placeholder_origin: SubregionOrigin<'tcx>,
sub: Region<'tcx>,
sup: Region<'tcx>,
@@ -695,7 +287,7 @@
self.report_and_explain_type_error(trace, &terr)
}
- _ => self.report_concrete_failure(region_scope_tree, placeholder_origin, sub, sup),
+ _ => self.report_concrete_failure(placeholder_origin, sub, sup),
}
}
}
diff --git a/src/librustc_infer/infer/free_regions.rs b/src/librustc_infer/infer/free_regions.rs
index e31c524..d975038 100644
--- a/src/librustc_infer/infer/free_regions.rs
+++ b/src/librustc_infer/infer/free_regions.rs
@@ -5,7 +5,6 @@
use rustc_data_structures::transitive_relation::TransitiveRelation;
use rustc_hir::def_id::DefId;
-use rustc_middle::middle::region;
use rustc_middle::ty::{self, Lift, Region, TyCtxt};
/// Combines a `region::ScopeTree` (which governs relationships between
@@ -21,21 +20,13 @@
/// The context used to fetch the region maps.
pub context: DefId,
- /// The region maps for the given context.
- pub region_scope_tree: &'a region::ScopeTree,
-
/// Free-region relationships.
pub free_regions: &'a FreeRegionMap<'tcx>,
}
impl<'a, 'tcx> RegionRelations<'a, 'tcx> {
- pub fn new(
- tcx: TyCtxt<'tcx>,
- context: DefId,
- region_scope_tree: &'a region::ScopeTree,
- free_regions: &'a FreeRegionMap<'tcx>,
- ) -> Self {
- Self { tcx, context, region_scope_tree, free_regions }
+ pub fn new(tcx: TyCtxt<'tcx>, context: DefId, free_regions: &'a FreeRegionMap<'tcx>) -> Self {
+ Self { tcx, context, free_regions }
}
pub fn lub_free_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> {
diff --git a/src/librustc_infer/infer/freshen.rs b/src/librustc_infer/infer/freshen.rs
index c9ed687..b4cfcb3 100644
--- a/src/librustc_infer/infer/freshen.rs
+++ b/src/librustc_infer/infer/freshen.rs
@@ -127,7 +127,6 @@
ty::ReStatic
| ty::ReEarlyBound(..)
| ty::ReFree(_)
- | ty::ReScope(_)
| ty::ReVar(_)
| ty::RePlaceholder(..)
| ty::ReEmpty(_)
diff --git a/src/librustc_infer/infer/lexical_region_resolve/graphviz.rs b/src/librustc_infer/infer/lexical_region_resolve/graphviz.rs
deleted file mode 100644
index 5d3e8f4..0000000
--- a/src/librustc_infer/infer/lexical_region_resolve/graphviz.rs
+++ /dev/null
@@ -1,253 +0,0 @@
-//! This module provides linkage between libgraphviz traits and
-//! `rustc_trait_selection::infer::region_constraints`, generating a
-//! rendering of the graph represented by the list of `Constraint`
-//! instances (which make up the edges of the graph), as well as the
-//! origin for each constraint (which are attached to the labels on
-//! each edge).
-
-/// For clarity, rename the graphviz crate locally to dot.
-use graphviz as dot;
-
-use super::Constraint;
-use crate::infer::region_constraints::RegionConstraintData;
-use crate::infer::RegionRelations;
-use crate::infer::SubregionOrigin;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir::def_id::DefIndex;
-use rustc_middle::middle::region;
-use rustc_middle::ty;
-
-use std::borrow::Cow;
-use std::collections::btree_map::BTreeMap;
-use std::collections::hash_map::Entry::Vacant;
-use std::env;
-use std::fs;
-use std::io;
-use std::sync::atomic::{AtomicBool, Ordering};
-
-fn print_help_message() {
- println!(
- "\
--Z print-region-graph by default prints a region constraint graph for every \n\
-function body, to the path `constraints.nodeXXX.dot`, where the XXX is \n\
-replaced with the node id of the function under analysis. \n\
- \n\
-To select one particular function body, set `RUST_REGION_GRAPH_NODE=XXX`, \n\
-where XXX is the node id desired. \n\
- \n\
-To generate output to some path other than the default \n\
-`constraints.nodeXXX.dot`, set `RUST_REGION_GRAPH=/path/desired.dot`; \n\
-occurrences of the character `%` in the requested path will be replaced with\n\
-the node id of the function under analysis. \n\
- \n\
-(Since you requested help via RUST_REGION_GRAPH=help, no region constraint \n\
-graphs will be printed. \n\
-"
- );
-}
-
-pub fn maybe_print_constraints_for<'a, 'tcx>(
- region_data: &RegionConstraintData<'tcx>,
- region_rels: &RegionRelations<'a, 'tcx>,
-) {
- let tcx = region_rels.tcx;
- let context = region_rels.context;
-
- if !tcx.sess.opts.debugging_opts.print_region_graph {
- return;
- }
-
- let requested_node = env::var("RUST_REGION_GRAPH_NODE")
- .ok()
- .and_then(|s| s.parse().map(DefIndex::from_u32).ok());
-
- if requested_node.is_some() && requested_node != Some(context.index) {
- return;
- }
-
- let requested_output = env::var("RUST_REGION_GRAPH");
- debug!("requested_output: {:?} requested_node: {:?}", requested_output, requested_node);
-
- let output_path = {
- let output_template = match requested_output {
- Ok(ref s) if s == "help" => {
- static PRINTED_YET: AtomicBool = AtomicBool::new(false);
- if !PRINTED_YET.load(Ordering::SeqCst) {
- print_help_message();
- PRINTED_YET.store(true, Ordering::SeqCst);
- }
- return;
- }
-
- Ok(other_path) => other_path,
- Err(_) => "constraints.node%.dot".to_string(),
- };
-
- if output_template.is_empty() {
- panic!("empty string provided as RUST_REGION_GRAPH");
- }
-
- if output_template.contains('%') {
- let mut new_str = String::new();
- for c in output_template.chars() {
- if c == '%' {
- new_str.push_str(&context.index.as_u32().to_string());
- } else {
- new_str.push(c);
- }
- }
- new_str
- } else {
- output_template
- }
- };
-
- if let Err(e) = dump_region_data_to(region_rels, ®ion_data.constraints, &output_path) {
- let msg = format!("io error dumping region constraints: {}", e);
- tcx.sess.err(&msg)
- }
-}
-
-struct ConstraintGraph<'a, 'tcx> {
- graph_name: String,
- region_rels: &'a RegionRelations<'a, 'tcx>,
- map: &'a BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
- node_ids: FxHashMap<Node, usize>,
-}
-
-#[derive(Clone, Hash, PartialEq, Eq, Debug, Copy)]
-enum Node {
- RegionVid(ty::RegionVid),
- Region(ty::RegionKind),
-}
-
-#[derive(Clone, PartialEq, Eq, Debug, Copy)]
-enum Edge<'tcx> {
- Constraint(Constraint<'tcx>),
- EnclScope(region::Scope, region::Scope),
-}
-
-impl<'a, 'tcx> ConstraintGraph<'a, 'tcx> {
- fn new(
- name: String,
- region_rels: &'a RegionRelations<'a, 'tcx>,
- map: &'a ConstraintMap<'tcx>,
- ) -> ConstraintGraph<'a, 'tcx> {
- let mut i = 0;
- let mut node_ids = FxHashMap::default();
- {
- let mut add_node = |node| {
- if let Vacant(e) = node_ids.entry(node) {
- e.insert(i);
- i += 1;
- }
- };
-
- for (n1, n2) in map.keys().map(|c| constraint_to_nodes(c)) {
- add_node(n1);
- add_node(n2);
- }
-
- region_rels.region_scope_tree.each_encl_scope(|sub, sup| {
- add_node(Node::Region(ty::ReScope(sub)));
- add_node(Node::Region(ty::ReScope(sup)));
- });
- }
-
- ConstraintGraph { map, node_ids, region_rels, graph_name: name }
- }
-}
-
-impl<'a, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'tcx> {
- type Node = Node;
- type Edge = Edge<'tcx>;
- fn graph_id(&self) -> dot::Id<'_> {
- dot::Id::new(&*self.graph_name).unwrap()
- }
- fn node_id(&self, n: &Node) -> dot::Id<'_> {
- let node_id = match self.node_ids.get(n) {
- Some(node_id) => node_id,
- None => bug!("no node_id found for node: {:?}", n),
- };
- let name = || format!("node_{}", node_id);
-
- dot::Id::new(name())
- .unwrap_or_else(|_| bug!("failed to create graphviz node identified by {}", name()))
- }
- fn node_label(&self, n: &Node) -> dot::LabelText<'_> {
- match *n {
- Node::RegionVid(n_vid) => dot::LabelText::label(format!("{:?}", n_vid)),
- Node::Region(n_rgn) => dot::LabelText::label(format!("{:?}", n_rgn)),
- }
- }
- fn edge_label(&self, e: &Edge<'_>) -> dot::LabelText<'_> {
- match *e {
- Edge::Constraint(ref c) => {
- dot::LabelText::label(format!("{:?}", self.map.get(c).unwrap()))
- }
- Edge::EnclScope(..) => dot::LabelText::label("(enclosed)".to_owned()),
- }
- }
-}
-
-fn constraint_to_nodes(c: &Constraint<'_>) -> (Node, Node) {
- match *c {
- Constraint::VarSubVar(rv_1, rv_2) => (Node::RegionVid(rv_1), Node::RegionVid(rv_2)),
- Constraint::RegSubVar(r_1, rv_2) => (Node::Region(*r_1), Node::RegionVid(rv_2)),
- Constraint::VarSubReg(rv_1, r_2) => (Node::RegionVid(rv_1), Node::Region(*r_2)),
- Constraint::RegSubReg(r_1, r_2) => (Node::Region(*r_1), Node::Region(*r_2)),
- }
-}
-
-fn edge_to_nodes(e: &Edge<'_>) -> (Node, Node) {
- match *e {
- Edge::Constraint(ref c) => constraint_to_nodes(c),
- Edge::EnclScope(sub, sup) => {
- (Node::Region(ty::ReScope(sub)), Node::Region(ty::ReScope(sup)))
- }
- }
-}
-
-impl<'a, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'tcx> {
- type Node = Node;
- type Edge = Edge<'tcx>;
- fn nodes(&self) -> dot::Nodes<'_, Node> {
- let set = self.node_ids.keys().cloned().collect::<FxHashSet<_>>();
- debug!("constraint graph has {} nodes", set.len());
- set.into_iter().collect()
- }
- fn edges(&self) -> dot::Edges<'_, Edge<'tcx>> {
- debug!("constraint graph has {} edges", self.map.len());
- let mut v: Vec<_> = self.map.keys().map(|e| Edge::Constraint(*e)).collect();
- self.region_rels
- .region_scope_tree
- .each_encl_scope(|sub, sup| v.push(Edge::EnclScope(sub, sup)));
- debug!("region graph has {} edges", v.len());
- Cow::Owned(v)
- }
- fn source(&self, edge: &Edge<'tcx>) -> Node {
- let (n1, _) = edge_to_nodes(edge);
- debug!("edge {:?} has source {:?}", edge, n1);
- n1
- }
- fn target(&self, edge: &Edge<'tcx>) -> Node {
- let (_, n2) = edge_to_nodes(edge);
- debug!("edge {:?} has target {:?}", edge, n2);
- n2
- }
-}
-
-pub type ConstraintMap<'tcx> = BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>;
-
-fn dump_region_data_to<'a, 'tcx>(
- region_rels: &RegionRelations<'a, 'tcx>,
- map: &ConstraintMap<'tcx>,
- path: &str,
-) -> io::Result<()> {
- debug!("dump_region_data map (len: {}) path: {}", map.len(), path);
- let g = ConstraintGraph::new("region_data".to_string(), region_rels, map);
- debug!("dump_region_data calling render");
- let mut v = Vec::new();
- dot::render(&g, &mut v).unwrap();
- fs::write(path, &v)
-}
diff --git a/src/librustc_infer/infer/lexical_region_resolve/mod.rs b/src/librustc_infer/infer/lexical_region_resolve/mod.rs
index 33a80fb..fcf1949 100644
--- a/src/librustc_infer/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc_infer/infer/lexical_region_resolve/mod.rs
@@ -18,13 +18,11 @@
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
-use rustc_middle::ty::{ReLateBound, RePlaceholder, ReScope, ReVar};
+use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar};
use rustc_middle::ty::{Region, RegionVid};
use rustc_span::Span;
use std::fmt;
-mod graphviz;
-
/// This function performs lexical region resolution given a complete
/// set of constraints and variable origins. It performs a fixed-point
/// iteration to find region values which satisfy all constraints,
@@ -49,7 +47,10 @@
let mut values = resolver.infer_variable_values(&mut errors);
let re_erased = region_rels.tcx.lifetimes.re_erased;
- values.values.iter_mut().for_each(|v| *v = VarValue::Value(re_erased));
+ values.values.iter_mut().for_each(|v| match *v {
+ VarValue::Value(ref mut r) => *r = re_erased,
+ VarValue::ErrorValue => {}
+ });
(values, errors)
}
RegionckMode::Erase { suppress_errors: true } => {
@@ -146,7 +147,6 @@
self.region_rels.context,
self.dump_constraints(self.region_rels)
);
- graphviz::maybe_print_constraints_for(&self.data, self.region_rels);
let graph = self.construct_graph();
self.expand_givens(&graph);
@@ -290,8 +290,8 @@
// Find all the "upper bounds" -- that is, each region `b` such that
// `r0 <= b` must hold.
- let (member_upper_bounds, _) =
- self.collect_concrete_regions(graph, member_vid, OUTGOING, None);
+ let (member_upper_bounds, ..) =
+ self.collect_bounding_regions(graph, member_vid, OUTGOING, None);
// Get an iterator over the *available choice* -- that is,
// each choice region `c` where `lb <= c` and `c <= ub` for all the
@@ -423,15 +423,6 @@
match *b_data {
VarValue::Value(cur_region) => {
- // Identical scopes can show up quite often, if the fixed point
- // iteration converges slowly. Skip them. This is purely an
- // optimization.
- if let (ReScope(a_scope), ReScope(cur_scope)) = (a_region, cur_region) {
- if a_scope == cur_scope {
- return false;
- }
- }
-
// This is a specialized version of the `lub_concrete_regions`
// check below for a common case, here purely as an
// optimization.
@@ -525,8 +516,8 @@
self.tcx().lifetimes.re_static
}
- (&ReEmpty(_), r @ (ReEarlyBound(_) | ReFree(_) | ReScope(_)))
- | (r @ (ReEarlyBound(_) | ReFree(_) | ReScope(_)), &ReEmpty(_)) => {
+ (&ReEmpty(_), r @ (ReEarlyBound(_) | ReFree(_)))
+ | (r @ (ReEarlyBound(_) | ReFree(_)), &ReEmpty(_)) => {
// All empty regions are less than early-bound, free,
// and scope regions.
r
@@ -551,46 +542,6 @@
}
}
- (&ReEarlyBound(_) | &ReFree(_), &ReScope(s_id))
- | (&ReScope(s_id), &ReEarlyBound(_) | &ReFree(_)) => {
- // A "free" region can be interpreted as "some region
- // at least as big as fr.scope". So, we can
- // reasonably compare free regions and scopes:
- let fr_scope = match (a, b) {
- (&ReEarlyBound(ref br), _) | (_, &ReEarlyBound(ref br)) => {
- self.region_rels.region_scope_tree.early_free_scope(self.tcx(), br)
- }
- (&ReFree(ref fr), _) | (_, &ReFree(ref fr)) => {
- self.region_rels.region_scope_tree.free_scope(self.tcx(), fr)
- }
- _ => bug!(),
- };
- let r_id =
- self.region_rels.region_scope_tree.nearest_common_ancestor(fr_scope, s_id);
- if r_id == fr_scope {
- // if the free region's scope `fr.scope` is bigger than
- // the scope region `s_id`, then the LUB is the free
- // region itself:
- match (a, b) {
- (_, &ReScope(_)) => return a,
- (&ReScope(_), _) => return b,
- _ => bug!(),
- }
- }
-
- // otherwise, we don't know what the free region is,
- // so we must conservatively say the LUB is static:
- self.tcx().lifetimes.re_static
- }
-
- (&ReScope(a_id), &ReScope(b_id)) => {
- // The region corresponding to an outer block is a
- // subtype of the region corresponding to an inner
- // block.
- let lub = self.region_rels.region_scope_tree.nearest_common_ancestor(a_id, b_id);
- self.tcx().mk_region(ReScope(lub))
- }
-
(&ReEarlyBound(_) | &ReFree(_), &ReEarlyBound(_) | &ReFree(_)) => {
self.region_rels.lub_free_regions(a, b)
}
@@ -659,7 +610,7 @@
if !self.sub_concrete_regions(a_region, b_region) {
debug!(
"collect_errors: region error at {:?}: \
- cannot verify that {:?}={:?} <= {:?}",
+ cannot verify that {:?}={:?} <= {:?}",
origin, a_vid, a_region, b_region
);
*a_data = VarValue::ErrorValue;
@@ -716,7 +667,7 @@
graph: &RegionGraph<'tcx>,
errors: &mut Vec<RegionResolutionError<'tcx>>,
) {
- debug!("collect_var_errors");
+ debug!("collect_var_errors, var_data = {:#?}", var_data.values);
// This is the best way that I have found to suppress
// duplicate and related errors. Basically we keep a set of
@@ -815,10 +766,10 @@
) {
// Errors in expanding nodes result from a lower-bound that is
// not contained by an upper-bound.
- let (mut lower_bounds, lower_dup) =
- self.collect_concrete_regions(graph, node_idx, INCOMING, Some(dup_vec));
- let (mut upper_bounds, upper_dup) =
- self.collect_concrete_regions(graph, node_idx, OUTGOING, Some(dup_vec));
+ let (mut lower_bounds, lower_vid_bounds, lower_dup) =
+ self.collect_bounding_regions(graph, node_idx, INCOMING, Some(dup_vec));
+ let (mut upper_bounds, _, upper_dup) =
+ self.collect_bounding_regions(graph, node_idx, OUTGOING, Some(dup_vec));
if lower_dup || upper_dup {
return;
@@ -874,15 +825,22 @@
// If we have a scenario like `exists<'a> { forall<'b> { 'b:
// 'a } }`, we wind up without any lower-bound -- all we have
// are placeholders as upper bounds, but the universe of the
- // variable `'a` doesn't permit those placeholders.
+ // variable `'a`, or some variable that `'a` has to outlive, doesn't
+ // permit those placeholders.
+ let min_universe = lower_vid_bounds
+ .into_iter()
+ .map(|vid| self.var_infos[vid].universe)
+ .min()
+ .expect("lower_vid_bounds should at least include `node_idx`");
+
for upper_bound in &upper_bounds {
if let ty::RePlaceholder(p) = upper_bound.region {
- if node_universe.cannot_name(p.universe) {
+ if min_universe.cannot_name(p.universe) {
let origin = self.var_infos[node_idx].origin;
errors.push(RegionResolutionError::UpperBoundUniverseConflict(
node_idx,
origin,
- node_universe,
+ min_universe,
upper_bound.origin.clone(),
upper_bound.region,
));
@@ -904,13 +862,24 @@
);
}
- fn collect_concrete_regions(
+ /// Collects all regions that "bound" the variable `orig_node_idx` in the
+ /// given direction.
+ ///
+ /// If `dup_vec` is `Some` it's used to track duplicates between successive
+ /// calls of this function.
+ ///
+ /// The return tuple fields are:
+ /// - a list of all concrete regions bounding the given region.
+ /// - the set of all region variables bounding the given region.
+ /// - a `bool` that's true if the returned region variables overlap with
+ /// those returned by a previous call for another region.
+ fn collect_bounding_regions(
&self,
graph: &RegionGraph<'tcx>,
orig_node_idx: RegionVid,
dir: Direction,
mut dup_vec: Option<&mut IndexVec<RegionVid, Option<RegionVid>>>,
- ) -> (Vec<RegionAndOrigin<'tcx>>, bool) {
+ ) -> (Vec<RegionAndOrigin<'tcx>>, FxHashSet<RegionVid>, bool) {
struct WalkState<'tcx> {
set: FxHashSet<RegionVid>,
stack: Vec<RegionVid>,
@@ -929,9 +898,7 @@
// direction specified
process_edges(&self.data, &mut state, graph, orig_node_idx, dir);
- while !state.stack.is_empty() {
- let node_idx = state.stack.pop().unwrap();
-
+ while let Some(node_idx) = state.stack.pop() {
// check whether we've visited this node on some previous walk
if let Some(dup_vec) = &mut dup_vec {
if dup_vec[node_idx].is_none() {
@@ -949,8 +916,8 @@
process_edges(&self.data, &mut state, graph, node_idx, dir);
}
- let WalkState { result, dup_found, .. } = state;
- return (result, dup_found);
+ let WalkState { result, dup_found, set, .. } = state;
+ return (result, set, dup_found);
fn process_edges<'tcx>(
this: &RegionConstraintData<'tcx>,
diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs
index 9c81a11..30af7d0 100644
--- a/src/librustc_infer/infer/mod.rs
+++ b/src/librustc_infer/infer/mod.rs
@@ -20,7 +20,6 @@
use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
-use rustc_middle::middle::region;
use rustc_middle::mir;
use rustc_middle::mir::interpret::ConstEvalResult;
use rustc_middle::traits::select;
@@ -378,22 +377,6 @@
/// Arose from a subtyping relation
Subtype(Box<TypeTrace<'tcx>>),
- /// Stack-allocated closures cannot outlive innermost loop
- /// or function so as to ensure we only require finite stack
- InfStackClosure(Span),
-
- /// Invocation of closure must be within its lifetime
- InvokeClosure(Span),
-
- /// Dereference of reference must be within its lifetime
- DerefPointer(Span),
-
- /// Closure bound must not outlive captured variables
- ClosureCapture(Span, hir::HirId),
-
- /// Index into slice must be within its lifetime
- IndexSlice(Span),
-
/// When casting `&'a T` to an `&'b Trait` object,
/// relating `'a` to `'b`
RelateObjectBound(Span),
@@ -406,10 +389,6 @@
/// that must outlive some other region.
RelateRegionParamBound(Span),
- /// A bound placed on type parameters that states that must outlive
- /// the moment of their instantiation.
- RelateDefaultParamBound(Span, Ty<'tcx>),
-
/// Creating a pointer `b` to contents of another reference
Reborrow(Span),
@@ -422,36 +401,9 @@
/// (&'a &'b T) where a >= b
ReferenceOutlivesReferent(Ty<'tcx>, Span),
- /// Type or region parameters must be in scope.
- ParameterInScope(ParameterOrigin, Span),
-
- /// The type T of an expression E must outlive the lifetime for E.
- ExprTypeIsNotInScope(Ty<'tcx>, Span),
-
- /// A `ref b` whose region does not enclose the decl site
- BindingTypeIsNotValidAtDecl(Span),
-
- /// Regions appearing in a method receiver must outlive method call
- CallRcvr(Span),
-
- /// Regions appearing in a function argument must outlive func call
- CallArg(Span),
-
/// Region in return type of invoked fn must enclose call
CallReturn(Span),
- /// Operands must be in scope
- Operand(Span),
-
- /// Region resulting from a `&` expr must enclose the `&` expr
- AddrOf(Span),
-
- /// An auto-borrow that does not enclose the expr where it occurs
- AutoBorrow(Span),
-
- /// Region constraint arriving from destructor safety
- SafeDestructor(Span),
-
/// Comparing the signature and requirements of an impl method against
/// the containing trait.
CompareImplMethodObligation {
@@ -1260,7 +1212,6 @@
pub fn resolve_regions_and_report_errors(
&self,
region_context: DefId,
- region_map: ®ion::ScopeTree,
outlives_env: &OutlivesEnvironment<'tcx>,
mode: RegionckMode,
) {
@@ -1280,12 +1231,8 @@
.into_infos_and_data()
};
- let region_rels = &RegionRelations::new(
- self.tcx,
- region_context,
- region_map,
- outlives_env.free_region_map(),
- );
+ let region_rels =
+ &RegionRelations::new(self.tcx, region_context, outlives_env.free_region_map());
let (lexical_region_resolutions, errors) =
lexical_region_resolve::resolve(region_rels, var_infos, data, mode);
@@ -1299,7 +1246,7 @@
// this infcx was in use. This is totally hokey but
// otherwise we have a hard time separating legit region
// errors from silly ones.
- self.report_region_errors(region_map, &errors);
+ self.report_region_errors(&errors);
}
}
@@ -1809,29 +1756,14 @@
pub fn span(&self) -> Span {
match *self {
Subtype(ref a) => a.span(),
- InfStackClosure(a) => a,
- InvokeClosure(a) => a,
- DerefPointer(a) => a,
- ClosureCapture(a, _) => a,
- IndexSlice(a) => a,
RelateObjectBound(a) => a,
RelateParamBound(a, _) => a,
RelateRegionParamBound(a) => a,
- RelateDefaultParamBound(a, _) => a,
Reborrow(a) => a,
ReborrowUpvar(a, _) => a,
DataBorrowed(_, a) => a,
ReferenceOutlivesReferent(_, a) => a,
- ParameterInScope(_, a) => a,
- ExprTypeIsNotInScope(_, a) => a,
- BindingTypeIsNotValidAtDecl(a) => a,
- CallRcvr(a) => a,
- CallArg(a) => a,
CallReturn(a) => a,
- Operand(a) => a,
- AddrOf(a) => a,
- AutoBorrow(a) => a,
- SafeDestructor(a) => a,
CompareImplMethodObligation { span, .. } => span,
}
}
diff --git a/src/librustc_infer/infer/outlives/mod.rs b/src/librustc_infer/infer/outlives/mod.rs
index 289457e..fd3b38e 100644
--- a/src/librustc_infer/infer/outlives/mod.rs
+++ b/src/librustc_infer/infer/outlives/mod.rs
@@ -11,17 +11,17 @@
param_env: ty::ParamEnv<'tcx>,
) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx {
debug!("explicit_outlives_bounds()");
- param_env.caller_bounds.into_iter().filter_map(move |predicate| match predicate {
- ty::Predicate::Projection(..)
- | ty::Predicate::Trait(..)
- | ty::Predicate::Subtype(..)
- | ty::Predicate::WellFormed(..)
- | ty::Predicate::ObjectSafe(..)
- | ty::Predicate::ClosureKind(..)
- | ty::Predicate::TypeOutlives(..)
- | ty::Predicate::ConstEvaluatable(..)
- | ty::Predicate::ConstEquate(..) => None,
- ty::Predicate::RegionOutlives(ref data) => data
+ param_env.caller_bounds.into_iter().filter_map(move |predicate| match predicate.kind() {
+ ty::PredicateKind::Projection(..)
+ | ty::PredicateKind::Trait(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::TypeOutlives(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => None,
+ ty::PredicateKind::RegionOutlives(ref data) => data
.no_bound_vars()
.map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a)),
})
diff --git a/src/librustc_infer/infer/region_constraints/mod.rs b/src/librustc_infer/infer/region_constraints/mod.rs
index 0c9f002..f45b224 100644
--- a/src/librustc_infer/infer/region_constraints/mod.rs
+++ b/src/librustc_infer/infer/region_constraints/mod.rs
@@ -758,11 +758,9 @@
pub fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex {
match *region {
- ty::ReScope(..)
- | ty::ReStatic
- | ty::ReErased
- | ty::ReFree(..)
- | ty::ReEarlyBound(..) => ty::UniverseIndex::ROOT,
+ ty::ReStatic | ty::ReErased | ty::ReFree(..) | ty::ReEarlyBound(..) => {
+ ty::UniverseIndex::ROOT
+ }
ty::ReEmpty(ui) => ui,
ty::RePlaceholder(placeholder) => placeholder.universe,
ty::ReVar(vid) => self.var_universe(vid),
@@ -784,7 +782,7 @@
)
}
- /// See [`RegionInference::region_constraints_added_in_snapshot`].
+ /// See `InferCtxt::region_constraints_added_in_snapshot`.
pub fn region_constraints_added_in_snapshot(&self, mark: &Snapshot<'tcx>) -> Option<bool> {
self.undo_log
.region_constraints_in_snapshot(mark)
diff --git a/src/librustc_infer/infer/sub.rs b/src/librustc_infer/infer/sub.rs
index 1ec67ef..b51af19 100644
--- a/src/librustc_infer/infer/sub.rs
+++ b/src/librustc_infer/infer/sub.rs
@@ -6,7 +6,7 @@
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::TyVar;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
use std::mem;
/// Ensures `a` is made a subtype of `b`. Returns `a` on success.
@@ -100,11 +100,12 @@
self.fields.obligations.push(Obligation::new(
self.fields.trace.cause.clone(),
self.fields.param_env,
- ty::Predicate::Subtype(ty::Binder::dummy(ty::SubtypePredicate {
+ ty::PredicateKind::Subtype(ty::Binder::dummy(ty::SubtypePredicate {
a_is_expected: self.a_is_expected,
a,
b,
- })),
+ }))
+ .to_predicate(self.tcx()),
));
Ok(a)
diff --git a/src/librustc_infer/traits/engine.rs b/src/librustc_infer/traits/engine.rs
index a95257b..2710deb 100644
--- a/src/librustc_infer/traits/engine.rs
+++ b/src/librustc_infer/traits/engine.rs
@@ -33,7 +33,7 @@
cause,
recursion_depth: 0,
param_env,
- predicate: trait_ref.without_const().to_predicate(),
+ predicate: trait_ref.without_const().to_predicate(infcx.tcx),
},
);
}
diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs
index 8d95904..892a628 100644
--- a/src/librustc_infer/traits/mod.rs
+++ b/src/librustc_infer/traits/mod.rs
@@ -59,7 +59,7 @@
// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
-static_assert_size!(PredicateObligation<'_>, 112);
+static_assert_size!(PredicateObligation<'_>, 88);
pub type Obligations<'tcx, O> = Vec<Obligation<'tcx, O>>;
pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>;
diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs
index ee903b6..88fc146 100644
--- a/src/librustc_infer/traits/util.rs
+++ b/src/librustc_infer/traits/util.rs
@@ -10,40 +10,49 @@
tcx: TyCtxt<'tcx>,
pred: &ty::Predicate<'tcx>,
) -> ty::Predicate<'tcx> {
- match *pred {
- ty::Predicate::Trait(ref data, constness) => {
- ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data), constness)
+ match pred.kind() {
+ &ty::PredicateKind::Trait(ref data, constness) => {
+ ty::PredicateKind::Trait(tcx.anonymize_late_bound_regions(data), constness)
+ .to_predicate(tcx)
}
- ty::Predicate::RegionOutlives(ref data) => {
- ty::Predicate::RegionOutlives(tcx.anonymize_late_bound_regions(data))
+ ty::PredicateKind::RegionOutlives(data) => {
+ ty::PredicateKind::RegionOutlives(tcx.anonymize_late_bound_regions(data))
+ .to_predicate(tcx)
}
- ty::Predicate::TypeOutlives(ref data) => {
- ty::Predicate::TypeOutlives(tcx.anonymize_late_bound_regions(data))
+ ty::PredicateKind::TypeOutlives(data) => {
+ ty::PredicateKind::TypeOutlives(tcx.anonymize_late_bound_regions(data))
+ .to_predicate(tcx)
}
- ty::Predicate::Projection(ref data) => {
- ty::Predicate::Projection(tcx.anonymize_late_bound_regions(data))
+ ty::PredicateKind::Projection(data) => {
+ ty::PredicateKind::Projection(tcx.anonymize_late_bound_regions(data)).to_predicate(tcx)
}
- ty::Predicate::WellFormed(data) => ty::Predicate::WellFormed(data),
-
- ty::Predicate::ObjectSafe(data) => ty::Predicate::ObjectSafe(data),
-
- ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
- ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind)
+ &ty::PredicateKind::WellFormed(data) => {
+ ty::PredicateKind::WellFormed(data).to_predicate(tcx)
}
- ty::Predicate::Subtype(ref data) => {
- ty::Predicate::Subtype(tcx.anonymize_late_bound_regions(data))
+ &ty::PredicateKind::ObjectSafe(data) => {
+ ty::PredicateKind::ObjectSafe(data).to_predicate(tcx)
}
- ty::Predicate::ConstEvaluatable(def_id, substs) => {
- ty::Predicate::ConstEvaluatable(def_id, substs)
+ &ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
+ ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind).to_predicate(tcx)
}
- ty::Predicate::ConstEquate(c1, c2) => ty::Predicate::ConstEquate(c1, c2),
+ ty::PredicateKind::Subtype(data) => {
+ ty::PredicateKind::Subtype(tcx.anonymize_late_bound_regions(data)).to_predicate(tcx)
+ }
+
+ &ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
+ ty::PredicateKind::ConstEvaluatable(def_id, substs).to_predicate(tcx)
+ }
+
+ ty::PredicateKind::ConstEquate(c1, c2) => {
+ ty::PredicateKind::ConstEquate(c1, c2).to_predicate(tcx)
+ }
}
}
@@ -99,14 +108,14 @@
tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
) -> Elaborator<'tcx> {
- elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate()))
+ elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx)))
}
pub fn elaborate_trait_refs<'tcx>(
tcx: TyCtxt<'tcx>,
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
) -> Elaborator<'tcx> {
- let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate());
+ let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate(tcx));
elaborate_predicates(tcx, predicates)
}
@@ -145,8 +154,8 @@
fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
let tcx = self.visited.tcx;
- match obligation.predicate {
- ty::Predicate::Trait(ref data, _) => {
+ match obligation.predicate.kind() {
+ ty::PredicateKind::Trait(ref data, _) => {
// Get predicates declared on the trait.
let predicates = tcx.super_predicates_of(data.def_id());
@@ -167,36 +176,36 @@
self.stack.extend(obligations);
}
- ty::Predicate::WellFormed(..) => {
+ ty::PredicateKind::WellFormed(..) => {
// Currently, we do not elaborate WF predicates,
// although we easily could.
}
- ty::Predicate::ObjectSafe(..) => {
+ ty::PredicateKind::ObjectSafe(..) => {
// Currently, we do not elaborate object-safe
// predicates.
}
- ty::Predicate::Subtype(..) => {
+ ty::PredicateKind::Subtype(..) => {
// Currently, we do not "elaborate" predicates like `X <: Y`,
// though conceivably we might.
}
- ty::Predicate::Projection(..) => {
+ ty::PredicateKind::Projection(..) => {
// Nothing to elaborate in a projection predicate.
}
- ty::Predicate::ClosureKind(..) => {
+ ty::PredicateKind::ClosureKind(..) => {
// Nothing to elaborate when waiting for a closure's kind to be inferred.
}
- ty::Predicate::ConstEvaluatable(..) => {
+ ty::PredicateKind::ConstEvaluatable(..) => {
// Currently, we do not elaborate const-evaluatable
// predicates.
}
- ty::Predicate::ConstEquate(..) => {
+ ty::PredicateKind::ConstEquate(..) => {
// Currently, we do not elaborate const-equate
// predicates.
}
- ty::Predicate::RegionOutlives(..) => {
+ ty::PredicateKind::RegionOutlives(..) => {
// Nothing to elaborate from `'a: 'b`.
}
- ty::Predicate::TypeOutlives(ref data) => {
+ ty::PredicateKind::TypeOutlives(ref data) => {
// We know that `T: 'a` for some type `T`. We can
// often elaborate this. For example, if we know that
// `[U]: 'a`, that implies that `U: 'a`. Similarly, if
@@ -228,7 +237,7 @@
if r.is_late_bound() {
None
} else {
- Some(ty::Predicate::RegionOutlives(ty::Binder::dummy(
+ Some(ty::PredicateKind::RegionOutlives(ty::Binder::dummy(
ty::OutlivesPredicate(r, r_min),
)))
}
@@ -236,7 +245,7 @@
Component::Param(p) => {
let ty = tcx.mk_ty_param(p.index, p.name);
- Some(ty::Predicate::TypeOutlives(ty::Binder::dummy(
+ Some(ty::PredicateKind::TypeOutlives(ty::Binder::dummy(
ty::OutlivesPredicate(ty, r_min),
)))
}
@@ -250,8 +259,9 @@
None
}
})
- .filter(|p| visited.insert(p))
- .map(|p| predicate_obligation(p, None)),
+ .map(|predicate_kind| predicate_kind.to_predicate(tcx))
+ .filter(|predicate| visited.insert(predicate))
+ .map(|predicate| predicate_obligation(predicate, None)),
);
}
}
@@ -317,7 +327,7 @@
fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
while let Some(obligation) = self.base_iterator.next() {
- if let ty::Predicate::Trait(data, _) = obligation.predicate {
+ if let ty::PredicateKind::Trait(data, _) = obligation.predicate.kind() {
return Some(data.to_poly_trait_ref());
}
}
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 801c8e9..214701d 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -7,7 +7,7 @@
use rustc_ast::{self, ast, visit};
use rustc_codegen_ssa::back::link::emit_metadata;
use rustc_codegen_ssa::traits::CodegenBackend;
-use rustc_data_structures::sync::{par_iter, Lrc, Once, ParallelIterator, WorkerLocal};
+use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal};
use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
use rustc_errors::{ErrorReported, PResult};
use rustc_expand::base::ExtCtxt;
@@ -169,10 +169,10 @@
sess.init_features(features);
let crate_types = util::collect_crate_types(sess, &krate.attrs);
- sess.crate_types.set(crate_types);
+ sess.init_crate_types(crate_types);
let disambiguator = util::compute_crate_disambiguator(sess);
- sess.crate_disambiguator.set(disambiguator);
+ sess.crate_disambiguator.set(disambiguator).expect("not yet initialized");
rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator);
if sess.opts.incremental.is_some() {
@@ -244,7 +244,7 @@
alt_std_name,
);
if let Some(name) = name {
- sess.parse_sess.injected_crate_name.set(name);
+ sess.parse_sess.injected_crate_name.set(name).expect("not yet initialized");
}
krate
});
@@ -288,7 +288,7 @@
let features = sess.features_untracked();
let cfg = rustc_expand::expand::ExpansionConfig {
features: Some(&features),
- recursion_limit: *sess.recursion_limit.get(),
+ recursion_limit: sess.recursion_limit(),
trace_mac: sess.opts.debugging_opts.trace_macros,
should_test: sess.opts.test,
..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string())
@@ -358,7 +358,7 @@
rustc_ast_passes::ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer())
});
- let crate_types = sess.crate_types.borrow();
+ let crate_types = sess.crate_types();
let is_proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
// For backwards compatibility, we don't try to run proc macro injection
@@ -488,7 +488,7 @@
// If the filename has been overridden using `-o`, it will not be modified
// by appending `.rlib`, `.exe`, etc., so we can skip this transformation.
OutputType::Exe if !exact_name => {
- for crate_type in sess.crate_types.borrow().iter() {
+ for crate_type in sess.crate_types().iter() {
let p = filename_for_input(sess, *crate_type, crate_name, outputs);
out_filenames.push(p);
}
@@ -721,7 +721,7 @@
mut resolver_outputs: ResolverOutputs,
outputs: OutputFilenames,
crate_name: &str,
- global_ctxt: &'tcx Once<GlobalCtxt<'tcx>>,
+ global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
) -> QueryContext<'tcx> {
let sess = &compiler.session();
@@ -743,7 +743,7 @@
}
let gcx = sess.time("setup_global_ctxt", || {
- global_ctxt.init_locking(|| {
+ global_ctxt.get_or_init(|| {
TyCtxt::create_global_ctxt(
sess,
lint_store,
@@ -905,8 +905,7 @@
let metadata_kind = tcx
.sess
- .crate_types
- .borrow()
+ .crate_types()
.iter()
.map(|ty| match *ty {
CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => MetadataKind::None,
diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs
index 94cd4bc..283be16 100644
--- a/src/librustc_interface/queries.rs
+++ b/src/librustc_interface/queries.rs
@@ -3,7 +3,7 @@
use rustc_ast::{self, ast};
use rustc_codegen_ssa::traits::CodegenBackend;
-use rustc_data_structures::sync::{Lrc, Once, WorkerLocal};
+use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
use rustc_errors::ErrorReported;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_hir::Crate;
@@ -65,7 +65,7 @@
pub struct Queries<'tcx> {
compiler: &'tcx Compiler,
- gcx: Once<GlobalCtxt<'tcx>>,
+ gcx: OnceCell<GlobalCtxt<'tcx>>,
arena: WorkerLocal<Arena<'tcx>>,
hir_arena: WorkerLocal<rustc_ast_lowering::Arena<'tcx>>,
@@ -86,7 +86,7 @@
pub fn new(compiler: &'tcx Compiler) -> Queries<'tcx> {
Queries {
compiler,
- gcx: Once::new(),
+ gcx: OnceCell::new(),
arena: WorkerLocal::new(|_| Arena::default()),
hir_arena: WorkerLocal::new(|_| rustc_ast_lowering::Arena::default()),
dep_graph_future: Default::default(),
diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs
index 5e17660..0394821 100644
--- a/src/librustc_interface/tests.rs
+++ b/src/librustc_interface/tests.rs
@@ -2,7 +2,6 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
-use rustc_middle::middle::cstore;
use rustc_session::config::Strip;
use rustc_session::config::{build_configuration, build_session_options, to_crate_config};
use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
@@ -11,6 +10,7 @@
use rustc_session::getopts;
use rustc_session::lint::Level;
use rustc_session::search_paths::SearchPath;
+use rustc_session::utils::NativeLibKind;
use rustc_session::{build_session, Session};
use rustc_span::edition::{Edition, DEFAULT_EDITION};
use rustc_span::symbol::sym;
@@ -300,30 +300,30 @@
// Reference
v1.libs = vec![
- (String::from("a"), None, Some(cstore::NativeStatic)),
- (String::from("b"), None, Some(cstore::NativeFramework)),
- (String::from("c"), None, Some(cstore::NativeUnknown)),
+ (String::from("a"), None, NativeLibKind::StaticBundle),
+ (String::from("b"), None, NativeLibKind::Framework),
+ (String::from("c"), None, NativeLibKind::Unspecified),
];
// Change label
v2.libs = vec![
- (String::from("a"), None, Some(cstore::NativeStatic)),
- (String::from("X"), None, Some(cstore::NativeFramework)),
- (String::from("c"), None, Some(cstore::NativeUnknown)),
+ (String::from("a"), None, NativeLibKind::StaticBundle),
+ (String::from("X"), None, NativeLibKind::Framework),
+ (String::from("c"), None, NativeLibKind::Unspecified),
];
// Change kind
v3.libs = vec![
- (String::from("a"), None, Some(cstore::NativeStatic)),
- (String::from("b"), None, Some(cstore::NativeStatic)),
- (String::from("c"), None, Some(cstore::NativeUnknown)),
+ (String::from("a"), None, NativeLibKind::StaticBundle),
+ (String::from("b"), None, NativeLibKind::StaticBundle),
+ (String::from("c"), None, NativeLibKind::Unspecified),
];
// Change new-name
v4.libs = vec![
- (String::from("a"), None, Some(cstore::NativeStatic)),
- (String::from("b"), Some(String::from("X")), Some(cstore::NativeFramework)),
- (String::from("c"), None, Some(cstore::NativeUnknown)),
+ (String::from("a"), None, NativeLibKind::StaticBundle),
+ (String::from("b"), Some(String::from("X")), NativeLibKind::Framework),
+ (String::from("c"), None, NativeLibKind::Unspecified),
];
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
@@ -345,21 +345,21 @@
// Reference
v1.libs = vec![
- (String::from("a"), None, Some(cstore::NativeStatic)),
- (String::from("b"), None, Some(cstore::NativeFramework)),
- (String::from("c"), None, Some(cstore::NativeUnknown)),
+ (String::from("a"), None, NativeLibKind::StaticBundle),
+ (String::from("b"), None, NativeLibKind::Framework),
+ (String::from("c"), None, NativeLibKind::Unspecified),
];
v2.libs = vec![
- (String::from("b"), None, Some(cstore::NativeFramework)),
- (String::from("a"), None, Some(cstore::NativeStatic)),
- (String::from("c"), None, Some(cstore::NativeUnknown)),
+ (String::from("b"), None, NativeLibKind::Framework),
+ (String::from("a"), None, NativeLibKind::StaticBundle),
+ (String::from("c"), None, NativeLibKind::Unspecified),
];
v3.libs = vec![
- (String::from("c"), None, Some(cstore::NativeUnknown)),
- (String::from("a"), None, Some(cstore::NativeStatic)),
- (String::from("b"), None, Some(cstore::NativeFramework)),
+ (String::from("c"), None, NativeLibKind::Unspecified),
+ (String::from("a"), None, NativeLibKind::StaticBundle),
+ (String::from("b"), None, NativeLibKind::Framework),
];
assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index 5a76802..a15da94 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -406,7 +406,7 @@
// Also incorporate crate type, so that we don't get symbol conflicts when
// linking against a library of the same name, if this is an executable.
- let is_exe = session.crate_types.borrow().contains(&CrateType::Executable);
+ let is_exe = session.crate_types().contains(&CrateType::Executable);
hasher.write(if is_exe { b"exe" } else { b"lib" });
CrateDisambiguator::from(hasher.finish::<Fingerprint>())
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index bca91fb..e17e8b7 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1202,13 +1202,13 @@
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'tcx>) {
use rustc_middle::ty::fold::TypeFoldable;
- use rustc_middle::ty::Predicate::*;
+ use rustc_middle::ty::PredicateKind::*;
if cx.tcx.features().trivial_bounds {
let def_id = cx.tcx.hir().local_def_id(item.hir_id);
let predicates = cx.tcx.predicates_of(def_id);
for &(predicate, span) in predicates.predicates {
- let predicate_kind_name = match predicate {
+ let predicate_kind_name = match predicate.kind() {
Trait(..) => "Trait",
TypeOutlives(..) |
RegionOutlives(..) => "Lifetime",
@@ -1497,8 +1497,8 @@
) -> Vec<ty::Region<'tcx>> {
inferred_outlives
.iter()
- .filter_map(|(pred, _)| match pred {
- ty::Predicate::RegionOutlives(outlives) => {
+ .filter_map(|(pred, _)| match pred.kind() {
+ ty::PredicateKind::RegionOutlives(outlives) => {
let outlives = outlives.skip_binder();
match outlives.0 {
ty::ReEarlyBound(ebr) if ebr.index == index => Some(outlives.1),
@@ -1516,8 +1516,8 @@
) -> Vec<ty::Region<'tcx>> {
inferred_outlives
.iter()
- .filter_map(|(pred, _)| match pred {
- ty::Predicate::TypeOutlives(outlives) => {
+ .filter_map(|(pred, _)| match pred.kind() {
+ ty::PredicateKind::TypeOutlives(outlives) => {
let outlives = outlives.skip_binder();
outlives.0.is_param(index).then_some(outlives.1)
}
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index c24079a..dea82934 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -146,7 +146,9 @@
ty::Opaque(def, _) => {
let mut has_emitted = false;
for (predicate, _) in cx.tcx.predicates_of(def).predicates {
- if let ty::Predicate::Trait(ref poly_trait_predicate, _) = predicate {
+ if let ty::PredicateKind::Trait(ref poly_trait_predicate, _) =
+ predicate.kind()
+ {
let trait_ref = poly_trait_predicate.skip_binder().trait_ref;
let def_id = trait_ref.def_id;
let descr_pre =
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index a9e7a9f..b0220dd 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -615,7 +615,7 @@
fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
// If we're only compiling an rlib, then there's no need to select a
// panic runtime, so we just skip this section entirely.
- let any_non_rlib = self.sess.crate_types.borrow().iter().any(|ct| *ct != CrateType::Rlib);
+ let any_non_rlib = self.sess.crate_types().iter().any(|ct| *ct != CrateType::Rlib);
if !any_non_rlib {
info!("panic runtime injection skipped, only generating rlib");
return;
@@ -734,7 +734,7 @@
// At this point we've determined that we need an allocator. Let's see
// if our compilation session actually needs an allocator based on what
// we're emitting.
- let all_rlib = self.sess.crate_types.borrow().iter().all(|ct| match *ct {
+ let all_rlib = self.sess.crate_types().iter().all(|ct| match *ct {
CrateType::Rlib => true,
_ => false,
});
diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs
index 0876cd1..aa5fafc 100644
--- a/src/librustc_metadata/dependency_format.rs
+++ b/src/librustc_metadata/dependency_format.rs
@@ -64,8 +64,7 @@
crate fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
tcx.sess
- .crate_types
- .borrow()
+ .crate_types()
.iter()
.map(|&ty| {
let linkage = calculate_type(tcx, ty);
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index f78f3c5..5a4862d 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -670,7 +670,7 @@
// The all loop is because `--crate-type=rlib --crate-type=rlib` is
// legal and produces both inside this type.
- let is_rlib = self.sess.crate_types.borrow().iter().all(|c| *c == CrateType::Rlib);
+ let is_rlib = self.sess.crate_types().iter().all(|c| *c == CrateType::Rlib);
let needs_object_code = self.sess.opts.output_types.should_codegen();
// If we're producing an rlib, then we don't need object code.
// Or, if we're not producing object code, then we don't need it either
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index 51c9950..fc4235a 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -3,22 +3,23 @@
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_middle::middle::cstore::{self, NativeLibrary};
+use rustc_middle::middle::cstore::NativeLib;
use rustc_middle::ty::TyCtxt;
use rustc_session::parse::feature_err;
+use rustc_session::utils::NativeLibKind;
use rustc_session::Session;
use rustc_span::source_map::Span;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_target::spec::abi::Abi;
-crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLibrary> {
+crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
let mut collector = Collector { tcx, libs: Vec::new() };
tcx.hir().krate().visit_all_item_likes(&mut collector);
collector.process_command_line();
collector.libs
}
-crate fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool {
+crate fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
match lib.cfg {
Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, None),
None => true,
@@ -27,7 +28,7 @@
struct Collector<'tcx> {
tcx: TyCtxt<'tcx>,
- libs: Vec<NativeLibrary>,
+ libs: Vec<NativeLib>,
}
impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
@@ -47,9 +48,9 @@
Some(item) => item,
None => continue,
};
- let mut lib = NativeLibrary {
+ let mut lib = NativeLib {
name: None,
- kind: cstore::NativeUnknown,
+ kind: NativeLibKind::Unspecified,
cfg: None,
foreign_module: Some(self.tcx.hir().local_def_id(it.hir_id).to_def_id()),
wasm_import_module: None,
@@ -64,11 +65,11 @@
None => continue, // skip like historical compilers
};
lib.kind = match &*kind.as_str() {
- "static" => cstore::NativeStatic,
- "static-nobundle" => cstore::NativeStaticNobundle,
- "dylib" => cstore::NativeUnknown,
- "framework" => cstore::NativeFramework,
- "raw-dylib" => cstore::NativeRawDylib,
+ "static" => NativeLibKind::StaticBundle,
+ "static-nobundle" => NativeLibKind::StaticNoBundle,
+ "dylib" => NativeLibKind::Dylib,
+ "framework" => NativeLibKind::Framework,
+ "raw-dylib" => NativeLibKind::RawDylib,
k => {
struct_span_err!(
self.tcx.sess,
@@ -80,7 +81,7 @@
.span_label(item.span(), "unknown kind")
.span_label(m.span, "")
.emit();
- cstore::NativeUnknown
+ NativeLibKind::Unspecified
}
};
} else if item.check_name(sym::name) {
@@ -134,7 +135,7 @@
}
impl Collector<'tcx> {
- fn register_native_lib(&mut self, span: Option<Span>, lib: NativeLibrary) {
+ fn register_native_lib(&mut self, span: Option<Span>, lib: NativeLib) {
if lib.name.as_ref().map(|&s| s == kw::Invalid).unwrap_or(false) {
match span {
Some(span) => {
@@ -154,7 +155,7 @@
return;
}
let is_osx = self.tcx.sess.target.target.options.is_like_osx;
- if lib.kind == cstore::NativeFramework && !is_osx {
+ if lib.kind == NativeLibKind::Framework && !is_osx {
let msg = "native frameworks are only available on macOS targets";
match span {
Some(span) => struct_span_err!(self.tcx.sess, span, E0455, "{}", msg).emit(),
@@ -170,7 +171,7 @@
)
.emit();
}
- if lib.kind == cstore::NativeStaticNobundle && !self.tcx.features().static_nobundle {
+ if lib.kind == NativeLibKind::StaticNoBundle && !self.tcx.features().static_nobundle {
feature_err(
&self.tcx.sess.parse_sess,
sym::static_nobundle,
@@ -179,7 +180,7 @@
)
.emit();
}
- if lib.kind == cstore::NativeRawDylib && !self.tcx.features().raw_dylib {
+ if lib.kind == NativeLibKind::RawDylib && !self.tcx.features().raw_dylib {
feature_err(
&self.tcx.sess.parse_sess,
sym::raw_dylib,
@@ -240,8 +241,8 @@
.drain_filter(|lib| {
if let Some(lib_name) = lib.name {
if lib_name.as_str() == *name {
- if let Some(k) = kind {
- lib.kind = k;
+ if kind != NativeLibKind::Unspecified {
+ lib.kind = kind;
}
if let &Some(ref new_name) = new_name {
lib.name = Some(Symbol::intern(new_name));
@@ -255,9 +256,9 @@
if existing.is_empty() {
// Add if not found
let new_name = new_name.as_ref().map(|s| &**s); // &Option<String> -> Option<&str>
- let lib = NativeLibrary {
+ let lib = NativeLib {
name: Some(Symbol::intern(new_name.unwrap_or(name))),
- kind: if let Some(k) = kind { k } else { cstore::NativeUnknown },
+ kind,
cfg: None,
foreign_module: None,
wasm_import_module: None,
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index 32149c0..2b292b3 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -10,7 +10,7 @@
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, Once};
+use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, OnceCell};
use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive};
use rustc_hir as hir;
@@ -23,7 +23,7 @@
use rustc_middle::dep_graph::{self, DepNode, DepNodeExt, DepNodeIndex};
use rustc_middle::hir::exports::Export;
use rustc_middle::middle::cstore::{CrateSource, ExternCrate};
-use rustc_middle::middle::cstore::{ForeignModule, LinkagePreference, NativeLibrary};
+use rustc_middle::middle::cstore::{ForeignModule, LinkagePreference, NativeLib};
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc_middle::mir::{self, interpret, Body, Promoted};
@@ -79,7 +79,7 @@
/// Proc macro descriptions for this crate, if it's a proc macro crate.
raw_proc_macros: Option<&'static [ProcMacro]>,
/// Source maps for code from the crate.
- source_map_import_info: Once<Vec<ImportedSourceFile>>,
+ source_map_import_info: OnceCell<Vec<ImportedSourceFile>>,
/// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
alloc_decoding_state: AllocDecodingState,
/// The `DepNodeIndex` of the `DepNode` representing this upstream crate.
@@ -1278,7 +1278,7 @@
})
}
- fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLibrary> {
+ fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLib> {
if self.root.is_proc_macro_crate() {
// Proc macro crates do not have any *target* native libraries.
vec![]
@@ -1486,7 +1486,7 @@
}
};
- self.cdata.source_map_import_info.init_locking(|| {
+ self.cdata.source_map_import_info.get_or_init(|| {
let external_source_map = self.root.source_map.decode(self);
external_source_map
@@ -1600,7 +1600,7 @@
def_path_table,
trait_impls,
raw_proc_macros,
- source_map_import_info: Once::new(),
+ source_map_import_info: OnceCell::new(),
alloc_decoding_state,
dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
cnum,
diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
index b182726..1b168bf 100644
--- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
+++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
@@ -13,12 +13,13 @@
use rustc_hir::definitions::DefPathTable;
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
use rustc_middle::hir::exports::Export;
-use rustc_middle::middle::cstore::{CrateSource, CrateStore, EncodedMetadata, NativeLibraryKind};
+use rustc_middle::middle::cstore::{CrateSource, CrateStore, EncodedMetadata};
use rustc_middle::middle::exported_symbols::ExportedSymbol;
use rustc_middle::middle::stability::DeprecationEntry;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::query::QueryConfig;
use rustc_middle::ty::{self, TyCtxt};
+use rustc_session::utils::NativeLibKind;
use rustc_session::{CrateDisambiguator, Session};
use rustc_span::source_map::{self, Span, Spanned};
use rustc_span::symbol::{Ident, Symbol};
@@ -246,11 +247,13 @@
// resolve! Does this work? Unsure! That's what the issue is about
*providers = Providers {
is_dllimport_foreign_item: |tcx, id| match tcx.native_library_kind(id) {
- Some(NativeLibraryKind::NativeUnknown | NativeLibraryKind::NativeRawDylib) => true,
+ Some(NativeLibKind::Dylib | NativeLibKind::RawDylib | NativeLibKind::Unspecified) => {
+ true
+ }
_ => false,
},
is_statically_included_foreign_item: |tcx, id| match tcx.native_library_kind(id) {
- Some(NativeLibraryKind::NativeStatic | NativeLibraryKind::NativeStaticNobundle) => true,
+ Some(NativeLibKind::StaticBundle | NativeLibKind::StaticNoBundle) => true,
_ => false,
},
native_library_kind: |tcx, id| {
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index 2589e16..91fbfcc 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -18,9 +18,7 @@
use rustc_hir::{AnonConst, GenericParamKind};
use rustc_index::vec::Idx;
use rustc_middle::hir::map::Map;
-use rustc_middle::middle::cstore::{
- EncodedMetadata, ForeignModule, LinkagePreference, NativeLibrary,
-};
+use rustc_middle::middle::cstore::{EncodedMetadata, ForeignModule, LinkagePreference, NativeLib};
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::{
metadata_symbol_name, ExportedSymbol, SymbolExportLevel,
@@ -418,7 +416,7 @@
}
fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
- let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
+ let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro);
let mut i = self.position();
@@ -1355,7 +1353,7 @@
self.encode_promoted_mir(def_id);
}
- fn encode_native_libraries(&mut self) -> Lazy<[NativeLibrary]> {
+ fn encode_native_libraries(&mut self) -> Lazy<[NativeLib]> {
let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
self.lazy(used_libraries.iter().cloned())
}
@@ -1366,7 +1364,7 @@
}
fn encode_proc_macros(&mut self) -> Option<Lazy<[DefIndex]>> {
- let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
+ let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro);
if is_proc_macro {
let tcx = self.tcx;
Some(self.lazy(tcx.hir().krate().proc_macros.iter().map(|p| p.owner.local_def_index)))
diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs
index 6693076..89d525e 100644
--- a/src/librustc_metadata/rmeta/mod.rs
+++ b/src/librustc_metadata/rmeta/mod.rs
@@ -11,7 +11,7 @@
use rustc_hir::lang_items;
use rustc_index::vec::IndexVec;
use rustc_middle::hir::exports::Export;
-use rustc_middle::middle::cstore::{DepKind, ForeignModule, LinkagePreference, NativeLibrary};
+use rustc_middle::middle::cstore::{DepKind, ForeignModule, LinkagePreference, NativeLib};
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use rustc_middle::mir;
use rustc_middle::ty::{self, ReprOptions, Ty};
@@ -190,7 +190,7 @@
lang_items: Lazy<[(DefIndex, usize)]>,
lang_items_missing: Lazy<[lang_items::LangItem]>,
diagnostic_items: Lazy<[(Symbol, DefIndex)]>,
- native_libraries: Lazy<[NativeLibrary]>,
+ native_libraries: Lazy<[NativeLib]>,
foreign_modules: Lazy<[ForeignModule]>,
source_map: Lazy<[rustc_span::SourceFile]>,
def_path_table: Lazy<rustc_hir::definitions::DefPathTable>,
diff --git a/src/librustc_middle/arena.rs b/src/librustc_middle/arena.rs
index a97db31..2df878c 100644
--- a/src/librustc_middle/arena.rs
+++ b/src/librustc_middle/arena.rs
@@ -76,6 +76,12 @@
[few] hir_definitions: rustc_hir::definitions::Definitions,
[] hir_owner: rustc_middle::hir::Owner<$tcx>,
[] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>,
+
+ // Note that this deliberately duplicates items in the `rustc_hir::arena`,
+ // since we need to allocate this type on both the `rustc_hir` arena
+ // (during lowering) and the `librustc_middle` arena (for decoding MIR)
+ [decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
+
], $tcx);
)
}
diff --git a/src/librustc_middle/ich/impls_ty.rs b/src/librustc_middle/ich/impls_ty.rs
index 377c866..ef62478 100644
--- a/src/librustc_middle/ich/impls_ty.rs
+++ b/src/librustc_middle/ich/impls_ty.rs
@@ -87,9 +87,6 @@
index.hash_stable(hcx, hasher);
name.hash_stable(hcx, hasher);
}
- ty::ReScope(scope) => {
- scope.hash_stable(hcx, hasher);
- }
ty::ReFree(ref free_region) => {
free_region.hash_stable(hcx, hasher);
}
diff --git a/src/librustc_middle/middle/cstore.rs b/src/librustc_middle/middle/cstore.rs
index 012390e..97e877d 100644
--- a/src/librustc_middle/middle/cstore.rs
+++ b/src/librustc_middle/middle/cstore.rs
@@ -2,8 +2,6 @@
//! are *mostly* used as a part of that interface, but these should
//! probably get a better home if someone can find one.
-pub use self::NativeLibraryKind::*;
-
use crate::ty::TyCtxt;
use rustc_ast::ast;
@@ -14,7 +12,7 @@
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, DefPathTable};
use rustc_macros::HashStable;
use rustc_session::search_paths::PathKind;
-pub use rustc_session::utils::NativeLibraryKind;
+use rustc_session::utils::NativeLibKind;
use rustc_session::CrateDisambiguator;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
@@ -89,8 +87,8 @@
}
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub struct NativeLibrary {
- pub kind: NativeLibraryKind,
+pub struct NativeLib {
+ pub kind: NativeLibKind,
pub name: Option<Symbol>,
pub cfg: Option<ast::MetaItem>,
pub foreign_module: Option<DefId>,
diff --git a/src/librustc_middle/middle/limits.rs b/src/librustc_middle/middle/limits.rs
index c43c22c..19c0569 100644
--- a/src/librustc_middle/middle/limits.rs
+++ b/src/librustc_middle/middle/limits.rs
@@ -7,7 +7,7 @@
use crate::bug;
use rustc_ast::ast;
-use rustc_data_structures::sync::Once;
+use rustc_data_structures::sync::OnceCell;
use rustc_session::Session;
use rustc_span::symbol::{sym, Symbol};
@@ -22,7 +22,7 @@
fn update_limit(
sess: &Session,
krate: &ast::Crate,
- limit: &Once<usize>,
+ limit: &OnceCell<usize>,
name: Symbol,
default: usize,
) {
@@ -34,7 +34,7 @@
if let Some(s) = attr.value_str() {
match s.as_str().parse() {
Ok(n) => {
- limit.set(n);
+ limit.set(n).unwrap();
return;
}
Err(e) => {
@@ -62,5 +62,5 @@
}
}
}
- limit.set(default);
+ limit.set(default).unwrap();
}
diff --git a/src/librustc_middle/middle/region.rs b/src/librustc_middle/middle/region.rs
index f02d8fe..943a065 100644
--- a/src/librustc_middle/middle/region.rs
+++ b/src/librustc_middle/middle/region.rs
@@ -7,7 +7,7 @@
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
use crate::ich::{NodeIdHashingMode, StableHashingContext};
-use crate::ty::{self, DefIdTree, TyCtxt};
+use crate::ty::TyCtxt;
use rustc_hir as hir;
use rustc_hir::Node;
@@ -333,7 +333,7 @@
pub source: hir::YieldSource,
}
-impl<'tcx> ScopeTree {
+impl ScopeTree {
pub fn record_scope_parent(&mut self, child: Scope, parent: Option<(Scope, ScopeDepth)>) {
debug!("{:?}.parent = {:?}", child, parent);
@@ -348,24 +348,6 @@
}
}
- pub fn each_encl_scope<E>(&self, mut e: E)
- where
- E: FnMut(Scope, Scope),
- {
- for (&child, &parent) in &self.parent_map {
- e(child, parent.0)
- }
- }
-
- pub fn each_var_scope<E>(&self, mut e: E)
- where
- E: FnMut(&hir::ItemLocalId, Scope),
- {
- for (child, &parent) in self.var_map.iter() {
- e(child, parent)
- }
- }
-
pub fn opt_destruction_scope(&self, n: hir::ItemLocalId) -> Option<Scope> {
self.destruction_scopes.get(&n).cloned()
}
@@ -406,12 +388,6 @@
self.parent_map.get(&id).cloned().map(|(p, _)| p)
}
- /// Returns the narrowest scope that encloses `id`, if any.
- #[allow(dead_code)] // used in cfg
- pub fn encl_scope(&self, id: Scope) -> Scope {
- self.opt_encl_scope(id).unwrap()
- }
-
/// Returns the lifetime of the local variable `var_id`
pub fn var_scope(&self, var_id: hir::ItemLocalId) -> Scope {
self.var_map
@@ -448,17 +424,6 @@
None
}
- /// Returns the lifetime of the variable `id`.
- pub fn var_region(&self, id: hir::ItemLocalId) -> ty::RegionKind {
- let scope = ty::ReScope(self.var_scope(id));
- debug!("var_region({:?}) = {:?}", id, scope);
- scope
- }
-
- pub fn scopes_intersect(&self, scope1: Scope, scope2: Scope) -> bool {
- self.is_subscope_of(scope1, scope2) || self.is_subscope_of(scope2, scope1)
- }
-
/// Returns `true` if `subscope` is equal to or is lexically nested inside `superscope`, and
/// `false` otherwise.
pub fn is_subscope_of(&self, subscope: Scope, superscope: Scope) -> bool {
@@ -479,127 +444,6 @@
true
}
- /// Returns the ID of the innermost containing body.
- pub fn containing_body(&self, mut scope: Scope) -> Option<hir::ItemLocalId> {
- loop {
- if let ScopeData::CallSite = scope.data {
- return Some(scope.item_local_id());
- }
-
- scope = self.opt_encl_scope(scope)?;
- }
- }
-
- /// Finds the nearest common ancestor of two scopes. That is, finds the
- /// smallest scope which is greater than or equal to both `scope_a` and
- /// `scope_b`.
- pub fn nearest_common_ancestor(&self, scope_a: Scope, scope_b: Scope) -> Scope {
- if scope_a == scope_b {
- return scope_a;
- }
-
- let mut a = scope_a;
- let mut b = scope_b;
-
- // Get the depth of each scope's parent. If either scope has no parent,
- // it must be the root, which means we can stop immediately because the
- // root must be the nearest common ancestor. (In practice, this is
- // moderately common.)
- let (parent_a, parent_a_depth) = match self.parent_map.get(&a) {
- Some(pd) => *pd,
- None => return a,
- };
- let (parent_b, parent_b_depth) = match self.parent_map.get(&b) {
- Some(pd) => *pd,
- None => return b,
- };
-
- if parent_a_depth > parent_b_depth {
- // `a` is lower than `b`. Move `a` up until it's at the same depth
- // as `b`. The first move up is trivial because we already found
- // `parent_a` above; the loop does the remaining N-1 moves.
- a = parent_a;
- for _ in 0..(parent_a_depth - parent_b_depth - 1) {
- a = self.parent_map.get(&a).unwrap().0;
- }
- } else if parent_b_depth > parent_a_depth {
- // `b` is lower than `a`.
- b = parent_b;
- for _ in 0..(parent_b_depth - parent_a_depth - 1) {
- b = self.parent_map.get(&b).unwrap().0;
- }
- } else {
- // Both scopes are at the same depth, and we know they're not equal
- // because that case was tested for at the top of this function. So
- // we can trivially move them both up one level now.
- assert!(parent_a_depth != 0);
- a = parent_a;
- b = parent_b;
- }
-
- // Now both scopes are at the same level. We move upwards in lockstep
- // until they match. In practice, this loop is almost always executed
- // zero times because `a` is almost always a direct ancestor of `b` or
- // vice versa.
- while a != b {
- a = self.parent_map.get(&a).unwrap().0;
- b = self.parent_map.get(&b).unwrap().0;
- }
-
- a
- }
-
- /// Assuming that the provided region was defined within this `ScopeTree`,
- /// returns the outermost `Scope` that the region outlives.
- pub fn early_free_scope(&self, tcx: TyCtxt<'tcx>, br: &ty::EarlyBoundRegion) -> Scope {
- let param_owner = tcx.parent(br.def_id).unwrap();
-
- let param_owner_id = tcx.hir().as_local_hir_id(param_owner.expect_local());
- let scope = tcx
- .hir()
- .maybe_body_owned_by(param_owner_id)
- .map(|body_id| tcx.hir().body(body_id).value.hir_id.local_id)
- .unwrap_or_else(|| {
- // The lifetime was defined on node that doesn't own a body,
- // which in practice can only mean a trait or an impl, that
- // is the parent of a method, and that is enforced below.
- if Some(param_owner_id) != self.root_parent {
- tcx.sess.delay_span_bug(
- DUMMY_SP,
- &format!(
- "free_scope: {:?} not recognized by the \
- region scope tree for {:?} / {:?}",
- param_owner,
- self.root_parent.map(|id| tcx.hir().local_def_id(id)),
- self.root_body.map(|hir_id| hir_id.owner)
- ),
- );
- }
-
- // The trait/impl lifetime is in scope for the method's body.
- self.root_body.unwrap().local_id
- });
-
- Scope { id: scope, data: ScopeData::CallSite }
- }
-
- /// Assuming that the provided region was defined within this `ScopeTree`,
- /// returns the outermost `Scope` that the region outlives.
- pub fn free_scope(&self, tcx: TyCtxt<'tcx>, fr: &ty::FreeRegion) -> Scope {
- let param_owner = match fr.bound_region {
- ty::BoundRegion::BrNamed(def_id, _) => tcx.parent(def_id).unwrap(),
- _ => fr.scope,
- };
-
- // Ensure that the named late-bound lifetimes were defined
- // on the same function that they ended up being freed in.
- assert_eq!(param_owner, fr.scope);
-
- let param_owner_id = tcx.hir().as_local_hir_id(param_owner.expect_local());
- let body_id = tcx.hir().body_owned_by(param_owner_id);
- Scope { id: tcx.hir().body(body_id).value.hir_id.local_id, data: ScopeData::CallSite }
- }
-
/// Checks whether the given scope contains a `yield`. If so,
/// returns `Some((span, expr_count))` with the span of a yield we found and
/// the number of expressions and patterns appearing before the `yield` in the body + 1.
diff --git a/src/librustc_middle/mir/interpret/allocation.rs b/src/librustc_middle/mir/interpret/allocation.rs
index 2b6cf22..96195db 100644
--- a/src/librustc_middle/mir/interpret/allocation.rs
+++ b/src/librustc_middle/mir/interpret/allocation.rs
@@ -11,6 +11,7 @@
use super::{
read_target_uint, write_target_uint, AllocId, InterpResult, Pointer, Scalar, ScalarMaybeUninit,
+ UninitBytesAccess,
};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
@@ -545,17 +546,23 @@
impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
/// Checks whether the given range is entirely defined.
///
- /// Returns `Ok(())` if it's defined. Otherwise returns the index of the byte
- /// at which the first undefined access begins.
- fn is_defined(&self, ptr: Pointer<Tag>, size: Size) -> Result<(), Size> {
+ /// Returns `Ok(())` if it's defined. Otherwise returns the range of byte
+ /// indexes of the first contiguous undefined access.
+ fn is_defined(&self, ptr: Pointer<Tag>, size: Size) -> Result<(), Range<Size>> {
self.init_mask.is_range_initialized(ptr.offset, ptr.offset + size) // `Size` addition
}
- /// Checks that a range of bytes is defined. If not, returns the `ReadUndefBytes`
- /// error which will report the first byte which is undefined.
+ /// Checks that a range of bytes is defined. If not, returns the `InvalidUndefBytes`
+ /// error which will report the first range of bytes which is undefined.
fn check_defined(&self, ptr: Pointer<Tag>, size: Size) -> InterpResult<'tcx> {
- self.is_defined(ptr, size)
- .or_else(|idx| throw_ub!(InvalidUninitBytes(Some(Pointer::new(ptr.alloc_id, idx)))))
+ self.is_defined(ptr, size).or_else(|idx_range| {
+ throw_ub!(InvalidUninitBytes(Some(Box::new(UninitBytesAccess {
+ access_ptr: ptr.erase_tag(),
+ access_size: size,
+ uninit_ptr: Pointer::new(ptr.alloc_id, idx_range.start),
+ uninit_size: idx_range.end - idx_range.start, // `Size` subtraction
+ }))))
+ })
}
pub fn mark_definedness(&mut self, ptr: Pointer<Tag>, size: Size, new_state: bool) {
@@ -758,19 +765,25 @@
/// Checks whether the range `start..end` (end-exclusive) is entirely initialized.
///
- /// Returns `Ok(())` if it's initialized. Otherwise returns the index of the byte
- /// at which the first uninitialized access begins.
+ /// Returns `Ok(())` if it's initialized. Otherwise returns a range of byte
+ /// indexes for the first contiguous span of the uninitialized access.
#[inline]
- pub fn is_range_initialized(&self, start: Size, end: Size) -> Result<(), Size> {
+ pub fn is_range_initialized(&self, start: Size, end: Size) -> Result<(), Range<Size>> {
if end > self.len {
- return Err(self.len);
+ return Err(self.len..end);
}
// FIXME(oli-obk): optimize this for allocations larger than a block.
let idx = (start.bytes()..end.bytes()).map(Size::from_bytes).find(|&i| !self.get(i));
match idx {
- Some(idx) => Err(idx),
+ Some(idx) => {
+ let undef_end = (idx.bytes()..end.bytes())
+ .map(Size::from_bytes)
+ .find(|&i| self.get(i))
+ .unwrap_or(end);
+ Err(idx..undef_end)
+ }
None => Ok(()),
}
}
diff --git a/src/librustc_middle/mir/interpret/error.rs b/src/librustc_middle/mir/interpret/error.rs
index 06fe379..d32a147 100644
--- a/src/librustc_middle/mir/interpret/error.rs
+++ b/src/librustc_middle/mir/interpret/error.rs
@@ -6,7 +6,7 @@
use crate::ty::{self, layout, tls, FnSig, Ty};
use rustc_data_structures::sync::Lock;
-use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorReported};
+use rustc_errors::{pluralize, struct_span_err, DiagnosticBuilder, ErrorReported};
use rustc_hir as hir;
use rustc_hir::definitions::DefPathData;
use rustc_macros::HashStable;
@@ -327,6 +327,19 @@
}
}
+/// Details of an access to uninitialized bytes where it is not allowed.
+#[derive(Debug)]
+pub struct UninitBytesAccess {
+ /// Location of the original memory access.
+ pub access_ptr: Pointer,
+ /// Size of the original memory access.
+ pub access_size: Size,
+ /// Location of the first uninitialized byte that was accessed.
+ pub uninit_ptr: Pointer,
+ /// Number of consecutive uninitialized bytes that were accessed.
+ pub uninit_size: Size,
+}
+
/// Error information for when the program caused Undefined Behavior.
pub enum UndefinedBehaviorInfo<'tcx> {
/// Free-form case. Only for errors that are never caught!
@@ -384,7 +397,7 @@
/// Using a string that is not valid UTF-8,
InvalidStr(std::str::Utf8Error),
/// Using uninitialized data where it is not allowed.
- InvalidUninitBytes(Option<Pointer>),
+ InvalidUninitBytes(Option<Box<UninitBytesAccess>>),
/// Working with a local that is not currently live.
DeadLocal,
/// Data size is not equal to target size.
@@ -455,10 +468,18 @@
write!(f, "using {} as function pointer but it does not point to a function", p)
}
InvalidStr(err) => write!(f, "this string is not valid UTF-8: {}", err),
- InvalidUninitBytes(Some(p)) => write!(
+ InvalidUninitBytes(Some(access)) => write!(
f,
- "reading uninitialized memory at {}, but this operation requires initialized memory",
- p
+ "reading {} byte{} of memory starting at {}, \
+ but {} byte{} {} uninitialized starting at {}, \
+ and this operation requires initialized memory",
+ access.access_size.bytes(),
+ pluralize!(access.access_size.bytes()),
+ access.access_ptr,
+ access.uninit_size.bytes(),
+ pluralize!(access.uninit_size.bytes()),
+ if access.uninit_size.bytes() != 1 { "are" } else { "is" },
+ access.uninit_ptr,
),
InvalidUninitBytes(None) => write!(
f,
@@ -556,6 +577,9 @@
}
}
+#[cfg(target_arch = "x86_64")]
+static_assert_size!(InterpError<'_>, 40);
+
pub enum InterpError<'tcx> {
/// The program caused undefined behavior.
UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
@@ -604,7 +628,10 @@
InterpError::MachineStop(b) => mem::size_of_val::<dyn MachineStopType>(&**b) > 0,
InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_))
- | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) => true,
+ | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
+ | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes(Some(_))) => {
+ true
+ }
_ => false,
}
}
diff --git a/src/librustc_middle/mir/interpret/mod.rs b/src/librustc_middle/mir/interpret/mod.rs
index 71adb2f..d9e52af 100644
--- a/src/librustc_middle/mir/interpret/mod.rs
+++ b/src/librustc_middle/mir/interpret/mod.rs
@@ -119,7 +119,7 @@
pub use self::error::{
struct_error, CheckInAllocMsg, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled,
FrameInfo, InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType,
- ResourceExhaustionInfo, UndefinedBehaviorInfo, UnsupportedOpInfo,
+ ResourceExhaustionInfo, UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
};
pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUninit};
diff --git a/src/librustc_middle/mir/predecessors.rs b/src/librustc_middle/mir/predecessors.rs
index 9508365..7508c02 100644
--- a/src/librustc_middle/mir/predecessors.rs
+++ b/src/librustc_middle/mir/predecessors.rs
@@ -1,7 +1,7 @@
//! Lazily compute the reverse control-flow graph for the MIR.
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::{Lock, Lrc};
+use rustc_data_structures::sync::OnceCell;
use rustc_index::vec::IndexVec;
use rustc_serialize as serialize;
use smallvec::SmallVec;
@@ -13,37 +13,33 @@
#[derive(Clone, Debug)]
pub(super) struct PredecessorCache {
- cache: Lock<Option<Lrc<Predecessors>>>,
+ cache: OnceCell<Predecessors>,
}
impl PredecessorCache {
#[inline]
pub(super) fn new() -> Self {
- PredecessorCache { cache: Lock::new(None) }
+ PredecessorCache { cache: OnceCell::new() }
}
/// Invalidates the predecessor cache.
- ///
- /// Invalidating the predecessor cache requires mutating the MIR, which in turn requires a
- /// unique reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all
- /// callers of `invalidate` have a unique reference to the MIR and thus to the predecessor
- /// cache. This means we don't actually need to take a lock when `invalidate` is called.
#[inline]
pub(super) fn invalidate(&mut self) {
- *self.cache.get_mut() = None;
+ // Invalidating the predecessor cache requires mutating the MIR, which in turn requires a
+ // unique reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all
+ // callers of `invalidate` have a unique reference to the MIR and thus to the predecessor
+ // cache. This means we never need to do synchronization when `invalidate` is called, we can
+ // simply reinitialize the `OnceCell`.
+ self.cache = OnceCell::new();
}
- /// Returns a ref-counted smart pointer containing the predecessor graph for this MIR.
- ///
- /// We use ref-counting instead of a mapped `LockGuard` here to ensure that the lock for
- /// `cache` is only held inside this function. As long as no other locks are taken while
- /// computing the predecessor graph, deadlock is impossible.
+ /// Returns the the predecessor graph for this MIR.
#[inline]
pub(super) fn compute(
&self,
basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>,
- ) -> Lrc<Predecessors> {
- Lrc::clone(self.cache.lock().get_or_insert_with(|| {
+ ) -> &Predecessors {
+ self.cache.get_or_init(|| {
let mut preds = IndexVec::from_elem(SmallVec::new(), basic_blocks);
for (bb, data) in basic_blocks.iter_enumerated() {
if let Some(term) = &data.terminator {
@@ -53,8 +49,8 @@
}
}
- Lrc::new(preds)
- }))
+ preds
+ })
}
}
diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs
index 13cf9a9..f7f5c5d 100644
--- a/src/librustc_middle/query/mod.rs
+++ b/src/librustc_middle/query/mod.rs
@@ -131,7 +131,7 @@
cache_on_disk_if { key.is_local() }
}
- query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLibrary>> {
+ query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLib>> {
desc { "looking up the native libraries of a linked crate" }
}
@@ -937,7 +937,7 @@
query is_dllimport_foreign_item(_: DefId) -> bool {}
query is_statically_included_foreign_item(_: DefId) -> bool {}
query native_library_kind(_: DefId)
- -> Option<NativeLibraryKind> {}
+ -> Option<NativeLibKind> {}
}
Linking {
diff --git a/src/librustc_middle/ty/codec.rs b/src/librustc_middle/ty/codec.rs
index 1cd4af4..c4d5bd7 100644
--- a/src/librustc_middle/ty/codec.rs
+++ b/src/librustc_middle/ty/codec.rs
@@ -10,7 +10,7 @@
use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
use crate::mir::{self, interpret::Allocation};
use crate::ty::subst::SubstsRef;
-use crate::ty::{self, List, Ty, TyCtxt};
+use crate::ty::{self, List, ToPredicate, Ty, TyCtxt};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
@@ -200,15 +200,16 @@
(0..decoder.read_usize()?)
.map(|_| {
// Handle shorthands first, if we have an usize > 0x80.
- let predicate = if decoder.positioned_at_shorthand() {
+ let predicate_kind = if decoder.positioned_at_shorthand() {
let pos = decoder.read_usize()?;
assert!(pos >= SHORTHAND_OFFSET);
let shorthand = pos - SHORTHAND_OFFSET;
- decoder.with_position(shorthand, ty::Predicate::decode)
+ decoder.with_position(shorthand, ty::PredicateKind::decode)
} else {
- ty::Predicate::decode(decoder)
+ ty::PredicateKind::decode(decoder)
}?;
+ let predicate = predicate_kind.to_predicate(tcx);
Ok((predicate, Decodable::decode(decoder)?))
})
.collect::<Result<Vec<_>, _>>()?,
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index d2e53fa..68c31c6 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -29,8 +29,9 @@
use crate::ty::{AdtDef, AdtKind, Const, Region};
use crate::ty::{BindingMode, BoundVar};
use crate::ty::{ConstVid, FloatVar, FloatVid, IntVar, IntVid, TyVar, TyVid};
-use crate::ty::{ExistentialPredicate, InferTy, ParamTy, PolyFnSig, Predicate, ProjectionTy};
+use crate::ty::{ExistentialPredicate, Predicate, PredicateKind};
use crate::ty::{InferConst, ParamConst};
+use crate::ty::{InferTy, ParamTy, PolyFnSig, ProjectionTy};
use crate::ty::{List, TyKind, TyS};
use rustc_ast::ast;
use rustc_ast::expand::allocator::AllocatorKind;
@@ -89,6 +90,7 @@
canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo>>,
region: InternedSet<'tcx, RegionKind>,
existential_predicates: InternedSet<'tcx, List<ExistentialPredicate<'tcx>>>,
+ predicate_kind: InternedSet<'tcx, PredicateKind<'tcx>>,
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
projs: InternedSet<'tcx, List<ProjectionKind>>,
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
@@ -107,6 +109,7 @@
region: Default::default(),
existential_predicates: Default::default(),
canonical_var_infos: Default::default(),
+ predicate_kind: Default::default(),
predicates: Default::default(),
projs: Default::default(),
place_elems: Default::default(),
@@ -1377,7 +1380,7 @@
pub fn local_crate_exports_generics(self) -> bool {
debug_assert!(self.sess.opts.share_generics());
- self.sess.crate_types.borrow().iter().any(|crate_type| {
+ self.sess.crate_types().iter().any(|crate_type| {
match crate_type {
CrateType::Executable
| CrateType::Staticlib
@@ -1574,6 +1577,7 @@
nop_lift! {type_; Ty<'a> => Ty<'tcx>}
nop_lift! {region; Region<'a> => Region<'tcx>}
nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>}
+nop_lift! {predicate_kind; &'a PredicateKind<'a> => &'tcx PredicateKind<'tcx>}
nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
nop_list_lift! {existential_predicates; ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
@@ -2012,8 +2016,14 @@
}
}
+impl<'tcx> Borrow<PredicateKind<'tcx>> for Interned<'tcx, PredicateKind<'tcx>> {
+ fn borrow<'a>(&'a self) -> &'a PredicateKind<'tcx> {
+ &self.0
+ }
+}
+
macro_rules! direct_interners {
- ($($name:ident: $method:ident($ty:ty)),+) => {
+ ($($name:ident: $method:ident($ty:ty),)+) => {
$(impl<'tcx> PartialEq for Interned<'tcx, $ty> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
@@ -2038,7 +2048,11 @@
}
}
-direct_interners!(region: mk_region(RegionKind), const_: mk_const(Const<'tcx>));
+direct_interners!(
+ region: mk_region(RegionKind),
+ const_: mk_const(Const<'tcx>),
+ predicate_kind: intern_predicate_kind(PredicateKind<'tcx>),
+);
macro_rules! slice_interners {
($($field:ident: $method:ident($ty:ty)),+) => (
@@ -2100,6 +2114,12 @@
self.interners.intern_ty(st)
}
+ #[inline]
+ pub fn mk_predicate(&self, kind: PredicateKind<'tcx>) -> Predicate<'tcx> {
+ let kind = self.intern_predicate_kind(kind);
+ Predicate { kind }
+ }
+
pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> {
match tm {
ast::IntTy::Isize => self.types.isize,
diff --git a/src/librustc_middle/ty/error.rs b/src/librustc_middle/ty/error.rs
index cf63a65..480420d 100644
--- a/src/librustc_middle/ty/error.rs
+++ b/src/librustc_middle/ty/error.rs
@@ -815,19 +815,18 @@
for item in &items[..] {
match item.kind {
hir::AssocItemKind::Type | hir::AssocItemKind::OpaqueTy => {
- if self.type_of(self.hir().local_def_id(item.id.hir_id)) == found {
- if let hir::Defaultness::Default { has_value: true } =
- item.defaultness
- {
+ // FIXME: account for returning some type in a trait fn impl that has
+ // an assoc type as a return type (#72076).
+ if let hir::Defaultness::Default { has_value: true } = item.defaultness
+ {
+ if self.type_of(self.hir().local_def_id(item.id.hir_id)) == found {
db.span_label(
item.span,
"associated type defaults can't be assumed inside the \
trait defining them",
);
- } else {
- db.span_label(item.span, "expected this associated type");
+ return true;
}
- return true;
}
}
_ => {}
diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs
index 2d49d85..5566e18 100644
--- a/src/librustc_middle/ty/layout.rs
+++ b/src/librustc_middle/ty/layout.rs
@@ -187,7 +187,7 @@
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
) -> Result<&'tcx Layout, LayoutError<'tcx>> {
ty::tls::with_related_context(tcx, move |icx| {
- let rec_limit = *tcx.sess.recursion_limit.get();
+ let rec_limit = tcx.sess.recursion_limit.get().copied().unwrap();
let (param_env, ty) = query.into_parts();
if icx.layout_depth > rec_limit {
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index 36bc44f..9e84566 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -1016,9 +1016,30 @@
}
}
+#[derive(Clone, Copy, Hash, RustcEncodable, RustcDecodable, Lift)]
+#[derive(HashStable)]
+pub struct Predicate<'tcx> {
+ kind: &'tcx PredicateKind<'tcx>,
+}
+
+impl<'tcx> PartialEq for Predicate<'tcx> {
+ fn eq(&self, other: &Self) -> bool {
+ // `self.kind` is always interned.
+ ptr::eq(self.kind, other.kind)
+ }
+}
+
+impl<'tcx> Eq for Predicate<'tcx> {}
+
+impl<'tcx> Predicate<'tcx> {
+ pub fn kind(self) -> &'tcx PredicateKind<'tcx> {
+ self.kind
+ }
+}
+
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
#[derive(HashStable, TypeFoldable)]
-pub enum Predicate<'tcx> {
+pub enum PredicateKind<'tcx> {
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
/// the `Self` type of the trait reference and `A`, `B`, and `C`
/// would be the type parameters.
@@ -1086,7 +1107,7 @@
/// substitution in terms of what happens with bound regions. See
/// lengthy comment below for details.
pub fn subst_supertrait(
- &self,
+ self,
tcx: TyCtxt<'tcx>,
trait_ref: &ty::PolyTraitRef<'tcx>,
) -> ty::Predicate<'tcx> {
@@ -1151,34 +1172,36 @@
// this trick achieves that).
let substs = &trait_ref.skip_binder().substs;
- match *self {
- Predicate::Trait(ref binder, constness) => {
- Predicate::Trait(binder.map_bound(|data| data.subst(tcx, substs)), constness)
+ let predicate = match self.kind() {
+ &PredicateKind::Trait(ref binder, constness) => {
+ PredicateKind::Trait(binder.map_bound(|data| data.subst(tcx, substs)), constness)
}
- Predicate::Subtype(ref binder) => {
- Predicate::Subtype(binder.map_bound(|data| data.subst(tcx, substs)))
+ PredicateKind::Subtype(binder) => {
+ PredicateKind::Subtype(binder.map_bound(|data| data.subst(tcx, substs)))
}
- Predicate::RegionOutlives(ref binder) => {
- Predicate::RegionOutlives(binder.map_bound(|data| data.subst(tcx, substs)))
+ PredicateKind::RegionOutlives(binder) => {
+ PredicateKind::RegionOutlives(binder.map_bound(|data| data.subst(tcx, substs)))
}
- Predicate::TypeOutlives(ref binder) => {
- Predicate::TypeOutlives(binder.map_bound(|data| data.subst(tcx, substs)))
+ PredicateKind::TypeOutlives(binder) => {
+ PredicateKind::TypeOutlives(binder.map_bound(|data| data.subst(tcx, substs)))
}
- Predicate::Projection(ref binder) => {
- Predicate::Projection(binder.map_bound(|data| data.subst(tcx, substs)))
+ PredicateKind::Projection(binder) => {
+ PredicateKind::Projection(binder.map_bound(|data| data.subst(tcx, substs)))
}
- Predicate::WellFormed(data) => Predicate::WellFormed(data.subst(tcx, substs)),
- Predicate::ObjectSafe(trait_def_id) => Predicate::ObjectSafe(trait_def_id),
- Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
- Predicate::ClosureKind(closure_def_id, closure_substs.subst(tcx, substs), kind)
+ &PredicateKind::WellFormed(data) => PredicateKind::WellFormed(data.subst(tcx, substs)),
+ &PredicateKind::ObjectSafe(trait_def_id) => PredicateKind::ObjectSafe(trait_def_id),
+ &PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
+ PredicateKind::ClosureKind(closure_def_id, closure_substs.subst(tcx, substs), kind)
}
- Predicate::ConstEvaluatable(def_id, const_substs) => {
- Predicate::ConstEvaluatable(def_id, const_substs.subst(tcx, substs))
+ &PredicateKind::ConstEvaluatable(def_id, const_substs) => {
+ PredicateKind::ConstEvaluatable(def_id, const_substs.subst(tcx, substs))
}
- Predicate::ConstEquate(c1, c2) => {
- Predicate::ConstEquate(c1.subst(tcx, substs), c2.subst(tcx, substs))
+ PredicateKind::ConstEquate(c1, c2) => {
+ PredicateKind::ConstEquate(c1.subst(tcx, substs), c2.subst(tcx, substs))
}
- }
+ };
+
+ predicate.to_predicate(tcx)
}
}
@@ -1293,85 +1316,95 @@
}
pub trait ToPredicate<'tcx> {
- fn to_predicate(&self) -> Predicate<'tcx>;
+ fn to_predicate(&self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>;
+}
+
+impl ToPredicate<'tcx> for PredicateKind<'tcx> {
+ fn to_predicate(&self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ tcx.mk_predicate(*self)
+ }
}
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<TraitRef<'tcx>> {
- fn to_predicate(&self) -> Predicate<'tcx> {
- ty::Predicate::Trait(
+ fn to_predicate(&self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ ty::PredicateKind::Trait(
ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value }),
self.constness,
)
+ .to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<&TraitRef<'tcx>> {
- fn to_predicate(&self) -> Predicate<'tcx> {
- ty::Predicate::Trait(
+ fn to_predicate(&self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ ty::PredicateKind::Trait(
ty::Binder::dummy(ty::TraitPredicate { trait_ref: *self.value }),
self.constness,
)
+ .to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitRef<'tcx>> {
- fn to_predicate(&self) -> Predicate<'tcx> {
- ty::Predicate::Trait(self.value.to_poly_trait_predicate(), self.constness)
+ fn to_predicate(&self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ ty::PredicateKind::Trait(self.value.to_poly_trait_predicate(), self.constness)
+ .to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<&PolyTraitRef<'tcx>> {
- fn to_predicate(&self) -> Predicate<'tcx> {
- ty::Predicate::Trait(self.value.to_poly_trait_predicate(), self.constness)
+ fn to_predicate(&self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ ty::PredicateKind::Trait(self.value.to_poly_trait_predicate(), self.constness)
+ .to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
- fn to_predicate(&self) -> Predicate<'tcx> {
- Predicate::RegionOutlives(*self)
+ fn to_predicate(&self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ PredicateKind::RegionOutlives(*self).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
- fn to_predicate(&self) -> Predicate<'tcx> {
- Predicate::TypeOutlives(*self)
+ fn to_predicate(&self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ PredicateKind::TypeOutlives(*self).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
- fn to_predicate(&self) -> Predicate<'tcx> {
- Predicate::Projection(*self)
+ fn to_predicate(&self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ PredicateKind::Projection(*self).to_predicate(tcx)
}
}
impl<'tcx> Predicate<'tcx> {
- pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> {
- match *self {
- Predicate::Trait(ref t, _) => Some(t.to_poly_trait_ref()),
- Predicate::Projection(..)
- | Predicate::Subtype(..)
- | Predicate::RegionOutlives(..)
- | Predicate::WellFormed(..)
- | Predicate::ObjectSafe(..)
- | Predicate::ClosureKind(..)
- | Predicate::TypeOutlives(..)
- | Predicate::ConstEvaluatable(..)
- | Predicate::ConstEquate(..) => None,
+ pub fn to_opt_poly_trait_ref(self) -> Option<PolyTraitRef<'tcx>> {
+ match self.kind() {
+ &PredicateKind::Trait(ref t, _) => Some(t.to_poly_trait_ref()),
+ PredicateKind::Projection(..)
+ | PredicateKind::Subtype(..)
+ | PredicateKind::RegionOutlives(..)
+ | PredicateKind::WellFormed(..)
+ | PredicateKind::ObjectSafe(..)
+ | PredicateKind::ClosureKind(..)
+ | PredicateKind::TypeOutlives(..)
+ | PredicateKind::ConstEvaluatable(..)
+ | PredicateKind::ConstEquate(..) => None,
}
}
- pub fn to_opt_type_outlives(&self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
- match *self {
- Predicate::TypeOutlives(data) => Some(data),
- Predicate::Trait(..)
- | Predicate::Projection(..)
- | Predicate::Subtype(..)
- | Predicate::RegionOutlives(..)
- | Predicate::WellFormed(..)
- | Predicate::ObjectSafe(..)
- | Predicate::ClosureKind(..)
- | Predicate::ConstEvaluatable(..)
- | Predicate::ConstEquate(..) => None,
+ pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
+ match self.kind() {
+ &PredicateKind::TypeOutlives(data) => Some(data),
+ PredicateKind::Trait(..)
+ | PredicateKind::Projection(..)
+ | PredicateKind::Subtype(..)
+ | PredicateKind::RegionOutlives(..)
+ | PredicateKind::WellFormed(..)
+ | PredicateKind::ObjectSafe(..)
+ | PredicateKind::ClosureKind(..)
+ | PredicateKind::ConstEvaluatable(..)
+ | PredicateKind::ConstEquate(..) => None,
}
}
}
@@ -1617,7 +1650,7 @@
pub value: T,
}
-// FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate()` to ensure that
+// FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that
// the constness of trait bounds is being propagated correctly.
pub trait WithConstness: Sized {
#[inline]
diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs
index 2502a4a..f03d91a 100644
--- a/src/librustc_middle/ty/print/pretty.rs
+++ b/src/librustc_middle/ty/print/pretty.rs
@@ -1,5 +1,4 @@
use crate::middle::cstore::{ExternCrate, ExternCrateSource};
-use crate::middle::region;
use crate::mir::interpret::{sign_extend, truncate, AllocId, ConstValue, Pointer, Scalar};
use crate::ty::layout::IntegerExt;
use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
@@ -1588,9 +1587,9 @@
false
}
- ty::ReScope(_) | ty::ReVar(_) if identify_regions => true,
+ ty::ReVar(_) if identify_regions => true,
- ty::ReVar(_) | ty::ReScope(_) | ty::ReErased => false,
+ ty::ReVar(_) | ty::ReErased => false,
ty::ReStatic | ty::ReEmpty(_) => true,
}
@@ -1666,32 +1665,12 @@
}
}
}
- ty::ReScope(scope) if identify_regions => {
- match scope.data {
- region::ScopeData::Node => p!(write("'{}s", scope.item_local_id().as_usize())),
- region::ScopeData::CallSite => {
- p!(write("'{}cs", scope.item_local_id().as_usize()))
- }
- region::ScopeData::Arguments => {
- p!(write("'{}as", scope.item_local_id().as_usize()))
- }
- region::ScopeData::Destruction => {
- p!(write("'{}ds", scope.item_local_id().as_usize()))
- }
- region::ScopeData::Remainder(first_statement_index) => p!(write(
- "'{}_{}rs",
- scope.item_local_id().as_usize(),
- first_statement_index.index()
- )),
- }
- return Ok(self);
- }
ty::ReVar(region_vid) if identify_regions => {
p!(write("{:?}", region_vid));
return Ok(self);
}
ty::ReVar(_) => {}
- ty::ReScope(_) | ty::ReErased => {}
+ ty::ReErased => {}
ty::ReStatic => {
p!(write("'static"));
return Ok(self);
@@ -2031,34 +2010,34 @@
}
ty::Predicate<'tcx> {
- match *self {
- ty::Predicate::Trait(ref data, constness) => {
+ match self.kind() {
+ &ty::PredicateKind::Trait(ref data, constness) => {
if let hir::Constness::Const = constness {
p!(write("const "));
}
p!(print(data))
}
- ty::Predicate::Subtype(ref predicate) => p!(print(predicate)),
- ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)),
- ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)),
- ty::Predicate::Projection(ref predicate) => p!(print(predicate)),
- ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")),
- ty::Predicate::ObjectSafe(trait_def_id) => {
+ ty::PredicateKind::Subtype(predicate) => p!(print(predicate)),
+ ty::PredicateKind::RegionOutlives(predicate) => p!(print(predicate)),
+ ty::PredicateKind::TypeOutlives(predicate) => p!(print(predicate)),
+ ty::PredicateKind::Projection(predicate) => p!(print(predicate)),
+ ty::PredicateKind::WellFormed(ty) => p!(print(ty), write(" well-formed")),
+ &ty::PredicateKind::ObjectSafe(trait_def_id) => {
p!(write("the trait `"),
print_def_path(trait_def_id, &[]),
write("` is object-safe"))
}
- ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => {
+ &ty::PredicateKind::ClosureKind(closure_def_id, _closure_substs, kind) => {
p!(write("the closure `"),
print_value_path(closure_def_id, &[]),
write("` implements the trait `{}`", kind))
}
- ty::Predicate::ConstEvaluatable(def_id, substs) => {
+ &ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
p!(write("the constant `"),
print_value_path(def_id, substs),
write("` can be evaluated"))
}
- ty::Predicate::ConstEquate(c1, c2) => {
+ ty::PredicateKind::ConstEquate(c1, c2) => {
p!(write("the constant `"),
print(c1),
write("` equals `"),
diff --git a/src/librustc_middle/ty/query/mod.rs b/src/librustc_middle/ty/query/mod.rs
index e1a5a76..f61fc65 100644
--- a/src/librustc_middle/ty/query/mod.rs
+++ b/src/librustc_middle/ty/query/mod.rs
@@ -4,8 +4,8 @@
use crate::infer::canonical::{self, Canonical};
use crate::lint::LintLevelMap;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
-use crate::middle::cstore::{CrateSource, DepKind, NativeLibraryKind};
-use crate::middle::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLibrary};
+use crate::middle::cstore::{CrateSource, DepKind};
+use crate::middle::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use crate::middle::lib_features::LibFeatures;
use crate::middle::privacy::AccessLevels;
@@ -46,6 +46,7 @@
use rustc_hir::{Crate, HirIdSet, ItemLocalId, TraitCandidate};
use rustc_index::vec::IndexVec;
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
+use rustc_session::utils::NativeLibKind;
use rustc_session::CrateDisambiguator;
use rustc_target::spec::PanicStrategy;
diff --git a/src/librustc_middle/ty/query/on_disk_cache.rs b/src/librustc_middle/ty/query/on_disk_cache.rs
index 71c2c24..4eae067 100644
--- a/src/librustc_middle/ty/query/on_disk_cache.rs
+++ b/src/librustc_middle/ty/query/on_disk_cache.rs
@@ -6,7 +6,7 @@
use crate::ty::{self, Ty};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, Once};
+use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
@@ -49,7 +49,7 @@
current_diagnostics: Lock<FxHashMap<DepNodeIndex, Vec<Diagnostic>>>,
prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
- cnum_map: Once<IndexVec<CrateNum, Option<CrateNum>>>,
+ cnum_map: OnceCell<IndexVec<CrateNum, Option<CrateNum>>>,
source_map: &'sess SourceMap,
file_index_to_stable_id: FxHashMap<SourceFileIndex, StableSourceFileId>,
@@ -128,7 +128,7 @@
file_index_to_stable_id: footer.file_index_to_stable_id,
file_index_to_file: Default::default(),
prev_cnums: footer.prev_cnums,
- cnum_map: Once::new(),
+ cnum_map: OnceCell::new(),
source_map: sess.source_map(),
current_diagnostics: Default::default(),
query_result_index: footer.query_result_index.into_iter().collect(),
@@ -144,7 +144,7 @@
file_index_to_stable_id: Default::default(),
file_index_to_file: Default::default(),
prev_cnums: vec![],
- cnum_map: Once::new(),
+ cnum_map: OnceCell::new(),
source_map,
current_diagnostics: Default::default(),
query_result_index: Default::default(),
@@ -370,14 +370,14 @@
{
let pos = index.get(&dep_node_index).cloned()?;
- // Initialize `cnum_map` using the value from the thread that finishes the closure first.
- self.cnum_map.init_nonlocking_same(|| Self::compute_cnum_map(tcx, &self.prev_cnums[..]));
+ let cnum_map =
+ self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx, &self.prev_cnums[..]));
let mut decoder = CacheDecoder {
tcx,
opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()),
source_map: self.source_map,
- cnum_map: self.cnum_map.get(),
+ cnum_map,
synthetic_syntax_contexts: &self.synthetic_syntax_contexts,
file_index_to_file: &self.file_index_to_file,
file_index_to_stable_id: &self.file_index_to_stable_id,
diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs
index c23a351..569a8d9 100644
--- a/src/librustc_middle/ty/structural_impls.rs
+++ b/src/librustc_middle/ty/structural_impls.rs
@@ -87,8 +87,6 @@
ty::ReFree(ref fr) => fr.fmt(f),
- ty::ReScope(id) => write!(f, "ReScope({:?})", id),
-
ty::ReStatic => write!(f, "ReStatic"),
ty::ReVar(ref vid) => vid.fmt(f),
@@ -221,26 +219,34 @@
impl fmt::Debug for ty::Predicate<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{:?}", self.kind())
+ }
+}
+
+impl fmt::Debug for ty::PredicateKind<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
- ty::Predicate::Trait(ref a, constness) => {
+ ty::PredicateKind::Trait(ref a, constness) => {
if let hir::Constness::Const = constness {
write!(f, "const ")?;
}
a.fmt(f)
}
- ty::Predicate::Subtype(ref pair) => pair.fmt(f),
- ty::Predicate::RegionOutlives(ref pair) => pair.fmt(f),
- ty::Predicate::TypeOutlives(ref pair) => pair.fmt(f),
- ty::Predicate::Projection(ref pair) => pair.fmt(f),
- ty::Predicate::WellFormed(ty) => write!(f, "WellFormed({:?})", ty),
- ty::Predicate::ObjectSafe(trait_def_id) => write!(f, "ObjectSafe({:?})", trait_def_id),
- ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
+ ty::PredicateKind::Subtype(ref pair) => pair.fmt(f),
+ ty::PredicateKind::RegionOutlives(ref pair) => pair.fmt(f),
+ ty::PredicateKind::TypeOutlives(ref pair) => pair.fmt(f),
+ ty::PredicateKind::Projection(ref pair) => pair.fmt(f),
+ ty::PredicateKind::WellFormed(ty) => write!(f, "WellFormed({:?})", ty),
+ ty::PredicateKind::ObjectSafe(trait_def_id) => {
+ write!(f, "ObjectSafe({:?})", trait_def_id)
+ }
+ ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
}
- ty::Predicate::ConstEvaluatable(def_id, substs) => {
+ ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs)
}
- ty::Predicate::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
+ ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
}
}
}
@@ -467,37 +473,39 @@
}
}
-impl<'a, 'tcx> Lift<'tcx> for ty::Predicate<'a> {
- type Lifted = ty::Predicate<'tcx>;
+impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> {
+ type Lifted = ty::PredicateKind<'tcx>;
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
match *self {
- ty::Predicate::Trait(ref binder, constness) => {
- tcx.lift(binder).map(|binder| ty::Predicate::Trait(binder, constness))
+ ty::PredicateKind::Trait(ref binder, constness) => {
+ tcx.lift(binder).map(|binder| ty::PredicateKind::Trait(binder, constness))
}
- ty::Predicate::Subtype(ref binder) => tcx.lift(binder).map(ty::Predicate::Subtype),
- ty::Predicate::RegionOutlives(ref binder) => {
- tcx.lift(binder).map(ty::Predicate::RegionOutlives)
+ ty::PredicateKind::Subtype(ref binder) => {
+ tcx.lift(binder).map(ty::PredicateKind::Subtype)
}
- ty::Predicate::TypeOutlives(ref binder) => {
- tcx.lift(binder).map(ty::Predicate::TypeOutlives)
+ ty::PredicateKind::RegionOutlives(ref binder) => {
+ tcx.lift(binder).map(ty::PredicateKind::RegionOutlives)
}
- ty::Predicate::Projection(ref binder) => {
- tcx.lift(binder).map(ty::Predicate::Projection)
+ ty::PredicateKind::TypeOutlives(ref binder) => {
+ tcx.lift(binder).map(ty::PredicateKind::TypeOutlives)
}
- ty::Predicate::WellFormed(ty) => tcx.lift(&ty).map(ty::Predicate::WellFormed),
- ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
+ ty::PredicateKind::Projection(ref binder) => {
+ tcx.lift(binder).map(ty::PredicateKind::Projection)
+ }
+ ty::PredicateKind::WellFormed(ty) => tcx.lift(&ty).map(ty::PredicateKind::WellFormed),
+ ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
tcx.lift(&closure_substs).map(|closure_substs| {
- ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind)
+ ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind)
})
}
- ty::Predicate::ObjectSafe(trait_def_id) => {
- Some(ty::Predicate::ObjectSafe(trait_def_id))
+ ty::PredicateKind::ObjectSafe(trait_def_id) => {
+ Some(ty::PredicateKind::ObjectSafe(trait_def_id))
}
- ty::Predicate::ConstEvaluatable(def_id, substs) => {
- tcx.lift(&substs).map(|substs| ty::Predicate::ConstEvaluatable(def_id, substs))
+ ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
+ tcx.lift(&substs).map(|substs| ty::PredicateKind::ConstEvaluatable(def_id, substs))
}
- ty::Predicate::ConstEquate(c1, c2) => {
- tcx.lift(&(c1, c2)).map(|(c1, c2)| ty::Predicate::ConstEquate(c1, c2))
+ ty::PredicateKind::ConstEquate(c1, c2) => {
+ tcx.lift(&(c1, c2)).map(|(c1, c2)| ty::PredicateKind::ConstEquate(c1, c2))
}
}
}
@@ -977,6 +985,16 @@
}
}
+impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
+ fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
+ folder.tcx().mk_predicate(ty::PredicateKind::super_fold_with(self.kind, folder))
+ }
+
+ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+ ty::PredicateKind::super_visit_with(self.kind, visitor)
+ }
+}
+
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
fold_list(*self, folder, |tcx, v| tcx.intern_predicates(v))
diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index 2ad673b..370702f 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -6,7 +6,6 @@
use self::TyKind::*;
use crate::infer::canonical::Canonical;
-use crate::middle::region;
use crate::mir::interpret::ConstValue;
use crate::mir::interpret::{LitToConstInput, Scalar};
use crate::mir::Promoted;
@@ -612,15 +611,16 @@
use crate::ty::ToPredicate;
match *self.skip_binder() {
ExistentialPredicate::Trait(tr) => {
- Binder(tr).with_self_ty(tcx, self_ty).without_const().to_predicate()
+ Binder(tr).with_self_ty(tcx, self_ty).without_const().to_predicate(tcx)
}
ExistentialPredicate::Projection(p) => {
- ty::Predicate::Projection(Binder(p.with_self_ty(tcx, self_ty)))
+ ty::PredicateKind::Projection(Binder(p.with_self_ty(tcx, self_ty)))
+ .to_predicate(tcx)
}
ExistentialPredicate::AutoTrait(did) => {
let trait_ref =
Binder(ty::TraitRef { def_id: did, substs: tcx.mk_substs_trait(self_ty, &[]) });
- trait_ref.without_const().to_predicate()
+ trait_ref.without_const().to_predicate(tcx)
}
}
}
@@ -1178,17 +1178,15 @@
pub type Region<'tcx> = &'tcx RegionKind;
-/// Representation of (lexical) regions. Note that the NLL checker
-/// uses a distinct representation of regions. For this reason, it
-/// internally replaces all the regions with inference variables --
-/// the index of the variable is then used to index into internal NLL
-/// data structures. See `rustc_mir::borrow_check` module for more
-/// information.
+/// Representation of regions. Note that the NLL checker uses a distinct
+/// representation of regions. For this reason, it internally replaces all the
+/// regions with inference variables -- the index of the variable is then used
+/// to index into internal NLL data structures. See `rustc_mir::borrow_check`
+/// module for more information.
///
/// ## The Region lattice within a given function
///
-/// In general, the (lexical, and hence deprecated) region lattice
-/// looks like
+/// In general, the region lattice looks like
///
/// ```
/// static ----------+-----...------+ (greatest)
@@ -1196,7 +1194,6 @@
/// early-bound and | |
/// free regions | |
/// | | |
-/// scope regions | |
/// | | |
/// empty(root) placeholder(U1) |
/// | / |
@@ -1211,13 +1208,7 @@
/// Early-bound/free regions are the named lifetimes in scope from the
/// function declaration. They have relationships to one another
/// determined based on the declared relationships from the
-/// function. They all collectively outlive the scope regions. (See
-/// `RegionRelations` type, and particularly
-/// `crate::infer::outlives::free_region_map::FreeRegionMap`.)
-///
-/// The scope regions are related to one another based on the AST
-/// structure. (See `RegionRelations` type, and particularly the
-/// `rustc_middle::middle::region::ScopeTree`.)
+/// function.
///
/// Note that inference variables and bound regions are not included
/// in this diagram. In the case of inference variables, they should
@@ -1306,11 +1297,6 @@
/// region parameters.
ReFree(FreeRegion),
- /// A concrete region naming some statically determined scope
- /// (e.g., an expression or sequence of statements) within the
- /// current function.
- ReScope(region::Scope),
-
/// Static data that has an "infinite" lifetime. Top in the region lattice.
ReStatic,
@@ -1534,7 +1520,6 @@
RegionKind::ReEarlyBound(ebr) => ebr.has_name(),
RegionKind::ReLateBound(_, br) => br.is_named(),
RegionKind::ReFree(fr) => fr.bound_region.is_named(),
- RegionKind::ReScope(..) => false,
RegionKind::ReStatic => true,
RegionKind::ReVar(..) => false,
RegionKind::RePlaceholder(placeholder) => placeholder.name.is_named(),
@@ -1615,7 +1600,7 @@
flags = flags | TypeFlags::HAS_RE_PARAM;
flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE;
}
- ty::ReFree { .. } | ty::ReScope { .. } => {
+ ty::ReFree { .. } => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
}
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index 98c0542..e19fab8 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -162,10 +162,8 @@
let type_test_span = type_test.locations.span(&self.body);
if let Some(lower_bound_region) = lower_bound_region {
- let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
self.infcx
.construct_generic_bound_failure(
- region_scope_tree,
type_test_span,
None,
type_test.generic_kind,
@@ -194,12 +192,10 @@
}
RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, member_region } => {
- let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
unexpected_hidden_region_diagnostic(
self.infcx.tcx,
- Some(region_scope_tree),
span,
named_ty,
named_region,
@@ -576,7 +572,7 @@
let mut found = false;
for predicate in bounds.predicates {
- if let ty::Predicate::TypeOutlives(binder) = predicate {
+ if let ty::PredicateKind::TypeOutlives(binder) = predicate.kind() {
if let ty::OutlivesPredicate(_, ty::RegionKind::ReStatic) =
binder.skip_binder()
{
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
index 37e2e04..e912ef7 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_name.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
@@ -284,7 +284,6 @@
},
ty::ReLateBound(..)
- | ty::ReScope(..)
| ty::ReVar(..)
| ty::RePlaceholder(..)
| ty::ReEmpty(_)
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index 08aa434..bdbce1d 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -27,8 +27,8 @@
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef, UserSubsts};
use rustc_middle::ty::{
- self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, RegionVid, ToPolyTraitRef, Ty,
- TyCtxt, UserType, UserTypeAnnotationIndex,
+ self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, RegionVid, ToPolyTraitRef,
+ ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::VariantIdx;
@@ -1016,7 +1016,7 @@
}
self.prove_predicate(
- ty::Predicate::WellFormed(inferred_ty),
+ ty::PredicateKind::WellFormed(inferred_ty).to_predicate(self.tcx()),
Locations::All(span),
ConstraintCategory::TypeAnnotation,
);
@@ -1268,7 +1268,7 @@
obligations.obligations.push(traits::Obligation::new(
ObligationCause::dummy(),
param_env,
- ty::Predicate::WellFormed(revealed_ty),
+ ty::PredicateKind::WellFormed(revealed_ty).to_predicate(infcx.tcx),
));
obligations.add(
infcx
@@ -1612,7 +1612,7 @@
self.check_call_dest(body, term, &sig, destination, term_location);
self.prove_predicates(
- sig.inputs_and_output.iter().map(|ty| ty::Predicate::WellFormed(ty)),
+ sig.inputs_and_output.iter().map(|ty| ty::PredicateKind::WellFormed(ty)),
term_location.to_locations(),
ConstraintCategory::Boring,
);
@@ -2017,7 +2017,7 @@
traits::ObligationCauseCode::RepeatVec(should_suggest),
),
self.param_env,
- ty::Predicate::Trait(
+ ty::PredicateKind::Trait(
ty::Binder::bind(ty::TraitPredicate {
trait_ref: ty::TraitRef::new(
self.tcx().require_lang_item(
@@ -2028,7 +2028,8 @@
),
}),
hir::Constness::NotConst,
- ),
+ )
+ .to_predicate(self.tcx()),
),
&traits::SelectionError::Unimplemented,
false,
@@ -2686,7 +2687,7 @@
category: ConstraintCategory,
) {
self.prove_predicates(
- Some(ty::Predicate::Trait(
+ Some(ty::PredicateKind::Trait(
trait_ref.to_poly_trait_ref().to_poly_trait_predicate(),
hir::Constness::NotConst,
)),
@@ -2708,11 +2709,12 @@
fn prove_predicates(
&mut self,
- predicates: impl IntoIterator<Item = ty::Predicate<'tcx>>,
+ predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
locations: Locations,
category: ConstraintCategory,
) {
for predicate in predicates {
+ let predicate = predicate.to_predicate(self.tcx());
debug!("prove_predicates(predicate={:?}, locations={:?})", predicate, locations,);
self.prove_predicate(predicate, locations, category);
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index 0637ebf..fd5e063 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -89,7 +89,7 @@
InterpCx::new(
tcx.at(span),
param_env,
- CompileTimeInterpreter::new(*tcx.sess.const_eval_limit.get()),
+ CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
MemoryExtra { can_access_statics },
)
}
@@ -303,7 +303,7 @@
let mut ecx = InterpCx::new(
tcx.at(span),
key.param_env,
- CompileTimeInterpreter::new(*tcx.sess.const_eval_limit.get()),
+ CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
MemoryExtra { can_access_statics: is_static },
);
diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
index f929b2d..b61dc56 100644
--- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs
+++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
@@ -99,6 +99,9 @@
where
K: BorrowAnalysisKind<'tcx>,
{
+ // The generator transform relies on the fact that this analysis does **not** use "before"
+ // effects.
+
fn statement_effect(
&self,
trans: &mut impl GenKill<Self::Idx>,
diff --git a/src/librustc_mir/dataflow/impls/init_locals.rs b/src/librustc_mir/dataflow/impls/init_locals.rs
new file mode 100644
index 0000000..726330b
--- /dev/null
+++ b/src/librustc_mir/dataflow/impls/init_locals.rs
@@ -0,0 +1,118 @@
+//! A less precise version of `MaybeInitializedPlaces` whose domain is entire locals.
+//!
+//! A local will be maybe initialized if *any* projections of that local might be initialized.
+
+use crate::dataflow::{self, BottomValue, GenKill};
+
+use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::visit::{PlaceContext, Visitor};
+use rustc_middle::mir::{self, BasicBlock, Local, Location};
+
+pub struct MaybeInitializedLocals;
+
+impl BottomValue for MaybeInitializedLocals {
+ /// bottom = uninit
+ const BOTTOM_VALUE: bool = false;
+}
+
+impl dataflow::AnalysisDomain<'tcx> for MaybeInitializedLocals {
+ type Idx = Local;
+
+ const NAME: &'static str = "maybe_init_locals";
+
+ fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize {
+ body.local_decls.len()
+ }
+
+ fn initialize_start_block(&self, body: &mir::Body<'tcx>, entry_set: &mut BitSet<Self::Idx>) {
+ // Function arguments are initialized to begin with.
+ for arg in body.args_iter() {
+ entry_set.insert(arg);
+ }
+ }
+}
+
+impl dataflow::GenKillAnalysis<'tcx> for MaybeInitializedLocals {
+ // The generator transform relies on the fact that this analysis does **not** use "before"
+ // effects.
+
+ fn statement_effect(
+ &self,
+ trans: &mut impl GenKill<Self::Idx>,
+ statement: &mir::Statement<'tcx>,
+ loc: Location,
+ ) {
+ TransferFunction { trans }.visit_statement(statement, loc)
+ }
+
+ fn terminator_effect(
+ &self,
+ trans: &mut impl GenKill<Self::Idx>,
+ terminator: &mir::Terminator<'tcx>,
+ loc: Location,
+ ) {
+ TransferFunction { trans }.visit_terminator(terminator, loc)
+ }
+
+ fn call_return_effect(
+ &self,
+ trans: &mut impl GenKill<Self::Idx>,
+ _block: BasicBlock,
+ _func: &mir::Operand<'tcx>,
+ _args: &[mir::Operand<'tcx>],
+ return_place: mir::Place<'tcx>,
+ ) {
+ trans.gen(return_place.local)
+ }
+
+ /// See `Analysis::apply_yield_resume_effect`.
+ fn yield_resume_effect(
+ &self,
+ trans: &mut impl GenKill<Self::Idx>,
+ _resume_block: BasicBlock,
+ resume_place: mir::Place<'tcx>,
+ ) {
+ trans.gen(resume_place.local)
+ }
+}
+
+struct TransferFunction<'a, T> {
+ trans: &'a mut T,
+}
+
+impl<T> Visitor<'tcx> for TransferFunction<'a, T>
+where
+ T: GenKill<Local>,
+{
+ fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) {
+ use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, NonUseContext};
+ match context {
+ // These are handled specially in `call_return_effect` and `yield_resume_effect`.
+ PlaceContext::MutatingUse(MutatingUseContext::Call | MutatingUseContext::Yield) => {}
+
+ // Otherwise, when a place is mutated, we must consider it possibly initialized.
+ PlaceContext::MutatingUse(_) => self.trans.gen(local),
+
+ // If the local is moved out of, or if it gets marked `StorageDead`, consider it no
+ // longer initialized.
+ PlaceContext::NonUse(NonUseContext::StorageDead)
+ | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => self.trans.kill(local),
+
+ // All other uses do not affect this analysis.
+ PlaceContext::NonUse(
+ NonUseContext::StorageLive
+ | NonUseContext::AscribeUserTy
+ | NonUseContext::VarDebugInfo,
+ )
+ | PlaceContext::NonMutatingUse(
+ NonMutatingUseContext::Inspect
+ | NonMutatingUseContext::Copy
+ | NonMutatingUseContext::SharedBorrow
+ | NonMutatingUseContext::ShallowBorrow
+ | NonMutatingUseContext::UniqueBorrow
+ | NonMutatingUseContext::AddressOf
+ | NonMutatingUseContext::Projection,
+ ) => {}
+ }
+ }
+}
diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs
index e199a17..ed01d6b 100644
--- a/src/librustc_mir/dataflow/impls/mod.rs
+++ b/src/librustc_mir/dataflow/impls/mod.rs
@@ -22,13 +22,15 @@
mod borrowed_locals;
pub(super) mod borrows;
+mod init_locals;
mod liveness;
mod storage_liveness;
pub use self::borrowed_locals::{MaybeBorrowedLocals, MaybeMutBorrowedLocals};
pub use self::borrows::Borrows;
+pub use self::init_locals::MaybeInitializedLocals;
pub use self::liveness::MaybeLiveLocals;
-pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageLive};
+pub use self::storage_liveness::MaybeStorageLive;
/// `MaybeInitializedPlaces` tracks all places that might be
/// initialized upon reaching a particular point in the control flow
diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs
index bbc4942..2a2be06 100644
--- a/src/librustc_mir/dataflow/impls/storage_liveness.rs
+++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs
@@ -1,11 +1,9 @@
pub use super::*;
use crate::dataflow::BottomValue;
-use crate::dataflow::{self, GenKill, Results, ResultsRefCursor};
+use crate::dataflow::{self, GenKill};
use crate::util::storage::AlwaysLiveLocals;
-use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
-use std::cell::RefCell;
#[derive(Clone)]
pub struct MaybeStorageLive {
@@ -78,233 +76,3 @@
/// bottom = dead
const BOTTOM_VALUE: bool = false;
}
-
-type BorrowedLocalsResults<'a, 'tcx> = ResultsRefCursor<'a, 'a, 'tcx, MaybeBorrowedLocals>;
-
-/// 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 MaybeRequiresStorage<'mir, 'tcx> {
- body: &'mir Body<'tcx>,
- borrowed_locals: RefCell<BorrowedLocalsResults<'mir, 'tcx>>,
-}
-
-impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> {
- pub fn new(
- body: &'mir Body<'tcx>,
- borrowed_locals: &'mir Results<'tcx, MaybeBorrowedLocals>,
- ) -> Self {
- MaybeRequiresStorage {
- body,
- borrowed_locals: RefCell::new(ResultsRefCursor::new(&body, borrowed_locals)),
- }
- }
-}
-
-impl<'mir, 'tcx> dataflow::AnalysisDomain<'tcx> for MaybeRequiresStorage<'mir, 'tcx> {
- type Idx = Local;
-
- const NAME: &'static str = "requires_storage";
-
- fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize {
- body.local_decls.len()
- }
-
- fn initialize_start_block(&self, body: &mir::Body<'tcx>, on_entry: &mut BitSet<Self::Idx>) {
- // The resume argument is live on function entry (we don't care about
- // the `self` argument)
- for arg in body.args_iter().skip(1) {
- on_entry.insert(arg);
- }
- }
-}
-
-impl<'mir, 'tcx> dataflow::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tcx> {
- fn before_statement_effect(
- &self,
- trans: &mut impl GenKill<Self::Idx>,
- stmt: &mir::Statement<'tcx>,
- loc: Location,
- ) {
- // If a place is borrowed in a statement, it needs storage for that statement.
- self.borrowed_locals.borrow().analysis().statement_effect(trans, stmt, loc);
-
- match &stmt.kind {
- StatementKind::StorageDead(l) => trans.kill(*l),
-
- // If a place is assigned to in a statement, it needs storage for that statement.
- StatementKind::Assign(box (place, _))
- | StatementKind::SetDiscriminant { box place, .. } => {
- trans.gen(place.local);
- }
- StatementKind::LlvmInlineAsm(asm) => {
- for place in &*asm.outputs {
- trans.gen(place.local);
- }
- }
-
- // Nothing to do for these. Match exhaustively so this fails to compile when new
- // variants are added.
- StatementKind::AscribeUserType(..)
- | StatementKind::FakeRead(..)
- | StatementKind::Nop
- | StatementKind::Retag(..)
- | StatementKind::StorageLive(..) => {}
- }
- }
-
- fn statement_effect(
- &self,
- trans: &mut impl GenKill<Self::Idx>,
- _: &mir::Statement<'tcx>,
- loc: Location,
- ) {
- // If we move from a place then only stops needing storage *after*
- // that statement.
- self.check_for_move(trans, loc);
- }
-
- fn before_terminator_effect(
- &self,
- trans: &mut impl GenKill<Self::Idx>,
- terminator: &mir::Terminator<'tcx>,
- loc: Location,
- ) {
- // If a place is borrowed in a terminator, it needs storage for that terminator.
- self.borrowed_locals.borrow().analysis().terminator_effect(trans, terminator, loc);
-
- match &terminator.kind {
- TerminatorKind::Call { destination: Some((place, _)), .. } => {
- trans.gen(place.local);
- }
-
- // Note that we do *not* gen the `resume_arg` of `Yield` terminators. The reason for
- // that is that a `yield` will return from the function, and `resume_arg` is written
- // only when the generator is later resumed. Unlike `Call`, this doesn't require the
- // place to have storage *before* the yield, only after.
- TerminatorKind::Yield { .. } => {}
-
- TerminatorKind::InlineAsm { operands, .. } => {
- for op in operands {
- match op {
- InlineAsmOperand::Out { place, .. }
- | InlineAsmOperand::InOut { out_place: place, .. } => {
- if let Some(place) = place {
- trans.gen(place.local);
- }
- }
- InlineAsmOperand::In { .. }
- | InlineAsmOperand::Const { .. }
- | InlineAsmOperand::SymFn { .. }
- | InlineAsmOperand::SymStatic { .. } => {}
- }
- }
- }
-
- // Nothing to do for these. Match exhaustively so this fails to compile when new
- // variants are added.
- TerminatorKind::Call { destination: None, .. }
- | TerminatorKind::Abort
- | TerminatorKind::Assert { .. }
- | TerminatorKind::Drop { .. }
- | TerminatorKind::DropAndReplace { .. }
- | TerminatorKind::FalseEdges { .. }
- | TerminatorKind::FalseUnwind { .. }
- | TerminatorKind::GeneratorDrop
- | TerminatorKind::Goto { .. }
- | TerminatorKind::Resume
- | TerminatorKind::Return
- | TerminatorKind::SwitchInt { .. }
- | TerminatorKind::Unreachable => {}
- }
- }
-
- fn terminator_effect(
- &self,
- trans: &mut impl GenKill<Self::Idx>,
- terminator: &mir::Terminator<'tcx>,
- loc: Location,
- ) {
- match &terminator.kind {
- // For call terminators the destination requires storage for the call
- // and after the call returns successfully, but not after a panic.
- // Since `propagate_call_unwind` doesn't exist, we have to kill the
- // destination here, and then gen it again in `call_return_effect`.
- TerminatorKind::Call { destination: Some((place, _)), .. } => {
- trans.kill(place.local);
- }
-
- // Nothing to do for these. Match exhaustively so this fails to compile when new
- // variants are added.
- TerminatorKind::Call { destination: None, .. }
- | TerminatorKind::Yield { .. }
- | TerminatorKind::Abort
- | TerminatorKind::Assert { .. }
- | TerminatorKind::Drop { .. }
- | TerminatorKind::DropAndReplace { .. }
- | TerminatorKind::FalseEdges { .. }
- | TerminatorKind::FalseUnwind { .. }
- | TerminatorKind::GeneratorDrop
- | TerminatorKind::Goto { .. }
- | TerminatorKind::InlineAsm { .. }
- | TerminatorKind::Resume
- | TerminatorKind::Return
- | TerminatorKind::SwitchInt { .. }
- | TerminatorKind::Unreachable => {}
- }
-
- self.check_for_move(trans, loc);
- }
-
- fn call_return_effect(
- &self,
- trans: &mut impl GenKill<Self::Idx>,
- _block: BasicBlock,
- _func: &mir::Operand<'tcx>,
- _args: &[mir::Operand<'tcx>],
- return_place: mir::Place<'tcx>,
- ) {
- trans.gen(return_place.local);
- }
-
- fn yield_resume_effect(
- &self,
- trans: &mut impl GenKill<Self::Idx>,
- _resume_block: BasicBlock,
- resume_place: mir::Place<'tcx>,
- ) {
- trans.gen(resume_place.local);
- }
-}
-
-impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> {
- /// Kill locals that are fully moved and have not been borrowed.
- fn check_for_move(&self, trans: &mut impl GenKill<Local>, loc: Location) {
- let mut visitor = MoveVisitor { trans, borrowed_locals: &self.borrowed_locals };
- visitor.visit_location(&self.body, loc);
- }
-}
-
-impl<'mir, 'tcx> BottomValue for MaybeRequiresStorage<'mir, 'tcx> {
- /// bottom = dead
- const BOTTOM_VALUE: bool = false;
-}
-
-struct MoveVisitor<'a, 'mir, 'tcx, T> {
- borrowed_locals: &'a RefCell<BorrowedLocalsResults<'mir, 'tcx>>,
- trans: &'a mut T,
-}
-
-impl<'a, 'mir, 'tcx, T> Visitor<'tcx> for MoveVisitor<'a, 'mir, 'tcx, T>
-where
- T: GenKill<Local>,
-{
- fn visit_local(&mut self, local: &Local, context: PlaceContext, loc: Location) {
- if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context {
- let mut borrowed_locals = self.borrowed_locals.borrow_mut();
- borrowed_locals.seek_before_primary_effect(loc);
- if !borrowed_locals.contains(*local) {
- self.trans.kill(*local);
- }
- }
- }
-}
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index eba4dd3..4f91257 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -651,7 +651,7 @@
M::after_stack_push(self)?;
info!("ENTERING({}) {}", self.frame_idx(), self.frame().instance);
- if self.stack().len() > *self.tcx.sess.recursion_limit.get() {
+ if self.stack().len() > self.tcx.sess.recursion_limit() {
throw_exhaust!(StackFrameLimitReached)
} else {
Ok(())
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 42b969c..fc4be82a 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -219,7 +219,10 @@
let place = self.deref_operand(args[0])?;
let discr_val = self.read_discriminant(place.into())?.0;
let scalar = match dest.layout.ty.kind {
- ty::Int(_) => Scalar::from_int(discr_val as i128, dest.layout.size),
+ ty::Int(_) => Scalar::from_int(
+ self.sign_extend(discr_val, dest.layout) as i128,
+ dest.layout.size,
+ ),
ty::Uint(_) => Scalar::from_uint(discr_val, dest.layout.size),
_ => bug!("invalid `discriminant_value` return layout: {:?}", dest.layout),
};
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index f602064..c83555d 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -366,7 +366,7 @@
let place = try_validation!(
self.ecx.ref_to_mplace(value),
self.path,
- err_ub!(InvalidUninitBytes(..)) => { "uninitialized {}", kind },
+ err_ub!(InvalidUninitBytes { .. }) => { "uninitialized {}", kind },
);
if place.layout.is_unsized() {
self.check_wide_ptr_meta(place.meta, place.layout)?;
@@ -514,7 +514,7 @@
let place = try_validation!(
self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?),
self.path,
- err_ub!(InvalidUninitBytes(..)) => { "uninitialized raw pointer" },
+ err_ub!(InvalidUninitBytes { .. } ) => { "uninitialized raw pointer" },
);
if place.layout.is_unsized() {
self.check_wide_ptr_meta(place.meta, place.layout)?;
@@ -592,7 +592,7 @@
let value = try_validation!(
value.not_undef(),
self.path,
- err_ub!(InvalidUninitBytes(..)) => { "{}", value }
+ err_ub!(InvalidUninitBytes { .. }) => { "{}", value }
expected { "something {}", wrapping_range_format(valid_range, max_hi) },
);
let bits = match value.to_bits_or_ptr(op.layout.size, self.ecx) {
@@ -803,12 +803,14 @@
// For some errors we might be able to provide extra information.
// (This custom logic does not fit the `try_validation!` macro.)
match err.kind {
- err_ub!(InvalidUninitBytes(Some(ptr))) => {
+ err_ub!(InvalidUninitBytes(Some(access))) => {
// Some byte was uninitialized, determine which
// element that byte belongs to so we can
// provide an index.
- let i = usize::try_from(ptr.offset.bytes() / layout.size.bytes())
- .unwrap();
+ let i = usize::try_from(
+ access.uninit_ptr.offset.bytes() / layout.size.bytes(),
+ )
+ .unwrap();
self.path.push(PathElem::ArrayElem(i));
throw_validation_failure!(self.path, { "uninitialized bytes" })
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 925b8d3..081f643 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -430,7 +430,7 @@
// Code that needs to instantiate the same function recursively
// more than the recursion limit is assumed to be causing an
// infinite expansion.
- if adjusted_recursion_depth > *tcx.sess.recursion_limit.get() {
+ if adjusted_recursion_depth > tcx.sess.recursion_limit() {
let error = format!("reached the recursion limit while instantiating `{}`", instance);
if let Some(def_id) = def_id.as_local() {
let hir_id = tcx.hir().as_local_hir_id(def_id);
@@ -463,8 +463,7 @@
// which means that rustc basically hangs.
//
// Bail out in these cases to avoid that bad user experience.
- let type_length_limit = *tcx.sess.type_length_limit.get();
- if type_length > type_length_limit {
+ if type_length > tcx.sess.type_length_limit() {
// The instance name is already known to be too long for rustc.
// Show only the first and last 32 characters to avoid blasting
// the user's terminal with thousands of lines of type-name.
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 4bf2adc..50a882a 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -50,7 +50,7 @@
//! Otherwise it drops all the values in scope at the last suspension point.
use crate::dataflow::impls::{
- MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive,
+ MaybeBorrowedLocals, MaybeInitializedLocals, MaybeLiveLocals, MaybeStorageLive,
};
use crate::dataflow::{self, Analysis};
use crate::transform::no_landing_pads::no_landing_pads;
@@ -266,7 +266,7 @@
// Create a statement which reads the discriminant into a temporary
fn get_discr(&self, body: &mut Body<'tcx>) -> (Statement<'tcx>, Place<'tcx>) {
- let temp_decl = LocalDecl::new(self.tcx.types.isize, body.span).internal();
+ let temp_decl = LocalDecl::new(self.discr_ty, body.span).internal();
let local_decls_len = body.local_decls.push(temp_decl);
let temp = Place::from(local_decls_len);
@@ -444,86 +444,80 @@
movable: bool,
) -> LivenessInfo {
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 mut storage_live = MaybeStorageLive::new(always_live_locals.clone())
- .into_engine(tcx, body_ref, def_id)
+ .into_engine(tcx, body, def_id)
.iterate_to_fixpoint()
- .into_results_cursor(body_ref);
+ .into_results_cursor(body);
- // Calculate the MIR locals which have been previously
- // borrowed (even if they are still active).
- let borrowed_locals_results =
- MaybeBorrowedLocals::all_borrows().into_engine(tcx, body_ref, def_id).iterate_to_fixpoint();
-
- let mut borrowed_locals_cursor =
- dataflow::ResultsCursor::new(body_ref, &borrowed_locals_results);
-
- // Calculate the MIR locals that we actually need to keep storage around
- // for.
- let requires_storage_results = MaybeRequiresStorage::new(body, &borrowed_locals_results)
- .into_engine(tcx, body_ref, def_id)
- .iterate_to_fixpoint();
- let mut requires_storage_cursor =
- dataflow::ResultsCursor::new(body_ref, &requires_storage_results);
-
- // Calculate the liveness of MIR locals ignoring borrows.
- let mut liveness = MaybeLiveLocals
- .into_engine(tcx, body_ref, def_id)
+ let mut init = MaybeInitializedLocals
+ .into_engine(tcx, body, def_id)
.iterate_to_fixpoint()
- .into_results_cursor(body_ref);
+ .into_results_cursor(body);
+
+ let mut live = MaybeLiveLocals
+ .into_engine(tcx, body, def_id)
+ .iterate_to_fixpoint()
+ .into_results_cursor(body);
+
+ let mut borrowed = MaybeBorrowedLocals::all_borrows()
+ .into_engine(tcx, body, def_id)
+ .iterate_to_fixpoint()
+ .into_results_cursor(body);
+
+ // Liveness across yield points is determined by the following boolean equation, where `live`,
+ // `init` and `borrowed` come from dataflow and `movable` is a property of the generator.
+ // Movable generators do not allow borrows to live across yield points, so they don't need to
+ // store a local simply because it is borrowed.
+ //
+ // live_across_yield := (live & init) | (!movable & borrowed)
+ //
+ let mut locals_live_across_yield_point = |block| {
+ live.seek_to_block_end(block);
+ let mut live_locals = live.get().clone();
+
+ init.seek_to_block_end(block);
+ live_locals.intersect(init.get());
+
+ if !movable {
+ borrowed.seek_to_block_end(block);
+ live_locals.union(borrowed.get());
+ }
+
+ live_locals
+ };
let mut storage_liveness_map = IndexVec::from_elem(None, body.basic_blocks());
let mut live_locals_at_suspension_points = Vec::new();
let mut live_locals_at_any_suspension_point = BitSet::new_empty(body.local_decls.len());
for (block, data) in body.basic_blocks().iter_enumerated() {
- if let TerminatorKind::Yield { .. } = data.terminator().kind {
- let loc = Location { block, statement_index: data.statements.len() };
-
- liveness.seek_to_block_end(block);
- let mut live_locals = liveness.get().clone();
-
- if !movable {
- // The `liveness` variable contains the liveness of MIR locals ignoring borrows.
- // This is correct for movable generators since borrows cannot live across
- // suspension points. However for immovable generators we need to account for
- // borrows, so we conseratively assume that all borrowed locals are live until
- // we find a StorageDead statement referencing the locals.
- // To do this we just union our `liveness` result with `borrowed_locals`, which
- // contains all the locals which has been borrowed before this suspension point.
- // If a borrow is converted to a raw reference, we must also assume that it lives
- // forever. Note that the final liveness is still bounded by the storage liveness
- // of the local, which happens using the `intersect` operation below.
- borrowed_locals_cursor.seek_before_primary_effect(loc);
- live_locals.union(borrowed_locals_cursor.get());
- }
-
- // Store the storage liveness for later use so we can restore the state
- // after a suspension point
- storage_live.seek_before_primary_effect(loc);
- storage_liveness_map[block] = Some(storage_live.get().clone());
-
- // Locals live are live at this point only if they are used across
- // suspension points (the `liveness` variable)
- // and their storage is required (the `storage_required` variable)
- requires_storage_cursor.seek_before_primary_effect(loc);
- live_locals.intersect(requires_storage_cursor.get());
-
- // The generator argument is ignored.
- live_locals.remove(SELF_ARG);
-
- debug!("loc = {:?}, live_locals = {:?}", loc, live_locals);
-
- // Add the locals live at this suspension point to the set of locals which live across
- // any suspension points
- live_locals_at_any_suspension_point.union(&live_locals);
-
- live_locals_at_suspension_points.push(live_locals);
+ if !matches!(data.terminator().kind, TerminatorKind::Yield { .. }) {
+ continue;
}
+
+ // Store the storage liveness for later use so we can restore the state
+ // after a suspension point
+ storage_live.seek_to_block_end(block);
+ storage_liveness_map[block] = Some(storage_live.get().clone());
+
+ let mut live_locals = locals_live_across_yield_point(block);
+
+ // The combination of `MaybeInitializedLocals` and `MaybeBorrowedLocals` should be strictly
+ // more precise than `MaybeStorageLive` because they handle `StorageDead` themselves. This
+ // assumes that the MIR forbids locals from being initialized/borrowed before reaching
+ // `StorageLive`.
+ debug_assert!(storage_live.get().superset(&live_locals));
+
+ // Ignore the generator's `self` argument since it is handled seperately.
+ live_locals.remove(SELF_ARG);
+ debug!("block = {:?}, live_locals = {:?}", block, live_locals);
+ live_locals_at_any_suspension_point.union(&live_locals);
+ live_locals_at_suspension_points.push(live_locals);
}
+
debug!("live_locals_anywhere = {:?}", live_locals_at_any_suspension_point);
// Renumber our liveness_map bitsets to include only the locals we are
@@ -534,10 +528,11 @@
.collect();
let storage_conflicts = compute_storage_conflicts(
- body_ref,
+ body,
&live_locals_at_any_suspension_point,
always_live_locals.clone(),
- requires_storage_results,
+ init,
+ borrowed,
);
LivenessInfo {
@@ -569,6 +564,37 @@
out
}
+/// Record conflicts between locals at the current dataflow cursor positions.
+///
+/// You need to seek the cursors before calling this function.
+fn record_conflicts_at_curr_loc(
+ local_conflicts: &mut BitMatrix<Local, Local>,
+ init: &dataflow::ResultsCursor<'mir, 'tcx, MaybeInitializedLocals>,
+ borrowed: &dataflow::ResultsCursor<'mir, 'tcx, MaybeBorrowedLocals>,
+) {
+ // A local requires storage if it is initialized or borrowed. For now, a local
+ // becomes uninitialized if it is moved from, but is still considered "borrowed".
+ //
+ // requires_storage := init | borrowed
+ //
+ // Just like when determining what locals are live at yield points, there is no need
+ // to look at storage liveness here, since `init | borrowed` is strictly more precise.
+ //
+ // FIXME: This function is called in a loop, so it might be better to pass in a temporary
+ // bitset rather than cloning here.
+ let mut requires_storage = init.get().clone();
+ requires_storage.union(borrowed.get());
+
+ for local in requires_storage.iter() {
+ local_conflicts.union_row_with(&requires_storage, local);
+ }
+
+ // `>1` because the `self` argument always requires storage.
+ if requires_storage.count() > 1 {
+ trace!("requires_storage={:?}", requires_storage);
+ }
+}
+
/// For every saved local, looks for which locals are StorageLive at the same
/// time. Generates a bitset for every local of all the other locals that may be
/// StorageLive simultaneously with that local. This is used in the layout
@@ -577,30 +603,45 @@
body: &'mir Body<'tcx>,
stored_locals: &BitSet<Local>,
always_live_locals: storage::AlwaysLiveLocals,
- requires_storage: dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>,
+ mut init: dataflow::ResultsCursor<'mir, 'tcx, MaybeInitializedLocals>,
+ mut borrowed: dataflow::ResultsCursor<'mir, 'tcx, MaybeBorrowedLocals>,
) -> BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal> {
+ debug!("compute_storage_conflicts({:?})", body.span);
assert_eq!(body.local_decls.len(), stored_locals.domain_size());
- debug!("compute_storage_conflicts({:?})", body.span);
- debug!("always_live = {:?}", always_live_locals);
+ // Locals that are always live conflict with all other locals.
+ //
+ // FIXME: Why do we need to handle locals without `Storage{Live,Dead}` specially here?
+ // Shouldn't it be enough to know whether they are initialized?
+ let always_live_locals = always_live_locals.into_inner();
+ let mut local_conflicts = BitMatrix::from_row_n(&always_live_locals, body.local_decls.len());
- // Locals that are always live or ones that need to be stored across
- // suspension points are not eligible for overlap.
- let mut ineligible_locals = always_live_locals.into_inner();
- ineligible_locals.intersect(stored_locals);
+ // Visit every reachable statement and terminator. The exact order does not matter. When two
+ // locals are live at the same point in time, add an entry in the conflict matrix.
+ for (block, data) in traversal::preorder(body) {
+ // Ignore unreachable blocks.
+ if data.terminator().kind == TerminatorKind::Unreachable {
+ continue;
+ }
- // Compute the storage conflicts for all eligible locals.
- let mut visitor = StorageConflictVisitor {
- body,
- stored_locals: &stored_locals,
- local_conflicts: BitMatrix::from_row_n(&ineligible_locals, body.local_decls.len()),
- };
+ // Observe the dataflow state *before* all possible locations (statement or terminator) in
+ // each basic block...
+ for statement_index in 0..=data.statements.len() {
+ let loc = Location { block, statement_index };
+ trace!("record conflicts at {:?}", loc);
+ init.seek_before_primary_effect(loc);
+ borrowed.seek_before_primary_effect(loc);
+ record_conflicts_at_curr_loc(&mut local_conflicts, &init, &borrowed);
+ }
- // Visit only reachable basic blocks. The exact order is not important.
- let reachable_blocks = traversal::preorder(body).map(|(bb, _)| bb);
- requires_storage.visit_with(body, reachable_blocks, &mut visitor);
-
- let local_conflicts = visitor.local_conflicts;
+ // ...and then observe the state *after* the terminator effect is applied. As long as
+ // neither `init` nor `borrowed` has a "before" effect, we will observe all possible
+ // dataflow states here or in the loop above.
+ trace!("record conflicts at end of {:?}", block);
+ init.seek_to_block_end(block);
+ borrowed.seek_to_block_end(block);
+ record_conflicts_at_curr_loc(&mut local_conflicts, &init, &borrowed);
+ }
// Compress the matrix using only stored locals (Local -> GeneratorSavedLocal).
//
@@ -612,7 +653,7 @@
let mut storage_conflicts = BitMatrix::new(stored_locals.count(), stored_locals.count());
for (idx_a, local_a) in stored_locals.iter().enumerate() {
let saved_local_a = GeneratorSavedLocal::new(idx_a);
- if ineligible_locals.contains(local_a) {
+ if always_live_locals.contains(local_a) {
// Conflicts with everything.
storage_conflicts.insert_all_into_row(saved_local_a);
} else {
@@ -628,56 +669,6 @@
storage_conflicts
}
-struct StorageConflictVisitor<'mir, 'tcx, 's> {
- body: &'mir Body<'tcx>,
- stored_locals: &'s BitSet<Local>,
- // FIXME(tmandry): Consider using sparse bitsets here once we have good
- // benchmarks for generators.
- local_conflicts: BitMatrix<Local, Local>,
-}
-
-impl dataflow::ResultsVisitor<'mir, 'tcx> for StorageConflictVisitor<'mir, 'tcx, '_> {
- type FlowState = BitSet<Local>;
-
- fn visit_statement_before_primary_effect(
- &mut self,
- state: &Self::FlowState,
- _statement: &'mir Statement<'tcx>,
- loc: Location,
- ) {
- self.apply_state(state, loc);
- }
-
- fn visit_terminator_before_primary_effect(
- &mut self,
- state: &Self::FlowState,
- _terminator: &'mir Terminator<'tcx>,
- loc: Location,
- ) {
- self.apply_state(state, loc);
- }
-}
-
-impl<'body, 'tcx, 's> StorageConflictVisitor<'body, 'tcx, 's> {
- fn apply_state(&mut self, flow_state: &BitSet<Local>, loc: Location) {
- // Ignore unreachable blocks.
- if self.body.basic_blocks()[loc.block].terminator().kind == TerminatorKind::Unreachable {
- return;
- }
-
- let mut eligible_storage_live = flow_state.clone();
- eligible_storage_live.intersect(&self.stored_locals);
-
- for local in eligible_storage_live.iter() {
- self.local_conflicts.union_row_with(&eligible_storage_live, local);
- }
-
- if eligible_storage_live.count() > 1 {
- trace!("at {:?}, eligible_storage_live={:?}", loc, eligible_storage_live);
- }
- }
-}
-
fn compute_layout<'tcx>(
tcx: TyCtxt<'tcx>,
source: MirSource<'tcx>,
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 0750284..ead530b 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -3,7 +3,7 @@
use rustc_hir::def_id::DefId;
use rustc_middle::mir::*;
use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::{self, adjustment::PointerCast, Predicate, Ty, TyCtxt};
+use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
use std::borrow::Cow;
@@ -23,28 +23,30 @@
loop {
let predicates = tcx.predicates_of(current);
for (predicate, _) in predicates.predicates {
- match predicate {
- Predicate::RegionOutlives(_)
- | Predicate::TypeOutlives(_)
- | Predicate::WellFormed(_)
- | Predicate::Projection(_)
- | Predicate::ConstEvaluatable(..)
- | Predicate::ConstEquate(..) => continue,
- Predicate::ObjectSafe(_) => {
+ match predicate.kind() {
+ ty::PredicateKind::RegionOutlives(_)
+ | ty::PredicateKind::TypeOutlives(_)
+ | ty::PredicateKind::WellFormed(_)
+ | ty::PredicateKind::Projection(_)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => continue,
+ ty::PredicateKind::ObjectSafe(_) => {
bug!("object safe predicate on function: {:#?}", predicate)
}
- Predicate::ClosureKind(..) => {
+ ty::PredicateKind::ClosureKind(..) => {
bug!("closure kind predicate on function: {:#?}", predicate)
}
- Predicate::Subtype(_) => bug!("subtype predicate on function: {:#?}", predicate),
- Predicate::Trait(pred, constness) => {
+ ty::PredicateKind::Subtype(_) => {
+ bug!("subtype predicate on function: {:#?}", predicate)
+ }
+ &ty::PredicateKind::Trait(pred, constness) => {
if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
continue;
}
match pred.skip_binder().self_ty().kind {
ty::Param(ref p) => {
// Allow `T: ?const Trait`
- if *constness == hir::Constness::NotConst
+ if constness == hir::Constness::NotConst
&& feature_allowed(tcx, def_id, sym::const_trait_bound_opt_out)
{
continue;
diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs
index f6941d3..626e531 100644
--- a/src/librustc_mir_build/hair/pattern/_match.rs
+++ b/src/librustc_mir_build/hair/pattern/_match.rs
@@ -1,5 +1,5 @@
-/// Note: most tests relevant to this file can be found (at the time of writing)
-/// in src/tests/ui/pattern/usefulness.
+/// Note: most of the tests relevant to this file can be found (at the time of writing) in
+/// src/tests/ui/pattern/usefulness.
///
/// This file includes the logic for exhaustiveness and usefulness checking for
/// pattern-matching. Specifically, given a list of patterns for a type, we can
@@ -13,6 +13,8 @@
/// summarise the algorithm here to hopefully save time and be a little clearer
/// (without being so rigorous).
///
+/// # Premise
+///
/// The core of the algorithm revolves about a "usefulness" check. In particular, we
/// are trying to compute a predicate `U(P, p)` where `P` is a list of patterns (we refer to this as
/// a matrix). `U(P, p)` represents whether, given an existing list of patterns
@@ -27,8 +29,51 @@
/// pattern to those that have come before it doesn't increase the number of values
/// we're matching).
///
+/// # Core concept
+///
+/// The idea that powers everything that is done in this file is the following: a value is made
+/// from a constructor applied to some fields. Examples of constructors are `Some`, `None`, `(,)`
+/// (the 2-tuple constructor), `Foo {..}` (the constructor for a struct `Foo`), and `2` (the
+/// constructor for the number `2`). Fields are just a (possibly empty) list of values.
+///
+/// Some of the constructors listed above might feel weird: `None` and `2` don't take any
+/// arguments. This is part of what makes constructors so general: we will consider plain values
+/// like numbers and string literals to be constructors that take no arguments, also called "0-ary
+/// constructors"; they are the simplest case of constructors. This allows us to see any value as
+/// made up from a tree of constructors, each having a given number of children. For example:
+/// `(None, Ok(0))` is made from 4 different constructors.
+///
+/// This idea can be extended to patterns: a pattern captures a set of possible values, and we can
+/// describe this set using constructors. For example, `Err(_)` captures all values of the type
+/// `Result<T, E>` that start with the `Err` constructor (for some choice of `T` and `E`). The
+/// wildcard `_` captures all values of the given type starting with any of the constructors for
+/// that type.
+///
+/// We use this to compute whether different patterns might capture a same value. Do the patterns
+/// `Ok("foo")` and `Err(_)` capture a common value? The answer is no, because the first pattern
+/// captures only values starting with the `Ok` constructor and the second only values starting
+/// with the `Err` constructor. Do the patterns `Some(42)` and `Some(1..10)` intersect? They might,
+/// since they both capture values starting with `Some`. To be certain, we need to dig under the
+/// `Some` constructor and continue asking the question. This is the main idea behind the
+/// exhaustiveness algorithm: by looking at patterns constructor-by-constructor, we can efficiently
+/// figure out if some new pattern might capture a value that hadn't been captured by previous
+/// patterns.
+///
+/// Constructors are represented by the `Constructor` enum, and its fields by the `Fields` enum.
+/// Most of the complexity of this file resides in transforming between patterns and
+/// (`Constructor`, `Fields`) pairs, handling all the special cases correctly.
+///
+/// Caveat: this constructors/fields distinction doesn't quite cover every Rust value. For example
+/// a value of type `Rc<u64>` doesn't fit this idea very well, nor do various other things.
+/// However, this idea covers most of the cases that are relevant to exhaustiveness checking.
+///
+///
+/// # Algorithm
+///
+/// Recall that `U(P, p)` represents whether, given an existing list of patterns (aka matrix) `P`,
+/// adding a new pattern `p` will cover previously-uncovered values of the type.
/// During the course of the algorithm, the rows of the matrix won't just be individual patterns,
-/// but rather partially-deconstructed patterns in the form of a list of patterns. The paper
+/// but rather partially-deconstructed patterns in the form of a list of fields. The paper
/// calls those pattern-vectors, and we will call them pattern-stacks. The same holds for the
/// new pattern `p`.
///
@@ -242,7 +287,7 @@
use rustc_middle::mir::interpret::{truncate, AllocId, ConstValue, Pointer, Scalar};
use rustc_middle::mir::Field;
use rustc_middle::ty::layout::IntegerExt;
-use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef};
+use rustc_middle::ty::{self, Const, Ty, TyCtxt};
use rustc_session::lint;
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{Integer, Size, VariantIdx};
@@ -441,13 +486,11 @@
&self,
cx: &mut MatchCheckCtxt<'p, 'tcx>,
constructor: &Constructor<'tcx>,
- ctor_wild_subpatterns: &'p [Pat<'tcx>],
+ ctor_wild_subpatterns: &Fields<'p, '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..]);
- new_head
- })
+ let new_fields =
+ specialize_one_pattern(cx, self.head(), constructor, ctor_wild_subpatterns)?;
+ Some(new_fields.push_on_patstack(&self.0[1..]))
}
}
@@ -503,7 +546,7 @@
&self,
cx: &mut MatchCheckCtxt<'p, 'tcx>,
constructor: &Constructor<'tcx>,
- ctor_wild_subpatterns: &'p [Pat<'tcx>],
+ ctor_wild_subpatterns: &Fields<'p, 'tcx>,
) -> Matrix<'p, 'tcx> {
self.0
.iter()
@@ -593,7 +636,7 @@
}
}
- // Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
+ /// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
crate fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
match ty.kind {
ty::Adt(def, ..) => {
@@ -602,15 +645,6 @@
_ => false,
}
}
-
- // Returns whether the given variant is from another crate and has its fields declared
- // `#[non_exhaustive]`.
- fn is_foreign_non_exhaustive_variant(&self, ty: Ty<'tcx>, variant: &VariantDef) -> bool {
- match ty.kind {
- ty::Adt(def, ..) => variant.is_field_list_non_exhaustive() && !def.did.is_local(),
- _ => false,
- }
- }
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -722,10 +756,17 @@
}
}
+/// A value can be decomposed into a constructor applied to some fields. This struct represents
+/// the constructor. See also `Fields`.
+///
+/// `pat_constructor` retrieves the constructor corresponding to a pattern.
+/// `specialize_one_pattern` returns the list of fields corresponding to a pattern, given a
+/// constructor. `Constructor::apply` reconstructs the pattern from a pair of `Constructor` and
+/// `Fields`.
#[derive(Clone, Debug, PartialEq)]
enum Constructor<'tcx> {
- /// The constructor of all patterns that don't vary by constructor,
- /// e.g., struct patterns and fixed-length arrays.
+ /// The constructor for patterns that have a single constructor, like tuples, struct patterns
+ /// and fixed-length arrays.
Single,
/// Enum variants.
Variant(DefId),
@@ -850,107 +891,10 @@
}
}
- /// This returns one wildcard pattern for each argument to this constructor.
- ///
- /// This must be consistent with `apply`, `specialize_one_pattern`, and `arity`.
- fn wildcard_subpatterns<'a>(
- &self,
- cx: &MatchCheckCtxt<'a, 'tcx>,
- ty: Ty<'tcx>,
- ) -> Vec<Pat<'tcx>> {
- debug!("wildcard_subpatterns({:#?}, {:?})", self, ty);
-
- match self {
- Single | Variant(_) => match ty.kind {
- ty::Tuple(ref fs) => {
- fs.into_iter().map(|t| t.expect_ty()).map(Pat::wildcard_from_ty).collect()
- }
- ty::Ref(_, rty, _) => vec![Pat::wildcard_from_ty(rty)],
- ty::Adt(adt, substs) => {
- if adt.is_box() {
- // Use T as the sub pattern type of Box<T>.
- vec![Pat::wildcard_from_ty(substs.type_at(0))]
- } else {
- let variant = &adt.variants[self.variant_index_for_adt(cx, adt)];
- let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(ty, variant);
- variant
- .fields
- .iter()
- .map(|field| {
- let is_visible = adt.is_enum()
- || field.vis.is_accessible_from(cx.module, cx.tcx);
- let is_uninhabited = cx.is_uninhabited(field.ty(cx.tcx, substs));
- match (is_visible, is_non_exhaustive, is_uninhabited) {
- // Treat all uninhabited types in non-exhaustive variants as
- // `TyErr`.
- (_, true, true) => cx.tcx.types.err,
- // Treat all non-visible fields as `TyErr`. They can't appear
- // in any other pattern from this match (because they are
- // private), so their type does not matter - but we don't want
- // to know they are uninhabited.
- (false, ..) => cx.tcx.types.err,
- (true, ..) => {
- let ty = field.ty(cx.tcx, substs);
- match ty.kind {
- // If the field type returned is an array of an unknown
- // size return an TyErr.
- ty::Array(_, len)
- if len
- .try_eval_usize(cx.tcx, cx.param_env)
- .is_none() =>
- {
- cx.tcx.types.err
- }
- _ => ty,
- }
- }
- }
- })
- .map(Pat::wildcard_from_ty)
- .collect()
- }
- }
- _ => vec![],
- },
- Slice(_) => match ty.kind {
- ty::Slice(ty) | ty::Array(ty, _) => {
- let arity = self.arity(cx, ty);
- (0..arity).map(|_| Pat::wildcard_from_ty(ty)).collect()
- }
- _ => bug!("bad slice pattern {:?} {:?}", self, ty),
- },
- ConstantValue(..) | FloatRange(..) | IntRange(..) | NonExhaustive => vec![],
- }
- }
-
- /// This computes the arity of a constructor. The arity of a constructor
- /// is how many subpattern patterns of that constructor should be expanded to.
- ///
- /// For instance, a tuple pattern `(_, 42, Some([]))` has the arity of 3.
- /// A struct pattern's arity is the number of fields it contains, etc.
- ///
- /// This must be consistent with `wildcard_subpatterns`, `specialize_one_pattern`, and `apply`.
- fn arity<'a>(&self, cx: &MatchCheckCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> u64 {
- debug!("Constructor::arity({:#?}, {:?})", self, ty);
- match self {
- Single | Variant(_) => match ty.kind {
- ty::Tuple(ref fs) => fs.len() as u64,
- ty::Slice(..) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", self, ty),
- ty::Ref(..) => 1,
- ty::Adt(adt, _) => {
- adt.variants[self.variant_index_for_adt(cx, adt)].fields.len() as u64
- }
- _ => 0,
- },
- Slice(slice) => slice.arity(),
- ConstantValue(..) | FloatRange(..) | IntRange(..) | NonExhaustive => 0,
- }
- }
-
/// Apply a constructor to a list of patterns, yielding a new pattern. `pats`
/// must have as many elements as this constructor's arity.
///
- /// This must be consistent with `wildcard_subpatterns`, `specialize_one_pattern`, and `arity`.
+ /// This is roughly the inverse of `specialize_one_pattern`.
///
/// Examples:
/// `self`: `Constructor::Single`
@@ -962,13 +906,13 @@
/// `ty`: `Option<bool>`
/// `pats`: `[false]`
/// returns `Some(false)`
- fn apply<'a>(
+ fn apply<'p>(
&self,
- cx: &MatchCheckCtxt<'a, 'tcx>,
+ cx: &MatchCheckCtxt<'p, 'tcx>,
ty: Ty<'tcx>,
- pats: impl IntoIterator<Item = Pat<'tcx>>,
+ fields: Fields<'p, 'tcx>,
) -> Pat<'tcx> {
- let mut subpatterns = pats.into_iter();
+ let mut subpatterns = fields.all_patterns();
let pat = match self {
Single | Variant(_) => match ty.kind {
@@ -1033,8 +977,263 @@
/// Like `apply`, but where all the subpatterns are wildcards `_`.
fn apply_wildcards<'a>(&self, cx: &MatchCheckCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Pat<'tcx> {
- let subpatterns = self.wildcard_subpatterns(cx, ty).into_iter().rev();
- self.apply(cx, ty, subpatterns)
+ self.apply(cx, ty, Fields::wildcards(cx, self, ty))
+ }
+}
+
+/// Some fields need to be explicitly hidden away in certain cases; see the comment above the
+/// `Fields` struct. This struct represents such a potentially-hidden field. When a field is hidden
+/// we still keep its type around.
+#[derive(Debug, Copy, Clone)]
+enum FilteredField<'p, 'tcx> {
+ Kept(&'p Pat<'tcx>),
+ Hidden(Ty<'tcx>),
+}
+
+impl<'p, 'tcx> FilteredField<'p, 'tcx> {
+ fn kept(self) -> Option<&'p Pat<'tcx>> {
+ match self {
+ FilteredField::Kept(p) => Some(p),
+ FilteredField::Hidden(_) => None,
+ }
+ }
+
+ fn to_pattern(self) -> Pat<'tcx> {
+ match self {
+ FilteredField::Kept(p) => p.clone(),
+ FilteredField::Hidden(ty) => Pat::wildcard_from_ty(ty),
+ }
+ }
+}
+
+/// A value can be decomposed into a constructor applied to some fields. This struct represents
+/// those fields, generalized to allow patterns in each field. See also `Constructor`.
+///
+/// If a private or `non_exhaustive` field is uninhabited, the code mustn't observe that it is
+/// uninhabited. For that, we filter these fields out of the matrix. This is subtle because we
+/// still need to have those fields back when going to/from a `Pat`. Most of this is handled
+/// automatically in `Fields`, but when constructing or deconstructing `Fields` you need to be
+/// careful. As a rule, when going to/from the matrix, use the filtered field list; when going
+/// to/from `Pat`, use the full field list.
+/// This filtering is uncommon in practice, because uninhabited fields are rarely used, so we avoid
+/// it when possible to preserve performance.
+#[derive(Debug, Clone)]
+enum Fields<'p, 'tcx> {
+ /// Lists of patterns that don't contain any filtered fields.
+ /// `Slice` and `Vec` behave the same; the difference is only to avoid allocating and
+ /// triple-dereferences when possible. Frankly this is premature optimization, I (Nadrieril)
+ /// have not measured if it really made a difference.
+ Slice(&'p [Pat<'tcx>]),
+ Vec(SmallVec<[&'p Pat<'tcx>; 2]>),
+ /// Patterns where some of the fields need to be hidden. `len` caches the number of non-hidden
+ /// fields.
+ Filtered {
+ fields: SmallVec<[FilteredField<'p, 'tcx>; 2]>,
+ len: usize,
+ },
+}
+
+impl<'p, 'tcx> Fields<'p, 'tcx> {
+ fn empty() -> Self {
+ Fields::Slice(&[])
+ }
+
+ /// Construct a new `Fields` from the given pattern. Must not be used if the pattern is a field
+ /// of a struct/tuple/variant.
+ fn from_single_pattern(pat: &'p Pat<'tcx>) -> Self {
+ Fields::Slice(std::slice::from_ref(pat))
+ }
+
+ /// Construct a new `Fields` from the given patterns. You must be sure those patterns can't
+ /// contain fields that need to be filtered out. When in doubt, prefer `replace_fields`.
+ fn from_slice_unfiltered(pats: &'p [Pat<'tcx>]) -> Self {
+ Fields::Slice(pats)
+ }
+
+ /// Convenience; internal use.
+ fn wildcards_from_tys(
+ cx: &MatchCheckCtxt<'p, 'tcx>,
+ tys: impl IntoIterator<Item = Ty<'tcx>>,
+ ) -> Self {
+ let wilds = tys.into_iter().map(Pat::wildcard_from_ty);
+ let pats = cx.pattern_arena.alloc_from_iter(wilds);
+ Fields::Slice(pats)
+ }
+
+ /// Creates a new list of wildcard fields for a given constructor.
+ fn wildcards(
+ cx: &MatchCheckCtxt<'p, 'tcx>,
+ constructor: &Constructor<'tcx>,
+ ty: Ty<'tcx>,
+ ) -> Self {
+ debug!("Fields::wildcards({:#?}, {:?})", constructor, ty);
+ let wildcard_from_ty = |ty| &*cx.pattern_arena.alloc(Pat::wildcard_from_ty(ty));
+
+ match constructor {
+ Single | Variant(_) => match ty.kind {
+ ty::Tuple(ref fs) => {
+ Fields::wildcards_from_tys(cx, fs.into_iter().map(|ty| ty.expect_ty()))
+ }
+ ty::Ref(_, rty, _) => Fields::from_single_pattern(wildcard_from_ty(rty)),
+ ty::Adt(adt, substs) => {
+ if adt.is_box() {
+ // Use T as the sub pattern type of Box<T>.
+ Fields::from_single_pattern(wildcard_from_ty(substs.type_at(0)))
+ } else {
+ let variant = &adt.variants[constructor.variant_index_for_adt(cx, adt)];
+ // Whether we must not match the fields of this variant exhaustively.
+ let is_non_exhaustive =
+ variant.is_field_list_non_exhaustive() && !adt.did.is_local();
+ let field_tys = variant.fields.iter().map(|field| field.ty(cx.tcx, substs));
+ // In the following cases, we don't need to filter out any fields. This is
+ // the vast majority of real cases, since uninhabited fields are uncommon.
+ let has_no_hidden_fields = (adt.is_enum() && !is_non_exhaustive)
+ || !field_tys.clone().any(|ty| cx.is_uninhabited(ty));
+
+ if has_no_hidden_fields {
+ Fields::wildcards_from_tys(cx, field_tys)
+ } else {
+ let mut len = 0;
+ let fields = variant
+ .fields
+ .iter()
+ .map(|field| {
+ let ty = field.ty(cx.tcx, substs);
+ let is_visible = adt.is_enum()
+ || field.vis.is_accessible_from(cx.module, cx.tcx);
+ let is_uninhabited = cx.is_uninhabited(ty);
+
+ // In the cases of either a `#[non_exhaustive]` field list
+ // or a non-public field, we hide uninhabited fields in
+ // order not to reveal the uninhabitedness of the whole
+ // variant.
+ if is_uninhabited && (!is_visible || is_non_exhaustive) {
+ FilteredField::Hidden(ty)
+ } else {
+ len += 1;
+ FilteredField::Kept(wildcard_from_ty(ty))
+ }
+ })
+ .collect();
+ Fields::Filtered { fields, len }
+ }
+ }
+ }
+ _ => Fields::empty(),
+ },
+ Slice(slice) => match ty.kind {
+ ty::Slice(ty) | ty::Array(ty, _) => {
+ let arity = slice.arity();
+ Fields::wildcards_from_tys(cx, (0..arity).map(|_| ty))
+ }
+ _ => bug!("bad slice pattern {:?} {:?}", constructor, ty),
+ },
+ ConstantValue(..) | FloatRange(..) | IntRange(..) | NonExhaustive => Fields::empty(),
+ }
+ }
+
+ fn len(&self) -> usize {
+ match self {
+ Fields::Slice(pats) => pats.len(),
+ Fields::Vec(pats) => pats.len(),
+ Fields::Filtered { len, .. } => *len,
+ }
+ }
+
+ /// Returns the complete list of patterns, including hidden fields.
+ fn all_patterns(self) -> impl Iterator<Item = Pat<'tcx>> {
+ let pats: SmallVec<[_; 2]> = match self {
+ Fields::Slice(pats) => pats.iter().cloned().collect(),
+ Fields::Vec(pats) => pats.into_iter().cloned().collect(),
+ Fields::Filtered { fields, .. } => {
+ // We don't skip any fields here.
+ fields.into_iter().map(|p| p.to_pattern()).collect()
+ }
+ };
+ pats.into_iter()
+ }
+
+ /// Overrides some of the fields with the provided patterns. Exactly like
+ /// `replace_fields_indexed`, except that it takes `FieldPat`s as input.
+ fn replace_with_fieldpats(
+ &self,
+ new_pats: impl IntoIterator<Item = &'p FieldPat<'tcx>>,
+ ) -> Self {
+ self.replace_fields_indexed(
+ new_pats.into_iter().map(|pat| (pat.field.index(), &pat.pattern)),
+ )
+ }
+
+ /// Overrides some of the fields with the provided patterns. This is used when a pattern
+ /// defines some fields but not all, for example `Foo { field1: Some(_), .. }`: here we start with a
+ /// `Fields` that is just one wildcard per field of the `Foo` struct, and override the entry
+ /// corresponding to `field1` with the pattern `Some(_)`. This is also used for slice patterns
+ /// for the same reason.
+ fn replace_fields_indexed(
+ &self,
+ new_pats: impl IntoIterator<Item = (usize, &'p Pat<'tcx>)>,
+ ) -> Self {
+ let mut fields = self.clone();
+ if let Fields::Slice(pats) = fields {
+ fields = Fields::Vec(pats.iter().collect());
+ }
+
+ match &mut fields {
+ Fields::Vec(pats) => {
+ for (i, pat) in new_pats {
+ pats[i] = pat
+ }
+ }
+ Fields::Filtered { fields, .. } => {
+ for (i, pat) in new_pats {
+ if let FilteredField::Kept(p) = &mut fields[i] {
+ *p = pat
+ }
+ }
+ }
+ Fields::Slice(_) => unreachable!(),
+ }
+ fields
+ }
+
+ /// Replaces contained fields with the given filtered list of patterns, e.g. taken from the
+ /// matrix. There must be `len()` patterns in `pats`.
+ fn replace_fields(
+ &self,
+ cx: &MatchCheckCtxt<'p, 'tcx>,
+ pats: impl IntoIterator<Item = Pat<'tcx>>,
+ ) -> Self {
+ let pats: &[_] = cx.pattern_arena.alloc_from_iter(pats);
+
+ match self {
+ Fields::Filtered { fields, len } => {
+ let mut pats = pats.iter();
+ let mut fields = fields.clone();
+ for f in &mut fields {
+ if let FilteredField::Kept(p) = f {
+ // We take one input pattern for each `Kept` field, in order.
+ *p = pats.next().unwrap();
+ }
+ }
+ Fields::Filtered { fields, len: *len }
+ }
+ _ => Fields::Slice(pats),
+ }
+ }
+
+ fn push_on_patstack(self, stack: &[&'p Pat<'tcx>]) -> PatStack<'p, 'tcx> {
+ let pats: SmallVec<_> = match self {
+ Fields::Slice(pats) => pats.iter().chain(stack.iter().copied()).collect(),
+ Fields::Vec(mut pats) => {
+ pats.extend_from_slice(stack);
+ pats
+ }
+ Fields::Filtered { fields, .. } => {
+ // We skip hidden fields here
+ fields.into_iter().filter_map(|p| p.kept()).chain(stack.iter().copied()).collect()
+ }
+ };
+ PatStack::from_vec(pats)
}
}
@@ -1064,15 +1263,16 @@
fn apply_constructor(
self,
- cx: &MatchCheckCtxt<'_, 'tcx>,
+ cx: &MatchCheckCtxt<'p, 'tcx>,
ctor: &Constructor<'tcx>,
ty: Ty<'tcx>,
+ ctor_wild_subpatterns: &Fields<'p, 'tcx>,
) -> Self {
match self {
UsefulWithWitness(witnesses) => UsefulWithWitness(
witnesses
.into_iter()
- .map(|witness| witness.apply_constructor(cx, &ctor, ty))
+ .map(|witness| witness.apply_constructor(cx, &ctor, ty, ctor_wild_subpatterns))
.collect(),
),
x => x,
@@ -1192,17 +1392,19 @@
///
/// left_ty: struct X { a: (bool, &'static str), b: usize}
/// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 }
- fn apply_constructor<'a>(
+ fn apply_constructor<'p>(
mut self,
- cx: &MatchCheckCtxt<'a, 'tcx>,
+ cx: &MatchCheckCtxt<'p, 'tcx>,
ctor: &Constructor<'tcx>,
ty: Ty<'tcx>,
+ ctor_wild_subpatterns: &Fields<'p, 'tcx>,
) -> Self {
- let arity = ctor.arity(cx, ty);
let pat = {
- let len = self.0.len() as u64;
- let pats = self.0.drain((len - arity) as usize..).rev();
- ctor.apply(cx, ty, pats)
+ let len = self.0.len();
+ let arity = ctor_wild_subpatterns.len();
+ let pats = self.0.drain((len - arity)..).rev();
+ let fields = ctor_wild_subpatterns.replace_fields(cx, pats);
+ ctor.apply(cx, ty, fields)
};
self.0.push(pat);
@@ -1600,11 +1802,7 @@
/// to a set of such vectors `m` - this is defined as there being a set of
/// inputs that will match `v` but not any of the sets in `m`.
///
-/// All the patterns at each column of the `matrix ++ v` matrix must
-/// have the same type, except that wildcard (PatKind::Wild) patterns
-/// with type `TyErr` are also allowed, even if the "type of the column"
-/// is not `TyErr`. That is used to represent private fields, as using their
-/// real type would assert that they are inhabited.
+/// All the patterns at each column of the `matrix ++ v` matrix must have the same type.
///
/// This is used both for reachability checking (if a pattern isn't useful in
/// relation to preceding patterns, it is not reachable) and exhaustiveness
@@ -1668,34 +1866,7 @@
return if any_is_useful { Useful(unreachable_pats) } else { NotUseful };
}
- let (ty, span) = matrix
- .heads()
- .map(|r| (r.ty, r.span))
- .find(|(ty, _)| !ty.references_error())
- .unwrap_or((v.head().ty, v.head().span));
- let pcx = PatCtxt {
- // TyErr is used to represent the type of wildcard patterns matching
- // against inaccessible (private) fields of structs, so that we won't
- // be able to observe whether the types of the struct's fields are
- // inhabited.
- //
- // If the field is truly inaccessible, then all the patterns
- // matching against it must be wildcard patterns, so its type
- // does not matter.
- //
- // However, if we are matching against non-wildcard patterns, we
- // need to know the real type of the field so we can specialize
- // against it. This primarily occurs through constants - they
- // can include contents for fields that are inaccessible at the
- // location of the match. In that case, the field's type is
- // inhabited - by the constant - so we can just use it.
- //
- // FIXME: this might lead to "unstable" behavior with macro hygiene
- // introducing uninhabited patterns for inaccessible fields. We
- // need to figure out how to model that.
- ty,
- span,
- };
+ let pcx = PatCtxt { ty: v.head().ty, span: v.head().span };
debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v.head());
@@ -1827,19 +1998,19 @@
matrix: &Matrix<'p, 'tcx>,
v: &PatStack<'p, 'tcx>,
ctor: Constructor<'tcx>,
- lty: Ty<'tcx>,
+ ty: Ty<'tcx>,
witness_preference: WitnessPreference,
hir_id: HirId,
is_under_guard: bool,
) -> Usefulness<'tcx, 'p> {
- debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty);
+ debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, ty);
- 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)
+ // We cache the result of `Fields::wildcards` because it is used a lot.
+ let ctor_wild_subpatterns = Fields::wildcards(cx, &ctor, ty);
+ 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, is_under_guard, false))
- .map(|u| u.apply_constructor(cx, &ctor, lty))
+ .map(|u| u.apply_constructor(cx, &ctor, ty, &ctor_wild_subpatterns))
.unwrap_or(NotUseful)
}
@@ -2303,27 +2474,6 @@
if intersects { Some(()) } else { None }
}
-fn patterns_for_variant<'p, 'tcx>(
- cx: &mut MatchCheckCtxt<'p, 'tcx>,
- subpatterns: &'p [FieldPat<'tcx>],
- ctor_wild_subpatterns: &'p [Pat<'tcx>],
- is_non_exhaustive: bool,
-) -> PatStack<'p, 'tcx> {
- let mut result: SmallVec<_> = ctor_wild_subpatterns.iter().collect();
-
- for subpat in subpatterns {
- if !is_non_exhaustive || !cx.is_uninhabited(subpat.pattern.ty) {
- result[subpat.field.index()] = &subpat.pattern;
- }
- }
-
- debug!(
- "patterns_for_variant({:#?}, {:#?}) = {:#?}",
- subpatterns, ctor_wild_subpatterns, result
- );
- PatStack::from_vec(result)
-}
-
/// This is the main specialization step. It expands the pattern
/// into `arity` patterns based on the constructor. For most patterns, the step is trivial,
/// for instance tuple patterns are flattened and box patterns expand into their inner pattern.
@@ -2333,37 +2483,40 @@
/// different patterns.
/// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
/// fields filled with wild patterns.
+///
+/// This is roughly the inverse of `Constructor::apply`.
fn specialize_one_pattern<'p, 'tcx>(
cx: &mut MatchCheckCtxt<'p, 'tcx>,
pat: &'p Pat<'tcx>,
constructor: &Constructor<'tcx>,
- ctor_wild_subpatterns: &'p [Pat<'tcx>],
-) -> Option<PatStack<'p, 'tcx>> {
+ ctor_wild_subpatterns: &Fields<'p, 'tcx>,
+) -> Option<Fields<'p, 'tcx>> {
if let NonExhaustive = constructor {
// Only a wildcard pattern can match the special extra constructor
- return if pat.is_wildcard() { Some(PatStack::default()) } else { None };
+ if !pat.is_wildcard() {
+ return None;
+ }
+ return Some(Fields::empty());
}
let result = match *pat.kind {
PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
- PatKind::Binding { .. } | PatKind::Wild => Some(ctor_wild_subpatterns.iter().collect()),
+ PatKind::Binding { .. } | PatKind::Wild => Some(ctor_wild_subpatterns.clone()),
PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
let variant = &adt_def.variants[variant_index];
- let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(pat.ty, variant);
- Some(Variant(variant.def_id))
- .filter(|variant_constructor| variant_constructor == constructor)
- .map(|_| {
- patterns_for_variant(cx, subpatterns, ctor_wild_subpatterns, is_non_exhaustive)
- })
+ if constructor != &Variant(variant.def_id) {
+ return None;
+ }
+ Some(ctor_wild_subpatterns.replace_with_fieldpats(subpatterns))
}
PatKind::Leaf { ref subpatterns } => {
- Some(patterns_for_variant(cx, subpatterns, ctor_wild_subpatterns, false))
+ Some(ctor_wild_subpatterns.replace_with_fieldpats(subpatterns))
}
- PatKind::Deref { ref subpattern } => Some(PatStack::from_pattern(subpattern)),
+ PatKind::Deref { ref subpattern } => Some(Fields::from_single_pattern(subpattern)),
PatKind::Constant { value } if constructor.is_slice() => {
// We extract an `Option` for the pointer because slices of zero
@@ -2376,11 +2529,10 @@
// Shortcut for `n == 0` where no matter what `alloc` and `offset` we produce,
// the result would be exactly what we early return here.
if n == 0 {
- if ctor_wild_subpatterns.len() as u64 == 0 {
- return Some(PatStack::from_slice(&[]));
- } else {
+ if ctor_wild_subpatterns.len() as u64 != n {
return None;
}
+ return Some(Fields::empty());
}
match value.val {
ty::ConstKind::Value(ConstValue::ByRef { offset, alloc, .. }) => {
@@ -2414,24 +2566,26 @@
constructor,
),
};
- if ctor_wild_subpatterns.len() as u64 == n {
- // convert a constant slice/array pattern to a list of patterns.
- let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?;
- let ptr = Pointer::new(AllocId(0), offset);
- (0..n)
- .map(|i| {
- let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?;
- let scalar = alloc.read_scalar(&cx.tcx, ptr, layout.size).ok()?;
- let scalar = scalar.not_undef().ok()?;
- let value = ty::Const::from_scalar(cx.tcx, scalar, ty);
- let pattern =
- Pat { ty, span: pat.span, kind: box PatKind::Constant { value } };
- Some(&*cx.pattern_arena.alloc(pattern))
- })
- .collect()
- } else {
- None
+ if ctor_wild_subpatterns.len() as u64 != n {
+ return None;
}
+
+ // Convert a constant slice/array pattern to a list of patterns.
+ let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?;
+ let ptr = Pointer::new(AllocId(0), offset);
+ let pats = cx.pattern_arena.alloc_from_iter((0..n).filter_map(|i| {
+ let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?;
+ let scalar = alloc.read_scalar(&cx.tcx, ptr, layout.size).ok()?;
+ let scalar = scalar.not_undef().ok()?;
+ let value = ty::Const::from_scalar(cx.tcx, scalar, ty);
+ let pattern = Pat { ty, span: pat.span, kind: box PatKind::Constant { value } };
+ Some(pattern)
+ }));
+ // Ensure none of the dereferences failed.
+ if pats.len() as u64 != n {
+ return None;
+ }
+ Some(Fields::from_slice_unfiltered(pats))
}
PatKind::Constant { .. } | PatKind::Range { .. } => {
@@ -2439,50 +2593,39 @@
// - Single value: add a row if the pattern contains the constructor.
// - Range: add a row if the constructor intersects the pattern.
if let IntRange(ctor) = constructor {
- match IntRange::from_pat(cx.tcx, cx.param_env, pat) {
- Some(pat) => ctor.intersection(cx.tcx, &pat).map(|_| {
- // Constructor splitting should ensure that all intersections we encounter
- // are actually inclusions.
- assert!(ctor.is_subrange(&pat));
- PatStack::default()
- }),
- _ => None,
- }
+ let pat = IntRange::from_pat(cx.tcx, cx.param_env, pat)?;
+ ctor.intersection(cx.tcx, &pat)?;
+ // Constructor splitting should ensure that all intersections we encounter
+ // are actually inclusions.
+ assert!(ctor.is_subrange(&pat));
} else {
// Fallback for non-ranges and ranges that involve
// floating-point numbers, which are not conveniently handled
// by `IntRange`. For these cases, the constructor may not be a
// range so intersection actually devolves into being covered
// by the pattern.
- constructor_covered_by_range(cx.tcx, cx.param_env, constructor, pat)
- .map(|()| PatStack::default())
+ constructor_covered_by_range(cx.tcx, cx.param_env, constructor, pat)?;
}
+ Some(Fields::empty())
}
PatKind::Array { ref prefix, ref slice, ref suffix }
| PatKind::Slice { ref prefix, ref slice, ref suffix } => match *constructor {
Slice(_) => {
+ // Number of subpatterns for this pattern
let pat_len = prefix.len() + suffix.len();
- if let Some(slice_count) = ctor_wild_subpatterns.len().checked_sub(pat_len) {
- if slice_count == 0 || slice.is_some() {
- Some(
- prefix
- .iter()
- .chain(
- ctor_wild_subpatterns
- .iter()
- .skip(prefix.len())
- .take(slice_count)
- .chain(suffix.iter()),
- )
- .collect(),
- )
- } else {
- None
- }
- } else {
- None
+ // Number of subpatterns for this constructor
+ let arity = ctor_wild_subpatterns.len();
+
+ if (slice.is_none() && arity != pat_len) || pat_len > arity {
+ return None;
}
+
+ // Replace the prefix and the suffix with the given patterns, leaving wildcards in
+ // the middle if there was a subslice pattern `..`.
+ let prefix = prefix.iter().enumerate();
+ let suffix = suffix.iter().enumerate().map(|(i, p)| (arity - suffix.len() + i, p));
+ Some(ctor_wild_subpatterns.replace_fields_indexed(prefix.chain(suffix)))
}
ConstantValue(cv) => {
match slice_pat_covered_by_const(
@@ -2494,7 +2637,7 @@
suffix,
cx.param_env,
) {
- Ok(true) => Some(PatStack::default()),
+ Ok(true) => Some(Fields::empty()),
Ok(false) => None,
Err(ErrorReported) => None,
}
diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs
index 65ff311..7075026 100644
--- a/src/librustc_mir_build/hair/pattern/check_match.rs
+++ b/src/librustc_mir_build/hair/pattern/check_match.rs
@@ -187,9 +187,9 @@
let matrix = check_arms(&mut cx, &inlined_arms, source);
// Fifth, check if the match is exhaustive.
- let scrut_ty = self.tables.node_type(scrut.hir_id);
// Note: An empty match isn't the same as an empty matrix for diagnostics purposes,
// since an empty matrix can occur when there are arms, if those arms all have guards.
+ let scrut_ty = self.tables.expr_ty_adjusted(scrut);
let is_empty_match = inlined_arms.is_empty();
check_exhaustive(&mut cx, scrut_ty, scrut.span, &matrix, scrut.hir_id, is_empty_match);
}
diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs
index d2f1d11..e0ad0ac 100644
--- a/src/librustc_passes/entry.rs
+++ b/src/librustc_passes/entry.rs
@@ -51,7 +51,7 @@
fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType)> {
assert_eq!(cnum, LOCAL_CRATE);
- let any_exe = tcx.sess.crate_types.borrow().iter().any(|ty| *ty == CrateType::Executable);
+ let any_exe = tcx.sess.crate_types().iter().any(|ty| *ty == CrateType::Executable);
if !any_exe {
// No need to find a main function.
return None;
diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs
index 7c169d6..cac71b3 100644
--- a/src/librustc_passes/reachable.rs
+++ b/src/librustc_passes/reachable.rs
@@ -376,7 +376,7 @@
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
let any_library =
- tcx.sess.crate_types.borrow().iter().any(|ty| {
+ tcx.sess.crate_types().iter().any(|ty| {
*ty == CrateType::Rlib || *ty == CrateType::Dylib || *ty == CrateType::ProcMacro
});
let mut reachable_context = ReachableContext {
diff --git a/src/librustc_passes/weak_lang_items.rs b/src/librustc_passes/weak_lang_items.rs
index 8a58162..96ec236 100644
--- a/src/librustc_passes/weak_lang_items.rs
+++ b/src/librustc_passes/weak_lang_items.rs
@@ -37,7 +37,7 @@
fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
// We only need to check for the presence of weak lang items if we're
// emitting something that's not an rlib.
- let needs_check = tcx.sess.crate_types.borrow().iter().any(|kind| match *kind {
+ let needs_check = tcx.sess.crate_types().iter().any(|kind| match *kind {
CrateType::Dylib
| CrateType::ProcMacro
| CrateType::Cdylib
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index b474b23..9a63e39 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -90,14 +90,14 @@
fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> bool {
let ty::GenericPredicates { parent: _, predicates } = predicates;
for (predicate, _span) in predicates {
- match predicate {
- ty::Predicate::Trait(poly_predicate, _) => {
+ match predicate.kind() {
+ ty::PredicateKind::Trait(poly_predicate, _) => {
let ty::TraitPredicate { trait_ref } = *poly_predicate.skip_binder();
if self.visit_trait(trait_ref) {
return true;
}
}
- ty::Predicate::Projection(poly_predicate) => {
+ ty::PredicateKind::Projection(poly_predicate) => {
let ty::ProjectionPredicate { projection_ty, ty } =
*poly_predicate.skip_binder();
if ty.visit_with(self) {
@@ -107,13 +107,13 @@
return true;
}
}
- ty::Predicate::TypeOutlives(poly_predicate) => {
+ ty::PredicateKind::TypeOutlives(poly_predicate) => {
let ty::OutlivesPredicate(ty, _region) = *poly_predicate.skip_binder();
if ty.visit_with(self) {
return true;
}
}
- ty::Predicate::RegionOutlives(..) => {}
+ ty::PredicateKind::RegionOutlives(..) => {}
_ => bug!("unexpected predicate: {:?}", predicate),
}
}
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 988ec3d..c32b823 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -126,8 +126,8 @@
}
crate fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {
- let def_id = match self.macro_defs.get(&expn_id) {
- Some(def_id) => *def_id,
+ let def_id = match expn_id.expn_data().macro_def_id {
+ Some(def_id) => def_id,
None => return self.ast_transform_scopes.get(&expn_id).unwrap_or(&self.graph_root),
};
if let Some(id) = self.definitions.as_local_node_id(def_id) {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index bfb7f08..34368a0 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -922,7 +922,6 @@
dummy_ext_bang: Lrc<SyntaxExtension>,
dummy_ext_derive: Lrc<SyntaxExtension>,
non_macro_attrs: [Lrc<SyntaxExtension>; 2],
- macro_defs: FxHashMap<ExpnId, DefId>,
local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
ast_transform_scopes: FxHashMap<ExpnId, Module<'a>>,
unused_macros: NodeMap<Span>,
@@ -1152,9 +1151,6 @@
let mut invocation_parent_scopes = FxHashMap::default();
invocation_parent_scopes.insert(ExpnId::root(), ParentScope::module(graph_root));
- let mut macro_defs = FxHashMap::default();
- macro_defs.insert(ExpnId::root(), root_def_id);
-
let features = session.features_untracked();
let non_macro_attr =
|mark_used| Lrc::new(SyntaxExtension::non_macro_attr(mark_used, session.edition()));
@@ -1229,7 +1225,6 @@
invocation_parent_scopes,
output_macro_rules_scopes: Default::default(),
helper_attrs: Default::default(),
- macro_defs,
local_macro_def_scopes: FxHashMap::default(),
name_already_seen: FxHashMap::default(),
potentially_unused_imports: Vec::new(),
@@ -1335,8 +1330,8 @@
fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
loop {
- match self.macro_defs.get(&ctxt.outer_expn()) {
- Some(&def_id) => return def_id,
+ match ctxt.outer_expn().expn_data().macro_def_id {
+ Some(def_id) => return def_id,
None => ctxt.remove_mark(),
};
}
@@ -1820,7 +1815,7 @@
&& module.expansion.is_descendant_of(parent.expansion)
{
// The macro is a proc macro derive
- if let Some(&def_id) = self.macro_defs.get(&module.expansion) {
+ if let Some(def_id) = module.expansion.expn_data().macro_def_id {
if let Some(ext) = self.get_macro_by_def_id(def_id) {
if !ext.is_builtin && ext.macro_kind() == MacroKind::Derive {
if parent.expansion.outer_expn_is_descendant_of(span.ctxt()) {
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 1b6268d..7027c82 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -186,6 +186,7 @@
call_site,
self.session.edition(),
features.into(),
+ None,
)));
let parent_scope = if let Some(module_id) = parent_module_id {
@@ -290,13 +291,17 @@
let (ext, res) = self.smart_resolve_macro_path(path, kind, parent_scope, force)?;
let span = invoc.span();
- invoc_id.set_expn_data(ext.expn_data(parent_scope.expansion, span, fast_print_path(path)));
+ invoc_id.set_expn_data(ext.expn_data(
+ parent_scope.expansion,
+ span,
+ fast_print_path(path),
+ res.opt_def_id(),
+ ));
- if let Res::Def(_, def_id) = res {
+ if let Res::Def(_, _) = res {
if after_derive {
self.session.span_err(span, "macro attributes must be placed before `#[derive]`");
}
- self.macro_defs.insert(invoc_id, def_id);
let normal_module_def_id = self.macro_def_scope(invoc_id).normal_ancestor_id;
self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id);
}
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 43fd2b1..3bd68a9 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -87,7 +87,7 @@
pub fn compilation_output(&self, crate_name: &str) -> PathBuf {
let sess = &self.tcx.sess;
// Save-analysis is emitted per whole session, not per each crate type
- let crate_type = sess.crate_types.borrow()[0];
+ let crate_type = sess.crate_types()[0];
let outputs = &*self.tcx.output_filenames(LOCAL_CRATE);
if outputs.outputs.contains_key(&OutputType::Metadata) {
@@ -987,8 +987,7 @@
error!("Could not create directory {}: {}", root_path.display(), e);
}
- let executable =
- sess.crate_types.borrow().iter().any(|ct| *ct == CrateType::Executable);
+ let executable = sess.crate_types().iter().any(|ct| *ct == CrateType::Executable);
let mut out_name = if executable { String::new() } else { "lib".to_owned() };
out_name.push_str(&self.cratename);
out_name.push_str(&sess.opts.cg.extra_filename);
diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs
index 5f34a39..5bdd7b6 100644
--- a/src/librustc_session/config.rs
+++ b/src/librustc_session/config.rs
@@ -5,7 +5,7 @@
use crate::lint;
use crate::search_paths::SearchPath;
-use crate::utils::NativeLibraryKind;
+use crate::utils::NativeLibKind;
use crate::{early_error, early_warn, Session};
use rustc_data_structures::fx::FxHashSet;
@@ -1452,7 +1452,7 @@
fn parse_libs(
matches: &getopts::Matches,
error_format: ErrorOutputType,
-) -> Vec<(String, Option<String>, Option<NativeLibraryKind>)> {
+) -> Vec<(String, Option<String>, NativeLibKind)> {
matches
.opt_strs("l")
.into_iter()
@@ -1462,13 +1462,11 @@
let mut parts = s.splitn(2, '=');
let kind = parts.next().unwrap();
let (name, kind) = match (parts.next(), kind) {
- (None, name) => (name, None),
- (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))
- }
+ (None, name) => (name, NativeLibKind::Unspecified),
+ (Some(name), "dylib") => (name, NativeLibKind::Dylib),
+ (Some(name), "framework") => (name, NativeLibKind::Framework),
+ (Some(name), "static") => (name, NativeLibKind::StaticBundle),
+ (Some(name), "static-nobundle") => (name, NativeLibKind::StaticNoBundle),
(_, s) => {
early_error(
error_format,
@@ -1480,9 +1478,7 @@
);
}
};
- if kind == Some(NativeLibraryKind::NativeStaticNobundle)
- && !nightly_options::is_nightly_build()
- {
+ if kind == NativeLibKind::StaticNoBundle && !nightly_options::is_nightly_build() {
early_error(
error_format,
"the library kind 'static-nobundle' is only \
@@ -2003,7 +1999,7 @@
SymbolManglingVersion,
};
use crate::lint;
- use crate::utils::NativeLibraryKind;
+ use crate::utils::NativeLibKind;
use rustc_feature::UnstableFeatures;
use rustc_span::edition::Edition;
use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel};
@@ -2062,7 +2058,6 @@
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<NativeLibraryKind>);
impl_dep_tracking_hash_via_hash!(CrateType);
impl_dep_tracking_hash_via_hash!(MergeFunctions);
impl_dep_tracking_hash_via_hash!(PanicStrategy);
@@ -2073,7 +2068,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!(NativeLibraryKind);
+ impl_dep_tracking_hash_via_hash!(NativeLibKind);
impl_dep_tracking_hash_via_hash!(Sanitizer);
impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
impl_dep_tracking_hash_via_hash!(CFGuard);
@@ -2088,11 +2083,7 @@
impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
impl_dep_tracking_hash_for_sortable_vec_of!(CrateType);
impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level));
- impl_dep_tracking_hash_for_sortable_vec_of!((
- String,
- Option<String>,
- Option<NativeLibraryKind>
- ));
+ impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>, NativeLibKind));
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/options.rs b/src/librustc_session/options.rs
index a8d213a..3b6c21e 100644
--- a/src/librustc_session/options.rs
+++ b/src/librustc_session/options.rs
@@ -3,7 +3,7 @@
use crate::early_error;
use crate::lint;
use crate::search_paths::SearchPath;
-use crate::utils::NativeLibraryKind;
+use crate::utils::NativeLibKind;
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
use rustc_target::spec::{RelocModel, RelroLevel, TargetTriple, TlsModel};
@@ -93,7 +93,7 @@
describe_lints: bool [UNTRACKED],
output_types: OutputTypes [TRACKED],
search_paths: Vec<SearchPath> [UNTRACKED],
- libs: Vec<(String, Option<String>, Option<NativeLibraryKind>)> [TRACKED],
+ libs: Vec<(String, Option<String>, NativeLibKind)> [TRACKED],
maybe_sysroot: Option<PathBuf> [UNTRACKED],
target_triple: TargetTriple [TRACKED],
diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs
index 69d3e99..746e353 100644
--- a/src/librustc_session/parse.rs
+++ b/src/librustc_session/parse.rs
@@ -4,7 +4,7 @@
use crate::lint::{BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId};
use rustc_ast::node_id::NodeId;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::sync::{Lock, Lrc, Once};
+use rustc_data_structures::sync::{Lock, Lrc, OnceCell};
use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
use rustc_errors::{error_code, Applicability, DiagnosticBuilder};
use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
@@ -130,7 +130,7 @@
/// operation token that followed it, but that the parser cannot identify without further
/// analysis.
pub ambiguous_block_expr_parse: Lock<FxHashMap<Span, Span>>,
- pub injected_crate_name: Once<Symbol>,
+ pub injected_crate_name: OnceCell<Symbol>,
pub gated_spans: GatedSpans,
pub symbol_gallery: SymbolGallery,
/// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors.
@@ -156,7 +156,7 @@
source_map,
buffered_lints: Lock::new(vec![]),
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
- injected_crate_name: Once::new(),
+ injected_crate_name: OnceCell::new(),
gated_spans: GatedSpans::default(),
symbol_gallery: SymbolGallery::default(),
reached_eof: Lock::new(false),
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index 143401d..f2f02cb 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -13,7 +13,7 @@
use rustc_data_structures::jobserver::{self, Client};
use rustc_data_structures::profiling::{duration_to_secs_str, SelfProfiler, SelfProfilerRef};
use rustc_data_structures::sync::{
- self, AtomicU64, AtomicUsize, Lock, Lrc, Once, OneThread, Ordering, Ordering::SeqCst,
+ self, AtomicU64, AtomicUsize, Lock, Lrc, OnceCell, OneThread, Ordering, Ordering::SeqCst,
};
use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter;
use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType};
@@ -77,25 +77,25 @@
/// (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 crate_types: Once<Vec<CrateType>>,
+ crate_types: OnceCell<Vec<CrateType>>,
/// The `crate_disambiguator` is constructed out of all the `-C metadata`
/// arguments passed to the compiler. Its value together with the crate-name
/// forms a unique global identifier for the crate. It is used to allow
/// multiple crates with the same name to coexist. See the
/// `rustc_codegen_llvm::back::symbol_names` module for more information.
- pub crate_disambiguator: Once<CrateDisambiguator>,
+ pub crate_disambiguator: OnceCell<CrateDisambiguator>,
- features: Once<rustc_feature::Features>,
+ features: OnceCell<rustc_feature::Features>,
/// The maximum recursion limit for potentially infinitely recursive
/// operations such as auto-dereference and monomorphization.
- pub recursion_limit: Once<usize>,
+ pub recursion_limit: OnceCell<usize>,
/// The maximum length of types during monomorphization.
- pub type_length_limit: Once<usize>,
+ pub type_length_limit: OnceCell<usize>,
/// The maximum blocks a const expression can evaluate.
- pub const_eval_limit: Once<usize>,
+ pub const_eval_limit: OnceCell<usize>,
incr_comp_session: OneThread<RefCell<IncrCompSession>>,
/// Used for incremental compilation tests. Will only be populated if
@@ -244,7 +244,27 @@
}
pub fn local_crate_disambiguator(&self) -> CrateDisambiguator {
- *self.crate_disambiguator.get()
+ self.crate_disambiguator.get().copied().unwrap()
+ }
+
+ pub fn crate_types(&self) -> &[CrateType] {
+ self.crate_types.get().unwrap().as_slice()
+ }
+
+ pub fn init_crate_types(&self, crate_types: Vec<CrateType>) {
+ self.crate_types.set(crate_types).expect("`crate_types` was initialized twice")
+ }
+
+ pub fn recursion_limit(&self) -> usize {
+ self.recursion_limit.get().copied().unwrap()
+ }
+
+ pub fn type_length_limit(&self) -> usize {
+ self.type_length_limit.get().copied().unwrap()
+ }
+
+ pub fn const_eval_limit(&self) -> usize {
+ self.const_eval_limit.get().copied().unwrap()
}
pub fn struct_span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> {
@@ -500,11 +520,14 @@
/// dependency tracking. Use tcx.features() instead.
#[inline]
pub fn features_untracked(&self) -> &rustc_feature::Features {
- self.features.get()
+ self.features.get().unwrap()
}
pub fn init_features(&self, features: rustc_feature::Features) {
- self.features.set(features);
+ match self.features.set(features) {
+ Ok(()) => {}
+ Err(_) => panic!("`features` was initialized twice"),
+ }
}
/// Calculates the flavor of LTO to use for this compilation.
@@ -1208,12 +1231,12 @@
local_crate_source_file,
working_dir,
one_time_diagnostics: Default::default(),
- crate_types: Once::new(),
- crate_disambiguator: Once::new(),
- features: Once::new(),
- recursion_limit: Once::new(),
- type_length_limit: Once::new(),
- const_eval_limit: Once::new(),
+ crate_types: OnceCell::new(),
+ crate_disambiguator: OnceCell::new(),
+ features: OnceCell::new(),
+ recursion_limit: OnceCell::new(),
+ type_length_limit: OnceCell::new(),
+ const_eval_limit: OnceCell::new(),
incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
cgu_reuse_tracker,
prof,
diff --git a/src/librustc_session/utils.rs b/src/librustc_session/utils.rs
index fda11b6..b97308c 100644
--- a/src/librustc_session/utils.rs
+++ b/src/librustc_session/utils.rs
@@ -11,17 +11,22 @@
}
#[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,
+pub enum NativeLibKind {
+ /// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC) included
+ /// when linking a final binary, but not when archiving an rlib.
+ StaticNoBundle,
+ /// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC) included
+ /// when linking a final binary, but also included when archiving an rlib.
+ StaticBundle,
+ /// Dynamic library (e.g. `libfoo.so` on Linux)
+ /// or an import library corresponding to a dynamic library (e.g. `foo.lib` on Windows/MSVC).
+ Dylib,
+ /// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library.
+ RawDylib,
+ /// A macOS-specific kind of dynamic libraries.
+ Framework,
+ /// The library kind wasn't specified, `Dylib` is currently used as a default.
+ Unspecified,
}
-rustc_data_structures::impl_stable_hash_via_hash!(NativeLibraryKind);
+rustc_data_structures::impl_stable_hash_via_hash!(NativeLibKind);
diff --git a/src/librustc_span/hygiene.rs b/src/librustc_span/hygiene.rs
index 23c3dcc..c0fb84e 100644
--- a/src/librustc_span/hygiene.rs
+++ b/src/librustc_span/hygiene.rs
@@ -25,6 +25,7 @@
// because getting it wrong can lead to nested `HygieneData::with` calls that
// trigger runtime aborts. (Fortunately these are obvious and easy to fix.)
+use crate::def_id::{DefId, CRATE_DEF_INDEX};
use crate::edition::Edition;
use crate::symbol::{kw, sym, Symbol};
use crate::GLOBALS;
@@ -155,7 +156,12 @@
impl HygieneData {
crate fn new(edition: Edition) -> Self {
HygieneData {
- expn_data: vec![Some(ExpnData::default(ExpnKind::Root, DUMMY_SP, edition))],
+ expn_data: vec![Some(ExpnData::default(
+ ExpnKind::Root,
+ DUMMY_SP,
+ edition,
+ Some(DefId::local(CRATE_DEF_INDEX)),
+ ))],
syntax_context_data: vec![SyntaxContextData {
outer_expn: ExpnId::root(),
outer_transparency: Transparency::Opaque,
@@ -673,11 +679,19 @@
pub local_inner_macros: bool,
/// Edition of the crate in which the macro is defined.
pub edition: Edition,
+ /// The `DefId` of the macro being invoked,
+ /// if this `ExpnData` corresponds to a macro invocation
+ pub macro_def_id: Option<DefId>,
}
impl ExpnData {
/// Constructs expansion data with default properties.
- pub fn default(kind: ExpnKind, call_site: Span, edition: Edition) -> ExpnData {
+ pub fn default(
+ kind: ExpnKind,
+ call_site: Span,
+ edition: Edition,
+ macro_def_id: Option<DefId>,
+ ) -> ExpnData {
ExpnData {
kind,
parent: ExpnId::root(),
@@ -687,6 +701,7 @@
allow_internal_unsafe: false,
local_inner_macros: false,
edition,
+ macro_def_id,
}
}
@@ -695,10 +710,11 @@
call_site: Span,
edition: Edition,
allow_internal_unstable: Lrc<[Symbol]>,
+ macro_def_id: Option<DefId>,
) -> ExpnData {
ExpnData {
allow_internal_unstable: Some(allow_internal_unstable),
- ..ExpnData::default(kind, call_site, edition)
+ ..ExpnData::default(kind, call_site, edition, macro_def_id)
}
}
diff --git a/src/librustc_target/asm/mod.rs b/src/librustc_target/asm/mod.rs
index 05aa85e..774146a 100644
--- a/src/librustc_target/asm/mod.rs
+++ b/src/librustc_target/asm/mod.rs
@@ -223,19 +223,19 @@
name: Symbol,
) -> Result<Self, &'static str> {
// FIXME: use direct symbol comparison for register names
- name.with(|name| {
- Ok(match arch {
- InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
- Self::X86(X86InlineAsmReg::parse(arch, has_feature, name)?)
- }
- InlineAsmArch::Arm => Self::Arm(ArmInlineAsmReg::parse(arch, has_feature, name)?),
- InlineAsmArch::AArch64 => {
- Self::AArch64(AArch64InlineAsmReg::parse(arch, has_feature, name)?)
- }
- InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
- Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, name)?)
- }
- })
+ // Use `Symbol::as_str` instead of `Symbol::with` here because `has_feature` may access `Symbol`.
+ let name = name.as_str();
+ Ok(match arch {
+ InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
+ Self::X86(X86InlineAsmReg::parse(arch, has_feature, &name)?)
+ }
+ InlineAsmArch::Arm => Self::Arm(ArmInlineAsmReg::parse(arch, has_feature, &name)?),
+ InlineAsmArch::AArch64 => {
+ Self::AArch64(AArch64InlineAsmReg::parse(arch, has_feature, &name)?)
+ }
+ InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
+ Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, &name)?)
+ }
})
}
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index 8770e03..df17231 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -618,6 +618,7 @@
("i686-uwp-windows-msvc", i686_uwp_windows_msvc),
("i586-pc-windows-msvc", i586_pc_windows_msvc),
("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc),
+ ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc),
("asmjs-unknown-emscripten", asmjs_unknown_emscripten),
("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
diff --git a/src/librustc_target/spec/thumbv7a_uwp_windows_msvc.rs b/src/librustc_target/spec/thumbv7a_uwp_windows_msvc.rs
new file mode 100644
index 0000000..ff2e892
--- /dev/null
+++ b/src/librustc_target/spec/thumbv7a_uwp_windows_msvc.rs
@@ -0,0 +1,30 @@
+use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+ let mut base = super::windows_uwp_msvc_base::opts();
+ base.max_atomic_width = Some(64);
+ base.has_elf_tls = true;
+
+ // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is
+ // implemented for windows/arm in LLVM
+ base.panic_strategy = PanicStrategy::Abort;
+
+ Ok(Target {
+ llvm_target: "thumbv7a-pc-windows-msvc".to_string(),
+ target_endian: "little".to_string(),
+ target_pointer_width: "32".to_string(),
+ target_c_int_width: "32".to_string(),
+ data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+ arch: "arm".to_string(),
+ target_os: "windows".to_string(),
+ target_env: "msvc".to_string(),
+ target_vendor: "uwp".to_string(),
+ linker_flavor: LinkerFlavor::Msvc,
+ options: TargetOptions {
+ features: "+vfp3,+neon".to_string(),
+ cpu: "generic".to_string(),
+ abi_blacklist: super::arm_base::abi_blacklist(),
+ ..base
+ },
+ })
+}
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 d26efc0..475a33a 100644
--- a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
+++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
@@ -1,6 +1,6 @@
use std::iter;
-use super::{crt_objects, LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};
pub fn target() -> Result<Target, String> {
const PRE_LINK_ARGS: &[&str] = &[
@@ -68,8 +68,6 @@
PRE_LINK_ARGS.iter().cloned().map(String::from).collect(),
))
.collect(),
- // FIXME: libunwind is certainly not a CRT object, use some other option instead.
- post_link_objects: crt_objects::all("libunwind.a"),
override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(String::from).collect()),
relax_elf_relocations: true,
..Default::default()
diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs
index 396965f..484677d 100644
--- a/src/librustc_trait_selection/opaque_types.rs
+++ b/src/librustc_trait_selection/opaque_types.rs
@@ -670,7 +670,7 @@
// `least_region`. We cannot use `push_outlives_components` because regions in
// closure signatures are not included in their outlives components. We need to
// ensure all regions outlive the given bound so that we don't end up with,
-// say, `ReScope` appearing in a return type and causing ICEs when other
+// say, `ReVar` appearing in a return type and causing ICEs when other
// functions end up with region constraints involving regions from other
// functions.
//
@@ -816,7 +816,7 @@
// The regions that we expect from borrow checking.
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
- ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) | ty::ReScope(_) => {
+ ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) => {
// All of the regions in the type should either have been
// erased by writeback, or mapped back to named regions by
// borrow checking.
@@ -835,7 +835,6 @@
if let Some(hidden_ty) = self.hidden_ty.take() {
unexpected_hidden_region_diagnostic(
self.tcx,
- None,
self.tcx.def_span(self.opaque_type_def_id),
hidden_ty,
r,
@@ -1168,7 +1167,7 @@
debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
for predicate in &bounds.predicates {
- if let ty::Predicate::Projection(projection) = &predicate {
+ if let ty::PredicateKind::Projection(projection) = predicate.kind() {
if projection.skip_binder().ty.references_error() {
// No point on adding these obligations since there's a type error involved.
return ty_var;
@@ -1269,17 +1268,17 @@
traits::elaborate_predicates(tcx, predicates)
.filter_map(|obligation| {
debug!("required_region_bounds(obligation={:?})", obligation);
- match obligation.predicate {
- ty::Predicate::Projection(..)
- | ty::Predicate::Trait(..)
- | ty::Predicate::Subtype(..)
- | ty::Predicate::WellFormed(..)
- | ty::Predicate::ObjectSafe(..)
- | ty::Predicate::ClosureKind(..)
- | ty::Predicate::RegionOutlives(..)
- | ty::Predicate::ConstEvaluatable(..)
- | ty::Predicate::ConstEquate(..) => None,
- ty::Predicate::TypeOutlives(predicate) => {
+ match obligation.predicate.kind() {
+ ty::PredicateKind::Projection(..)
+ | ty::PredicateKind::Trait(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::RegionOutlives(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => None,
+ ty::PredicateKind::TypeOutlives(predicate) => {
// Search for a bound of the form `erased_self_ty
// : 'a`, but be wary of something like `for<'a>
// erased_self_ty : 'a` (we interpret a
diff --git a/src/librustc_trait_selection/traits/auto_trait.rs b/src/librustc_trait_selection/traits/auto_trait.rs
index e19ddcd..716cbce 100644
--- a/src/librustc_trait_selection/traits/auto_trait.rs
+++ b/src/librustc_trait_selection/traits/auto_trait.rs
@@ -341,7 +341,8 @@
already_visited.remove(&pred);
self.add_user_pred(
&mut user_computed_preds,
- ty::Predicate::Trait(pred, hir::Constness::NotConst),
+ ty::PredicateKind::Trait(pred, hir::Constness::NotConst)
+ .to_predicate(self.tcx),
);
predicates.push_back(pred);
} else {
@@ -411,8 +412,10 @@
) {
let mut should_add_new = true;
user_computed_preds.retain(|&old_pred| {
- if let (&ty::Predicate::Trait(new_trait, _), ty::Predicate::Trait(old_trait, _)) =
- (&new_pred, old_pred)
+ if let (
+ ty::PredicateKind::Trait(new_trait, _),
+ ty::PredicateKind::Trait(old_trait, _),
+ ) = (new_pred.kind(), old_pred.kind())
{
if new_trait.def_id() == old_trait.def_id() {
let new_substs = new_trait.skip_binder().trait_ref.substs;
@@ -630,8 +633,8 @@
//
// We check this by calling is_of_param on the relevant types
// from the various possible predicates
- match &predicate {
- &ty::Predicate::Trait(p, _) => {
+ match predicate.kind() {
+ &ty::PredicateKind::Trait(p, _) => {
if self.is_param_no_infer(p.skip_binder().trait_ref.substs)
&& !only_projections
&& is_new_pred
@@ -640,7 +643,7 @@
}
predicates.push_back(p);
}
- &ty::Predicate::Projection(p) => {
+ &ty::PredicateKind::Projection(p) => {
debug!(
"evaluate_nested_obligations: examining projection predicate {:?}",
predicate
@@ -765,12 +768,12 @@
}
}
}
- &ty::Predicate::RegionOutlives(ref binder) => {
+ ty::PredicateKind::RegionOutlives(ref binder) => {
if select.infcx().region_outlives_predicate(&dummy_cause, binder).is_err() {
return false;
}
}
- &ty::Predicate::TypeOutlives(ref binder) => {
+ ty::PredicateKind::TypeOutlives(ref binder) => {
match (
binder.no_bound_vars(),
binder.map_bound_ref(|pred| pred.0).no_bound_vars(),
diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs
index 139b860..b1c6815 100644
--- a/src/librustc_trait_selection/traits/error_reporting/mod.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs
@@ -252,8 +252,8 @@
.emit();
return;
}
- match obligation.predicate {
- ty::Predicate::Trait(ref trait_predicate, _) => {
+ match obligation.predicate.kind() {
+ ty::PredicateKind::Trait(ref trait_predicate, _) => {
let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
if self.tcx.sess.has_errors() && trait_predicate.references_error() {
@@ -308,7 +308,7 @@
"{}",
message.unwrap_or_else(|| format!(
"the trait bound `{}` is not satisfied{}",
- trait_ref.without_const().to_predicate(),
+ trait_ref.without_const().to_predicate(tcx),
post_message,
))
);
@@ -468,10 +468,11 @@
trait_pred
});
let unit_obligation = Obligation {
- predicate: ty::Predicate::Trait(
+ predicate: ty::PredicateKind::Trait(
predicate,
hir::Constness::NotConst,
- ),
+ )
+ .to_predicate(self.tcx),
..obligation.clone()
};
if self.predicate_may_hold(&unit_obligation) {
@@ -489,14 +490,14 @@
err
}
- ty::Predicate::Subtype(ref predicate) => {
+ ty::PredicateKind::Subtype(ref predicate) => {
// Errors for Subtype predicates show up as
// `FulfillmentErrorCode::CodeSubtypeError`,
// not selection error.
span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
}
- ty::Predicate::RegionOutlives(ref predicate) => {
+ ty::PredicateKind::RegionOutlives(ref predicate) => {
let predicate = self.resolve_vars_if_possible(predicate);
let err = self
.region_outlives_predicate(&obligation.cause, &predicate)
@@ -512,7 +513,7 @@
)
}
- ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
+ ty::PredicateKind::Projection(..) | ty::PredicateKind::TypeOutlives(..) => {
let predicate = self.resolve_vars_if_possible(&obligation.predicate);
struct_span_err!(
self.tcx.sess,
@@ -523,12 +524,12 @@
)
}
- ty::Predicate::ObjectSafe(trait_def_id) => {
+ &ty::PredicateKind::ObjectSafe(trait_def_id) => {
let violations = self.tcx.object_safety_violations(trait_def_id);
report_object_safety_error(self.tcx, span, trait_def_id, violations)
}
- ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
+ &ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
let found_kind = self.closure_kind(closure_substs).unwrap();
let closure_span =
self.tcx.sess.source_map().guess_head_span(
@@ -587,7 +588,7 @@
return;
}
- ty::Predicate::WellFormed(ty) => {
+ ty::PredicateKind::WellFormed(ty) => {
if !self.tcx.sess.opts.debugging_opts.chalk {
// WF predicates cannot themselves make
// errors. They can only block due to
@@ -605,7 +606,7 @@
}
}
- ty::Predicate::ConstEvaluatable(..) => {
+ ty::PredicateKind::ConstEvaluatable(..) => {
// Errors for `ConstEvaluatable` predicates show up as
// `SelectionError::ConstEvalFailure`,
// not `Unimplemented`.
@@ -616,7 +617,7 @@
)
}
- ty::Predicate::ConstEquate(..) => {
+ ty::PredicateKind::ConstEquate(..) => {
// Errors for `ConstEquate` predicates show up as
// `SelectionError::ConstEvalFailure`,
// not `Unimplemented`.
@@ -999,12 +1000,15 @@
trait_ref: &ty::PolyTraitRef<'tcx>,
);
- fn mk_obligation_for_def_id(
+ /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the
+ /// `trait_ref`.
+ ///
+ /// For this to work, `new_self_ty` must have no escaping bound variables.
+ fn mk_trait_obligation_with_new_self_ty(
&self,
- def_id: DefId,
- output_ty: Ty<'tcx>,
- cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
+ trait_ref: &ty::PolyTraitRef<'tcx>,
+ new_self_ty: Ty<'tcx>,
) -> PredicateObligation<'tcx>;
fn maybe_report_ambiguity(
@@ -1021,13 +1025,13 @@
fn note_obligation_cause(
&self,
- err: &mut DiagnosticBuilder<'_>,
+ err: &mut DiagnosticBuilder<'tcx>,
obligation: &PredicateObligation<'tcx>,
);
fn suggest_unsized_bound_if_applicable(
&self,
- err: &mut DiagnosticBuilder<'_>,
+ err: &mut DiagnosticBuilder<'tcx>,
obligation: &PredicateObligation<'tcx>,
);
@@ -1046,8 +1050,8 @@
return true;
}
- let (cond, error) = match (cond, error) {
- (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error),
+ let (cond, error) = match (cond.kind(), error.kind()) {
+ (ty::PredicateKind::Trait(..), ty::PredicateKind::Trait(error, _)) => (cond, error),
_ => {
// FIXME: make this work in other cases too.
return false;
@@ -1055,7 +1059,7 @@
};
for obligation in super::elaborate_predicates(self.tcx, std::iter::once(*cond)) {
- if let ty::Predicate::Trait(implication, _) = obligation.predicate {
+ if let ty::PredicateKind::Trait(implication, _) = obligation.predicate.kind() {
let error = error.to_poly_trait_ref();
let implication = implication.to_poly_trait_ref();
// FIXME: I'm just not taking associated types at all here.
@@ -1135,7 +1139,7 @@
//
// this can fail if the problem was higher-ranked, in which
// cause I have no idea for a good error message.
- if let ty::Predicate::Projection(ref data) = predicate {
+ if let ty::PredicateKind::Projection(ref data) = predicate.kind() {
let mut selcx = SelectionContext::new(self);
let (data, _) = self.replace_bound_vars_with_fresh_vars(
obligation.cause.span,
@@ -1379,16 +1383,24 @@
}
}
- fn mk_obligation_for_def_id(
+ fn mk_trait_obligation_with_new_self_ty(
&self,
- def_id: DefId,
- output_ty: Ty<'tcx>,
- cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
+ trait_ref: &ty::PolyTraitRef<'tcx>,
+ new_self_ty: Ty<'tcx>,
) -> PredicateObligation<'tcx> {
- let new_trait_ref =
- ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
- Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate())
+ assert!(!new_self_ty.has_escaping_bound_vars());
+
+ let trait_ref = trait_ref.map_bound_ref(|tr| ty::TraitRef {
+ substs: self.tcx.mk_substs_trait(new_self_ty, &tr.substs[1..]),
+ ..*tr
+ });
+
+ Obligation::new(
+ ObligationCause::dummy(),
+ param_env,
+ trait_ref.without_const().to_predicate(self.tcx),
+ )
}
fn maybe_report_ambiguity(
@@ -1415,8 +1427,8 @@
return;
}
- let mut err = match predicate {
- ty::Predicate::Trait(ref data, _) => {
+ let mut err = match predicate.kind() {
+ ty::PredicateKind::Trait(ref data, _) => {
let trait_ref = data.to_poly_trait_ref();
let self_ty = trait_ref.self_ty();
debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
@@ -1515,7 +1527,7 @@
err
}
- ty::Predicate::WellFormed(ty) => {
+ ty::PredicateKind::WellFormed(ty) => {
// Same hacky approach as above to avoid deluging user
// with error messages.
if ty.references_error() || self.tcx.sess.has_errors() {
@@ -1524,7 +1536,7 @@
self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
}
- ty::Predicate::Subtype(ref data) => {
+ ty::PredicateKind::Subtype(ref data) => {
if data.references_error() || self.tcx.sess.has_errors() {
// no need to overload user in such cases
return;
@@ -1534,7 +1546,7 @@
assert!(a.is_ty_var() && b.is_ty_var());
self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
}
- ty::Predicate::Projection(ref data) => {
+ ty::PredicateKind::Projection(ref data) => {
let trait_ref = data.to_poly_trait_ref(self.tcx);
let self_ty = trait_ref.self_ty();
let ty = data.skip_binder().ty;
@@ -1627,7 +1639,7 @@
let obligation = Obligation::new(
ObligationCause::dummy(),
param_env,
- cleaned_pred.without_const().to_predicate(),
+ cleaned_pred.without_const().to_predicate(selcx.tcx()),
);
self.predicate_may_hold(&obligation)
@@ -1636,7 +1648,7 @@
fn note_obligation_cause(
&self,
- err: &mut DiagnosticBuilder<'_>,
+ err: &mut DiagnosticBuilder<'tcx>,
obligation: &PredicateObligation<'tcx>,
) {
// First, attempt to add note to this error with an async-await-specific
@@ -1654,13 +1666,13 @@
fn suggest_unsized_bound_if_applicable(
&self,
- err: &mut DiagnosticBuilder<'_>,
+ err: &mut DiagnosticBuilder<'tcx>,
obligation: &PredicateObligation<'tcx>,
) {
if let (
- ty::Predicate::Trait(pred, _),
+ ty::PredicateKind::Trait(pred, _),
ObligationCauseCode::BindingObligation(item_def_id, span),
- ) = (&obligation.predicate, &obligation.cause.code)
+ ) = (obligation.predicate.kind(), &obligation.cause.code)
{
if let (Some(generics), true) = (
self.tcx.hir().get_if_local(*item_def_id).as_ref().and_then(|n| n.generics()),
diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
index b8771d5..5c85855 100644
--- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
@@ -38,14 +38,14 @@
fn suggest_restricting_param_bound(
&self,
err: &mut DiagnosticBuilder<'_>,
- trait_ref: ty::PolyTraitRef<'_>,
+ trait_ref: ty::PolyTraitRef<'tcx>,
body_id: hir::HirId,
);
fn suggest_borrow_on_unsized_slice(
&self,
code: &ObligationCauseCode<'tcx>,
- err: &mut DiagnosticBuilder<'tcx>,
+ err: &mut DiagnosticBuilder<'_>,
);
fn get_closure_name(
@@ -66,7 +66,7 @@
fn suggest_add_reference_to_arg(
&self,
obligation: &PredicateObligation<'tcx>,
- err: &mut DiagnosticBuilder<'tcx>,
+ err: &mut DiagnosticBuilder<'_>,
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
points_at_arg: bool,
has_custom_message: bool,
@@ -75,14 +75,14 @@
fn suggest_remove_reference(
&self,
obligation: &PredicateObligation<'tcx>,
- err: &mut DiagnosticBuilder<'tcx>,
+ err: &mut DiagnosticBuilder<'_>,
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
);
fn suggest_change_mut(
&self,
obligation: &PredicateObligation<'tcx>,
- err: &mut DiagnosticBuilder<'tcx>,
+ err: &mut DiagnosticBuilder<'_>,
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
points_at_arg: bool,
);
@@ -90,7 +90,7 @@
fn suggest_semicolon_removal(
&self,
obligation: &PredicateObligation<'tcx>,
- err: &mut DiagnosticBuilder<'tcx>,
+ err: &mut DiagnosticBuilder<'_>,
span: Span,
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
);
@@ -99,7 +99,7 @@
fn suggest_impl_trait(
&self,
- err: &mut DiagnosticBuilder<'tcx>,
+ err: &mut DiagnosticBuilder<'_>,
span: Span,
obligation: &PredicateObligation<'tcx>,
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
@@ -107,7 +107,7 @@
fn point_at_returns_when_relevant(
&self,
- err: &mut DiagnosticBuilder<'tcx>,
+ err: &mut DiagnosticBuilder<'_>,
obligation: &PredicateObligation<'tcx>,
);
@@ -138,11 +138,11 @@
err: &mut DiagnosticBuilder<'_>,
interior_or_upvar_span: GeneratorInteriorOrUpvar,
interior_extra_info: Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>,
- inner_generator_body: Option<&hir::Body<'_>>,
+ inner_generator_body: Option<&hir::Body<'tcx>>,
outer_generator: Option<DefId>,
- trait_ref: ty::TraitRef<'_>,
+ trait_ref: ty::TraitRef<'tcx>,
target_ty: Ty<'tcx>,
- tables: &ty::TypeckTables<'_>,
+ tables: &ty::TypeckTables<'tcx>,
obligation: &PredicateObligation<'tcx>,
next_code: Option<&ObligationCauseCode<'tcx>>,
);
@@ -183,12 +183,13 @@
/// it can also be an `impl Trait` param that needs to be decomposed to a type
/// param for cleaner code.
fn suggest_restriction(
- generics: &hir::Generics<'_>,
+ tcx: TyCtxt<'tcx>,
+ generics: &hir::Generics<'tcx>,
msg: &str,
err: &mut DiagnosticBuilder<'_>,
fn_sig: Option<&hir::FnSig<'_>>,
projection: Option<&ty::ProjectionTy<'_>>,
- trait_ref: ty::PolyTraitRef<'_>,
+ trait_ref: ty::PolyTraitRef<'tcx>,
super_traits: Option<(&Ident, &hir::GenericBounds<'_>)>,
) {
// When we are dealing with a trait, `super_traits` will be `Some`:
@@ -243,7 +244,7 @@
// FIXME: modify the `trait_ref` instead of string shenanigans.
// Turn `<impl Trait as Foo>::Bar: Qux` into `<T as Foo>::Bar: Qux`.
- let pred = trait_ref.without_const().to_predicate().to_string();
+ let pred = trait_ref.without_const().to_predicate(tcx).to_string();
let pred = pred.replace(&impl_trait_str, &type_param_name);
let mut sugg = vec![
match generics
@@ -285,9 +286,10 @@
} else {
// Trivial case: `T` needs an extra bound: `T: Bound`.
let (sp, suggestion) = match super_traits {
- None => {
- predicate_constraint(generics, trait_ref.without_const().to_predicate().to_string())
- }
+ None => predicate_constraint(
+ generics,
+ trait_ref.without_const().to_predicate(tcx).to_string(),
+ ),
Some((ident, bounds)) => match bounds {
[.., bound] => (
bound.span().shrink_to_hi(),
@@ -313,7 +315,7 @@
fn suggest_restricting_param_bound(
&self,
mut err: &mut DiagnosticBuilder<'_>,
- trait_ref: ty::PolyTraitRef<'_>,
+ trait_ref: ty::PolyTraitRef<'tcx>,
body_id: hir::HirId,
) {
let self_ty = trait_ref.self_ty();
@@ -336,6 +338,7 @@
assert!(param_ty);
// Restricting `Self` for a single method.
suggest_restriction(
+ self.tcx,
&generics,
"`Self`",
err,
@@ -355,7 +358,7 @@
assert!(param_ty);
// Restricting `Self` for a single method.
suggest_restriction(
- &generics, "`Self`", err, None, projection, trait_ref, None,
+ self.tcx, &generics, "`Self`", err, None, projection, trait_ref, None,
);
return;
}
@@ -375,6 +378,7 @@
}) if projection.is_some() => {
// Missing restriction on associated type of type parameter (unmet projection).
suggest_restriction(
+ self.tcx,
&generics,
"the associated type",
err,
@@ -393,6 +397,7 @@
}) if projection.is_some() => {
// Missing restriction on associated type of type parameter (unmet projection).
suggest_restriction(
+ self.tcx,
&generics,
"the associated type",
err,
@@ -450,7 +455,7 @@
fn suggest_borrow_on_unsized_slice(
&self,
code: &ObligationCauseCode<'tcx>,
- err: &mut DiagnosticBuilder<'tcx>,
+ err: &mut DiagnosticBuilder<'_>,
) {
if let &ObligationCauseCode::VariableType(hir_id) = code {
let parent_node = self.tcx.hir().get_parent_node(hir_id);
@@ -527,14 +532,17 @@
};
let msg = format!("use parentheses to call the {}", callable);
- let obligation = self.mk_obligation_for_def_id(
- trait_ref.def_id(),
- output_ty.skip_binder(),
- obligation.cause.clone(),
- obligation.param_env,
- );
+ // `mk_trait_obligation_with_new_self_ty` only works for types with no escaping bound
+ // variables, so bail out if we have any.
+ let output_ty = match output_ty.no_bound_vars() {
+ Some(ty) => ty,
+ None => return,
+ };
- match self.evaluate_obligation(&obligation) {
+ let new_obligation =
+ self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_ref, output_ty);
+
+ match self.evaluate_obligation(&new_obligation) {
Ok(
EvaluationResult::EvaluatedToOk
| EvaluationResult::EvaluatedToOkModuloRegions
@@ -601,7 +609,7 @@
fn suggest_add_reference_to_arg(
&self,
obligation: &PredicateObligation<'tcx>,
- err: &mut DiagnosticBuilder<'tcx>,
+ err: &mut DiagnosticBuilder<'_>,
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
points_at_arg: bool,
has_custom_message: bool,
@@ -624,8 +632,9 @@
let new_obligation = Obligation::new(
ObligationCause::dummy(),
param_env,
- new_trait_ref.without_const().to_predicate(),
+ new_trait_ref.without_const().to_predicate(self.tcx),
);
+
if self.predicate_must_hold_modulo_regions(&new_obligation) {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
// We have a very specific type of error, where just borrowing this argument
@@ -633,6 +642,7 @@
// original type obligation, not the last one that failed, which is arbitrary.
// Because of this, we modify the error to refer to the original obligation and
// return early in the caller.
+
let msg = format!(
"the trait bound `{}: {}` is not satisfied",
found,
@@ -655,12 +665,23 @@
obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
),
);
- err.span_suggestion(
- span,
- "consider borrowing here",
- format!("&{}", snippet),
- Applicability::MaybeIncorrect,
- );
+
+ // This if is to prevent a special edge-case
+ if !span.from_expansion() {
+ // We don't want a borrowing suggestion on the fields in structs,
+ // ```
+ // struct Foo {
+ // the_foos: Vec<Foo>
+ // }
+ // ```
+
+ err.span_suggestion(
+ span,
+ "consider borrowing here",
+ format!("&{}", snippet),
+ Applicability::MaybeIncorrect,
+ );
+ }
return true;
}
}
@@ -673,10 +694,9 @@
fn suggest_remove_reference(
&self,
obligation: &PredicateObligation<'tcx>,
- err: &mut DiagnosticBuilder<'tcx>,
+ err: &mut DiagnosticBuilder<'_>,
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
) {
- let trait_ref = trait_ref.skip_binder();
let span = obligation.cause.span;
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
@@ -687,17 +707,16 @@
return;
}
- let mut trait_type = trait_ref.self_ty();
+ let mut suggested_ty = trait_ref.self_ty();
for refs_remaining in 0..refs_number {
- if let ty::Ref(_, t_type, _) = trait_type.kind {
- trait_type = t_type;
+ if let ty::Ref(_, inner_ty, _) = suggested_ty.kind {
+ suggested_ty = inner_ty;
- let new_obligation = self.mk_obligation_for_def_id(
- trait_ref.def_id,
- trait_type,
- ObligationCause::dummy(),
+ let new_obligation = self.mk_trait_obligation_with_new_self_ty(
obligation.param_env,
+ trait_ref,
+ suggested_ty,
);
if self.predicate_may_hold(&new_obligation) {
@@ -735,7 +754,7 @@
fn suggest_change_mut(
&self,
obligation: &PredicateObligation<'tcx>,
- err: &mut DiagnosticBuilder<'tcx>,
+ err: &mut DiagnosticBuilder<'_>,
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
points_at_arg: bool,
) {
@@ -764,20 +783,20 @@
return;
}
- let trait_type = match mutability {
+ let suggested_ty = match mutability {
hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
};
- let new_obligation = self.mk_obligation_for_def_id(
- trait_ref.skip_binder().def_id,
- trait_type,
- ObligationCause::dummy(),
+ let new_obligation = self.mk_trait_obligation_with_new_self_ty(
obligation.param_env,
+ &trait_ref,
+ suggested_ty,
);
-
- if self.evaluate_obligation_no_overflow(&new_obligation).must_apply_modulo_regions()
- {
+ let suggested_ty_would_satisfy_obligation = self
+ .evaluate_obligation_no_overflow(&new_obligation)
+ .must_apply_modulo_regions();
+ if suggested_ty_would_satisfy_obligation {
let sp = self
.tcx
.sess
@@ -794,7 +813,7 @@
err.note(&format!(
"`{}` is implemented for `{:?}`, but not for `{:?}`",
trait_ref.print_only_trait_path(),
- trait_type,
+ suggested_ty,
trait_ref.skip_binder().self_ty(),
));
}
@@ -806,7 +825,7 @@
fn suggest_semicolon_removal(
&self,
obligation: &PredicateObligation<'tcx>,
- err: &mut DiagnosticBuilder<'tcx>,
+ err: &mut DiagnosticBuilder<'_>,
span: Span,
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
) {
@@ -852,7 +871,7 @@
/// emitted.
fn suggest_impl_trait(
&self,
- err: &mut DiagnosticBuilder<'tcx>,
+ err: &mut DiagnosticBuilder<'_>,
span: Span,
obligation: &PredicateObligation<'tcx>,
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
@@ -1048,7 +1067,7 @@
fn point_at_returns_when_relevant(
&self,
- err: &mut DiagnosticBuilder<'tcx>,
+ err: &mut DiagnosticBuilder<'_>,
obligation: &PredicateObligation<'tcx>,
) {
match obligation.cause.code.peel_derives() {
@@ -1237,8 +1256,8 @@
// the type. The last generator (`outer_generator` below) has information about where the
// bound was introduced. At least one generator should be present for this diagnostic to be
// modified.
- let (mut trait_ref, mut target_ty) = match obligation.predicate {
- ty::Predicate::Trait(p, _) => {
+ let (mut trait_ref, mut target_ty) = match obligation.predicate.kind() {
+ ty::PredicateKind::Trait(p, _) => {
(Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
}
_ => (None, None),
@@ -1430,11 +1449,11 @@
err: &mut DiagnosticBuilder<'_>,
interior_or_upvar_span: GeneratorInteriorOrUpvar,
interior_extra_info: Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>,
- inner_generator_body: Option<&hir::Body<'_>>,
+ inner_generator_body: Option<&hir::Body<'tcx>>,
outer_generator: Option<DefId>,
- trait_ref: ty::TraitRef<'_>,
+ trait_ref: ty::TraitRef<'tcx>,
target_ty: Ty<'tcx>,
- tables: &ty::TypeckTables<'_>,
+ tables: &ty::TypeckTables<'tcx>,
obligation: &PredicateObligation<'tcx>,
next_code: Option<&ObligationCauseCode<'tcx>>,
) {
@@ -1788,7 +1807,7 @@
err.note(&format!("required because it appears within the type `{}`", ty));
obligated_types.push(ty);
- let parent_predicate = parent_trait_ref.without_const().to_predicate();
+ let parent_predicate = parent_trait_ref.without_const().to_predicate(tcx);
if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
self.note_obligation_cause_code(
err,
@@ -1805,7 +1824,7 @@
parent_trait_ref.print_only_trait_path(),
parent_trait_ref.skip_binder().self_ty()
));
- let parent_predicate = parent_trait_ref.without_const().to_predicate();
+ let parent_predicate = parent_trait_ref.without_const().to_predicate(tcx);
self.note_obligation_cause_code(
err,
&parent_predicate,
@@ -1815,7 +1834,7 @@
}
ObligationCauseCode::DerivedObligation(ref data) => {
let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
- let parent_predicate = parent_trait_ref.without_const().to_predicate();
+ let parent_predicate = parent_trait_ref.without_const().to_predicate(tcx);
self.note_obligation_cause_code(
err,
&parent_predicate,
@@ -1857,7 +1876,7 @@
}
fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
- let current_limit = self.tcx.sess.recursion_limit.get();
+ let current_limit = self.tcx.sess.recursion_limit();
let suggested_limit = current_limit * 2;
err.help(&format!(
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
@@ -1873,7 +1892,7 @@
span: Span,
) {
debug!(
- "suggest_await_befor_try: obligation={:?}, span={:?}, trait_ref={:?}, trait_ref_self_ty={:?}",
+ "suggest_await_before_try: obligation={:?}, span={:?}, trait_ref={:?}, trait_ref_self_ty={:?}",
obligation,
span,
trait_ref,
@@ -1928,16 +1947,15 @@
);
debug!(
- "suggest_await_befor_try: normalized_projection_type {:?}",
+ "suggest_await_before_try: normalized_projection_type {:?}",
self.resolve_vars_if_possible(&normalized_ty)
);
- let try_obligation = self.mk_obligation_for_def_id(
- trait_ref.def_id(),
- normalized_ty,
- obligation.cause.clone(),
+ let try_obligation = self.mk_trait_obligation_with_new_self_ty(
obligation.param_env,
+ trait_ref,
+ normalized_ty,
);
- debug!("suggest_await_befor_try: try_trait_obligation {:?}", try_obligation);
+ debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation);
if self.predicate_may_hold(&try_obligation) && impls_future {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
if snippet.ends_with('?') {
@@ -2061,7 +2079,7 @@
}
fn suggest_trait_object_return_type_alternatives(
- err: &mut DiagnosticBuilder<'tcx>,
+ err: &mut DiagnosticBuilder<'_>,
ret_ty: Span,
trait_obj: &str,
is_object_safe: bool,
diff --git a/src/librustc_trait_selection/traits/fulfill.rs b/src/librustc_trait_selection/traits/fulfill.rs
index 98f6ac0..e44163f 100644
--- a/src/librustc_trait_selection/traits/fulfill.rs
+++ b/src/librustc_trait_selection/traits/fulfill.rs
@@ -83,7 +83,7 @@
// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
-static_assert_size!(PendingPredicateObligation<'_>, 136);
+static_assert_size!(PendingPredicateObligation<'_>, 112);
impl<'a, 'tcx> FulfillmentContext<'tcx> {
/// Creates a new fulfillment context.
@@ -322,8 +322,8 @@
let infcx = self.selcx.infcx();
- match obligation.predicate {
- ty::Predicate::Trait(ref data, _) => {
+ match obligation.predicate.kind() {
+ ty::PredicateKind::Trait(ref data, _) => {
let trait_obligation = obligation.with(*data);
if data.is_global() {
@@ -378,14 +378,14 @@
}
}
- ty::Predicate::RegionOutlives(ref binder) => {
+ ty::PredicateKind::RegionOutlives(ref binder) => {
match infcx.region_outlives_predicate(&obligation.cause, binder) {
Ok(()) => ProcessResult::Changed(vec![]),
Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)),
}
}
- ty::Predicate::TypeOutlives(ref binder) => {
+ ty::PredicateKind::TypeOutlives(ref binder) => {
// Check if there are higher-ranked vars.
match binder.no_bound_vars() {
// If there are, inspect the underlying type further.
@@ -429,7 +429,7 @@
}
}
- ty::Predicate::Projection(ref data) => {
+ ty::PredicateKind::Projection(ref data) => {
let project_obligation = obligation.with(*data);
match project::poly_project_and_unify_type(self.selcx, &project_obligation) {
Ok(None) => {
@@ -443,7 +443,7 @@
}
}
- ty::Predicate::ObjectSafe(trait_def_id) => {
+ &ty::PredicateKind::ObjectSafe(trait_def_id) => {
if !self.selcx.tcx().is_object_safe(trait_def_id) {
ProcessResult::Error(CodeSelectionError(Unimplemented))
} else {
@@ -451,7 +451,7 @@
}
}
- ty::Predicate::ClosureKind(_, closure_substs, kind) => {
+ &ty::PredicateKind::ClosureKind(_, closure_substs, kind) => {
match self.selcx.infcx().closure_kind(closure_substs) {
Some(closure_kind) => {
if closure_kind.extends(kind) {
@@ -464,7 +464,7 @@
}
}
- ty::Predicate::WellFormed(ty) => {
+ &ty::PredicateKind::WellFormed(ty) => {
match wf::obligations(
self.selcx.infcx(),
obligation.param_env,
@@ -481,7 +481,7 @@
}
}
- ty::Predicate::Subtype(ref subtype) => {
+ ty::PredicateKind::Subtype(subtype) => {
match self.selcx.infcx().subtype_predicate(
&obligation.cause,
obligation.param_env,
@@ -510,7 +510,7 @@
}
}
- ty::Predicate::ConstEvaluatable(def_id, substs) => {
+ &ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
match self.selcx.infcx().const_eval_resolve(
obligation.param_env,
def_id,
@@ -523,7 +523,7 @@
}
}
- ty::Predicate::ConstEquate(c1, c2) => {
+ ty::PredicateKind::ConstEquate(c1, c2) => {
debug!("equating consts: c1={:?} c2={:?}", c1, c2);
let stalled_on = &mut pending_obligation.stalled_on;
diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs
index 9592f93..d8e99dc 100644
--- a/src/librustc_trait_selection/traits/mod.rs
+++ b/src/librustc_trait_selection/traits/mod.rs
@@ -28,7 +28,6 @@
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
-use rustc_middle::middle::region;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
use rustc_middle::ty::{
@@ -143,7 +142,7 @@
param_env,
cause: ObligationCause::misc(span, hir::CRATE_HIR_ID),
recursion_depth: 0,
- predicate: trait_ref.without_const().to_predicate(),
+ predicate: trait_ref.without_const().to_predicate(infcx.tcx),
};
let result = infcx.predicate_must_hold_modulo_regions(&obligation);
@@ -237,15 +236,12 @@
debug!("do_normalize_predictes: normalized predicates = {:?}", predicates);
- let region_scope_tree = region::ScopeTree::default();
-
// We can use the `elaborated_env` here; the region code only
// cares about declarations like `'a: 'b`.
let outlives_env = OutlivesEnvironment::new(elaborated_env);
infcx.resolve_regions_and_report_errors(
region_context,
- ®ion_scope_tree,
&outlives_env,
RegionckMode::default(),
);
@@ -333,8 +329,8 @@
// This works fairly well because trait matching does not actually care about param-env
// TypeOutlives predicates - these are normally used by regionck.
let outlives_predicates: Vec<_> = predicates
- .drain_filter(|predicate| match predicate {
- ty::Predicate::TypeOutlives(..) => true,
+ .drain_filter(|predicate| match predicate.kind() {
+ ty::PredicateKind::TypeOutlives(..) => true,
_ => false,
})
.collect();
@@ -557,7 +553,7 @@
cause: ObligationCause::dummy(),
param_env,
recursion_depth: 0,
- predicate: trait_ref.without_const().to_predicate(),
+ predicate: trait_ref.without_const().to_predicate(tcx),
};
tcx.infer_ctxt().enter(|infcx| infcx.predicate_must_hold_modulo_regions(&obligation))
}
diff --git a/src/librustc_trait_selection/traits/object_safety.rs b/src/librustc_trait_selection/traits/object_safety.rs
index 1bfcacd..b2d684e 100644
--- a/src/librustc_trait_selection/traits/object_safety.rs
+++ b/src/librustc_trait_selection/traits/object_safety.rs
@@ -245,8 +245,8 @@
.iter()
.map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), sp))
.filter_map(|(predicate, &sp)| {
- match predicate {
- ty::Predicate::Trait(ref data, _) => {
+ match predicate.kind() {
+ ty::PredicateKind::Trait(ref data, _) => {
// In the case of a trait predicate, we can skip the "self" type.
if data.skip_binder().trait_ref.substs[1..].iter().any(has_self_ty) {
Some(sp)
@@ -254,7 +254,7 @@
None
}
}
- ty::Predicate::Projection(ref data) => {
+ ty::PredicateKind::Projection(ref data) => {
// And similarly for projections. This should be redundant with
// the previous check because any projection should have a
// matching `Trait` predicate with the same inputs, but we do
@@ -276,14 +276,14 @@
None
}
}
- ty::Predicate::WellFormed(..)
- | ty::Predicate::ObjectSafe(..)
- | ty::Predicate::TypeOutlives(..)
- | ty::Predicate::RegionOutlives(..)
- | ty::Predicate::ClosureKind(..)
- | ty::Predicate::Subtype(..)
- | ty::Predicate::ConstEvaluatable(..)
- | ty::Predicate::ConstEquate(..) => None,
+ ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::TypeOutlives(..)
+ | ty::PredicateKind::RegionOutlives(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => None,
}
})
.collect()
@@ -304,19 +304,22 @@
// Search for a predicate like `Self : Sized` amongst the trait bounds.
let predicates = tcx.predicates_of(def_id);
let predicates = predicates.instantiate_identity(tcx).predicates;
- elaborate_predicates(tcx, predicates.into_iter()).any(|obligation| match obligation.predicate {
- ty::Predicate::Trait(ref trait_pred, _) => {
- trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0)
+ elaborate_predicates(tcx, predicates.into_iter()).any(|obligation| {
+ match obligation.predicate.kind() {
+ ty::PredicateKind::Trait(ref trait_pred, _) => {
+ trait_pred.def_id() == sized_def_id
+ && trait_pred.skip_binder().self_ty().is_param(0)
+ }
+ ty::PredicateKind::Projection(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::RegionOutlives(..)
+ | ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::TypeOutlives(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => false,
}
- ty::Predicate::Projection(..)
- | ty::Predicate::Subtype(..)
- | ty::Predicate::RegionOutlives(..)
- | ty::Predicate::WellFormed(..)
- | ty::Predicate::ObjectSafe(..)
- | ty::Predicate::ClosureKind(..)
- | ty::Predicate::TypeOutlives(..)
- | ty::Predicate::ConstEvaluatable(..)
- | ty::Predicate::ConstEquate(..) => false,
})
}
@@ -636,7 +639,7 @@
substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
}
.without_const()
- .to_predicate();
+ .to_predicate(tcx);
// U: Trait<Arg1, ..., ArgN>
let trait_predicate = {
@@ -649,7 +652,7 @@
}
});
- ty::TraitRef { def_id: unsize_did, substs }.without_const().to_predicate()
+ ty::TraitRef { def_id: unsize_did, substs }.without_const().to_predicate(tcx)
};
let caller_bounds: Vec<Predicate<'tcx>> = param_env
@@ -672,7 +675,7 @@
substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
}
.without_const()
- .to_predicate();
+ .to_predicate(tcx);
Obligation::new(ObligationCause::dummy(), param_env, predicate)
};
diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs
index f102f34..914485f 100644
--- a/src/librustc_trait_selection/traits/project.rs
+++ b/src/librustc_trait_selection/traits/project.rs
@@ -332,7 +332,7 @@
Reveal::UserFacing => ty,
Reveal::All => {
- let recursion_limit = *self.tcx().sess.recursion_limit.get();
+ let recursion_limit = self.tcx().sess.recursion_limit();
if self.depth >= recursion_limit {
let obligation = Obligation::with_depth(
self.cause.clone(),
@@ -436,7 +436,7 @@
});
let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var });
let obligation =
- Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate());
+ Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate(tcx));
obligations.push(obligation);
ty_var
})
@@ -520,7 +520,7 @@
);
// But for now, let's classify this as an overflow:
- let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
+ let recursion_limit = selcx.tcx().sess.recursion_limit();
let obligation =
Obligation::with_depth(cause, recursion_limit, param_env, projection_ty);
selcx.infcx().report_overflow_error(&obligation, false);
@@ -665,7 +665,7 @@
let mut obligations: Vec<_> = result
.obligations
.iter()
- .filter(|obligation| match obligation.predicate {
+ .filter(|obligation| match obligation.predicate.kind() {
// We found a `T: Foo<X = U>` predicate, let's check
// if `U` references any unresolved type
// variables. In principle, we only care if this
@@ -675,7 +675,9 @@
// indirect obligations (e.g., we project to `?0`,
// but we have `T: Foo<X = ?1>` and `?1: Bar<X =
// ?0>`).
- ty::Predicate::Projection(ref data) => infcx.unresolved_type_vars(&data.ty()).is_some(),
+ ty::PredicateKind::Projection(ref data) => {
+ infcx.unresolved_type_vars(&data.ty()).is_some()
+ }
// We are only interested in `T: Foo<X = U>` predicates, whre
// `U` references one of `unresolved_type_vars`. =)
@@ -724,7 +726,7 @@
cause,
recursion_depth: depth,
param_env,
- predicate: trait_ref.without_const().to_predicate(),
+ predicate: trait_ref.without_const().to_predicate(infcx.tcx),
}
}
@@ -759,7 +761,7 @@
cause,
recursion_depth: depth,
param_env,
- predicate: trait_ref.without_const().to_predicate(),
+ predicate: trait_ref.without_const().to_predicate(selcx.tcx()),
};
let tcx = selcx.infcx().tcx;
let def_id = projection_ty.item_def_id;
@@ -812,7 +814,7 @@
) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> {
debug!("project(obligation={:?})", obligation);
- let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
+ let recursion_limit = selcx.tcx().sess.recursion_limit();
if obligation.recursion_depth >= recursion_limit {
debug!("project: overflow!");
return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
@@ -932,7 +934,7 @@
let infcx = selcx.infcx();
for predicate in env_predicates {
debug!("assemble_candidates_from_predicates: predicate={:?}", predicate);
- if let ty::Predicate::Projection(data) = predicate {
+ if let &ty::PredicateKind::Projection(data) = predicate.kind() {
let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
let is_match = same_def_id
@@ -1202,20 +1204,19 @@
object_ty
),
};
- let env_predicates =
- data.projection_bounds().map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate());
+ let env_predicates = data
+ .projection_bounds()
+ .map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate(selcx.tcx()));
let env_predicate = {
let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
// select only those projections that are actually projecting an
// item with the correct name
- let env_predicates = env_predicates.filter_map(|o| match o.predicate {
- ty::Predicate::Projection(data) => {
- if data.projection_def_id() == obligation.predicate.item_def_id {
- Some(data)
- } else {
- None
- }
+ let env_predicates = env_predicates.filter_map(|o| match o.predicate.kind() {
+ &ty::PredicateKind::Projection(data)
+ if data.projection_def_id() == obligation.predicate.item_def_id =>
+ {
+ Some(data)
}
_ => None,
});
diff --git a/src/librustc_trait_selection/traits/query/normalize.rs b/src/librustc_trait_selection/traits/query/normalize.rs
index 3b985a4..008ca8d 100644
--- a/src/librustc_trait_selection/traits/query/normalize.rs
+++ b/src/librustc_trait_selection/traits/query/normalize.rs
@@ -108,7 +108,7 @@
Reveal::UserFacing => ty,
Reveal::All => {
- let recursion_limit = *self.tcx().sess.recursion_limit.get();
+ let recursion_limit = self.tcx().sess.recursion_limit();
if self.anon_depth >= recursion_limit {
let obligation = Obligation::with_depth(
self.cause.clone(),
diff --git a/src/librustc_trait_selection/traits/query/type_op/prove_predicate.rs b/src/librustc_trait_selection/traits/query/type_op/prove_predicate.rs
index 981745a..5c8719d 100644
--- a/src/librustc_trait_selection/traits/query/type_op/prove_predicate.rs
+++ b/src/librustc_trait_selection/traits/query/type_op/prove_predicate.rs
@@ -1,6 +1,6 @@
use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
use crate::traits::query::Fallible;
-use rustc_middle::ty::{ParamEnvAnd, Predicate, TyCtxt};
+use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt};
pub use rustc_middle::traits::query::type_op::ProvePredicate;
@@ -15,7 +15,7 @@
// `&T`, accounts for about 60% percentage of the predicates
// we have to prove. No need to canonicalize and all that for
// such cases.
- if let Predicate::Trait(trait_ref, _) = key.value.predicate {
+ if let ty::PredicateKind::Trait(trait_ref, _) = key.value.predicate.kind() {
if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
if trait_ref.def_id() == sized_def_id {
if trait_ref.skip_binder().self_ty().is_trivially_sized(tcx) {
diff --git a/src/librustc_trait_selection/traits/select.rs b/src/librustc_trait_selection/traits/select.rs
index d903779..b402aba 100644
--- a/src/librustc_trait_selection/traits/select.rs
+++ b/src/librustc_trait_selection/traits/select.rs
@@ -414,14 +414,14 @@
None => self.check_recursion_limit(&obligation, &obligation)?,
}
- match obligation.predicate {
- ty::Predicate::Trait(ref t, _) => {
+ match obligation.predicate.kind() {
+ ty::PredicateKind::Trait(t, _) => {
debug_assert!(!t.has_escaping_bound_vars());
let obligation = obligation.with(*t);
self.evaluate_trait_predicate_recursively(previous_stack, obligation)
}
- ty::Predicate::Subtype(ref p) => {
+ ty::PredicateKind::Subtype(p) => {
// Does this code ever run?
match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {
Some(Ok(InferOk { mut obligations, .. })) => {
@@ -436,7 +436,7 @@
}
}
- ty::Predicate::WellFormed(ty) => match wf::obligations(
+ &ty::PredicateKind::WellFormed(ty) => match wf::obligations(
self.infcx,
obligation.param_env,
obligation.cause.body_id,
@@ -450,12 +450,12 @@
None => Ok(EvaluatedToAmbig),
},
- ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => {
+ ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::RegionOutlives(..) => {
// We do not consider region relationships when evaluating trait matches.
Ok(EvaluatedToOkModuloRegions)
}
- ty::Predicate::ObjectSafe(trait_def_id) => {
+ &ty::PredicateKind::ObjectSafe(trait_def_id) => {
if self.tcx().is_object_safe(trait_def_id) {
Ok(EvaluatedToOk)
} else {
@@ -463,7 +463,7 @@
}
}
- ty::Predicate::Projection(ref data) => {
+ ty::PredicateKind::Projection(data) => {
let project_obligation = obligation.with(*data);
match project::poly_project_and_unify_type(self, &project_obligation) {
Ok(Some(mut subobligations)) => {
@@ -484,7 +484,7 @@
}
}
- ty::Predicate::ClosureKind(_, closure_substs, kind) => {
+ &ty::PredicateKind::ClosureKind(_, closure_substs, kind) => {
match self.infcx.closure_kind(closure_substs) {
Some(closure_kind) => {
if closure_kind.extends(kind) {
@@ -497,7 +497,7 @@
}
}
- ty::Predicate::ConstEvaluatable(def_id, substs) => {
+ &ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
match self.tcx().const_eval_resolve(
obligation.param_env,
def_id,
@@ -511,7 +511,7 @@
}
}
- ty::Predicate::ConstEquate(c1, c2) => {
+ ty::PredicateKind::ConstEquate(c1, c2) => {
debug!("evaluate_predicate_recursively: equating consts c1={:?} c2={:?}", c1, c2);
let evaluate = |c: &'tcx ty::Const<'tcx>| {
@@ -676,8 +676,10 @@
// trait refs. This is important because it's only a cycle
// if the regions match exactly.
let cycle = stack.iter().skip(1).take_while(|s| s.depth >= cycle_depth);
+ let tcx = self.tcx();
let cycle = cycle.map(|stack| {
- ty::Predicate::Trait(stack.obligation.predicate, hir::Constness::NotConst)
+ ty::PredicateKind::Trait(stack.obligation.predicate, hir::Constness::NotConst)
+ .to_predicate(tcx)
});
if self.coinductive_match(cycle) {
debug!("evaluate_stack({:?}) --> recursive, coinductive", stack.fresh_trait_ref);
@@ -792,8 +794,8 @@
}
fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
- let result = match predicate {
- ty::Predicate::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()),
+ let result = match predicate.kind() {
+ ty::PredicateKind::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()),
_ => false,
};
debug!("coinductive_predicate({:?}) = {:?}", predicate, result);
@@ -917,8 +919,7 @@
obligation: &Obligation<'tcx, T>,
error_obligation: &Obligation<'tcx, V>,
) -> Result<(), OverflowError> {
- let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get();
- if obligation.recursion_depth >= recursion_limit {
+ if obligation.recursion_depth >= self.infcx.tcx.sess.recursion_limit() {
match self.query_mode {
TraitQueryMode::Standard => {
self.infcx().report_overflow_error(error_obligation, true);
@@ -2926,7 +2927,8 @@
obligations.push(Obligation::new(
obligation.cause.clone(),
obligation.param_env,
- ty::Predicate::ClosureKind(closure_def_id, substs, kind),
+ ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)
+ .to_predicate(self.tcx()),
));
}
@@ -3036,7 +3038,7 @@
cause,
obligation.recursion_depth + 1,
obligation.param_env,
- ty::Binder::bind(outlives).to_predicate(),
+ ty::Binder::bind(outlives).to_predicate(tcx),
));
}
@@ -3079,12 +3081,12 @@
tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
tcx.mk_substs_trait(source, &[]),
);
- nested.push(predicate_to_obligation(tr.without_const().to_predicate()));
+ nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx)));
// If the type is `Foo + 'a`, ensure that the type
// being cast to `Foo + 'a` outlives `'a`:
let outlives = ty::OutlivesPredicate(source, r);
- nested.push(predicate_to_obligation(ty::Binder::dummy(outlives).to_predicate()));
+ nested.push(predicate_to_obligation(ty::Binder::dummy(outlives).to_predicate(tcx)));
}
// `[T; n]` -> `[T]`
diff --git a/src/librustc_trait_selection/traits/util.rs b/src/librustc_trait_selection/traits/util.rs
index eff73cf..f2d3f0e 100644
--- a/src/librustc_trait_selection/traits/util.rs
+++ b/src/librustc_trait_selection/traits/util.rs
@@ -97,7 +97,7 @@
fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
let tcx = self.tcx;
let trait_ref = item.trait_ref();
- let pred = trait_ref.without_const().to_predicate();
+ let pred = trait_ref.without_const().to_predicate(tcx);
debug!("expand_trait_aliases: trait_ref={:?}", trait_ref);
@@ -110,7 +110,7 @@
// Don't recurse if this trait alias is already on the stack for the DFS search.
let anon_pred = anonymize_predicate(tcx, &pred);
if item.path.iter().rev().skip(1).any(|(tr, _)| {
- anonymize_predicate(tcx, &tr.without_const().to_predicate()) == anon_pred
+ anonymize_predicate(tcx, &tr.without_const().to_predicate(tcx)) == anon_pred
}) {
return false;
}
@@ -234,6 +234,7 @@
}
pub fn predicate_for_trait_ref<'tcx>(
+ tcx: TyCtxt<'tcx>,
cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
trait_ref: ty::TraitRef<'tcx>,
@@ -243,7 +244,7 @@
cause,
param_env,
recursion_depth,
- predicate: trait_ref.without_const().to_predicate(),
+ predicate: trait_ref.without_const().to_predicate(tcx),
}
}
@@ -258,7 +259,7 @@
) -> PredicateObligation<'tcx> {
let trait_ref =
ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(self_ty, params) };
- predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth)
+ predicate_for_trait_ref(tcx, cause, param_env, trait_ref, recursion_depth)
}
/// Casts a trait reference into a reference to one of its super
diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs
index 4d3bbfa..5118859 100644
--- a/src/librustc_trait_selection/traits/wf.rs
+++ b/src/librustc_trait_selection/traits/wf.rs
@@ -72,29 +72,29 @@
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
// (*) ok to skip binders, because wf code is prepared for it
- match *predicate {
- ty::Predicate::Trait(ref t, _) => {
+ match predicate.kind() {
+ ty::PredicateKind::Trait(t, _) => {
wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*)
}
- ty::Predicate::RegionOutlives(..) => {}
- ty::Predicate::TypeOutlives(ref t) => {
+ ty::PredicateKind::RegionOutlives(..) => {}
+ ty::PredicateKind::TypeOutlives(t) => {
wf.compute(t.skip_binder().0);
}
- ty::Predicate::Projection(ref t) => {
+ ty::PredicateKind::Projection(t) => {
let t = t.skip_binder(); // (*)
wf.compute_projection(t.projection_ty);
wf.compute(t.ty);
}
- ty::Predicate::WellFormed(t) => {
+ &ty::PredicateKind::WellFormed(t) => {
wf.compute(t);
}
- ty::Predicate::ObjectSafe(_) => {}
- ty::Predicate::ClosureKind(..) => {}
- ty::Predicate::Subtype(ref data) => {
+ ty::PredicateKind::ObjectSafe(_) => {}
+ ty::PredicateKind::ClosureKind(..) => {}
+ ty::PredicateKind::Subtype(data) => {
wf.compute(data.skip_binder().a); // (*)
wf.compute(data.skip_binder().b); // (*)
}
- ty::Predicate::ConstEvaluatable(def_id, substs) => {
+ &ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
let obligations = wf.nominal_obligations(def_id, substs);
wf.out.extend(obligations);
@@ -102,7 +102,7 @@
wf.compute(ty);
}
}
- ty::Predicate::ConstEquate(c1, c2) => {
+ ty::PredicateKind::ConstEquate(c1, c2) => {
wf.compute(c1.ty);
wf.compute(c2.ty);
}
@@ -170,8 +170,8 @@
hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::TyAlias(ty) => ty.span,
_ => impl_item_ref.span,
};
- match pred {
- ty::Predicate::Projection(proj) => {
+ match pred.kind() {
+ ty::PredicateKind::Projection(proj) => {
// The obligation comes not from the current `impl` nor the `trait` being
// implemented, but rather from a "second order" obligation, like in
// `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs`.
@@ -194,7 +194,7 @@
}
}
}
- ty::Predicate::Trait(pred, _) => {
+ ty::PredicateKind::Trait(pred, _) => {
// An associated item obligation born out of the `trait` failed to be met. An example
// can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
@@ -216,6 +216,10 @@
}
impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
+ fn tcx(&self) -> TyCtxt<'tcx> {
+ self.infcx.tcx
+ }
+
fn cause(&mut self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> {
traits::ObligationCause::new(self.span, self.body_id, code)
}
@@ -275,8 +279,15 @@
self.out.extend(obligations);
}
+ let tcx = self.tcx();
self.out.extend(trait_ref.substs.types().filter(|ty| !ty.has_escaping_bound_vars()).map(
- |ty| traits::Obligation::new(cause.clone(), param_env, ty::Predicate::WellFormed(ty)),
+ |ty| {
+ traits::Obligation::new(
+ cause.clone(),
+ param_env,
+ ty::PredicateKind::WellFormed(ty).to_predicate(tcx),
+ )
+ },
));
}
@@ -290,7 +301,7 @@
self.compute_trait_ref(&trait_ref, Elaborate::None);
if !data.has_escaping_bound_vars() {
- let predicate = trait_ref.without_const().to_predicate();
+ let predicate = trait_ref.without_const().to_predicate(self.infcx.tcx);
let cause = self.cause(traits::ProjectionWf(data));
self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
}
@@ -305,7 +316,8 @@
let obligations = self.nominal_obligations(def_id, substs);
self.out.extend(obligations);
- let predicate = ty::Predicate::ConstEvaluatable(def_id, substs);
+ let predicate =
+ ty::PredicateKind::ConstEvaluatable(def_id, substs).to_predicate(self.tcx());
let cause = self.cause(traits::MiscObligation);
self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
}
@@ -321,7 +333,7 @@
self.out.push(traits::Obligation::new(
cause,
self.param_env,
- trait_ref.without_const().to_predicate(),
+ trait_ref.without_const().to_predicate(self.infcx.tcx),
));
}
}
@@ -411,9 +423,10 @@
self.out.push(traits::Obligation::new(
cause,
param_env,
- ty::Predicate::TypeOutlives(ty::Binder::dummy(ty::OutlivesPredicate(
- rty, r,
- ))),
+ ty::PredicateKind::TypeOutlives(ty::Binder::dummy(
+ ty::OutlivesPredicate(rty, r),
+ ))
+ .to_predicate(self.tcx()),
));
}
}
@@ -493,16 +506,17 @@
// obligations that don't refer to Self and
// checking those
- let defer_to_coercion = self.infcx.tcx.features().object_safe_for_dispatch;
+ let defer_to_coercion = self.tcx().features().object_safe_for_dispatch;
if !defer_to_coercion {
let cause = self.cause(traits::MiscObligation);
let component_traits = data.auto_traits().chain(data.principal_def_id());
+ let tcx = self.tcx();
self.out.extend(component_traits.map(|did| {
traits::Obligation::new(
cause.clone(),
param_env,
- ty::Predicate::ObjectSafe(did),
+ ty::PredicateKind::ObjectSafe(did).to_predicate(tcx),
)
}));
}
@@ -528,7 +542,7 @@
self.out.push(traits::Obligation::new(
cause,
param_env,
- ty::Predicate::WellFormed(ty),
+ ty::PredicateKind::WellFormed(ty).to_predicate(self.tcx()),
));
} else {
// Yes, resolved, proceed with the result.
@@ -608,7 +622,7 @@
self.out.push(traits::Obligation::new(
cause,
self.param_env,
- outlives.to_predicate(),
+ outlives.to_predicate(self.infcx.tcx),
));
}
}
diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs
index 184b9a9..a33ada2 100644
--- a/src/librustc_traits/chalk/lowering.rs
+++ b/src/librustc_traits/chalk/lowering.rs
@@ -38,8 +38,7 @@
use rustc_middle::ty::fold::TypeFolder;
use rustc_middle::ty::subst::{GenericArg, SubstsRef};
use rustc_middle::ty::{
- self, Binder, BoundRegion, Predicate, Region, RegionKind, Ty, TyCtxt, TyKind, TypeFoldable,
- TypeVisitor,
+ self, Binder, BoundRegion, Region, RegionKind, Ty, TyCtxt, TyKind, TypeFoldable, TypeVisitor,
};
use rustc_span::def_id::DefId;
@@ -78,8 +77,8 @@
) -> chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'tcx>>> {
let clauses = self.environment.into_iter().filter_map(|clause| match clause {
ChalkEnvironmentClause::Predicate(predicate) => {
- match predicate {
- ty::Predicate::Trait(predicate, _) => {
+ match &predicate.kind() {
+ ty::PredicateKind::Trait(predicate, _) => {
let (predicate, binders, _named_regions) =
collect_bound_vars(interner, interner.tcx, predicate);
@@ -100,9 +99,9 @@
)
}
// FIXME(chalk): need to add RegionOutlives/TypeOutlives
- ty::Predicate::RegionOutlives(_) => None,
- ty::Predicate::TypeOutlives(_) => None,
- ty::Predicate::Projection(predicate) => {
+ ty::PredicateKind::RegionOutlives(_) => None,
+ ty::PredicateKind::TypeOutlives(_) => None,
+ ty::PredicateKind::Projection(predicate) => {
let (predicate, binders, _named_regions) =
collect_bound_vars(interner, interner.tcx, predicate);
@@ -122,12 +121,14 @@
.intern(interner),
)
}
- ty::Predicate::WellFormed(..)
- | ty::Predicate::ObjectSafe(..)
- | ty::Predicate::ClosureKind(..)
- | ty::Predicate::Subtype(..)
- | ty::Predicate::ConstEvaluatable(..)
- | ty::Predicate::ConstEquate(..) => bug!("unexpected predicate {}", predicate),
+ ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => {
+ bug!("unexpected predicate {}", predicate)
+ }
}
}
ChalkEnvironmentClause::TypeFromEnv(ty) => Some(
@@ -154,17 +155,17 @@
impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predicate<'tcx> {
fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::GoalData<RustInterner<'tcx>> {
- match self {
- Predicate::Trait(predicate, _) => predicate.lower_into(interner),
+ match self.kind() {
+ ty::PredicateKind::Trait(predicate, _) => predicate.lower_into(interner),
// FIXME(chalk): we need to register constraints.
- Predicate::RegionOutlives(_predicate) => {
+ ty::PredicateKind::RegionOutlives(_predicate) => {
chalk_ir::GoalData::All(chalk_ir::Goals::new(interner))
}
- Predicate::TypeOutlives(_predicate) => {
+ ty::PredicateKind::TypeOutlives(_predicate) => {
chalk_ir::GoalData::All(chalk_ir::Goals::new(interner))
}
- Predicate::Projection(predicate) => predicate.lower_into(interner),
- Predicate::WellFormed(ty) => match ty.kind {
+ ty::PredicateKind::Projection(predicate) => predicate.lower_into(interner),
+ ty::PredicateKind::WellFormed(ty) => match ty.kind {
// These types are always WF.
ty::Str | ty::Placeholder(..) | ty::Error | ty::Never => {
chalk_ir::GoalData::All(chalk_ir::Goals::new(interner))
@@ -188,11 +189,13 @@
//
// We can defer this, but ultimately we'll want to express
// some of these in terms of chalk operations.
- Predicate::ObjectSafe(..)
- | Predicate::ClosureKind(..)
- | Predicate::Subtype(..)
- | Predicate::ConstEvaluatable(..)
- | Predicate::ConstEquate(..) => chalk_ir::GoalData::All(chalk_ir::Goals::new(interner)),
+ ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => {
+ chalk_ir::GoalData::All(chalk_ir::Goals::new(interner))
+ }
}
}
}
@@ -391,7 +394,6 @@
ty::BrEnv => unimplemented!(),
},
ReFree(_) => unimplemented!(),
- ReScope(_) => unimplemented!(),
ReStatic => unimplemented!(),
ReVar(_) => unimplemented!(),
RePlaceholder(placeholder_region) => {
@@ -439,8 +441,8 @@
self,
interner: &RustInterner<'tcx>,
) -> Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>> {
- match &self {
- Predicate::Trait(predicate, _) => {
+ match &self.kind() {
+ ty::PredicateKind::Trait(predicate, _) => {
let (predicate, binders, _named_regions) =
collect_bound_vars(interner, interner.tcx, predicate);
@@ -449,16 +451,16 @@
chalk_ir::WhereClause::Implemented(predicate.trait_ref.lower_into(interner)),
))
}
- Predicate::RegionOutlives(_predicate) => None,
- Predicate::TypeOutlives(_predicate) => None,
- Predicate::Projection(_predicate) => None,
- Predicate::WellFormed(_ty) => None,
+ ty::PredicateKind::RegionOutlives(_predicate) => None,
+ ty::PredicateKind::TypeOutlives(_predicate) => None,
+ ty::PredicateKind::Projection(_predicate) => None,
+ ty::PredicateKind::WellFormed(_ty) => None,
- Predicate::ObjectSafe(..)
- | Predicate::ClosureKind(..)
- | Predicate::Subtype(..)
- | Predicate::ConstEvaluatable(..)
- | Predicate::ConstEquate(..) => bug!("unexpected predicate {}", &self),
+ ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => bug!("unexpected predicate {}", &self),
}
}
}
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index 08475d6..fb9c0d7 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -163,7 +163,7 @@
) -> Result<(), NoSolution> {
debug!("dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty);
- if depth >= *tcx.sess.recursion_limit.get() {
+ if depth >= tcx.sess.recursion_limit() {
constraints.overflows.push(ty);
return Ok(());
}
diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs
index eaaab87..5dee71a 100644
--- a/src/librustc_traits/implied_outlives_bounds.rs
+++ b/src/librustc_traits/implied_outlives_bounds.rs
@@ -94,28 +94,28 @@
// region relationships.
implied_bounds.extend(obligations.into_iter().flat_map(|obligation| {
assert!(!obligation.has_escaping_bound_vars());
- match obligation.predicate {
- ty::Predicate::Trait(..)
- | ty::Predicate::Subtype(..)
- | ty::Predicate::Projection(..)
- | ty::Predicate::ClosureKind(..)
- | ty::Predicate::ObjectSafe(..)
- | ty::Predicate::ConstEvaluatable(..)
- | ty::Predicate::ConstEquate(..) => vec![],
+ match obligation.predicate.kind() {
+ ty::PredicateKind::Trait(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::Projection(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => vec![],
- ty::Predicate::WellFormed(subty) => {
+ ty::PredicateKind::WellFormed(subty) => {
wf_types.push(subty);
vec![]
}
- ty::Predicate::RegionOutlives(ref data) => match data.no_bound_vars() {
+ ty::PredicateKind::RegionOutlives(ref data) => match data.no_bound_vars() {
None => vec![],
Some(ty::OutlivesPredicate(r_a, r_b)) => {
vec![OutlivesBound::RegionSubRegion(r_b, r_a)]
}
},
- ty::Predicate::TypeOutlives(ref data) => match data.no_bound_vars() {
+ ty::PredicateKind::TypeOutlives(ref data) => match data.no_bound_vars() {
None => vec![],
Some(ty::OutlivesPredicate(ty_a, r_b)) => {
let ty_a = infcx.resolve_vars_if_possible(&ty_a);
diff --git a/src/librustc_traits/normalize_erasing_regions.rs b/src/librustc_traits/normalize_erasing_regions.rs
index ed30ed5..fcb7514 100644
--- a/src/librustc_traits/normalize_erasing_regions.rs
+++ b/src/librustc_traits/normalize_erasing_regions.rs
@@ -40,15 +40,15 @@
}
fn not_outlives_predicate(p: &ty::Predicate<'_>) -> bool {
- match p {
- ty::Predicate::RegionOutlives(..) | ty::Predicate::TypeOutlives(..) => false,
- ty::Predicate::Trait(..)
- | ty::Predicate::Projection(..)
- | ty::Predicate::WellFormed(..)
- | ty::Predicate::ObjectSafe(..)
- | ty::Predicate::ClosureKind(..)
- | ty::Predicate::Subtype(..)
- | ty::Predicate::ConstEvaluatable(..)
- | ty::Predicate::ConstEquate(..) => true,
+ match p.kind() {
+ ty::PredicateKind::RegionOutlives(..) | ty::PredicateKind::TypeOutlives(..) => false,
+ ty::PredicateKind::Trait(..)
+ | ty::PredicateKind::Projection(..)
+ | ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => true,
}
}
diff --git a/src/librustc_traits/type_op.rs b/src/librustc_traits/type_op.rs
index aeb31c2..22077b4 100644
--- a/src/librustc_traits/type_op.rs
+++ b/src/librustc_traits/type_op.rs
@@ -6,9 +6,8 @@
use rustc_infer::traits::TraitEngineExt as _;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::{GenericArg, Subst, UserSelfTy, UserSubsts};
-use rustc_middle::ty::{
- FnSig, Lift, ParamEnv, ParamEnvAnd, PolyFnSig, Predicate, Ty, TyCtxt, TypeFoldable, Variance,
-};
+use rustc_middle::ty::{self, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable, Variance};
+use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Predicate, ToPredicate};
use rustc_span::DUMMY_SP;
use rustc_trait_selection::infer::InferCtxtBuilderExt;
use rustc_trait_selection::infer::InferCtxtExt;
@@ -140,7 +139,9 @@
self.relate(self_ty, Variance::Invariant, impl_self_ty)?;
- self.prove_predicate(Predicate::WellFormed(impl_self_ty));
+ self.prove_predicate(
+ ty::PredicateKind::WellFormed(impl_self_ty).to_predicate(self.tcx()),
+ );
}
// In addition to proving the predicates, we have to
@@ -154,7 +155,7 @@
// them? This would only be relevant if some input
// type were ill-formed but did not appear in `ty`,
// which...could happen with normalization...
- self.prove_predicate(Predicate::WellFormed(ty));
+ self.prove_predicate(ty::PredicateKind::WellFormed(ty).to_predicate(self.tcx()));
Ok(())
}
}
diff --git a/src/librustc_ty/needs_drop.rs b/src/librustc_ty/needs_drop.rs
index 97994b4..e94a47f 100644
--- a/src/librustc_ty/needs_drop.rs
+++ b/src/librustc_ty/needs_drop.rs
@@ -43,14 +43,13 @@
) -> Self {
let mut seen_tys = FxHashSet::default();
seen_tys.insert(ty);
- let recursion_limit = *tcx.sess.recursion_limit.get();
Self {
tcx,
param_env,
seen_tys,
query_ty: ty,
unchecked_tys: vec![(ty, 0)],
- recursion_limit,
+ recursion_limit: tcx.sess.recursion_limit(),
adt_components,
}
}
diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs
index 1aa11a7..3da5da2d 100644
--- a/src/librustc_ty/ty.rs
+++ b/src/librustc_ty/ty.rs
@@ -61,7 +61,7 @@
substs: tcx.mk_substs_trait(ty, &[]),
})
.without_const()
- .to_predicate();
+ .to_predicate(tcx);
let predicates = tcx.predicates_of(adtdef.did).predicates;
if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] }
}
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 6529d78..9a5fe95 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1596,8 +1596,8 @@
"conv_object_ty_poly_trait_ref: observing object predicate `{:?}`",
obligation.predicate
);
- match obligation.predicate {
- ty::Predicate::Trait(pred, _) => {
+ match obligation.predicate.kind() {
+ ty::PredicateKind::Trait(pred, _) => {
associated_types.entry(span).or_default().extend(
tcx.associated_items(pred.def_id())
.in_definition_order()
@@ -1605,7 +1605,7 @@
.map(|item| item.def_id),
);
}
- ty::Predicate::Projection(pred) => {
+ &ty::PredicateKind::Projection(pred) => {
// A `Self` within the original bound will be substituted with a
// `trait_object_dummy_self`, so check for that.
let references_self =
@@ -3042,7 +3042,7 @@
def_id: sized,
substs: tcx.mk_substs_trait(param_ty, &[]),
});
- (trait_ref.without_const().to_predicate(), span)
+ (trait_ref.without_const().to_predicate(tcx), span)
})
});
@@ -3057,16 +3057,16 @@
// or it's a generic associated type that deliberately has escaping bound vars.
let region_bound = ty::fold::shift_region(tcx, region_bound, 1);
let outlives = ty::OutlivesPredicate(param_ty, region_bound);
- (ty::Binder::bind(outlives).to_predicate(), span)
+ (ty::Binder::bind(outlives).to_predicate(tcx), span)
})
.chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
- let predicate = bound_trait_ref.with_constness(constness).to_predicate();
+ let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
(predicate, span)
}))
.chain(
self.projection_bounds
.iter()
- .map(|&(projection, span)| (projection.to_predicate(), span)),
+ .map(|&(projection, span)| (projection.to_predicate(tcx), span)),
),
)
.collect()
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 16af168..fb139b5 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -436,6 +436,8 @@
if let Some(m) = contains_ref_bindings {
self.check_expr_with_needs(scrut, Needs::maybe_mut_place(m))
+ } else if arms.is_empty() {
+ self.check_expr(scrut)
} else {
// ...but otherwise we want to use any supertype of the
// scrutinee. This is sort of a workaround, see note (*) in
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index ae6c173..d4c01a8 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -48,7 +48,7 @@
return Some((self.cur_ty, 0));
}
- if self.steps.len() >= *tcx.sess.recursion_limit.get() {
+ if self.steps.len() >= tcx.sess.recursion_limit() {
if !self.silence_errors {
report_autoderef_recursion_limit_error(tcx, self.span, self.cur_ty);
}
@@ -125,7 +125,7 @@
let obligation = traits::Obligation::new(
cause.clone(),
self.param_env,
- trait_ref.without_const().to_predicate(),
+ trait_ref.without_const().to_predicate(tcx),
);
if !self.infcx.predicate_may_hold(&obligation) {
debug!("overloaded_deref_ty: cannot match obligation");
@@ -236,7 +236,7 @@
pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
// We've reached the recursion limit, error gracefully.
- let suggested_limit = *tcx.sess.recursion_limit.get() * 2;
+ let suggested_limit = tcx.sess.recursion_limit() * 2;
let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty);
let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg);
let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 87a6f11..8fa901d 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -3,7 +3,6 @@
use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
use crate::astconv::AstConv;
-use crate::middle::region;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::{FutureTraitLangItem, GeneratorTraitLangItem};
@@ -17,7 +16,6 @@
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::ArgKind;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
-use rustc_trait_selection::traits::Obligation;
use std::cmp;
use std::iter;
@@ -206,7 +204,9 @@
obligation.predicate
);
- if let ty::Predicate::Projection(ref proj_predicate) = obligation.predicate {
+ if let ty::PredicateKind::Projection(ref proj_predicate) =
+ obligation.predicate.kind()
+ {
// Given a Projection predicate, we can potentially infer
// the complete signature.
self.deduce_sig_from_projection(Some(obligation.cause.span), proj_predicate)
@@ -516,21 +516,6 @@
let InferOk { value: (), obligations } =
self.at(&cause, self.param_env).eq(*expected_ty, supplied_ty)?;
all_obligations.extend(obligations);
-
- // Also, require that the supplied type must outlive
- // the closure body.
- let closure_body_region = self.tcx.mk_region(ty::ReScope(region::Scope {
- id: body.value.hir_id.local_id,
- data: region::ScopeData::Node,
- }));
- all_obligations.push(Obligation::new(
- cause,
- self.param_env,
- ty::Predicate::TypeOutlives(ty::Binder::dummy(ty::OutlivesPredicate(
- supplied_ty,
- closure_body_region,
- ))),
- ));
}
let (supplied_output_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars(
@@ -641,7 +626,7 @@
// where R is the return type we are expecting. This type `T`
// will be our output.
let output_ty = self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| {
- if let ty::Predicate::Projection(ref proj_predicate) = obligation.predicate {
+ if let ty::PredicateKind::Projection(ref proj_predicate) = obligation.predicate.kind() {
self.deduce_future_output_from_projection(obligation.cause.span, proj_predicate)
} else {
None
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 54562cf..a324bd0 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -596,8 +596,10 @@
while !queue.is_empty() {
let obligation = queue.remove(0);
debug!("coerce_unsized resolve step: {:?}", obligation);
- let trait_pred = match obligation.predicate {
- ty::Predicate::Trait(trait_pred, _) if traits.contains(&trait_pred.def_id()) => {
+ let trait_pred = match obligation.predicate.kind() {
+ &ty::PredicateKind::Trait(trait_pred, _)
+ if traits.contains(&trait_pred.def_id()) =>
+ {
if unsize_did == trait_pred.def_id() {
let unsize_ty = trait_pred.skip_binder().trait_ref.substs[1].expect_ty();
if let ty::Tuple(..) = unsize_ty.kind {
@@ -885,7 +887,7 @@
let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
coerce
.autoderef(rustc_span::DUMMY_SP, expr_ty)
- .find_map(|(ty, steps)| coerce.unify(ty, target).ok().map(|_| steps))
+ .find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps))
}
/// Given some expressions, their known unified type and another expression,
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 9694ce9..700b935 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -1,13 +1,12 @@
use crate::check::FnCtxt;
use rustc_infer::infer::InferOk;
use rustc_trait_selection::infer::InferCtxtExt as _;
-use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
-use rustc_trait_selection::traits::{self, ObligationCause};
+use rustc_trait_selection::traits::ObligationCause;
use rustc_ast::util::parser::PREC_POSTFIX;
use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_hir as hir;
-use rustc_hir::lang_items::{CloneTraitLangItem, DerefTraitLangItem};
+use rustc_hir::lang_items::CloneTraitLangItem;
use rustc_hir::{is_range_literal, Node};
use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
@@ -633,47 +632,29 @@
}
}
_ if sp == expr.span && !is_macro => {
- // Check for `Deref` implementations by constructing a predicate to
- // prove: `<T as Deref>::Output == U`
- let deref_trait = self.tcx.require_lang_item(DerefTraitLangItem, Some(sp));
- let item_def_id = self
- .tcx
- .associated_items(deref_trait)
- .in_definition_order()
- .find(|item| item.kind == ty::AssocKind::Type)
- .unwrap()
- .def_id;
- let predicate =
- ty::Predicate::Projection(ty::Binder::bind(ty::ProjectionPredicate {
- // `<T as Deref>::Output`
- projection_ty: ty::ProjectionTy {
- // `T`
- substs: self.tcx.intern_substs(&[checked_ty.into()]),
- // `Deref::Output`
- item_def_id,
- },
- // `U`
- ty: expected,
- }));
- let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate);
- let impls_deref = self.infcx.predicate_may_hold(&obligation);
-
- // For a suggestion to make sense, the type would need to be `Copy`.
- let is_copy = self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp);
-
- if is_copy && impls_deref {
- if let Ok(code) = sm.span_to_snippet(sp) {
- let message = if checked_ty.is_region_ptr() {
- "consider dereferencing the borrow"
- } else {
- "consider dereferencing the type"
- };
- let suggestion = if is_struct_pat_shorthand_field {
- format!("{}: *{}", code, code)
- } else {
- format!("*{}", code)
- };
- return Some((sp, message, suggestion, Applicability::MachineApplicable));
+ if let Some(steps) = self.deref_steps(checked_ty, expected) {
+ if steps == 1 {
+ // For a suggestion to make sense, the type would need to be `Copy`.
+ if self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp) {
+ if let Ok(code) = sm.span_to_snippet(sp) {
+ let message = if checked_ty.is_region_ptr() {
+ "consider dereferencing the borrow"
+ } else {
+ "consider dereferencing the type"
+ };
+ let suggestion = if is_struct_pat_shorthand_field {
+ format!("{}: *{}", code, code)
+ } else {
+ format!("*{}", code)
+ };
+ return Some((
+ sp,
+ message,
+ suggestion,
+ Applicability::MachineApplicable,
+ ));
+ }
+ }
}
}
}
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 478a848..24c319f 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -5,7 +5,6 @@
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{InferOk, RegionckMode, TyCtxtInferExt};
use rustc_infer::traits::TraitEngineExt as _;
-use rustc_middle::middle::region;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc_middle::ty::subst::{Subst, SubstsRef};
@@ -120,8 +119,6 @@
return Err(ErrorReported);
}
- let region_scope_tree = region::ScopeTree::default();
-
// NB. It seems a bit... suspicious to use an empty param-env
// here. The correct thing, I imagine, would be
// `OutlivesEnvironment::new(impl_param_env)`, which would
@@ -134,7 +131,6 @@
infcx.resolve_regions_and_report_errors(
drop_impl_did.to_def_id(),
- ®ion_scope_tree,
&outlives_env,
RegionckMode::default(),
);
@@ -230,9 +226,11 @@
// could be extended easily also to the other `Predicate`.
let predicate_matches_closure = |p: &'_ Predicate<'tcx>| {
let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env);
- match (predicate, p) {
- (Predicate::Trait(a, _), Predicate::Trait(b, _)) => relator.relate(a, b).is_ok(),
- (Predicate::Projection(a), Predicate::Projection(b)) => {
+ match (predicate.kind(), p.kind()) {
+ (ty::PredicateKind::Trait(a, _), ty::PredicateKind::Trait(b, _)) => {
+ relator.relate(a, b).is_ok()
+ }
+ (ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => {
relator.relate(a, b).is_ok()
}
_ => predicate == p,
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index c4805c5..410c5ef 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -574,8 +574,8 @@
};
traits::elaborate_predicates(self.tcx, predicates.predicates.iter().copied())
- .filter_map(|obligation| match obligation.predicate {
- ty::Predicate::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => {
+ .filter_map(|obligation| match obligation.predicate.kind() {
+ ty::PredicateKind::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => {
let span = predicates
.predicates
.iter()
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index a254aec..aae02ea 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -324,7 +324,7 @@
span,
self.body_id,
self.param_env,
- poly_trait_ref.without_const().to_predicate(),
+ poly_trait_ref.without_const().to_predicate(self.tcx),
);
// Now we want to know if this can be matched
@@ -401,7 +401,7 @@
obligations.push(traits::Obligation::new(
cause,
self.param_env,
- ty::Predicate::WellFormed(method_ty),
+ ty::PredicateKind::WellFormed(method_ty).to_predicate(tcx),
));
let callee = MethodCallee { def_id, substs: trait_ref.substs, sig: fn_sig };
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index e21db90..91562d5 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -796,23 +796,26 @@
fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
// FIXME: do we want to commit to this behavior for param bounds?
- let bounds = self.param_env.caller_bounds.iter().filter_map(|predicate| match *predicate {
- ty::Predicate::Trait(ref trait_predicate, _) => {
- match trait_predicate.skip_binder().trait_ref.self_ty().kind {
- ty::Param(ref p) if *p == param_ty => Some(trait_predicate.to_poly_trait_ref()),
- _ => None,
+ let bounds =
+ self.param_env.caller_bounds.iter().filter_map(|predicate| match predicate.kind() {
+ ty::PredicateKind::Trait(ref trait_predicate, _) => {
+ match trait_predicate.skip_binder().trait_ref.self_ty().kind {
+ ty::Param(ref p) if *p == param_ty => {
+ Some(trait_predicate.to_poly_trait_ref())
+ }
+ _ => None,
+ }
}
- }
- ty::Predicate::Subtype(..)
- | ty::Predicate::Projection(..)
- | ty::Predicate::RegionOutlives(..)
- | ty::Predicate::WellFormed(..)
- | ty::Predicate::ObjectSafe(..)
- | ty::Predicate::ClosureKind(..)
- | ty::Predicate::TypeOutlives(..)
- | ty::Predicate::ConstEvaluatable(..)
- | ty::Predicate::ConstEquate(..) => None,
- });
+ ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::Projection(..)
+ | ty::PredicateKind::RegionOutlives(..)
+ | ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::TypeOutlives(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => None,
+ });
self.elaborate_bounds(bounds, |this, poly_trait_ref, item| {
let trait_ref = this.erase_late_bound_regions(&poly_trait_ref);
@@ -1374,7 +1377,7 @@
}
TraitCandidate(trait_ref) => {
- let predicate = trait_ref.without_const().to_predicate();
+ let predicate = trait_ref.without_const().to_predicate(self.tcx);
let obligation = traits::Obligation::new(cause, self.param_env, predicate);
if !self.predicate_may_hold(&obligation) {
result = ProbeResult::NoMatch;
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index cf26c94..7ca3eb8 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -58,7 +58,7 @@
span,
self.body_id,
self.param_env,
- poly_trait_ref.without_const().to_predicate(),
+ poly_trait_ref.without_const().to_predicate(tcx),
);
self.predicate_may_hold(&obligation)
})
@@ -574,8 +574,8 @@
let mut bound_spans = vec![];
let mut collect_type_param_suggestions =
|self_ty: Ty<'_>, parent_pred: &ty::Predicate<'_>, obligation: &str| {
- if let (ty::Param(_), ty::Predicate::Trait(p, _)) =
- (&self_ty.kind, parent_pred)
+ if let (ty::Param(_), ty::PredicateKind::Trait(p, _)) =
+ (&self_ty.kind, parent_pred.kind())
{
if let ty::Adt(def, _) = p.skip_binder().trait_ref.self_ty().kind {
let node = def.did.as_local().map(|def_id| {
@@ -626,9 +626,9 @@
_ => {}
}
};
- let mut format_pred = |pred| {
- match pred {
- ty::Predicate::Projection(pred) => {
+ let mut format_pred = |pred: ty::Predicate<'tcx>| {
+ match pred.kind() {
+ ty::PredicateKind::Projection(pred) => {
// `<Foo as Iterator>::Item = String`.
let trait_ref =
pred.skip_binder().projection_ty.trait_ref(self.tcx);
@@ -646,7 +646,7 @@
bound_span_label(trait_ref.self_ty(), &obligation, &quiet);
Some((obligation, trait_ref.self_ty()))
}
- ty::Predicate::Trait(poly_trait_ref, _) => {
+ ty::PredicateKind::Trait(poly_trait_ref, _) => {
let p = poly_trait_ref.skip_binder().trait_ref;
let self_ty = p.self_ty();
let path = p.print_only_trait_path();
@@ -946,11 +946,11 @@
// this isn't perfect (that is, there are cases when
// implementing a trait would be legal but is rejected
// here).
- unsatisfied_predicates.iter().all(|(p, _)| match p {
+ unsatisfied_predicates.iter().all(|(p, _)| match p.kind() {
// Hide traits if they are present in predicates as they can be fixed without
// having to implement them.
- ty::Predicate::Trait(t, _) => t.def_id() == info.def_id,
- ty::Predicate::Projection(p) => p.item_def_id() == info.def_id,
+ ty::PredicateKind::Trait(t, _) => t.def_id() == info.def_id,
+ ty::PredicateKind::Projection(p) => p.item_def_id() == info.def_id,
_ => false,
}) && (type_is_local || info.def_id.is_local())
&& self
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index d72c74e..6b7adb7 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -106,13 +106,13 @@
use rustc_hir::{ExprKind, GenericArg, HirIdMap, Item, ItemKind, Node, PatKind, QPath};
use rustc_index::bit_set::BitSet;
use rustc_index::vec::Idx;
+use rustc_infer::infer;
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
-use rustc_infer::infer::{self, InferCtxt, InferOk, InferResult, TyCtxtInferExt};
+use rustc_infer::infer::{InferCtxt, InferOk, InferResult, RegionVariableOrigin, TyCtxtInferExt};
use rustc_middle::hir::map::blocks::FnLikeNode;
-use rustc_middle::middle::region;
use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
@@ -667,13 +667,6 @@
let tcx = infcx.tcx;
let item_id = tcx.hir().local_def_id_to_hir_id(def_id);
let body_id = tcx.hir().maybe_body_owned_by(item_id);
- let implicit_region_bound = body_id.map(|body_id| {
- let body = tcx.hir().body(body_id);
- tcx.mk_region(ty::ReScope(region::Scope {
- id: body.value.hir_id.local_id,
- data: region::ScopeData::CallSite,
- }))
- });
Inherited {
tables: MaybeInProgressTables { maybe_tables: infcx.in_progress_tables },
@@ -686,7 +679,7 @@
deferred_generator_interiors: RefCell::new(Vec::new()),
opaque_types: RefCell::new(Default::default()),
opaque_types_vars: RefCell::new(Default::default()),
- implicit_region_bound,
+ implicit_region_bound: None,
body_id,
}
}
@@ -1337,12 +1330,9 @@
// C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
// (as it's created inside the body itself, not passed in from outside).
let maybe_va_list = if fn_sig.c_variadic {
- let va_list_did =
- tcx.require_lang_item(VaListTypeLangItem, Some(body.params.last().unwrap().span));
- let region = tcx.mk_region(ty::ReScope(region::Scope {
- id: body.value.hir_id.local_id,
- data: region::ScopeData::CallSite,
- }));
+ let span = body.params.last().unwrap().span;
+ let va_list_did = tcx.require_lang_item(VaListTypeLangItem, Some(span));
+ let region = fcx.next_region_var(RegionVariableOrigin::MiscVariable(span));
Some(tcx.type_of(va_list_did).subst(tcx, &[region.into()]))
} else {
@@ -1458,7 +1448,7 @@
inherited.register_predicate(traits::Obligation::new(
cause,
param_env,
- trait_ref.without_const().to_predicate(),
+ trait_ref.without_const().to_predicate(tcx),
));
}
}
@@ -2223,8 +2213,8 @@
let mut projections = vec![];
for (predicate, _) in predicates.predicates {
debug!("predicate {:?}", predicate);
- match predicate {
- ty::Predicate::Trait(trait_predicate, _) => {
+ match predicate.kind() {
+ ty::PredicateKind::Trait(trait_predicate, _) => {
let entry = types.entry(trait_predicate.skip_binder().self_ty()).or_default();
let def_id = trait_predicate.skip_binder().def_id();
if Some(def_id) != tcx.lang_items().sized_trait() {
@@ -2233,7 +2223,7 @@
entry.push(trait_predicate.skip_binder().def_id());
}
}
- ty::Predicate::Projection(projection_pred) => {
+ ty::PredicateKind::Projection(projection_pred) => {
projections.push(projection_pred);
}
_ => {}
@@ -2769,8 +2759,8 @@
ty::GenericPredicates {
parent: None,
predicates: tcx.arena.alloc_from_iter(self.param_env.caller_bounds.iter().filter_map(
- |&predicate| match predicate {
- ty::Predicate::Trait(ref data, _)
+ |&predicate| match predicate.kind() {
+ ty::PredicateKind::Trait(ref data, _)
if data.skip_binder().self_ty().is_param(index) =>
{
// HACK(eddyb) should get the original `Span`.
@@ -3379,7 +3369,7 @@
self.register_predicate(traits::Obligation::new(
cause,
self.param_env,
- ty::Predicate::ConstEvaluatable(def_id, substs),
+ ty::PredicateKind::ConstEvaluatable(def_id, substs).to_predicate(self.tcx),
));
}
@@ -3428,7 +3418,7 @@
self.register_predicate(traits::Obligation::new(
cause,
self.param_env,
- ty::Predicate::WellFormed(ty),
+ ty::PredicateKind::WellFormed(ty).to_predicate(self.tcx),
));
}
@@ -3857,18 +3847,20 @@
.borrow()
.pending_obligations()
.into_iter()
- .filter_map(move |obligation| match obligation.predicate {
- ty::Predicate::Projection(ref data) => {
+ .filter_map(move |obligation| match obligation.predicate.kind() {
+ ty::PredicateKind::Projection(ref data) => {
Some((data.to_poly_trait_ref(self.tcx), obligation))
}
- ty::Predicate::Trait(ref data, _) => Some((data.to_poly_trait_ref(), obligation)),
- ty::Predicate::Subtype(..) => None,
- ty::Predicate::RegionOutlives(..) => None,
- ty::Predicate::TypeOutlives(..) => None,
- ty::Predicate::WellFormed(..) => None,
- ty::Predicate::ObjectSafe(..) => None,
- ty::Predicate::ConstEvaluatable(..) => None,
- ty::Predicate::ConstEquate(..) => None,
+ ty::PredicateKind::Trait(ref data, _) => {
+ Some((data.to_poly_trait_ref(), obligation))
+ }
+ ty::PredicateKind::Subtype(..) => None,
+ ty::PredicateKind::RegionOutlives(..) => None,
+ ty::PredicateKind::TypeOutlives(..) => None,
+ ty::PredicateKind::WellFormed(..) => None,
+ ty::PredicateKind::ObjectSafe(..) => None,
+ ty::PredicateKind::ConstEvaluatable(..) => None,
+ ty::PredicateKind::ConstEquate(..) => None,
// N.B., this predicate is created by breaking down a
// `ClosureType: FnFoo()` predicate, where
// `ClosureType` represents some `Closure`. It can't
@@ -3877,7 +3869,7 @@
// this closure yet; this is exactly why the other
// code is looking for a self type of a unresolved
// inference variable.
- ty::Predicate::ClosureKind(..) => None,
+ ty::PredicateKind::ClosureKind(..) => None,
})
.filter(move |(tr, _)| self.self_type_matches_expected_vid(*tr, ty_var_root))
}
@@ -4206,7 +4198,7 @@
continue;
}
- if let ty::Predicate::Trait(predicate, _) = error.obligation.predicate {
+ if let ty::PredicateKind::Trait(predicate, _) = error.obligation.predicate.kind() {
// Collect the argument position for all arguments that could have caused this
// `FulfillmentError`.
let mut referenced_in = final_arg_types
@@ -4253,7 +4245,9 @@
if let hir::ExprKind::Path(qpath) = &path.kind {
if let hir::QPath::Resolved(_, path) = &qpath {
for error in errors {
- if let ty::Predicate::Trait(predicate, _) = error.obligation.predicate {
+ if let ty::PredicateKind::Trait(predicate, _) =
+ error.obligation.predicate.kind()
+ {
// If any of the type arguments in this path segment caused the
// `FullfillmentError`, point at its span (#61860).
for arg in path
@@ -5322,10 +5316,11 @@
};
let predicate =
- ty::Predicate::Projection(ty::Binder::bind(ty::ProjectionPredicate {
+ ty::PredicateKind::Projection(ty::Binder::bind(ty::ProjectionPredicate {
projection_ty,
ty: expected,
- }));
+ }))
+ .to_predicate(self.tcx);
let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate);
debug!("suggest_missing_await: trying obligation {:?}", obligation);
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 049f476..90ba15a 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -83,12 +83,10 @@
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{self, RegionObligation, RegionckMode};
use rustc_middle::ty::adjustment;
-use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
use rustc_trait_selection::infer::OutlivesEnvironmentExt;
use rustc_trait_selection::opaque_types::InferCtxtExt;
-use std::mem;
use std::ops::Deref;
// a variation on try that just returns unit
@@ -111,8 +109,7 @@
pub fn regionck_expr(&self, body: &'tcx hir::Body<'tcx>) {
let subject = self.tcx.hir().body_owner_def_id(body.id());
let id = body.value.hir_id;
- let mut rcx =
- RegionCtxt::new(self, RepeatingScope(id), id, Subject(subject), self.param_env);
+ let mut rcx = RegionCtxt::new(self, id, Subject(subject), self.param_env);
// There are no add'l implied bounds when checking a
// standalone expr (e.g., the `E` in a type like `[u32; E]`).
@@ -131,13 +128,7 @@
pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: &[Ty<'tcx>]) {
debug!("regionck_item(item.id={:?}, wf_tys={:?})", item_id, wf_tys);
let subject = self.tcx.hir().local_def_id(item_id);
- let mut rcx = RegionCtxt::new(
- self,
- RepeatingScope(item_id),
- item_id,
- Subject(subject),
- self.param_env,
- );
+ let mut rcx = RegionCtxt::new(self, item_id, Subject(subject), self.param_env);
rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span);
rcx.outlives_environment.save_implied_bounds(item_id);
rcx.visit_region_obligations(item_id);
@@ -156,8 +147,7 @@
debug!("regionck_fn(id={})", fn_id);
let subject = self.tcx.hir().body_owner_def_id(body.id());
let hir_id = body.value.hir_id;
- let mut rcx =
- RegionCtxt::new(self, RepeatingScope(hir_id), hir_id, Subject(subject), self.param_env);
+ let mut rcx = RegionCtxt::new(self, hir_id, Subject(subject), self.param_env);
if !self.errors_reported_since_creation() {
// regionck assumes typeck succeeded
@@ -182,12 +172,6 @@
body_id: hir::HirId,
body_owner: LocalDefId,
- // call_site scope of innermost fn
- call_site_scope: Option<region::Scope>,
-
- // id of innermost fn or loop
- repeating_scope: hir::HirId,
-
// id of AST node being analyzed (the subject of the analysis).
subject_def_id: LocalDefId,
}
@@ -199,13 +183,11 @@
}
}
-pub struct RepeatingScope(hir::HirId);
pub struct Subject(LocalDefId);
impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
pub fn new(
fcx: &'a FnCtxt<'a, 'tcx>,
- RepeatingScope(initial_repeating_scope): RepeatingScope,
initial_body_id: hir::HirId,
Subject(subject): Subject,
param_env: ty::ParamEnv<'tcx>,
@@ -215,19 +197,13 @@
RegionCtxt {
fcx,
region_scope_tree,
- repeating_scope: initial_repeating_scope,
body_id: initial_body_id,
body_owner: subject,
- call_site_scope: None,
subject_def_id: subject,
outlives_environment,
}
}
- fn set_repeating_scope(&mut self, scope: hir::HirId) -> hir::HirId {
- mem::replace(&mut self.repeating_scope, scope)
- }
-
/// Try to resolve the type for the given node, returning `t_err` if an error results. Note that
/// we never care about the details of the error, the same error will be detected and reported
/// in the writeback phase.
@@ -261,16 +237,10 @@
self.resolve_type(t)
}
- /// Try to resolve the type for the given node.
- pub fn resolve_expr_type_adjusted(&mut self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
- let ty = self.tables.borrow().expr_ty_adjusted(expr);
- self.resolve_type(ty)
- }
-
- /// This is the "main" function when region-checking a function item or a closure
- /// within a function item. It begins by updating various fields (e.g., `call_site_scope`
- /// and `outlives_environment`) to be appropriate to the function and then adds constraints
- /// derived from the function body.
+ /// This is the "main" function when region-checking a function item or a
+ /// closure within a function item. It begins by updating various fields
+ /// (e.g., `outlives_environment`) to be appropriate to the function and
+ /// then adds constraints derived from the function body.
///
/// Note that it does **not** restore the state of the fields that
/// it updates! This is intentional, since -- for the main
@@ -292,10 +262,6 @@
self.body_id = body_id.hir_id;
self.body_owner = self.tcx.hir().body_owner_def_id(body_id);
- let call_site =
- region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite };
- self.call_site_scope = Some(call_site);
-
let fn_sig = {
match self.tables.borrow().liberated_fn_sigs().get(id) {
Some(f) => *f,
@@ -324,12 +290,6 @@
self.visit_body(body);
self.visit_region_obligations(body_id.hir_id);
- let call_site_scope = self.call_site_scope.unwrap();
- debug!("visit_fn_body body.id {:?} call_site_scope: {:?}", body.id(), call_site_scope);
- let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope));
-
- self.type_of_node_must_outlive(infer::CallReturn(span), body_id.hir_id, call_site_region);
-
self.constrain_opaque_types(
&self.fcx.opaque_types.borrow(),
self.outlives_environment.free_region_map(),
@@ -354,7 +314,6 @@
self.fcx.resolve_regions_and_report_errors(
self.subject_def_id.to_def_id(),
- &self.region_scope_tree,
&self.outlives_environment,
mode,
);
@@ -363,34 +322,6 @@
fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat<'_>) {
debug!("regionck::visit_pat(pat={:?})", pat);
pat.each_binding(|_, hir_id, span, _| {
- // If we have a variable that contains region'd data, that
- // data will be accessible from anywhere that the variable is
- // accessed. We must be wary of loops like this:
- //
- // // from src/test/compile-fail/borrowck-lend-flow.rs
- // let mut v = box 3, w = box 4;
- // let mut x = &mut w;
- // loop {
- // **x += 1; // (2)
- // borrow(v); //~ ERROR cannot borrow
- // x = &mut v; // (1)
- // }
- //
- // Typically, we try to determine the region of a borrow from
- // those points where it is dereferenced. In this case, one
- // might imagine that the lifetime of `x` need only be the
- // body of the loop. But of course this is incorrect because
- // the pointer that is created at point (1) is consumed at
- // point (2), meaning that it must be live across the loop
- // iteration. The easiest way to guarantee this is to require
- // that the lifetime of any regions that appear in a
- // variable's type enclose at least the variable's scope.
- let var_scope = self.region_scope_tree.var_scope(hir_id.local_id);
- let var_region = self.tcx.mk_region(ty::ReScope(var_scope));
-
- let origin = infer::BindingTypeIsNotValidAtDecl(span);
- self.type_of_node_must_outlive(origin, hir_id, var_region);
-
let typ = self.resolve_node_type(hir_id);
let body_id = self.body_id;
let _ = dropck::check_drop_obligations(self, typ, span, body_id);
@@ -433,7 +364,6 @@
// `visit_fn_body`. We will restore afterwards.
let old_body_id = self.body_id;
let old_body_owner = self.body_owner;
- let old_call_site_scope = self.call_site_scope;
let env_snapshot = self.outlives_environment.push_snapshot_pre_closure();
let body = self.tcx.hir().body(body_id);
@@ -441,7 +371,6 @@
// Restore state from previous function.
self.outlives_environment.pop_snapshot_post_closure(env_snapshot);
- self.call_site_scope = old_call_site_scope;
self.body_id = old_body_id;
self.body_owner = old_body_owner;
}
@@ -462,42 +391,6 @@
}
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
- debug!("regionck::visit_expr(e={:?}, repeating_scope={:?})", expr, self.repeating_scope);
-
- // No matter what, the type of each expression must outlive the
- // scope of that expression. This also guarantees basic WF.
- let expr_ty = self.resolve_node_type(expr.hir_id);
- // the region corresponding to this expression
- let expr_region = self.tcx.mk_region(ty::ReScope(region::Scope {
- id: expr.hir_id.local_id,
- data: region::ScopeData::Node,
- }));
- self.type_must_outlive(
- infer::ExprTypeIsNotInScope(expr_ty, expr.span),
- expr_ty,
- expr_region,
- );
-
- let is_method_call = self.tables.borrow().is_method_call(expr);
-
- // If we are calling a method (either explicitly or via an
- // overloaded operator), check that all of the types provided as
- // arguments for its type parameters are well-formed, and all the regions
- // provided as arguments outlive the call.
- if is_method_call {
- let origin = match expr.kind {
- hir::ExprKind::MethodCall(..) => infer::ParameterOrigin::MethodCall,
- hir::ExprKind::Unary(op, _) if op == hir::UnOp::UnDeref => {
- infer::ParameterOrigin::OverloadedDeref
- }
- _ => infer::ParameterOrigin::OverloadedOperator,
- };
-
- let substs = self.tables.borrow().node_substs(expr.hir_id);
- self.substs_wf_in_scope(origin, substs, expr.span, expr_region);
- // Arguments (sub-expressions) are checked via `constrain_call`, below.
- }
-
// Check any autoderefs or autorefs that appear.
let cmt_result = self.constrain_adjustments(expr);
@@ -512,117 +405,10 @@
}
}
- debug!(
- "regionck::visit_expr(e={:?}, repeating_scope={:?}) - visiting subexprs",
- expr, self.repeating_scope
- );
match expr.kind {
- hir::ExprKind::Path(_) => {
- let substs = self.tables.borrow().node_substs(expr.hir_id);
- let origin = infer::ParameterOrigin::Path;
- self.substs_wf_in_scope(origin, substs, expr.span, expr_region);
- }
-
- hir::ExprKind::Call(ref callee, ref args) => {
- if is_method_call {
- self.constrain_call(expr, Some(&callee), args.iter().map(|e| &*e));
- } else {
- self.constrain_callee(&callee);
- self.constrain_call(expr, None, args.iter().map(|e| &*e));
- }
-
- intravisit::walk_expr(self, expr);
- }
-
- hir::ExprKind::MethodCall(.., ref args) => {
- self.constrain_call(expr, Some(&args[0]), args[1..].iter().map(|e| &*e));
-
- intravisit::walk_expr(self, expr);
- }
-
- hir::ExprKind::AssignOp(_, ref lhs, ref rhs) => {
- if is_method_call {
- self.constrain_call(expr, Some(&lhs), Some(&**rhs).into_iter());
- }
-
- intravisit::walk_expr(self, expr);
- }
-
- hir::ExprKind::Index(ref lhs, ref rhs) if is_method_call => {
- self.constrain_call(expr, Some(&lhs), Some(&**rhs).into_iter());
-
- intravisit::walk_expr(self, expr);
- }
-
- hir::ExprKind::Binary(_, ref lhs, ref rhs) if is_method_call => {
- // As `ExprKind::MethodCall`, but the call is via an overloaded op.
- self.constrain_call(expr, Some(&lhs), Some(&**rhs).into_iter());
-
- intravisit::walk_expr(self, expr);
- }
-
- hir::ExprKind::Binary(_, ref lhs, ref rhs) => {
- // If you do `x OP y`, then the types of `x` and `y` must
- // outlive the operation you are performing.
- let lhs_ty = self.resolve_expr_type_adjusted(&lhs);
- let rhs_ty = self.resolve_expr_type_adjusted(&rhs);
- for &ty in &[lhs_ty, rhs_ty] {
- self.type_must_outlive(infer::Operand(expr.span), ty, expr_region);
- }
- intravisit::walk_expr(self, expr);
- }
-
- hir::ExprKind::Unary(hir::UnOp::UnDeref, ref base) => {
- // For *a, the lifetime of a must enclose the deref
- if is_method_call {
- self.constrain_call(expr, Some(base), None::<hir::Expr<'_>>.iter());
- }
- // For overloaded derefs, base_ty is the input to `Deref::deref`,
- // but it's a reference type uing the same region as the output.
- let base_ty = self.resolve_expr_type_adjusted(base);
- if let ty::Ref(r_ptr, _, _) = base_ty.kind {
- self.mk_subregion_due_to_dereference(expr.span, expr_region, r_ptr);
- }
-
- intravisit::walk_expr(self, expr);
- }
-
- hir::ExprKind::Unary(_, ref lhs) if is_method_call => {
- // As above.
- self.constrain_call(expr, Some(&lhs), None::<hir::Expr<'_>>.iter());
-
- intravisit::walk_expr(self, expr);
- }
-
- hir::ExprKind::Index(ref vec_expr, _) => {
- // For a[b], the lifetime of a must enclose the deref
- let vec_type = self.resolve_expr_type_adjusted(&vec_expr);
- self.constrain_index(expr, vec_type);
-
- intravisit::walk_expr(self, expr);
- }
-
- hir::ExprKind::Cast(ref source, _) => {
- // Determine if we are casting `source` to a trait
- // instance. If so, we have to be sure that the type of
- // the source obeys the trait's region bound.
- self.constrain_cast(expr, &source);
- intravisit::walk_expr(self, expr);
- }
-
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, m, ref base) => {
self.link_addr_of(expr, m, &base);
- // Require that when you write a `&expr` expression, the
- // resulting pointer has a lifetime that encompasses the
- // `&expr` expression itself. Note that we constraining
- // the type of the node expr.id here *before applying
- // adjustments*.
- //
- // FIXME(https://github.com/rust-lang/rfcs/issues/811)
- // nested method calls requires that this rule change
- let ty0 = self.resolve_node_type(expr.hir_id);
- self.type_must_outlive(infer::AddrOf(expr.span), ty0, expr_region);
intravisit::walk_expr(self, expr);
}
@@ -632,140 +418,12 @@
intravisit::walk_expr(self, expr);
}
- hir::ExprKind::Closure(.., body_id, _, _) => {
- self.check_expr_fn_block(expr, body_id);
- }
-
- hir::ExprKind::Loop(ref body, _, _) => {
- let repeating_scope = self.set_repeating_scope(body.hir_id);
- intravisit::walk_expr(self, expr);
- self.set_repeating_scope(repeating_scope);
- }
-
- hir::ExprKind::Ret(Some(ref ret_expr)) => {
- let call_site_scope = self.call_site_scope;
- debug!(
- "visit_expr ExprKind::Ret ret_expr.hir_id {} call_site_scope: {:?}",
- ret_expr.hir_id, call_site_scope
- );
- let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope.unwrap()));
- self.type_of_node_must_outlive(
- infer::CallReturn(ret_expr.span),
- ret_expr.hir_id,
- call_site_region,
- );
- intravisit::walk_expr(self, expr);
- }
-
- _ => {
- intravisit::walk_expr(self, expr);
- }
+ _ => intravisit::walk_expr(self, expr),
}
}
}
impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
- fn constrain_cast(&mut self, cast_expr: &hir::Expr<'_>, source_expr: &hir::Expr<'_>) {
- debug!("constrain_cast(cast_expr={:?}, source_expr={:?})", cast_expr, source_expr);
-
- let source_ty = self.resolve_node_type(source_expr.hir_id);
- let target_ty = self.resolve_node_type(cast_expr.hir_id);
-
- self.walk_cast(cast_expr, source_ty, target_ty);
- }
-
- fn walk_cast(&mut self, cast_expr: &hir::Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) {
- debug!("walk_cast(from_ty={:?}, to_ty={:?})", from_ty, to_ty);
- match (&from_ty.kind, &to_ty.kind) {
- /*From:*/
- (&ty::Ref(from_r, from_ty, _), /*To: */ &ty::Ref(to_r, to_ty, _)) => {
- // Target cannot outlive source, naturally.
- self.sub_regions(infer::Reborrow(cast_expr.span), to_r, from_r);
- self.walk_cast(cast_expr, from_ty, to_ty);
- }
-
- /*From:*/
- (_, /*To: */ &ty::Dynamic(.., r)) => {
- // When T is existentially quantified as a trait
- // `Foo+'to`, it must outlive the region bound `'to`.
- self.type_must_outlive(infer::RelateObjectBound(cast_expr.span), from_ty, r);
- }
-
- /*From:*/
- (&ty::Adt(from_def, _), /*To: */ &ty::Adt(to_def, _))
- if from_def.is_box() && to_def.is_box() =>
- {
- self.walk_cast(cast_expr, from_ty.boxed_ty(), to_ty.boxed_ty());
- }
-
- _ => {}
- }
- }
-
- fn check_expr_fn_block(&mut self, expr: &'tcx hir::Expr<'tcx>, body_id: hir::BodyId) {
- let repeating_scope = self.set_repeating_scope(body_id.hir_id);
- intravisit::walk_expr(self, expr);
- self.set_repeating_scope(repeating_scope);
- }
-
- fn constrain_callee(&mut self, callee_expr: &hir::Expr<'_>) {
- let callee_ty = self.resolve_node_type(callee_expr.hir_id);
- match callee_ty.kind {
- ty::FnDef(..) | ty::FnPtr(_) => {}
- _ => {
- // this should not happen, but it does if the program is
- // erroneous
- //
- // bug!(
- // callee_expr.span,
- // "Calling non-function: {}",
- // callee_ty);
- }
- }
- }
-
- fn constrain_call<'b, I: Iterator<Item = &'b hir::Expr<'b>>>(
- &mut self,
- call_expr: &hir::Expr<'_>,
- receiver: Option<&hir::Expr<'_>>,
- arg_exprs: I,
- ) {
- //! Invoked on every call site (i.e., normal calls, method calls,
- //! and overloaded operators). Constrains the regions which appear
- //! in the type of the function. Also constrains the regions that
- //! appear in the arguments appropriately.
-
- debug!("constrain_call(call_expr={:?}, receiver={:?})", call_expr, receiver);
-
- // `callee_region` is the scope representing the time in which the
- // call occurs.
- //
- // FIXME(#6268) to support nested method calls, should be callee_id
- let callee_scope =
- region::Scope { id: call_expr.hir_id.local_id, data: region::ScopeData::Node };
- let callee_region = self.tcx.mk_region(ty::ReScope(callee_scope));
-
- debug!("callee_region={:?}", callee_region);
-
- for arg_expr in arg_exprs {
- debug!("argument: {:?}", arg_expr);
-
- // ensure that any regions appearing in the argument type are
- // valid for at least the lifetime of the function:
- self.type_of_node_must_outlive(
- infer::CallArg(arg_expr.span),
- arg_expr.hir_id,
- callee_region,
- );
- }
-
- // as loop above, but for receiver
- if let Some(r) = receiver {
- debug!("receiver: {:?}", r);
- self.type_of_node_must_outlive(infer::CallRcvr(r.span), r.hir_id, callee_region);
- }
- }
-
/// Creates a temporary `MemCategorizationContext` and pass it to the closure.
fn with_mc<F, R>(&self, f: F) -> R
where
@@ -784,79 +442,40 @@
fn constrain_adjustments(&mut self, expr: &hir::Expr<'_>) -> mc::McResult<mc::Place<'tcx>> {
debug!("constrain_adjustments(expr={:?})", expr);
- let mut cmt = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?;
+ let mut place = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?;
let tables = self.tables.borrow();
let adjustments = tables.expr_adjustments(&expr);
if adjustments.is_empty() {
- return Ok(cmt);
+ return Ok(place);
}
debug!("constrain_adjustments: adjustments={:?}", adjustments);
// If necessary, constrain destructors in the unadjusted form of this
// expression.
- self.check_safety_of_rvalue_destructor_if_necessary(&cmt, expr.span);
+ self.check_safety_of_rvalue_destructor_if_necessary(&place, expr.span);
- let expr_region = self.tcx.mk_region(ty::ReScope(region::Scope {
- id: expr.hir_id.local_id,
- data: region::ScopeData::Node,
- }));
for adjustment in adjustments {
- debug!("constrain_adjustments: adjustment={:?}, cmt={:?}", adjustment, cmt);
+ debug!("constrain_adjustments: adjustment={:?}, place={:?}", adjustment, place);
if let adjustment::Adjust::Deref(Some(deref)) = adjustment.kind {
- debug!("constrain_adjustments: overloaded deref: {:?}", deref);
-
- // Treat overloaded autoderefs as if an AutoBorrow adjustment
- // was applied on the base type, as that is always the case.
- let input = self
- .tcx
- .mk_ref(deref.region, ty::TypeAndMut { ty: cmt.ty, mutbl: deref.mutbl });
- let output = self.tcx.mk_ref(
- deref.region,
- ty::TypeAndMut { ty: adjustment.target, mutbl: deref.mutbl },
- );
-
self.link_region(
expr.span,
deref.region,
ty::BorrowKind::from_mutbl(deref.mutbl),
- &cmt,
+ &place,
);
-
- // Specialized version of constrain_call.
- self.type_must_outlive(infer::CallRcvr(expr.span), input, expr_region);
- self.type_must_outlive(infer::CallReturn(expr.span), output, expr_region);
}
if let adjustment::Adjust::Borrow(ref autoref) = adjustment.kind {
- self.link_autoref(expr, &cmt, autoref);
-
- // Require that the resulting region encompasses
- // the current node.
- //
- // FIXME(#6268) remove to support nested method calls
- self.type_of_node_must_outlive(
- infer::AutoBorrow(expr.span),
- expr.hir_id,
- expr_region,
- );
+ self.link_autoref(expr, &place, autoref);
}
- cmt = self.with_mc(|mc| mc.cat_expr_adjusted(expr, cmt, &adjustment))?;
+ place = self.with_mc(|mc| mc.cat_expr_adjusted(expr, place, &adjustment))?;
}
- Ok(cmt)
- }
-
- pub fn mk_subregion_due_to_dereference(
- &mut self,
- deref_span: Span,
- minimum_lifetime: ty::Region<'tcx>,
- maximum_lifetime: ty::Region<'tcx>,
- ) {
- self.sub_regions(infer::DerefPointer(deref_span), minimum_lifetime, maximum_lifetime)
+ Ok(place)
}
fn check_safety_of_rvalue_destructor_if_necessary(
@@ -872,59 +491,6 @@
}
}
}
-
- /// Invoked on any index expression that occurs. Checks that if this is a slice
- /// being indexed, the lifetime of the pointer includes the deref expr.
- fn constrain_index(&mut self, index_expr: &hir::Expr<'_>, indexed_ty: Ty<'tcx>) {
- debug!("constrain_index(index_expr=?, indexed_ty={}", self.ty_to_string(indexed_ty));
-
- let r_index_expr = ty::ReScope(region::Scope {
- id: index_expr.hir_id.local_id,
- data: region::ScopeData::Node,
- });
- if let ty::Ref(r_ptr, r_ty, _) = indexed_ty.kind {
- match r_ty.kind {
- ty::Slice(_) | ty::Str => {
- self.sub_regions(
- infer::IndexSlice(index_expr.span),
- self.tcx.mk_region(r_index_expr),
- r_ptr,
- );
- }
- _ => {}
- }
- }
- }
-
- /// Guarantees that any lifetimes that appear in the type of the node `id` (after applying
- /// adjustments) are valid for at least `minimum_lifetime`.
- fn type_of_node_must_outlive(
- &mut self,
- origin: infer::SubregionOrigin<'tcx>,
- hir_id: hir::HirId,
- minimum_lifetime: ty::Region<'tcx>,
- ) {
- // Try to resolve the type. If we encounter an error, then typeck
- // is going to fail anyway, so just stop here and let typeck
- // report errors later on in the writeback phase.
- let ty0 = self.resolve_node_type(hir_id);
-
- let ty = self
- .tables
- .borrow()
- .adjustments()
- .get(hir_id)
- .and_then(|adj| adj.last())
- .map_or(ty0, |adj| adj.target);
- let ty = self.resolve_type(ty);
- debug!(
- "constrain_regions_in_type_of_node(\
- ty={}, ty0={}, id={:?}, minimum_lifetime={:?})",
- ty, ty0, hir_id, minimum_lifetime
- );
- self.type_must_outlive(origin, ty, minimum_lifetime);
- }
-
/// Adds constraints to inference such that `T: 'a` holds (or
/// reports an error if it cannot).
///
@@ -1035,13 +601,7 @@
self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m.into()), expr_cmt);
}
- adjustment::AutoBorrow::RawPtr(m) => {
- let r = self.tcx.mk_region(ty::ReScope(region::Scope {
- id: expr.hir_id.local_id,
- data: region::ScopeData::Node,
- }));
- self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m), expr_cmt);
- }
+ adjustment::AutoBorrow::RawPtr(_) => {}
}
}
@@ -1251,39 +811,4 @@
}
}
}
-
- /// Checks that the values provided for type/region arguments in a given
- /// expression are well-formed and in-scope.
- fn substs_wf_in_scope(
- &mut self,
- origin: infer::ParameterOrigin,
- substs: SubstsRef<'tcx>,
- expr_span: Span,
- expr_region: ty::Region<'tcx>,
- ) {
- debug!(
- "substs_wf_in_scope(substs={:?}, \
- expr_region={:?}, \
- origin={:?}, \
- expr_span={:?})",
- substs, expr_region, origin, expr_span
- );
-
- let origin = infer::ParameterInScope(origin, expr_span);
-
- for kind in substs {
- match kind.unpack() {
- GenericArgKind::Lifetime(lt) => {
- self.sub_regions(origin.clone(), expr_region, lt);
- }
- GenericArgKind::Type(ty) => {
- let ty = self.resolve_type(ty);
- self.type_must_outlive(origin.clone(), ty, expr_region);
- }
- GenericArgKind::Const(_) => {
- // Const parameters don't impose constraints.
- }
- }
- }
- }
}
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index b79ac50..d5db613 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -425,7 +425,8 @@
fcx.register_predicate(traits::Obligation::new(
cause,
fcx.param_env,
- ty::Predicate::ConstEvaluatable(discr_def_id.to_def_id(), discr_substs),
+ ty::PredicateKind::ConstEvaluatable(discr_def_id.to_def_id(), discr_substs)
+ .to_predicate(fcx.tcx),
));
}
}
@@ -1174,8 +1175,11 @@
substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]),
};
- let obligation =
- traits::Obligation::new(cause, fcx.param_env, trait_ref.without_const().to_predicate());
+ let obligation = traits::Obligation::new(
+ cause,
+ fcx.param_env,
+ trait_ref.without_const().to_predicate(fcx.tcx),
+ );
if fcx.predicate_must_hold_modulo_regions(&obligation) {
true
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index efa3cd9..c5dd314 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -11,7 +11,6 @@
use rustc_infer::infer;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{RegionckMode, TyCtxtInferExt};
-use rustc_middle::middle::region;
use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -293,11 +292,9 @@
}
// Finally, resolve all regions.
- let region_scope_tree = region::ScopeTree::default();
let outlives_env = OutlivesEnvironment::new(param_env);
infcx.resolve_regions_and_report_errors(
impl_did.to_def_id(),
- ®ion_scope_tree,
&outlives_env,
RegionckMode::default(),
);
@@ -552,14 +549,8 @@
}
// Finally, resolve all regions.
- let region_scope_tree = region::ScopeTree::default();
let outlives_env = OutlivesEnvironment::new(param_env);
- infcx.resolve_regions_and_report_errors(
- impl_did,
- ®ion_scope_tree,
- &outlives_env,
- RegionckMode::default(),
- );
+ infcx.resolve_regions_and_report_errors(impl_did, &outlives_env, RegionckMode::default());
CoerceUnsizedInfo { custom_kind: kind }
})
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 66ef6a0..355b4fc 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -528,7 +528,7 @@
if param_id == item_hir_id {
let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id);
extend =
- Some((identity_trait_ref.without_const().to_predicate(), item.span));
+ Some((identity_trait_ref.without_const().to_predicate(tcx), item.span));
}
generics
}
@@ -548,8 +548,10 @@
let extra_predicates = extend.into_iter().chain(
icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true))
.into_iter()
- .filter(|(predicate, _)| match predicate {
- ty::Predicate::Trait(ref data, _) => data.skip_binder().self_ty().is_param(index),
+ .filter(|(predicate, _)| match predicate.kind() {
+ ty::PredicateKind::Trait(ref data, _) => {
+ data.skip_binder().self_ty().is_param(index)
+ }
_ => false,
}),
);
@@ -994,7 +996,7 @@
// which will, in turn, reach indirect supertraits.
for &(pred, span) in superbounds {
debug!("superbound: {:?}", pred);
- if let ty::Predicate::Trait(bound, _) = pred {
+ if let ty::PredicateKind::Trait(bound, _) = pred.kind() {
tcx.at(span).super_predicates_of(bound.def_id());
}
}
@@ -1655,7 +1657,7 @@
let span = tcx.sess.source_map().guess_head_span(tcx.def_span(def_id));
result.predicates =
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
- ty::TraitRef::identity(tcx, def_id).without_const().to_predicate(),
+ ty::TraitRef::identity(tcx, def_id).without_const().to_predicate(tcx),
span,
))));
}
@@ -1830,7 +1832,7 @@
// set of defaults that can be incorporated into another impl.
if let Some(trait_ref) = is_default_impl_trait {
predicates.push((
- trait_ref.to_poly_trait_ref().without_const().to_predicate(),
+ trait_ref.to_poly_trait_ref().without_const().to_predicate(tcx),
tcx.def_span(def_id),
));
}
@@ -1853,7 +1855,7 @@
hir::GenericBound::Outlives(lt) => {
let bound = AstConv::ast_region_to_region(&icx, <, None);
let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound));
- predicates.push((outlives.to_predicate(), lt.span));
+ predicates.push((outlives.to_predicate(tcx), lt.span));
}
_ => bug!(),
});
@@ -1899,7 +1901,8 @@
let re_root_empty = tcx.lifetimes.re_root_empty;
let predicate = ty::OutlivesPredicate(ty, re_root_empty);
predicates.push((
- ty::Predicate::TypeOutlives(ty::Binder::dummy(predicate)),
+ ty::PredicateKind::TypeOutlives(ty::Binder::dummy(predicate))
+ .to_predicate(tcx),
span,
));
}
@@ -1928,7 +1931,10 @@
&hir::GenericBound::Outlives(ref lifetime) => {
let region = AstConv::ast_region_to_region(&icx, lifetime, None);
let pred = ty::Binder::bind(ty::OutlivesPredicate(ty, region));
- predicates.push((ty::Predicate::TypeOutlives(pred), lifetime.span))
+ predicates.push((
+ ty::PredicateKind::TypeOutlives(pred).to_predicate(tcx),
+ lifetime.span,
+ ))
}
}
}
@@ -1945,7 +1951,7 @@
};
let pred = ty::Binder::bind(ty::OutlivesPredicate(r1, r2));
- (ty::Predicate::RegionOutlives(pred), span)
+ (ty::PredicateKind::RegionOutlives(pred).to_predicate(icx.tcx), span)
}))
}
@@ -2116,7 +2122,7 @@
hir::GenericBound::Outlives(ref lifetime) => {
let region = astconv.ast_region_to_region(lifetime, None);
let pred = ty::Binder::bind(ty::OutlivesPredicate(param_ty, region));
- vec![(ty::Predicate::TypeOutlives(pred), lifetime.span)]
+ vec![(ty::PredicateKind::TypeOutlives(pred).to_predicate(astconv.tcx()), lifetime.span)]
}
}
}
diff --git a/src/librustc_typeck/constrained_generic_params.rs b/src/librustc_typeck/constrained_generic_params.rs
index 07ff3bc..34497d1 100644
--- a/src/librustc_typeck/constrained_generic_params.rs
+++ b/src/librustc_typeck/constrained_generic_params.rs
@@ -180,7 +180,7 @@
changed = false;
for j in i..predicates.len() {
- if let ty::Predicate::Projection(ref poly_projection) = predicates[j].0 {
+ if let ty::PredicateKind::Projection(ref poly_projection) = predicates[j].0.kind() {
// Note that we can skip binder here because the impl
// trait ref never contains any late-bound regions.
let projection = poly_projection.skip_binder();
diff --git a/src/librustc_typeck/impl_wf_check/min_specialization.rs b/src/librustc_typeck/impl_wf_check/min_specialization.rs
index 919bcc9..08404be 100644
--- a/src/librustc_typeck/impl_wf_check/min_specialization.rs
+++ b/src/librustc_typeck/impl_wf_check/min_specialization.rs
@@ -73,7 +73,6 @@
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt};
use rustc_infer::traits::specialization_graph::Node;
-use rustc_middle::middle::region::ScopeTree;
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{self, InstantiatedPredicates, TyCtxt, TypeFoldable};
@@ -165,12 +164,7 @@
// Conservatively use an empty `ParamEnv`.
let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty());
- infcx.resolve_regions_and_report_errors(
- impl1_def_id,
- &ScopeTree::default(),
- &outlives_env,
- RegionckMode::default(),
- );
+ infcx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env, RegionckMode::default());
let impl2_substs = match infcx.fully_resolve(&impl2_substs) {
Ok(s) => s,
Err(_) => {
@@ -204,7 +198,7 @@
// the functions in `cgp` add the constrained parameters to a list of
// unconstrained parameters.
for (predicate, _) in impl_generic_predicates.predicates.iter() {
- if let ty::Predicate::Projection(proj) = predicate {
+ if let ty::PredicateKind::Projection(proj) = predicate.kind() {
let projection_ty = proj.skip_binder().projection_ty;
let projected_ty = proj.skip_binder().ty;
@@ -368,13 +362,13 @@
fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: &ty::Predicate<'tcx>, span: Span) {
debug!("can_specialize_on(predicate = {:?})", predicate);
- match predicate {
+ match predicate.kind() {
// Global predicates are either always true or always false, so we
// are fine to specialize on.
_ if predicate.is_global() => (),
// We allow specializing on explicitly marked traits with no associated
// items.
- ty::Predicate::Trait(pred, hir::Constness::NotConst) => {
+ ty::PredicateKind::Trait(pred, hir::Constness::NotConst) => {
if !matches!(
trait_predicate_kind(tcx, predicate),
Some(TraitSpecializationKind::Marker)
@@ -401,19 +395,19 @@
tcx: TyCtxt<'tcx>,
predicate: &ty::Predicate<'tcx>,
) -> Option<TraitSpecializationKind> {
- match predicate {
- ty::Predicate::Trait(pred, hir::Constness::NotConst) => {
+ match predicate.kind() {
+ ty::PredicateKind::Trait(pred, hir::Constness::NotConst) => {
Some(tcx.trait_def(pred.def_id()).specialization_kind)
}
- ty::Predicate::Trait(_, hir::Constness::Const)
- | ty::Predicate::RegionOutlives(_)
- | ty::Predicate::TypeOutlives(_)
- | ty::Predicate::Projection(_)
- | ty::Predicate::WellFormed(_)
- | ty::Predicate::Subtype(_)
- | ty::Predicate::ObjectSafe(_)
- | ty::Predicate::ClosureKind(..)
- | ty::Predicate::ConstEvaluatable(..)
- | ty::Predicate::ConstEquate(..) => None,
+ ty::PredicateKind::Trait(_, hir::Constness::Const)
+ | ty::PredicateKind::RegionOutlives(_)
+ | ty::PredicateKind::TypeOutlives(_)
+ | ty::PredicateKind::Projection(_)
+ | ty::PredicateKind::WellFormed(_)
+ | ty::PredicateKind::Subtype(_)
+ | ty::PredicateKind::ObjectSafe(_)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => None,
}
}
diff --git a/src/librustc_typeck/outlives/explicit.rs b/src/librustc_typeck/outlives/explicit.rs
index 66daf0e..5740cc2 100644
--- a/src/librustc_typeck/outlives/explicit.rs
+++ b/src/librustc_typeck/outlives/explicit.rs
@@ -29,8 +29,8 @@
// process predicates and convert to `RequiredPredicates` entry, see below
for &(predicate, span) in predicates.predicates {
- match predicate {
- ty::Predicate::TypeOutlives(predicate) => {
+ match predicate.kind() {
+ ty::PredicateKind::TypeOutlives(predicate) => {
let OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder();
insert_outlives_predicate(
tcx,
@@ -41,7 +41,7 @@
)
}
- ty::Predicate::RegionOutlives(predicate) => {
+ ty::PredicateKind::RegionOutlives(predicate) => {
let OutlivesPredicate(ref reg1, ref reg2) = predicate.skip_binder();
insert_outlives_predicate(
tcx,
@@ -52,14 +52,14 @@
)
}
- ty::Predicate::Trait(..)
- | ty::Predicate::Projection(..)
- | ty::Predicate::WellFormed(..)
- | ty::Predicate::ObjectSafe(..)
- | ty::Predicate::ClosureKind(..)
- | ty::Predicate::Subtype(..)
- | ty::Predicate::ConstEvaluatable(..)
- | ty::Predicate::ConstEquate(..) => (),
+ ty::PredicateKind::Trait(..)
+ | ty::PredicateKind::Projection(..)
+ | ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => (),
}
}
diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs
index a49d8e5..1b2b08a 100644
--- a/src/librustc_typeck/outlives/mod.rs
+++ b/src/librustc_typeck/outlives/mod.rs
@@ -3,7 +3,7 @@
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt};
+use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt};
use rustc_span::symbol::sym;
use rustc_span::Span;
@@ -30,9 +30,9 @@
if tcx.has_attr(item_def_id, sym::rustc_outlives) {
let mut pred: Vec<String> = predicates
.iter()
- .map(|(out_pred, _)| match out_pred {
- ty::Predicate::RegionOutlives(p) => p.to_string(),
- ty::Predicate::TypeOutlives(p) => p.to_string(),
+ .map(|(out_pred, _)| match out_pred.kind() {
+ ty::PredicateKind::RegionOutlives(p) => p.to_string(),
+ ty::PredicateKind::TypeOutlives(p) => p.to_string(),
err => bug!("unexpected predicate {:?}", err),
})
.collect();
@@ -82,22 +82,26 @@
.iter()
.map(|(&def_id, set)| {
let predicates = &*tcx.arena.alloc_from_iter(set.iter().filter_map(
- |(ty::OutlivesPredicate(kind1, region2), &span)| match kind1.unpack() {
- GenericArgKind::Type(ty1) => Some((
- ty::Predicate::TypeOutlives(ty::Binder::bind(ty::OutlivesPredicate(
- ty1, region2,
- ))),
- span,
- )),
- GenericArgKind::Lifetime(region1) => Some((
- ty::Predicate::RegionOutlives(ty::Binder::bind(ty::OutlivesPredicate(
- region1, region2,
- ))),
- span,
- )),
- GenericArgKind::Const(_) => {
- // Generic consts don't impose any constraints.
- None
+ |(ty::OutlivesPredicate(kind1, region2), &span)| {
+ match kind1.unpack() {
+ GenericArgKind::Type(ty1) => Some((
+ ty::PredicateKind::TypeOutlives(ty::Binder::bind(
+ ty::OutlivesPredicate(ty1, region2),
+ ))
+ .to_predicate(tcx),
+ span,
+ )),
+ GenericArgKind::Lifetime(region1) => Some((
+ ty::PredicateKind::RegionOutlives(ty::Binder::bind(
+ ty::OutlivesPredicate(region1, region2),
+ ))
+ .to_predicate(tcx),
+ span,
+ )),
+ GenericArgKind::Const(_) => {
+ // Generic consts don't impose any constraints.
+ None
+ }
}
},
));
diff --git a/src/librustc_typeck/outlives/utils.rs b/src/librustc_typeck/outlives/utils.rs
index 3bbe3e3..8b06967 100644
--- a/src/librustc_typeck/outlives/utils.rs
+++ b/src/librustc_typeck/outlives/utils.rs
@@ -170,7 +170,6 @@
// These regions don't appear in types from type declarations:
RegionKind::ReErased
- | RegionKind::ReScope(..)
| RegionKind::ReVar(..)
| RegionKind::RePlaceholder(..)
| RegionKind::ReFree(..) => {
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 3a680f5..e04af68 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -444,7 +444,6 @@
}
ty::ReFree(..)
- | ty::ReScope(..)
| ty::ReVar(..)
| ty::RePlaceholder(..)
| ty::ReEmpty(_)
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 144c169..423160f 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -315,11 +315,11 @@
tcx: TyCtxt<'tcx>,
pred: ty::Predicate<'tcx>,
) -> FxHashSet<GenericParamDef> {
- let regions = match pred {
- ty::Predicate::Trait(poly_trait_pred, _) => {
+ let regions = match pred.kind() {
+ ty::PredicateKind::Trait(poly_trait_pred, _) => {
tcx.collect_referenced_late_bound_regions(&poly_trait_pred)
}
- ty::Predicate::Projection(poly_proj_pred) => {
+ ty::PredicateKind::Projection(poly_proj_pred) => {
tcx.collect_referenced_late_bound_regions(&poly_proj_pred)
}
_ => return FxHashSet::default(),
@@ -465,8 +465,8 @@
.iter()
.filter(|p| {
!orig_bounds.contains(p)
- || match p {
- ty::Predicate::Trait(pred, _) => pred.def_id() == sized_trait,
+ || match p.kind() {
+ ty::PredicateKind::Trait(pred, _) => pred.def_id() == sized_trait,
_ => false,
}
})
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index d987505..3d27855 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -65,7 +65,7 @@
match infcx.evaluate_obligation(&traits::Obligation::new(
cause,
param_env,
- trait_ref.without_const().to_predicate(),
+ trait_ref.without_const().to_predicate(infcx.tcx),
)) {
Ok(eval_result) => eval_result.may_apply(),
Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index c130ed3..702c7d1 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -447,7 +447,6 @@
ty::ReLateBound(..)
| ty::ReFree(..)
- | ty::ReScope(..)
| ty::ReVar(..)
| ty::RePlaceholder(..)
| ty::ReEmpty(_)
@@ -481,20 +480,18 @@
impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
- use rustc_middle::ty::Predicate;
+ match self.kind() {
+ ty::PredicateKind::Trait(ref pred, _) => Some(pred.clean(cx)),
+ ty::PredicateKind::Subtype(ref pred) => Some(pred.clean(cx)),
+ ty::PredicateKind::RegionOutlives(ref pred) => pred.clean(cx),
+ ty::PredicateKind::TypeOutlives(ref pred) => pred.clean(cx),
+ ty::PredicateKind::Projection(ref pred) => Some(pred.clean(cx)),
- match *self {
- Predicate::Trait(ref pred, _) => Some(pred.clean(cx)),
- Predicate::Subtype(ref pred) => Some(pred.clean(cx)),
- Predicate::RegionOutlives(ref pred) => pred.clean(cx),
- Predicate::TypeOutlives(ref pred) => pred.clean(cx),
- Predicate::Projection(ref pred) => Some(pred.clean(cx)),
-
- Predicate::WellFormed(..)
- | Predicate::ObjectSafe(..)
- | Predicate::ClosureKind(..)
- | Predicate::ConstEvaluatable(..)
- | Predicate::ConstEquate(..) => panic!("not user writable"),
+ ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => panic!("not user writable"),
}
}
}
@@ -765,7 +762,7 @@
if let ty::Param(param) = outlives.skip_binder().0.kind {
return Some(param.index);
}
- } else if let ty::Predicate::Projection(p) = p {
+ } else if let ty::PredicateKind::Projection(p) = p.kind() {
if let ty::Param(param) = p.skip_binder().projection_ty.self_ty().kind {
projection = Some(p);
return Some(param.index);
@@ -1663,7 +1660,7 @@
.filter_map(|predicate| {
let trait_ref = if let Some(tr) = predicate.to_opt_poly_trait_ref() {
tr
- } else if let ty::Predicate::TypeOutlives(pred) = *predicate {
+ } else if let ty::PredicateKind::TypeOutlives(pred) = predicate.kind() {
// these should turn up at the end
if let Some(r) = pred.skip_binder().1.clean(cx) {
regions.push(GenericBound::Outlives(r));
@@ -1684,7 +1681,7 @@
.predicates
.iter()
.filter_map(|pred| {
- if let ty::Predicate::Projection(proj) = *pred {
+ if let ty::PredicateKind::Projection(proj) = pred.kind() {
let proj = proj.skip_binder();
if proj.projection_ty.trait_ref(cx.tcx)
== *trait_ref.skip_binder()
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 1404d45..37c613f 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -141,7 +141,7 @@
.predicates
.iter()
.filter_map(|(pred, _)| {
- if let ty::Predicate::Trait(ref pred, _) = *pred {
+ if let ty::PredicateKind::Trait(ref pred, _) = pred.kind() {
if pred.skip_binder().trait_ref.self_ty() == self_ty {
Some(pred.def_id())
} else {
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index ab52475..b1e0ab9 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -3,12 +3,14 @@
font-family: 'Fira Sans';
font-style: normal;
font-weight: 400;
+ font-display: optional;
src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff');
}
@font-face {
font-family: 'Fira Sans';
font-style: normal;
font-weight: 500;
+ font-display: optional;
src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff');
}
@@ -17,18 +19,23 @@
font-family: 'Source Serif Pro';
font-style: normal;
font-weight: 400;
+ /* The difference for body text without this font is greater than other fonts,
+ * so the 0~100ms block of fallback is preferred over optional, for legibility. */
+ font-display: fallback;
src: local('Source Serif Pro'), url("SourceSerifPro-Regular.ttf.woff") format('woff');
}
@font-face {
font-family: 'Source Serif Pro';
font-style: italic;
font-weight: 400;
+ font-display: optional;
src: local('Source Serif Pro Italic'), url("SourceSerifPro-It.ttf.woff") format('woff');
}
@font-face {
font-family: 'Source Serif Pro';
font-style: normal;
font-weight: 700;
+ font-display: optional;
src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.ttf.woff") format('woff');
}
@@ -37,6 +44,7 @@
font-family: 'Source Code Pro';
font-style: normal;
font-weight: 400;
+ font-display: optional;
/* Avoid using locally installed font because bad versions are in circulation:
* see https://github.com/rust-lang/rust/issues/24355 */
src: url("SourceCodePro-Regular.woff") format('woff');
@@ -45,6 +53,7 @@
font-family: 'Source Code Pro';
font-style: normal;
font-weight: 600;
+ font-display: optional;
src: url("SourceCodePro-Semibold.woff") format('woff');
}
@@ -625,7 +634,7 @@
display: initial;
}
-.in-band:hover > .anchor {
+.in-band:hover > .anchor, .impl:hover > .anchor {
display: inline-block;
position: absolute;
}
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index a3ef350..adb7fc3 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -232,37 +232,46 @@
DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::TyAlias,
did,
) => {
- // We need item's parent to know if it's
- // trait impl or struct/enum/etc impl
- let item_parent = item_opt
+ // Checks if item_name belongs to `impl SomeItem`
+ let impl_item = cx
+ .tcx
+ .inherent_impls(did)
+ .iter()
+ .flat_map(|imp| cx.tcx.associated_items(*imp).in_definition_order())
+ .find(|item| item.ident.name == item_name);
+ let trait_item = item_opt
.and_then(|item| self.cx.as_local_hir_id(item.def_id))
.and_then(|item_hir| {
+ // Checks if item_name belongs to `impl SomeTrait for SomeItem`
let parent_hir = self.cx.tcx.hir().get_parent_item(item_hir);
- self.cx.tcx.hir().find(parent_hir)
+ let item_parent = self.cx.tcx.hir().find(parent_hir);
+ match item_parent {
+ Some(hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::Impl { of_trait: Some(_), self_ty, .. },
+ ..
+ })) => cx
+ .tcx
+ .associated_item_def_ids(self_ty.hir_id.owner)
+ .iter()
+ .map(|child| {
+ let associated_item = cx.tcx.associated_item(*child);
+ associated_item
+ })
+ .find(|child| child.ident.name == item_name),
+ _ => None,
+ }
});
- let item = match item_parent {
- Some(hir::Node::Item(hir::Item {
- kind: hir::ItemKind::Impl { of_trait: Some(_), self_ty, .. },
- ..
- })) => {
- // trait impl
- cx.tcx
- .associated_item_def_ids(self_ty.hir_id.owner)
- .iter()
- .map(|child| {
- let associated_item = cx.tcx.associated_item(*child);
- associated_item
- })
- .find(|child| child.ident.name == item_name)
+ let item = match (impl_item, trait_item) {
+ (Some(from_impl), Some(_)) => {
+ // Although it's ambiguous, return impl version for compat. sake.
+ // To handle that properly resolve() would have to support
+ // something like
+ // [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
+ Some(from_impl)
}
- _ => {
- // struct/enum/etc. impl
- cx.tcx
- .inherent_impls(did)
- .iter()
- .flat_map(|imp| cx.tcx.associated_items(*imp).in_definition_order())
- .find(|item| item.ident.name == item_name)
- }
+ (None, Some(from_trait)) => Some(from_trait),
+ (Some(from_impl), None) => Some(from_impl),
+ _ => None,
};
if let Some(item) = item {
@@ -422,6 +431,43 @@
look_for_tests(&cx, &dox, &item, true);
+ // find item's parent to resolve `Self` in item's docs below
+ let parent_name = self.cx.as_local_hir_id(item.def_id).and_then(|item_hir| {
+ let parent_hir = self.cx.tcx.hir().get_parent_item(item_hir);
+ let item_parent = self.cx.tcx.hir().find(parent_hir);
+ match item_parent {
+ Some(hir::Node::Item(hir::Item {
+ kind:
+ hir::ItemKind::Impl {
+ self_ty:
+ hir::Ty {
+ kind:
+ hir::TyKind::Path(hir::QPath::Resolved(
+ _,
+ hir::Path { segments, .. },
+ )),
+ ..
+ },
+ ..
+ },
+ ..
+ })) => segments.first().and_then(|seg| Some(seg.ident.to_string())),
+ Some(hir::Node::Item(hir::Item {
+ ident, kind: hir::ItemKind::Enum(..), ..
+ }))
+ | Some(hir::Node::Item(hir::Item {
+ ident, kind: hir::ItemKind::Struct(..), ..
+ }))
+ | Some(hir::Node::Item(hir::Item {
+ ident, kind: hir::ItemKind::Union(..), ..
+ }))
+ | Some(hir::Node::Item(hir::Item {
+ ident, kind: hir::ItemKind::Trait(..), ..
+ })) => Some(ident.to_string()),
+ _ => None,
+ }
+ });
+
for (ori_link, link_range) in markdown_links(&dox) {
// Bail early for real links.
if ori_link.contains('/') {
@@ -458,7 +504,7 @@
};
let (res, fragment) = {
let mut kind = None;
- let path_str = if let Some(prefix) =
+ let mut path_str = if let Some(prefix) =
["struct@", "enum@", "type@", "trait@", "union@"]
.iter()
.find(|p| link.starts_with(**p))
@@ -512,6 +558,15 @@
let base_node =
if item.is_mod() && item.attrs.inner_docs { None } else { parent_node };
+ let resolved_self;
+ // replace `Self` with suitable item's parent name
+ if path_str.starts_with("Self::") {
+ if let Some(ref name) = parent_name {
+ resolved_self = format!("{}::{}", name, &path_str[6..]);
+ path_str = &resolved_self;
+ }
+ }
+
match kind {
Some(ns @ ValueNS) => {
match self.resolve(
@@ -520,7 +575,7 @@
¤t_item,
base_node,
&extra_fragment,
- None,
+ Some(&item),
) {
Ok(res) => res,
Err(ErrorKind::ResolutionFailure) => {
@@ -543,7 +598,7 @@
¤t_item,
base_node,
&extra_fragment,
- None,
+ Some(&item),
) {
Ok(res) => res,
Err(ErrorKind::ResolutionFailure) => {
@@ -568,7 +623,7 @@
¤t_item,
base_node,
&extra_fragment,
- None,
+ Some(&item),
) {
Err(ErrorKind::AnchorFailure(msg)) => {
anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 8e743ac..deb9eb5 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -882,7 +882,7 @@
/// Returns `max` if `self` is greater than `max`, and `min` if `self` is
/// less than `min`. Otherwise this returns `self`.
///
- /// Not that this function returns NaN if the initial value was NaN as
+ /// Note that this function returns NaN if the initial value was NaN as
/// well.
///
/// # Panics
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index fe64d27..b79e550 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -884,7 +884,7 @@
/// Returns `max` if `self` is greater than `max`, and `min` if `self` is
/// less than `min`. Otherwise this returns `self`.
///
- /// Not that this function returns NaN if the initial value was NaN as
+ /// Note that this function returns NaN if the initial value was NaN as
/// well.
///
/// # Panics
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
index e2092cf..89dd9fb 100644
--- a/src/libstd/future.rs
+++ b/src/libstd/future.rs
@@ -2,4 +2,16 @@
#[doc(inline)]
#[stable(feature = "futures_api", since = "1.36.0")]
-pub use core::future::*;
+pub use core::future::Future;
+
+#[doc(inline)]
+#[unstable(feature = "gen_future", issue = "50547")]
+pub use core::future::{from_generator, get_context, ResumeTy};
+
+#[doc(inline)]
+#[unstable(feature = "future_readiness_fns", issue = "70921")]
+pub use core::future::{pending, ready, Pending, Ready};
+
+#[doc(inline)]
+#[unstable(feature = "into_future", issue = "67644")]
+pub use core::future::IntoFuture;
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index ac07af5..cc3e613 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -266,12 +266,15 @@
#![feature(external_doc)]
#![feature(fn_traits)]
#![feature(format_args_nl)]
+#![feature(future_readiness_fns)]
+#![feature(gen_future)]
#![feature(generator_trait)]
#![feature(global_asm)]
#![feature(hash_raw_entry)]
#![feature(hashmap_internals)]
#![feature(int_error_internals)]
#![feature(int_error_matching)]
+#![feature(into_future)]
#![feature(integer_atomics)]
#![feature(lang_items)]
#![feature(libc)]
diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs
index edc2803..6e2478b 100644
--- a/src/libstd/net/ip.rs
+++ b/src/libstd/net/ip.rs
@@ -856,16 +856,23 @@
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Ipv4Addr {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- const IPV4_BUF_LEN: usize = 15; // Long enough for the longest possible IPv4 address
- let mut buf = [0u8; IPV4_BUF_LEN];
- let mut buf_slice = &mut buf[..];
let octets = self.octets();
- // Note: The call to write should never fail, hence the unwrap
- write!(buf_slice, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]).unwrap();
- let len = IPV4_BUF_LEN - buf_slice.len();
- // This unsafe is OK because we know what is being written to the buffer
- let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
- fmt.pad(buf)
+ // Fast Path: if there's no alignment stuff, write directly to the buffer
+ if fmt.precision().is_none() && fmt.width().is_none() {
+ write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
+ } else {
+ const IPV4_BUF_LEN: usize = 15; // Long enough for the longest possible IPv4 address
+ let mut buf = [0u8; IPV4_BUF_LEN];
+ let mut buf_slice = &mut buf[..];
+
+ // Note: The call to write should never fail, hence the unwrap
+ write!(buf_slice, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]).unwrap();
+ let len = IPV4_BUF_LEN - buf_slice.len();
+
+ // This unsafe is OK because we know what is being written to the buffer
+ let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
+ fmt.pad(buf)
+ }
}
}
diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs
index fa8670b..048ce24 100644
--- a/src/libstd/sys/unix/ext/process.rs
+++ b/src/libstd/sys/unix/ext/process.rs
@@ -111,7 +111,7 @@
///
/// Set the first process argument, `argv[0]`, to something other than the
/// default executable path.
- #[unstable(feature = "process_set_argv0", issue = "66510")]
+ #[stable(feature = "process_set_argv0", since = "1.45.0")]
fn arg0<S>(&mut self, arg: S) -> &mut process::Command
where
S: AsRef<OsStr>;
diff --git a/src/libstd/sys/vxworks/ext/process.rs b/src/libstd/sys/vxworks/ext/process.rs
index 31e691d..c3710f4 100644
--- a/src/libstd/sys/vxworks/ext/process.rs
+++ b/src/libstd/sys/vxworks/ext/process.rs
@@ -111,7 +111,7 @@
///
/// Set the first process argument, `argv[0]`, to something other than the
/// default executable path.
- #[unstable(feature = "process_set_argv0", issue = "66510")]
+ #[stable(feature = "process_set_argv0", since = "1.45.0")]
fn arg0<S>(&mut self, arg: S) -> &mut process::Command
where
S: AsRef<OsStr>;
diff --git a/src/libstd/tests/run-time-detect.rs b/src/libstd/tests/run-time-detect.rs
index 2e6d1bc..8dd1a8a 100644
--- a/src/libstd/tests/run-time-detect.rs
+++ b/src/libstd/tests/run-time-detect.rs
@@ -32,6 +32,7 @@
println!("rdm: {}", is_aarch64_feature_detected!("rdm"));
println!("rcpc: {}", is_aarch64_feature_detected!("rcpc"));
println!("dotprod: {}", is_aarch64_feature_detected!("dotprod"));
+ println!("tme: {}", is_aarch64_feature_detected!("tme"));
}
#[test]
diff --git a/src/libunwind/lib.rs b/src/libunwind/lib.rs
index 18d41be..cc025da 100644
--- a/src/libunwind/lib.rs
+++ b/src/libunwind/lib.rs
@@ -27,3 +27,7 @@
#[link(name = "gcc_eh", kind = "static-nobundle", cfg(target_feature = "crt-static"))]
#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
extern "C" {}
+
+#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
+#[link(name = "unwind", kind = "static-nobundle")]
+extern "C" {}
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 6c638c5..02dcfb8 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -445,7 +445,7 @@
const char *TripleStr, const char *CPU, const char *Feature,
const char *ABIStr, LLVMRustCodeModel RustCM, LLVMRustRelocModel RustReloc,
LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
- bool PositionIndependentExecutable, bool FunctionSections,
+ bool FunctionSections,
bool DataSections,
bool TrapUnreachable,
bool Singlethread,
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index b988d06..24f3562 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -720,7 +720,6 @@
extern "C" LLVMMetadataRef
LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
- LLVMMetadataRef File,
LLVMMetadataRef ParameterTypes) {
return wrap(Builder->createSubroutineType(
DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
@@ -755,7 +754,7 @@
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
- uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding) {
+ uint64_t SizeInBits, unsigned Encoding) {
return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
}
@@ -964,9 +963,7 @@
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
- const char *Name, size_t NameLen,
- LLVMMetadataRef Ty, LLVMMetadataRef File, unsigned LineNo,
- unsigned ColumnNo) {
+ const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
return wrap(Builder->createTemplateTypeParameter(
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty)));
}
diff --git a/src/test/incremental/issue-72386.rs b/src/test/incremental/issue-72386.rs
new file mode 100644
index 0000000..3dc7f50
--- /dev/null
+++ b/src/test/incremental/issue-72386.rs
@@ -0,0 +1,22 @@
+// revisions: rpass1 cfail1 rpass3
+// only-x86_64
+// Regression test for issue #72386
+// Checks that we don't ICE when switching to an invalid register
+// and back again
+
+#![feature(asm)]
+
+#[cfg(any(rpass1, rpass3))]
+fn main() {
+ unsafe {
+ asm!("nop")
+ }
+}
+
+#[cfg(cfail1)]
+fn main() {
+ unsafe {
+ asm!("nop",out("invalid_reg")_)
+ //[cfail1]~^ ERROR invalid register
+ }
+}
diff --git "a/src/test/mir-opt/generator-drop-cleanup/rustc.main-\173\173closure\175\175.generator_drop.0.mir" "b/src/test/mir-opt/generator-drop-cleanup/rustc.main-\173\173closure\175\175.generator_drop.0.mir"
index 382273a..6a32a42 100644
--- "a/src/test/mir-opt/generator-drop-cleanup/rustc.main-\173\173closure\175\175.generator_drop.0.mir"
+++ "b/src/test/mir-opt/generator-drop-cleanup/rustc.main-\173\173closure\175\175.generator_drop.0.mir"
@@ -9,7 +9,7 @@
let mut _5: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:12:9: 12:14
let mut _7: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:10:18: 10:18
let mut _8: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6
- let mut _9: isize; // in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6
+ let mut _9: u32; // in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6
scope 1 {
debug _s => (((*_1) as variant#3).0: std::string::String); // in scope 1 at $DIR/generator-drop-cleanup.rs:11:13: 11:15
}
diff --git "a/src/test/mir-opt/generator-tiny/rustc.main-\173\173closure\175\175.generator_resume.0.mir" "b/src/test/mir-opt/generator-tiny/rustc.main-\173\173closure\175\175.generator_resume.0.mir"
index 75c2fb3..c73dea5 100644
--- "a/src/test/mir-opt/generator-tiny/rustc.main-\173\173closure\175\175.generator_resume.0.mir"
+++ "b/src/test/mir-opt/generator-tiny/rustc.main-\173\173closure\175\175.generator_resume.0.mir"
@@ -12,7 +12,7 @@
let _8: (); // in scope 0 at $DIR/generator-tiny.rs:23:13: 23:21
let mut _9: (); // in scope 0 at $DIR/generator-tiny.rs:19:25: 19:25
let _10: u8; // in scope 0 at $DIR/generator-tiny.rs:19:17: 19:19
- let mut _11: isize; // in scope 0 at $DIR/generator-tiny.rs:19:16: 25:6
+ let mut _11: u32; // in scope 0 at $DIR/generator-tiny.rs:19:16: 25:6
scope 1 {
debug _d => (((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 {u8, HasDrop, ()}])) as variant#3).0: HasDrop); // in scope 1 at $DIR/generator-tiny.rs:20:13: 20:15
}
diff --git a/src/test/rustdoc/intra-link-self.rs b/src/test/rustdoc/intra-link-self.rs
index acf975f..97752d5 100644
--- a/src/test/rustdoc/intra-link-self.rs
+++ b/src/test/rustdoc/intra-link-self.rs
@@ -1,5 +1,7 @@
#![crate_name = "foo"]
+// ignore-tidy-linelength
+
// @has foo/index.html '//a/@href' '../foo/struct.Foo.html#method.new'
// @has foo/struct.Foo.html '//a/@href' '../foo/struct.Foo.html#method.new'
@@ -27,3 +29,89 @@
unimplemented!()
}
}
+
+pub struct MyStruct {
+ // @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#structfield.struct_field'
+
+ /// [`struct_field`]
+ ///
+ /// [`struct_field`]: Self::struct_field
+ pub struct_field: u8,
+}
+
+pub enum MyEnum {
+ // @has foo/enum.MyEnum.html '//a/@href' '../foo/enum.MyEnum.html#EnumVariant.v'
+
+ /// [`EnumVariant`]
+ ///
+ /// [`EnumVariant`]: Self::EnumVariant
+ EnumVariant,
+}
+
+pub union MyUnion {
+ // @has foo/union.MyUnion.html '//a/@href' '../foo/union.MyUnion.html#structfield.union_field'
+
+ /// [`union_field`]
+ ///
+ /// [`union_field`]: Self::union_field
+ pub union_field: f32,
+}
+
+pub trait MyTrait {
+ // @has foo/trait.MyTrait.html '//a/@href' '../foo/trait.MyTrait.html#associatedtype.AssoType'
+
+ /// [`AssoType`]
+ ///
+ /// [`AssoType`]: Self::AssoType
+ type AssoType;
+
+ // @has foo/trait.MyTrait.html '//a/@href' '../foo/trait.MyTrait.html#associatedconstant.ASSO_CONST'
+
+ /// [`ASSO_CONST`]
+ ///
+ /// [`ASSO_CONST`]: Self::ASSO_CONST
+ const ASSO_CONST: i32 = 1;
+
+ // @has foo/trait.MyTrait.html '//a/@href' '../foo/trait.MyTrait.html#method.asso_fn'
+
+ /// [`asso_fn`]
+ ///
+ /// [`asso_fn`]: Self::asso_fn
+ fn asso_fn() {}
+}
+
+impl MyStruct {
+ // @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#method.for_impl'
+
+ /// [`for_impl`]
+ ///
+ /// [`for_impl`]: Self::for_impl
+ pub fn for_impl() {
+ unimplemented!()
+ }
+}
+
+impl MyTrait for MyStruct {
+ // @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedtype.AssoType'
+
+ /// [`AssoType`]
+ ///
+ /// [`AssoType`]: Self::AssoType
+ type AssoType = u32;
+
+ // @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedconstant.ASSO_CONST'
+
+ /// [`ASSO_CONST`]
+ ///
+ /// [`ASSO_CONST`]: Self::ASSO_CONST
+ const ASSO_CONST: i32 = 10;
+
+ // @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#method.asso_fn'
+
+ /// [`asso_fn`]
+ ///
+ /// [`asso_fn`]: Self::asso_fn
+ fn asso_fn() {
+ unimplemented!()
+ }
+}
diff --git a/src/test/rustdoc/issue-72340.rs b/src/test/rustdoc/issue-72340.rs
new file mode 100644
index 0000000..6ed3bfb
--- /dev/null
+++ b/src/test/rustdoc/issue-72340.rs
@@ -0,0 +1,19 @@
+#![crate_name = "foo"]
+
+pub struct Body;
+
+impl Body {
+ pub fn empty() -> Self {
+ Body
+ }
+
+}
+
+impl Default for Body {
+ // @has foo/struct.Body.html '//a/@href' '../foo/struct.Body.html#method.empty'
+
+ /// Returns [`Body::empty()`](Body::empty).
+ fn default() -> Body {
+ Body::empty()
+ }
+}
diff --git a/src/test/ui/async-await/async-fn-size-moved-locals.rs b/src/test/ui/async-await/async-fn-size-moved-locals.rs
index 636fafc..000acf1 100644
--- a/src/test/ui/async-await/async-fn-size-moved-locals.rs
+++ b/src/test/ui/async-await/async-fn-size-moved-locals.rs
@@ -114,5 +114,5 @@
assert_eq!(1026, std::mem::size_of_val(&single_with_noop()));
assert_eq!(3078, std::mem::size_of_val(&joined()));
assert_eq!(3079, std::mem::size_of_val(&joined_with_noop()));
- assert_eq!(7181, std::mem::size_of_val(&mixed_sizes()));
+ assert_eq!(6157, std::mem::size_of_val(&mixed_sizes()));
}
diff --git a/src/test/ui/borrowck/issue-45983.migrate.stderr b/src/test/ui/borrowck/issue-45983.migrate.stderr
deleted file mode 100644
index c1564cf..0000000
--- a/src/test/ui/borrowck/issue-45983.migrate.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error: borrowed data cannot be stored outside of its closure
- --> $DIR/issue-45983.rs:20:27
- |
-LL | let x = None;
- | - borrowed data cannot be stored into here...
-LL | give_any(|y| x = Some(y));
- | --- ^ cannot be stored outside of its closure
- | |
- | ...because it cannot outlive this closure
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/borrowck/issue-45983.nll.stderr b/src/test/ui/borrowck/issue-45983.nll.stderr
deleted file mode 100644
index 51bb4de..0000000
--- a/src/test/ui/borrowck/issue-45983.nll.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0521]: borrowed data escapes outside of closure
- --> $DIR/issue-45983.rs:20:18
- |
-LL | let x = None;
- | - `x` declared here, outside of the closure body
-LL | give_any(|y| x = Some(y));
- | - ^^^^^^^^^^^ `y` escapes the closure body here
- | |
- | `y` is a reference that is only valid in the closure body
-
-error[E0594]: cannot assign to `x`, as it is not declared as mutable
- --> $DIR/issue-45983.rs:20:18
- |
-LL | let x = None;
- | - help: consider changing this to be mutable: `mut x`
-LL | give_any(|y| x = Some(y));
- | ^^^^^^^^^^^ cannot assign
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/issue-45983.rs b/src/test/ui/borrowck/issue-45983.rs
index 3cd2820..6784f6f 100644
--- a/src/test/ui/borrowck/issue-45983.rs
+++ b/src/test/ui/borrowck/issue-45983.rs
@@ -1,24 +1,12 @@
// As documented in Issue #45983, this test is evaluating the quality
// of our diagnostics on erroneous code using higher-ranked closures.
-// revisions: migrate nll
-
-// Since we are testing nll (and migration) explicitly as a separate
-// revisions, don't worry about the --compare-mode=nll on this test.
-
-// ignore-compare-mode-nll
-// ignore-compare-mode-polonius
-
-//[nll]compile-flags: -Z borrowck=mir
-
fn give_any<F: for<'r> FnOnce(&'r ())>(f: F) {
f(&());
}
fn main() {
- let x = None;
+ let mut x = None;
give_any(|y| x = Some(y));
- //[migrate]~^ ERROR borrowed data cannot be stored outside of its closure
- //[nll]~^^ ERROR borrowed data escapes outside of closure
- //[nll]~| ERROR cannot assign to `x`, as it is not declared as mutable
+ //~^ ERROR borrowed data escapes outside of closure
}
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr b/src/test/ui/borrowck/issue-45983.stderr
similarity index 81%
rename from src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr
rename to src/test/ui/borrowck/issue-45983.stderr
index 68a0fe0..efd414a 100644
--- a/src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr
+++ b/src/test/ui/borrowck/issue-45983.stderr
@@ -1,9 +1,9 @@
error[E0521]: borrowed data escapes outside of closure
- --> $DIR/regions-escape-bound-fn-2.rs:8:18
+ --> $DIR/issue-45983.rs:10:18
|
LL | let mut x = None;
| ----- `x` declared here, outside of the closure body
-LL | with_int(|y| x = Some(y));
+LL | give_any(|y| x = Some(y));
| - ^^^^^^^^^^^ `y` escapes the closure body here
| |
| `y` is a reference that is only valid in the closure body
diff --git a/src/test/ui/borrowck/issue-7573.nll.stderr b/src/test/ui/borrowck/issue-7573.nll.stderr
deleted file mode 100644
index 20afecf..0000000
--- a/src/test/ui/borrowck/issue-7573.nll.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0521]: borrowed data escapes outside of closure
- --> $DIR/issue-7573.rs:21:9
- |
-LL | let mut lines_to_use: Vec<&CrateId> = Vec::new();
- | ---------------- `lines_to_use` declared here, outside of the closure body
-LL |
-LL | let push_id = |installed_id: &CrateId| {
- | ------------ `installed_id` is a reference that is only valid in the closure body
-...
-LL | lines_to_use.push(installed_id);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `installed_id` escapes the closure body here
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/borrowck/issue-7573.rs b/src/test/ui/borrowck/issue-7573.rs
index 20a6a5c..7c07411 100644
--- a/src/test/ui/borrowck/issue-7573.rs
+++ b/src/test/ui/borrowck/issue-7573.rs
@@ -1,36 +1,34 @@
pub struct CrateId {
local_path: String,
- junk: String
+ junk: String,
}
impl CrateId {
fn new(s: &str) -> CrateId {
- CrateId {
- local_path: s.to_string(),
- junk: "wutevs".to_string()
- }
+ CrateId { local_path: s.to_string(), junk: "wutevs".to_string() }
}
}
pub fn remove_package_from_database() {
let mut lines_to_use: Vec<&CrateId> = Vec::new();
- //~^ NOTE cannot infer an appropriate lifetime
+ //~^ NOTE `lines_to_use` declared here, outside of the closure body
let push_id = |installed_id: &CrateId| {
- //~^ NOTE borrowed data cannot outlive this closure
- //~| NOTE ...so that variable is valid at time of its declaration
+ //~^ NOTE `installed_id` is a reference that is only valid in the closure body
lines_to_use.push(installed_id);
- //~^ ERROR borrowed data cannot be stored outside of its closure
- //~| NOTE cannot be stored outside of its closure
+ //~^ ERROR borrowed data escapes outside of closure
+ //~| NOTE `installed_id` escapes the closure body here
};
list_database(push_id);
for l in &lines_to_use {
println!("{}", l.local_path);
}
-
}
-pub fn list_database<F>(mut f: F) where F: FnMut(&CrateId) {
+pub fn list_database<F>(mut f: F)
+where
+ F: FnMut(&CrateId),
+{
let stuff = ["foo", "bar"];
for l in &stuff {
diff --git a/src/test/ui/borrowck/issue-7573.stderr b/src/test/ui/borrowck/issue-7573.stderr
index 32b3ef7..815419d 100644
--- a/src/test/ui/borrowck/issue-7573.stderr
+++ b/src/test/ui/borrowck/issue-7573.stderr
@@ -1,16 +1,14 @@
-error: borrowed data cannot be stored outside of its closure
- --> $DIR/issue-7573.rs:21:27
+error[E0521]: borrowed data escapes outside of closure
+ --> $DIR/issue-7573.rs:17:9
|
LL | let mut lines_to_use: Vec<&CrateId> = Vec::new();
- | - cannot infer an appropriate lifetime...
+ | ---------------- `lines_to_use` declared here, outside of the closure body
LL |
LL | let push_id = |installed_id: &CrateId| {
- | ------- ------------------------ borrowed data cannot outlive this closure
- | |
- | ...so that variable is valid at time of its declaration
-...
+ | ------------ `installed_id` is a reference that is only valid in the closure body
+LL |
LL | lines_to_use.push(installed_id);
- | ^^^^^^^^^^^^ cannot be stored outside of its closure
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `installed_id` escapes the closure body here
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn-2.rs b/src/test/ui/borrowck/regions-escape-bound-fn-2.rs
index cb42303..0e98d98 100644
--- a/src/test/ui/borrowck/regions-escape-bound-fn-2.rs
+++ b/src/test/ui/borrowck/regions-escape-bound-fn-2.rs
@@ -1,4 +1,7 @@
-fn with_int<F>(f: F) where F: FnOnce(&isize) {
+fn with_int<F>(f: F)
+where
+ F: FnOnce(&isize),
+{
let x = 3;
f(&x);
}
@@ -6,5 +9,5 @@
fn main() {
let mut x = None;
with_int(|y| x = Some(y));
- //~^ ERROR borrowed data cannot be stored outside of its closure
+ //~^ ERROR borrowed data escapes outside of closure
}
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn-2.stderr b/src/test/ui/borrowck/regions-escape-bound-fn-2.stderr
index 4b37eda..1dc60bb 100644
--- a/src/test/ui/borrowck/regions-escape-bound-fn-2.stderr
+++ b/src/test/ui/borrowck/regions-escape-bound-fn-2.stderr
@@ -1,12 +1,12 @@
-error: borrowed data cannot be stored outside of its closure
- --> $DIR/regions-escape-bound-fn-2.rs:8:27
+error[E0521]: borrowed data escapes outside of closure
+ --> $DIR/regions-escape-bound-fn-2.rs:11:18
|
LL | let mut x = None;
- | ----- borrowed data cannot be stored into here...
+ | ----- `x` declared here, outside of the closure body
LL | with_int(|y| x = Some(y));
- | --- ^ cannot be stored outside of its closure
- | |
- | ...because it cannot outlive this closure
+ | - ^^^^^^^^^^^ `y` escapes the closure body here
+ | |
+ | `y` is a reference that is only valid in the closure body
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr b/src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr
deleted file mode 100644
index d304de9..0000000
--- a/src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0521]: borrowed data escapes outside of closure
- --> $DIR/regions-escape-bound-fn.rs:8:18
- |
-LL | let mut x: Option<&isize> = None;
- | ----- `x` declared here, outside of the closure body
-LL | with_int(|y| x = Some(y));
- | - ^^^^^^^^^^^ `y` escapes the closure body here
- | |
- | `y` is a reference that is only valid in the closure body
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn.rs b/src/test/ui/borrowck/regions-escape-bound-fn.rs
index 772df3e..f896ae7 100644
--- a/src/test/ui/borrowck/regions-escape-bound-fn.rs
+++ b/src/test/ui/borrowck/regions-escape-bound-fn.rs
@@ -1,4 +1,7 @@
-fn with_int<F>(f: F) where F: FnOnce(&isize) {
+fn with_int<F>(f: F)
+where
+ F: FnOnce(&isize),
+{
let x = 3;
f(&x);
}
@@ -6,5 +9,5 @@
fn main() {
let mut x: Option<&isize> = None;
with_int(|y| x = Some(y));
- //~^ ERROR borrowed data cannot be stored outside of its closure
+ //~^ ERROR borrowed data escapes outside of closure
}
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn.stderr b/src/test/ui/borrowck/regions-escape-bound-fn.stderr
index 4973d53..5c548ec 100644
--- a/src/test/ui/borrowck/regions-escape-bound-fn.stderr
+++ b/src/test/ui/borrowck/regions-escape-bound-fn.stderr
@@ -1,12 +1,12 @@
-error: borrowed data cannot be stored outside of its closure
- --> $DIR/regions-escape-bound-fn.rs:8:27
+error[E0521]: borrowed data escapes outside of closure
+ --> $DIR/regions-escape-bound-fn.rs:11:18
|
LL | let mut x: Option<&isize> = None;
- | ----- borrowed data cannot be stored into here...
+ | ----- `x` declared here, outside of the closure body
LL | with_int(|y| x = Some(y));
- | --- ^ cannot be stored outside of its closure
- | |
- | ...because it cannot outlive this closure
+ | - ^^^^^^^^^^^ `y` escapes the closure body here
+ | |
+ | `y` is a reference that is only valid in the closure body
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr b/src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr
deleted file mode 100644
index d993130..0000000
--- a/src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0521]: borrowed data escapes outside of closure
- --> $DIR/regions-escape-unboxed-closure.rs:6:23
- |
-LL | let mut x: Option<&isize> = None;
- | ----- `x` declared here, outside of the closure body
-LL | with_int(&mut |y| x = Some(y));
- | - ^^^^^^^^^^^ `y` escapes the closure body here
- | |
- | `y` is a reference that is only valid in the closure body
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/borrowck/regions-escape-unboxed-closure.rs b/src/test/ui/borrowck/regions-escape-unboxed-closure.rs
index d8bef92..f01e471 100644
--- a/src/test/ui/borrowck/regions-escape-unboxed-closure.rs
+++ b/src/test/ui/borrowck/regions-escape-unboxed-closure.rs
@@ -1,8 +1,7 @@
-fn with_int(f: &mut dyn FnMut(&isize)) {
-}
+fn with_int(f: &mut dyn FnMut(&isize)) {}
fn main() {
let mut x: Option<&isize> = None;
with_int(&mut |y| x = Some(y));
- //~^ ERROR borrowed data cannot be stored outside of its closure
+ //~^ ERROR borrowed data escapes outside of closure
}
diff --git a/src/test/ui/borrowck/regions-escape-unboxed-closure.stderr b/src/test/ui/borrowck/regions-escape-unboxed-closure.stderr
index 047e290..f2a49e7 100644
--- a/src/test/ui/borrowck/regions-escape-unboxed-closure.stderr
+++ b/src/test/ui/borrowck/regions-escape-unboxed-closure.stderr
@@ -1,12 +1,12 @@
-error: borrowed data cannot be stored outside of its closure
- --> $DIR/regions-escape-unboxed-closure.rs:6:32
+error[E0521]: borrowed data escapes outside of closure
+ --> $DIR/regions-escape-unboxed-closure.rs:5:23
|
LL | let mut x: Option<&isize> = None;
- | ----- borrowed data cannot be stored into here...
+ | ----- `x` declared here, outside of the closure body
LL | with_int(&mut |y| x = Some(y));
- | --- ^ cannot be stored outside of its closure
- | |
- | ...because it cannot outlive this closure
+ | - ^^^^^^^^^^^ `y` escapes the closure body here
+ | |
+ | `y` is a reference that is only valid in the closure body
error: aborting due to previous error
diff --git a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr
deleted file mode 100644
index 89107e7..0000000
--- a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr
+++ /dev/null
@@ -1,123 +0,0 @@
-error: lifetime may not live long enough
- --> $DIR/variadic-ffi-4.rs:8:5
- |
-LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> {
- | -- -- has type `core::ffi::VaListImpl<'1>`
- | |
- | lifetime `'f` defined here
-LL | ap
- | ^^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'f`
-
-error: lifetime may not live long enough
- --> $DIR/variadic-ffi-4.rs:8:5
- |
-LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> {
- | -- -- has type `core::ffi::VaListImpl<'1>`
- | |
- | lifetime `'f` defined here
-LL | ap
- | ^^ returning this value requires that `'1` must outlive `'f`
-
-error: lifetime may not live long enough
- --> $DIR/variadic-ffi-4.rs:12:5
- |
-LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> {
- | -- has type `core::ffi::VaListImpl<'1>`
-LL | ap
- | ^^ returning this value requires that `'1` must outlive `'static`
-
-error: lifetime may not live long enough
- --> $DIR/variadic-ffi-4.rs:16:33
- |
-LL | let _ = ap.with_copy(|ap| { ap });
- | --- ^^ returning this value requires that `'1` must outlive `'2`
- | | |
- | | return type of closure is core::ffi::VaList<'2, '_>
- | has type `core::ffi::VaList<'1, '_>`
-
-error: lifetime may not live long enough
- --> $DIR/variadic-ffi-4.rs:20:5
- |
-LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
- | ------- ------- has type `core::ffi::VaListImpl<'2>`
- | |
- | has type `&mut core::ffi::VaListImpl<'1>`
-LL | *ap0 = ap1;
- | ^^^^ assignment requires that `'1` must outlive `'2`
-
-error: lifetime may not live long enough
- --> $DIR/variadic-ffi-4.rs:20:5
- |
-LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
- | ------- ------- has type `core::ffi::VaListImpl<'2>`
- | |
- | has type `&mut core::ffi::VaListImpl<'1>`
-LL | *ap0 = ap1;
- | ^^^^ assignment requires that `'2` must outlive `'1`
-
-error: lifetime may not live long enough
- --> $DIR/variadic-ffi-4.rs:24:5
- |
-LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
- | --- ------- has type `core::ffi::VaListImpl<'2>`
- | |
- | has type `&mut core::ffi::VaListImpl<'1>`
-LL | ap0 = &mut ap1;
- | ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
-
-error: lifetime may not live long enough
- --> $DIR/variadic-ffi-4.rs:24:5
- |
-LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
- | --- ------- has type `core::ffi::VaListImpl<'2>`
- | |
- | has type `&mut core::ffi::VaListImpl<'1>`
-LL | ap0 = &mut ap1;
- | ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1`
-
-error[E0384]: cannot assign to immutable argument `ap0`
- --> $DIR/variadic-ffi-4.rs:24:5
- |
-LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
- | --- help: make this binding mutable: `mut ap0`
-LL | ap0 = &mut ap1;
- | ^^^^^^^^^^^^^^ cannot assign to immutable argument
-
-error[E0597]: `ap1` does not live long enough
- --> $DIR/variadic-ffi-4.rs:24:11
- |
-LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
- | - let's call the lifetime of this reference `'3`
-LL | ap0 = &mut ap1;
- | ------^^^^^^^^
- | | |
- | | borrowed value does not live long enough
- | assignment requires that `ap1` is borrowed for `'3`
-...
-LL | }
- | - `ap1` dropped here while still borrowed
-
-error: lifetime may not live long enough
- --> $DIR/variadic-ffi-4.rs:31:12
- |
-LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
- | ------- ------- has type `core::ffi::VaListImpl<'2>`
- | |
- | has type `&mut core::ffi::VaListImpl<'1>`
-LL | *ap0 = ap1.clone();
- | ^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
-
-error: lifetime may not live long enough
- --> $DIR/variadic-ffi-4.rs:31:12
- |
-LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
- | ------- ------- has type `core::ffi::VaListImpl<'2>`
- | |
- | has type `&mut core::ffi::VaListImpl<'1>`
-LL | *ap0 = ap1.clone();
- | ^^^^^^^^^^^ argument requires that `'2` must outlive `'1`
-
-error: aborting due to 12 previous errors
-
-Some errors have detailed explanations: E0384, E0597.
-For more information about an error, try `rustc --explain E0384`.
diff --git a/src/test/ui/c-variadic/variadic-ffi-4.rs b/src/test/ui/c-variadic/variadic-ffi-4.rs
index a4d658c..8064037 100644
--- a/src/test/ui/c-variadic/variadic-ffi-4.rs
+++ b/src/test/ui/c-variadic/variadic-ffi-4.rs
@@ -1,32 +1,38 @@
-#![crate_type="lib"]
+#![crate_type = "lib"]
#![no_std]
#![feature(c_variadic)]
use core::ffi::{VaList, VaListImpl};
pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> {
- ap //~ ERROR: mismatched types
+ ap
+ //~^ ERROR: lifetime may not live long enough
+ //~| ERROR: lifetime may not live long enough
}
pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> {
- ap //~ ERROR: mismatched types
+ ap //~ ERROR: lifetime may not live long enough
}
pub unsafe extern "C" fn no_escape2(_: usize, ap: ...) {
- let _ = ap.with_copy(|ap| { ap }); //~ ERROR: cannot infer an appropriate lifetime
+ let _ = ap.with_copy(|ap| ap); //~ ERROR: lifetime may not live long enough
}
pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
- *ap0 = ap1; //~ ERROR: mismatched types
+ *ap0 = ap1;
+ //~^ ERROR: lifetime may not live long enough
+ //~| ERROR: lifetime may not live long enough
}
-pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
+pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
ap0 = &mut ap1;
- //~^ ERROR: a value of type `core::ffi::VaListImpl<'_>` is borrowed for too long
- //~| ERROR: mismatched types
- //~| ERROR: cannot infer an appropriate lifetime
+ //~^ ERROR: `ap1` does not live long enough
+ //~| ERROR: lifetime may not live long enough
+ //~| ERROR: lifetime may not live long enough
}
pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
- *ap0 = ap1.clone(); //~ ERROR: mismatched types
+ *ap0 = ap1.clone();
+ //~^ ERROR: lifetime may not live long enough
+ //~| ERROR: lifetime may not live long enough
}
diff --git a/src/test/ui/c-variadic/variadic-ffi-4.stderr b/src/test/ui/c-variadic/variadic-ffi-4.stderr
index cd4cd8b..6562350 100644
--- a/src/test/ui/c-variadic/variadic-ffi-4.stderr
+++ b/src/test/ui/c-variadic/variadic-ffi-4.stderr
@@ -1,217 +1,114 @@
-error[E0308]: mismatched types
+error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:8:5
|
+LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> {
+ | -- -- has type `core::ffi::VaListImpl<'1>`
+ | |
+ | lifetime `'f` defined here
LL | ap
- | ^^ lifetime mismatch
- |
- = note: expected struct `core::ffi::VaListImpl<'f>`
- found struct `core::ffi::VaListImpl<'_>`
-note: the scope of call-site for function at 7:78...
- --> $DIR/variadic-ffi-4.rs:7:78
- |
-LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> {
- | ______________________________________________________________________________^
-LL | | ap
-LL | | }
- | |_^
-note: ...does not necessarily outlive the lifetime `'f` as defined on the function body at 7:37
- --> $DIR/variadic-ffi-4.rs:7:37
+ | ^^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'f`
+
+error: lifetime may not live long enough
+ --> $DIR/variadic-ffi-4.rs:8:5
|
LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> {
- | ^^
-
-error[E0308]: mismatched types
- --> $DIR/variadic-ffi-4.rs:12:5
- |
+ | -- -- has type `core::ffi::VaListImpl<'1>`
+ | |
+ | lifetime `'f` defined here
LL | ap
- | ^^ lifetime mismatch
- |
- = note: expected struct `core::ffi::VaListImpl<'static>`
- found struct `core::ffi::VaListImpl<'_>`
-note: the scope of call-site for function at 11:79...
- --> $DIR/variadic-ffi-4.rs:11:79
- |
-LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> {
- | _______________________________________________________________________________^
-LL | | ap
-LL | | }
- | |_^
- = note: ...does not necessarily outlive the static lifetime
+ | ^^ returning this value requires that `'1` must outlive `'f`
-error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
- --> $DIR/variadic-ffi-4.rs:16:33
+error: lifetime may not live long enough
+ --> $DIR/variadic-ffi-4.rs:14:5
|
-LL | let _ = ap.with_copy(|ap| { ap });
- | ^^
- |
-note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 16:26...
- --> $DIR/variadic-ffi-4.rs:16:26
- |
-LL | let _ = ap.with_copy(|ap| { ap });
- | ^^^^^^^^^^^
-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
- |
-LL | let _ = ap.with_copy(|ap| { ap });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...so type `core::ffi::VaList<'_, '_>` of expression is valid during the expression
- --> $DIR/variadic-ffi-4.rs:16:13
- |
-LL | let _ = ap.with_copy(|ap| { ap });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> {
+ | -- has type `core::ffi::VaListImpl<'1>`
+LL | ap
+ | ^^ returning this value requires that `'1` must outlive `'static`
-error[E0308]: mismatched types
- --> $DIR/variadic-ffi-4.rs:20:12
+error: lifetime may not live long enough
+ --> $DIR/variadic-ffi-4.rs:18:31
|
+LL | let _ = ap.with_copy(|ap| ap);
+ | --- ^^ returning this value requires that `'1` must outlive `'2`
+ | | |
+ | | return type of closure is core::ffi::VaList<'2, '_>
+ | has type `core::ffi::VaList<'1, '_>`
+
+error: lifetime may not live long enough
+ --> $DIR/variadic-ffi-4.rs:22:5
+ |
+LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
+ | ------- ------- has type `core::ffi::VaListImpl<'2>`
+ | |
+ | has type `&mut core::ffi::VaListImpl<'1>`
LL | *ap0 = ap1;
- | ^^^ lifetime mismatch
- |
- = note: expected struct `core::ffi::VaListImpl<'_>`
- found struct `core::ffi::VaListImpl<'_>`
-note: the scope of call-site for function at 19:87...
- --> $DIR/variadic-ffi-4.rs:19:87
- |
-LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
- | _______________________________________________________________________________________^
-LL | | *ap0 = ap1;
-LL | | }
- | |_^
-note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 19:1
- --> $DIR/variadic-ffi-4.rs:19:1
- |
-LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
-LL | | *ap0 = ap1;
-LL | | }
- | |_^
+ | ^^^^ assignment requires that `'1` must outlive `'2`
-error[E0490]: a value of type `core::ffi::VaListImpl<'_>` is borrowed for too long
- --> $DIR/variadic-ffi-4.rs:24:11
+error: lifetime may not live long enough
+ --> $DIR/variadic-ffi-4.rs:22:5
|
-LL | ap0 = &mut ap1;
- | ^^^^^^^^
- |
-note: the type is valid for the anonymous lifetime #1 defined on the function body at 23:1
- --> $DIR/variadic-ffi-4.rs:23:1
- |
-LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
-LL | | ap0 = &mut ap1;
-LL | |
-LL | |
-LL | |
-LL | | }
- | |_^
-note: but the borrow lasts for the scope of call-site for function at 23:83
- --> $DIR/variadic-ffi-4.rs:23:83
- |
-LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
- | ___________________________________________________________________________________^
-LL | | ap0 = &mut ap1;
-LL | |
-LL | |
-LL | |
-LL | | }
- | |_^
+LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
+ | ------- ------- has type `core::ffi::VaListImpl<'2>`
+ | |
+ | has type `&mut core::ffi::VaListImpl<'1>`
+LL | *ap0 = ap1;
+ | ^^^^ assignment requires that `'2` must outlive `'1`
-error[E0308]: mismatched types
- --> $DIR/variadic-ffi-4.rs:24:11
+error: lifetime may not live long enough
+ --> $DIR/variadic-ffi-4.rs:28:5
|
+LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
+ | ------- ------- has type `core::ffi::VaListImpl<'2>`
+ | |
+ | has type `&mut core::ffi::VaListImpl<'1>`
LL | ap0 = &mut ap1;
- | ^^^^^^^^ lifetime mismatch
- |
- = note: expected mutable reference `&mut core::ffi::VaListImpl<'_>`
- found mutable reference `&mut core::ffi::VaListImpl<'_>`
-note: the scope of call-site for function at 23:83...
- --> $DIR/variadic-ffi-4.rs:23:83
- |
-LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
- | ___________________________________________________________________________________^
-LL | | ap0 = &mut ap1;
-LL | |
-LL | |
-LL | |
-LL | | }
- | |_^
-note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 23:1
- --> $DIR/variadic-ffi-4.rs:23:1
- |
-LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
-LL | | ap0 = &mut ap1;
-LL | |
-LL | |
-LL | |
-LL | | }
- | |_^
+ | ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
-error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
- --> $DIR/variadic-ffi-4.rs:24:11
+error: lifetime may not live long enough
+ --> $DIR/variadic-ffi-4.rs:28:5
|
+LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
+ | ------- ------- has type `core::ffi::VaListImpl<'2>`
+ | |
+ | has type `&mut core::ffi::VaListImpl<'1>`
LL | ap0 = &mut ap1;
- | ^^^^^^^^
- |
-note: first, the lifetime cannot outlive the scope of call-site for function at 23:83...
- --> $DIR/variadic-ffi-4.rs:23:83
- |
-LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
- | ___________________________________________________________________________________^
-LL | | ap0 = &mut ap1;
-LL | |
-LL | |
-LL | |
-LL | | }
- | |_^
-note: ...so that the type `core::ffi::VaListImpl<'_>` is not borrowed for too long
- --> $DIR/variadic-ffi-4.rs:24:11
- |
-LL | ap0 = &mut ap1;
- | ^^^^^^^^
-note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the function body at 23:1...
- --> $DIR/variadic-ffi-4.rs:23:1
- |
-LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
-LL | | ap0 = &mut ap1;
-LL | |
-LL | |
-LL | |
-LL | | }
- | |_^
-note: ...so that reference does not outlive borrowed content
- --> $DIR/variadic-ffi-4.rs:24:11
- |
-LL | ap0 = &mut ap1;
- | ^^^^^^^^
+ | ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1`
-error[E0308]: mismatched types
- --> $DIR/variadic-ffi-4.rs:31:12
+error[E0597]: `ap1` does not live long enough
+ --> $DIR/variadic-ffi-4.rs:28:11
|
+LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
+ | - let's call the lifetime of this reference `'3`
+LL | ap0 = &mut ap1;
+ | ------^^^^^^^^
+ | | |
+ | | borrowed value does not live long enough
+ | assignment requires that `ap1` is borrowed for `'3`
+...
+LL | }
+ | - `ap1` dropped here while still borrowed
+
+error: lifetime may not live long enough
+ --> $DIR/variadic-ffi-4.rs:35:12
+ |
+LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
+ | ------- ------- has type `core::ffi::VaListImpl<'2>`
+ | |
+ | has type `&mut core::ffi::VaListImpl<'1>`
LL | *ap0 = ap1.clone();
- | ^^^^^^^^^^^ lifetime mismatch
- |
- = note: expected struct `core::ffi::VaListImpl<'_>`
- found struct `core::ffi::VaListImpl<'_>`
-note: the scope of call-site for function at 30:87...
- --> $DIR/variadic-ffi-4.rs:30:87
- |
-LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
- | _______________________________________________________________________________________^
-LL | | *ap0 = ap1.clone();
-LL | | }
- | |_^
-note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 30:1
- --> $DIR/variadic-ffi-4.rs:30:1
- |
-LL | / pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
-LL | | *ap0 = ap1.clone();
-LL | | }
- | |_^
+ | ^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
-error: aborting due to 8 previous errors
+error: lifetime may not live long enough
+ --> $DIR/variadic-ffi-4.rs:35:12
+ |
+LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
+ | ------- ------- has type `core::ffi::VaListImpl<'2>`
+ | |
+ | has type `&mut core::ffi::VaListImpl<'1>`
+LL | *ap0 = ap1.clone();
+ | ^^^^^^^^^^^ argument requires that `'2` must outlive `'1`
-Some errors have detailed explanations: E0308, E0495.
-For more information about an error, try `rustc --explain E0308`.
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.nll.stderr b/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.nll.stderr
new file mode 100644
index 0000000..52bca8d
--- /dev/null
+++ b/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.nll.stderr
@@ -0,0 +1,24 @@
+error: lifetime may not live long enough
+ --> $DIR/expect-region-supply-region-2.rs:14:30
+ |
+LL | fn expect_bound_supply_named<'x>() {
+ | -- lifetime `'x` defined here
+...
+LL | closure_expecting_bound(|x: &'x u32| {
+ | ^ - let's call the lifetime of this reference `'1`
+ | |
+ | requires that `'1` must outlive `'x`
+
+error: lifetime may not live long enough
+ --> $DIR/expect-region-supply-region-2.rs:14:30
+ |
+LL | fn expect_bound_supply_named<'x>() {
+ | -- lifetime `'x` defined here
+...
+LL | closure_expecting_bound(|x: &'x u32| {
+ | ^ requires that `'x` must outlive `'static`
+ |
+ = help: consider replacing `'x` with `'static`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.rs b/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.rs
new file mode 100644
index 0000000..7405b1a
--- /dev/null
+++ b/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.rs
@@ -0,0 +1,24 @@
+#![allow(warnings)]
+
+fn closure_expecting_bound<F>(_: F)
+where
+ F: FnOnce(&u32),
+{
+}
+
+fn expect_bound_supply_named<'x>() {
+ let mut f: Option<&u32> = None;
+
+ // Here we give a type annotation that `x` should be free. We get
+ // an error because of that.
+ closure_expecting_bound(|x: &'x u32| {
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+
+ // Borrowck doesn't get a chance to run, but if it did it should error
+ // here.
+ f = Some(x);
+ });
+}
+
+fn main() {}
diff --git a/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.stderr b/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.stderr
new file mode 100644
index 0000000..7f52790
--- /dev/null
+++ b/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.stderr
@@ -0,0 +1,55 @@
+error[E0308]: mismatched types
+ --> $DIR/expect-region-supply-region-2.rs:14:33
+ |
+LL | closure_expecting_bound(|x: &'x u32| {
+ | ^^^^^^^ lifetime mismatch
+ |
+ = note: expected reference `&u32`
+ found reference `&'x u32`
+note: the anonymous lifetime #2 defined on the body at 14:29...
+ --> $DIR/expect-region-supply-region-2.rs:14:29
+ |
+LL | closure_expecting_bound(|x: &'x u32| {
+ | _____________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | f = Some(x);
+LL | | });
+ | |_____^
+note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 9:30
+ --> $DIR/expect-region-supply-region-2.rs:9:30
+ |
+LL | fn expect_bound_supply_named<'x>() {
+ | ^^
+
+error[E0308]: mismatched types
+ --> $DIR/expect-region-supply-region-2.rs:14:33
+ |
+LL | closure_expecting_bound(|x: &'x u32| {
+ | ^^^^^^^ lifetime mismatch
+ |
+ = note: expected reference `&u32`
+ found reference `&'x u32`
+note: the lifetime `'x` as defined on the function body at 9:30...
+ --> $DIR/expect-region-supply-region-2.rs:9:30
+ |
+LL | fn expect_bound_supply_named<'x>() {
+ | ^^
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 14:29
+ --> $DIR/expect-region-supply-region-2.rs:14:29
+ |
+LL | closure_expecting_bound(|x: &'x u32| {
+ | _____________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | f = Some(x);
+LL | | });
+ | |_____^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/closures/closure-expected-type/expect-region-supply-region.nll.stderr b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.nll.stderr
deleted file mode 100644
index d7d716e..0000000
--- a/src/test/ui/closures/closure-expected-type/expect-region-supply-region.nll.stderr
+++ /dev/null
@@ -1,44 +0,0 @@
-error[E0521]: borrowed data escapes outside of closure
- --> $DIR/expect-region-supply-region.rs:18:9
- |
-LL | let mut f: Option<&u32> = None;
- | ----- `f` declared here, outside of the closure body
-LL | closure_expecting_bound(|x| {
- | - `x` is a reference that is only valid in the closure body
-LL | f = Some(x);
- | ^^^^^^^^^^^ `x` escapes the closure body here
-
-error[E0521]: borrowed data escapes outside of closure
- --> $DIR/expect-region-supply-region.rs:28:9
- |
-LL | let mut f: Option<&u32> = None;
- | ----- `f` declared here, outside of the closure body
-LL | closure_expecting_bound(|x: &u32| {
- | - `x` is a reference that is only valid in the closure body
-LL | f = Some(x);
- | ^^^^^^^^^^^ `x` escapes the closure body here
-
-error: lifetime may not live long enough
- --> $DIR/expect-region-supply-region.rs:37:30
- |
-LL | fn expect_bound_supply_named<'x>() {
- | -- lifetime `'x` defined here
-...
-LL | closure_expecting_bound(|x: &'x u32| {
- | ^ - let's call the lifetime of this reference `'1`
- | |
- | requires that `'1` must outlive `'x`
-
-error: lifetime may not live long enough
- --> $DIR/expect-region-supply-region.rs:37:30
- |
-LL | fn expect_bound_supply_named<'x>() {
- | -- lifetime `'x` defined here
-...
-LL | closure_expecting_bound(|x: &'x u32| {
- | ^ requires that `'x` must outlive `'static`
- |
- = help: consider replacing `'x` with `'static`
-
-error: aborting due to 4 previous errors
-
diff --git a/src/test/ui/closures/closure-expected-type/expect-region-supply-region.rs b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.rs
index 28a6ab7..55c6aa7 100644
--- a/src/test/ui/closures/closure-expected-type/expect-region-supply-region.rs
+++ b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.rs
@@ -1,12 +1,14 @@
#![allow(warnings)]
fn closure_expecting_bound<F>(_: F)
- where F: FnOnce(&u32)
+where
+ F: FnOnce(&u32),
{
}
fn closure_expecting_free<'a, F>(_: F)
- where F: FnOnce(&'a u32)
+where
+ F: FnOnce(&'a u32),
{
}
@@ -15,7 +17,7 @@
// it to escape into `f`:
let mut f: Option<&u32> = None;
closure_expecting_bound(|x| {
- f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
+ f = Some(x); //~ ERROR borrowed data escapes outside of closure
});
}
@@ -25,22 +27,7 @@
// closure:
let mut f: Option<&u32> = None;
closure_expecting_bound(|x: &u32| {
- f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
- });
-}
-
-fn expect_bound_supply_named<'x>() {
- let mut f: Option<&u32> = None;
-
- // Here we give a type annotation that `x` should be free. We get
- // an error because of that.
- closure_expecting_bound(|x: &'x u32| {
- //~^ ERROR mismatched types
- //~| ERROR mismatched types
-
- // And we still cannot let `x` escape into `f`.
- f = Some(x);
- //~^ ERROR borrowed data cannot be stored outside of its closure
+ f = Some(x); //~ ERROR borrowed data escapes outside of closure
});
}
@@ -67,4 +54,4 @@
closure_expecting_free(|x: &'x u32| f = Some(x)); // OK
}
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/closures/closure-expected-type/expect-region-supply-region.stderr b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.stderr
index eb860f9..213071a 100644
--- a/src/test/ui/closures/closure-expected-type/expect-region-supply-region.stderr
+++ b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.stderr
@@ -1,87 +1,22 @@
-error: borrowed data cannot be stored outside of its closure
- --> $DIR/expect-region-supply-region.rs:18:18
+error[E0521]: borrowed data escapes outside of closure
+ --> $DIR/expect-region-supply-region.rs:20:9
|
LL | let mut f: Option<&u32> = None;
- | ----- borrowed data cannot be stored into here...
+ | ----- `f` declared here, outside of the closure body
LL | closure_expecting_bound(|x| {
- | --- ...because it cannot outlive this closure
+ | - `x` is a reference that is only valid in the closure body
LL | f = Some(x);
- | ^ cannot be stored outside of its closure
+ | ^^^^^^^^^^^ `x` escapes the closure body here
-error: borrowed data cannot be stored outside of its closure
- --> $DIR/expect-region-supply-region.rs:28:18
+error[E0521]: borrowed data escapes outside of closure
+ --> $DIR/expect-region-supply-region.rs:30:9
|
LL | let mut f: Option<&u32> = None;
- | ----- borrowed data cannot be stored into here...
+ | ----- `f` declared here, outside of the closure body
LL | closure_expecting_bound(|x: &u32| {
- | --------- ...because it cannot outlive this closure
+ | - `x` is a reference that is only valid in the closure body
LL | f = Some(x);
- | ^ cannot be stored outside of its closure
+ | ^^^^^^^^^^^ `x` escapes the closure body here
-error[E0308]: mismatched types
- --> $DIR/expect-region-supply-region.rs:37:33
- |
-LL | closure_expecting_bound(|x: &'x u32| {
- | ^^^^^^^ lifetime mismatch
- |
- = note: expected reference `&u32`
- found reference `&'x u32`
-note: the anonymous lifetime #2 defined on the body at 37:29...
- --> $DIR/expect-region-supply-region.rs:37:29
- |
-LL | closure_expecting_bound(|x: &'x u32| {
- | _____________________________^
-LL | |
-LL | |
-LL | |
-... |
-LL | |
-LL | | });
- | |_____^
-note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 32:30
- --> $DIR/expect-region-supply-region.rs:32:30
- |
-LL | fn expect_bound_supply_named<'x>() {
- | ^^
+error: aborting due to 2 previous errors
-error[E0308]: mismatched types
- --> $DIR/expect-region-supply-region.rs:37:33
- |
-LL | closure_expecting_bound(|x: &'x u32| {
- | ^^^^^^^ lifetime mismatch
- |
- = note: expected reference `&u32`
- found reference `&'x u32`
-note: the lifetime `'x` as defined on the function body at 32:30...
- --> $DIR/expect-region-supply-region.rs:32:30
- |
-LL | fn expect_bound_supply_named<'x>() {
- | ^^
-note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 37:29
- --> $DIR/expect-region-supply-region.rs:37:29
- |
-LL | closure_expecting_bound(|x: &'x u32| {
- | _____________________________^
-LL | |
-LL | |
-LL | |
-... |
-LL | |
-LL | | });
- | |_____^
-
-error: borrowed data cannot be stored outside of its closure
- --> $DIR/expect-region-supply-region.rs:42:18
- |
-LL | let mut f: Option<&u32> = None;
- | ----- borrowed data cannot be stored into here...
-...
-LL | closure_expecting_bound(|x: &'x u32| {
- | ------------ ...because it cannot outlive this closure
-...
-LL | f = Some(x);
- | ^ cannot be stored outside of its closure
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/command/command-argv0-debug.rs b/src/test/ui/command/command-argv0-debug.rs
index 133d2ad..cb948a9 100644
--- a/src/test/ui/command/command-argv0-debug.rs
+++ b/src/test/ui/command/command-argv0-debug.rs
@@ -4,8 +4,6 @@
// ignore-cloudabi no processes
// ignore-emscripten no processes
// ignore-sgx no processes
-#![feature(process_set_argv0)]
-
use std::os::unix::process::CommandExt;
use std::process::Command;
diff --git a/src/test/ui/command/command-argv0.rs b/src/test/ui/command/command-argv0.rs
index 56a9fb4..e3394e0 100644
--- a/src/test/ui/command/command-argv0.rs
+++ b/src/test/ui/command/command-argv0.rs
@@ -4,8 +4,6 @@
// ignore-cloudabi no processes
// ignore-emscripten no processes
// ignore-sgx no processes
-#![feature(process_set_argv0)]
-
use std::env;
use std::os::unix::process::CommandExt;
use std::process::Command;
diff --git a/src/test/ui/error-codes/E0490.nll.stderr b/src/test/ui/error-codes/E0490.nll.stderr
new file mode 100644
index 0000000..a1c33bb
--- /dev/null
+++ b/src/test/ui/error-codes/E0490.nll.stderr
@@ -0,0 +1,28 @@
+error: lifetime may not live long enough
+ --> $DIR/E0490.rs:2:12
+ |
+LL | fn f<'a, 'b>(y: &'b ()) {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | let x: &'a _ = &y;
+ | ^^^^^ type annotation requires that `'b` must outlive `'a`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+
+error[E0597]: `y` does not live long enough
+ --> $DIR/E0490.rs:2:20
+ |
+LL | fn f<'a, 'b>(y: &'b ()) {
+ | -- lifetime `'a` defined here
+LL | let x: &'a _ = &y;
+ | ----- ^^ borrowed value does not live long enough
+ | |
+ | type annotation requires that `y` is borrowed for `'a`
+...
+LL | }
+ | - `y` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/error-codes/E0490.rs b/src/test/ui/error-codes/E0490.rs
new file mode 100644
index 0000000..36bafa2
--- /dev/null
+++ b/src/test/ui/error-codes/E0490.rs
@@ -0,0 +1,8 @@
+fn f<'a, 'b>(y: &'b ()) {
+ let x: &'a _ = &y;
+ //~^ E0490
+ //~| E0495
+ //~| E0495
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0490.stderr b/src/test/ui/error-codes/E0490.stderr
new file mode 100644
index 0000000..03fce21
--- /dev/null
+++ b/src/test/ui/error-codes/E0490.stderr
@@ -0,0 +1,76 @@
+error[E0490]: a value of type `&'b ()` is borrowed for too long
+ --> $DIR/E0490.rs:2:20
+ |
+LL | let x: &'a _ = &y;
+ | ^^
+ |
+note: the type is valid for the lifetime `'a` as defined on the function body at 1:6
+ --> $DIR/E0490.rs:1:6
+ |
+LL | fn f<'a, 'b>(y: &'b ()) {
+ | ^^
+note: but the borrow lasts for the lifetime `'b` as defined on the function body at 1:10
+ --> $DIR/E0490.rs:1:10
+ |
+LL | fn f<'a, 'b>(y: &'b ()) {
+ | ^^
+
+error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+ --> $DIR/E0490.rs:2:20
+ |
+LL | let x: &'a _ = &y;
+ | ^^
+ |
+note: first, the lifetime cannot outlive the lifetime `'b` as defined on the function body at 1:10...
+ --> $DIR/E0490.rs:1:10
+ |
+LL | fn f<'a, 'b>(y: &'b ()) {
+ | ^^
+note: ...so that the type `&'b ()` is not borrowed for too long
+ --> $DIR/E0490.rs:2:20
+ |
+LL | let x: &'a _ = &y;
+ | ^^
+note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 1:6...
+ --> $DIR/E0490.rs:1:6
+ |
+LL | fn f<'a, 'b>(y: &'b ()) {
+ | ^^
+note: ...so that reference does not outlive borrowed content
+ --> $DIR/E0490.rs:2:20
+ |
+LL | let x: &'a _ = &y;
+ | ^^
+
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+ --> $DIR/E0490.rs:2:20
+ |
+LL | let x: &'a _ = &y;
+ | ^^
+ |
+note: first, the lifetime cannot outlive the lifetime `'b` as defined on the function body at 1:10...
+ --> $DIR/E0490.rs:1:10
+ |
+LL | fn f<'a, 'b>(y: &'b ()) {
+ | ^^
+note: ...so that the expression is assignable
+ --> $DIR/E0490.rs:2:20
+ |
+LL | let x: &'a _ = &y;
+ | ^^
+ = note: expected `&'a &()`
+ found `&'a &'b ()`
+note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 1:6...
+ --> $DIR/E0490.rs:1:6
+ |
+LL | fn f<'a, 'b>(y: &'b ()) {
+ | ^^
+note: ...so that the reference type `&'a &()` does not outlive the data it points at
+ --> $DIR/E0490.rs:2:12
+ |
+LL | let x: &'a _ = &y;
+ | ^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr
deleted file mode 100644
index 5140d1a..0000000
--- a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: lifetime may not live long enough
- --> $DIR/E0621-does-not-trigger-for-closures.rs:15:45
- |
-LL | invoke(&x, |a, b| if a > b { a } else { b });
- | -- ^ returning this value requires that `'1` must outlive `'2`
- | ||
- | |return type of closure is &'2 i32
- | has type `&'1 i32`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.rs b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.rs
index c58744d..44f174c 100644
--- a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.rs
+++ b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.rs
@@ -1,9 +1,7 @@
-// Test that we give the generic E0495 when one of the free regions is
+// Test that we give the generic error when one of the free regions is
// bound in a closure (rather than suggesting a change to the signature
// of the closure, which is not specified in `foo` but rather in `invoke`).
-// FIXME - This might be better as a UI test, but the finer details
-// of the error seem to vary on different machines.
fn invoke<'a, F>(x: &'a i32, f: F) -> &'a i32
where F: FnOnce(&'a i32, &i32) -> &'a i32
{
@@ -12,7 +10,7 @@
}
fn foo<'a>(x: &'a i32) {
- invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495
+ invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR lifetime may not live long enough
}
fn main() {}
diff --git a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr
index feca7f1..b9edeb8 100644
--- a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr
+++ b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr
@@ -1,30 +1,11 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
- --> $DIR/E0621-does-not-trigger-for-closures.rs:15:5
+error: lifetime may not live long enough
+ --> $DIR/E0621-does-not-trigger-for-closures.rs:13:45
|
LL | invoke(&x, |a, b| if a > b { a } else { b });
- | ^^^^^^
- |
-note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 15:16...
- --> $DIR/E0621-does-not-trigger-for-closures.rs:15:16
- |
-LL | invoke(&x, |a, b| if a > b { a } else { b });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...so that reference does not outlive borrowed content
- --> $DIR/E0621-does-not-trigger-for-closures.rs:15:45
- |
-LL | invoke(&x, |a, b| if a > b { a } else { b });
- | ^
-note: but, the lifetime must be valid for the call at 15:5...
- --> $DIR/E0621-does-not-trigger-for-closures.rs:15:5
- |
-LL | invoke(&x, |a, b| if a > b { a } else { b });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...so type `&i32` of expression is valid during the expression
- --> $DIR/E0621-does-not-trigger-for-closures.rs:15:5
- |
-LL | invoke(&x, |a, b| if a > b { a } else { b });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | -- ^ returning this value requires that `'1` must outlive `'2`
+ | ||
+ | |return type of closure is &'2 i32
+ | has type `&'1 i32`
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs
index 0faa909..9bce274 100644
--- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs
+++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs
@@ -1,3 +1,6 @@
+// compile-flags: -Zsave-analysis
+// This is also a regression test for #69415 and the above flag is needed.
+
#![feature(untagged_unions)]
trait Tr1 { type As1: Copy; }
diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr
index bfa59d8..7f2704e 100644
--- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr
+++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr
@@ -1,5 +1,5 @@
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:12:22
+ --> $DIR/feature-gate-associated_type_bounds.rs:15:22
|
LL | type A: Iterator<Item: Copy>;
| ^^^^^^^^^^
@@ -8,7 +8,7 @@
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:15:22
+ --> $DIR/feature-gate-associated_type_bounds.rs:18:22
|
LL | type B: Iterator<Item: 'static>;
| ^^^^^^^^^^^^^
@@ -17,7 +17,7 @@
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:19:20
+ --> $DIR/feature-gate-associated_type_bounds.rs:22:20
|
LL | struct _St1<T: Tr1<As1: Tr2>> {
| ^^^^^^^^
@@ -26,7 +26,7 @@
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:26:18
+ --> $DIR/feature-gate-associated_type_bounds.rs:29:18
|
LL | enum _En1<T: Tr1<As1: Tr2>> {
| ^^^^^^^^
@@ -35,7 +35,7 @@
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:33:19
+ --> $DIR/feature-gate-associated_type_bounds.rs:36:19
|
LL | union _Un1<T: Tr1<As1: Tr2>> {
| ^^^^^^^^
@@ -44,7 +44,7 @@
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:40:37
+ --> $DIR/feature-gate-associated_type_bounds.rs:43:37
|
LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
| ^^^^^^^^^^
@@ -53,7 +53,7 @@
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:43:22
+ --> $DIR/feature-gate-associated_type_bounds.rs:46:22
|
LL | fn _apit(_: impl Tr1<As1: Copy>) {}
| ^^^^^^^^^
@@ -62,7 +62,7 @@
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:45:26
+ --> $DIR/feature-gate-associated_type_bounds.rs:48:26
|
LL | fn _apit_dyn(_: &dyn Tr1<As1: Copy>) {}
| ^^^^^^^^^
@@ -71,7 +71,7 @@
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:48:24
+ --> $DIR/feature-gate-associated_type_bounds.rs:51:24
|
LL | fn _rpit() -> impl Tr1<As1: Copy> { S1 }
| ^^^^^^^^^
@@ -80,7 +80,7 @@
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:51:31
+ --> $DIR/feature-gate-associated_type_bounds.rs:54:31
|
LL | fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) }
| ^^^^^^^^^
@@ -89,7 +89,7 @@
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:54:23
+ --> $DIR/feature-gate-associated_type_bounds.rs:57:23
|
LL | const _cdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^
@@ -98,7 +98,7 @@
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:60:24
+ --> $DIR/feature-gate-associated_type_bounds.rs:63:24
|
LL | static _sdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^
@@ -107,7 +107,7 @@
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:67:21
+ --> $DIR/feature-gate-associated_type_bounds.rs:70:21
|
LL | let _: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^
@@ -116,7 +116,7 @@
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
- --> $DIR/feature-gate-associated_type_bounds.rs:54:14
+ --> $DIR/feature-gate-associated_type_bounds.rs:57:14
|
LL | const _cdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^^^^^^^^^^^
@@ -124,7 +124,7 @@
= help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
- --> $DIR/feature-gate-associated_type_bounds.rs:60:15
+ --> $DIR/feature-gate-associated_type_bounds.rs:63:15
|
LL | static _sdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^^^^^^^^^^^
@@ -132,7 +132,7 @@
= help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
- --> $DIR/feature-gate-associated_type_bounds.rs:67:12
+ --> $DIR/feature-gate-associated_type_bounds.rs:70:12
|
LL | let _: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/generator/size-moved-locals.rs b/src/test/ui/generator/size-moved-locals.rs
index 74c60d9..a5786c29 100644
--- a/src/test/ui/generator/size-moved-locals.rs
+++ b/src/test/ui/generator/size-moved-locals.rs
@@ -72,6 +72,6 @@
fn main() {
assert_eq!(1025, std::mem::size_of_val(&move_before_yield()));
assert_eq!(1026, std::mem::size_of_val(&move_before_yield_with_noop()));
- assert_eq!(2051, std::mem::size_of_val(&overlap_move_points()));
+ assert_eq!(1027, std::mem::size_of_val(&overlap_move_points()));
assert_eq!(1026, std::mem::size_of_val(&overlap_x_and_y()));
}
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
index cd2d46a..b42ff14 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
@@ -4,17 +4,11 @@
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
| ^^^^^^^^^^^^^^^^^^
|
-note: hidden type `Ordinary<'_>` captures the scope of call-site for function at 23:1
- --> $DIR/ordinary-bounds-unrelated.rs:23:1
+note: hidden type `Ordinary<'_>` captures lifetime smaller than the function body
+ --> $DIR/ordinary-bounds-unrelated.rs:18:74
|
-LL | / {
-LL | | // Hidden type `Ordinary<'0>` with constraints:
-LL | | //
-LL | | // ```
-... |
-LL | | if condition() { a } else { b }
-LL | | }
- | |_^
+LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
+ | ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
index 59ce93f..254643c 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
@@ -4,17 +4,11 @@
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
| ^^^^^^^^^^^^^^^^^^
|
-note: hidden type `Ordinary<'_>` captures the scope of call-site for function at 22:1
- --> $DIR/ordinary-bounds-unsuited.rs:22:1
+note: hidden type `Ordinary<'_>` captures lifetime smaller than the function body
+ --> $DIR/ordinary-bounds-unsuited.rs:20:62
|
-LL | / {
-LL | | // We return a value:
-LL | | //
-LL | | // ```
-... |
-LL | | if condition() { a } else { b }
-LL | | }
- | |_^
+LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
+ | ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-72076.rs b/src/test/ui/issues/issue-72076.rs
new file mode 100644
index 0000000..1659044
--- /dev/null
+++ b/src/test/ui/issues/issue-72076.rs
@@ -0,0 +1,6 @@
+trait X {
+ type S;
+ fn f() -> Self::S {} //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-72076.stderr b/src/test/ui/issues/issue-72076.stderr
new file mode 100644
index 0000000..b942cf7
--- /dev/null
+++ b/src/test/ui/issues/issue-72076.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-72076.rs:3:23
+ |
+LL | fn f() -> Self::S {}
+ | ^^ expected associated type, found `()`
+ |
+ = note: expected associated type `<Self as X>::S`
+ found unit type `()`
+ = help: consider constraining the associated type `<Self as X>::S` to `()` or calling a method that returns `<Self as X>::S`
+ = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-72455.rs b/src/test/ui/issues/issue-72455.rs
new file mode 100644
index 0000000..b6c3bb2
--- /dev/null
+++ b/src/test/ui/issues/issue-72455.rs
@@ -0,0 +1,27 @@
+// check-pass
+
+pub trait ResultExt {
+ type Ok;
+ fn err_eprint_and_ignore(self) -> Option<Self::Ok>;
+}
+
+impl<O, E> ResultExt for std::result::Result<O, E>
+where
+ E: std::error::Error,
+{
+ type Ok = O;
+ fn err_eprint_and_ignore(self) -> Option<O>
+ where
+ Self: ,
+ {
+ match self {
+ Err(e) => {
+ eprintln!("{}", e);
+ None
+ }
+ Ok(o) => Some(o),
+ }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/pattern/usefulness/issue-71930-type-of-match-scrutinee.rs b/src/test/ui/pattern/usefulness/issue-71930-type-of-match-scrutinee.rs
new file mode 100644
index 0000000..e2ff9ac
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/issue-71930-type-of-match-scrutinee.rs
@@ -0,0 +1,22 @@
+// check-pass
+
+// In PR 71930, it was discovered that the code to retrieve the inferred type of a match scrutinee
+// was incorrect.
+
+fn f() -> ! {
+ panic!()
+}
+
+fn g() -> usize {
+ match f() { // Should infer type `bool`
+ false => 0,
+ true => 1,
+ }
+}
+
+fn h() -> usize {
+ match f() { // Should infer type `!`
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/break-token-spans.rs b/src/test/ui/proc-macro/break-token-spans.rs
new file mode 100644
index 0000000..59dc3b5
--- /dev/null
+++ b/src/test/ui/proc-macro/break-token-spans.rs
@@ -0,0 +1,16 @@
+// aux-build:test-macros.rs
+// Regression test for issues #68489 and #70987
+// Tests that we properly break tokens in `probably_equal_for_proc_macro`
+// See #72306
+//
+// Note that the weird spacing in this example is critical
+// for testing the issue.
+
+extern crate test_macros;
+
+#[test_macros::recollect_attr]
+fn repro() {
+ f :: < Vec < _ > > ( ) ; //~ ERROR cannot find
+ let a: Option<Option<u8>>= true; //~ ERROR mismatched
+}
+fn main() {}
diff --git a/src/test/ui/proc-macro/break-token-spans.stderr b/src/test/ui/proc-macro/break-token-spans.stderr
new file mode 100644
index 0000000..caca973
--- /dev/null
+++ b/src/test/ui/proc-macro/break-token-spans.stderr
@@ -0,0 +1,21 @@
+error[E0425]: cannot find function `f` in this scope
+ --> $DIR/break-token-spans.rs:13:5
+ |
+LL | f :: < Vec < _ > > ( ) ;
+ | ^ not found in this scope
+
+error[E0308]: mismatched types
+ --> $DIR/break-token-spans.rs:14:32
+ |
+LL | let a: Option<Option<u8>>= true;
+ | ------------------ ^^^^ expected enum `std::option::Option`, found `bool`
+ | |
+ | expected due to this
+ |
+ = note: expected enum `std::option::Option<std::option::Option<u8>>`
+ found type `bool`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0425.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-5.rs b/src/test/ui/regions/regions-close-object-into-object-5.rs
index 2921a2b..ff35b9a 100644
--- a/src/test/ui/regions/regions-close-object-into-object-5.rs
+++ b/src/test/ui/regions/regions-close-object-into-object-5.rs
@@ -6,22 +6,21 @@
fn get(&self) -> T { panic!() }
}
-struct B<'a, T:'a>(&'a (A<T>+'a));
+struct B<'a, T: 'a>(&'a (A<T> + 'a));
trait X { fn foo(&self) {} }
impl<'a, T> X for B<'a, T> {}
-fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
// oh dear!
box B(&*v) as Box<X>
- //~^ ERROR the parameter type `T` may not live long enough
- //~| ERROR the parameter type `T` may not live long enough
- //~| ERROR the parameter type `T` may not live long enough
- //~| ERROR the parameter type `T` may not live long enough
- //~| ERROR the parameter type `T` may not live long enough
- //~| ERROR the parameter type `T` may not live long enough
- //~| ERROR the parameter type `T` may not live long enough
+ //~^ ERROR the parameter type `T` may not live long enough
+ //~| ERROR the parameter type `T` may not live long enough
+ //~| ERROR the parameter type `T` may not live long enough
+ //~| ERROR the parameter type `T` may not live long enough
+ //~| ERROR the parameter type `T` may not live long enough
+ //~| ERROR the parameter type `T` may not live long enough
}
fn main() {}
diff --git a/src/test/ui/regions/regions-close-object-into-object-5.stderr b/src/test/ui/regions/regions-close-object-into-object-5.stderr
index 1472700..2bcdcd1 100644
--- a/src/test/ui/regions/regions-close-object-into-object-5.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-5.stderr
@@ -1,7 +1,7 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:5
|
-LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | box B(&*v) as Box<X>
@@ -14,24 +14,9 @@
| ^^^^^^^^^^
error[E0310]: the parameter type `T` may not live long enough
- --> $DIR/regions-close-object-into-object-5.rs:17:5
- |
-LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
- | - help: consider adding an explicit lifetime bound...: `T: 'static`
-LL | // oh dear!
-LL | box B(&*v) as Box<X>
- | ^^^^^^^^^^^^^^^^^^^^
- |
-note: ...so that it can be closed over into an object
- --> $DIR/regions-close-object-into-object-5.rs:17:5
- |
-LL | box B(&*v) as Box<X>
- | ^^^^^^^^^^^^^^^^^^^^
-
-error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:9
|
-LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | box B(&*v) as Box<X>
@@ -46,7 +31,7 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:9
|
-LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | box B(&*v) as Box<X>
@@ -61,7 +46,7 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:11
|
-LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | box B(&*v) as Box<X>
@@ -76,7 +61,7 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:11
|
-LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | box B(&*v) as Box<X>
@@ -91,7 +76,7 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:11
|
-LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | box B(&*v) as Box<X>
@@ -103,6 +88,6 @@
LL | box B(&*v) as Box<X>
| ^^^
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-1.nll.stderr b/src/test/ui/regions/regions-close-over-type-parameter-1.nll.stderr
index 7d3d51b..3101d81 100644
--- a/src/test/ui/regions/regions-close-over-type-parameter-1.nll.stderr
+++ b/src/test/ui/regions/regions-close-over-type-parameter-1.nll.stderr
@@ -1,5 +1,5 @@
error[E0310]: the parameter type `A` may not live long enough
- --> $DIR/regions-close-over-type-parameter-1.rs:10:5
+ --> $DIR/regions-close-over-type-parameter-1.rs:12:5
|
LL | box v as Box<dyn SomeTrait + 'static>
| ^^^^^
@@ -7,7 +7,7 @@
= help: consider adding an explicit lifetime bound `A: 'static`...
error[E0309]: the parameter type `A` may not live long enough
- --> $DIR/regions-close-over-type-parameter-1.rs:20:5
+ --> $DIR/regions-close-over-type-parameter-1.rs:21:5
|
LL | box v as Box<dyn SomeTrait + 'b>
| ^^^^^
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-1.rs b/src/test/ui/regions/regions-close-over-type-parameter-1.rs
index 6a9aa66..6e708a5 100644
--- a/src/test/ui/regions/regions-close-over-type-parameter-1.rs
+++ b/src/test/ui/regions/regions-close-over-type-parameter-1.rs
@@ -4,22 +4,22 @@
// an object. This should yield errors unless `A` (and the object)
// both have suitable bounds.
-trait SomeTrait { fn get(&self) -> isize; }
-
-fn make_object1<A:SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
- box v as Box<dyn SomeTrait + 'static>
- //~^ ERROR the parameter type `A` may not live long enough
- //~| ERROR the parameter type `A` may not live long enough
+trait SomeTrait {
+ fn get(&self) -> isize;
}
-fn make_object2<'a,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait + 'a> {
+fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
+ box v as Box<dyn SomeTrait + 'static>
+ //~^ ERROR the parameter type `A` may not live long enough
+}
+
+fn make_object2<'a, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'a> {
box v as Box<dyn SomeTrait + 'a>
}
-fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait + 'b> {
+fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> {
box v as Box<dyn SomeTrait + 'b>
- //~^ ERROR the parameter type `A` may not live long enough
- //~| ERROR the parameter type `A` may not live long enough
+ //~^ ERROR the parameter type `A` may not live long enough
}
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr
index ed9a604..a7509cb 100644
--- a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr
+++ b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr
@@ -1,60 +1,32 @@
error[E0310]: the parameter type `A` may not live long enough
- --> $DIR/regions-close-over-type-parameter-1.rs:10:5
+ --> $DIR/regions-close-over-type-parameter-1.rs:12:5
|
-LL | fn make_object1<A:SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
+LL | fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
| -- help: consider adding an explicit lifetime bound...: `A: 'static +`
LL | box v as Box<dyn SomeTrait + 'static>
| ^^^^^
|
note: ...so that the type `A` will meet its required lifetime bounds
- --> $DIR/regions-close-over-type-parameter-1.rs:10:5
+ --> $DIR/regions-close-over-type-parameter-1.rs:12:5
|
LL | box v as Box<dyn SomeTrait + 'static>
| ^^^^^
-error[E0310]: the parameter type `A` may not live long enough
- --> $DIR/regions-close-over-type-parameter-1.rs:10:5
- |
-LL | fn make_object1<A:SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
- | -- help: consider adding an explicit lifetime bound...: `A: 'static +`
-LL | box v as Box<dyn SomeTrait + 'static>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: ...so that it can be closed over into an object
- --> $DIR/regions-close-over-type-parameter-1.rs:10:5
- |
-LL | box v as Box<dyn SomeTrait + 'static>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
error[E0309]: the parameter type `A` may not live long enough
- --> $DIR/regions-close-over-type-parameter-1.rs:20:5
+ --> $DIR/regions-close-over-type-parameter-1.rs:21:5
|
-LL | fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait + 'b> {
- | -- help: consider adding an explicit lifetime bound...: `A: 'b +`
+LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> {
+ | -- help: consider adding an explicit lifetime bound...: `A: 'b +`
LL | box v as Box<dyn SomeTrait + 'b>
| ^^^^^
|
note: ...so that the type `A` will meet its required lifetime bounds
- --> $DIR/regions-close-over-type-parameter-1.rs:20:5
+ --> $DIR/regions-close-over-type-parameter-1.rs:21:5
|
LL | box v as Box<dyn SomeTrait + 'b>
| ^^^^^
-error[E0309]: the parameter type `A` may not live long enough
- --> $DIR/regions-close-over-type-parameter-1.rs:20:5
- |
-LL | fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait + 'b> {
- | -- help: consider adding an explicit lifetime bound...: `A: 'b +`
-LL | box v as Box<dyn SomeTrait + 'b>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: ...so that it can be closed over into an object
- --> $DIR/regions-close-over-type-parameter-1.rs:20:5
- |
-LL | box v as Box<dyn SomeTrait + 'b>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
Some errors have detailed explanations: E0309, E0310.
For more information about an error, try `rustc --explain E0309`.
diff --git a/src/test/ui/regions/regions-escape-method.nll.stderr b/src/test/ui/regions/regions-escape-method.nll.stderr
deleted file mode 100644
index 9f42512..0000000
--- a/src/test/ui/regions/regions-escape-method.nll.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: lifetime may not live long enough
- --> $DIR/regions-escape-method.rs:15:13
- |
-LL | s.f(|p| p)
- | -- ^ returning this value requires that `'1` must outlive `'2`
- | ||
- | |return type of closure is &'2 i32
- | has type `&'1 i32`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/regions/regions-escape-method.rs b/src/test/ui/regions/regions-escape-method.rs
index 5127d4d..69c01ae 100644
--- a/src/test/ui/regions/regions-escape-method.rs
+++ b/src/test/ui/regions/regions-escape-method.rs
@@ -12,5 +12,5 @@
fn main() {
let s = S;
- s.f(|p| p) //~ ERROR cannot infer
+ s.f(|p| p) //~ ERROR lifetime may not live long enough
}
diff --git a/src/test/ui/regions/regions-escape-method.stderr b/src/test/ui/regions/regions-escape-method.stderr
index ffc2a259..9f42512 100644
--- a/src/test/ui/regions/regions-escape-method.stderr
+++ b/src/test/ui/regions/regions-escape-method.stderr
@@ -1,32 +1,11 @@
-error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+error: lifetime may not live long enough
--> $DIR/regions-escape-method.rs:15:13
|
LL | s.f(|p| p)
- | ^
- |
-note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 15:9...
- --> $DIR/regions-escape-method.rs:15:9
- |
-LL | s.f(|p| p)
- | ^^^^^
-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
- |
-LL | s.f(|p| p)
- | ^^^^^^^^^^
-note: ...so that a type/lifetime parameter is in scope here
- --> $DIR/regions-escape-method.rs:15:5
- |
-LL | s.f(|p| p)
- | ^^^^^^^^^^
+ | -- ^ returning this value requires that `'1` must outlive `'2`
+ | ||
+ | |return type of closure is &'2 i32
+ | has type `&'1 i32`
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-escape-via-trait-or-not.nll.stderr b/src/test/ui/regions/regions-escape-via-trait-or-not.nll.stderr
deleted file mode 100644
index cae6c33..0000000
--- a/src/test/ui/regions/regions-escape-via-trait-or-not.nll.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: lifetime may not live long enough
- --> $DIR/regions-escape-via-trait-or-not.rs:18:14
- |
-LL | with(|o| o)
- | -- ^ returning this value requires that `'1` must outlive `'2`
- | ||
- | |return type of closure is &'2 isize
- | has type `&'1 isize`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/regions/regions-escape-via-trait-or-not.rs b/src/test/ui/regions/regions-escape-via-trait-or-not.rs
index 1e08961..ac0e56d 100644
--- a/src/test/ui/regions/regions-escape-via-trait-or-not.rs
+++ b/src/test/ui/regions/regions-escape-via-trait-or-not.rs
@@ -15,7 +15,7 @@
}
fn return_it() -> isize {
- with(|o| o) //~ ERROR cannot infer
+ with(|o| o) //~ ERROR lifetime may not live long enough
}
fn main() {
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 9082346..cae6c33 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
@@ -1,32 +1,11 @@
-error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+error: lifetime may not live long enough
--> $DIR/regions-escape-via-trait-or-not.rs:18:14
|
LL | with(|o| o)
- | ^
- |
-note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 18:10...
- --> $DIR/regions-escape-via-trait-or-not.rs:18:10
- |
-LL | with(|o| o)
- | ^^^^^
-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
- |
-LL | with(|o| o)
- | ^^^^
-note: ...so type `fn([closure@$DIR/regions-escape-via-trait-or-not.rs:18:10: 18:15]) -> isize {with::<&isize, [closure@$DIR/regions-escape-via-trait-or-not.rs:18:10: 18:15]>}` of expression is valid during the expression
- --> $DIR/regions-escape-via-trait-or-not.rs:18:5
- |
-LL | with(|o| o)
- | ^^^^
+ | -- ^ returning this value requires that `'1` must outlive `'2`
+ | ||
+ | |return type of closure is &'2 isize
+ | has type `&'1 isize`
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-infer-call-3.nll.stderr b/src/test/ui/regions/regions-infer-call-3.nll.stderr
deleted file mode 100644
index ca51555..0000000
--- a/src/test/ui/regions/regions-infer-call-3.nll.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: lifetime may not live long enough
- --> $DIR/regions-infer-call-3.rs:8:24
- |
-LL | let z = with(|y| { select(x, y) });
- | -- ^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
- | ||
- | |return type of closure is &'2 isize
- | has type `&'1 isize`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/regions/regions-infer-call-3.rs b/src/test/ui/regions/regions-infer-call-3.rs
index a76fccb..063ec84 100644
--- a/src/test/ui/regions/regions-infer-call-3.rs
+++ b/src/test/ui/regions/regions-infer-call-3.rs
@@ -6,7 +6,7 @@
fn manip<'a>(x: &'a isize) -> isize {
let z = with(|y| { select(x, y) });
- //~^ ERROR cannot infer
+ //~^ ERROR lifetime may not live long enough
*z
}
diff --git a/src/test/ui/regions/regions-infer-call-3.stderr b/src/test/ui/regions/regions-infer-call-3.stderr
index 1d6dbdb..ca51555 100644
--- a/src/test/ui/regions/regions-infer-call-3.stderr
+++ b/src/test/ui/regions/regions-infer-call-3.stderr
@@ -1,30 +1,11 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'r in function call due to conflicting requirements
+error: lifetime may not live long enough
--> $DIR/regions-infer-call-3.rs:8:24
|
LL | let z = with(|y| { select(x, y) });
- | ^^^^^^^^^^^^
- |
-note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 8:18...
- --> $DIR/regions-infer-call-3.rs:8:18
- |
-LL | let z = with(|y| { select(x, y) });
- | ^^^^^^^^^^^^^^^^^^^^
-note: ...so that reference does not outlive borrowed content
- --> $DIR/regions-infer-call-3.rs:8:34
- |
-LL | let z = with(|y| { select(x, y) });
- | ^
-note: but, the lifetime must be valid for the call at 8:13...
- --> $DIR/regions-infer-call-3.rs:8:13
- |
-LL | let z = with(|y| { select(x, y) });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...so type `&isize` of expression is valid during the expression
- --> $DIR/regions-infer-call-3.rs:8:13
- |
-LL | let z = with(|y| { select(x, y) });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | -- ^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
+ | ||
+ | |return type of closure is &'2 isize
+ | has type `&'1 isize`
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.nll.stderr b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.nll.stderr
deleted file mode 100644
index 4c275b1..0000000
--- a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.nll.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error: captured variable cannot escape `FnMut` closure body
- --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:24
- |
-LL | let mut f = || &mut x;
- | - ^^^^^^ returns a reference to a captured variable which escapes the closure body
- | |
- | inferred to be a `FnMut` closure
- |
- = note: `FnMut` closures only have access to their captured variables while they are executing...
- = note: ...therefore, they cannot allow references to captured variables to escape
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.rs b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.rs
index afe87f4..86e759f 100644
--- a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.rs
+++ b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.rs
@@ -4,7 +4,7 @@
// Unboxed closure case
{
let mut x = 0;
- let mut f = || &mut x; //~ ERROR cannot infer
+ let mut f = || &mut x; //~ ERROR captured variable cannot escape `FnMut` closure body
let x = f();
let y = f();
}
diff --git a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr
index 946465b..4c275b1 100644
--- a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr
+++ b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr
@@ -1,30 +1,13 @@
-error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+error: captured variable cannot escape `FnMut` closure body
--> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:24
|
LL | let mut f = || &mut x;
- | ^^^^^^
+ | - ^^^^^^ returns a reference to a captured variable which escapes the closure body
+ | |
+ | inferred to be a `FnMut` closure
|
-note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 7:21...
- --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:21
- |
-LL | let mut f = || &mut x;
- | ^^^^^^^^^
-note: ...so that closure can access `x`
- --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:24
- |
-LL | let mut f = || &mut x;
- | ^^^^^^
-note: but, the lifetime must be valid for the call at 9:17...
- --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:9:17
- |
-LL | let y = f();
- | ^^^
-note: ...so type `&mut i32` of expression is valid during the expression
- --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:9:17
- |
-LL | let y = f();
- | ^^^
+ = note: `FnMut` closures only have access to their captured variables while they are executing...
+ = note: ...therefore, they cannot allow references to captured variables to escape
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr
index 7414a7c..f7affdb 100644
--- a/src/test/ui/suggestions/into-str.stderr
+++ b/src/test/ui/suggestions/into-str.stderr
@@ -8,7 +8,6 @@
| ^^^ the trait `std::convert::From<std::string::String>` is not implemented for `&str`
|
= note: to coerce a `std::string::String` into a `&str`, use `&*` as a prefix
- = note: `std::convert::From<std::string::String>` is implemented for `&mut str`, but not for `&str`
= note: required because of the requirements on the impl of `std::convert::Into<&str>` for `std::string::String`
error: aborting due to previous error
diff --git a/src/test/ui/suggestions/issue-61963.rs b/src/test/ui/suggestions/issue-61963.rs
index c9d738f..666fc96 100644
--- a/src/test/ui/suggestions/issue-61963.rs
+++ b/src/test/ui/suggestions/issue-61963.rs
@@ -16,6 +16,7 @@
#[dom_struct]
pub struct Foo {
+ //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
qux: Qux<Qux<Baz>>,
bar: Box<Bar>,
//~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
diff --git a/src/test/ui/suggestions/issue-61963.stderr b/src/test/ui/suggestions/issue-61963.stderr
index 0e2eb76..62ae5fa 100644
--- a/src/test/ui/suggestions/issue-61963.stderr
+++ b/src/test/ui/suggestions/issue-61963.stderr
@@ -1,5 +1,5 @@
error: trait objects without an explicit `dyn` are deprecated
- --> $DIR/issue-61963.rs:20:14
+ --> $DIR/issue-61963.rs:21:14
|
LL | bar: Box<Bar>,
| ^^^ help: use `dyn`: `dyn Bar`
@@ -10,5 +10,11 @@
LL | #![deny(bare_trait_objects)]
| ^^^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/issue-61963.rs:18:1
+ |
+LL | pub struct Foo {
+ | ^^^ help: use `dyn`: `dyn pub`
+
+error: aborting due to 2 previous errors
diff --git a/src/test/ui/suggestions/issue-71394-no-from-impl.rs b/src/test/ui/suggestions/issue-71394-no-from-impl.rs
new file mode 100644
index 0000000..9ffcc3f
--- /dev/null
+++ b/src/test/ui/suggestions/issue-71394-no-from-impl.rs
@@ -0,0 +1,5 @@
+fn main() {
+ let data: &[u8] = &[0; 10];
+ let _: &[i8] = data.into();
+ //~^ ERROR the trait bound `&[i8]: std::convert::From<&[u8]>` is not satisfied
+}
diff --git a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr
new file mode 100644
index 0000000..84c73c2
--- /dev/null
+++ b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `&[i8]: std::convert::From<&[u8]>` is not satisfied
+ --> $DIR/issue-71394-no-from-impl.rs:3:25
+ |
+LL | let _: &[i8] = data.into();
+ | ^^^^ the trait `std::convert::From<&[u8]>` is not implemented for `&[i8]`
+ |
+ = note: required because of the requirements on the impl of `std::convert::Into<&[i8]>` for `&[u8]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.rs b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.rs
index 7465049..0d90e44 100644
--- a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.rs
+++ b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.rs
@@ -7,6 +7,7 @@
fn func(&self) -> Self::A;
fn funk(&self, _: Self::A);
+ fn funq(&self) -> Self::A {} //~ ERROR mismatched types
}
fn foo(_: impl Trait, x: impl Trait) {
diff --git a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr
index 5ae1d45..e629f8f 100644
--- a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr
+++ b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr
@@ -1,5 +1,19 @@
error[E0308]: mismatched types
- --> $DIR/trait-with-missing-associated-type-restriction.rs:13:9
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:10:31
+ |
+LL | fn funq(&self) -> Self::A {}
+ | ^^ expected associated type, found `()`
+ |
+ = note: expected associated type `<Self as Trait<T>>::A`
+ found unit type `()`
+help: a method is available that returns `<Self as Trait<T>>::A`
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:8:5
+ |
+LL | fn func(&self) -> Self::A;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::func`
+
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:14:9
|
LL | qux(x.func())
| ^^^^^^^^ expected `usize`, found associated type
@@ -12,7 +26,7 @@
| ^^^^^^^^^^^
error[E0308]: mismatched types
- --> $DIR/trait-with-missing-associated-type-restriction.rs:17:9
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:18:9
|
LL | qux(x.func())
| ^^^^^^^^ expected `usize`, found associated type
@@ -25,7 +39,7 @@
| ^^^^^^^^^^^
error[E0308]: mismatched types
- --> $DIR/trait-with-missing-associated-type-restriction.rs:21:9
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:22:9
|
LL | qux(x.func())
| ^^^^^^^^ expected `usize`, found associated type
@@ -38,25 +52,28 @@
| ^^^^^^^^^^^
error[E0308]: mismatched types
- --> $DIR/trait-with-missing-associated-type-restriction.rs:25:12
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:26:12
|
LL | x.funk(3);
| ^ expected associated type, found integer
|
= note: expected associated type `<T as Trait<i32>>::A`
found type `{integer}`
-help: a method is available that returns `<T as Trait<i32>>::A`
+help: some methods are available that return `<T as Trait<i32>>::A`
--> $DIR/trait-with-missing-associated-type-restriction.rs:8:5
|
LL | fn func(&self) -> Self::A;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::func`
+LL | fn funk(&self, _: Self::A);
+LL | fn funq(&self) -> Self::A {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::funq`
help: consider constraining the associated type `<T as Trait<i32>>::A` to `{integer}`
|
LL | fn bar2<T: Trait<i32, A = {integer}>>(x: T) {
| ^^^^^^^^^^^^^^^
error[E0308]: mismatched types
- --> $DIR/trait-with-missing-associated-type-restriction.rs:26:9
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:27:9
|
LL | qux(x.func())
| ^^^^^^^^ expected `usize`, found associated type
@@ -69,7 +86,7 @@
| ^^^^^^^^^^^
error[E0308]: mismatched types
- --> $DIR/trait-with-missing-associated-type-restriction.rs:30:9
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:31:9
|
LL | fn baz<D: std::fmt::Debug, T: Trait<A = D>>(x: T) {
| - this type parameter
@@ -80,13 +97,13 @@
found type parameter `D`
error[E0308]: mismatched types
- --> $DIR/trait-with-missing-associated-type-restriction.rs:34:9
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:35:9
|
LL | qux(x.func())
| ^^^^^^^^ expected `usize`, found `()`
error[E0308]: mismatched types
- --> $DIR/trait-with-missing-associated-type-restriction.rs:38:9
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:39:9
|
LL | qux(x.func())
| ^^^^^^^^ expected `usize`, found associated type
@@ -98,6 +115,6 @@
LL | fn ban<T>(x: T) where T: Trait<A = usize> {
| ^^^^^^^^^^^
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs
index 1f689a5..cdcf89e 100644
--- a/src/test/ui/symbol-names/impl1.rs
+++ b/src/test/ui/symbol-names/impl1.rs
@@ -3,8 +3,8 @@
// revisions: legacy v0
//[legacy]compile-flags: -Z symbol-mangling-version=legacy
//[v0]compile-flags: -Z symbol-mangling-version=v0
-//[legacy]normalize-stderr-32bit: "hdb62078998ce7ea8" -> "SYMBOL_HASH"
-//[legacy]normalize-stderr-64bit: "h62e540f14f879d56" -> "SYMBOL_HASH"
+//[legacy]normalize-stderr-32bit: "h5ef5dfc14aeecbfc" -> "SYMBOL_HASH"
+//[legacy]normalize-stderr-64bit: "h9e54d216f70fcbc5" -> "SYMBOL_HASH"
#![feature(optin_builtin_traits, rustc_attrs)]
#![allow(dead_code)]
diff --git a/src/test/ui/traits/traits-issue-71136.rs b/src/test/ui/traits/traits-issue-71136.rs
new file mode 100644
index 0000000..b21756e
--- /dev/null
+++ b/src/test/ui/traits/traits-issue-71136.rs
@@ -0,0 +1,8 @@
+struct Foo(u8);
+
+#[derive(Clone)]
+struct FooHolster {
+ the_foos: Vec<Foo>, //~ERROR Clone
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/traits-issue-71136.stderr b/src/test/ui/traits/traits-issue-71136.stderr
new file mode 100644
index 0000000..4c0a430
--- /dev/null
+++ b/src/test/ui/traits/traits-issue-71136.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the trait bound `Foo: std::clone::Clone` is not satisfied
+ --> $DIR/traits-issue-71136.rs:5:5
+ |
+LL | the_foos: Vec<Foo>,
+ | ^^^^^^^^^^^^^^^^^^ expected an implementor of trait `std::clone::Clone`
+ |
+ = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<Foo>`
+ = note: required by `std::clone::Clone::clone`
+ = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index 704a95e..0a02aa7 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -3,7 +3,7 @@
use rustc_hir::{Body, FnDecl, HirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{Opaque, Predicate::Trait, ToPolyTraitRef};
+use rustc_middle::ty::{Opaque, PredicateKind::Trait, ToPolyTraitRef};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{sym, Span};
use rustc_trait_selection::traits::error_reporting::suggestions::InferCtxtExt;
@@ -91,7 +91,7 @@
cx.tcx.infer_ctxt().enter(|infcx| {
for FulfillmentError { obligation, .. } in send_errors {
infcx.maybe_note_obligation_cause_for_async_await(db, &obligation);
- if let Trait(trait_pred, _) = obligation.predicate {
+ if let Trait(trait_pred, _) = obligation.predicate.kind() {
let trait_ref = trait_pred.to_poly_trait_ref();
db.note(&*format!(
"`{}` doesn't implement `{}`",
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 626427c..810a226 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -18,7 +18,7 @@
use rustc_middle::hir::map::Map;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::{self, Predicate, Ty};
+use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::symbol::{sym, SymbolStr};
@@ -1496,8 +1496,8 @@
if let ty::Opaque(def_id, _) = ret_ty.kind {
// one of the associated types must be Self
for predicate in cx.tcx.predicates_of(def_id).predicates {
- match predicate {
- (Predicate::Projection(poly_projection_predicate), _) => {
+ match predicate.0.kind() {
+ ty::PredicateKind::Projection(poly_projection_predicate) => {
let binder = poly_projection_predicate.ty();
let associated_type = binder.skip_binder();
@@ -1506,7 +1506,7 @@
return;
}
},
- (_, _) => {},
+ _ => {},
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index 5300fd2..3ad3d5a 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -71,7 +71,7 @@
fn is_executable(cx: &LateContext<'_, '_>) -> bool {
use rustc_session::config::CrateType;
- cx.tcx.sess.crate_types.get().iter().any(|t: &CrateType| match t {
+ cx.tcx.sess.crate_types().iter().any(|t: &CrateType| match t {
CrateType::Executable => true,
_ => false,
})
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index ed48ab5..60c5360 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -114,7 +114,7 @@
let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds.iter().copied())
.filter(|p| !p.is_global())
.filter_map(|obligation| {
- if let ty::Predicate::Trait(poly_trait_ref, _) = obligation.predicate {
+ if let ty::PredicateKind::Trait(poly_trait_ref, _) = obligation.predicate.kind() {
if poly_trait_ref.def_id() == sized_trait || poly_trait_ref.skip_binder().has_escaping_bound_vars()
{
return None;
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index 438a9f4..f224732 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -1299,7 +1299,7 @@
ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
ty::Opaque(ref def_id, _) => {
for (predicate, _) in cx.tcx.predicates_of(*def_id).predicates {
- if let ty::Predicate::Trait(ref poly_trait_predicate, _) = predicate {
+ if let ty::PredicateKind::Trait(ref poly_trait_predicate, _) = predicate.kind() {
if must_use_attr(&cx.tcx.get_attrs(poly_trait_predicate.skip_binder().trait_ref.def_id)).is_some() {
return true;
}
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index 988a226..72437e0 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -39,6 +39,19 @@
'rustc-dev-guide': {'mark-i-m', 'spastorino', 'amanjeev', 'JohnTitor'},
}
+LABELS = {
+ 'miri': ['A-miri', 'C-bug'],
+ 'rls': ['A-rls', 'C-bug'],
+ 'rustfmt': ['C-bug'],
+ 'book': ['C-bug'],
+ 'nomicon': ['C-bug'],
+ 'reference': ['C-bug'],
+ 'rust-by-example': ['C-bug'],
+ 'embedded-book': ['C-bug'],
+ 'edition-guide': ['C-bug'],
+ 'rustc-dev-guide': ['C-bug'],
+}
+
REPOS = {
'miri': 'https://github.com/rust-lang/miri',
'rls': 'https://github.com/rust-lang/rls',
@@ -132,6 +145,7 @@
assignees,
relevant_pr_number,
relevant_pr_user,
+ labels,
):
# Open an issue about the toolstate failure.
if status == 'test-fail':
@@ -155,6 +169,7 @@
)),
'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number),
'assignees': list(assignees),
+ 'labels': labels,
})
print("Creating issue:\n{}".format(request))
response = urllib2.urlopen(urllib2.Request(
@@ -235,7 +250,7 @@
try:
issue(
tool, create_issue_for_status, MAINTAINERS.get(tool, ''),
- relevant_pr_number, relevant_pr_user,
+ relevant_pr_number, relevant_pr_user, LABELS.get(tool, ''),
)
except urllib2.HTTPError as e:
# network errors will simply end up not creating an issue, but that's better
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index d3c7b7a..6138902 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -128,6 +128,7 @@
"miniz_oxide",
"nodrop",
"num_cpus",
+ "once_cell",
"opaque-debug",
"parking_lot",
"parking_lot_core",
diff --git a/triagebot.toml b/triagebot.toml
index 2210a8f..f12d516 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -37,5 +37,9 @@
[prioritize]
label = "I-prioritize"
prioritize_on = ["regression-from-stable-to-stable", "regression-from-stable-to-beta", "regression-from-stable-to-nightly"]
-priority_labels = "P-*"
+exclude_labels = [
+ "P-*",
+ "T-infra",
+ "T-release",
+]
zulip_stream = 227806