diff options
258 files changed, 3076 insertions, 2113 deletions
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index c9c973bd343..6f78c816093 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2361,8 +2361,8 @@ mod error { if !self.errors.buffered.is_empty() { self.errors.buffered.sort_by_key(|diag| diag.sort_span); - for diag in self.errors.buffered.drain(..) { - self.infcx.tcx.sess.diagnostic().emit_diagnostic(&diag); + for mut diag in self.errors.buffered.drain(..) { + self.infcx.tcx.sess.diagnostic().emit_diagnostic(&mut diag); } } diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index bbc8e62d68f..be628c9202c 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -3,15 +3,17 @@ use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; +use rustc_errors::PResult; use rustc_expand::base::{self, *}; use rustc_expand::module::DirOwnership; use rustc_parse::parser::{ForceCollect, Parser}; use rustc_parse::{self, new_parser_from_file}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; use rustc_span::symbol::Symbol; -use rustc_span::{self, Pos, Span}; +use rustc_span::{self, FileName, Pos, Span}; use smallvec::SmallVec; +use std::path::PathBuf; use std::rc::Rc; // These macros all relate to the file system; they either return @@ -102,7 +104,7 @@ pub fn expand_include<'cx>( return DummyResult::any(sp); }; // The file will be added to the code map by the parser - let file = match cx.resolve_path(file, sp) { + let file = match resolve_path(cx, file, sp) { Ok(f) => f, Err(mut err) => { err.emit(); @@ -171,7 +173,7 @@ pub fn expand_include_str( let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_str!") else { return DummyResult::any(sp); }; - let file = match cx.resolve_path(file, sp) { + let file = match resolve_path(cx, file, sp) { Ok(f) => f, Err(mut err) => { err.emit(); @@ -205,7 +207,7 @@ pub fn expand_include_bytes( let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_bytes!") else { return DummyResult::any(sp); }; - let file = match cx.resolve_path(file, sp) { + let file = match resolve_path(cx, file, sp) { Ok(f) => f, Err(mut err) => { err.emit(); @@ -220,3 +222,40 @@ pub fn expand_include_bytes( } } } + +/// Resolves a `path` mentioned inside Rust code, returning an absolute path. +/// +/// This unifies the logic used for resolving `include_X!`. +fn resolve_path<'a>( + cx: &mut ExtCtxt<'a>, + path: impl Into<PathBuf>, + span: Span, +) -> PResult<'a, PathBuf> { + let path = path.into(); + + // Relative paths are resolved relative to the file in which they are found + // after macro expansion (that is, they are unhygienic). + if !path.is_absolute() { + let callsite = span.source_callsite(); + let mut result = match cx.source_map().span_to_filename(callsite) { + FileName::Real(name) => name + .into_local_path() + .expect("attempting to resolve a file path in an external file"), + FileName::DocTest(path, _) => path, + other => { + return Err(cx.struct_span_err( + span, + &format!( + "cannot resolve relative path in non-file source `{}`", + cx.source_map().filename_for_diagnostics(&other) + ), + )); + } + }; + result.pop(); + result.push(path); + Ok(result) + } else { + Ok(path) + } +} diff --git a/compiler/rustc_codegen_gcc/.github/workflows/main.yml b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml index 98bed8ef387..337837c40bf 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/main.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml @@ -10,10 +10,17 @@ jobs: strategy: fail-fast: false + matrix: + libgccjit_version: ["libgccjit.so", "libgccjit_without_int128.so"] steps: - uses: actions/checkout@v2 + - uses: actions/checkout@v2 + with: + repository: llvm/llvm-project + path: llvm + - name: Install packages run: sudo apt-get install ninja-build ripgrep @@ -21,19 +28,25 @@ jobs: uses: dawidd6/action-download-artifact@v2 with: workflow: main.yml - name: libgccjit.so + name: ${{ matrix.libgccjit_version }} path: gcc-build repo: antoyo/gcc + search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts. - name: Setup path to libgccjit run: | echo $(readlink -f gcc-build) > gcc_path + # NOTE: the filename is still libgccjit.so even when the artifact name is different. ln gcc-build/libgccjit.so gcc-build/libgccjit.so.0 - - name: Set LIBRARY_PATH + - name: Set env run: | echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV + echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV + + - name: Set RUST_COMPILER_RT_ROOT + run: echo "RUST_COMPILER_RT_ROOT="${{ env.workspace }}/llvm/compiler-rt >> $GITHUB_ENV # https://github.com/actions/cache/issues/133 - name: Fixup owner of ~/.cargo/ diff --git a/compiler/rustc_codegen_gcc/.gitignore b/compiler/rustc_codegen_gcc/.gitignore index 1e2f9e3aebb..efda74b2633 100644 --- a/compiler/rustc_codegen_gcc/.gitignore +++ b/compiler/rustc_codegen_gcc/.gitignore @@ -18,3 +18,4 @@ gimple* res test-backend gcc_path +benchmarks diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock index 47925f72c2c..a1d9f2f5e38 100644 --- a/compiler/rustc_codegen_gcc/Cargo.lock +++ b/compiler/rustc_codegen_gcc/Cargo.lock @@ -41,7 +41,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#0672b78d162d65b6f36ea4062947253affe9fdef" +source = "git+https://github.com/antoyo/gccjit.rs#bdecdecfb8a02ec861a39a350f990faa33bd31c3" dependencies = [ "gccjit_sys", ] @@ -49,7 +49,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#0672b78d162d65b6f36ea4062947253affe9fdef" +source = "git+https://github.com/antoyo/gccjit.rs#bdecdecfb8a02ec861a39a350f990faa33bd31c3" dependencies = [ "libc 0.1.12", ] diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md index 1fcfb5f6e20..27b30e0fd1b 100644 --- a/compiler/rustc_codegen_gcc/Readme.md +++ b/compiler/rustc_codegen_gcc/Readme.md @@ -21,6 +21,8 @@ You can also use my [fork of gcc](https://github.com/antoyo/gcc) which already i ```bash $ git clone https://github.com/rust-lang/rustc_codegen_gcc.git $ cd rustc_codegen_gcc +$ git clone https://github.com/llvm/llvm-project llvm --depth 1 --single-branch +$ export RUST_COMPILER_RT_ROOT="$PWD/llvm/compiler-rt" $ ./prepare_build.sh # download and patch sysroot src $ ./build.sh --release ``` @@ -109,6 +111,13 @@ Or add a breakpoint to `add_error` in gdb and print the line number using: ``` p loc->m_line +p loc->m_filename->m_buffer +``` + +To print a debug representation of a tree: + +```c +debug_tree(expr); ``` To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo build`. @@ -134,4 +143,5 @@ To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo b * Set `linker='-Clinker=m68k-linux-gcc'`. * Set the path to the cross-compiling libgccjit in `gcc_path`. * Disable the 128-bit integer types if the target doesn't support them by using `let i128_type = context.new_type::<i64>();` in `context.rs` (same for u128_type). + * Comment the line: `context.add_command_line_option("-masm=intel");` in src/base.rs. * (might not be necessary) Disable the compilation of libstd.so (and possibly libcore.so?). diff --git a/compiler/rustc_codegen_gcc/build.sh b/compiler/rustc_codegen_gcc/build.sh index 17a0d2ab3f0..230ab7b6d42 100755 --- a/compiler/rustc_codegen_gcc/build.sh +++ b/compiler/rustc_codegen_gcc/build.sh @@ -3,7 +3,27 @@ #set -x set -e -if [ -f ./gcc_path ]; then +codegen_channel=debug +sysroot_channel=debug + +while [[ $# -gt 0 ]]; do + case $1 in + --release) + codegen_channel=release + shift + ;; + --release-sysroot) + sysroot_channel=release + shift + ;; + *) + echo "Unknown option $1" + exit 1 + ;; + esac +done + +if [ -f ./gcc_path ]; then export GCC_PATH=$(cat gcc_path) else echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details' @@ -13,13 +33,21 @@ fi export LD_LIBRARY_PATH="$GCC_PATH" export LIBRARY_PATH="$GCC_PATH" -if [[ "$1" == "--release" ]]; then +features= + +if [[ "$1" == "--features" ]]; then + shift + features="--features $1" + shift +fi + +if [[ "$codegen_channel" == "release" ]]; then export CHANNEL='release' - CARGO_INCREMENTAL=1 cargo rustc --release + CARGO_INCREMENTAL=1 cargo rustc --release $features else echo $LD_LIBRARY_PATH export CHANNEL='debug' - cargo rustc + cargo rustc $features fi source config.sh @@ -28,4 +56,9 @@ rm -r target/out || true mkdir -p target/out/gccjit echo "[BUILD] sysroot" -time ./build_sysroot/build_sysroot.sh $CHANNEL +if [[ "$sysroot_channel" == "release" ]]; then + time ./build_sysroot/build_sysroot.sh --release +else + time ./build_sysroot/build_sysroot.sh +fi + diff --git a/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh b/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh index d1dcf495db8..a965ca971a0 100755 --- a/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh +++ b/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh @@ -22,7 +22,7 @@ if [[ "$1" == "--release" ]]; then RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target $TARGET_TRIPLE --release else sysroot_channel='debug' - cargo build --target $TARGET_TRIPLE + cargo build --target $TARGET_TRIPLE --features compiler_builtins/c fi # Copy files to sysroot diff --git a/compiler/rustc_codegen_gcc/cargo.sh b/compiler/rustc_codegen_gcc/cargo.sh index 1001c522052..332f365ce0c 100755 --- a/compiler/rustc_codegen_gcc/cargo.sh +++ b/compiler/rustc_codegen_gcc/cargo.sh @@ -8,7 +8,7 @@ pushd $(dirname "$0") >/dev/null source config.sh # read nightly compiler from rust-toolchain file -TOOLCHAIN=$(cat rust-toolchain) +TOOLCHAIN=$(cat rust-toolchain | grep channel | sed 's/channel = "\(.*\)"/\1/') popd >/dev/null diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs index 1067cee8814..a8435287d9f 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core.rs @@ -14,6 +14,9 @@ unsafe extern "C" fn _Unwind_Resume() { #[lang = "sized"] pub trait Sized {} +#[lang = "destruct"] +pub trait Destruct {} + #[lang = "unsize"] pub trait Unsize<T: ?Sized> {} @@ -59,6 +62,7 @@ unsafe impl Copy for i16 {} unsafe impl Copy for i32 {} unsafe impl Copy for isize {} unsafe impl Copy for f32 {} +unsafe impl Copy for f64 {} unsafe impl Copy for char {} unsafe impl<'a, T: ?Sized> Copy for &'a T {} unsafe impl<T: ?Sized> Copy for *const T {} @@ -443,12 +447,22 @@ pub trait Deref { fn deref(&self) -> &Self::Target; } +pub trait Allocator { +} + +pub struct Global; + +impl Allocator for Global {} + #[lang = "owned_box"] -pub struct Box<T: ?Sized>(*mut T); +pub struct Box< + T: ?Sized, + A: Allocator = Global, +>(*mut T, A); impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {} -impl<T: ?Sized> Drop for Box<T> { +impl<T: ?Sized, A: Allocator> Drop for Box<T, A> { fn drop(&mut self) { // drop is currently performed by compiler. } @@ -468,7 +482,7 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { } #[lang = "box_free"] -unsafe fn box_free<T: ?Sized>(ptr: *mut T) { +unsafe fn box_free<T: ?Sized, A: Allocator>(ptr: *mut T, alloc: A) { libc::free(ptr as *mut u8); } diff --git a/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch index aae62a938b4..301b3f9bde4 100644 --- a/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch +++ b/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch @@ -22,7 +22,7 @@ index 0000000..46fd999 +[package] +name = "core" +version = "0.0.0" -+edition = "2018" ++edition = "2021" + +[lib] +name = "coretests" diff --git a/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch b/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch index 73e9c858caf..ee5ba449fb8 100644 --- a/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch +++ b/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch @@ -46,24 +46,4 @@ index 4bc44e9..8e3c7a4 100644 #[test] fn cell_allows_array_cycle() { -diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs -index 3e00e0a..8e5663b 100644 ---- a/library/core/tests/slice.rs -+++ b/library/core/tests/slice.rs -@@ -2108,6 +2108,7 @@ fn test_copy_within_panics_src_out_of_bounds() { - bytes.copy_within(usize::MAX..=usize::MAX, 0); - } - -+/* - #[test] - fn test_is_sorted() { - let empty: [i32; 0] = []; -@@ -2122,6 +2123,7 @@ fn test_is_sorted() { - assert!(!["c", "bb", "aaa"].is_sorted()); - assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len())); - } -+*/ - - #[test] - fn test_slice_run_destructors() { -- 2.21.0 (Apple Git-122) diff --git a/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch b/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch index 8954f91021f..03900ba101a 100644 --- a/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch +++ b/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch @@ -7,18 +7,222 @@ Subject: [PATCH] [core] Disable portable-simd test library/core/tests/lib.rs | 1 - 1 file changed, 1 deletion(-) +diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs +index aa1ad93..95fbf55 100644 +--- a/library/core/src/lib.rs ++++ b/library/core/src/lib.rs +@@ -398,23 +398,4 @@ pub mod arch { + } + } + +-// Pull in the `core_simd` crate directly into libcore. The contents of +-// `core_simd` are in a different repository: rust-lang/portable-simd. +-// +-// `core_simd` depends on libcore, but the contents of this module are +-// set up in such a way that directly pulling it here works such that the +-// crate uses this crate as its libcore. +-#[path = "../../portable-simd/crates/core_simd/src/mod.rs"] +-#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)] +-#[allow(rustdoc::bare_urls)] +-#[unstable(feature = "portable_simd", issue = "86656")] +-mod core_simd; +- +-#[doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")] +-#[unstable(feature = "portable_simd", issue = "86656")] +-pub mod simd { +- #[unstable(feature = "portable_simd", issue = "86656")] +- pub use crate::core_simd::simd::*; +-} +- + include!("primitive_docs.rs"); +diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs +index cd38c3a..ad632dc 100644 +--- a/library/core/src/slice/mod.rs ++++ b/library/core/src/slice/mod.rs +@@ -17,6 +17,5 @@ use crate::ptr; + use crate::result::Result; + use crate::result::Result::{Err, Ok}; +-use crate::simd::{self, Simd}; + use crate::slice; + + #[unstable( +@@ -3475,121 +3474,6 @@ impl<T> [T] { + } + } + +- /// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix. +- /// +- /// This is a safe wrapper around [`slice::align_to`], so has the same weak +- /// postconditions as that method. You're only assured that +- /// `self.len() == prefix.len() + middle.len() * LANES + suffix.len()`. +- /// +- /// Notably, all of the following are possible: +- /// - `prefix.len() >= LANES`. +- /// - `middle.is_empty()` despite `self.len() >= 3 * LANES`. +- /// - `suffix.len() >= LANES`. +- /// +- /// That said, this is a safe method, so if you're only writing safe code, +- /// then this can at most cause incorrect logic, not unsoundness. +- /// +- /// # Panics +- /// +- /// This will panic if the size of the SIMD type is different from +- /// `LANES` times that of the scalar. +- /// +- /// At the time of writing, the trait restrictions on `Simd<T, LANES>` keeps +- /// that from ever happening, as only power-of-two numbers of lanes are +- /// supported. It's possible that, in the future, those restrictions might +- /// be lifted in a way that would make it possible to see panics from this +- /// method for something like `LANES == 3`. +- /// +- /// # Examples +- /// +- /// ``` +- /// #![feature(portable_simd)] +- /// +- /// let short = &[1, 2, 3]; +- /// let (prefix, middle, suffix) = short.as_simd::<4>(); +- /// assert_eq!(middle, []); // Not enough elements for anything in the middle +- /// +- /// // They might be split in any possible way between prefix and suffix +- /// let it = prefix.iter().chain(suffix).copied(); +- /// assert_eq!(it.collect::<Vec<_>>(), vec![1, 2, 3]); +- /// +- /// fn basic_simd_sum(x: &[f32]) -> f32 { +- /// use std::ops::Add; +- /// use std::simd::f32x4; +- /// let (prefix, middle, suffix) = x.as_simd(); +- /// let sums = f32x4::from_array([ +- /// prefix.iter().copied().sum(), +- /// 0.0, +- /// 0.0, +- /// suffix.iter().copied().sum(), +- /// ]); +- /// let sums = middle.iter().copied().fold(sums, f32x4::add); +- /// sums.reduce_sum() +- /// } +- /// +- /// let numbers: Vec<f32> = (1..101).map(|x| x as _).collect(); +- /// assert_eq!(basic_simd_sum(&numbers[1..99]), 4949.0); +- /// ``` +- #[unstable(feature = "portable_simd", issue = "86656")] +- pub fn as_simd<const LANES: usize>(&self) -> (&[T], &[Simd<T, LANES>], &[T]) +- where +- Simd<T, LANES>: AsRef<[T; LANES]>, +- T: simd::SimdElement, +- simd::LaneCount<LANES>: simd::SupportedLaneCount, +- { +- // These are expected to always match, as vector types are laid out like +- // arrays per <https://llvm.org/docs/LangRef.html#vector-type>, but we +- // might as well double-check since it'll optimize away anyhow. +- assert_eq!(mem::size_of::<Simd<T, LANES>>(), mem::size_of::<[T; LANES]>()); +- +- // SAFETY: The simd types have the same layout as arrays, just with +- // potentially-higher alignment, so the de-facto transmutes are sound. +- unsafe { self.align_to() } +- } +- +- /// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix. +- /// +- /// This is a safe wrapper around [`slice::align_to_mut`], so has the same weak +- /// postconditions as that method. You're only assured that +- /// `self.len() == prefix.len() + middle.len() * LANES + suffix.len()`. +- /// +- /// Notably, all of the following are possible: +- /// - `prefix.len() >= LANES`. +- /// - `middle.is_empty()` despite `self.len() >= 3 * LANES`. +- /// - `suffix.len() >= LANES`. +- /// +- /// That said, this is a safe method, so if you're only writing safe code, +- /// then this can at most cause incorrect logic, not unsoundness. +- /// +- /// This is the mutable version of [`slice::as_simd`]; see that for examples. +- /// +- /// # Panics +- /// +- /// This will panic if the size of the SIMD type is different from +- /// `LANES` times that of the scalar. +- /// +- /// At the time of writing, the trait restrictions on `Simd<T, LANES>` keeps +- /// that from ever happening, as only power-of-two numbers of lanes are +- /// supported. It's possible that, in the future, those restrictions might +- /// be lifted in a way that would make it possible to see panics from this +- /// method for something like `LANES == 3`. +- #[unstable(feature = "portable_simd", issue = "86656")] +- pub fn as_simd_mut<const LANES: usize>(&mut self) -> (&mut [T], &mut [Simd<T, LANES>], &mut [T]) +- where +- Simd<T, LANES>: AsMut<[T; LANES]>, +- T: simd::SimdElement, +- simd::LaneCount<LANES>: simd::SupportedLaneCount, +- { +- // These are expected to always match, as vector types are laid out like +- // arrays per <https://llvm.org/docs/LangRef.html#vector-type>, but we +- // might as well double-check since it'll optimize away anyhow. +- assert_eq!(mem::size_of::<Simd<T, LANES>>(), mem::size_of::<[T; LANES]>()); +- +- // SAFETY: The simd types have the same layout as arrays, just with +- // potentially-higher alignment, so the de-facto transmutes are sound. +- unsafe { self.align_to_mut() } +- } +- + /// Checks if the elements of this slice are sorted. + /// + /// That is, for each element `a` and its following element `b`, `a <= b` must hold. If the diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs -index ec70034..7cd9e21 100644 +index 06c7be0..359e2e7 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs -@@ -121,7 +121,6 @@ mod pattern; - mod pin; +@@ -75,7 +75,6 @@ + #![feature(never_type)] + #![feature(unwrap_infallible)] + #![feature(result_into_ok_or_err)] +-#![feature(portable_simd)] + #![feature(ptr_metadata)] + #![feature(once_cell)] + #![feature(option_result_contains)] +@@ -127,7 +126,6 @@ mod pin; + mod pin_macro; mod ptr; mod result; -mod simd; mod slice; mod str; mod str_lossy; --- +diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs +index 5dc586d..b6fc48f 100644 +--- a/library/std/src/lib.rs ++++ b/library/std/src/lib.rs +@@ -312,6 +312,5 @@ + #![feature(panic_can_unwind)] + #![feature(panic_unwind)] + #![feature(platform_intrinsics)] +-#![feature(portable_simd)] + #![feature(prelude_import)] + #![feature(ptr_as_uninit)] +@@ -508,23 +508,6 @@ pub mod time; + #[unstable(feature = "once_cell", issue = "74465")] + pub mod lazy; + +-// Pull in `std_float` crate into libstd. The contents of +-// `std_float` are in a different repository: rust-lang/portable-simd. +-#[path = "../../portable-simd/crates/std_float/src/lib.rs"] +-#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)] +-#[allow(rustdoc::bare_urls)] +-#[unstable(feature = "portable_simd", issue = "86656")] +-mod std_float; +- +-#[doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")] +-#[unstable(feature = "portable_simd", issue = "86656")] +-pub mod simd { +- #[doc(inline)] +- pub use crate::std_float::StdFloat; +- #[doc(inline)] +- pub use core::simd::*; +-} +- + #[stable(feature = "futures_api", since = "1.36.0")] + pub mod task { + //! Types and Traits for working with asynchronous tasks. +-- 2.26.2.7.g19db9cfb68 diff --git a/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch b/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch index bf74a74c7c4..dc1beae6d2e 100644 --- a/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch +++ b/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch @@ -1,30 +1,32 @@ -From 0ffdd8eda8df364391c8ac6e1ce92c73ba9254d4 Mon Sep 17 00:00:00 2001 +From eb703e627e7a84f1cd8d0d87f0f69da1f0acf765 Mon Sep 17 00:00:00 2001 From: bjorn3 <bjorn3@users.noreply.github.com> Date: Fri, 3 Dec 2021 12:16:30 +0100 Subject: [PATCH] Disable long running tests --- - library/core/tests/slice.rs | 3 +++ - 1 file changed, 3 insertions(+) + library/core/tests/slice.rs | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs -index 2c8f00a..44847ee 100644 +index 8402833..84592e0 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs -@@ -2332,7 +2332,8 @@ macro_rules! empty_max_mut { - }; - } +@@ -2462,6 +2462,7 @@ take_tests! { + #[cfg(not(miri))] // unused in Miri + const EMPTY_MAX: &'static [()] = &[(); usize::MAX]; +/* - #[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations) - take_tests! { - slice: &[(); usize::MAX], method: take, - (take_in_bounds_max_range_to, (..usize::MAX), Some(EMPTY_MAX), &[(); 0]), -@@ -2345,3 +2347,4 @@ take_tests! { + // can't be a constant due to const mutability rules + #[cfg(not(miri))] // unused in Miri + macro_rules! empty_max_mut { +@@ -2485,6 +2486,7 @@ take_tests! { (take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()), (take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()), } +*/ + + #[test] + fn test_slice_from_ptr_range() { -- 2.26.2.7.g19db9cfb68 diff --git a/compiler/rustc_codegen_gcc/prepare_build.sh b/compiler/rustc_codegen_gcc/prepare_build.sh index ccf53509830..3896775a0b9 100755 --- a/compiler/rustc_codegen_gcc/prepare_build.sh +++ b/compiler/rustc_codegen_gcc/prepare_build.sh @@ -1,5 +1,4 @@ #!/bin/bash --verbose set -e -rustup component add rust-src rustc-dev llvm-tools-preview ./build_sysroot/prepare_sysroot_src.sh diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain index ee0822f6c31..db14ea2bebc 100644 --- a/compiler/rustc_codegen_gcc/rust-toolchain +++ b/compiler/rustc_codegen_gcc/rust-toolchain @@ -1 +1,3 @@ -nightly-2021-12-30 +[toolchain] +channel = "nightly-2022-03-26" +components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs index a8b1e70e2bb..2c796d0f69e 100644 --- a/compiler/rustc_codegen_gcc/src/abi.rs +++ b/compiler/rustc_codegen_gcc/src/abi.rs @@ -1,5 +1,6 @@ -use gccjit::{ToRValue, Type}; +use gccjit::{ToLValue, ToRValue, Type}; use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeMethods}; +use rustc_data_structures::stable_set::FxHashSet; use rustc_middle::bug; use rustc_middle::ty::Ty; use rustc_target::abi::call::{CastTarget, FnAbi, PassMode, Reg, RegKind}; @@ -15,9 +16,21 @@ impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } fn get_param(&mut self, index: usize) -> Self::Value { - self.cx.current_func.borrow().expect("current func") - .get_param(index as i32) - .to_rvalue() + let func = self.current_func(); + let param = func.get_param(index as i32); + let on_stack = + if let Some(on_stack_param_indices) = self.on_stack_function_params.borrow().get(&func) { + on_stack_param_indices.contains(&index) + } + else { + false + }; + if on_stack { + param.to_lvalue().get_address(None) + } + else { + param.to_rvalue() + } } } @@ -87,12 +100,13 @@ impl GccType for Reg { pub trait FnAbiGccExt<'gcc, 'tcx> { // TODO(antoyo): return a function pointer type instead? - fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool); + fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>); fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; } impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { - fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool) { + fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>) { + let mut on_stack_param_indices = FxHashSet::default(); let args_capacity: usize = self.args.iter().map(|arg| if arg.pad.is_some() { 1 @@ -144,17 +158,22 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { unimplemented!(); } PassMode::Cast(cast) => cast.gcc_type(cx), - PassMode::Indirect { extra_attrs: None, .. } => cx.type_ptr_to(arg.memory_ty(cx)), + PassMode::Indirect { extra_attrs: None, on_stack: true, .. } => { + on_stack_param_indices.insert(argument_tys.len()); + arg.memory_ty(cx) + }, + PassMode::Indirect { extra_attrs: None, on_stack: false, .. } => cx.type_ptr_to(arg.memory_ty(cx)), }; argument_tys.push(arg_ty); } - (return_ty, argument_tys, self.c_variadic) + (return_ty, argument_tys, self.c_variadic, on_stack_param_indices) } fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> { - let (return_type, params, variadic) = self.gcc_type(cx); + let (return_type, params, variadic, on_stack_param_indices) = self.gcc_type(cx); let pointer_type = cx.context.new_function_pointer_type(None, return_type, ¶ms, variadic); + cx.on_stack_params.borrow_mut().insert(pointer_type.dyncast_function_ptr_type().expect("function ptr type"), on_stack_param_indices); pointer_type } } diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs index 334ef32f1d1..b503bd020f6 100644 --- a/compiler/rustc_codegen_gcc/src/back/write.rs +++ b/compiler/rustc_codegen_gcc/src/back/write.rs @@ -45,7 +45,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, _diag_han if env::var("CG_GCCJIT_DUMP_MODULE_NAMES").as_deref() == Ok("1") { println!("Module {}", module.name); } - if env::var("CG_GCCJIT_DUMP_MODULE").as_deref() == Ok(&module.name) { + if env::var("CG_GCCJIT_DUMP_ALL_MODULES").as_deref() == Ok("1") || env::var("CG_GCCJIT_DUMP_MODULE").as_deref() == Ok(&module.name) { println!("Dumping reproducer {}", module.name); let _ = fs::create_dir("/tmp/reproducers"); // FIXME(antoyo): segfault in dump_reproducer_to_file() might be caused by @@ -54,6 +54,11 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, _diag_han context.dump_reproducer_to_file(&format!("/tmp/reproducers/{}.c", module.name)); println!("Dumped reproducer {}", module.name); } + if env::var("CG_GCCJIT_DUMP_TO_FILE").as_deref() == Ok("1") { + let _ = fs::create_dir("/tmp/gccjit_dumps"); + let path = &format!("/tmp/gccjit_dumps/{}.c", module.name); + context.dump_to_file(path, true); + } context.compile_to_file(OutputKind::ObjectFile, obj_out.to_str().expect("path to str")); } diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs index 8b23e96066e..f5aca35cdcb 100644 --- a/compiler/rustc_codegen_gcc/src/base.rs +++ b/compiler/rustc_codegen_gcc/src/base.rs @@ -52,7 +52,7 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType { } } -pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (ModuleCodegen<GccContext>, u64) { +pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol, supports_128bit_integers: bool) -> (ModuleCodegen<GccContext>, u64) { let prof_timer = tcx.prof.generic_activity("codegen_module"); let start_time = Instant::now(); @@ -60,7 +60,7 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul let (module, _) = tcx.dep_graph.with_task( dep_node, tcx, - cgu_name, + (cgu_name, supports_128bit_integers), module_codegen, Some(dep_graph::hash_result), ); @@ -71,7 +71,7 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul // the time we needed for codegenning it. let cost = time_to_codegen.as_secs() * 1_000_000_000 + time_to_codegen.subsec_nanos() as u64; - fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<GccContext> { + fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, supports_128bit_integers): (Symbol, bool)) -> ModuleCodegen<GccContext> { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... //let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str()); @@ -85,6 +85,12 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul context.add_command_line_option("-fno-semantic-interposition"); // NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292). context.add_command_line_option("-fno-strict-aliasing"); + + if tcx.sess.opts.debugging_opts.function_sections.unwrap_or(tcx.sess.target.function_sections) { + context.add_command_line_option("-ffunction-sections"); + context.add_command_line_option("-fdata-sections"); + } + if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") { context.set_dump_code_on_compile(true); } @@ -99,8 +105,11 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul context.set_keep_intermediates(true); } + // TODO(bjorn3): Remove once unwinding is properly implemented + context.set_allow_unreachable_blocks(true); + { - let cx = CodegenCx::new(&context, cgu, tcx); + let cx = CodegenCx::new(&context, cgu, tcx, supports_128bit_integers); let mono_items = cgu.items_in_deterministic_order(tcx); for &(mono_item, (linkage, visibility)) in &mono_items { diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index be3f6a12706..b2f46e92ecc 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -30,6 +30,7 @@ use rustc_codegen_ssa::traits::{ OverflowOp, StaticBuilderMethods, }; +use rustc_data_structures::stable_set::FxHashSet; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_span::Span; @@ -80,21 +81,21 @@ impl EnumClone for AtomicOrdering { pub struct Builder<'a: 'gcc, 'gcc, 'tcx> { pub cx: &'a CodegenCx<'gcc, 'tcx>, - pub block: Option<Block<'gcc>>, + pub block: Block<'gcc>, stack_var_count: Cell<usize>, } impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { - fn with_cx(cx: &'a CodegenCx<'gcc, 'tcx>) -> Self { + fn with_cx(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Self { Builder { cx, - block: None, + block, stack_var_count: Cell::new(0), } } fn atomic_extremum(&mut self, operation: ExtremumOperation, dst: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering) -> RValue<'gcc> { - let size = self.cx.int_width(src.get_type()) / 8; + let size = src.get_type().get_size(); let func = self.current_func(); @@ -114,10 +115,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let after_block = func.new_block("after_while"); self.llbb().end_with_jump(None, while_block); - // NOTE: since jumps were added and compare_exchange doesn't expect this, the current blocks in the + // NOTE: since jumps were added and compare_exchange doesn't expect this, the current block in the // state need to be updated. - self.block = Some(while_block); - *self.cx.current_block.borrow_mut() = Some(while_block); + self.switch_to_block(while_block); let comparison_operator = match operation { @@ -132,17 +132,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { while_block.end_with_conditional(None, cond, while_block, after_block); - // NOTE: since jumps were added in a place rustc does not expect, the current blocks in the + // NOTE: since jumps were added in a place rustc does not expect, the current block in the // state need to be updated. - self.block = Some(after_block); - *self.cx.current_block.borrow_mut() = Some(after_block); + self.switch_to_block(after_block); return_value.to_rvalue() } fn compare_exchange(&self, dst: RValue<'gcc>, cmp: LValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> RValue<'gcc> { - let size = self.cx.int_width(src.get_type()); - let compare_exchange = self.context.get_builtin_function(&format!("__atomic_compare_exchange_{}", size / 8)); + let size = src.get_type().get_size(); + let compare_exchange = self.context.get_builtin_function(&format!("__atomic_compare_exchange_{}", size)); let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc()); let failure_order = self.context.new_rvalue_from_int(self.i32_type, failure_order.to_gcc()); let weak = self.context.new_rvalue_from_int(self.bool_type, weak as i32); @@ -209,6 +208,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { param_types.push(param); } + let mut on_stack_param_indices = FxHashSet::default(); + if let Some(indices) = self.on_stack_params.borrow().get(&gcc_func) { + on_stack_param_indices = indices.clone(); + } + if all_args_match { return Cow::Borrowed(args); } @@ -217,10 +221,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { .into_iter() .zip(args.iter()) .enumerate() - .map(|(_i, (expected_ty, &actual_val))| { + .map(|(index, (expected_ty, &actual_val))| { let actual_ty = actual_val.get_type(); if expected_ty != actual_ty { - self.bitcast(actual_val, expected_ty) + if on_stack_param_indices.contains(&index) { + actual_val.dereference(None).to_rvalue() + } + else { + self.bitcast(actual_val, expected_ty) + } } else { actual_val @@ -245,7 +254,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } pub fn current_func(&self) -> Function<'gcc> { - self.block.expect("block").get_function() + self.block.get_function() } fn function_call(&mut self, func: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> { @@ -256,17 +265,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). let return_type = func.get_return_type(); - let current_block = self.current_block.borrow().expect("block"); let void_type = self.context.new_type::<()>(); - let current_func = current_block.get_function(); + let current_func = self.block.get_function(); if return_type != void_type { unsafe { RETURN_VALUE_COUNT += 1 }; let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT })); - current_block.add_assignment(None, result, self.cx.context.new_call(None, func, &args)); + self.block.add_assignment(None, result, self.cx.context.new_call(None, func, &args)); result.to_rvalue() } else { - current_block.add_eval(None, self.cx.context.new_call(None, func, &args)); + self.block.add_eval(None, self.cx.context.new_call(None, func, &args)); // Return dummy value when not having return value. self.context.new_rvalue_from_long(self.isize_type, 0) } @@ -279,9 +287,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // That's why we assign the result to a local or call add_eval(). let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr"); let mut return_type = gcc_func.get_return_type(); - let current_block = self.current_block.borrow().expect("block"); let void_type = self.context.new_type::<()>(); - let current_func = current_block.get_function(); + let current_func = self.block.get_function(); // FIXME(antoyo): As a temporary workaround for unsupported LLVM intrinsics. if gcc_func.get_param_count() == 0 && format!("{:?}", func_ptr) == "__builtin_ia32_pmovmskb128" { @@ -290,35 +297,34 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { if return_type != void_type { unsafe { RETURN_VALUE_COUNT += 1 }; - let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT })); - current_block.add_assignment(None, result, self.cx.context.new_call_through_ptr(None, func_ptr, &args)); + let result = current_func.new_local(None, return_type, &format!("ptrReturnValue{}", unsafe { RETURN_VALUE_COUNT })); + self.block.add_assignment(None, result, self.cx.context.new_call_through_ptr(None, func_ptr, &args)); result.to_rvalue() } else { if gcc_func.get_param_count() == 0 { // FIXME(antoyo): As a temporary workaround for unsupported LLVM intrinsics. - current_block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &[])); + self.block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &[])); } else { - current_block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &args)); + self.block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &args)); } // Return dummy value when not having return value. let result = current_func.new_local(None, self.isize_type, "dummyValueThatShouldNeverBeUsed"); - current_block.add_assignment(None, result, self.context.new_rvalue_from_long(self.isize_type, 0)); + self.block.add_assignment(None, result, self.context.new_rvalue_from_long(self.isize_type, 0)); result.to_rvalue() } } - pub fn overflow_call(&mut self, func: Function<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> { + pub fn overflow_call(&self, func: Function<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> { // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local. let return_type = self.context.new_type::<bool>(); - let current_block = self.current_block.borrow().expect("block"); - let current_func = current_block.get_function(); + let current_func = self.block.get_function(); // TODO(antoyo): return the new_call() directly? Since the overflow function has no side-effects. unsafe { RETURN_VALUE_COUNT += 1 }; - let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT })); - current_block.add_assignment(None, result, self.cx.context.new_call(None, func, &args)); + let result = current_func.new_local(None, return_type, &format!("overflowReturnValue{}", unsafe { RETURN_VALUE_COUNT })); + self.block.add_assignment(None, result, self.cx.context.new_call(None, func, &args)); result.to_rvalue() } } @@ -384,14 +390,11 @@ impl<'gcc, 'tcx> BackendTypes for Builder<'_, 'gcc, 'tcx> { impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Self { - let mut bx = Builder::with_cx(cx); - *cx.current_block.borrow_mut() = Some(block); - bx.block = Some(block); - bx + Builder::with_cx(cx, block) } fn llbb(&self) -> Block<'gcc> { - self.block.expect("block") + self.block } fn append_block(cx: &'a CodegenCx<'gcc, 'tcx>, func: RValue<'gcc>, name: &str) -> Block<'gcc> { @@ -405,8 +408,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn switch_to_block(&mut self, block: Self::BasicBlock) { - *self.cx.current_block.borrow_mut() = Some(block); - self.block = Some(block); + self.block = block; } fn ret_void(&mut self) { @@ -441,50 +443,42 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let on_val = self.const_uint_big(typ, on_val); gcc_cases.push(self.context.new_case(on_val, on_val, dest)); } - self.block.expect("block").end_with_switch(None, value, default_block, &gcc_cases); + self.block.end_with_switch(None, value, default_block, &gcc_cases); } - fn invoke(&mut self, _typ: Type<'gcc>, _func: RValue<'gcc>, _args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> { - let condition = self.context.new_rvalue_from_int(self.bool_type, 0); + fn invoke(&mut self, typ: Type<'gcc>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> { + // TODO(bjorn3): Properly implement unwinding. + let call_site = self.call(typ, func, args, None); + let condition = self.context.new_rvalue_from_int(self.bool_type, 1); self.llbb().end_with_conditional(None, condition, then, catch); - self.context.new_rvalue_from_int(self.int_type, 0) - - // TODO(antoyo) + call_site } fn unreachable(&mut self) { let func = self.context.get_builtin_function("__builtin_unreachable"); - let block = self.block.expect("block"); - block.add_eval(None, self.context.new_call(None, func, &[])); - let return_type = block.get_function().get_return_type(); + self.block.add_eval(None, self.context.new_call(None, func, &[])); + let return_type = self.block.get_function().get_return_type(); let void_type = self.context.new_type::<()>(); if return_type == void_type { - block.end_with_void_return(None) + self.block.end_with_void_return(None) } else { let return_value = self.current_func() .new_local(None, return_type, "unreachableReturn"); - block.end_with_return(None, return_value) + self.block.end_with_return(None, return_value) } } - fn add(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { - // FIXME(antoyo): this should not be required. - if format!("{:?}", a.get_type()) != format!("{:?}", b.get_type()) { - b = self.context.new_cast(None, b, a.get_type()); - } - a + b + fn add(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + self.gcc_add(a, b) } fn fadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { a + b } - fn sub(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { - if a.get_type() != b.get_type() { - b = self.context.new_cast(None, b, a.get_type()); - } - a - b + fn sub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + self.gcc_sub(a, b) } fn fsub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -492,7 +486,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn mul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - a * b + self.gcc_mul(a, b) } fn fmul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -500,8 +494,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn udiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - // TODO(antoyo): convert the arguments to unsigned? - a / b + self.gcc_udiv(a, b) } fn exactudiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -511,8 +504,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn sdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - // TODO(antoyo): convert the arguments to signed? - a / b + self.gcc_sdiv(a, b) } fn exactsdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -529,11 +521,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn urem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - a % b + self.gcc_urem(a, b) } fn srem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - a % b + self.gcc_srem(a, b) } fn frem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -549,81 +541,33 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn shl(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by an unsigned number. - let a_type = a.get_type(); - let b_type = b.get_type(); - if a_type.is_unsigned(self) && b_type.is_signed(self) { - let a = self.context.new_cast(None, a, b_type); - let result = a << b; - self.context.new_cast(None, result, a_type) - } - else if a_type.is_signed(self) && b_type.is_unsigned(self) { - let b = self.context.new_cast(None, b, a_type); - a << b - } - else { - a << b - } + self.gcc_shl(a, b) } fn lshr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by an unsigned number. - // TODO(antoyo): cast to unsigned to do a logical shift if that does not work. - let a_type = a.get_type(); - let b_type = b.get_type(); - if a_type.is_unsigned(self) && b_type.is_signed(self) { - let a = self.context.new_cast(None, a, b_type); - let result = a >> b; - self.context.new_cast(None, result, a_type) - } - else if a_type.is_signed(self) && b_type.is_unsigned(self) { - let b = self.context.new_cast(None, b, a_type); - a >> b - } - else { - a >> b - } + self.gcc_lshr(a, b) } fn ashr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { // TODO(antoyo): check whether behavior is an arithmetic shift for >> . - // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by an unsigned number. - let a_type = a.get_type(); - let b_type = b.get_type(); - if a_type.is_unsigned(self) && b_type.is_signed(self) { - let a = self.context.new_cast(None, a, b_type); - let result = a >> b; - self.context.new_cast(None, result, a_type) - } - else if a_type.is_signed(self) && b_type.is_unsigned(self) { - let b = self.context.new_cast(None, b, a_type); - a >> b - } - else { - a >> b - } + // It seems to be if the value is signed. + self.gcc_lshr(a, b) } - fn and(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { - if a.get_type() != b.get_type() { - b = self.context.new_cast(None, b, a.get_type()); - } - a & b + fn and(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + self.gcc_and(a, b) } - fn or(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { - if a.get_type() != b.get_type() { - b = self.context.new_cast(None, b, a.get_type()); - } - a | b + fn or(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + self.cx.gcc_or(a, b) } fn xor(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - a ^ b + self.gcc_xor(a, b) } fn neg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { - self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a) + self.gcc_neg(a) } fn fneg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { @@ -631,14 +575,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn not(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { - let operation = - if a.get_type().is_bool() { - UnaryOp::LogicalNegate - } - else { - UnaryOp::BitwiseNegate - }; - self.cx.context.new_unary_op(None, operation, a.get_type(), a) + self.gcc_not(a) } fn unchecked_sadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -646,7 +583,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn unchecked_uadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - a + b + self.gcc_add(a, b) } fn unchecked_ssub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -655,7 +592,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn unchecked_usub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { // TODO(antoyo): should generate poison value? - a - b + self.gcc_sub(a, b) } fn unchecked_smul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -687,76 +624,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn checked_binop(&mut self, oop: OverflowOp, typ: Ty<'_>, lhs: Self::Value, rhs: Self::Value) -> (Self::Value, Self::Value) { - use rustc_middle::ty::{Int, IntTy::*, Uint, UintTy::*}; - - let new_kind = - match typ.kind() { - Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.pointer_width)), - Uint(t @ Usize) => Uint(t.normalize(self.tcx.sess.target.pointer_width)), - t @ (Uint(_) | Int(_)) => t.clone(), - _ => panic!("tried to get overflow intrinsic for op applied to non-int type"), - }; - - // TODO(antoyo): remove duplication with intrinsic? - let name = - match oop { - OverflowOp::Add => - match new_kind { - Int(I8) => "__builtin_add_overflow", - Int(I16) => "__builtin_add_overflow", - Int(I32) => "__builtin_sadd_overflow", - Int(I64) => "__builtin_saddll_overflow", - Int(I128) => "__builtin_add_overflow", - - Uint(U8) => "__builtin_add_overflow", - Uint(U16) => "__builtin_add_overflow", - Uint(U32) => "__builtin_uadd_overflow", - Uint(U64) => "__builtin_uaddll_overflow", - Uint(U128) => "__builtin_add_overflow", - - _ => unreachable!(), - }, - OverflowOp::Sub => - match new_kind { - Int(I8) => "__builtin_sub_overflow", - Int(I16) => "__builtin_sub_overflow", - Int(I32) => "__builtin_ssub_overflow", - Int(I64) => "__builtin_ssubll_overflow", - Int(I128) => "__builtin_sub_overflow", - - Uint(U8) => "__builtin_sub_overflow", - Uint(U16) => "__builtin_sub_overflow", - Uint(U32) => "__builtin_usub_overflow", - Uint(U64) => "__builtin_usubll_overflow", - Uint(U128) => "__builtin_sub_overflow", - - _ => unreachable!(), - }, - OverflowOp::Mul => - match new_kind { - Int(I8) => "__builtin_mul_overflow", - Int(I16) => "__builtin_mul_overflow", - Int(I32) => "__builtin_smul_overflow", - Int(I64) => "__builtin_smulll_overflow", - Int(I128) => "__builtin_mul_overflow", - - Uint(U8) => "__builtin_mul_overflow", - Uint(U16) => "__builtin_mul_overflow", - Uint(U32) => "__builtin_umul_overflow", - Uint(U64) => "__builtin_umulll_overflow", - Uint(U128) => "__builtin_mul_overflow", - - _ => unreachable!(), - }, - }; - - let intrinsic = self.context.get_builtin_function(&name); - let res = self.current_func() - // TODO(antoyo): is it correct to use rhs type instead of the parameter typ? - .new_local(None, rhs.get_type(), "binopResult") - .get_address(None); - let overflow = self.overflow_call(intrinsic, &[lhs, rhs, res], None); - (res.dereference(None).to_rvalue(), overflow) + self.gcc_checked_binop(oop, typ, lhs, rhs) } fn alloca(&mut self, ty: Type<'gcc>, align: Align) -> RValue<'gcc> { @@ -1006,7 +874,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { /* Casts */ fn trunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { // TODO(antoyo): check that it indeed truncate the value. - self.context.new_cast(None, value, dest_ty) + self.gcc_int_cast(value, dest_ty) } fn sext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { @@ -1019,19 +887,19 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn fptoui(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { - self.context.new_cast(None, value, dest_ty) + self.gcc_float_to_uint_cast(value, dest_ty) } fn fptosi(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { - self.context.new_cast(None, value, dest_ty) + self.gcc_float_to_int_cast(value, dest_ty) } fn uitofp(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { - self.context.new_cast(None, value, dest_ty) + self.gcc_uint_to_float_cast(value, dest_ty) } fn sitofp(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { - self.context.new_cast(None, value, dest_ty) + self.gcc_int_to_float_cast(value, dest_ty) } fn fptrunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { @@ -1044,11 +912,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn ptrtoint(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { - self.cx.ptrtoint(self.block.expect("block"), value, dest_ty) + let usize_value = self.cx.const_bitcast(value, self.cx.type_isize()); + self.intcast(usize_value, dest_ty, false) } fn inttoptr(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { - self.cx.inttoptr(self.block.expect("block"), value, dest_ty) + let usize_value = self.intcast(value, self.cx.type_isize(), false); + self.cx.const_bitcast(usize_value, dest_ty) } fn bitcast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { @@ -1057,7 +927,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn intcast(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>, _is_signed: bool) -> RValue<'gcc> { // NOTE: is_signed is for value, not dest_typ. - self.cx.context.new_cast(None, value, dest_typ) + self.gcc_int_cast(value, dest_typ) } fn pointercast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { @@ -1078,21 +948,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } /* Comparisons */ - fn icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> { - let left_type = lhs.get_type(); - let right_type = rhs.get_type(); - if left_type != right_type { - // NOTE: because libgccjit cannot compare function pointers. - if left_type.dyncast_function_ptr_type().is_some() && right_type.dyncast_function_ptr_type().is_some() { - lhs = self.context.new_cast(None, lhs, self.usize_type.make_pointer()); - rhs = self.context.new_cast(None, rhs, self.usize_type.make_pointer()); - } - // NOTE: hack because we try to cast a vector type to the same vector type. - else if format!("{:?}", left_type) != format!("{:?}", right_type) { - rhs = self.context.new_cast(None, rhs, left_type); - } - } - self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs) + fn icmp(&mut self, op: IntPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { + self.gcc_icmp(op, lhs, rhs) } fn fcmp(&mut self, op: RealPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { @@ -1100,22 +957,15 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } /* Miscellaneous instructions */ - fn memcpy(&mut self, dst: RValue<'gcc>, dst_align: Align, src: RValue<'gcc>, src_align: Align, size: RValue<'gcc>, flags: MemFlags) { - if flags.contains(MemFlags::NONTEMPORAL) { - // HACK(nox): This is inefficient but there is no nontemporal memcpy. - let val = self.load(src.get_type(), src, src_align); - let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val))); - self.store_with_flags(val, ptr, dst_align, flags); - return; - } + fn memcpy(&mut self, dst: RValue<'gcc>, _dst_align: Align, src: RValue<'gcc>, _src_align: Align, size: RValue<'gcc>, flags: MemFlags) { + assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memcpy not supported"); let size = self.intcast(size, self.type_size_t(), false); let _is_volatile = flags.contains(MemFlags::VOLATILE); let dst = self.pointercast(dst, self.type_i8p()); let src = self.pointercast(src, self.type_ptr_to(self.type_void())); let memcpy = self.context.get_builtin_function("memcpy"); - let block = self.block.expect("block"); // TODO(antoyo): handle aligns and is_volatile. - block.add_eval(None, self.context.new_call(None, memcpy, &[dst, src, size])); + self.block.add_eval(None, self.context.new_call(None, memcpy, &[dst, src, size])); } fn memmove(&mut self, dst: RValue<'gcc>, dst_align: Align, src: RValue<'gcc>, src_align: Align, size: RValue<'gcc>, flags: MemFlags) { @@ -1132,20 +982,18 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let src = self.pointercast(src, self.type_ptr_to(self.type_void())); let memmove = self.context.get_builtin_function("memmove"); - let block = self.block.expect("block"); // TODO(antoyo): handle is_volatile. - block.add_eval(None, self.context.new_call(None, memmove, &[dst, src, size])); + self.block.add_eval(None, self.context.new_call(None, memmove, &[dst, src, size])); } fn memset(&mut self, ptr: RValue<'gcc>, fill_byte: RValue<'gcc>, size: RValue<'gcc>, _align: Align, flags: MemFlags) { let _is_volatile = flags.contains(MemFlags::VOLATILE); let ptr = self.pointercast(ptr, self.type_i8p()); let memset = self.context.get_builtin_function("memset"); - let block = self.block.expect("block"); // TODO(antoyo): handle align and is_volatile. let fill_byte = self.context.new_cast(None, fill_byte, self.i32_type); let size = self.intcast(size, self.type_size_t(), false); - block.add_eval(None, self.context.new_call(None, memset, &[ptr, fill_byte, size])); + self.block.add_eval(None, self.context.new_call(None, memset, &[ptr, fill_byte, size])); } fn select(&mut self, cond: RValue<'gcc>, then_val: RValue<'gcc>, mut else_val: RValue<'gcc>) -> RValue<'gcc> { @@ -1159,16 +1007,15 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { then_block.add_assignment(None, variable, then_val); then_block.end_with_jump(None, after_block); - if then_val.get_type() != else_val.get_type() { + if !then_val.get_type().is_compatible_with(else_val.get_type()) { else_val = self.context.new_cast(None, else_val, then_val.get_type()); } else_block.add_assignment(None, variable, else_val); else_block.end_with_jump(None, after_block); - // NOTE: since jumps were added in a place rustc does not expect, the current blocks in the + // NOTE: since jumps were added in a place rustc does not expect, the current block in the // state need to be updated. - self.block = Some(after_block); - *self.cx.current_block.borrow_mut() = Some(after_block); + self.switch_to_block(after_block); variable.to_rvalue() } @@ -1264,7 +1111,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn cleanup_landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>) -> RValue<'gcc> { - let field1 = self.context.new_field(None, self.u8_type, "landing_pad_field_1"); + let field1 = self.context.new_field(None, self.u8_type.make_pointer(), "landing_pad_field_1"); let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_1"); let struct_type = self.context.new_struct_type(None, "landing_pad", &[field1, field2]); self.current_func().new_local(None, struct_type.as_type(), "landing_pad") @@ -1275,7 +1122,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn resume(&mut self, _exn: RValue<'gcc>) { - unimplemented!(); + // TODO(bjorn3): Properly implement unwinding. + self.unreachable(); } fn cleanup_pad(&mut self, _parent: Option<RValue<'gcc>>, _args: &[RValue<'gcc>]) -> Funclet { @@ -1322,7 +1170,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn atomic_rmw(&mut self, op: AtomicRmwBinOp, dst: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering) -> RValue<'gcc> { - let size = self.cx.int_width(src.get_type()) / 8; + let size = src.get_type().get_size(); let name = match op { AtomicRmwBinOp::AtomicXchg => format!("__atomic_exchange_{}", size), @@ -1396,7 +1244,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // Fix the code in codegen_ssa::base::from_immediate. return value; } - self.context.new_cast(None, value, dest_typ) + self.gcc_int_cast(value, dest_typ) } fn cx(&self) -> &CodegenCx<'gcc, 'tcx> { @@ -1404,7 +1252,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn do_not_inline(&mut self, _llret: RValue<'gcc>) { - unimplemented!(); + // FIMXE(bjorn3): implement } fn set_span(&mut self, _span: Span) {} @@ -1470,7 +1318,7 @@ impl<'tcx> HasTargetSpec for Builder<'_, '_, 'tcx> { } } -trait ToGccComp { +pub trait ToGccComp { fn to_gcc_comparison(&self) -> ComparisonOp; } diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index d1ff15367c3..61709dd92de 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -1,7 +1,5 @@ -use std::convert::TryFrom; - use gccjit::LValue; -use gccjit::{Block, CType, RValue, Type, ToRValue}; +use gccjit::{RValue, Type, ToRValue}; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{ BaseTypeMethods, @@ -35,27 +33,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global // TODO(antoyo): set linkage. } - - pub fn inttoptr(&self, block: Block<'gcc>, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { - let func = block.get_function(); - let local = func.new_local(None, value.get_type(), "intLocal"); - block.add_assignment(None, local, value); - let value_address = local.get_address(None); - - let ptr = self.context.new_cast(None, value_address, dest_ty.make_pointer()); - ptr.dereference(None).to_rvalue() - } - - pub fn ptrtoint(&self, block: Block<'gcc>, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { - // TODO(antoyo): when libgccjit allow casting from pointer to int, remove this. - let func = block.get_function(); - let local = func.new_local(None, value.get_type(), "ptrLocal"); - block.add_assignment(None, local, value); - let ptr_address = local.get_address(None); - - let ptr = self.context.new_cast(None, ptr_address, dest_ty.make_pointer()); - ptr.dereference(None).to_rvalue() - } } pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> { @@ -99,29 +76,15 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn const_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> { - self.context.new_rvalue_from_long(typ, i64::try_from(int).expect("i64::try_from")) + self.gcc_int(typ, int) } fn const_uint(&self, typ: Type<'gcc>, int: u64) -> RValue<'gcc> { - self.context.new_rvalue_from_long(typ, u64::try_from(int).expect("u64::try_from") as i64) + self.gcc_uint(typ, int) } fn const_uint_big(&self, typ: Type<'gcc>, num: u128) -> RValue<'gcc> { - if num >> 64 != 0 { - // FIXME(antoyo): use a new function new_rvalue_from_unsigned_long()? - let low = self.context.new_rvalue_from_long(self.u64_type, num as u64 as i64); - let high = self.context.new_rvalue_from_long(typ, (num >> 64) as u64 as i64); - - let sixty_four = self.context.new_rvalue_from_long(typ, 64); - (high << sixty_four) | self.context.new_cast(None, low, typ) - } - else if typ.is_i128(self) { - let num = self.context.new_rvalue_from_long(self.u64_type, num as u64 as i64); - self.context.new_cast(None, num, typ) - } - else { - self.context.new_rvalue_from_long(typ, num as u64 as i64) - } + self.gcc_uint_big(typ, num) } fn const_bool(&self, val: bool) -> RValue<'gcc> { @@ -210,11 +173,8 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } let value = self.const_uint_big(self.type_ix(bitsize), data); - if layout.value == Pointer { - self.inttoptr(self.current_block.borrow().expect("block"), value, ty) - } else { - self.const_bitcast(value, ty) - } + // TODO(bjorn3): assert size is correct + self.const_bitcast(value, ty) } Scalar::Ptr(ptr, _size) => { let (alloc_id, offset) = ptr.into_parts(); @@ -418,11 +378,11 @@ impl<'gcc, 'tcx> TypeReflection<'gcc, 'tcx> for Type<'gcc> { } fn is_i128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.unqualified() == cx.context.new_c_type(CType::Int128t) + self.unqualified() == cx.i128_type.unqualified() } fn is_u128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.unqualified() == cx.context.new_c_type(CType::UInt128t) + self.unqualified() == cx.u128_type.unqualified() } fn is_f32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index d53b15159fa..de52f3ea225 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -1,4 +1,4 @@ -use gccjit::{LValue, RValue, ToRValue, Type}; +use gccjit::{GlobalKind, LValue, RValue, ToRValue, Type}; use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, DerivedTypeMethods, StaticMethods}; use rustc_hir as hir; use rustc_hir::Node; @@ -35,7 +35,12 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { // following: for (value, variable) in &*self.const_globals.borrow() { if format!("{:?}", value) == format!("{:?}", cv) { - // TODO(antoyo): upgrade alignment. + if let Some(global_variable) = self.global_lvalues.borrow().get(variable) { + let alignment = align.bits() as i32; + if alignment > global_variable.get_alignment() { + global_variable.set_alignment(alignment); + } + } return *variable; } } @@ -165,11 +170,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { match kind { Some(kind) if !self.tcx.sess.fewer_names() => { let name = self.generate_local_symbol_name(kind); - // TODO(antoyo): check if it's okay that TLS is off here. - // TODO(antoyo): check if it's okay that link_section is None here. + // TODO(antoyo): check if it's okay that no link_section is set. // TODO(antoyo): set alignment here as well. - let global = self.define_global(&name[..], self.val_ty(cv), false, None); - // TODO(antoyo): set linkage. + let global = self.declare_private_global(&name[..], self.val_ty(cv)); global } _ => { @@ -178,11 +181,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global }, }; - // FIXME(antoyo): I think the name coming from generate_local_symbol_name() above cannot be used - // globally. global.global_set_initializer_rvalue(cv); // TODO(antoyo): set unnamed address. - global.get_address(None) + let rvalue = global.get_address(None); + self.global_lvalues.borrow_mut().insert(rvalue, global); + rvalue } pub fn get_static(&self, def_id: DefId) -> LValue<'gcc> { @@ -218,7 +221,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } let is_tls = fn_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); - let global = self.declare_global(&sym, llty, is_tls, fn_attrs.link_section); + let global = self.declare_global( + &sym, + llty, + GlobalKind::Exported, + is_tls, + fn_attrs.link_section, + ); if !self.tcx.is_reachable_non_generic(def_id) { // TODO(antoyo): set visibility. @@ -390,6 +399,6 @@ fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &Codeg // don't do this then linker errors can be generated where the linker // complains that one object files has a thread local version of the // symbol and another one doesn't. - cx.declare_global(&sym, llty, is_tls, attrs.link_section) + cx.declare_global(&sym, llty, GlobalKind::Imported, is_tls, attrs.link_section) } } diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 6c1dce969f0..5e5b9e7e9b1 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -1,6 +1,6 @@ use std::cell::{Cell, RefCell}; -use gccjit::{Block, CType, Context, Function, FunctionType, LValue, RValue, Struct, Type}; +use gccjit::{Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, RValue, Struct, Type}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::traits::{ BackendTypes, @@ -18,7 +18,6 @@ use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDat use rustc_target::spec::{HasTargetSpec, Target, TlsModel}; use crate::callee::get_fn; -use crate::declare::mangle_name; #[derive(Clone)] pub struct FuncSig<'gcc> { @@ -31,8 +30,7 @@ pub struct CodegenCx<'gcc, 'tcx> { pub codegen_unit: &'tcx CodegenUnit<'tcx>, pub context: &'gcc Context<'gcc>, - // TODO(antoyo): First set it to a dummy block to avoid using Option? - pub current_block: RefCell<Option<Block<'gcc>>>, + // TODO(bjorn3): Can this field be removed? pub current_func: RefCell<Option<Function<'gcc>>>, pub normal_function_addresses: RefCell<FxHashSet<RValue<'gcc>>>, @@ -62,6 +60,8 @@ pub struct CodegenCx<'gcc, 'tcx> { pub ulonglong_type: Type<'gcc>, pub sizet_type: Type<'gcc>, + pub supports_128bit_integers: bool, + pub float_type: Type<'gcc>, pub double_type: Type<'gcc>, @@ -81,9 +81,19 @@ pub struct CodegenCx<'gcc, 'tcx> { /// Cache generated vtables pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>, + // TODO(antoyo): improve the SSA API to not require those. + // Mapping from function pointer type to indexes of on stack parameters. + pub on_stack_params: RefCell<FxHashMap<FunctionPtrType<'gcc>, FxHashSet<usize>>>, + // Mapping from function to indexes of on stack parameters. + pub on_stack_function_params: RefCell<FxHashMap<Function<'gcc>, FxHashSet<usize>>>, + /// Cache of emitted const globals (value -> global) pub const_globals: RefCell<FxHashMap<RValue<'gcc>, RValue<'gcc>>>, + /// Map from the address of a global variable (rvalue) to the global variable itself (lvalue). + /// TODO(antoyo): remove when the rustc API is fixed. + pub global_lvalues: RefCell<FxHashMap<RValue<'gcc>, LValue<'gcc>>>, + /// Cache of constant strings, pub const_str_cache: RefCell<FxHashMap<Symbol, LValue<'gcc>>>, @@ -92,7 +102,6 @@ pub struct CodegenCx<'gcc, 'tcx> { /// A counter that is used for generating local symbol names local_gen_sym_counter: Cell<usize>, - pub global_gen_sym_counter: Cell<usize>, eh_personality: Cell<Option<RValue<'gcc>>>, @@ -107,22 +116,29 @@ pub struct CodegenCx<'gcc, 'tcx> { } impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { - pub fn new(context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + pub fn new(context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>, tcx: TyCtxt<'tcx>, supports_128bit_integers: bool) -> Self { let check_overflow = tcx.sess.overflow_checks(); - // TODO(antoyo): fix this mess. libgccjit seems to return random type when using new_int_type(). - let isize_type = context.new_c_type(CType::LongLong); - let usize_type = context.new_c_type(CType::ULongLong); - let bool_type = context.new_type::<bool>(); - let i8_type = context.new_type::<i8>(); - let i16_type = context.new_type::<i16>(); - let i32_type = context.new_type::<i32>(); - let i64_type = context.new_c_type(CType::LongLong); - let i128_type = context.new_c_type(CType::Int128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded? - let u8_type = context.new_type::<u8>(); - let u16_type = context.new_type::<u16>(); - let u32_type = context.new_type::<u32>(); - let u64_type = context.new_c_type(CType::ULongLong); - let u128_type = context.new_c_type(CType::UInt128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded? + + let i8_type = context.new_c_type(CType::Int8t); + let i16_type = context.new_c_type(CType::Int16t); + let i32_type = context.new_c_type(CType::Int32t); + let i64_type = context.new_c_type(CType::Int64t); + let u8_type = context.new_c_type(CType::UInt8t); + let u16_type = context.new_c_type(CType::UInt16t); + let u32_type = context.new_c_type(CType::UInt32t); + let u64_type = context.new_c_type(CType::UInt64t); + + let (i128_type, u128_type) = + if supports_128bit_integers { + let i128_type = context.new_c_type(CType::Int128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded?; + let u128_type = context.new_c_type(CType::UInt128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded?; + (i128_type, u128_type) + } + else { + let i128_type = context.new_array_type(None, i64_type, 2); + let u128_type = context.new_array_type(None, u64_type, 2); + (i128_type, u128_type) + }; let tls_model = to_gcc_tls_mode(tcx.sess.tls_model()); @@ -136,8 +152,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let ulonglong_type = context.new_c_type(CType::ULongLong); let sizet_type = context.new_c_type(CType::SizeT); - assert_eq!(isize_type, i64_type); - assert_eq!(usize_type, u64_type); + let isize_type = context.new_c_type(CType::LongLong); + let usize_type = context.new_c_type(CType::ULongLong); + let bool_type = context.new_type::<bool>(); + + // TODO(antoyo): only have those assertions on x86_64. + assert_eq!(isize_type.get_size(), i64_type.get_size()); + assert_eq!(usize_type.get_size(), u64_type.get_size()); let mut functions = FxHashMap::default(); let builtins = [ @@ -160,7 +181,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { check_overflow, codegen_unit, context, - current_block: RefCell::new(None), current_func: RefCell::new(None), normal_function_addresses: Default::default(), functions: RefCell::new(functions), @@ -187,14 +207,19 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { ulonglong_type, sizet_type, + supports_128bit_integers, + float_type, double_type, linkage: Cell::new(FunctionType::Internal), instances: Default::default(), function_instances: Default::default(), + on_stack_params: Default::default(), + on_stack_function_params: Default::default(), vtables: Default::default(), const_globals: Default::default(), + global_lvalues: Default::default(), const_str_cache: Default::default(), globals: Default::default(), scalar_types: Default::default(), @@ -203,7 +228,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { struct_types: Default::default(), types_with_fields_to_set: Default::default(), local_gen_sym_counter: Cell::new(0), - global_gen_sym_counter: Cell::new(0), eh_personality: Cell::new(None), pointee_infos: Default::default(), structs_as_pointer: Default::default(), @@ -217,6 +241,41 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { function } + pub fn is_native_int_type(&self, typ: Type<'gcc>) -> bool { + let types = [ + self.u8_type, + self.u16_type, + self.u32_type, + self.u64_type, + self.i8_type, + self.i16_type, + self.i32_type, + self.i64_type, + ]; + + for native_type in types { + if native_type.is_compatible_with(typ) { + return true; + } + } + + self.supports_128bit_integers && + (self.u128_type.is_compatible_with(typ) || self.i128_type.is_compatible_with(typ)) + } + + pub fn is_non_native_int_type(&self, typ: Type<'gcc>) -> bool { + !self.supports_128bit_integers && + (self.u128_type.is_compatible_with(typ) || self.i128_type.is_compatible_with(typ)) + } + + pub fn is_native_int_type_or_bool(&self, typ: Type<'gcc>) -> bool { + self.is_native_int_type(typ) || typ == self.bool_type + } + + pub fn is_int_type_or_bool(&self, typ: Type<'gcc>) -> bool { + self.is_native_int_type(typ) || self.is_non_native_int_type(typ) || typ == self.bool_type + } + pub fn sess(&self) -> &Session { &self.tcx.sess } @@ -450,11 +509,6 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { } } -pub fn unit_name<'tcx>(codegen_unit: &CodegenUnit<'tcx>) -> String { - let name = &codegen_unit.name().to_string(); - mangle_name(&name.replace('-', "_")) -} - fn to_gcc_tls_mode(tls_model: TlsModel) -> gccjit::TlsModel { match tls_model { TlsModel::GeneralDynamic => gccjit::TlsModel::GlobalDynamic, diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs index dbee505a497..43017376916 100644 --- a/compiler/rustc_codegen_gcc/src/declare.rs +++ b/compiler/rustc_codegen_gcc/src/declare.rs @@ -5,7 +5,7 @@ use rustc_span::Symbol; use rustc_target::abi::call::FnAbi; use crate::abi::FnAbiGccExt; -use crate::context::{CodegenCx, unit_name}; +use crate::context::CodegenCx; use crate::intrinsic::llvm; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -22,15 +22,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global } else { - self.declare_global(name, ty, is_tls, link_section) + self.declare_global(name, ty, GlobalKind::Exported, is_tls, link_section) } } pub fn declare_unnamed_global(&self, ty: Type<'gcc>) -> LValue<'gcc> { - let index = self.global_gen_sym_counter.get(); - self.global_gen_sym_counter.set(index + 1); - let name = format!("global_{}_{}", index, unit_name(&self.codegen_unit)); - self.context.new_global(None, GlobalKind::Exported, ty, &name) + let name = self.generate_local_symbol_name("global"); + self.context.new_global(None, GlobalKind::Internal, ty, &name) } pub fn declare_global_with_linkage(&self, name: &str, ty: Type<'gcc>, linkage: GlobalKind) -> LValue<'gcc> { @@ -47,8 +45,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { unsafe { std::mem::transmute(func) } }*/ - pub fn declare_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> { - let global = self.context.new_global(None, GlobalKind::Exported, ty, name); + pub fn declare_global(&self, name: &str, ty: Type<'gcc>, global_kind: GlobalKind, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> { + let global = self.context.new_global(None, global_kind, ty, name); if is_tls { global.set_tls_model(self.tls_model); } @@ -82,8 +80,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> RValue<'gcc> { - let (return_type, params, variadic) = fn_abi.gcc_type(self); + let (return_type, params, variadic, on_stack_param_indices) = fn_abi.gcc_type(self); let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, ¶ms, variadic); + self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices); // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API. unsafe { std::mem::transmute(func) } } diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs new file mode 100644 index 00000000000..c3ed71ff730 --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/int.rs @@ -0,0 +1,730 @@ +//! Module to handle integer operations. +//! This module exists because some integer types are not supported on some gcc platforms, e.g. +//! 128-bit integers on 32-bit platforms and thus require to be handled manually. + +use std::convert::TryFrom; + +use gccjit::{ComparisonOp, FunctionType, RValue, ToRValue, Type, UnaryOp, BinaryOp}; +use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; +use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, BuilderMethods, OverflowOp}; +use rustc_middle::ty::Ty; + +use crate::builder::ToGccComp; +use crate::{builder::Builder, common::{SignType, TypeReflection}, context::CodegenCx}; + +impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { + pub fn gcc_urem(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + // 128-bit unsigned %: __umodti3 + self.multiplicative_operation(BinaryOp::Modulo, "mod", false, a, b) + } + + pub fn gcc_srem(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + // 128-bit signed %: __modti3 + self.multiplicative_operation(BinaryOp::Modulo, "mod", true, a, b) + } + + pub fn gcc_not(&self, a: RValue<'gcc>) -> RValue<'gcc> { + let typ = a.get_type(); + if self.is_native_int_type_or_bool(typ) { + let operation = + if typ.is_bool() { + UnaryOp::LogicalNegate + } + else { + UnaryOp::BitwiseNegate + }; + self.cx.context.new_unary_op(None, operation, typ, a) + } + else { + // TODO(antoyo): use __negdi2 and __negti2 instead? + let element_type = typ.dyncast_array().expect("element type"); + let values = [ + self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.low(a)), + self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.high(a)), + ]; + self.cx.context.new_array_constructor(None, typ, &values) + } + } + + pub fn gcc_neg(&self, a: RValue<'gcc>) -> RValue<'gcc> { + let a_type = a.get_type(); + if self.is_native_int_type(a_type) { + self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a) + } + else { + let param_a = self.context.new_parameter(None, a_type, "a"); + let func = self.context.new_function(None, FunctionType::Extern, a_type, &[param_a], "__negti2", false); + self.context.new_call(None, func, &[a]) + } + } + + pub fn gcc_and(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + self.cx.bitwise_operation(BinaryOp::BitwiseAnd, a, b) + } + + pub fn gcc_lshr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + let a_type = a.get_type(); + let b_type = b.get_type(); + let a_native = self.is_native_int_type(a_type); + let b_native = self.is_native_int_type(b_type); + if a_native && b_native { + // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by a signed number. + // TODO(antoyo): cast to unsigned to do a logical shift if that does not work. + if a_type.is_signed(self) != b_type.is_signed(self) { + let b = self.context.new_cast(None, b, a_type); + a >> b + } + else { + a >> b + } + } + else if a_native && !b_native { + self.gcc_lshr(a, self.gcc_int_cast(b, a_type)) + } + else { + // NOTE: we cannot use the lshr builtin because it's calling hi() (to get the most + // significant half of the number) which uses lshr. + + let native_int_type = a_type.dyncast_array().expect("get element type"); + + let func = self.current_func(); + let then_block = func.new_block("then"); + let else_block = func.new_block("else"); + let after_block = func.new_block("after"); + let b0_block = func.new_block("b0"); + let actual_else_block = func.new_block("actual_else"); + + let result = func.new_local(None, a_type, "shiftResult"); + + let sixty_four = self.gcc_int(native_int_type, 64); + let sixty_three = self.gcc_int(native_int_type, 63); + let zero = self.gcc_zero(native_int_type); + let b = self.gcc_int_cast(b, native_int_type); + let condition = self.gcc_icmp(IntPredicate::IntNE, self.gcc_and(b, sixty_four), zero); + self.llbb().end_with_conditional(None, condition, then_block, else_block); + + // TODO(antoyo): take endianness into account. + let shift_value = self.gcc_sub(b, sixty_four); + let high = self.high(a); + let sign = + if a_type.is_signed(self) { + high >> sixty_three + } + else { + zero + }; + let values = [ + high >> shift_value, + sign, + ]; + let array_value = self.context.new_array_constructor(None, a_type, &values); + then_block.add_assignment(None, result, array_value); + then_block.end_with_jump(None, after_block); + + let condition = self.gcc_icmp(IntPredicate::IntEQ, b, zero); + else_block.end_with_conditional(None, condition, b0_block, actual_else_block); + + b0_block.add_assignment(None, result, a); + b0_block.end_with_jump(None, after_block); + + let shift_value = self.gcc_sub(sixty_four, b); + // NOTE: cast low to its unsigned type in order to perform a logical right shift. + let unsigned_type = native_int_type.to_unsigned(&self.cx); + let casted_low = self.context.new_cast(None, self.low(a), unsigned_type); + let shifted_low = casted_low >> self.context.new_cast(None, b, unsigned_type); + let shifted_low = self.context.new_cast(None, shifted_low, native_int_type); + let values = [ + (high << shift_value) | shifted_low, + high >> b, + ]; + let array_value = self.context.new_array_constructor(None, a_type, &values); + actual_else_block.add_assignment(None, result, array_value); + actual_else_block.end_with_jump(None, after_block); + + // NOTE: since jumps were added in a place rustc does not expect, the current block in the + // state need to be updated. + self.switch_to_block(after_block); + + result.to_rvalue() + } + } + + fn additive_operation(&self, operation: BinaryOp, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { + let a_type = a.get_type(); + let b_type = b.get_type(); + if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) { + if a.get_type() != b.get_type() { + b = self.context.new_cast(None, b, a.get_type()); + } + self.context.new_binary_op(None, operation, a_type, a, b) + } + else { + let signed = a_type.is_compatible_with(self.i128_type); + let func_name = + match (operation, signed) { + (BinaryOp::Plus, true) => "__rust_i128_add", + (BinaryOp::Plus, false) => "__rust_u128_add", + (BinaryOp::Minus, true) => "__rust_i128_sub", + (BinaryOp::Minus, false) => "__rust_u128_sub", + _ => unreachable!("unexpected additive operation {:?}", operation), + }; + let param_a = self.context.new_parameter(None, a_type, "a"); + let param_b = self.context.new_parameter(None, b_type, "b"); + let func = self.context.new_function(None, FunctionType::Extern, a_type, &[param_a, param_b], func_name, false); + self.context.new_call(None, func, &[a, b]) + } + } + + pub fn gcc_add(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + self.additive_operation(BinaryOp::Plus, a, b) + } + + pub fn gcc_mul(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + self.multiplicative_operation(BinaryOp::Mult, "mul", true, a, b) + } + + pub fn gcc_sub(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + self.additive_operation(BinaryOp::Minus, a, b) + } + + fn multiplicative_operation(&self, operation: BinaryOp, operation_name: &str, signed: bool, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + let a_type = a.get_type(); + let b_type = b.get_type(); + if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) { + self.context.new_binary_op(None, operation, a_type, a, b) + } + else { + let sign = + if signed { + "" + } + else { + "u" + }; + let func_name = format!("__{}{}ti3", sign, operation_name); + let param_a = self.context.new_parameter(None, a_type, "a"); + let param_b = self.context.new_parameter(None, b_type, "b"); + let func = self.context.new_function(None, FunctionType::Extern, a_type, &[param_a, param_b], func_name, false); + self.context.new_call(None, func, &[a, b]) + } + } + + pub fn gcc_sdiv(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): check if the types are signed? + // 128-bit, signed: __divti3 + // TODO(antoyo): convert the arguments to signed? + self.multiplicative_operation(BinaryOp::Divide, "div", true, a, b) + } + + pub fn gcc_udiv(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + // 128-bit, unsigned: __udivti3 + self.multiplicative_operation(BinaryOp::Divide, "div", false, a, b) + } + + pub fn gcc_checked_binop(&self, oop: OverflowOp, typ: Ty<'_>, lhs: <Self as BackendTypes>::Value, rhs: <Self as BackendTypes>::Value) -> (<Self as BackendTypes>::Value, <Self as BackendTypes>::Value) { + use rustc_middle::ty::{Int, IntTy::*, Uint, UintTy::*}; + + let new_kind = + match typ.kind() { + Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.pointer_width)), + Uint(t @ Usize) => Uint(t.normalize(self.tcx.sess.target.pointer_width)), + t @ (Uint(_) | Int(_)) => t.clone(), + _ => panic!("tried to get overflow intrinsic for op applied to non-int type"), + }; + + // TODO(antoyo): remove duplication with intrinsic? + let name = + if self.is_native_int_type(lhs.get_type()) { + match oop { + OverflowOp::Add => + match new_kind { + Int(I8) => "__builtin_add_overflow", + Int(I16) => "__builtin_add_overflow", + Int(I32) => "__builtin_sadd_overflow", + Int(I64) => "__builtin_saddll_overflow", + Int(I128) => "__builtin_add_overflow", + + Uint(U8) => "__builtin_add_overflow", + Uint(U16) => "__builtin_add_overflow", + Uint(U32) => "__builtin_uadd_overflow", + Uint(U64) => "__builtin_uaddll_overflow", + Uint(U128) => "__builtin_add_overflow", + + _ => unreachable!(), + }, + OverflowOp::Sub => + match new_kind { + Int(I8) => "__builtin_sub_overflow", + Int(I16) => "__builtin_sub_overflow", + Int(I32) => "__builtin_ssub_overflow", + Int(I64) => "__builtin_ssubll_overflow", + Int(I128) => "__builtin_sub_overflow", + + Uint(U8) => "__builtin_sub_overflow", + Uint(U16) => "__builtin_sub_overflow", + Uint(U32) => "__builtin_usub_overflow", + Uint(U64) => "__builtin_usubll_overflow", + Uint(U128) => "__builtin_sub_overflow", + + _ => unreachable!(), + }, + OverflowOp::Mul => + match new_kind { + Int(I8) => "__builtin_mul_overflow", + Int(I16) => "__builtin_mul_overflow", + Int(I32) => "__builtin_smul_overflow", + Int(I64) => "__builtin_smulll_overflow", + Int(I128) => "__builtin_mul_overflow", + + Uint(U8) => "__builtin_mul_overflow", + Uint(U16) => "__builtin_mul_overflow", + Uint(U32) => "__builtin_umul_overflow", + Uint(U64) => "__builtin_umulll_overflow", + Uint(U128) => "__builtin_mul_overflow", + + _ => unreachable!(), + }, + } + } + else { + match new_kind { + Int(I128) | Uint(U128) => { + let func_name = + match oop { + OverflowOp::Add => + match new_kind { + Int(I128) => "__rust_i128_addo", + Uint(U128) => "__rust_u128_addo", + _ => unreachable!(), + }, + OverflowOp::Sub => + match new_kind { + Int(I128) => "__rust_i128_subo", + Uint(U128) => "__rust_u128_subo", + _ => unreachable!(), + }, + OverflowOp::Mul => + match new_kind { + Int(I128) => "__rust_i128_mulo", // TODO(antoyo): use __muloti4d instead? + Uint(U128) => "__rust_u128_mulo", + _ => unreachable!(), + }, + }; + let a_type = lhs.get_type(); + let b_type = rhs.get_type(); + let param_a = self.context.new_parameter(None, a_type, "a"); + let param_b = self.context.new_parameter(None, b_type, "b"); + let result_field = self.context.new_field(None, a_type, "result"); + let overflow_field = self.context.new_field(None, self.bool_type, "overflow"); + let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]); + let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false); + let result = self.context.new_call(None, func, &[lhs, rhs]); + let overflow = result.access_field(None, overflow_field); + let int_result = result.access_field(None, result_field); + return (int_result, overflow); + }, + _ => { + match oop { + OverflowOp::Mul => + match new_kind { + Int(I32) => "__mulosi4", + Int(I64) => "__mulodi4", + _ => unreachable!(), + }, + _ => unimplemented!("overflow operation for {:?}", new_kind), + } + } + } + }; + + let intrinsic = self.context.get_builtin_function(&name); + let res = self.current_func() + // TODO(antoyo): is it correct to use rhs type instead of the parameter typ? + .new_local(None, rhs.get_type(), "binopResult") + .get_address(None); + let overflow = self.overflow_call(intrinsic, &[lhs, rhs, res], None); + (res.dereference(None).to_rvalue(), overflow) + } + + pub fn gcc_icmp(&self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> { + let a_type = lhs.get_type(); + let b_type = rhs.get_type(); + if self.is_non_native_int_type(a_type) || self.is_non_native_int_type(b_type) { + let signed = a_type.is_compatible_with(self.i128_type); + let sign = + if signed { + "" + } + else { + "u" + }; + let func_name = format!("__{}cmpti2", sign); + let param_a = self.context.new_parameter(None, a_type, "a"); + let param_b = self.context.new_parameter(None, b_type, "b"); + let func = self.context.new_function(None, FunctionType::Extern, self.int_type, &[param_a, param_b], func_name, false); + let cmp = self.context.new_call(None, func, &[lhs, rhs]); + let (op, limit) = + match op { + IntPredicate::IntEQ => { + return self.context.new_comparison(None, ComparisonOp::Equals, cmp, self.context.new_rvalue_one(self.int_type)); + }, + IntPredicate::IntNE => { + return self.context.new_comparison(None, ComparisonOp::NotEquals, cmp, self.context.new_rvalue_one(self.int_type)); + }, + IntPredicate::IntUGT => (ComparisonOp::Equals, 2), + IntPredicate::IntUGE => (ComparisonOp::GreaterThanEquals, 1), + IntPredicate::IntULT => (ComparisonOp::Equals, 0), + IntPredicate::IntULE => (ComparisonOp::LessThanEquals, 1), + IntPredicate::IntSGT => (ComparisonOp::Equals, 2), + IntPredicate::IntSGE => (ComparisonOp::GreaterThanEquals, 1), + IntPredicate::IntSLT => (ComparisonOp::Equals, 0), + IntPredicate::IntSLE => (ComparisonOp::LessThanEquals, 1), + }; + self.context.new_comparison(None, op, cmp, self.context.new_rvalue_from_int(self.int_type, limit)) + } + else { + let left_type = lhs.get_type(); + let right_type = rhs.get_type(); + if left_type != right_type { + // NOTE: because libgccjit cannot compare function pointers. + if left_type.dyncast_function_ptr_type().is_some() && right_type.dyncast_function_ptr_type().is_some() { + lhs = self.context.new_cast(None, lhs, self.usize_type.make_pointer()); + rhs = self.context.new_cast(None, rhs, self.usize_type.make_pointer()); + } + // NOTE: hack because we try to cast a vector type to the same vector type. + else if format!("{:?}", left_type) != format!("{:?}", right_type) { + rhs = self.context.new_cast(None, rhs, left_type); + } + } + self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs) + } + } + + pub fn gcc_xor(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + let a_type = a.get_type(); + let b_type = b.get_type(); + if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) { + a ^ b + } + else { + let values = [ + self.low(a) ^ self.low(b), + self.high(a) ^ self.high(b), + ]; + self.context.new_array_constructor(None, a_type, &values) + } + } + + pub fn gcc_shl(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + let a_type = a.get_type(); + let b_type = b.get_type(); + let a_native = self.is_native_int_type(a_type); + let b_native = self.is_native_int_type(b_type); + if a_native && b_native { + // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by an unsigned number. + if a_type.is_unsigned(self) && b_type.is_signed(self) { + let a = self.context.new_cast(None, a, b_type); + let result = a << b; + self.context.new_cast(None, result, a_type) + } + else if a_type.is_signed(self) && b_type.is_unsigned(self) { + let b = self.context.new_cast(None, b, a_type); + a << b + } + else { + a << b + } + } + else if a_native && !b_native { + self.gcc_shl(a, self.gcc_int_cast(b, a_type)) + } + else { + // NOTE: we cannot use the ashl builtin because it's calling widen_hi() which uses ashl. + let native_int_type = a_type.dyncast_array().expect("get element type"); + + let func = self.current_func(); + let then_block = func.new_block("then"); + let else_block = func.new_block("else"); + let after_block = func.new_block("after"); + let b0_block = func.new_block("b0"); + let actual_else_block = func.new_block("actual_else"); + + let result = func.new_local(None, a_type, "shiftResult"); + + let b = self.gcc_int_cast(b, native_int_type); + let sixty_four = self.gcc_int(native_int_type, 64); + let zero = self.gcc_zero(native_int_type); + let condition = self.gcc_icmp(IntPredicate::IntNE, self.gcc_and(b, sixty_four), zero); + self.llbb().end_with_conditional(None, condition, then_block, else_block); + + // TODO(antoyo): take endianness into account. + let values = [ + zero, + self.low(a) << (b - sixty_four), + ]; + let array_value = self.context.new_array_constructor(None, a_type, &values); + then_block.add_assignment(None, result, array_value); + then_block.end_with_jump(None, after_block); + + let condition = self.gcc_icmp(IntPredicate::IntEQ, b, zero); + else_block.end_with_conditional(None, condition, b0_block, actual_else_block); + + b0_block.add_assignment(None, result, a); + b0_block.end_with_jump(None, after_block); + + // NOTE: cast low to its unsigned type in order to perform a logical right shift. + let unsigned_type = native_int_type.to_unsigned(&self.cx); + let casted_low = self.context.new_cast(None, self.low(a), unsigned_type); + let shift_value = self.context.new_cast(None, sixty_four - b, unsigned_type); + let high_low = self.context.new_cast(None, casted_low >> shift_value, native_int_type); + let values = [ + self.low(a) << b, + (self.high(a) << b) | high_low, + ]; + + let array_value = self.context.new_array_constructor(None, a_type, &values); + actual_else_block.add_assignment(None, result, array_value); + actual_else_block.end_with_jump(None, after_block); + + // NOTE: since jumps were added in a place rustc does not expect, the current block in the + // state need to be updated. + self.switch_to_block(after_block); + + result.to_rvalue() + } + } + + pub fn gcc_bswap(&mut self, mut arg: RValue<'gcc>, width: u64) -> RValue<'gcc> { + let arg_type = arg.get_type(); + if !self.is_native_int_type(arg_type) { + let native_int_type = arg_type.dyncast_array().expect("get element type"); + let lsb = self.context.new_array_access(None, arg, self.context.new_rvalue_from_int(self.int_type, 0)).to_rvalue(); + let swapped_lsb = self.gcc_bswap(lsb, width / 2); + let swapped_lsb = self.context.new_cast(None, swapped_lsb, native_int_type); + let msb = self.context.new_array_access(None, arg, self.context.new_rvalue_from_int(self.int_type, 1)).to_rvalue(); + let swapped_msb = self.gcc_bswap(msb, width / 2); + let swapped_msb = self.context.new_cast(None, swapped_msb, native_int_type); + + // NOTE: we also need to swap the two elements here, in addition to swapping inside + // the elements themselves like done above. + return self.context.new_array_constructor(None, arg_type, &[swapped_msb, swapped_lsb]); + } + + // TODO(antoyo): check if it's faster to use string literals and a + // match instead of format!. + let bswap = self.cx.context.get_builtin_function(&format!("__builtin_bswap{}", width)); + // FIXME(antoyo): this cast should not be necessary. Remove + // when having proper sized integer types. + let param_type = bswap.get_param(0).to_rvalue().get_type(); + if param_type != arg_type { + arg = self.bitcast(arg, param_type); + } + self.cx.context.new_call(None, bswap, &[arg]) + } +} + +impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { + pub fn gcc_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> { + if self.is_native_int_type_or_bool(typ) { + self.context.new_rvalue_from_long(typ, i64::try_from(int).expect("i64::try_from")) + } + else { + // NOTE: set the sign in high. + self.from_low_high(typ, int, -(int.is_negative() as i64)) + } + } + + pub fn gcc_uint(&self, typ: Type<'gcc>, int: u64) -> RValue<'gcc> { + if self.is_native_int_type_or_bool(typ) { + self.context.new_rvalue_from_long(typ, u64::try_from(int).expect("u64::try_from") as i64) + } + else { + self.from_low_high(typ, int as i64, 0) + } + } + + pub fn gcc_uint_big(&self, typ: Type<'gcc>, num: u128) -> RValue<'gcc> { + let low = num as u64; + let high = (num >> 64) as u64; + if num >> 64 != 0 { + // FIXME(antoyo): use a new function new_rvalue_from_unsigned_long()? + if self.is_native_int_type(typ) { + let low = self.context.new_rvalue_from_long(self.u64_type, low as i64); + let high = self.context.new_rvalue_from_long(typ, high as i64); + + let sixty_four = self.context.new_rvalue_from_long(typ, 64); + let shift = high << sixty_four; + shift | self.context.new_cast(None, low, typ) + } + else { + self.from_low_high(typ, low as i64, high as i64) + } + } + else if typ.is_i128(self) { + let num = self.context.new_rvalue_from_long(self.u64_type, num as u64 as i64); + self.gcc_int_cast(num, typ) + } + else { + self.gcc_uint(typ, num as u64) + } + } + + pub fn gcc_zero(&self, typ: Type<'gcc>) -> RValue<'gcc> { + if self.is_native_int_type_or_bool(typ) { + self.context.new_rvalue_zero(typ) + } + else { + self.from_low_high(typ, 0, 0) + } + } + + pub fn gcc_int_width(&self, typ: Type<'gcc>) -> u64 { + if self.is_native_int_type_or_bool(typ) { + typ.get_size() as u64 * 8 + } + else { + // NOTE: the only unsupported types are u128 and i128. + 128 + } + } + + fn bitwise_operation(&self, operation: BinaryOp, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { + let a_type = a.get_type(); + let b_type = b.get_type(); + let a_native = self.is_native_int_type_or_bool(a_type); + let b_native = self.is_native_int_type_or_bool(b_type); + if a_native && b_native { + if a_type != b_type { + b = self.context.new_cast(None, b, a_type); + } + self.context.new_binary_op(None, operation, a_type, a, b) + } + else { + assert!(!a_native && !b_native, "both types should either be native or non-native for or operation"); + let native_int_type = a_type.dyncast_array().expect("get element type"); + let values = [ + self.context.new_binary_op(None, operation, native_int_type, self.low(a), self.low(b)), + self.context.new_binary_op(None, operation, native_int_type, self.high(a), self.high(b)), + ]; + self.context.new_array_constructor(None, a_type, &values) + } + } + + pub fn gcc_or(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + self.bitwise_operation(BinaryOp::BitwiseOr, a, b) + } + + // TODO(antoyo): can we use https://github.com/rust-lang/compiler-builtins/blob/master/src/int/mod.rs#L379 instead? + pub fn gcc_int_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { + let value_type = value.get_type(); + if self.is_native_int_type_or_bool(dest_typ) && self.is_native_int_type_or_bool(value_type) { + self.context.new_cast(None, value, dest_typ) + } + else if self.is_native_int_type_or_bool(dest_typ) { + self.context.new_cast(None, self.low(value), dest_typ) + } + else if self.is_native_int_type_or_bool(value_type) { + let dest_element_type = dest_typ.dyncast_array().expect("get element type"); + + // NOTE: set the sign of the value. + let zero = self.context.new_rvalue_zero(value_type); + let is_negative = self.context.new_comparison(None, ComparisonOp::LessThan, value, zero); + let is_negative = self.gcc_int_cast(is_negative, dest_element_type); + let values = [ + self.context.new_cast(None, value, dest_element_type), + self.context.new_unary_op(None, UnaryOp::Minus, dest_element_type, is_negative), + ]; + self.context.new_array_constructor(None, dest_typ, &values) + } + else { + // Since u128 and i128 are the only types that can be unsupported, we know the type of + // value and the destination type have the same size, so a bitcast is fine. + self.context.new_bitcast(None, value, dest_typ) + } + } + + fn int_to_float_cast(&self, signed: bool, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { + let value_type = value.get_type(); + if self.is_native_int_type_or_bool(value_type) { + return self.context.new_cast(None, value, dest_typ); + } + + let name_suffix = + match self.type_kind(dest_typ) { + TypeKind::Float => "tisf", + TypeKind::Double => "tidf", + kind => panic!("cannot cast a non-native integer to type {:?}", kind), + }; + let sign = + if signed { + "" + } + else { + "un" + }; + let func_name = format!("__float{}{}", sign, name_suffix); + let param = self.context.new_parameter(None, value_type, "n"); + let func = self.context.new_function(None, FunctionType::Extern, dest_typ, &[param], func_name, false); + self.context.new_call(None, func, &[value]) + } + + pub fn gcc_int_to_float_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { + self.int_to_float_cast(true, value, dest_typ) + } + + pub fn gcc_uint_to_float_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { + self.int_to_float_cast(false, value, dest_typ) + } + + fn float_to_int_cast(&self, signed: bool, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { + let value_type = value.get_type(); + if self.is_native_int_type_or_bool(dest_typ) { + return self.context.new_cast(None, value, dest_typ); + } + + let name_suffix = + match self.type_kind(value_type) { + TypeKind::Float => "sfti", + TypeKind::Double => "dfti", + kind => panic!("cannot cast a {:?} to non-native integer", kind), + }; + let sign = + if signed { + "" + } + else { + "uns" + }; + let func_name = format!("__fix{}{}", sign, name_suffix); + let param = self.context.new_parameter(None, value_type, "n"); + let func = self.context.new_function(None, FunctionType::Extern, dest_typ, &[param], func_name, false); + self.context.new_call(None, func, &[value]) + } + + pub fn gcc_float_to_int_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { + self.float_to_int_cast(true, value, dest_typ) + } + + pub fn gcc_float_to_uint_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { + self.float_to_int_cast(false, value, dest_typ) + } + + fn high(&self, value: RValue<'gcc>) -> RValue<'gcc> { + self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, 1)) + .to_rvalue() + } + + fn low(&self, value: RValue<'gcc>) -> RValue<'gcc> { + self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, 0)) + .to_rvalue() + } + + fn from_low_high(&self, typ: Type<'gcc>, low: i64, high: i64) -> RValue<'gcc> { + let native_int_type = typ.dyncast_array().expect("get element type"); + let values = [ + self.context.new_rvalue_from_long(native_int_type, low), + self.context.new_rvalue_from_long(native_int_type, high), + ]; + self.context.new_array_constructor(None, typ, &values) + } +} diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index ef213f56369..08e584a46f3 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -1,7 +1,7 @@ pub mod llvm; mod simd; -use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp}; +use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::{IntPredicate, span_invalid_monomorphization_error}; @@ -175,19 +175,18 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let arg = args[0].immediate(); let result = func.new_local(None, arg.get_type(), "zeros"); - let zero = self.cx.context.new_rvalue_zero(arg.get_type()); - let cond = self.cx.context.new_comparison(None, ComparisonOp::Equals, arg, zero); + let zero = self.cx.gcc_zero(arg.get_type()); + let cond = self.gcc_icmp(IntPredicate::IntEQ, arg, zero); self.llbb().end_with_conditional(None, cond, then_block, else_block); - let zero_result = self.cx.context.new_rvalue_from_long(arg.get_type(), width as i64); + let zero_result = self.cx.gcc_uint(arg.get_type(), width); then_block.add_assignment(None, result, zero_result); then_block.end_with_jump(None, after_block); // NOTE: since jumps were added in a place - // count_leading_zeroes() does not expect, the current blocks + // count_leading_zeroes() does not expect, the current block // in the state need to be updated. - *self.current_block.borrow_mut() = Some(else_block); - self.block = Some(else_block); + self.switch_to_block(else_block); let zeros = match name { @@ -195,13 +194,12 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { sym::cttz => self.count_trailing_zeroes(width, arg), _ => unreachable!(), }; - else_block.add_assignment(None, result, zeros); - else_block.end_with_jump(None, after_block); + self.llbb().add_assignment(None, result, zeros); + self.llbb().end_with_jump(None, after_block); // NOTE: since jumps were added in a place rustc does not - // expect, the current blocks in the state need to be updated. - *self.current_block.borrow_mut() = Some(after_block); - self.block = Some(after_block); + // expect, the current block in the state need to be updated. + self.switch_to_block(after_block); result.to_rvalue() } @@ -217,17 +215,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { args[0].immediate() // byte swap a u8/i8 is just a no-op } else { - // TODO(antoyo): check if it's faster to use string literals and a - // match instead of format!. - let bswap = self.cx.context.get_builtin_function(&format!("__builtin_bswap{}", width)); - let mut arg = args[0].immediate(); - // FIXME(antoyo): this cast should not be necessary. Remove - // when having proper sized integer types. - let param_type = bswap.get_param(0).to_rvalue().get_type(); - if param_type != arg.get_type() { - arg = self.bitcast(arg, param_type); - } - self.cx.context.new_call(None, bswap, &[arg]) + self.gcc_bswap(args[0].immediate(), width) } }, sym::bitreverse => self.bit_reverse(width, args[0].immediate()), @@ -476,17 +464,17 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { val.to_rvalue() }; match self.mode { - PassMode::Ignore => {} + PassMode::Ignore => {}, PassMode::Pair(..) => { OperandValue::Pair(next(), next()).store(bx, dst); - } + }, PassMode::Indirect { extra_attrs: Some(_), .. } => { OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst); - } + }, PassMode::Direct(_) | PassMode::Indirect { extra_attrs: None, .. } | PassMode::Cast(_) => { let next_arg = next(); - self.store(bx, next_arg.to_rvalue(), dst); - } + self.store(bx, next_arg, dst); + }, } } } @@ -526,7 +514,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let value = if result_type.is_signed(self.cx) { - self.context.new_cast(None, value, typ) + self.gcc_int_cast(value, typ) } else { value @@ -673,30 +661,33 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { }, 128 => { // TODO(antoyo): find a more efficient implementation? - let sixty_four = self.context.new_rvalue_from_long(typ, 64); - let high = self.context.new_cast(None, value >> sixty_four, self.u64_type); - let low = self.context.new_cast(None, value, self.u64_type); + let sixty_four = self.gcc_int(typ, 64); + let right_shift = self.gcc_lshr(value, sixty_four); + let high = self.gcc_int_cast(right_shift, self.u64_type); + let low = self.gcc_int_cast(value, self.u64_type); let reversed_high = self.bit_reverse(64, high); let reversed_low = self.bit_reverse(64, low); - let new_low = self.context.new_cast(None, reversed_high, typ); - let new_high = self.context.new_cast(None, reversed_low, typ) << sixty_four; + let new_low = self.gcc_int_cast(reversed_high, typ); + let new_high = self.shl(self.gcc_int_cast(reversed_low, typ), sixty_four); - new_low | new_high + self.gcc_or(new_low, new_high) }, _ => { panic!("cannot bit reverse with width = {}", width); }, }; - self.context.new_cast(None, result, result_type) + self.gcc_int_cast(result, result_type) } - fn count_leading_zeroes(&self, width: u64, arg: RValue<'gcc>) -> RValue<'gcc> { + fn count_leading_zeroes(&mut self, width: u64, arg: RValue<'gcc>) -> RValue<'gcc> { // TODO(antoyo): use width? let arg_type = arg.get_type(); let count_leading_zeroes = + // TODO(antoyo): write a new function Type::is_compatible_with(&Type) and use it here + // instead of using is_uint(). if arg_type.is_uint(&self.cx) { "__builtin_clz" } @@ -712,9 +703,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let result = self.current_func() .new_local(None, array_type, "count_loading_zeroes_results"); - let sixty_four = self.context.new_rvalue_from_long(arg_type, 64); - let high = self.context.new_cast(None, arg >> sixty_four, self.u64_type); - let low = self.context.new_cast(None, arg, self.u64_type); + let sixty_four = self.const_uint(arg_type, 64); + let shift = self.lshr(arg, sixty_four); + let high = self.gcc_int_cast(shift, self.u64_type); + let low = self.gcc_int_cast(arg, self.u64_type); let zero = self.context.new_rvalue_zero(self.usize_type); let one = self.context.new_rvalue_one(self.usize_type); @@ -723,17 +715,18 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let clzll = self.context.get_builtin_function("__builtin_clzll"); let first_elem = self.context.new_array_access(None, result, zero); - let first_value = self.context.new_cast(None, self.context.new_call(None, clzll, &[high]), arg_type); + let first_value = self.gcc_int_cast(self.context.new_call(None, clzll, &[high]), arg_type); self.llbb() .add_assignment(None, first_elem, first_value); let second_elem = self.context.new_array_access(None, result, one); - let second_value = self.context.new_cast(None, self.context.new_call(None, clzll, &[low]), arg_type) + sixty_four; + let cast = self.gcc_int_cast(self.context.new_call(None, clzll, &[low]), arg_type); + let second_value = self.add(cast, sixty_four); self.llbb() .add_assignment(None, second_elem, second_value); let third_elem = self.context.new_array_access(None, result, two); - let third_value = self.context.new_rvalue_from_long(arg_type, 128); + let third_value = self.const_uint(arg_type, 128); self.llbb() .add_assignment(None, third_elem, third_value); @@ -749,13 +742,13 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let res = self.context.new_array_access(None, result, index); - return self.context.new_cast(None, res, arg_type); + return self.gcc_int_cast(res.to_rvalue(), arg_type); } else { - let count_leading_zeroes = self.context.get_builtin_function("__builtin_clz"); - let arg = self.context.new_cast(None, arg, self.uint_type); - let diff = self.int_width(self.uint_type) - self.int_width(arg_type); - let diff = self.context.new_rvalue_from_long(self.int_type, diff); + let count_leading_zeroes = self.context.get_builtin_function("__builtin_clzll"); + let arg = self.context.new_cast(None, arg, self.ulonglong_type); + let diff = self.ulonglong_type.get_size() as i64 - arg_type.get_size() as i64; + let diff = self.context.new_rvalue_from_long(self.int_type, diff * 8); let res = self.context.new_call(None, count_leading_zeroes, &[arg]) - diff; return self.context.new_cast(None, res, arg_type); }; @@ -764,18 +757,20 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.context.new_cast(None, res, arg_type) } - fn count_trailing_zeroes(&self, _width: u64, arg: RValue<'gcc>) -> RValue<'gcc> { + fn count_trailing_zeroes(&mut self, _width: u64, arg: RValue<'gcc>) -> RValue<'gcc> { let result_type = arg.get_type(); let arg = if result_type.is_signed(self.cx) { let new_type = result_type.to_unsigned(self.cx); - self.context.new_cast(None, arg, new_type) + self.gcc_int_cast(arg, new_type) } else { arg }; let arg_type = arg.get_type(); let (count_trailing_zeroes, expected_type) = + // TODO(antoyo): write a new function Type::is_compatible_with(&Type) and use it here + // instead of using is_uint(). if arg_type.is_uchar(&self.cx) || arg_type.is_ushort(&self.cx) || arg_type.is_uint(&self.cx) { // NOTE: we don't need to & 0xFF for uchar because the result is undefined on zero. ("__builtin_ctz", self.cx.uint_type) @@ -792,9 +787,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let result = self.current_func() .new_local(None, array_type, "count_loading_zeroes_results"); - let sixty_four = self.context.new_rvalue_from_long(arg_type, 64); - let high = self.context.new_cast(None, arg >> sixty_four, self.u64_type); - let low = self.context.new_cast(None, arg, self.u64_type); + let sixty_four = self.gcc_int(arg_type, 64); + let shift = self.gcc_lshr(arg, sixty_four); + let high = self.gcc_int_cast(shift, self.u64_type); + let low = self.gcc_int_cast(arg, self.u64_type); let zero = self.context.new_rvalue_zero(self.usize_type); let one = self.context.new_rvalue_one(self.usize_type); @@ -803,17 +799,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let ctzll = self.context.get_builtin_function("__builtin_ctzll"); let first_elem = self.context.new_array_access(None, result, zero); - let first_value = self.context.new_cast(None, self.context.new_call(None, ctzll, &[low]), arg_type); + let first_value = self.gcc_int_cast(self.context.new_call(None, ctzll, &[low]), arg_type); self.llbb() .add_assignment(None, first_elem, first_value); let second_elem = self.context.new_array_access(None, result, one); - let second_value = self.context.new_cast(None, self.context.new_call(None, ctzll, &[high]), arg_type) + sixty_four; + let second_value = self.gcc_add(self.gcc_int_cast(self.context.new_call(None, ctzll, &[high]), arg_type), sixty_four); self.llbb() .add_assignment(None, second_elem, second_value); let third_elem = self.context.new_array_access(None, result, two); - let third_value = self.context.new_rvalue_from_long(arg_type, 128); + let third_value = self.gcc_int(arg_type, 128); self.llbb() .add_assignment(None, third_elem, third_value); @@ -829,10 +825,20 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let res = self.context.new_array_access(None, result, index); - return self.context.new_cast(None, res, result_type); + return self.gcc_int_cast(res.to_rvalue(), result_type); } else { - unimplemented!("count_trailing_zeroes for {:?}", arg_type); + let count_trailing_zeroes = self.context.get_builtin_function("__builtin_ctzll"); + let arg_size = arg_type.get_size(); + let casted_arg = self.context.new_cast(None, arg, self.ulonglong_type); + let byte_diff = self.ulonglong_type.get_size() as i64 - arg_size as i64; + let diff = self.context.new_rvalue_from_long(self.int_type, byte_diff * 8); + let mask = self.context.new_rvalue_from_long(arg_type, -1); // To get the value with all bits set. + let masked = mask & self.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, arg); + let cond = self.context.new_comparison(None, ComparisonOp::Equals, masked, mask); + let diff = diff * self.context.new_cast(None, cond, self.int_type); + let res = self.context.new_call(None, count_trailing_zeroes, &[casted_arg]) - diff; + return self.context.new_cast(None, res, result_type); }; let count_trailing_zeroes = self.context.get_builtin_function(count_trailing_zeroes); let arg = @@ -846,18 +852,14 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.context.new_cast(None, res, result_type) } - fn int_width(&self, typ: Type<'gcc>) -> i64 { - self.cx.int_width(typ) as i64 - } - - fn pop_count(&self, value: RValue<'gcc>) -> RValue<'gcc> { + fn pop_count(&mut self, value: RValue<'gcc>) -> RValue<'gcc> { // TODO(antoyo): use the optimized version with fewer operations. let result_type = value.get_type(); let value_type = result_type.to_unsigned(self.cx); let value = if result_type.is_signed(self.cx) { - self.context.new_cast(None, value, value_type) + self.gcc_int_cast(value, value_type) } else { value @@ -867,13 +869,14 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // TODO(antoyo): implement in the normal algorithm below to have a more efficient // implementation (that does not require a call to __popcountdi2). let popcount = self.context.get_builtin_function("__builtin_popcountll"); - let sixty_four = self.context.new_rvalue_from_long(value_type, 64); - let high = self.context.new_cast(None, value >> sixty_four, self.cx.ulonglong_type); + let sixty_four = self.gcc_int(value_type, 64); + let right_shift = self.gcc_lshr(value, sixty_four); + let high = self.gcc_int_cast(right_shift, self.cx.ulonglong_type); let high = self.context.new_call(None, popcount, &[high]); - let low = self.context.new_cast(None, value, self.cx.ulonglong_type); + let low = self.gcc_int_cast(value, self.cx.ulonglong_type); let low = self.context.new_call(None, popcount, &[low]); let res = high + low; - return self.context.new_cast(None, res, result_type); + return self.gcc_int_cast(res, result_type); } // First step. @@ -935,13 +938,14 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // Algorithm from: https://blog.regehr.org/archives/1063 fn rotate_left(&mut self, value: RValue<'gcc>, shift: RValue<'gcc>, width: u64) -> RValue<'gcc> { - let max = self.context.new_rvalue_from_long(shift.get_type(), width as i64); - let shift = shift % max; + let max = self.const_uint(shift.get_type(), width); + let shift = self.urem(shift, max); let lhs = self.shl(value, shift); + let result_neg = self.neg(shift); let result_and = self.and( - self.context.new_unary_op(None, UnaryOp::Minus, shift.get_type(), shift), - self.context.new_rvalue_from_long(shift.get_type(), width as i64 - 1), + result_neg, + self.const_uint(shift.get_type(), width - 1), ); let rhs = self.lshr(value, result_and); self.or(lhs, rhs) @@ -949,13 +953,14 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // Algorithm from: https://blog.regehr.org/archives/1063 fn rotate_right(&mut self, value: RValue<'gcc>, shift: RValue<'gcc>, width: u64) -> RValue<'gcc> { - let max = self.context.new_rvalue_from_long(shift.get_type(), width as i64); - let shift = shift % max; + let max = self.const_uint(shift.get_type(), width); + let shift = self.urem(shift, max); let lhs = self.lshr(value, shift); + let result_neg = self.neg(shift); let result_and = self.and( - self.context.new_unary_op(None, UnaryOp::Minus, shift.get_type(), shift), - self.context.new_rvalue_from_long(shift.get_type(), width as i64 - 1), + result_neg, + self.const_uint(shift.get_type(), width - 1), ); let rhs = self.shl(value, result_and); self.or(lhs, rhs) @@ -995,9 +1000,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.llbb().end_with_conditional(None, overflow, then_block, after_block); // NOTE: since jumps were added in a place rustc does not - // expect, the current blocks in the state need to be updated. - *self.current_block.borrow_mut() = Some(after_block); - self.block = Some(after_block); + // expect, the current block in the state need to be updated. + self.switch_to_block(after_block); res.to_rvalue() } @@ -1015,39 +1019,59 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fn saturating_sub(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>, signed: bool, width: u64) -> RValue<'gcc> { if signed { // Also based on algorithm from: https://stackoverflow.com/a/56531252/389119 - let func_name = - match width { - 8 => "__builtin_sub_overflow", - 16 => "__builtin_sub_overflow", - 32 => "__builtin_ssub_overflow", - 64 => "__builtin_ssubll_overflow", - 128 => "__builtin_sub_overflow", - _ => unreachable!(), - }; - let overflow_func = self.context.get_builtin_function(func_name); let result_type = lhs.get_type(); let func = self.current_func.borrow().expect("func"); let res = func.new_local(None, result_type, "saturating_diff"); - let overflow = self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(None)], None); + let supports_native_type = self.is_native_int_type(result_type); + let overflow = + if supports_native_type { + let func_name = + match width { + 8 => "__builtin_sub_overflow", + 16 => "__builtin_sub_overflow", + 32 => "__builtin_ssub_overflow", + 64 => "__builtin_ssubll_overflow", + 128 => "__builtin_sub_overflow", + _ => unreachable!(), + }; + let overflow_func = self.context.get_builtin_function(func_name); + self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(None)], None) + } + else { + let func_name = + match width { + 128 => "__rust_i128_subo", + _ => unreachable!(), + }; + let param_a = self.context.new_parameter(None, result_type, "a"); + let param_b = self.context.new_parameter(None, result_type, "b"); + let result_field = self.context.new_field(None, result_type, "result"); + let overflow_field = self.context.new_field(None, self.bool_type, "overflow"); + let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]); + let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false); + let result = self.context.new_call(None, func, &[lhs, rhs]); + let overflow = result.access_field(None, overflow_field); + let int_result = result.access_field(None, result_field); + self.llbb().add_assignment(None, res, int_result); + overflow + }; let then_block = func.new_block("then"); let after_block = func.new_block("after"); - let unsigned_type = self.context.new_int_type(width as i32 / 8, false); - let shifted = self.context.new_cast(None, lhs, unsigned_type) >> self.context.new_rvalue_from_int(unsigned_type, width as i32 - 1); - let uint_max = self.context.new_unary_op(None, UnaryOp::BitwiseNegate, unsigned_type, - self.context.new_rvalue_from_int(unsigned_type, 0) - ); - let int_max = uint_max >> self.context.new_rvalue_one(unsigned_type); - then_block.add_assignment(None, res, self.context.new_cast(None, shifted + int_max, result_type)); + // NOTE: convert the type to unsigned to have an unsigned shift. + let unsigned_type = result_type.to_unsigned(&self.cx); + let shifted = self.gcc_lshr(self.gcc_int_cast(lhs, unsigned_type), self.gcc_int(unsigned_type, width as i64 - 1)); + let uint_max = self.gcc_not(self.gcc_int(unsigned_type, 0)); + let int_max = self.gcc_lshr(uint_max, self.gcc_int(unsigned_type, 1)); + then_block.add_assignment(None, res, self.gcc_int_cast(self.gcc_add(shifted, int_max), result_type)); then_block.end_with_jump(None, after_block); self.llbb().end_with_conditional(None, overflow, then_block, after_block); // NOTE: since jumps were added in a place rustc does not - // expect, the current blocks in the state need to be updated. - *self.current_block.borrow_mut() = Some(after_block); - self.block = Some(after_block); + // expect, the current block in the state need to be updated. + self.switch_to_block(after_block); res.to_rvalue() } @@ -1062,7 +1086,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } fn try_intrinsic<'gcc, 'tcx>(bx: &mut Builder<'_, 'gcc, 'tcx>, try_func: RValue<'gcc>, data: RValue<'gcc>, _catch_func: RValue<'gcc>, dest: RValue<'gcc>) { - if bx.sess().panic_strategy() == PanicStrategy::Abort { + // NOTE: the `|| true` here is to use the panic=abort strategy with panic=unwind too + if bx.sess().panic_strategy() == PanicStrategy::Abort || true { + // TODO(bjorn3): Properly implement unwinding and remove the `|| true` once this is done. bx.call(bx.type_void(), try_func, &[data], None); // Return 0 unconditionally from the intrinsic call; // we can never unwind. diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index aff27f71d91..7d7811c8782 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -163,5 +163,26 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, simd_xor: Uint, Int => xor; } + macro_rules! arith_unary { + ($($name: ident: $($($p: ident),* => $call: ident),*;)*) => { + $(if name == sym::$name { + match in_elem.kind() { + $($(ty::$p(_))|* => { + return Ok(bx.$call(args[0].immediate())) + })* + _ => {}, + } + require!(false, + "unsupported operation on `{}` with element `{}`", + in_ty, + in_elem) + })* + } + } + + arith_unary! { + simd_neg: Int => neg, Float => fneg; + } + unimplemented!("simd {}", name); } diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index ef95dfb6e2e..eac4a06226c 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -1,6 +1,7 @@ /* + * TODO(antoyo): implement equality in libgccjit based on https://zpz.github.io/blog/overloading-equality-operator-in-cpp-class-hierarchy/ (for type equality?) * TODO(antoyo): support #[inline] attributes. - * TODO(antoyo): support LTO. + * TODO(antoyo): support LTO (gcc's equivalent to Thin LTO is enabled by -fwhopr: https://stackoverflow.com/questions/64954525/does-gcc-have-thin-lto). * * TODO(antoyo): remove the patches. */ @@ -21,6 +22,7 @@ extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; extern crate rustc_target; +extern crate tempfile; // This prevents duplicating functions and statics that are already part of the host rustc process. #[allow(unused_extern_crates)] @@ -40,15 +42,16 @@ mod context; mod coverageinfo; mod debuginfo; mod declare; +mod int; mod intrinsic; mod mono_item; mod type_; mod type_of; use std::any::Any; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; -use gccjit::{Context, OptimizationLevel}; +use gccjit::{Context, OptimizationLevel, CType}; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen}; use rustc_codegen_ssa::base::codegen_crate; @@ -61,10 +64,12 @@ use rustc_errors::{ErrorGuaranteed, Handler}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::query::Providers; use rustc_session::config::{Lto, OptLevel, OutputFilenames}; use rustc_session::Session; use rustc_span::Symbol; use rustc_span::fatal_error::FatalError; +use tempfile::TempDir; pub struct PrintOnPanic<F: Fn() -> String>(pub F); @@ -77,13 +82,29 @@ impl<F: Fn() -> String> Drop for PrintOnPanic<F> { } #[derive(Clone)] -pub struct GccCodegenBackend; +pub struct GccCodegenBackend { + supports_128bit_integers: Arc<Mutex<bool>>, +} impl CodegenBackend for GccCodegenBackend { fn init(&self, sess: &Session) { if sess.lto() != Lto::No { sess.warn("LTO is not supported. You may get a linker error."); } + + let temp_dir = TempDir::new().expect("cannot create temporary directory"); + let temp_file = temp_dir.into_path().join("result.asm"); + let check_context = Context::default(); + check_context.set_print_errors_to_stderr(false); + let _int128_ty = check_context.new_c_type(CType::UInt128t); + // NOTE: we cannot just call compile() as this would require other files than libgccjit.so. + check_context.compile_to_file(gccjit::OutputKind::Assembler, temp_file.to_str().expect("path to str")); + *self.supports_128bit_integers.lock().expect("lock") = check_context.get_last_error() == Ok(None); + } + + fn provide(&self, providers: &mut Providers) { + // FIXME(antoyo) compute list of enabled features from cli flags + providers.global_backend_features = |_tcx, ()| vec![]; } fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, need_metadata_module: bool) -> Box<dyn Any> { @@ -129,7 +150,7 @@ impl ExtraBackendMethods for GccCodegenBackend { } fn compile_codegen_unit<'tcx>(&self, tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (ModuleCodegen<Self::Module>, u64) { - base::compile_codegen_unit(tcx, cgu_name) + base::compile_codegen_unit(tcx, cgu_name, *self.supports_128bit_integers.lock().expect("lock")) } fn target_machine_factory(&self, _sess: &Session, _opt_level: OptLevel, _features: &[String]) -> TargetMachineFactoryFn<Self> { @@ -237,7 +258,9 @@ impl WriteBackendMethods for GccCodegenBackend { /// This is the entrypoint for a hot plugged rustc_codegen_gccjit #[no_mangle] pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> { - Box::new(GccCodegenBackend) + Box::new(GccCodegenBackend { + supports_128bit_integers: Arc::new(Mutex::new(false)), + }) } fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel { diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs index 28e2adc492b..e9505808521 100644 --- a/compiler/rustc_codegen_gcc/src/type_.rs +++ b/compiler/rustc_codegen_gcc/src/type_.rs @@ -7,7 +7,6 @@ use rustc_middle::bug; use rustc_middle::ty::layout::TyAndLayout; use rustc_target::abi::{AddressSpace, Align, Integer, Size}; -use crate::common::TypeReflection; use crate::context::CodegenCx; use crate::type_of::LayoutGccExt; @@ -119,9 +118,15 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn type_kind(&self, typ: Type<'gcc>) -> TypeKind { - if typ.is_integral() { + if self.is_int_type_or_bool(typ) { TypeKind::Integer } + else if typ.is_compatible_with(self.float_type) { + TypeKind::Float + } + else if typ.is_compatible_with(self.double_type) { + TypeKind::Double + } else if typ.dyncast_vector().is_some() { TypeKind::Vector } @@ -175,24 +180,7 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn int_width(&self, typ: Type<'gcc>) -> u64 { - if typ.is_i8(self) || typ.is_u8(self) { - 8 - } - else if typ.is_i16(self) || typ.is_u16(self) { - 16 - } - else if typ.is_i32(self) || typ.is_u32(self) { - 32 - } - else if typ.is_i64(self) || typ.is_u64(self) { - 64 - } - else if typ.is_i128(self) || typ.is_u128(self) { - 128 - } - else { - panic!("Cannot get width of int type {:?}", typ); - } + self.gcc_int_width(typ) } fn val_ty(&self, value: RValue<'gcc>) -> Type<'gcc> { diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 649ffc16249..ed8f0445ca3 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -251,7 +251,9 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { ty::Ref(..) | ty::RawPtr(_) => { return self.field(cx, index).gcc_type(cx, true); } - ty::Adt(def, _) if def.is_box() => { + // only wide pointer boxes are handled as pointers + // thin pointer boxes with scalar allocators are handled by the general logic below + ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => { let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty()); return cx.layout_of(ptr_ty).scalar_pair_element_gcc_type(cx, index, immediate); } diff --git a/compiler/rustc_codegen_gcc/test.sh b/compiler/rustc_codegen_gcc/test.sh index b9aeee79550..1beeee136df 100755 --- a/compiler/rustc_codegen_gcc/test.sh +++ b/compiler/rustc_codegen_gcc/test.sh @@ -4,7 +4,7 @@ set -e -if [ -f ./gcc_path ]; then +if [ -f ./gcc_path ]; then export GCC_PATH=$(cat gcc_path) else echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details' @@ -14,14 +14,26 @@ fi export LD_LIBRARY_PATH="$GCC_PATH" export LIBRARY_PATH="$GCC_PATH" +features= + +if [[ "$1" == "--features" ]]; then + shift + features="--features $1" + shift +fi + if [[ "$1" == "--release" ]]; then export CHANNEL='release' - CARGO_INCREMENTAL=1 cargo rustc --release + CARGO_INCREMENTAL=1 cargo rustc --release $features shift else echo $LD_LIBRARY_PATH export CHANNEL='debug' - cargo rustc + cargo rustc $features +fi + +if [[ "$1" == "--build" ]]; then + exit fi source config.sh @@ -145,7 +157,7 @@ function test_rustc() { echo echo "[TEST] rust-lang/rust" - rust_toolchain=$(cat rust-toolchain) + rust_toolchain=$(cat rust-toolchain | grep channel | sed 's/channel = "\(.*\)"/\1/') git clone https://github.com/rust-lang/rust.git || true cd rust @@ -153,6 +165,24 @@ function test_rustc() { git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(') export RUSTFLAGS= + git apply - <<EOF +diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs +index 887d27fd6dca4..2c2239f2b83d1 100644 +--- a/src/tools/compiletest/src/header.rs ++++ b/src/tools/compiletest/src/header.rs +@@ -806,8 +806,8 @@ pub fn make_test_description<R: Read>( + cfg: Option<&str>, + ) -> test::TestDesc { + let mut ignore = false; + #[cfg(not(bootstrap))] +- let ignore_message: Option<String> = None; ++ let ignore_message: Option<&str> = None; + let mut should_fail = false; + + let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some(); + +EOF + rm config.toml || true cat > config.toml <<EOF @@ -175,13 +205,12 @@ EOF git checkout -- src/test/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed - rm -r src/test/ui/{abi*,extern/,llvm-asm/,panic-runtime/,panics/,unsized-locals/,proc-macro/,threads-sendsync/,thinlto/,simd*,borrowck/,test*,*lto*.rs} || true + rm -r src/test/ui/{abi*,extern/,panic-runtime/,panics/,unsized-locals/,proc-macro/,threads-sendsync/,thinlto/,simd*,borrowck/,test*,*lto*.rs} || true for test in $(rg --files-with-matches "catch_unwind|should_panic|thread|lto" src/test/ui); do rm $test done git checkout src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs git checkout src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs - rm src/test/ui/llvm-asm/llvm-asm-in-out-operand.rs || true # TODO(antoyo): Enable back this test if I ever implement the llvm_asm! macro. RUSTC_ARGS="-Zpanic-abort-tests -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot -Cpanic=abort" @@ -206,6 +235,14 @@ case $1 in clean_ui_tests ;; + "--std-tests") + std_tests + ;; + + "--build-sysroot") + build_sysroot + ;; + *) clean mini_tests diff --git a/compiler/rustc_codegen_gcc/tests/run/assign.rs b/compiler/rustc_codegen_gcc/tests/run/assign.rs index cc8647006ca..eb38a8a3835 100644 --- a/compiler/rustc_codegen_gcc/tests/run/assign.rs +++ b/compiler/rustc_codegen_gcc/tests/run/assign.rs @@ -51,7 +51,7 @@ mod libc { pub fn fflush(stream: *mut i32) -> i32; pub fn printf(format: *const i8, ...) -> i32; - pub static STDOUT: *mut i32; + pub static stdout: *mut i32; } } @@ -67,7 +67,7 @@ mod intrinsics { pub fn panic(_msg: &str) -> ! { unsafe { libc::puts("Panicking\0" as *const str as *const u8); - libc::fflush(libc::STDOUT); + libc::fflush(libc::stdout); intrinsics::abort(); } } diff --git a/compiler/rustc_codegen_gcc/tests/run/int.rs b/compiler/rustc_codegen_gcc/tests/run/int.rs new file mode 100644 index 00000000000..49376012c40 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/int.rs @@ -0,0 +1,153 @@ +// Compiler: +// +// Run-time: +// status: 0 + +#![feature(arbitrary_self_types, auto_traits, core_intrinsics, lang_items, start, intrinsics)] + +#![no_std] + +mod intrinsics { + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +/* + * Core + */ + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn puts(s: *const u8) -> i32; + } +} + +#[panic_handler] +fn panic_handler(_: &core::panic::PanicInfo) -> ! { + unsafe { + core::intrinsics::abort(); + } +} + +/* + * Code + */ + +#[start] +fn main(argc: isize, _argv: *const *const u8) -> isize { + let var = 134217856_u128; + let var2 = 10475372733397991552_u128; + let var3 = 193236519889708027473620326106273939584_u128; + let var4 = 123236519889708027473620326106273939584_u128; + let var5 = 153236519889708027473620326106273939584_u128; + let var6 = 18446744073709551616_i128; + let var7 = 170141183460469231731687303715884105728_u128; + + // Shifts. + assert_eq!(var << (argc as u128 - 1), var); + assert_eq!(var << argc as u128, 268435712); + assert_eq!(var << (argc + 32) as u128, 1152922604118474752); + assert_eq!(var << (argc + 48) as u128, 75557935783508361347072); + assert_eq!(var << (argc + 60) as u128, 309485304969250248077606912); + assert_eq!(var << (argc + 62) as u128, 1237941219877000992310427648); + assert_eq!(var << (argc + 63) as u128, 2475882439754001984620855296); + assert_eq!(var << (argc + 80) as u128, 324518863143436548128224745357312); + + assert_eq!(var2 << argc as u128, 20950745466795983104); + assert_eq!(var2 << (argc as u128 - 1), var2); + assert_eq!(var2 << (argc + 32) as u128, 89982766606709001335848566784); + assert_eq!(var2 << (argc + 48) as u128, 5897110592337281111546171672756224); + assert_eq!(var2 << (argc + 60) as u128, 24154564986213503432893119171609493504); + assert_eq!(var2 << (argc + 62) as u128, 96618259944854013731572476686437974016); + assert_eq!(var2 << (argc + 63) as u128, 193236519889708027463144953372875948032); + + assert_eq!(var3 << argc as u128, 46190672858477591483866044780779667712); + assert_eq!(var3 << (argc as u128 - 1), var3); + assert_eq!(var3 << (argc + 32) as u128, 21267668304951024224840338247585366016); + assert_eq!(var3 << (argc + 48) as u128, 1335125106377253154015353231953100800); + assert_eq!(var3 << (argc + 60) as u128, 24154564986213503432893119171609493504); + assert_eq!(var3 << (argc + 62) as u128, 96618259944854013731572476686437974016); + assert_eq!(var3 << (argc + 63) as u128, 193236519889708027463144953372875948032); + + assert_eq!((2220326408_u32 + argc as u32) >> (32 - 6), 33); + + assert_eq!(var >> (argc as u128 - 1), var); + assert_eq!(var >> argc as u128, 67108928); + assert_eq!(var >> (argc + 32) as u128, 0); + assert_eq!(var >> (argc + 48) as u128, 0); + assert_eq!(var >> (argc + 60) as u128, 0); + assert_eq!(var >> (argc + 62) as u128, 0); + assert_eq!(var >> (argc + 63) as u128, 0); + + assert_eq!(var2 >> argc as u128, 5237686366698995776); + assert_eq!(var2 >> (argc as u128 - 1), var2); + assert_eq!(var2 >> (argc + 32) as u128, 1219493888); + assert_eq!(var2 >> (argc + 48) as u128, 18608); + assert_eq!(var2 >> (argc + 60) as u128, 4); + assert_eq!(var2 >> (argc + 62) as u128, 1); + assert_eq!(var2 >> (argc + 63) as u128, 0); + + assert_eq!(var3 >> (argc as u128 - 1), var3); + assert_eq!(var3 >> argc as u128, 96618259944854013736810163053136969792); + assert_eq!(var3 >> (argc + 32) as u128, 22495691651677250335181635584); + assert_eq!(var3 >> (argc + 48) as u128, 343257013727985387194544); + assert_eq!(var3 >> (argc + 60) as u128, 83802981867183932420); + assert_eq!(var3 >> (argc + 62) as u128, 20950745466795983105); + assert_eq!(var3 >> (argc + 63) as u128, 10475372733397991552); + assert_eq!(var3 >> (argc + 80) as u128, 79920751444992); + + assert_eq!(var6 >> argc as u128, 9223372036854775808); + assert_eq!((var6 - 1) >> argc as u128, 9223372036854775807); + assert_eq!(var7 >> argc as u128, 85070591730234615865843651857942052864); + + // Casts + assert_eq!((var >> (argc + 32) as u128) as u64, 0); + assert_eq!((var >> argc as u128) as u64, 67108928); + + // Addition. + assert_eq!(var + argc as u128, 134217857); + + assert_eq!(var2 + argc as u128, 10475372733397991553); + assert_eq!(var2 + (var2 + argc as u128) as u128, 20950745466795983105); + + assert_eq!(var3 + argc as u128, 193236519889708027473620326106273939585); + + // Subtraction + assert_eq!(var - argc as u128, 134217855); + + assert_eq!(var2 - argc as u128, 10475372733397991551); + + assert_eq!(var3 - argc as u128, 193236519889708027473620326106273939583); + + // Multiplication + assert_eq!(var * (argc + 1) as u128, 268435712); + assert_eq!(var * (argc as u128 + var2), 1405982069077538020949770368); + + assert_eq!(var2 * (argc + 1) as u128, 20950745466795983104); + assert_eq!(var2 * (argc as u128 + var2), 109733433903618109003204073240861360256); + + assert_eq!(var3 * argc as u128, 193236519889708027473620326106273939584); + + assert_eq!(var4 * (argc + 1) as u128, 246473039779416054947240652212547879168); + + assert_eq!(var5 * (argc + 1) as u128, 306473039779416054947240652212547879168); + + // Division. + assert_eq!(var / (argc + 1) as u128, 67108928); + assert_eq!(var / (argc + 2) as u128, 44739285); + + assert_eq!(var2 / (argc + 1) as u128, 5237686366698995776); + assert_eq!(var2 / (argc + 2) as u128, 3491790911132663850); + + assert_eq!(var3 / (argc + 1) as u128, 96618259944854013736810163053136969792); + assert_eq!(var3 / (argc + 2) as u128, 64412173296569342491206775368757979861); + assert_eq!(var3 / (argc as u128 + var4), 1); + assert_eq!(var3 / (argc as u128 + var2), 18446744073709551615); + + assert_eq!(var4 / (argc + 1) as u128, 61618259944854013736810163053136969792); + assert_eq!(var4 / (argc + 2) as u128, 41078839963236009157873442035424646528); + + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs b/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs index 7111703ca25..6477b839828 100644 --- a/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs +++ b/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs @@ -49,7 +49,7 @@ mod libc { pub fn puts(s: *const u8) -> i32; pub fn fflush(stream: *mut i32) -> i32; - pub static STDOUT: *mut i32; + pub static stdout: *mut i32; } } @@ -65,7 +65,7 @@ mod intrinsics { pub fn panic(_msg: &str) -> ! { unsafe { libc::puts("Panicking\0" as *const str as *const u8); - libc::fflush(libc::STDOUT); + libc::fflush(libc::stdout); intrinsics::abort(); } } diff --git a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs index e8876009cc6..52de20021f3 100644 --- a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs +++ b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs @@ -53,7 +53,7 @@ mod libc { pub fn fflush(stream: *mut i32) -> i32; pub fn printf(format: *const i8, ...) -> i32; - pub static STDOUT: *mut i32; + pub static stdout: *mut i32; } } @@ -69,7 +69,7 @@ mod intrinsics { pub fn panic(_msg: &str) -> ! { unsafe { libc::puts("Panicking\0" as *const str as *const u8); - libc::fflush(libc::STDOUT); + libc::fflush(libc::stdout); intrinsics::abort(); } } diff --git a/compiler/rustc_codegen_gcc/tests/run/operations.rs b/compiler/rustc_codegen_gcc/tests/run/operations.rs index 4dc375309e4..e078b37b4ab 100644 --- a/compiler/rustc_codegen_gcc/tests/run/operations.rs +++ b/compiler/rustc_codegen_gcc/tests/run/operations.rs @@ -59,7 +59,7 @@ mod libc { pub fn puts(s: *const u8) -> i32; pub fn fflush(stream: *mut i32) -> i32; - pub static STDOUT: *mut i32; + pub static stdout: *mut i32; } } @@ -75,7 +75,7 @@ mod intrinsics { pub fn panic(_msg: &str) -> ! { unsafe { libc::puts("Panicking\0" as *const str as *const u8); - libc::fflush(libc::STDOUT); + libc::fflush(libc::stdout); intrinsics::abort(); } } diff --git a/compiler/rustc_codegen_gcc/tests/run/static.rs b/compiler/rustc_codegen_gcc/tests/run/static.rs index ab89f6aff4b..294add96844 100644 --- a/compiler/rustc_codegen_gcc/tests/run/static.rs +++ b/compiler/rustc_codegen_gcc/tests/run/static.rs @@ -22,6 +22,12 @@ #[lang = "sized"] pub trait Sized {} +#[lang = "destruct"] +pub trait Destruct {} + +#[lang = "drop"] +pub trait Drop {} + #[lang = "copy"] trait Copy { } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index e23572104c4..1d11e6dfbd2 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1748,7 +1748,7 @@ impl SharedEmitterMain { if let Some(code) = diag.code { d.code(code); } - handler.emit_diagnostic(&d); + handler.emit_diagnostic(&mut d); } Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => { let msg = msg.strip_prefix("error: ").unwrap_or(&msg); diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index d78c7a9fad9..abd7094440e 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -444,6 +444,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { match scalar.try_to_int() { Ok(int) => int.is_null(), Err(_) => { + // Can only happen during CTFE. let ptr = self.scalar_to_ptr(scalar); match self.memory.ptr_try_get_alloc(ptr) { Ok((alloc_id, offset, _)) => { @@ -455,7 +456,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Note that one-past-the-end (offset == size) is still inbounds, and never null. offset > size } - Err(offset) => offset == 0, + Err(_offset) => bug!("a non-int scalar is always a pointer"), } } } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 8bdafa87623..9da7f5e30cb 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -21,7 +21,7 @@ use std::hash::Hash; use super::{ alloc_range, CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine, - MemPlaceMeta, OpTy, ScalarMaybeUninit, ValueVisitor, + MemPlaceMeta, OpTy, Scalar, ScalarMaybeUninit, ValueVisitor, }; macro_rules! throw_validation_failure { @@ -521,8 +521,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // NOTE: Keep this in sync with the array optimization for int/float // types below! if M::enforce_number_validity(self.ecx) { - // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous - let is_bits = value.check_init().map_or(false, |v| v.try_to_int().is_ok()); + // Integers/floats with number validity: Must be scalar bits, pointers are dangerous. + // As a special exception we *do* match on a `Scalar` here, since we truly want + // to know its underlying representation (and *not* cast it to an integer). + let is_bits = + value.check_init().map_or(false, |v| matches!(v, Scalar::Int(..))); if !is_bits { throw_validation_failure!(self.path, { "{:x}", value } expected { "initialized plain (non-pointer) bytes" } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index eb01e261c1a..223b3ad0cf9 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -255,8 +255,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { // "secondary" errors if they occurred. let secondary_errors = mem::take(&mut self.secondary_errors); if self.error_emitted.is_none() { - for error in secondary_errors { - self.tcx.sess.diagnostic().emit_diagnostic(&error); + for mut error in secondary_errors { + self.tcx.sess.diagnostic().emit_diagnostic(&mut error); } } else { assert!(self.tcx.sess.has_errors().is_some()); diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 91bb38e5a95..667c63b709b 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1181,8 +1181,8 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { // a .span_bug or .bug call has already printed what // it wants to print. if !info.payload().is::<rustc_errors::ExplicitBug>() { - let d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic"); - handler.emit_diagnostic(&d); + let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic"); + handler.emit_diagnostic(&mut d); } let mut xs: Vec<Cow<'static, str>> = vec![ diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index a185902123d..61a177f291b 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -394,6 +394,7 @@ E0663: include_str!("./error_codes/E0663.md"), E0664: include_str!("./error_codes/E0664.md"), E0665: include_str!("./error_codes/E0665.md"), E0666: include_str!("./error_codes/E0666.md"), +E0667: include_str!("./error_codes/E0667.md"), E0668: include_str!("./error_codes/E0668.md"), E0669: include_str!("./error_codes/E0669.md"), E0670: include_str!("./error_codes/E0670.md"), @@ -633,7 +634,6 @@ E0787: include_str!("./error_codes/E0787.md"), // attribute E0640, // infer outlives requirements // E0645, // trait aliases not finished - E0667, // `impl Trait` in projections // E0694, // an unknown tool name found in scoped attributes // E0702, // replaced with a generic attribute input check // E0707, // multiple elided lifetimes used in arguments of `async fn` diff --git a/compiler/rustc_error_codes/src/error_codes/E0667.md b/compiler/rustc_error_codes/src/error_codes/E0667.md new file mode 100644 index 00000000000..0709a24c433 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0667.md @@ -0,0 +1,18 @@ +`impl Trait` is not allowed in path parameters. + +Erroneous code example: + +```compile_fail,E0667 +fn some_fn(mut x: impl Iterator) -> <impl Iterator>::Item { // error! + x.next().unwrap() +} +``` + +You cannot use `impl Trait` in path parameters. If you want something +equivalent, you can do this instead: + +``` +fn some_fn<T: Iterator>(mut x: T) -> T::Item { // ok! + x.next().unwrap() +} +``` diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index c380455012d..5f59eba23f8 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -70,7 +70,7 @@ fn annotation_type_for_level(level: Level) -> AnnotationType { AnnotationType::Error } Level::Warning => AnnotationType::Warning, - Level::Note => AnnotationType::Note, + Level::Note | Level::OnceNote => AnnotationType::Note, Level::Help => AnnotationType::Help, // FIXME(#59346): Not sure how to map this level Level::FailureNote => AnnotationType::Error, diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 5c36c3c55b5..00ecbbbb93b 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -135,7 +135,12 @@ impl Diagnostic { | Level::Error { .. } | Level::FailureNote => true, - Level::Warning | Level::Note | Level::Help | Level::Allow | Level::Expect(_) => false, + Level::Warning + | Level::Note + | Level::OnceNote + | Level::Help + | Level::Allow + | Level::Expect(_) => false, } } @@ -335,11 +340,25 @@ impl Diagnostic { /// Prints the span with a note above it. /// This is like [`Diagnostic::note()`], but it gets its own span. + pub fn note_once(&mut self, msg: &str) -> &mut Self { + self.sub(Level::OnceNote, msg, MultiSpan::new(), None); + self + } + + /// Prints the span with a note above it. + /// This is like [`Diagnostic::note()`], but it gets its own span. pub fn span_note<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self { self.sub(Level::Note, msg, sp.into(), None); self } + /// Prints the span with a note above it. + /// This is like [`Diagnostic::note()`], but it gets its own span. + pub fn span_note_once<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self { + self.sub(Level::OnceNote, msg, sp.into(), None); + self + } + /// Add a warning attached to this diagnostic. pub fn warn(&mut self, msg: &str) -> &mut Self { self.sub(Level::Warning, msg, MultiSpan::new(), None); diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 72471638a96..088f6091528 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -128,7 +128,7 @@ impl EmissionGuarantee for ErrorGuaranteed { DiagnosticBuilderState::Emittable(handler) => { db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - let guar = handler.emit_diagnostic(&db.inner.diagnostic); + let guar = handler.emit_diagnostic(&mut db.inner.diagnostic); // Only allow a guarantee if the `level` wasn't switched to a // non-error - the field isn't `pub`, but the whole `Diagnostic` @@ -190,7 +190,7 @@ impl EmissionGuarantee for () { DiagnosticBuilderState::Emittable(handler) => { db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - handler.emit_diagnostic(&db.inner.diagnostic); + handler.emit_diagnostic(&mut db.inner.diagnostic); } // `.emit()` was previously called, disallowed from repeating it. DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} @@ -396,11 +396,17 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { ) -> &mut Self); forward!(pub fn note(&mut self, msg: &str) -> &mut Self); + forward!(pub fn note_once(&mut self, msg: &str) -> &mut Self); forward!(pub fn span_note( &mut self, sp: impl Into<MultiSpan>, msg: &str, ) -> &mut Self); + forward!(pub fn span_note_once( + &mut self, + sp: impl Into<MultiSpan>, + msg: &str, + ) -> &mut Self); forward!(pub fn warn(&mut self, msg: &str) -> &mut Self); forward!(pub fn span_warn(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> &mut Self); forward!(pub fn help(&mut self, msg: &str) -> &mut Self); @@ -500,11 +506,11 @@ impl Drop for DiagnosticBuilderInner<'_> { // No `.emit()` or `.cancel()` calls. DiagnosticBuilderState::Emittable(handler) => { if !panicking() { - handler.emit_diagnostic(&Diagnostic::new( + handler.emit_diagnostic(&mut Diagnostic::new( Level::Bug, "the following error was constructed but not emitted", )); - handler.emit_diagnostic(&self.diagnostic); + handler.emit_diagnostic(&mut self.diagnostic); panic!(); } } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 831d408195e..93b7201023a 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -542,7 +542,7 @@ impl Emitter for SilentEmitter { if let Some(ref note) = self.fatal_note { d.note(note); } - self.fatal_handler.emit_diagnostic(&d); + self.fatal_handler.emit_diagnostic(&mut d); } } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index c719e4910ce..2f2f6ed1a5a 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -4,6 +4,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(crate_visibility_modifier)] +#![feature(drain_filter)] #![feature(backtrace)] #![feature(if_let_guard)] #![feature(let_else)] @@ -919,7 +920,7 @@ impl Handler { self.inner.borrow_mut().force_print_diagnostic(db) } - pub fn emit_diagnostic(&self, diagnostic: &Diagnostic) -> Option<ErrorGuaranteed> { + pub fn emit_diagnostic(&self, diagnostic: &mut Diagnostic) -> Option<ErrorGuaranteed> { self.inner.borrow_mut().emit_diagnostic(diagnostic) } @@ -993,25 +994,25 @@ impl HandlerInner { self.taught_diagnostics.insert(code.clone()) } - fn force_print_diagnostic(&mut self, db: Diagnostic) { - self.emitter.emit_diagnostic(&db); + fn force_print_diagnostic(&mut self, mut db: Diagnostic) { + self.emitter.emit_diagnostic(&mut db); } /// Emit all stashed diagnostics. fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> { let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::<Vec<_>>(); let mut reported = None; - diags.iter().for_each(|diag| { + for mut diag in diags { if diag.is_error() { reported = Some(ErrorGuaranteed(())); } - self.emit_diagnostic(diag); - }); + self.emit_diagnostic(&mut diag); + } reported } // FIXME(eddyb) this should ideally take `diagnostic` by value. - fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) -> Option<ErrorGuaranteed> { + fn emit_diagnostic(&mut self, diagnostic: &mut Diagnostic) -> Option<ErrorGuaranteed> { if diagnostic.level == Level::DelayedBug { // FIXME(eddyb) this should check for `has_errors` and stop pushing // once *any* errors were emitted (and truncate `delayed_span_bugs` @@ -1070,7 +1071,23 @@ impl HandlerInner { // Only emit the diagnostic if we've been asked to deduplicate and // haven't already emitted an equivalent diagnostic. if !(self.flags.deduplicate_diagnostics && already_emitted(self)) { - self.emitter.emit_diagnostic(diagnostic); + debug!(?diagnostic); + debug!(?self.emitted_diagnostics); + let already_emitted_sub = |sub: &mut SubDiagnostic| { + debug!(?sub); + if sub.level != Level::OnceNote { + return false; + } + let mut hasher = StableHasher::new(); + sub.hash(&mut hasher); + let diagnostic_hash = hasher.finish(); + debug!(?diagnostic_hash); + !self.emitted_diagnostics.insert(diagnostic_hash) + }; + + diagnostic.children.drain_filter(already_emitted_sub).for_each(|_| {}); + + self.emitter.emit_diagnostic(&diagnostic); if diagnostic.is_error() { self.deduplicated_err_count += 1; } else if diagnostic.level == Warning { @@ -1221,22 +1238,22 @@ impl HandlerInner { let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg); diagnostic.set_span(sp.into()); diagnostic.note(&format!("delayed at {}", std::panic::Location::caller())); - self.emit_diagnostic(&diagnostic).unwrap() + self.emit_diagnostic(&mut diagnostic).unwrap() } // FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's // where the explanation of what "good path" is (also, it should be renamed). fn delay_good_path_bug(&mut self, msg: &str) { - let diagnostic = Diagnostic::new(Level::DelayedBug, msg); + let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg); if self.flags.report_delayed_bugs { - self.emit_diagnostic(&diagnostic); + self.emit_diagnostic(&mut diagnostic); } let backtrace = std::backtrace::Backtrace::force_capture(); self.delayed_good_path_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); } fn failure(&mut self, msg: &str) { - self.emit_diagnostic(&Diagnostic::new(FailureNote, msg)); + self.emit_diagnostic(&mut Diagnostic::new(FailureNote, msg)); } fn fatal(&mut self, msg: &str) -> FatalError { @@ -1253,11 +1270,11 @@ impl HandlerInner { if self.treat_err_as_bug() { self.bug(msg); } - self.emit_diagnostic(&Diagnostic::new(level, msg)).unwrap() + self.emit_diagnostic(&mut Diagnostic::new(level, msg)).unwrap() } fn bug(&mut self, msg: &str) -> ! { - self.emit_diagnostic(&Diagnostic::new(Bug, msg)); + self.emit_diagnostic(&mut Diagnostic::new(Bug, msg)); panic::panic_any(ExplicitBug); } @@ -1267,7 +1284,7 @@ impl HandlerInner { if no_bugs { // Put the overall explanation before the `DelayedBug`s, to // frame them better (e.g. separate warnings from them). - self.emit_diagnostic(&Diagnostic::new(Bug, explanation)); + self.emit_diagnostic(&mut Diagnostic::new(Bug, explanation)); no_bugs = false; } @@ -1283,7 +1300,7 @@ impl HandlerInner { } bug.level = Level::Bug; - self.emit_diagnostic(&bug); + self.emit_diagnostic(&mut bug); } // Panic with `ExplicitBug` to avoid "unexpected panic" messages. @@ -1350,6 +1367,8 @@ pub enum Level { }, Warning, Note, + /// A note that is only emitted once. + OnceNote, Help, FailureNote, Allow, @@ -1372,7 +1391,7 @@ impl Level { Warning => { spec.set_fg(Some(Color::Yellow)).set_intense(cfg!(windows)); } - Note => { + Note | OnceNote => { spec.set_fg(Some(Color::Green)).set_intense(true); } Help => { @@ -1389,7 +1408,7 @@ impl Level { Bug | DelayedBug => "error: internal compiler error", Fatal | Error { .. } => "error", Warning => "warning", - Note => "note", + Note | OnceNote => "note", Help => "help", FailureNote => "failure-note", Allow => panic!("Shouldn't call on allowed error"), diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index d6b308cdf85..7f569af4abd 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -10,7 +10,7 @@ use rustc_ast::{self as ast, AstLike, Attribute, Item, NodeId, PatKind}; use rustc_attr::{self as attr, Deprecation, Stability}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{self, Lrc}; -use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult}; +use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed}; use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; use rustc_lint_defs::BuiltinLintDiagnostics; use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS}; @@ -20,7 +20,7 @@ use rustc_span::edition::Edition; use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{FileName, MultiSpan, Span, DUMMY_SP}; +use rustc_span::{MultiSpan, Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; use std::default::Default; @@ -1128,41 +1128,6 @@ impl<'a> ExtCtxt<'a> { pub fn check_unused_macros(&mut self) { self.resolver.check_unused_macros(); } - - /// Resolves a `path` mentioned inside Rust code, returning an absolute path. - /// - /// This unifies the logic used for resolving `include_X!`. - /// - /// FIXME: move this to `rustc_builtin_macros` and make it private. - pub fn resolve_path(&self, path: impl Into<PathBuf>, span: Span) -> PResult<'a, PathBuf> { - let path = path.into(); - - // Relative paths are resolved relative to the file in which they are found - // after macro expansion (that is, they are unhygienic). - if !path.is_absolute() { - let callsite = span.source_callsite(); - let mut result = match self.source_map().span_to_filename(callsite) { - FileName::Real(name) => name - .into_local_path() - .expect("attempting to resolve a file path in an external file"), - FileName::DocTest(path, _) => path, - other => { - return Err(self.struct_span_err( - span, - &format!( - "cannot resolve relative path in non-file source `{}`", - self.source_map().filename_for_diagnostics(&other) - ), - )); - } - }; - result.pop(); - result.push(path); - Ok(result) - } else { - Ok(path) - } - } } /// Extracts a string literal from the macro expanded version of `expr`, diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 0aef5982cff..bfdf99762f5 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -1,22 +1,19 @@ use crate::base::ExtCtxt; use rustc_ast as ast; -use rustc_ast::token::{self, Nonterminal, NtIdent}; +use rustc_ast::token; use rustc_ast::tokenstream::{self, CanSynthesizeMissingTokens}; use rustc_ast::tokenstream::{DelimSpan, Spacing::*, TokenStream, TreeAndSpacing}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_errors::{Diagnostic, PResult}; -use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; -use rustc_lint_defs::BuiltinLintDiagnostics; use rustc_parse::lexer::nfc_normalize; use rustc_parse::{nt_to_tokenstream, parse_stream_from_source_str}; use rustc_session::parse::ParseSess; use rustc_span::def_id::CrateNum; -use rustc_span::hygiene::ExpnKind; use rustc_span::symbol::{self, kw, sym, Symbol}; -use rustc_span::{BytePos, FileName, MultiSpan, Pos, RealFileName, SourceFile, Span}; +use rustc_span::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span}; use pm::bridge::{server, TokenTree}; use pm::{Delimiter, Level, LineColumn, Spacing}; @@ -178,10 +175,8 @@ impl FromInternal<(TreeAndSpacing, &'_ mut Vec<Self>, &mut Rustc<'_, '_>)> tt!(Punct::new('#', false)) } - Interpolated(nt) - if let Some((name, is_raw)) = ident_name_compatibility_hack(&nt, span, rustc) => - { - TokenTree::Ident(Ident::new(rustc.sess(), name.name, is_raw, name.span)) + Interpolated(nt) if let NtIdent(ident, is_raw) = *nt => { + TokenTree::Ident(Ident::new(rustc.sess(), ident.name, is_raw, ident.span)) } Interpolated(nt) => { let stream = nt_to_tokenstream(&nt, rustc.sess(), CanSynthesizeMissingTokens::No); @@ -771,8 +766,8 @@ impl server::Diagnostic for Rustc<'_, '_> { ) { diag.sub(level.to_internal(), msg, MultiSpan::from_spans(spans), None); } - fn emit(&mut self, diag: Self::Diagnostic) { - self.sess().span_diagnostic.emit_diagnostic(&diag); + fn emit(&mut self, mut diag: Self::Diagnostic) { + self.sess().span_diagnostic.emit_diagnostic(&mut diag); } } @@ -868,100 +863,3 @@ impl server::Span for Rustc<'_, '_> { }) } } - -// See issue #74616 for details -fn ident_name_compatibility_hack( - nt: &Nonterminal, - orig_span: Span, - rustc: &mut Rustc<'_, '_>, -) -> Option<(rustc_span::symbol::Ident, bool)> { - if let NtIdent(ident, is_raw) = nt { - if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind { - let source_map = rustc.sess().source_map(); - let filename = source_map.span_to_filename(orig_span); - if let FileName::Real(RealFileName::LocalPath(path)) = filename { - let matches_prefix = |prefix, filename| { - // Check for a path that ends with 'prefix*/src/<filename>' - let mut iter = path.components().rev(); - iter.next().and_then(|p| p.as_os_str().to_str()) == Some(filename) - && iter.next().and_then(|p| p.as_os_str().to_str()) == Some("src") - && iter - .next() - .and_then(|p| p.as_os_str().to_str()) - .map_or(false, |p| p.starts_with(prefix)) - }; - - let time_macros_impl = - macro_name == sym::impl_macros && matches_prefix("time-macros-impl", "lib.rs"); - let js_sys = macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs"); - if time_macros_impl || js_sys { - let snippet = source_map.span_to_snippet(orig_span); - if snippet.as_deref() == Ok("$name") { - if time_macros_impl { - rustc.sess().buffer_lint_with_diagnostic( - &PROC_MACRO_BACK_COMPAT, - orig_span, - ast::CRATE_NODE_ID, - "using an old version of `time-macros-impl`", - BuiltinLintDiagnostics::ProcMacroBackCompat( - "the `time-macros-impl` crate will stop compiling in futures version of Rust. \ - Please update to the latest version of the `time` crate to avoid breakage".to_string()) - ); - return Some((*ident, *is_raw)); - } - if js_sys { - if let Some(c) = path - .components() - .flat_map(|c| c.as_os_str().to_str()) - .find(|c| c.starts_with("js-sys")) - { - let mut version = c.trim_start_matches("js-sys-").split('.'); - if version.next() == Some("0") - && version.next() == Some("3") - && version - .next() - .and_then(|c| c.parse::<u32>().ok()) - .map_or(false, |v| v < 40) - { - rustc.sess().buffer_lint_with_diagnostic( - &PROC_MACRO_BACK_COMPAT, - orig_span, - ast::CRATE_NODE_ID, - "using an old version of `js-sys`", - BuiltinLintDiagnostics::ProcMacroBackCompat( - "older versions of the `js-sys` crate will stop compiling in future versions of Rust; \ - please update to `js-sys` v0.3.40 or above".to_string()) - ); - return Some((*ident, *is_raw)); - } - } - } - } - } - - if macro_name == sym::tuple_from_req && matches_prefix("actix-web", "extract.rs") { - let snippet = source_map.span_to_snippet(orig_span); - if snippet.as_deref() == Ok("$T") { - if let FileName::Real(RealFileName::LocalPath(macro_path)) = - source_map.span_to_filename(rustc.def_site) - { - if macro_path.to_string_lossy().contains("pin-project-internal-0.") { - rustc.sess().buffer_lint_with_diagnostic( - &PROC_MACRO_BACK_COMPAT, - orig_span, - ast::CRATE_NODE_ID, - "using an old version of `actix-web`", - BuiltinLintDiagnostics::ProcMacroBackCompat( - "the version of `actix-web` you are using might stop compiling in future versions of Rust; \ - please update to the latest version of the `actix-web` crate to avoid breakage".to_string()) - ); - return Some((*ident, *is_raw)); - } - } - } - } - } - } - } - None -} diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index b13f0b0d3da..9b328842056 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -111,7 +111,7 @@ use rustc_fs_util::{link_or_copy, LinkOrCopy}; use rustc_session::{Session, StableCrateId}; use std::fs as std_fs; -use std::io; +use std::io::{self, ErrorKind}; use std::mem; use std::path::{Path, PathBuf}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; @@ -371,7 +371,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) { let new_path = incr_comp_session_dir.parent().unwrap().join(new_sub_dir_name); debug!("finalize_session_directory() - new path: {}", new_path.display()); - match std_fs::rename(&*incr_comp_session_dir, &new_path) { + match rename_path_with_retry(&*incr_comp_session_dir, &new_path, 3) { Ok(_) => { debug!("finalize_session_directory() - directory renamed successfully"); @@ -961,3 +961,24 @@ fn safe_remove_file(p: &Path) -> io::Result<()> { result => result, } } + +// On Windows the compiler would sometimes fail to rename the session directory because +// the OS thought something was still being accessed in it. So we retry a few times to give +// the OS time to catch up. +// See https://github.com/rust-lang/rust/issues/86929. +fn rename_path_with_retry(from: &Path, to: &Path, mut retries_left: usize) -> std::io::Result<()> { + loop { + match std_fs::rename(from, to) { + Ok(()) => return Ok(()), + Err(e) => { + if retries_left > 0 && e.kind() == ErrorKind::PermissionDenied { + // Try again after a short waiting period. + std::thread::sleep(Duration::from_millis(50)); + retries_left -= 1; + } else { + return Err(e); + } + } + } + } +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index abc25d51776..238145c5c6e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -333,6 +333,9 @@ pub fn same_type_modulo_infer<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { ) | (&ty::Infer(ty::InferTy::TyVar(_)), _) | (_, &ty::Infer(ty::InferTy::TyVar(_))) => true, + (&ty::Ref(reg_a, ty_a, mut_a), &ty::Ref(reg_b, ty_b, mut_b)) => { + reg_a == reg_b && mut_a == mut_b && same_type_modulo_infer(*ty_a, *ty_b) + } _ => a == b, } } @@ -602,7 +605,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { match *cause.code() { ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => { let ty = self.resolve_vars_if_possible(root_ty); - if ty.is_suggestable() { + if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_))) + { // don't show type `_` err.span_label(span, format!("this expression has type `{}`", ty)); } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2886d921c70..83ba9c96978 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1434,6 +1434,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { value.fold_with(&mut r) } + pub fn resolve_numeric_literals_with_default<T>(&self, value: T) -> T + where + T: TypeFoldable<'tcx>, + { + if !value.needs_infer() { + return value; // Avoid duplicated subst-folding. + } + let mut r = InferenceLiteralEraser { tcx: self.tcx }; + value.fold_with(&mut r) + } + /// Returns the first unresolved variable contained in `T`. In the /// process of visiting `T`, this will resolve (where possible) /// type variables in `T`, but it never constructs the final, @@ -1785,6 +1796,26 @@ impl<'tcx> TyOrConstInferVar<'tcx> { } } +/// Replace `{integer}` with `i32` and `{float}` with `f64`. +/// Used only for diagnostics. +struct InferenceLiteralEraser<'tcx> { + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> TypeFolder<'tcx> for InferenceLiteralEraser<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + match ty.kind() { + ty::Infer(ty::IntVar(_) | ty::FreshIntTy(_)) => self.tcx.types.i32, + ty::Infer(ty::FloatVar(_) | ty::FreshFloatTy(_)) => self.tcx.types.f64, + _ => ty.super_fold_with(self), + } + } +} + struct ShallowResolver<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index dc1fe5f2b08..1f0cd907f8a 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -12,7 +12,7 @@ use rustc_session::lint::{ builtin::{self, FORBIDDEN_LINT_GROUPS}, FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId, }; -use rustc_session::{DiagnosticMessageId, Session}; +use rustc_session::Session; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan}; use rustc_span::{symbol, Span, Symbol, DUMMY_SP}; @@ -245,7 +245,6 @@ impl<'a> LintDiagnosticBuilder<'a, ErrorGuaranteed> { } pub fn explain_lint_level_source( - sess: &Session, lint: &'static Lint, level: Level, src: LintLevelSource, @@ -254,11 +253,7 @@ pub fn explain_lint_level_source( let name = lint.name_lower(); match src { LintLevelSource::Default => { - sess.diag_note_once( - err, - DiagnosticMessageId::from(lint), - &format!("`#[{}({})]` on by default", level.as_str(), name), - ); + err.note_once(&format!("`#[{}({})]` on by default", level.as_str(), name)); } LintLevelSource::CommandLine(lint_flag_val, orig_level) => { let flag = match orig_level { @@ -273,46 +268,29 @@ pub fn explain_lint_level_source( }; let hyphen_case_lint_name = name.replace('_', "-"); if lint_flag_val.as_str() == name { - sess.diag_note_once( - err, - DiagnosticMessageId::from(lint), - &format!( - "requested on the command line with `{} {}`", - flag, hyphen_case_lint_name - ), - ); + err.note_once(&format!( + "requested on the command line with `{} {}`", + flag, hyphen_case_lint_name + )); } else { let hyphen_case_flag_val = lint_flag_val.as_str().replace('_', "-"); - sess.diag_note_once( - err, - DiagnosticMessageId::from(lint), - &format!( - "`{} {}` implied by `{} {}`", - flag, hyphen_case_lint_name, flag, hyphen_case_flag_val - ), - ); + err.note_once(&format!( + "`{} {}` implied by `{} {}`", + flag, hyphen_case_lint_name, flag, hyphen_case_flag_val + )); } } LintLevelSource::Node(lint_attr_name, src, reason) => { if let Some(rationale) = reason { err.note(rationale.as_str()); } - sess.diag_span_note_once( - err, - DiagnosticMessageId::from(lint), - src, - "the lint level is defined here", - ); + err.span_note_once(src, "the lint level is defined here"); if lint_attr_name.as_str() != name { let level_str = level.as_str(); - sess.diag_note_once( - err, - DiagnosticMessageId::from(lint), - &format!( - "`#[{}({})]` implied by `#[{}({})]`", - level_str, name, level_str, lint_attr_name - ), - ); + err.note_once(&format!( + "`#[{}({})]` implied by `#[{}({})]`", + level_str, name, level_str, lint_attr_name + )); } } } @@ -412,7 +390,7 @@ pub fn struct_lint_level<'s, 'd>( return; } - explain_lint_level_source(sess, lint, level, src, &mut err); + explain_lint_level_source(lint, level, src, &mut err); let name = lint.name_lower(); let is_force_warn = matches!(level, Level::ForceWarn); diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 219af6caa1a..fd6e241346d 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -17,9 +17,9 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE}; use rustc_session::lint::{BuiltinLintDiagnostics, Level, Lint, LintBuffer}; use rustc_session::parse::feature_err_issue; -use rustc_session::{DiagnosticMessageId, Session}; +use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::{MultiSpan, Span}; +use rustc_span::Span; use std::num::NonZeroU32; #[derive(PartialEq, Clone, Copy, Debug)] @@ -94,30 +94,15 @@ pub fn report_unstable( None => format!("use of unstable library feature '{}'", &feature), }; - let msp: MultiSpan = span.into(); - let sm = &sess.parse_sess.source_map(); - let span_key = msp.primary_span().and_then(|sp: Span| { - if !sp.is_dummy() { - let file = sm.lookup_char_pos(sp.lo()).file; - if file.is_imported() { None } else { Some(span) } - } else { - None - } - }); - - let error_id = (DiagnosticMessageId::StabilityId(issue), span_key, msg.clone()); - let fresh = sess.one_time_diagnostics.borrow_mut().insert(error_id); - if fresh { - if is_soft { - soft_handler(SOFT_UNSTABLE, span, &msg) - } else { - let mut err = - feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), &msg); - if let Some((inner_types, ref msg, sugg, applicability)) = suggestion { - err.span_suggestion(inner_types, msg, sugg, applicability); - } - err.emit(); + if is_soft { + soft_handler(SOFT_UNSTABLE, span, &msg) + } else { + let mut err = + feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), &msg); + if let Some((inner_types, ref msg, sugg, applicability)) = suggestion { + err.span_suggestion(inner_types, msg, sugg, applicability); } + err.emit(); } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index ea71cff1616..eec6eed311b 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -45,6 +45,7 @@ use std::{iter, mem, option}; use self::graph_cyclic_cache::GraphIsCyclicCache; use self::predecessors::{PredecessorCache, Predecessors}; pub use self::query::*; +use self::switch_sources::{SwitchSourceCache, SwitchSources}; pub mod coverage; mod generic_graph; @@ -58,6 +59,7 @@ mod predecessors; pub mod pretty; mod query; pub mod spanview; +mod switch_sources; pub mod tcx; pub mod terminator; pub use terminator::*; @@ -296,6 +298,7 @@ pub struct Body<'tcx> { pub is_polymorphic: bool, predecessor_cache: PredecessorCache, + switch_source_cache: SwitchSourceCache, is_cyclic: GraphIsCyclicCache, pub tainted_by_errors: Option<ErrorGuaranteed>, @@ -344,6 +347,7 @@ impl<'tcx> Body<'tcx> { required_consts: Vec::new(), is_polymorphic: false, predecessor_cache: PredecessorCache::new(), + switch_source_cache: SwitchSourceCache::new(), is_cyclic: GraphIsCyclicCache::new(), tainted_by_errors, }; @@ -372,6 +376,7 @@ impl<'tcx> Body<'tcx> { var_debug_info: Vec::new(), is_polymorphic: false, predecessor_cache: PredecessorCache::new(), + switch_source_cache: SwitchSourceCache::new(), is_cyclic: GraphIsCyclicCache::new(), tainted_by_errors: None, }; @@ -392,6 +397,7 @@ impl<'tcx> Body<'tcx> { // FIXME: Use a finer-grained API for this, so only transformations that alter terminators // invalidate the caches. self.predecessor_cache.invalidate(); + self.switch_source_cache.invalidate(); self.is_cyclic.invalidate(); &mut self.basic_blocks } @@ -401,6 +407,7 @@ impl<'tcx> Body<'tcx> { &mut self, ) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) { self.predecessor_cache.invalidate(); + self.switch_source_cache.invalidate(); self.is_cyclic.invalidate(); (&mut self.basic_blocks, &mut self.local_decls) } @@ -414,6 +421,7 @@ impl<'tcx> Body<'tcx> { &mut Vec<VarDebugInfo<'tcx>>, ) { self.predecessor_cache.invalidate(); + self.switch_source_cache.invalidate(); self.is_cyclic.invalidate(); (&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info) } @@ -542,6 +550,11 @@ impl<'tcx> Body<'tcx> { } #[inline] + pub fn switch_sources(&self) -> &SwitchSources { + self.switch_source_cache.compute(&self.basic_blocks) + } + + #[inline] pub fn dominators(&self) -> Dominators<BasicBlock> { dominators(self) } diff --git a/compiler/rustc_middle/src/mir/switch_sources.rs b/compiler/rustc_middle/src/mir/switch_sources.rs new file mode 100644 index 00000000000..7f62b4d0dba --- /dev/null +++ b/compiler/rustc_middle/src/mir/switch_sources.rs @@ -0,0 +1,82 @@ +//! Lazily compute the inverse of each `SwitchInt`'s switch targets. Modeled after +//! `Predecessors`/`PredecessorCache`. + +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::sync::OnceCell; +use rustc_index::vec::IndexVec; +use rustc_serialize as serialize; +use smallvec::SmallVec; + +use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind}; + +pub type SwitchSources = IndexVec<BasicBlock, IndexVec<BasicBlock, SmallVec<[Option<u128>; 1]>>>; + +#[derive(Clone, Debug)] +pub(super) struct SwitchSourceCache { + cache: OnceCell<SwitchSources>, +} + +impl SwitchSourceCache { + #[inline] + pub(super) fn new() -> Self { + SwitchSourceCache { cache: OnceCell::new() } + } + + /// Invalidates the switch source cache. + #[inline] + pub(super) fn invalidate(&mut self) { + self.cache = OnceCell::new(); + } + + /// Returns the switch sources for this MIR. + #[inline] + pub(super) fn compute( + &self, + basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>, + ) -> &SwitchSources { + self.cache.get_or_init(|| { + let mut switch_sources = IndexVec::from_elem( + IndexVec::from_elem(SmallVec::new(), basic_blocks), + basic_blocks, + ); + for (bb, data) in basic_blocks.iter_enumerated() { + if let Some(Terminator { + kind: TerminatorKind::SwitchInt { targets, .. }, .. + }) = &data.terminator + { + for (value, target) in targets.iter() { + switch_sources[target][bb].push(Some(value)); + } + switch_sources[targets.otherwise()][bb].push(None); + } + } + + switch_sources + }) + } +} + +impl<S: serialize::Encoder> serialize::Encodable<S> for SwitchSourceCache { + #[inline] + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + s.emit_unit() + } +} + +impl<D: serialize::Decoder> serialize::Decodable<D> for SwitchSourceCache { + #[inline] + fn decode(_: &mut D) -> Self { + Self::new() + } +} + +impl<CTX> HashStable<CTX> for SwitchSourceCache { + #[inline] + fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) { + // do nothing + } +} + +TrivialTypeFoldableAndLiftImpls! { + SwitchSourceCache, +} diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 102e7439772..93118dfeb77 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -248,6 +248,7 @@ impl Direction for Backward { ); propagate(pred, &tmp); } + mir::TerminatorKind::InlineAsm { destination: Some(dest), ref operands, .. } if dest == bb => { @@ -266,6 +267,23 @@ impl Direction for Backward { propagate(pred, &tmp); } + mir::TerminatorKind::SwitchInt { targets: _, ref discr, switch_ty: _ } => { + let mut applier = BackwardSwitchIntEdgeEffectsApplier { + pred, + exit_state, + values: &body.switch_sources()[bb][pred], + bb, + propagate: &mut propagate, + effects_applied: false, + }; + + analysis.apply_switch_int_edge_effects(pred, discr, &mut applier); + + if !applier.effects_applied { + propagate(pred, exit_state) + } + } + // Ignore dead unwinds. mir::TerminatorKind::Call { cleanup: Some(unwind), .. } | mir::TerminatorKind::Assert { cleanup: Some(unwind), .. } @@ -286,6 +304,37 @@ impl Direction for Backward { } } +struct BackwardSwitchIntEdgeEffectsApplier<'a, D, F> { + pred: BasicBlock, + exit_state: &'a mut D, + values: &'a [Option<u128>], + bb: BasicBlock, + propagate: &'a mut F, + + effects_applied: bool, +} + +impl<D, F> super::SwitchIntEdgeEffects<D> for BackwardSwitchIntEdgeEffectsApplier<'_, D, F> +where + D: Clone, + F: FnMut(BasicBlock, &D), +{ + fn apply(&mut self, mut apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)) { + assert!(!self.effects_applied); + + let targets = self.values.iter().map(|&value| SwitchIntTarget { value, target: self.bb }); + + let mut tmp = None; + for target in targets { + let tmp = opt_clone_from_or_clone(&mut tmp, self.exit_state); + apply_edge_effect(tmp, target); + (self.propagate)(self.pred, tmp); + } + + self.effects_applied = true; + } +} + /// Dataflow that runs from the entry of a block (the first statement), to its exit (terminator). pub struct Forward; @@ -528,7 +577,7 @@ impl Direction for Forward { } SwitchInt { ref targets, ref discr, switch_ty: _ } => { - let mut applier = SwitchIntEdgeEffectApplier { + let mut applier = ForwardSwitchIntEdgeEffectsApplier { exit_state, targets, propagate, @@ -537,8 +586,11 @@ impl Direction for Forward { analysis.apply_switch_int_edge_effects(bb, discr, &mut applier); - let SwitchIntEdgeEffectApplier { - exit_state, mut propagate, effects_applied, .. + let ForwardSwitchIntEdgeEffectsApplier { + exit_state, + mut propagate, + effects_applied, + .. } = applier; if !effects_applied { @@ -551,7 +603,7 @@ impl Direction for Forward { } } -struct SwitchIntEdgeEffectApplier<'a, D, F> { +struct ForwardSwitchIntEdgeEffectsApplier<'a, D, F> { exit_state: &'a mut D, targets: &'a SwitchTargets, propagate: F, @@ -559,7 +611,7 @@ struct SwitchIntEdgeEffectApplier<'a, D, F> { effects_applied: bool, } -impl<D, F> super::SwitchIntEdgeEffects<D> for SwitchIntEdgeEffectApplier<'_, D, F> +impl<D, F> super::SwitchIntEdgeEffects<D> for ForwardSwitchIntEdgeEffectsApplier<'_, D, F> where D: Clone, F: FnMut(BasicBlock, &D), diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index c51dd06de25..67c16e6c084 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -234,8 +234,6 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { /// about a given `SwitchInt` terminator for each one of its edges—and more efficient—the /// engine doesn't need to clone the exit state for a block unless /// `SwitchIntEdgeEffects::apply` is actually called. - /// - /// FIXME: This class of effects is not supported for backward dataflow analyses. fn apply_switch_int_edge_effects( &self, _block: BasicBlock, diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 6c2d1b85646..c221b358670 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -28,7 +28,7 @@ pub use self::drop_flag_effects::{ pub use self::framework::{ fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, CallReturnPlaces, Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, - ResultsRefCursor, ResultsVisitable, ResultsVisitor, + ResultsRefCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, }; use self::move_paths::MoveData; diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index f8d0e448ce7..8de05990cdf 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -554,7 +554,6 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) { tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, usage_lint_root); assert_eq!(level, Level::Allow); lint::explain_lint_level_source( - tcx.sess, UNSAFE_OP_IN_UNSAFE_FN, Level::Allow, source, diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index a3e66464fbc..0ce86a764f4 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -49,8 +49,8 @@ macro_rules! panictry_buffer { match $e { Ok(e) => e, Err(errs) => { - for e in errs { - $handler.emit_diagnostic(&e); + for mut e in errs { + $handler.emit_diagnostic(&mut e); } FatalError.raise() } @@ -167,8 +167,8 @@ fn try_file_to_source_file( fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>) -> Lrc<SourceFile> { match try_file_to_source_file(sess, path, spanopt) { Ok(source_file) => source_file, - Err(d) => { - sess.span_diagnostic.emit_diagnostic(&d); + Err(mut d) => { + sess.span_diagnostic.emit_diagnostic(&mut d); FatalError.raise(); } } diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 07ce879de8f..93663a349f5 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -272,7 +272,23 @@ impl<'a> Parser<'a> { lo, ty_generics, )?; - self.expect_gt()?; + self.expect_gt().map_err(|mut err| { + // Attempt to find places where a missing `>` might belong. + if let Some(arg) = args + .iter() + .rev() + .skip_while(|arg| matches!(arg, AngleBracketedArg::Constraint(_))) + .next() + { + err.span_suggestion_verbose( + arg.span().shrink_to_hi(), + "you might have meant to end the type parameters here", + ">".to_string(), + Applicability::MaybeIncorrect, + ); + } + err + })?; let span = lo.to(self.prev_token.span); AngleBracketedArgs { args, span }.into() } else { @@ -462,6 +478,23 @@ impl<'a> Parser<'a> { while let Some(arg) = self.parse_angle_arg(ty_generics)? { args.push(arg); if !self.eat(&token::Comma) { + if self.token.kind == token::Semi + && self.look_ahead(1, |t| t.is_ident() || t.is_lifetime()) + { + // Add `>` to the list of expected tokens. + self.check(&token::Gt); + // Handle `,` to `;` substitution + let mut err = self.unexpected::<()>().unwrap_err(); + self.bump(); + err.span_suggestion_verbose( + self.prev_token.span.until(self.token.span), + "use a comma to separate type parameters", + ", ".to_string(), + Applicability::MachineApplicable, + ); + err.emit(); + continue; + } if !self.token.kind.should_end_const_arg() { if self.handle_ambiguous_unbraced_const_arg(&mut args)? { // We've managed to (partially) recover, so continue trying to parse diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index a080b4a3e9a..f7655e55d34 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -784,8 +784,8 @@ impl<K: DepKind> DepGraph<K> { let handle = tcx.dep_context().sess().diagnostic(); - for diagnostic in side_effects.diagnostics { - handle.emit_diagnostic(&diagnostic); + for mut diagnostic in side_effects.diagnostics { + handle.emit_diagnostic(&mut diagnostic); } } } diff --git a/compiler/rustc_session/src/cgu_reuse_tracker.rs b/compiler/rustc_session/src/cgu_reuse_tracker.rs index a9e14754334..dd64e8ab71e 100644 --- a/compiler/rustc_session/src/cgu_reuse_tracker.rs +++ b/compiler/rustc_session/src/cgu_reuse_tracker.rs @@ -52,7 +52,7 @@ impl CguReuseTracker { pub fn set_actual_reuse(&self, cgu_name: &str, kind: CguReuse) { if let Some(ref data) = self.data { - debug!("set_actual_reuse({:?}, {:?})", cgu_name, kind); + debug!("set_actual_reuse({cgu_name:?}, {kind:?})"); let prev_reuse = data.lock().unwrap().actual_reuse.insert(cgu_name.to_string(), kind); @@ -74,7 +74,7 @@ impl CguReuseTracker { comparison_kind: ComparisonKind, ) { if let Some(ref data) = self.data { - debug!("set_expectation({:?}, {:?}, {:?})", cgu_name, expected_reuse, comparison_kind); + debug!("set_expectation({cgu_name:?}, {expected_reuse:?}, {comparison_kind:?})"); let mut data = data.lock().unwrap(); data.expected_reuse.insert( @@ -100,17 +100,15 @@ impl CguReuseTracker { if error { let at_least = if at_least { "at least " } else { "" }; let msg = format!( - "CGU-reuse for `{}` is `{:?}` but \ - should be {}`{:?}`", - cgu_user_name, actual_reuse, at_least, expected_reuse + "CGU-reuse for `{cgu_user_name}` is `{actual_reuse:?}` but \ + should be {at_least}`{expected_reuse:?}`" ); diag.span_err(error_span.0, &msg); } } else { let msg = format!( - "CGU-reuse for `{}` (mangled: `{}`) was \ - not recorded", - cgu_user_name, cgu_name + "CGU-reuse for `{cgu_user_name}` (mangled: `{cgu_name}`) was \ + not recorded" ); diag.span_fatal(error_span.0, &msg) } diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs index c263da69c35..cbb03ffd7a0 100644 --- a/compiler/rustc_session/src/code_stats.rs +++ b/compiler/rustc_session/src/code_stats.rs @@ -91,15 +91,15 @@ impl CodeStats { } }); - for info in &sorted { + for info in sorted { + let TypeSizeInfo { type_description, overall_size, align, kind, variants, .. } = info; println!( - "print-type-size type: `{}`: {} bytes, alignment: {} bytes", - info.type_description, info.overall_size, info.align + "print-type-size type: `{type_description}`: {overall_size} bytes, alignment: {align} bytes" ); let indent = " "; let discr_size = if let Some(discr_size) = info.opt_discr_size { - println!("print-type-size {}discriminant: {} bytes", indent, discr_size); + println!("print-type-size {indent}discriminant: {discr_size} bytes"); discr_size } else { 0 @@ -111,11 +111,11 @@ impl CodeStats { // to reflect the presence of the discriminant. let mut max_variant_size = discr_size; - let struct_like = match info.kind { + let struct_like = match kind { DataTypeKind::Struct | DataTypeKind::Closure => true, DataTypeKind::Enum | DataTypeKind::Union => false, }; - for (i, variant_info) in info.variants.iter().enumerate() { + for (i, variant_info) in variants.into_iter().enumerate() { let VariantInfo { ref name, kind: _, align: _, size, ref fields } = *variant_info; let indent = if !struct_like { let name = match name.as_ref() { @@ -123,10 +123,8 @@ impl CodeStats { None => i.to_string(), }; println!( - "print-type-size {}variant `{}`: {} bytes", - indent, - name, - size - discr_size + "print-type-size {indent}variant `{name}`: {diff} bytes", + diff = size - discr_size ); " " } else { @@ -144,30 +142,28 @@ impl CodeStats { let mut fields = fields.clone(); fields.sort_by_key(|f| (f.offset, f.size)); - for field in fields.iter() { - let FieldInfo { ref name, offset, size, align } = *field; + for field in fields { + let FieldInfo { ref name, offset, size, align } = field; if offset > min_offset { let pad = offset - min_offset; - println!("print-type-size {}padding: {} bytes", indent, pad); + println!("print-type-size {indent}padding: {pad} bytes"); } if offset < min_offset { // If this happens it's probably a union. println!( - "print-type-size {}field `.{}`: {} bytes, \ - offset: {} bytes, \ - alignment: {} bytes", - indent, name, size, offset, align + "print-type-size {indent}field `.{name}`: {size} bytes, \ + offset: {offset} bytes, \ + alignment: {align} bytes" ); } else if info.packed || offset == min_offset { - println!("print-type-size {}field `.{}`: {} bytes", indent, name, size); + println!("print-type-size {indent}field `.{name}`: {size} bytes"); } else { // Include field alignment in output only if it caused padding injection println!( - "print-type-size {}field `.{}`: {} bytes, \ - alignment: {} bytes", - indent, name, size, align + "print-type-size {indent}field `.{name}`: {size} bytes, \ + alignment: {align} bytes" ); } @@ -175,18 +171,10 @@ impl CodeStats { } } - assert!( - max_variant_size <= info.overall_size, - "max_variant_size {} !<= {} overall_size", - max_variant_size, - info.overall_size - ); - if max_variant_size < info.overall_size { - println!( - "print-type-size {}end padding: {} bytes", - indent, - info.overall_size - max_variant_size - ); + match overall_size.checked_sub(max_variant_size) { + None => panic!("max_variant_size {max_variant_size} > {overall_size} overall_size"), + Some(diff @ 1..) => println!("print-type-size {indent}end padding: {diff} bytes"), + Some(0) => {} } } } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 2357f5ad903..44a2e2bdc85 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -659,7 +659,7 @@ impl OutputFilenames { single_output_file, temps_directory, outputs, - filestem: format!("{}{}", out_filestem, extra), + filestem: format!("{out_filestem}{extra}"), } } @@ -1514,7 +1514,7 @@ pub fn get_cmd_lint_options( let lint_cap = matches.opt_str("cap-lints").map(|cap| { lint::Level::from_str(&cap) - .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{}`", cap))) + .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{cap}`"))) }); (lint_opts, describe_lints, lint_cap) @@ -1533,8 +1533,7 @@ pub fn parse_color(matches: &getopts::Matches) -> ColorConfig { ErrorOutputType::default(), &format!( "argument for `--color` must be auto, \ - always or never (instead was `{}`)", - arg + always or never (instead was `{arg}`)" ), ), } @@ -1579,7 +1578,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig { "future-incompat" => json_future_incompat = true, s => early_error( ErrorOutputType::default(), - &format!("unknown `--json` option `{}`", s), + &format!("unknown `--json` option `{s}`"), ), } } @@ -1619,8 +1618,7 @@ pub fn parse_error_format( ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)), &format!( "argument for `--error-format` must be `human`, `json` or \ - `short` (instead was `{}`)", - arg + `short` (instead was `{arg}`)" ), ), } @@ -1654,8 +1652,7 @@ pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition { ErrorOutputType::default(), &format!( "argument for `--edition` must be one of: \ - {}. (instead was `{}`)", - EDITION_NAME_LIST, arg + {EDITION_NAME_LIST}. (instead was `{arg}`)" ), ) }), @@ -1670,7 +1667,7 @@ pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition { edition, LATEST_STABLE_EDITION ) } else { - format!("edition {} is unstable and only available with -Z unstable-options", edition) + format!("edition {edition} is unstable and only available with -Z unstable-options") }; early_error(ErrorOutputType::default(), &msg) } @@ -1718,9 +1715,8 @@ fn parse_output_types( early_error( error_format, &format!( - "unknown emission type: `{}` - expected one of: {}", - shorthand, - OutputType::shorthands_display(), + "unknown emission type: `{shorthand}` - expected one of: {display}", + display = OutputType::shorthands_display(), ), ) }); @@ -1758,9 +1754,8 @@ fn should_override_cgus_and_disable_thinlto( early_warn( error_format, &format!( - "`--emit={}` with `-o` incompatible with \ + "`--emit={ot}` with `-o` incompatible with \ `-C codegen-units=N` for N > 1", - ot ), ); } @@ -1835,7 +1830,7 @@ fn collect_print_requests( } } "link-args" => PrintRequest::LinkArgs, - req => early_error(error_format, &format!("unknown print request `{}`", req)), + req => early_error(error_format, &format!("unknown print request `{req}`")), })); prints @@ -1849,7 +1844,7 @@ pub fn parse_target_triple( Some(target) if target.ends_with(".json") => { let path = Path::new(&target); TargetTriple::from_path(&path).unwrap_or_else(|_| { - early_error(error_format, &format!("target file {:?} does not exist", path)) + early_error(error_format, &format!("target file {path:?} does not exist")) }) } Some(target) => TargetTriple::TargetTriple(target), @@ -1892,8 +1887,7 @@ fn parse_opt_level( error_format, &format!( "optimization level needs to be \ - between 0-3, s or z (instead was `{}`)", - arg + between 0-3, s or z (instead was `{arg}`)" ), ); } @@ -1927,8 +1921,7 @@ fn select_debuginfo( error_format, &format!( "debug info level needs to be between \ - 0-2 (instead was `{}`)", - arg + 0-2 (instead was `{arg}`)" ), ); } @@ -1943,10 +1936,9 @@ crate fn parse_assert_incr_state( match opt_assertion { Some(s) if s.as_str() == "loaded" => Some(IncrementalStateAssertion::Loaded), Some(s) if s.as_str() == "not-loaded" => Some(IncrementalStateAssertion::NotLoaded), - Some(s) => early_error( - error_format, - &format!("unexpected incremental state assertion value: {}", s), - ), + Some(s) => { + early_error(error_format, &format!("unexpected incremental state assertion value: {s}")) + } None => None, } } @@ -1991,7 +1983,7 @@ fn parse_native_lib_kind( } s => early_error( error_format, - &format!("unknown library kind `{}`, expected one of dylib, framework, or static", s), + &format!("unknown library kind `{s}`, expected one of dylib, framework, or static"), ), }; match modifiers { @@ -2066,9 +2058,8 @@ fn parse_native_lib_modifiers( _ => early_error( error_format, &format!( - "unrecognized linking modifier `{}`, expected one \ - of: bundle, verbatim, whole-archive, as-needed", - modifier + "unrecognized linking modifier `{modifier}`, expected one \ + of: bundle, verbatim, whole-archive, as-needed" ), ), } @@ -2109,7 +2100,7 @@ fn parse_borrowck_mode(dopts: &DebuggingOptions, error_format: ErrorOutputType) match dopts.borrowck.as_ref() { "migrate" => BorrowckMode::Migrate, "mir" => BorrowckMode::Mir, - m => early_error(error_format, &format!("unknown borrowck mode `{}`", m)), + m => early_error(error_format, &format!("unknown borrowck mode `{m}`")), } } @@ -2197,7 +2188,7 @@ pub fn parse_externs( ); } } - _ => early_error(error_format, &format!("unknown --extern option `{}`", opt)), + _ => early_error(error_format, &format!("unknown --extern option `{opt}`")), } } } @@ -2234,7 +2225,7 @@ fn parse_extern_dep_specs( let loc = parts.next().unwrap_or_else(|| { early_error( error_format, - &format!("`--extern-location`: specify location for extern crate `{}`", name), + &format!("`--extern-location`: specify location for extern crate `{name}`"), ) }); @@ -2255,14 +2246,14 @@ fn parse_extern_dep_specs( let json = json::from_str(raw).unwrap_or_else(|_| { early_error( error_format, - &format!("`--extern-location`: malformed json location `{}`", raw), + &format!("`--extern-location`: malformed json location `{raw}`"), ) }); ExternDepSpec::Json(json) } [bad, ..] => early_error( error_format, - &format!("unknown location type `{}`: use `raw` or `json`", bad), + &format!("unknown location type `{bad}`: use `raw` or `json`"), ), [] => early_error(error_format, "missing location specification"), }; @@ -2527,9 +2518,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { && !target_triple.triple().contains("apple") && cg.split_debuginfo.is_some() { - { - early_error(error_format, "`-Csplit-debuginfo` is unstable on this platform"); - } + early_error(error_format, "`-Csplit-debuginfo` is unstable on this platform"); } // Try to find a directory containing the Rust `src`, for more details see @@ -2561,7 +2550,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { }; let working_dir = std::env::current_dir().unwrap_or_else(|e| { - early_error(error_format, &format!("Current directory is invalid: {}", e)); + early_error(error_format, &format!("Current directory is invalid: {e}")); }); let (path, remapped) = @@ -2636,12 +2625,11 @@ fn parse_pretty(debugging_opts: &DebuggingOptions, efmt: ErrorOutputType) -> Opt "argument to `unpretty` must be one of `normal`, `identified`, \ `expanded`, `expanded,identified`, `expanded,hygiene`, \ `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \ - `hir,typed`, `hir-tree`, `thir-tree`, `mir` or `mir-cfg`; got {}", - name + `hir,typed`, `hir-tree`, `thir-tree`, `mir` or `mir-cfg`; got {name}" ), ), }; - tracing::debug!("got unpretty option: {:?}", first); + tracing::debug!("got unpretty option: {first:?}"); Some(first) } @@ -2667,7 +2655,7 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy "cdylib" => CrateType::Cdylib, "bin" => CrateType::Executable, "proc-macro" => CrateType::ProcMacro, - _ => return Err(format!("unknown crate type: `{}`", part)), + _ => return Err(format!("unknown crate type: `{part}`")), }; if !crate_types.contains(&new_part) { crate_types.push(new_part) diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 9200be363ad..c973e3140ce 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -85,7 +85,7 @@ pub fn get_or_default_sysroot() -> PathBuf { p.pop(); p } - Err(e) => panic!("failed to get current_exe: {}", e), + Err(e) => panic!("failed to get current_exe: {e}"), } } diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 2db217d9716..bd4e37f1ab7 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -1,5 +1,6 @@ #![feature(crate_visibility_modifier)] #![feature(derive_default_enum)] +#![feature(let_chains)] #![feature(let_else)] #![feature(min_specialization)] #![feature(once_cell)] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 0289b962a5a..463c5c9d8b5 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -345,14 +345,13 @@ fn build_options<O: Default>( Some(value) => early_error( error_format, &format!( - "incorrect value `{}` for {} option `{}` - {} was expected", - value, outputname, key, type_desc + "incorrect value `{value}` for {outputname} option `{key}` - {type_desc} was expected" ), ), } } } - None => early_error(error_format, &format!("unknown {} option: `{}`", outputname, key)), + None => early_error(error_format, &format!("unknown {outputname} option: `{key}`")), } } return op; diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index 7f696da86f2..e5e6579d75b 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -63,8 +63,7 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) if name.as_str() != s { let msg = format!( "`--crate-name` and `#[crate_name]` are \ - required to match, but `{}` != `{}`", - s, name + required to match, but `{s}` != `{name}`" ); sess.span_err(attr.span, &msg); } @@ -80,8 +79,7 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) if s.starts_with('-') { let msg = format!( "crate names cannot start with a `-`, but \ - `{}` has a leading hyphen", - s + `{s}` has a leading hyphen" ); sess.err(&msg); } else { @@ -113,7 +111,7 @@ pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) { if c == '_' { continue; } - say(&format!("invalid character `{}` in crate name: `{}`", c, s)); + say(&format!("invalid character `{c}` in crate name: `{s}`")); } } @@ -137,7 +135,7 @@ pub fn filename_for_metadata( let out_filename = outputs .single_output_file .clone() - .unwrap_or_else(|| outputs.out_directory.join(&format!("lib{}.rmeta", libname))); + .unwrap_or_else(|| outputs.out_directory.join(&format!("lib{libname}.rmeta"))); check_file_is_writeable(&out_filename, sess); @@ -153,14 +151,14 @@ pub fn filename_for_input( let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename); match crate_type { - CrateType::Rlib => outputs.out_directory.join(&format!("lib{}.rlib", libname)), + CrateType::Rlib => outputs.out_directory.join(&format!("lib{libname}.rlib")), CrateType::Cdylib | CrateType::ProcMacro | CrateType::Dylib => { let (prefix, suffix) = (&sess.target.dll_prefix, &sess.target.dll_suffix); - outputs.out_directory.join(&format!("{}{}{}", prefix, libname, suffix)) + outputs.out_directory.join(&format!("{prefix}{libname}{suffix}")) } CrateType::Staticlib => { let (prefix, suffix) = (&sess.target.staticlib_prefix, &sess.target.staticlib_suffix); - outputs.out_directory.join(&format!("{}{}{}", prefix, libname, suffix)) + outputs.out_directory.join(&format!("{prefix}{libname}{suffix}")) } CrateType::Executable => { let suffix = &sess.target.exe_suffix; @@ -185,24 +183,18 @@ pub fn default_output_for_target(sess: &Session) -> CrateType { /// Checks if target supports crate_type as output pub fn invalid_output_for_target(sess: &Session, crate_type: CrateType) -> bool { - match crate_type { - CrateType::Cdylib | CrateType::Dylib | CrateType::ProcMacro => { - if !sess.target.dynamic_linking { - return true; - } - if sess.crt_static(Some(crate_type)) && !sess.target.crt_static_allows_dylibs { - return true; - } + if let CrateType::Cdylib | CrateType::Dylib | CrateType::ProcMacro = crate_type { + if !sess.target.dynamic_linking { + return true; } - _ => {} - } - if sess.target.only_cdylib { - match crate_type { - CrateType::ProcMacro | CrateType::Dylib => return true, - _ => {} + if sess.crt_static(Some(crate_type)) && !sess.target.crt_static_allows_dylibs { + return true; } } - if !sess.target.executables && crate_type == CrateType::Executable { + if let CrateType::ProcMacro | CrateType::Dylib = crate_type && sess.target.only_cdylib { + return true; + } + if let CrateType::Executable = crate_type && !sess.target.executables { return true; } diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 36bbccf1b90..6f0c4761841 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -120,14 +120,13 @@ pub fn add_feature_diagnostics_for_issue<'a>( ) { if let Some(n) = find_feature_issue(feature, issue) { err.note(&format!( - "see issue #{} <https://github.com/rust-lang/rust/issues/{}> for more information", - n, n, + "see issue #{n} <https://github.com/rust-lang/rust/issues/{n}> for more information" )); } // #23973: do not suggest `#![feature(...)]` if we are in beta/stable if sess.unstable_features.is_nightly_build() { - err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature)); + err.help(&format!("add `#![feature({feature})]` to the crate attributes to enable")); } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 7eeb6f90f99..4876e2eb851 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -19,7 +19,7 @@ use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter; use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType}; use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; -use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed}; +use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed}; use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; use rustc_span::edition::Edition; @@ -35,7 +35,6 @@ use std::cell::{self, RefCell}; use std::env; use std::fmt; use std::io::Write; -use std::num::NonZeroU32; use std::ops::{Div, Mul}; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -88,7 +87,7 @@ impl From<usize> for Limit { impl fmt::Display for Limit { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) + self.0.fmt(f) } } @@ -136,10 +135,6 @@ pub struct Session { /// `None` means that there is no source file. pub local_crate_source_file: Option<PathBuf>, - /// Set of `(DiagnosticId, Option<Span>, message)` tuples tracking - /// (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)>>, crate_types: OnceCell<Vec<CrateType>>, /// The `stable_crate_id` is constructed out of the crate name and all the /// `-C metadata` arguments passed to the compiler. Its value forms a unique @@ -209,13 +204,6 @@ pub struct PerfStats { pub normalize_projection_ty: AtomicUsize, } -/// Enum to support dispatch of one-time diagnostics (in `Session.diag_once`). -enum DiagnosticBuilderMethod { - Note, - SpanNote, - // Add more variants as needed to support one-time diagnostics. -} - /// Trait implemented by error types. This should not be implemented manually. Instead, use /// `#[derive(SessionDiagnostic)]` -- see [rustc_macros::SessionDiagnostic]. pub trait SessionDiagnostic<'a> { @@ -224,21 +212,6 @@ pub trait SessionDiagnostic<'a> { fn into_diagnostic(self, sess: &'a Session) -> DiagnosticBuilder<'a, ErrorGuaranteed>; } -/// Diagnostic message ID, used by `Session.one_time_diagnostics` to avoid -/// emitting the same message more than once. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub enum DiagnosticMessageId { - ErrorId(u16), // EXXXX error code as integer - LintId(lint::LintId), - StabilityId(Option<NonZeroU32>), // issue number -} - -impl From<&'static lint::Lint> for DiagnosticMessageId { - fn from(lint: &'static lint::Lint) -> Self { - DiagnosticMessageId::LintId(lint::LintId::of(lint)) - } -} - impl Session { pub fn miri_unleashed_feature(&self, span: Span, feature_gate: Option<Symbol>) { self.miri_unleashed_features.lock().push((span, feature_gate)); @@ -252,8 +225,8 @@ impl Session { let mut diag = self.struct_warn("skipping const checks"); for &(span, feature_gate) in unleashed_features.iter() { // FIXME: `span_label` doesn't do anything, so we use "help" as a hack. - if let Some(feature_gate) = feature_gate { - diag.span_help(span, &format!("skipping check for `{}` feature", feature_gate)); + if let Some(gate) = feature_gate { + diag.span_help(span, &format!("skipping check for `{gate}` feature")); // The unleash flag must *not* be used to just "hack around" feature gates. must_err = true; } else { @@ -497,50 +470,6 @@ impl Session { &self.parse_sess.span_diagnostic } - /// Analogous to calling methods on the given `DiagnosticBuilder`, but - /// deduplicates on lint ID, span (if any), and message for this `Session` - fn diag_once( - &self, - diag: &mut Diagnostic, - method: DiagnosticBuilderMethod, - msg_id: DiagnosticMessageId, - message: &str, - span_maybe: Option<Span>, - ) { - let id_span_message = (msg_id, span_maybe, message.to_owned()); - let fresh = self.one_time_diagnostics.borrow_mut().insert(id_span_message); - if fresh { - match method { - DiagnosticBuilderMethod::Note => { - diag.note(message); - } - DiagnosticBuilderMethod::SpanNote => { - let span = span_maybe.expect("`span_note` needs a span"); - diag.span_note(span, message); - } - } - } - } - - pub fn diag_span_note_once( - &self, - diag: &mut Diagnostic, - msg_id: DiagnosticMessageId, - span: Span, - message: &str, - ) { - self.diag_once(diag, DiagnosticBuilderMethod::SpanNote, msg_id, message, Some(span)); - } - - pub fn diag_note_once( - &self, - diag: &mut Diagnostic, - msg_id: DiagnosticMessageId, - message: &str, - ) { - self.diag_once(diag, DiagnosticBuilderMethod::Note, msg_id, message, None); - } - #[inline] pub fn source_map(&self) -> &SourceMap { self.parse_sess.source_map() @@ -1204,7 +1133,7 @@ pub fn build_session( let target_cfg = config::build_target_config(&sopts, target_override, &sysroot); let host_triple = TargetTriple::from_triple(config::host_triple()); let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| { - early_error(sopts.error_format, &format!("Error loading host specification: {}", e)) + early_error(sopts.error_format, &format!("Error loading host specification: {e}")) }); for warning in target_warnings.warning_messages() { early_warn(sopts.error_format, &warning) @@ -1243,7 +1172,7 @@ pub fn build_session( match profiler { Ok(profiler) => Some(Arc::new(profiler)), Err(e) => { - early_warn(sopts.error_format, &format!("failed to create profiler: {}", e)); + early_warn(sopts.error_format, &format!("failed to create profiler: {e}")); None } } @@ -1306,7 +1235,6 @@ pub fn build_session( parse_sess, sysroot, local_crate_source_file, - one_time_diagnostics: Default::default(), crate_types: OnceCell::new(), stable_crate_id: OnceCell::new(), features: OnceCell::new(), @@ -1407,7 +1335,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { // Cannot mix and match sanitizers. let mut sanitizer_iter = sess.opts.debugging_opts.sanitizer.into_iter(); if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) { - sess.err(&format!("`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`", first, second)); + sess.err(&format!("`-Zsanitizer={first}` is incompatible with `-Zsanitizer={second}`")); } // Cannot enable crt-static with sanitizers on Linux diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none_hermitkernel.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none_hermitkernel.rs deleted file mode 100644 index 6e9d6c6221c..00000000000 --- a/compiler/rustc_target/src/spec/aarch64_unknown_none_hermitkernel.rs +++ /dev/null @@ -1,16 +0,0 @@ -use crate::spec::Target; - -pub fn target() -> Target { - let mut base = super::hermit_kernel_base::opts(); - base.max_atomic_width = Some(128); - base.abi = "softfloat".to_string(); - base.features = "+strict-align,-neon,-fp-armv8".to_string(); - - Target { - llvm_target: "aarch64-unknown-hermit".to_string(), - pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), - arch: "aarch64".to_string(), - options: base, - } -} diff --git a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs index 3e3a6ac82a4..84105fbad47 100644 --- a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs +++ b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs @@ -37,6 +37,7 @@ pub fn target() -> Target { pre_link_args, exe_suffix: ".elf".to_string(), no_default_libraries: false, + has_thread_local: true, ..Default::default() }, } diff --git a/compiler/rustc_target/src/spec/hermit_kernel_base.rs b/compiler/rustc_target/src/spec/hermit_kernel_base.rs deleted file mode 100644 index ce3dad26458..00000000000 --- a/compiler/rustc_target/src/spec/hermit_kernel_base.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions}; - -pub fn opts() -> TargetOptions { - let mut pre_link_args = LinkArgs::new(); - pre_link_args.insert( - LinkerFlavor::Lld(LldFlavor::Ld), - vec!["--build-id".to_string(), "--hash-style=gnu".to_string(), "--Bstatic".to_string()], - ); - - TargetOptions { - linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), - disable_redzone: true, - linker: Some("rust-lld".to_owned()), - executables: true, - pre_link_args, - panic_strategy: PanicStrategy::Abort, - position_independent_executables: true, - static_position_independent_executables: true, - ..Default::default() - } -} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 4f0c3bec1ee..f2ca28ba5f9 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -63,7 +63,6 @@ mod freebsd_base; mod fuchsia_base; mod haiku_base; mod hermit_base; -mod hermit_kernel_base; mod illumos_base; mod l4re_base; mod linux_base; @@ -971,9 +970,6 @@ supported_targets! { ("aarch64-unknown-hermit", aarch64_unknown_hermit), ("x86_64-unknown-hermit", x86_64_unknown_hermit), - ("aarch64-unknown-none-hermitkernel", aarch64_unknown_none_hermitkernel), - ("x86_64-unknown-none-hermitkernel", x86_64_unknown_none_hermitkernel), - ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf), ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf), ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf), diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none_hermitkernel.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none_hermitkernel.rs deleted file mode 100644 index 359cb0f6881..00000000000 --- a/compiler/rustc_target/src/spec/x86_64_unknown_none_hermitkernel.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::spec::{StackProbeType, Target}; - -pub fn target() -> Target { - let mut base = super::hermit_kernel_base::opts(); - base.cpu = "x86-64".to_string(); - base.max_atomic_width = Some(64); - base.features = - "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float" - .to_string(); - // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved - base.stack_probes = StackProbeType::Call; - - Target { - llvm_target: "x86_64-unknown-hermit".to_string(), - pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .to_string(), - arch: "x86_64".to_string(), - options: base, - } -} diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index 46c74660f86..5b88cff03d7 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -5,7 +5,7 @@ use rustc_hir as hir; use rustc_infer::infer::InferCtxt; use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt}; use rustc_middle::ty::{ToPredicate, TypeFoldable}; -use rustc_session::{DiagnosticMessageId, Limit}; +use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::Span; @@ -222,24 +222,19 @@ pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Spa Limit(0) => Limit(2), limit => 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); - if fresh { - struct_span_err!( - tcx.sess, - span, - E0055, - "reached the recursion limit while auto-dereferencing `{:?}`", - ty - ) - .span_label(span, "deref recursion limit reached") - .help(&format!( - "consider increasing the recursion limit by adding a \ + struct_span_err!( + tcx.sess, + span, + E0055, + "reached the recursion limit while auto-dereferencing `{:?}`", + ty + ) + .span_label(span, "deref recursion limit reached") + .help(&format!( + "consider increasing the recursion limit by adding a \ `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)", - suggested_limit, - tcx.crate_name(LOCAL_CRATE), - )) - .emit(); - } + suggested_limit, + tcx.crate_name(LOCAL_CRATE), + )) + .emit(); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 5e220173cae..468c7a3c55b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -28,7 +28,6 @@ use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{ self, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, }; -use rustc_session::DiagnosticMessageId; use rustc_span::symbol::{kw, sym}; use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP}; use std::fmt; @@ -1406,60 +1405,49 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { } } - let msg = format!("type mismatch resolving `{}`", predicate); - let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg); - let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); - if fresh { - let mut diag = struct_span_err!( - self.tcx.sess, - obligation.cause.span, - E0271, - "type mismatch resolving `{}`", - predicate - ); - let secondary_span = match predicate.kind().skip_binder() { - ty::PredicateKind::Projection(proj) => self - .tcx - .opt_associated_item(proj.projection_ty.item_def_id) - .and_then(|trait_assoc_item| { + let mut diag = struct_span_err!( + self.tcx.sess, + obligation.cause.span, + E0271, + "type mismatch resolving `{}`", + predicate + ); + let secondary_span = match predicate.kind().skip_binder() { + ty::PredicateKind::Projection(proj) => self + .tcx + .opt_associated_item(proj.projection_ty.item_def_id) + .and_then(|trait_assoc_item| { + self.tcx + .trait_of_item(proj.projection_ty.item_def_id) + .map(|id| (trait_assoc_item, id)) + }) + .and_then(|(trait_assoc_item, id)| { + let trait_assoc_ident = trait_assoc_item.ident(self.tcx); + self.tcx.find_map_relevant_impl(id, proj.projection_ty.self_ty(), |did| { self.tcx - .trait_of_item(proj.projection_ty.item_def_id) - .map(|id| (trait_assoc_item, id)) - }) - .and_then(|(trait_assoc_item, id)| { - let trait_assoc_ident = trait_assoc_item.ident(self.tcx); - self.tcx.find_map_relevant_impl( - id, - proj.projection_ty.self_ty(), - |did| { - self.tcx - .associated_items(did) - .in_definition_order() - .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident) - }, - ) + .associated_items(did) + .in_definition_order() + .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident) }) - .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) { - Some( - hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Type(_, Some(ty)), - .. - }) - | hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::TyAlias(ty), - .. - }), - ) => { - Some((ty.span, format!("type mismatch resolving `{}`", predicate))) - } - _ => None, - }), - _ => None, - }; - self.note_type_err(&mut diag, &obligation.cause, secondary_span, values, err, true); - self.note_obligation_cause(&mut diag, obligation); - diag.emit(); - } + }) + .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) { + Some( + hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Type(_, Some(ty)), + .. + }) + | hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::TyAlias(ty), + .. + }), + ) => Some((ty.span, format!("type mismatch resolving `{}`", predicate))), + _ => None, + }), + _ => None, + }; + self.note_type_err(&mut diag, &obligation.cause, secondary_span, values, err, true); + self.note_obligation_cause(&mut diag, obligation); + diag.emit(); }); } @@ -1966,7 +1954,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { if self.is_tainted_by_errors() && crate_names.len() == 1 - && crate_names[0] == "`core`" + && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str()) && spans.len() == 0 { // Avoid complaining about other inference issues for expressions like diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 754172b1158..a07700aa9f5 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -11,6 +11,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::GenericArg; +use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::ty::{ self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, Ty, TyCtxt, }; @@ -83,7 +84,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Some(param_local_id) = param.def_id.as_local() { let param_hir_id = tcx.hir().local_def_id_to_hir_id(param_local_id); let param_name = tcx.hir().ty_param_name(param_hir_id); - let param_type = tcx.type_of(param.def_id); + let param_type = tcx.infer_ctxt().enter(|infcx| { + infcx.resolve_numeric_literals_with_default(tcx.type_of(param.def_id)) + }); if param_type.is_suggestable() { err.span_suggestion( tcx.def_span(src_def_id), diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 0a720f15025..e5784259ce8 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -32,6 +32,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; +use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, HirId, QPath}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -1556,7 +1557,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if inaccessible_remaining_fields { self.report_inaccessible_fields(adt_ty, span); } else { - self.report_missing_fields(adt_ty, span, remaining_fields); + self.report_missing_fields( + adt_ty, + span, + remaining_fields, + variant, + ast_fields, + substs, + ); } } } @@ -1590,6 +1598,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { adt_ty: Ty<'tcx>, span: Span, remaining_fields: FxHashMap<Ident, (usize, &ty::FieldDef)>, + variant: &'tcx ty::VariantDef, + ast_fields: &'tcx [hir::ExprField<'tcx>], + substs: SubstsRef<'tcx>, ) { let len = remaining_fields.len(); @@ -1615,7 +1626,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - struct_span_err!( + let mut err = struct_span_err!( self.tcx.sess, span, E0063, @@ -1624,9 +1635,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { remaining_fields_names, truncated_fields_error, adt_ty - ) - .span_label(span, format!("missing {}{}", remaining_fields_names, truncated_fields_error)) - .emit(); + ); + err.span_label( + span, + format!("missing {}{}", remaining_fields_names, truncated_fields_error), + ); + + // If the last field is a range literal, but it isn't supposed to be, then they probably + // meant to use functional update syntax. + // + // I don't use 'is_range_literal' because only double-sided, half-open ranges count. + if let Some(( + last, + ExprKind::Struct( + QPath::LangItem(LangItem::Range, ..), + &[ref range_start, ref range_end], + _, + ), + )) = ast_fields.last().map(|last| (last, &last.expr.kind)) && + let variant_field = + variant.fields.iter().find(|field| field.ident(self.tcx) == last.ident) && + let range_def_id = self.tcx.lang_items().range_struct() && + variant_field + .and_then(|field| field.ty(self.tcx, substs).ty_adt_def()) + .map(|adt| adt.did()) + != range_def_id + { + let instead = self + .tcx + .sess + .source_map() + .span_to_snippet(range_end.expr.span) + .map(|s| format!(" from `{s}`")) + .unwrap_or(String::new()); + err.span_suggestion( + range_start.span.shrink_to_hi(), + &format!("to set the remaining fields{instead}, separate the last named field with a comma"), + ",".to_string(), + Applicability::MaybeIncorrect, + ); + } + + err.emit(); } /// Report an error for a struct field expression when there are invisible fields. diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 67d61668b6d..e6a98ad6dc0 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -521,6 +521,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { can_suggest: bool, fn_id: hir::HirId, ) -> bool { + let found = + self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(found)); // Only suggest changing the return type for methods that // haven't set a return type at all (and aren't `fn main()` or an impl). match (&fn_decl.output, found.is_suggestable(), can_suggest, expected.is_unit()) { @@ -528,13 +530,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion( span, "try adding a return type", - format!("-> {} ", self.resolve_vars_with_obligations(found)), + format!("-> {} ", found), Applicability::MachineApplicable, ); true } (&hir::FnRetTy::DefaultReturn(span), false, true, true) => { - err.span_label(span, "possibly return type missing here?"); + // FIXME: if `found` could be `impl Iterator` or `impl Fn*`, we should suggest + // that. + err.span_suggestion( + span, + "a return type might be missing here", + "-> _ ".to_string(), + Applicability::HasPlaceholders, + ); true } (&hir::FnRetTy::DefaultReturn(span), _, false, true) => { diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 16ffabb76a5..c1cb9a1a8d1 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -467,8 +467,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { if !errors_buffer.is_empty() { errors_buffer.sort_by_key(|diag| diag.span.primary_span()); - for diag in errors_buffer.drain(..) { - self.tcx().sess.diagnostic().emit_diagnostic(&diag); + for mut diag in errors_buffer.drain(..) { + self.tcx().sess.diagnostic().emit_diagnostic(&mut diag); } } } diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 71419c15196..71b6b9b41f5 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1038,7 +1038,7 @@ impl String { } /// Tries to reserve the minimum capacity for exactly `additional` more elements to - /// be inserted in the given `String`. After calling `reserve_exact`, + /// be inserted in the given `String`. After calling `try_reserve_exact`, /// capacity will be greater than or equal to `self.len() + additional`. /// Does nothing if the capacity is already sufficient. /// diff --git a/library/alloc/tests/fmt.rs b/library/alloc/tests/fmt.rs index 1575a5999f9..67e12c612db 100644 --- a/library/alloc/tests/fmt.rs +++ b/library/alloc/tests/fmt.rs @@ -69,7 +69,7 @@ fn test_format_macro_interface() { t!(format!("{:?}", "true"), "\"true\""); t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\""); t!(format!("{:?}", "foo\n\"bar\"\r\n\'baz\'\t\\qux\\"), r#""foo\n\"bar\"\r\n'baz'\t\\qux\\""#); - t!(format!("{:?}", "foo\0bar\x01baz\u{7f}q\u{75}x"), r#""foo\u{0}bar\u{1}baz\u{7f}qux""#); + t!(format!("{:?}", "foo\0bar\x01baz\u{7f}q\u{75}x"), r#""foo\0bar\u{1}baz\u{7f}qux""#); t!(format!("{:o}", 10_usize), "12"); t!(format!("{:x}", 10_usize), "a"); t!(format!("{:X}", 10_usize), "A"); diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index cbb86265233..abce47e5afe 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -10,7 +10,6 @@ #![feature(const_intrinsic_copy)] #![feature(const_mut_refs)] #![feature(const_nonnull_slice_from_raw_parts)] -#![feature(const_ptr_offset)] #![feature(const_ptr_write)] #![feature(const_try)] #![feature(core_intrinsics)] diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs index f3ed611acda..32396e35696 100644 --- a/library/alloc/tests/str.rs +++ b/library/alloc/tests/str.rs @@ -1116,7 +1116,7 @@ fn test_escape_debug() { assert_eq!("abc".escape_debug().to_string(), "abc"); assert_eq!("a c".escape_debug().to_string(), "a c"); assert_eq!("éèê".escape_debug().to_string(), "éèê"); - assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t"); + assert_eq!("\0\r\n\t".escape_debug().to_string(), "\\0\\r\\n\\t"); assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\"); assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}"); assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}"); diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 66de94d1b92..f75cd74ee2d 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -421,6 +421,7 @@ impl char { #[inline] pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug { let init_state = match self { + '\0' => EscapeDefaultState::Backslash('0'), '\t' => EscapeDefaultState::Backslash('t'), '\r' => EscapeDefaultState::Backslash('r'), '\n' => EscapeDefaultState::Backslash('n'), diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 22c6c1cd868..129402ad23a 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1168,7 +1168,7 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is [`pointer::offset`]. #[must_use = "returns a new pointer rather than modifying its argument"] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] pub fn offset<T>(dst: *const T, offset: isize) -> *const T; /// Calculates the offset from a pointer, potentially wrapping. @@ -1185,7 +1185,7 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is [`pointer::wrapping_offset`]. #[must_use = "returns a new pointer rather than modifying its argument"] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T; /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 145c5ee109d..22b76ea66ff 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -243,13 +243,12 @@ //! ``` //! //! While many collections offer `iter()`, not all offer `iter_mut()`. For -//! example, mutating the keys of a [`HashSet<T>`] or [`HashMap<K, V>`] could -//! put the collection into an inconsistent state if the key hashes change, so -//! these collections only offer `iter()`. +//! example, mutating the keys of a [`HashSet<T>`] could put the collection +//! into an inconsistent state if the key hashes change, so this collection +//! only offers `iter()`. //! //! [`into_iter()`]: IntoIterator::into_iter //! [`HashSet<T>`]: ../../std/collections/struct.HashSet.html -//! [`HashMap<K, V>`]: ../../std/collections/struct.HashMap.html //! //! # Adapters //! diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 1a85e2ef7b6..5c16346cbd1 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -126,7 +126,6 @@ #![feature(const_pin)] #![feature(const_replace)] #![feature(const_ptr_is_null)] -#![feature(const_ptr_offset)] #![feature(const_ptr_offset_from)] #![feature(const_ptr_read)] #![feature(const_ptr_write)] diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 19953afb4fe..8cdd98149ad 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -285,7 +285,7 @@ impl<T: ?Sized> *const T { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "returns a new pointer rather than modifying its argument"] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline(always)] pub const unsafe fn offset(self, count: isize) -> *const T where @@ -347,7 +347,7 @@ impl<T: ?Sized> *const T { /// ``` #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")] #[must_use = "returns a new pointer rather than modifying its argument"] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline(always)] pub const fn wrapping_offset(self, count: isize) -> *const T where @@ -566,7 +566,7 @@ impl<T: ?Sized> *const T { /// ``` #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline(always)] pub const unsafe fn add(self, count: usize) -> Self where @@ -630,7 +630,7 @@ impl<T: ?Sized> *const T { /// ``` #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline] pub const unsafe fn sub(self, count: usize) -> Self where @@ -693,7 +693,7 @@ impl<T: ?Sized> *const T { /// ``` #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline(always)] pub const fn wrapping_add(self, count: usize) -> Self where @@ -755,7 +755,7 @@ impl<T: ?Sized> *const T { /// ``` #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline] pub const fn wrapping_sub(self, count: usize) -> Self where diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 861412703d3..0c5b16aa01d 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -295,7 +295,7 @@ impl<T: ?Sized> *mut T { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "returns a new pointer rather than modifying its argument"] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline(always)] pub const unsafe fn offset(self, count: isize) -> *mut T where @@ -358,7 +358,7 @@ impl<T: ?Sized> *mut T { /// ``` #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")] #[must_use = "returns a new pointer rather than modifying its argument"] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline(always)] pub const fn wrapping_offset(self, count: isize) -> *mut T where @@ -680,7 +680,7 @@ impl<T: ?Sized> *mut T { /// ``` #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline(always)] pub const unsafe fn add(self, count: usize) -> Self where @@ -744,7 +744,7 @@ impl<T: ?Sized> *mut T { /// ``` #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline] pub const unsafe fn sub(self, count: usize) -> Self where @@ -807,7 +807,7 @@ impl<T: ?Sized> *mut T { /// ``` #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline(always)] pub const fn wrapping_add(self, count: usize) -> Self where @@ -869,7 +869,7 @@ impl<T: ?Sized> *mut T { /// ``` #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline] pub const fn wrapping_sub(self, count: usize) -> Self where diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 1dba24dd149..c02a6f2d78c 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -172,6 +172,7 @@ impl_fn_for_zst! { /// documentation for more information. #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] #[derive(Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct EscapeAscii<'a> { inner: iter::FlatMap<super::Iter<'a, u8>, ascii::EscapeDefault, EscapeByte>, } diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 3353c239866..a23de54ef20 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -549,7 +549,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeToInclusive<usize> { /// /// use std::slice; /// -/// slice::range(2..1, ..3); +/// let _ = slice::range(2..1, ..3); /// ``` /// /// ```should_panic @@ -557,7 +557,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeToInclusive<usize> { /// /// use std::slice; /// -/// slice::range(1..4, ..3); +/// let _ = slice::range(1..4, ..3); /// ``` /// /// ```should_panic @@ -565,12 +565,13 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeToInclusive<usize> { /// /// use std::slice; /// -/// slice::range(1..=usize::MAX, ..3); +/// let _ = slice::range(1..=usize::MAX, ..3); /// ``` /// /// [`Index::index`]: ops::Index::index #[track_caller] #[unstable(feature = "slice_range", issue = "76393")] +#[must_use] pub fn range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize> where R: ops::RangeBounds<usize>, diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 82bd7dbcf6c..22662f7d18d 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -62,6 +62,7 @@ fn size_from_ptr<T>(_: *const T) -> usize { /// [`iter`]: slice::iter /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct Iter<'a, T: 'a> { ptr: NonNull<T>, end: *const T, // If T is a ZST, this is actually ptr+len. This encoding is picked so that @@ -182,6 +183,7 @@ impl<T> AsRef<[T]> for Iter<'_, T> { /// [`iter_mut`]: slice::iter_mut /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct IterMut<'a, T: 'a> { ptr: NonNull<T>, end: *mut T, // If T is a ZST, this is actually ptr+len. This encoding is picked so that @@ -339,6 +341,7 @@ pub(super) trait SplitIter: DoubleEndedIterator { /// [`split`]: slice::split /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct Split<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -469,6 +472,7 @@ impl<T, P> FusedIterator for Split<'_, T, P> where P: FnMut(&T) -> bool {} /// [`split_inclusive`]: slice::split_inclusive /// [slices]: slice #[stable(feature = "split_inclusive", since = "1.51.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct SplitInclusive<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -589,6 +593,7 @@ impl<T, P> FusedIterator for SplitInclusive<'_, T, P> where P: FnMut(&T) -> bool /// [`split_mut`]: slice::split_mut /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct SplitMut<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -718,6 +723,7 @@ impl<T, P> FusedIterator for SplitMut<'_, T, P> where P: FnMut(&T) -> bool {} /// [`split_inclusive_mut`]: slice::split_inclusive_mut /// [slices]: slice #[stable(feature = "split_inclusive", since = "1.51.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct SplitInclusiveMut<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -841,6 +847,7 @@ impl<T, P> FusedIterator for SplitInclusiveMut<'_, T, P> where P: FnMut(&T) -> b /// [`rsplit`]: slice::rsplit /// [slices]: slice #[stable(feature = "slice_rsplit", since = "1.27.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RSplit<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -937,6 +944,7 @@ impl<T, P> FusedIterator for RSplit<'_, T, P> where P: FnMut(&T) -> bool {} /// [`rsplit_mut`]: slice::rsplit_mut /// [slices]: slice #[stable(feature = "slice_rsplit", since = "1.27.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RSplitMut<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -1059,6 +1067,7 @@ impl<T, I: SplitIter<Item = T>> Iterator for GenericSplitN<I> { /// [`splitn`]: slice::splitn /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct SplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -1099,6 +1108,7 @@ where /// [`rsplitn`]: slice::rsplitn /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -1138,6 +1148,7 @@ where /// [`splitn_mut`]: slice::splitn_mut /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct SplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -1178,6 +1189,7 @@ where /// [`rsplitn_mut`]: slice::rsplitn_mut /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -1222,6 +1234,7 @@ forward_iterator! { RSplitNMut: T, &'a mut [T] } /// [slices]: slice #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct Windows<'a, T: 'a> { v: &'a [T], size: NonZeroUsize, @@ -1370,6 +1383,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for Windows<'a, T> { /// [slices]: slice #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct Chunks<'a, T: 'a> { v: &'a [T], chunk_size: usize, @@ -1553,6 +1567,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for Chunks<'a, T> { /// [slices]: slice #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ChunksMut<'a, T: 'a> { v: &'a mut [T], chunk_size: usize, @@ -1722,6 +1737,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for ChunksMut<'a, T> { /// [slices]: slice #[derive(Debug)] #[stable(feature = "chunks_exact", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ChunksExact<'a, T: 'a> { v: &'a [T], rem: &'a [T], @@ -1881,6 +1897,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for ChunksExact<'a, T> { /// [slices]: slice #[derive(Debug)] #[stable(feature = "chunks_exact", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ChunksExactMut<'a, T: 'a> { v: &'a mut [T], rem: &'a mut [T], @@ -2034,6 +2051,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for ChunksExactMut<'a, T> { /// [slices]: slice #[derive(Debug, Clone, Copy)] #[unstable(feature = "array_windows", issue = "75027")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ArrayWindows<'a, T: 'a, const N: usize> { slice_head: *const T, num: usize, @@ -2156,6 +2174,7 @@ impl<T, const N: usize> ExactSizeIterator for ArrayWindows<'_, T, N> { /// [slices]: slice #[derive(Debug)] #[unstable(feature = "array_chunks", issue = "74985")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ArrayChunks<'a, T: 'a, const N: usize> { iter: Iter<'a, [T; N]>, rem: &'a [T], @@ -2282,6 +2301,7 @@ unsafe impl<'a, T, const N: usize> TrustedRandomAccessNoCoerce for ArrayChunks<' /// [slices]: slice #[derive(Debug)] #[unstable(feature = "array_chunks", issue = "74985")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ArrayChunksMut<'a, T: 'a, const N: usize> { iter: IterMut<'a, [T; N]>, rem: &'a mut [T], @@ -2396,6 +2416,7 @@ unsafe impl<'a, T, const N: usize> TrustedRandomAccessNoCoerce for ArrayChunksMu /// [slices]: slice #[derive(Debug)] #[stable(feature = "rchunks", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RChunks<'a, T: 'a> { v: &'a [T], chunk_size: usize, @@ -2569,6 +2590,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunks<'a, T> { /// [slices]: slice #[derive(Debug)] #[stable(feature = "rchunks", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RChunksMut<'a, T: 'a> { v: &'a mut [T], chunk_size: usize, @@ -2742,6 +2764,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunksMut<'a, T> { /// [slices]: slice #[derive(Debug)] #[stable(feature = "rchunks", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RChunksExact<'a, T: 'a> { v: &'a [T], rem: &'a [T], @@ -2905,6 +2928,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunksExact<'a, T> { /// [slices]: slice #[derive(Debug)] #[stable(feature = "rchunks", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RChunksExactMut<'a, T: 'a> { v: &'a mut [T], rem: &'a mut [T], @@ -3071,6 +3095,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for IterMut<'a, T> { /// [`group_by`]: slice::group_by /// [slices]: slice #[unstable(feature = "slice_group_by", issue = "80552")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct GroupBy<'a, T: 'a, P> { slice: &'a [T], predicate: P, @@ -3157,6 +3182,7 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupBy<'a, T, P> { /// [`group_by_mut`]: slice::group_by_mut /// [slices]: slice #[unstable(feature = "slice_group_by", issue = "80552")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct GroupByMut<'a, T: 'a, P> { slice: &'a mut [T], predicate: P, diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index c0eb000e877..26d4fa15d0a 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -124,6 +124,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_len", since = "1.39.0")] #[inline] + #[must_use] // SAFETY: const sound because we transmute out the length field as a usize (which it must be) pub const fn len(&self) -> usize { // FIXME: Replace with `crate::ptr::metadata(self)` when that is const-stable. @@ -147,6 +148,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_is_empty", since = "1.39.0")] #[inline] + #[must_use] pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -165,6 +167,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")] #[inline] + #[must_use] pub const fn first(&self) -> Option<&T> { if let [first, ..] = self { Some(first) } else { None } } @@ -184,6 +187,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] + #[must_use] pub const fn first_mut(&mut self) -> Option<&mut T> { if let [first, ..] = self { Some(first) } else { None } } @@ -203,6 +207,7 @@ impl<T> [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")] #[inline] + #[must_use] pub const fn split_first(&self) -> Option<(&T, &[T])> { if let [first, tail @ ..] = self { Some((first, tail)) } else { None } } @@ -224,6 +229,7 @@ impl<T> [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] + #[must_use] pub const fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { if let [first, tail @ ..] = self { Some((first, tail)) } else { None } } @@ -243,6 +249,7 @@ impl<T> [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")] #[inline] + #[must_use] pub const fn split_last(&self) -> Option<(&T, &[T])> { if let [init @ .., last] = self { Some((last, init)) } else { None } } @@ -264,6 +271,7 @@ impl<T> [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] + #[must_use] pub const fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { if let [init @ .., last] = self { Some((last, init)) } else { None } } @@ -282,6 +290,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")] #[inline] + #[must_use] pub const fn last(&self) -> Option<&T> { if let [.., last] = self { Some(last) } else { None } } @@ -301,6 +310,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] + #[must_use] pub const fn last_mut(&mut self) -> Option<&mut T> { if let [.., last] = self { Some(last) } else { None } } @@ -325,6 +335,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] + #[must_use] pub const fn get<I>(&self, index: I) -> Option<&I::Output> where I: ~const SliceIndex<Self>, @@ -350,6 +361,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] + #[must_use] pub const fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output> where I: ~const SliceIndex<Self>, @@ -382,6 +394,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] + #[must_use] pub const unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output where I: ~const SliceIndex<Self>, @@ -419,6 +432,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] + #[must_use] pub const unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output where I: ~const SliceIndex<Self>, @@ -458,6 +472,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")] #[inline] + #[must_use] pub const fn as_ptr(&self) -> *const T { self as *const [T] as *const T } @@ -484,8 +499,10 @@ impl<T> [T] { /// assert_eq!(x, &[3, 4, 6]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[rustc_allow_const_fn_unstable(const_mut_refs)] #[inline] + #[must_use] pub const fn as_mut_ptr(&mut self) -> *mut T { self as *mut [T] as *mut T } @@ -519,8 +536,9 @@ impl<T> [T] { /// /// [`as_ptr`]: slice::as_ptr #[stable(feature = "slice_ptr_range", since = "1.48.0")] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline] + #[must_use] pub const fn as_ptr_range(&self) -> Range<*const T> { let start = self.as_ptr(); // SAFETY: The `add` here is safe, because: @@ -561,8 +579,10 @@ impl<T> [T] { /// /// [`as_mut_ptr`]: slice::as_mut_ptr #[stable(feature = "slice_ptr_range", since = "1.48.0")] - #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[rustc_allow_const_fn_unstable(const_mut_refs)] #[inline] + #[must_use] pub const fn as_mut_ptr_range(&mut self) -> Range<*mut T> { let start = self.as_mut_ptr(); // SAFETY: See as_ptr_range() above for why `add` here is safe. @@ -948,6 +968,7 @@ impl<T> [T] { /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] + #[must_use] pub unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] { debug_assert_ne!(N, 0); debug_assert_eq!(self.len() % N, 0); @@ -979,6 +1000,7 @@ impl<T> [T] { /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] + #[must_use] pub fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]) { assert_ne!(N, 0); let len = self.len() / N; @@ -1009,6 +1031,7 @@ impl<T> [T] { /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] + #[must_use] pub fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]) { assert_ne!(N, 0); let len = self.len() / N; @@ -1084,6 +1107,7 @@ impl<T> [T] { /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] + #[must_use] pub unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] { debug_assert_ne!(N, 0); debug_assert_eq!(self.len() % N, 0); @@ -1121,6 +1145,7 @@ impl<T> [T] { /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] + #[must_use] pub fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]) { assert_ne!(N, 0); let len = self.len() / N; @@ -1157,6 +1182,7 @@ impl<T> [T] { /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] + #[must_use] pub fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]) { assert_ne!(N, 0); let len = self.len() / N; @@ -1515,6 +1541,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] #[track_caller] + #[must_use] pub fn split_at(&self, mid: usize) -> (&[T], &[T]) { assert!(mid <= self.len()); // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which @@ -1546,6 +1573,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] #[track_caller] + #[must_use] pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { assert!(mid <= self.len()); // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which @@ -1597,6 +1625,7 @@ impl<T> [T] { /// ``` #[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")] #[inline] + #[must_use] pub unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) { // SAFETY: Caller has to check that `0 <= mid <= self.len()` unsafe { (self.get_unchecked(..mid), self.get_unchecked(mid..)) } @@ -1637,6 +1666,7 @@ impl<T> [T] { /// ``` #[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")] #[inline] + #[must_use] pub unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) { let len = self.len(); let ptr = self.as_mut_ptr(); @@ -1686,6 +1716,7 @@ impl<T> [T] { #[unstable(feature = "split_array", reason = "new API", issue = "90091")] #[inline] #[track_caller] + #[must_use] pub fn split_array_ref<const N: usize>(&self) -> (&[T; N], &[T]) { let (a, b) = self.split_at(N); // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at) @@ -1718,6 +1749,7 @@ impl<T> [T] { #[unstable(feature = "split_array", reason = "new API", issue = "90091")] #[inline] #[track_caller] + #[must_use] pub fn split_array_mut<const N: usize>(&mut self) -> (&mut [T; N], &mut [T]) { let (a, b) = self.split_at_mut(N); // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at_mut) @@ -1762,6 +1794,7 @@ impl<T> [T] { /// ``` #[unstable(feature = "split_array", reason = "new API", issue = "90091")] #[inline] + #[must_use] pub fn rsplit_array_ref<const N: usize>(&self) -> (&[T], &[T; N]) { assert!(N <= self.len()); let (a, b) = self.split_at(self.len() - N); @@ -1795,6 +1828,7 @@ impl<T> [T] { /// ``` #[unstable(feature = "split_array", reason = "new API", issue = "90091")] #[inline] + #[must_use] pub fn rsplit_array_mut<const N: usize>(&mut self) -> (&mut [T], &mut [T; N]) { assert!(N <= self.len()); let (a, b) = self.split_at_mut(self.len() - N); @@ -2126,6 +2160,7 @@ impl<T> [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[must_use] pub fn contains(&self, x: &T) -> bool where T: PartialEq, @@ -2154,6 +2189,7 @@ impl<T> [T] { /// assert!(v.starts_with(&[])); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq, @@ -2183,6 +2219,7 @@ impl<T> [T] { /// assert!(v.ends_with(&[])); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq, @@ -3390,6 +3427,7 @@ impl<T> [T] { /// } /// ``` #[stable(feature = "slice_align_to", since = "1.30.0")] + #[must_use] pub unsafe fn align_to<U>(&self) -> (&[T], &[U], &[T]) { // Note that most of this function will be constant-evaluated, if mem::size_of::<U>() == 0 || mem::size_of::<T>() == 0 { @@ -3450,6 +3488,7 @@ impl<T> [T] { /// } /// ``` #[stable(feature = "slice_align_to", since = "1.30.0")] + #[must_use] pub unsafe fn align_to_mut<U>(&mut self) -> (&mut [T], &mut [U], &mut [T]) { // Note that most of this function will be constant-evaluated, if mem::size_of::<U>() == 0 || mem::size_of::<T>() == 0 { @@ -3543,6 +3582,7 @@ impl<T> [T] { /// assert_eq!(basic_simd_sum(&numbers[1..99]), 4949.0); /// ``` #[unstable(feature = "portable_simd", issue = "86656")] + #[must_use] pub fn as_simd<const LANES: usize>(&self) -> (&[T], &[Simd<T, LANES>], &[T]) where Simd<T, LANES>: AsRef<[T; LANES]>, @@ -3586,6 +3626,7 @@ impl<T> [T] { /// be lifted in a way that would make it possible to see panics from this /// method for something like `LANES == 3`. #[unstable(feature = "portable_simd", issue = "86656")] + #[must_use] pub fn as_simd_mut<const LANES: usize>(&mut self) -> (&mut [T], &mut [Simd<T, LANES>], &mut [T]) where Simd<T, LANES>: AsMut<[T; LANES]>, @@ -3625,6 +3666,7 @@ impl<T> [T] { /// ``` #[inline] #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] + #[must_use] pub fn is_sorted(&self) -> bool where T: PartialOrd, @@ -3640,6 +3682,7 @@ impl<T> [T] { /// /// [`is_sorted`]: slice::is_sorted #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] + #[must_use] pub fn is_sorted_by<F>(&self, mut compare: F) -> bool where F: FnMut(&T, &T) -> Option<Ordering>, @@ -3665,6 +3708,7 @@ impl<T> [T] { /// ``` #[inline] #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] + #[must_use] pub fn is_sorted_by_key<F, K>(&self, f: F) -> bool where F: FnMut(&T) -> K, @@ -3702,6 +3746,7 @@ impl<T> [T] { /// assert!(v[i..].iter().all(|&x| !(x < 5))); /// ``` #[stable(feature = "partition_point", since = "1.52.0")] + #[must_use] pub fn partition_point<P>(&self, mut pred: P) -> usize where P: FnMut(&T) -> bool, diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 39c8d68e4bf..6744400c304 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -85,6 +85,7 @@ use crate::ptr; #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] +#[must_use] pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { debug_check_data_len(data, len); @@ -124,6 +125,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] +#[must_use] pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { debug_check_data_len(data as _, len); @@ -168,6 +170,7 @@ const fn debug_check_data_len<T>(_data: *const T, _len: usize) {} /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] #[rustc_const_unstable(feature = "const_slice_from_ref", issue = "90206")] +#[must_use] pub const fn from_ref<T>(s: &T) -> &[T] { array::from_ref(s) } @@ -175,6 +178,7 @@ pub const fn from_ref<T>(s: &T) -> &[T] { /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] #[rustc_const_unstable(feature = "const_slice_from_ref", issue = "90206")] +#[must_use] pub const fn from_mut<T>(s: &mut T) -> &mut [T] { array::from_mut(s) } diff --git a/library/core/tests/char.rs b/library/core/tests/char.rs index 4c899b6eb43..8542e5c70d4 100644 --- a/library/core/tests/char.rs +++ b/library/core/tests/char.rs @@ -197,7 +197,7 @@ fn test_escape_debug() { assert_eq!(string('~'), "~"); assert_eq!(string('é'), "é"); assert_eq!(string('æ–‡'), "æ–‡"); - assert_eq!(string('\x00'), "\\u{0}"); + assert_eq!(string('\x00'), "\\0"); assert_eq!(string('\x1f'), "\\u{1f}"); assert_eq!(string('\x7f'), "\\u{7f}"); assert_eq!(string('\u{80}'), "\\u{80}"); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 5c861236e86..5f90a76ab74 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -20,7 +20,6 @@ #![feature(const_ptr_as_ref)] #![feature(const_ptr_read)] #![feature(const_ptr_write)] -#![feature(const_ptr_offset)] #![feature(const_trait_impl)] #![feature(const_likely)] #![feature(core_ffi_c)] diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 7c4d2f266f9..798fcc3dfde 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2344,7 +2344,7 @@ fn slice_rsplit_array_mut() { fn slice_split_array_ref_out_of_bounds() { let v = &[1, 2, 3, 4, 5, 6][..]; - v.split_array_ref::<7>(); + let _ = v.split_array_ref::<7>(); } #[should_panic] @@ -2352,7 +2352,7 @@ fn slice_split_array_ref_out_of_bounds() { fn slice_split_array_mut_out_of_bounds() { let v = &mut [1, 2, 3, 4, 5, 6][..]; - v.split_array_mut::<7>(); + let _ = v.split_array_mut::<7>(); } #[should_panic] @@ -2360,7 +2360,7 @@ fn slice_split_array_mut_out_of_bounds() { fn slice_rsplit_array_ref_out_of_bounds() { let v = &[1, 2, 3, 4, 5, 6][..]; - v.rsplit_array_ref::<7>(); + let _ = v.rsplit_array_ref::<7>(); } #[should_panic] @@ -2368,7 +2368,7 @@ fn slice_rsplit_array_ref_out_of_bounds() { fn slice_rsplit_array_mut_out_of_bounds() { let v = &mut [1, 2, 3, 4, 5, 6][..]; - v.rsplit_array_mut::<7>(); + let _ = v.rsplit_array_mut::<7>(); } macro_rules! take_tests { diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 9824cce6c72..b6edf8bca0a 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -525,7 +525,11 @@ impl Command { /// * No arguments to the program /// * Inherit the current process's environment /// * Inherit the current process's working directory - /// * Inherit stdin/stdout/stderr for `spawn` or `status`, but create pipes for `output` + /// * Inherit stdin/stdout/stderr for [`spawn`] or [`status`], but create pipes for [`output`] + /// + /// [`spawn`]: Self::spawn + /// [`status`]: Self::status + /// [`output`]: Self::output /// /// Builder methods are provided to change these defaults and /// otherwise configure the process. @@ -772,11 +776,14 @@ impl Command { /// Configuration for the child process's standard input (stdin) handle. /// - /// Defaults to [`inherit`] when used with `spawn` or `status`, and - /// defaults to [`piped`] when used with `output`. + /// Defaults to [`inherit`] when used with [`spawn`] or [`status`], and + /// defaults to [`piped`] when used with [`output`]. /// /// [`inherit`]: Stdio::inherit /// [`piped`]: Stdio::piped + /// [`spawn`]: Self::spawn + /// [`status`]: Self::status + /// [`output`]: Self::output /// /// # Examples /// @@ -798,11 +805,14 @@ impl Command { /// Configuration for the child process's standard output (stdout) handle. /// - /// Defaults to [`inherit`] when used with `spawn` or `status`, and - /// defaults to [`piped`] when used with `output`. + /// Defaults to [`inherit`] when used with [`spawn`] or [`status`], and + /// defaults to [`piped`] when used with [`output`]. /// /// [`inherit`]: Stdio::inherit /// [`piped`]: Stdio::piped + /// [`spawn`]: Self::spawn + /// [`status`]: Self::status + /// [`output`]: Self::output /// /// # Examples /// @@ -824,11 +834,14 @@ impl Command { /// Configuration for the child process's standard error (stderr) handle. /// - /// Defaults to [`inherit`] when used with `spawn` or `status`, and - /// defaults to [`piped`] when used with `output`. + /// Defaults to [`inherit`] when used with [`spawn`] or [`status`], and + /// defaults to [`piped`] when used with [`output`]. /// /// [`inherit`]: Stdio::inherit /// [`piped`]: Stdio::piped + /// [`spawn`]: Self::spawn + /// [`status`]: Self::status + /// [`output`]: Self::output /// /// # Examples /// diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index fab77af2a1a..fcbb5375b7e 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -1 +1 @@ -0.8.3 \ No newline at end of file +0.8.4 \ No newline at end of file diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index aecd892ce8b..2cf26603273 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -17,7 +17,6 @@ - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md) - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md) - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md) - - [aarch64-unknown-none-hermitkernel](platform-support/aarch64-unknown-none-hermitkernel.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) - [*-unknown-openbsd](platform-support/openbsd.md) - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index cc92d273ed1..8fc5a0d312b 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -207,7 +207,6 @@ target | std | host | notes [`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ | | ARM64 SOLID with TOPPERS/ASP3 `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD `aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore -[`aarch64-unknown-none-hermitkernel`](platform-support/aarch64-unknown-none-hermitkernel.md) | * | | ARM64 HermitCore kernel `aarch64-unknown-uefi` | * | | ARM64 UEFI `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) `aarch64-unknown-netbsd` | ✓ | ✓ | @@ -293,7 +292,6 @@ target | std | host | notes `x86_64-unknown-hermit` | ✓ | | HermitCore `x86_64-unknown-l4re-uclibc` | ? | | [`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | | Freestanding/bare-metal x86_64, softfloat -`x86_64-unknown-none-hermitkernel` | * | | HermitCore kernel `x86_64-unknown-none-linuxkernel` | * | | Linux kernel modules [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD `x86_64-unknown-uefi` | * | | 64-bit UEFI diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-none-hermitkernel.md b/src/doc/rustc/src/platform-support/aarch64-unknown-none-hermitkernel.md deleted file mode 100644 index b8967f63187..00000000000 --- a/src/doc/rustc/src/platform-support/aarch64-unknown-none-hermitkernel.md +++ /dev/null @@ -1,77 +0,0 @@ -# `aarch64-unknown-none-hermitkernel` - -**Tier: 3** - -Required to build the kernel for [HermitCore](https://github.com/hermitcore/hermit-playground) -or [RustyHermit](https://github.com/hermitcore/rusty-hermit). -The result is a bare-metal aarch64 binary in ELF format. - -## Target maintainers - -- Stefan Lankes, https://github.com/stlankes - -## Requirements - -This target is cross-compiled. There is no support for `std`, but the -library operating system provides a simple allocator to use `alloc`. - -By default, Rust code generated for this target does not use any vector or -floating-point registers. This allows the generated code to build the library -operaring system, which may need to avoid the use of such -registers or which may have special considerations about the use of such -registers (e.g. saving and restoring them to avoid breaking userspace code -using the same registers). In contrast to `aarch64-unknown-none-softfloat`, -the target is completly relocatable, which is a required feature of RustyHermit. - -By default, code generated with this target should run on any `aarch64` -hardware; enabling additional target features may raise this baseline. -On `aarch64-unknown-none-hermitkernel`, `extern "C"` uses the [standard System V calling -convention](https://github.com/ARM-software/abi-aa/releases/download/2021Q3/sysvabi64.pdf), -without red zones. - -This target generated binaries in the ELF format. - -## Building the target - -Typical you should not use the target directly. The target `aarch64-unknown-hermit` -builds the _user space_ of RustyHermit and supports red zones and floating-point -operations. -To build and link the kernel to the application, the crate -[hermit-sys](https://github.com/hermitcore/rusty-hermit/tree/master/hermit-sys) -should be used by adding the following lines to the `Cargo.toml` file of -your application. - -```toml -[target.'cfg(target_os = "hermit")'.dependencies] -hermit-sys = "0.1.*" -``` - -The crate `hermit-sys` uses the target `aarch64-unknown-none-hermitkernel` -to build the kernel. - -## Building Rust programs - -Rust does not yet ship pre-compiled artifacts for this target. To compile for -this target, you need to build the crate `hermit-sys` (see -"Building the target" above). - -## Testing - -As `aarch64-unknown-none-hermitkernel` does not support `std` -and does not support running any Rust testsuite. - -## Cross-compilation toolchains and C code - -If you want to compile C code along with Rust you will need an -appropriate `aarch64` toolchain. - -Rust *may* be able to use an `aarch64-linux-gnu-` toolchain with appropriate -standalone flags to build for this toolchain (depending on the assumptions of -that toolchain, see below), or you may wish to use a separate -`aarch64-unknown-none` (or `aarch64-elf-`) toolchain. - -On some `aarch64` hosts that use ELF binaries, you *may* be able to use the host -C toolchain, if it does not introduce assumptions about the host environment -that don't match the expectations of a standalone environment. Otherwise, you -may need a separate toolchain for standalone/freestanding development, just as -when cross-compiling from a non-`aarch64` platform. diff --git a/src/test/rustdoc-gui/default-settings.goml b/src/test/rustdoc-gui/default-settings.goml index 68b674a11f2..90f0b087a1b 100644 --- a/src/test/rustdoc-gui/default-settings.goml +++ b/src/test/rustdoc-gui/default-settings.goml @@ -4,5 +4,5 @@ // check. goto: file://|DOC_PATH|/settings/index.html // Wait a bit to be sure the default theme is applied. -wait-for: 1000 -assert-css: ("body", {"background-color": "rgb(15, 20, 25)"}) +// If the theme isn't applied, the command will time out. +wait-for-css: ("body", {"background-color": "rgb(15, 20, 25)"}) diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml index 3f78d60f28c..aca8390dfb3 100644 --- a/src/test/rustdoc-gui/search-filter.goml +++ b/src/test/rustdoc-gui/search-filter.goml @@ -24,11 +24,9 @@ assert-property: ("#crate-search", {"value": "lib2"}) // Now we check that leaving the search results and putting them back keeps the // crate filtering. press-key: "Escape" -wait-for: 100 -assert-css: ("#main-content", {"display": "block"}) +wait-for-css: ("#main-content", {"display": "block"}) focus: ".search-input" -wait-for: 100 -assert-css: ("#main-content", {"display": "none"}) +wait-for-css: ("#main-content", {"display": "none"}) // We check that there is no more "test_docs" appearing. assert-false: "#results .externcrate" assert-property: ("#crate-search", {"value": "lib2"}) diff --git a/src/test/rustdoc-gui/search-result-go-to-first.goml b/src/test/rustdoc-gui/search-result-go-to-first.goml index cadd7f6a3f3..255470a3e35 100644 --- a/src/test/rustdoc-gui/search-result-go-to-first.goml +++ b/src/test/rustdoc-gui/search-result-go-to-first.goml @@ -16,5 +16,4 @@ assert-css: ("#main-content", {"display": "none"}) // Now we can check that the feature is working as expected! goto: file://|DOC_PATH|/test_docs/index.html?search=struct%3AFoo&go_to_first=true // Waiting for the page to load... -wait-for: 500 -assert-text: (".fqn .in-band", "Struct test_docs::Foo") +wait-for-text: (".fqn .in-band", "Struct test_docs::Foo") diff --git a/src/test/rustdoc-gui/sidebar-source-code-display.goml b/src/test/rustdoc-gui/sidebar-source-code-display.goml index 27229705a9f..377ee9c6eef 100644 --- a/src/test/rustdoc-gui/sidebar-source-code-display.goml +++ b/src/test/rustdoc-gui/sidebar-source-code-display.goml @@ -5,8 +5,7 @@ goto: file://|DOC_PATH|/src/test_docs/lib.rs.html assert-false: "#sidebar-toggle" // For some reason, we need to wait a bit here because it seems like the transition on opacity // is being applied whereas it can't be reproduced in a browser... -wait-for: 500 -assert-css: (".sidebar > *", {"visibility": "hidden", "opacity": 0}) +wait-for-css: (".sidebar > *", {"visibility": "hidden", "opacity": 0}) // Let's retry with javascript enabled. javascript: true @@ -17,6 +16,5 @@ assert-css: (".sidebar > *:not(#sidebar-toggle)", {"visibility": "hidden", "opac // Let's expand the sidebar now. click: "#sidebar-toggle" // Because of the transition CSS, better wait a second before checking. -wait-for: 1000 -assert-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) +wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) assert-css: (".sidebar > *:not(#sidebar-toggle)", {"visibility": "visible", "opacity": 1}) diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml index 0cb8e776385..8b4a8bd40dd 100644 --- a/src/test/rustdoc-gui/sidebar-source-code.goml +++ b/src/test/rustdoc-gui/sidebar-source-code.goml @@ -7,16 +7,13 @@ size: (1100, 800) assert-css: ("nav.sidebar", {"width": "50px"}) // We now click on the button to expand the sidebar. click: (10, 10) -// We wait for the sidebar to be expanded (there is a 0.5s animation). -wait-for: 600 -assert-css: ("nav.sidebar.expanded", {"width": "300px"}) +// We wait for the sidebar to be expanded. +wait-for-css: ("nav.sidebar.expanded", {"width": "300px"}) assert-css: ("nav.sidebar.expanded a", {"font-size": "14px"}) // We collapse the sidebar. click: (10, 10) -// We wait for the sidebar to be collapsed (there is a 0.5s animation). -wait-for: 600 // We ensure that the class has been removed. -assert-false: "nav.sidebar.expanded" +wait-for: "nav.sidebar:not(.expanded)" assert: "nav.sidebar" // We now switch to mobile mode. diff --git a/src/test/rustdoc-gui/theme-change.goml b/src/test/rustdoc-gui/theme-change.goml index 73edee64e43..333391ba279 100644 --- a/src/test/rustdoc-gui/theme-change.goml +++ b/src/test/rustdoc-gui/theme-change.goml @@ -2,26 +2,21 @@ goto: file://|DOC_PATH|/test_docs/index.html click: "#theme-picker" click: "#theme-choices > button:first-child" -wait-for: 500 // should be the ayu theme so let's check the color -assert-css: ("body", { "background-color": "rgb(15, 20, 25)" }) +wait-for-css: ("body", { "background-color": "rgb(15, 20, 25)" }) click: "#theme-choices > button:last-child" -wait-for: 500 // should be the light theme so let's check the color -assert-css: ("body", { "background-color": "rgb(255, 255, 255)" }) +wait-for-css: ("body", { "background-color": "rgb(255, 255, 255)" }) goto: file://|DOC_PATH|/settings.html click: "#theme-light" -wait-for: 500 -assert-css: ("body", { "background-color": "rgb(255, 255, 255)" }) +wait-for-css: ("body", { "background-color": "rgb(255, 255, 255)" }) assert-local-storage: { "rustdoc-theme": "light" } click: "#theme-dark" -wait-for: 500 -assert-css: ("body", { "background-color": "rgb(53, 53, 53)" }) +wait-for-css: ("body", { "background-color": "rgb(53, 53, 53)" }) assert-local-storage: { "rustdoc-theme": "dark" } click: "#theme-ayu" -wait-for: 500 -assert-css: ("body", { "background-color": "rgb(15, 20, 25)" }) +wait-for-css: ("body", { "background-color": "rgb(15, 20, 25)" }) assert-local-storage: { "rustdoc-theme": "ayu" } diff --git a/src/test/rustdoc-gui/theme-in-history.goml b/src/test/rustdoc-gui/theme-in-history.goml index b53799188ef..3b66c85d8da 100644 --- a/src/test/rustdoc-gui/theme-in-history.goml +++ b/src/test/rustdoc-gui/theme-in-history.goml @@ -12,8 +12,7 @@ click: "#settings-menu" wait-for: ".settings" // We change the theme to "light". click: "#theme-light" -wait-for: 250 -assert-css: ("body", { "background-color": "rgb(255, 255, 255)" }) +wait-for-css: ("body", { "background-color": "rgb(255, 255, 255)" }) assert-local-storage: { "rustdoc-theme": "light" } // We go back in history. diff --git a/src/test/rustdoc-gui/toggle-docs.goml b/src/test/rustdoc-gui/toggle-docs.goml index bbc85ecd4ad..63962b576df 100644 --- a/src/test/rustdoc-gui/toggle-docs.goml +++ b/src/test/rustdoc-gui/toggle-docs.goml @@ -8,9 +8,8 @@ wait-for: 50 assert-attribute-false: ("#main-content > details.top-doc", {"open": ""}) assert-text: ("#toggle-all-docs", "[+]") click: "#toggle-all-docs" -wait-for: 50 // Not collapsed anymore so the "open" attribute should be back. -assert-attribute: ("#main-content > details.top-doc", {"open": ""}) +wait-for-attribute: ("#main-content > details.top-doc", {"open": ""}) assert-text: ("#toggle-all-docs", "[−]") // Check that it works on non-module pages as well. @@ -27,8 +26,7 @@ assert-attribute-false: ( // We collapse them all. click: "#toggle-all-docs" -wait-for: 50 -assert-text: ("#toggle-all-docs", "[+]") +wait-for-text: ("#toggle-all-docs", "[+]") // We check that all <details> are collapsed (except for the impl block ones). assert-attribute-false: ("details.rustdoc-toggle:not(.implementors-toggle)", {"open": ""}, ALL) assert-attribute: ("#implementations-list > details.implementors-toggle", {"open": ""}) @@ -40,6 +38,5 @@ assert-attribute-false: ( ) // We open them all again. click: "#toggle-all-docs" -wait-for: 50 -assert-text: ("#toggle-all-docs", "[−]") +wait-for-text: ("#toggle-all-docs", "[−]") assert-attribute: ("details.rustdoc-toggle", {"open": ""}, ALL) diff --git a/src/test/rustdoc-ui/check-fail.stderr b/src/test/rustdoc-ui/check-fail.stderr index 2758c5490a3..5d46dc72014 100644 --- a/src/test/rustdoc-ui/check-fail.stderr +++ b/src/test/rustdoc-ui/check-fail.stderr @@ -32,11 +32,6 @@ LL | | //! let x = 12; LL | | //! ``` | |_______^ | -note: the lint level is defined here - --> $DIR/check-fail.rs:4:9 - | -LL | #![deny(rustdoc::all)] - | ^^^^^^^^^^^^ = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(rustdoc::all)]` = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function diff --git a/src/test/rustdoc-ui/check.stderr b/src/test/rustdoc-ui/check.stderr index 8c9e70e57fe..06e607fbe55 100644 --- a/src/test/rustdoc-ui/check.stderr +++ b/src/test/rustdoc-ui/check.stderr @@ -43,11 +43,6 @@ LL | | LL | | pub fn foo() {} | |_______________^ | -note: the lint level is defined here - --> $DIR/check.rs:8:9 - | -LL | #![warn(rustdoc::all)] - | ^^^^^^^^^^^^ = note: `#[warn(rustdoc::missing_doc_code_examples)]` implied by `#[warn(rustdoc::all)]` warning: missing code example in this documentation diff --git a/src/test/rustdoc-ui/display-output.stdout b/src/test/rustdoc-ui/display-output.stdout index 41c1f41f2cf..51d638b31a8 100644 --- a/src/test/rustdoc-ui/display-output.stdout +++ b/src/test/rustdoc-ui/display-output.stdout @@ -30,11 +30,6 @@ warning: function is never used: `foo` LL | fn foo(x: &dyn std::fmt::Display) {} | ^^^ | -note: the lint level is defined here - --> $DIR/display-output.rs:9:9 - | -LL | #![warn(unused)] - | ^^^^^^ = note: `#[warn(dead_code)]` implied by `#[warn(unused)]` warning: 3 warnings emitted diff --git a/src/test/rustdoc-ui/lint-group.stderr b/src/test/rustdoc-ui/lint-group.stderr index cc6f03b03ff..e28600160b1 100644 --- a/src/test/rustdoc-ui/lint-group.stderr +++ b/src/test/rustdoc-ui/lint-group.stderr @@ -21,11 +21,6 @@ LL | | /// println!("sup"); LL | | /// ``` | |_______^ | -note: the lint level is defined here - --> $DIR/lint-group.rs:7:9 - | -LL | #![deny(rustdoc::all)] - | ^^^^^^^^^^^^ = note: `#[deny(rustdoc::private_doc_tests)]` implied by `#[deny(rustdoc::all)]` error: missing code example in this documentation @@ -40,11 +35,6 @@ error: unresolved link to `error` LL | /// what up, let's make an [error] | ^^^^^ no item named `error` in scope | -note: the lint level is defined here - --> $DIR/lint-group.rs:7:9 - | -LL | #![deny(rustdoc::all)] - | ^^^^^^^^^^^^ = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(rustdoc::all)]` = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` @@ -54,11 +44,6 @@ error: unclosed HTML tag `unknown` LL | /// <unknown> | ^^^^^^^^^ | -note: the lint level is defined here - --> $DIR/lint-group.rs:7:9 - | -LL | #![deny(rustdoc::all)] - | ^^^^^^^^^^^^ = note: `#[deny(rustdoc::invalid_html_tags)]` implied by `#[deny(rustdoc::all)]` error: aborting due to 5 previous errors diff --git a/src/test/ui-fulldeps/hash-stable-is-unstable.rs b/src/test/ui-fulldeps/hash-stable-is-unstable.rs index 1be08191bc9..11fe688f391 100644 --- a/src/test/ui-fulldeps/hash-stable-is-unstable.rs +++ b/src/test/ui-fulldeps/hash-stable-is-unstable.rs @@ -1,5 +1,5 @@ // ignore-stage1 - +// compile-flags: -Zdeduplicate-diagnostics=yes extern crate rustc_data_structures; //~^ use of unstable library feature 'rustc_private' extern crate rustc_macros; diff --git a/src/test/ui-fulldeps/lint-tool-test.stderr b/src/test/ui-fulldeps/lint-tool-test.stderr index 0f76384ed5b..513f70d0f05 100644 --- a/src/test/ui-fulldeps/lint-tool-test.stderr +++ b/src/test/ui-fulldeps/lint-tool-test.stderr @@ -83,11 +83,6 @@ error: item is named 'lintmetoo' LL | fn lintmetoo() { } | ^^^^^^^^^^^^^^^^^^ | -note: the lint level is defined here - --> $DIR/lint-tool-test.rs:14:9 - | -LL | #![deny(clippy_group)] - | ^^^^^^^^^^^^ = note: `#[deny(clippy::test_group)]` implied by `#[deny(clippy::group)]` warning: lint name `test_group` is deprecated and may not have an effect in the future. diff --git a/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs deleted file mode 100644 index 5cbf8093c5c..00000000000 --- a/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![crate_name = "anonexternmod"] -#![feature(rustc_private)] - -extern crate libc; - -#[link(name = "rust_test_helpers", kind = "static")] -extern "C" { - pub fn rust_get_test_int() -> libc::intptr_t; -} diff --git a/src/test/ui/abi/auxiliary/foreign_lib.rs b/src/test/ui/abi/auxiliary/foreign_lib.rs deleted file mode 100644 index 3c649b778bd..00000000000 --- a/src/test/ui/abi/auxiliary/foreign_lib.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![crate_name = "foreign_lib"] -#![feature(rustc_private)] - -pub mod rustrt { - extern crate libc; - - #[link(name = "rust_test_helpers", kind = "static")] - extern "C" { - pub fn rust_get_test_int() -> libc::intptr_t; - } -} - -pub mod rustrt2 { - extern crate libc; - - extern "C" { - pub fn rust_get_test_int() -> libc::intptr_t; - } -} - -pub mod rustrt3 { - // Different type, but same ABI (on all supported platforms). - // Ensures that we don't ICE or trigger LLVM asserts when - // importing the same symbol under different types. - // See https://github.com/rust-lang/rust/issues/32740. - extern "C" { - pub fn rust_get_test_int() -> *const u8; - } -} - -pub fn local_uses() { - unsafe { - let x = rustrt::rust_get_test_int(); - assert_eq!(x, rustrt2::rust_get_test_int()); - assert_eq!(x as *const _, rustrt3::rust_get_test_int()); - } -} diff --git a/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs deleted file mode 100644 index 5cbf8093c5c..00000000000 --- a/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![crate_name = "anonexternmod"] -#![feature(rustc_private)] - -extern crate libc; - -#[link(name = "rust_test_helpers", kind = "static")] -extern "C" { - pub fn rust_get_test_int() -> libc::intptr_t; -} diff --git a/src/test/ui/abi/duplicated-external-mods.rs b/src/test/ui/abi/cross-crate/duplicated-external-mods.rs index 05a279a3014..05a279a3014 100644 --- a/src/test/ui/abi/duplicated-external-mods.rs +++ b/src/test/ui/abi/cross-crate/duplicated-external-mods.rs diff --git a/src/test/ui/abi/invoke-external-foreign.rs b/src/test/ui/abi/foreign/invoke-external-foreign.rs index dbd2b4ad865..dbd2b4ad865 100644 --- a/src/test/ui/abi/invoke-external-foreign.rs +++ b/src/test/ui/abi/foreign/invoke-external-foreign.rs diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs index a94136cfea1..750fad8393b 100644 --- a/src/test/ui/async-await/issue-61076.rs +++ b/src/test/ui/async-await/issue-61076.rs @@ -87,6 +87,7 @@ async fn baz() -> Result<(), ()> { async fn match_() { match tuple() { //~ HELP consider `await`ing on the `Future` + //~^ NOTE this expression has type `impl Future<Output = Tuple>` Tuple(_) => {} //~ ERROR mismatched types //~^ NOTE expected opaque type, found struct `Tuple` //~| NOTE expected opaque type `impl Future<Output = Tuple>` diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr index 65c0bc695bf..33839ea5939 100644 --- a/src/test/ui/async-await/issue-61076.stderr +++ b/src/test/ui/async-await/issue-61076.stderr @@ -56,8 +56,11 @@ LL | struct_().await.method(); | ++++++ error[E0308]: mismatched types - --> $DIR/issue-61076.rs:90:9 + --> $DIR/issue-61076.rs:91:9 | +LL | match tuple() { + | ------- this expression has type `impl Future<Output = Tuple>` +LL | LL | Tuple(_) => {} | ^^^^^^^^ expected opaque type, found struct `Tuple` | diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr index 3cca9616a35..76073c4c879 100644 --- a/src/test/ui/async-await/suggest-missing-await.stderr +++ b/src/test/ui/async-await/suggest-missing-await.stderr @@ -91,6 +91,8 @@ LL ~ 1 => dummy().await, error[E0308]: mismatched types --> $DIR/suggest-missing-await.rs:53:9 | +LL | let _x = match dummy() { + | ------- this expression has type `impl Future<Output = ()>` LL | () => {} | ^^ expected opaque type, found `()` | @@ -109,6 +111,9 @@ LL | let _x = match dummy().await { error[E0308]: mismatched types --> $DIR/suggest-missing-await.rs:67:9 | +LL | match dummy_result() { + | -------------- this expression has type `impl Future<Output = Result<(), ()>>` +... LL | Ok(_) => {} | ^^^^^ expected opaque type, found enum `Result` | @@ -127,6 +132,9 @@ LL | match dummy_result().await { error[E0308]: mismatched types --> $DIR/suggest-missing-await.rs:69:9 | +LL | match dummy_result() { + | -------------- this expression has type `impl Future<Output = Result<(), ()>>` +... LL | Err(_) => {} | ^^^^^^ expected opaque type, found enum `Result` | diff --git a/src/test/ui/autoref-autoderef/issue-38940.rs b/src/test/ui/autoref-autoderef/issue-38940.rs index 3f10fc017a7..d2f1c6e3271 100644 --- a/src/test/ui/autoref-autoderef/issue-38940.rs +++ b/src/test/ui/autoref-autoderef/issue-38940.rs @@ -2,8 +2,10 @@ // Test that the recursion limit can be changed. In this case, we have // deeply nested types that will fail the `Send` check by overflow // when the recursion limit is set very low. +// compile-flags: -Zdeduplicate-diagnostics=yes + #![allow(dead_code)] -#![recursion_limit="10"] +#![recursion_limit = "10"] macro_rules! link { ($outer:ident, $inner:ident) => { struct $outer($inner); @@ -18,14 +20,17 @@ macro_rules! link { &self.0 } } - } + }; } + struct Bottom; + impl Bottom { fn new() -> Bottom { Bottom } } + link!(Top, A); link!(A, B); link!(B, C); @@ -38,6 +43,7 @@ link!(H, I); link!(I, J); link!(J, K); link!(K, Bottom); + fn main() { let t = Top::new(); let x: &Bottom = &t; diff --git a/src/test/ui/autoref-autoderef/issue-38940.stderr b/src/test/ui/autoref-autoderef/issue-38940.stderr index a560334314c..f0b8405770e 100644 --- a/src/test/ui/autoref-autoderef/issue-38940.stderr +++ b/src/test/ui/autoref-autoderef/issue-38940.stderr @@ -1,5 +1,5 @@ error[E0055]: reached the recursion limit while auto-dereferencing `J` - --> $DIR/issue-38940.rs:43:22 + --> $DIR/issue-38940.rs:49:22 | LL | let x: &Bottom = &t; | ^^ deref recursion limit reached @@ -7,7 +7,7 @@ LL | let x: &Bottom = &t; = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`issue_38940`) error[E0308]: mismatched types - --> $DIR/issue-38940.rs:43:22 + --> $DIR/issue-38940.rs:49:22 | LL | let x: &Bottom = &t; | ------- ^^ expected struct `Bottom`, found struct `Top` diff --git a/src/test/ui/blind/blind-item-block-middle.stderr b/src/test/ui/blind/blind-item-block-middle.stderr index 9db11cf1590..dd83f6edf62 100644 --- a/src/test/ui/blind/blind-item-block-middle.stderr +++ b/src/test/ui/blind/blind-item-block-middle.stderr @@ -5,7 +5,7 @@ LL | mod foo { pub struct bar; } | --------------- unit struct defined here ... LL | let bar = 5; - | ^^^ + | ^^^ - this expression has type `{integer}` | | | expected integer, found struct `bar` | `bar` is interpreted as a unit struct, not a new binding diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr index 09c06e8428d..e9ca0ad9029 100644 --- a/src/test/ui/block-result/issue-20862.stderr +++ b/src/test/ui/block-result/issue-20862.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-20862.rs:2:5 | LL | fn foo(x: i32) { - | - possibly return type missing here? + | - help: a return type might be missing here: `-> _` LL | |y| x + y | ^^^^^^^^^ expected `()`, found closure | diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr index 74109772724..7e767cba3cc 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr @@ -18,11 +18,6 @@ warning: unused variable: `a` LL | a += 1; | ^ | -note: the lint level is defined here - --> $DIR/liveness.rs:5:9 - | -LL | #![warn(unused)] - | ^^^^^^ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` = help: did you mean to capture by reference instead? diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr index 11a440554f7..2ac801b49f1 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr @@ -18,11 +18,6 @@ warning: unused variable: `a` LL | a = s; | ^ | -note: the lint level is defined here - --> $DIR/liveness_unintentional_copy.rs:4:9 - | -LL | #![warn(unused)] - | ^^^^^^ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` = help: did you mean to capture by reference instead? diff --git a/src/test/ui/const-ptr/out_of_bounds_read.rs b/src/test/ui/const-ptr/out_of_bounds_read.rs index c45198cc39b..9dd669180da 100644 --- a/src/test/ui/const-ptr/out_of_bounds_read.rs +++ b/src/test/ui/const-ptr/out_of_bounds_read.rs @@ -1,7 +1,6 @@ // error-pattern: evaluation of constant value failed #![feature(const_ptr_read)] -#![feature(const_ptr_offset)] fn main() { use std::ptr; diff --git a/src/test/ui/const-ptr/out_of_bounds_read.stderr b/src/test/ui/const-ptr/out_of_bounds_read.stderr index 62af6a6adb6..678714d0e05 100644 --- a/src/test/ui/const-ptr/out_of_bounds_read.stderr +++ b/src/test/ui/const-ptr/out_of_bounds_read.stderr @@ -7,10 +7,10 @@ LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); | memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL | - ::: $DIR/out_of_bounds_read.rs:13:33 + ::: $DIR/out_of_bounds_read.rs:12:33 | LL | const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) }; - | ----------------------- inside `_READ` at $DIR/out_of_bounds_read.rs:13:33 + | ----------------------- inside `_READ` at $DIR/out_of_bounds_read.rs:12:33 error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL @@ -26,10 +26,10 @@ LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); LL | unsafe { read(self) } | ---------- inside `ptr::const_ptr::<impl *const u32>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/out_of_bounds_read.rs:14:39 + ::: $DIR/out_of_bounds_read.rs:13:39 | LL | const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() }; - | ------------------- inside `_CONST_READ` at $DIR/out_of_bounds_read.rs:14:39 + | ------------------- inside `_CONST_READ` at $DIR/out_of_bounds_read.rs:13:39 error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL @@ -45,10 +45,10 @@ LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); LL | unsafe { read(self) } | ---------- inside `ptr::mut_ptr::<impl *mut u32>::read` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL | - ::: $DIR/out_of_bounds_read.rs:15:37 + ::: $DIR/out_of_bounds_read.rs:14:37 | LL | const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() }; - | --------------------------------- inside `_MUT_READ` at $DIR/out_of_bounds_read.rs:15:37 + | --------------------------------- inside `_MUT_READ` at $DIR/out_of_bounds_read.rs:14:37 error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/auxiliary/cci_borrow_lib.rs b/src/test/ui/consts/auxiliary/cci_borrow_lib.rs deleted file mode 100644 index 7c57a1c6678..00000000000 --- a/src/test/ui/consts/auxiliary/cci_borrow_lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub fn foo(x: &usize) -> usize { - *x -} diff --git a/src/test/ui/consts/auxiliary/cci_const.rs b/src/test/ui/consts/auxiliary/cci_const.rs deleted file mode 100644 index c83b3f4a5bb..00000000000 --- a/src/test/ui/consts/auxiliary/cci_const.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub extern "C" fn bar() { -} - -pub const foopy: &'static str = "hi there"; -pub const uint_val: usize = 12; -pub const uint_expr: usize = (1 << uint_val) - 1; diff --git a/src/test/ui/consts/copy-intrinsic.rs b/src/test/ui/consts/copy-intrinsic.rs index 124e16e2b2c..5ab90324b8f 100644 --- a/src/test/ui/consts/copy-intrinsic.rs +++ b/src/test/ui/consts/copy-intrinsic.rs @@ -2,7 +2,7 @@ // ignore-tidy-linelength #![feature(intrinsics, staged_api)] -#![feature(const_mut_refs, const_intrinsic_copy, const_ptr_offset)] +#![feature(const_mut_refs, const_intrinsic_copy)] use std::mem; extern "rust-intrinsic" { diff --git a/src/test/ui/consts/invalid-union.32bit.stderr b/src/test/ui/consts/invalid-union.32bit.stderr index c8f9e570467..38c38d1ae67 100644 --- a/src/test/ui/consts/invalid-union.32bit.stderr +++ b/src/test/ui/consts/invalid-union.32bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-union.rs:41:1 + --> $DIR/invalid-union.rs:40:1 | LL | fn main() { | ^^^^^^^^^ type validation failed at .<deref>.y.<enum-variant(B)>.0: encountered `UnsafeCell` in a `const` @@ -10,7 +10,7 @@ LL | fn main() { } error: erroneous constant used - --> $DIR/invalid-union.rs:42:25 + --> $DIR/invalid-union.rs:41:25 | LL | let _: &'static _ = &C; | ^^ referenced constant has errors diff --git a/src/test/ui/consts/invalid-union.64bit.stderr b/src/test/ui/consts/invalid-union.64bit.stderr index 2ca54ccf9a0..6bfa97a2fde 100644 --- a/src/test/ui/consts/invalid-union.64bit.stderr +++ b/src/test/ui/consts/invalid-union.64bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-union.rs:41:1 + --> $DIR/invalid-union.rs:40:1 | LL | fn main() { | ^^^^^^^^^ type validation failed at .<deref>.y.<enum-variant(B)>.0: encountered `UnsafeCell` in a `const` @@ -10,7 +10,7 @@ LL | fn main() { } error: erroneous constant used - --> $DIR/invalid-union.rs:42:25 + --> $DIR/invalid-union.rs:41:25 | LL | let _: &'static _ = &C; | ^^ referenced constant has errors diff --git a/src/test/ui/consts/invalid-union.rs b/src/test/ui/consts/invalid-union.rs index 1d5cc978a9e..f3f1af89b2c 100644 --- a/src/test/ui/consts/invalid-union.rs +++ b/src/test/ui/consts/invalid-union.rs @@ -9,7 +9,6 @@ // build-fail // stderr-per-bitwidth #![feature(const_mut_refs)] -#![feature(const_ptr_offset)] #![feature(untagged_unions)] use std::cell::Cell; diff --git a/src/test/ui/consts/issue-miri-1910.rs b/src/test/ui/consts/issue-miri-1910.rs index 20efa145dbe..2b23626e3d7 100644 --- a/src/test/ui/consts/issue-miri-1910.rs +++ b/src/test/ui/consts/issue-miri-1910.rs @@ -1,6 +1,5 @@ // error-pattern unable to turn pointer into raw bytes #![feature(const_ptr_read)] -#![feature(const_ptr_offset)] const C: () = unsafe { let foo = Some(&42 as *const i32); diff --git a/src/test/ui/consts/issue-miri-1910.stderr b/src/test/ui/consts/issue-miri-1910.stderr index e2f4ef63588..87882449c73 100644 --- a/src/test/ui/consts/issue-miri-1910.stderr +++ b/src/test/ui/consts/issue-miri-1910.stderr @@ -7,9 +7,9 @@ LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); | unable to turn pointer into raw bytes | inside `std::ptr::read::<u8>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL | inside `ptr::const_ptr::<impl *const u8>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `C` at $DIR/issue-miri-1910.rs:8:5 + | inside `C` at $DIR/issue-miri-1910.rs:7:5 | - ::: $DIR/issue-miri-1910.rs:5:1 + ::: $DIR/issue-miri-1910.rs:4:1 | LL | / const C: () = unsafe { LL | | let foo = Some(&42 as *const i32); diff --git a/src/test/ui/consts/offset.rs b/src/test/ui/consts/offset.rs index a491f1c92d3..f9ddda554fc 100644 --- a/src/test/ui/consts/offset.rs +++ b/src/test/ui/consts/offset.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(const_ptr_offset)] #![feature(const_ptr_offset_from)] use std::ptr; diff --git a/src/test/ui/consts/offset_from_ub.rs b/src/test/ui/consts/offset_from_ub.rs index fee61907eb3..939c1e31f9a 100644 --- a/src/test/ui/consts/offset_from_ub.rs +++ b/src/test/ui/consts/offset_from_ub.rs @@ -1,4 +1,4 @@ -#![feature(const_ptr_offset_from, const_ptr_offset)] +#![feature(const_ptr_offset_from)] #![feature(core_intrinsics)] use std::intrinsics::ptr_offset_from; diff --git a/src/test/ui/consts/offset_ub.rs b/src/test/ui/consts/offset_ub.rs index 42a285a6eab..1b01e4fd147 100644 --- a/src/test/ui/consts/offset_ub.rs +++ b/src/test/ui/consts/offset_ub.rs @@ -1,4 +1,3 @@ -#![feature(const_ptr_offset)] use std::ptr; // normalize-stderr-test "alloc\d+" -> "allocN" diff --git a/src/test/ui/consts/offset_ub.stderr b/src/test/ui/consts/offset_ub.stderr index e774e389313..4d3e7ee2411 100644 --- a/src/test/ui/consts/offset_ub.stderr +++ b/src/test/ui/consts/offset_ub.stderr @@ -7,10 +7,10 @@ LL | unsafe { intrinsics::offset(self, count) } | overflowing in-bounds pointer arithmetic | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/offset_ub.rs:8:46 + ::: $DIR/offset_ub.rs:7:46 | LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) }; - | ------------------------------ inside `BEFORE_START` at $DIR/offset_ub.rs:8:46 + | ------------------------------ inside `BEFORE_START` at $DIR/offset_ub.rs:7:46 error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -21,10 +21,10 @@ LL | unsafe { intrinsics::offset(self, count) } | pointer arithmetic failed: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/offset_ub.rs:9:43 + ::: $DIR/offset_ub.rs:8:43 | LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) }; - | ----------------------------- inside `AFTER_END` at $DIR/offset_ub.rs:9:43 + | ----------------------------- inside `AFTER_END` at $DIR/offset_ub.rs:8:43 error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -35,10 +35,10 @@ LL | unsafe { intrinsics::offset(self, count) } | pointer arithmetic failed: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/offset_ub.rs:10:45 + ::: $DIR/offset_ub.rs:9:45 | LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) }; - | ------------------------------- inside `AFTER_ARRAY` at $DIR/offset_ub.rs:10:45 + | ------------------------------- inside `AFTER_ARRAY` at $DIR/offset_ub.rs:9:45 error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -49,10 +49,10 @@ LL | unsafe { intrinsics::offset(self, count) } | overflowing in-bounds pointer arithmetic | inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/offset_ub.rs:12:43 + ::: $DIR/offset_ub.rs:11:43 | LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) }; - | ------------------------------------- inside `OVERFLOW` at $DIR/offset_ub.rs:12:43 + | ------------------------------------- inside `OVERFLOW` at $DIR/offset_ub.rs:11:43 error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -63,10 +63,10 @@ LL | unsafe { intrinsics::offset(self, count) } | overflowing in-bounds pointer arithmetic | inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/offset_ub.rs:13:44 + ::: $DIR/offset_ub.rs:12:44 | LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) }; - | ------------------------------------- inside `UNDERFLOW` at $DIR/offset_ub.rs:13:44 + | ------------------------------------- inside `UNDERFLOW` at $DIR/offset_ub.rs:12:44 error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -77,10 +77,10 @@ LL | unsafe { intrinsics::offset(self, count) } | overflowing in-bounds pointer arithmetic | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/offset_ub.rs:14:56 + ::: $DIR/offset_ub.rs:13:56 | LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) }; - | ----------------------------------- inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:14:56 + | ----------------------------------- inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:13:56 error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -91,10 +91,10 @@ LL | unsafe { intrinsics::offset(self, count) } | overflowing in-bounds pointer arithmetic | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/offset_ub.rs:15:57 + ::: $DIR/offset_ub.rs:14:57 | LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) }; - | --------------------------- inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:15:57 + | --------------------------- inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:14:57 error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -105,10 +105,10 @@ LL | unsafe { intrinsics::offset(self, count) } | pointer arithmetic failed: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/offset_ub.rs:16:49 + ::: $DIR/offset_ub.rs:15:49 | LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) }; - | ------------------------------------------------ inside `NEGATIVE_OFFSET` at $DIR/offset_ub.rs:16:49 + | ------------------------------------------------ inside `NEGATIVE_OFFSET` at $DIR/offset_ub.rs:15:49 error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -119,10 +119,10 @@ LL | unsafe { intrinsics::offset(self, count) } | pointer arithmetic failed: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/offset_ub.rs:18:50 + ::: $DIR/offset_ub.rs:17:50 | LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) }; - | --------------------------- inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:18:50 + | --------------------------- inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:17:50 error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL @@ -133,10 +133,10 @@ LL | unsafe { intrinsics::offset(self, count) as *mut T } | pointer arithmetic failed: 0x1 is not a valid pointer | inside `ptr::mut_ptr::<impl *mut u8>::offset` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL | - ::: $DIR/offset_ub.rs:19:42 + ::: $DIR/offset_ub.rs:18:42 | LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ptr().offset(4) }; - | ------------------------------------------------- inside `DANGLING` at $DIR/offset_ub.rs:19:42 + | ------------------------------------------------- inside `DANGLING` at $DIR/offset_ub.rs:18:42 error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -147,10 +147,10 @@ LL | unsafe { intrinsics::offset(self, count) } | pointer arithmetic failed: null pointer is not a valid pointer | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/offset_ub.rs:22:50 + ::: $DIR/offset_ub.rs:21:50 | LL | pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::<u8>().offset(0) }; - | --------------------------- inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:22:50 + | --------------------------- inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:21:50 error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -161,10 +161,10 @@ LL | unsafe { intrinsics::offset(self, count) } | pointer arithmetic failed: 0x7f..f is not a valid pointer | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/offset_ub.rs:25:47 + ::: $DIR/offset_ub.rs:24:47 | LL | pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).offset(isize::MIN) }; - | -------------------------------------------- inside `UNDERFLOW_ABS` at $DIR/offset_ub.rs:25:47 + | -------------------------------------------- inside `UNDERFLOW_ABS` at $DIR/offset_ub.rs:24:47 error: aborting due to 12 previous errors diff --git a/src/test/ui/consts/ptr_comparisons.rs b/src/test/ui/consts/ptr_comparisons.rs index 8161c7af968..20233db09c9 100644 --- a/src/test/ui/consts/ptr_comparisons.rs +++ b/src/test/ui/consts/ptr_comparisons.rs @@ -7,7 +7,6 @@ #![feature( core_intrinsics, const_raw_ptr_comparison, - const_ptr_offset, )] const FOO: &usize = &42; diff --git a/src/test/ui/consts/ptr_comparisons.stderr b/src/test/ui/consts/ptr_comparisons.stderr index cfec25a7194..678ce5d3a35 100644 --- a/src/test/ui/consts/ptr_comparisons.stderr +++ b/src/test/ui/consts/ptr_comparisons.stderr @@ -7,19 +7,19 @@ LL | unsafe { intrinsics::offset(self, count) } | pointer arithmetic failed: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds | inside `ptr::const_ptr::<impl *const usize>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/ptr_comparisons.rs:59:34 + ::: $DIR/ptr_comparisons.rs:58:34 | LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) }; - | ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:59:34 + | ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:58:34 error[E0080]: evaluation of constant value failed - --> $DIR/ptr_comparisons.rs:62:33 + --> $DIR/ptr_comparisons.rs:61:33 | LL | unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: alloc3 has size $WORD, so pointer to 1000 bytes starting at offset 0 is out-of-bounds error: any use of this value will cause an error - --> $DIR/ptr_comparisons.rs:66:27 + --> $DIR/ptr_comparisons.rs:65:27 | LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 }; | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -31,7 +31,7 @@ LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> error: any use of this value will cause an error - --> $DIR/ptr_comparisons.rs:71:27 + --> $DIR/ptr_comparisons.rs:70:27 | LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 }; | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- diff --git a/src/test/ui/consts/const-cross-crate-const.rs b/src/test/ui/cross-crate/const-cross-crate-const.rs index 92020417ff5..92020417ff5 100644 --- a/src/test/ui/consts/const-cross-crate-const.rs +++ b/src/test/ui/cross-crate/const-cross-crate-const.rs diff --git a/src/test/ui/consts/const-cross-crate-extern.rs b/src/test/ui/cross-crate/const-cross-crate-extern.rs index 3c61afd5bec..3c61afd5bec 100644 --- a/src/test/ui/consts/const-cross-crate-extern.rs +++ b/src/test/ui/cross-crate/const-cross-crate-extern.rs diff --git a/src/test/ui/destructuring-assignment/default-match-bindings-forbidden.stderr b/src/test/ui/destructuring-assignment/default-match-bindings-forbidden.stderr index 2250f561b54..3d472bf6309 100644 --- a/src/test/ui/destructuring-assignment/default-match-bindings-forbidden.stderr +++ b/src/test/ui/destructuring-assignment/default-match-bindings-forbidden.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/default-match-bindings-forbidden.rs:4:5 | LL | (x, y) = &(1, 2); - | ^^^^^^ expected reference, found tuple + | ^^^^^^ ------- this expression has type `&({integer}, {integer})` + | | + | expected reference, found tuple | = note: expected type `&({integer}, {integer})` found tuple `(_, _)` diff --git a/src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr index 184b3ea6da8..55b08b74af0 100644 --- a/src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr @@ -10,7 +10,9 @@ error[E0308]: mismatched types --> $DIR/tuple_destructure_fail.rs:6:5 | LL | (a, a, b) = (1, 2); - | ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements + | ^^^^^^^^^ ------ this expression has type `({integer}, {integer})` + | | + | expected a tuple with 2 elements, found one with 3 elements | = note: expected type `({integer}, {integer})` found tuple `(_, _, _)` @@ -27,7 +29,9 @@ error[E0308]: mismatched types --> $DIR/tuple_destructure_fail.rs:8:5 | LL | (_,) = (1, 2); - | ^^^^ expected a tuple with 2 elements, found one with 1 element + | ^^^^ ------ this expression has type `({integer}, {integer})` + | | + | expected a tuple with 2 elements, found one with 1 element | = note: expected type `({integer}, {integer})` found tuple `(_,)` diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.rs b/src/test/ui/did_you_mean/recursion_limit_deref.rs index 613843801d4..41bbca661dd 100644 --- a/src/test/ui/did_you_mean/recursion_limit_deref.rs +++ b/src/test/ui/did_you_mean/recursion_limit_deref.rs @@ -1,6 +1,7 @@ // Test that the recursion limit can be changed and that the compiler // suggests a fix. In this case, we have a long chain of Deref impls // which will cause an overflow during the autoderef loop. +// compile-flags: -Zdeduplicate-diagnostics=yes #![allow(dead_code)] #![recursion_limit="10"] diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr index 658207a47c9..a6b5681a68c 100644 --- a/src/test/ui/did_you_mean/recursion_limit_deref.stderr +++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr @@ -1,5 +1,5 @@ error[E0055]: reached the recursion limit while auto-dereferencing `J` - --> $DIR/recursion_limit_deref.rs:50:22 + --> $DIR/recursion_limit_deref.rs:51:22 | LL | let x: &Bottom = &t; | ^^ deref recursion limit reached @@ -7,7 +7,7 @@ LL | let x: &Bottom = &t; = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`recursion_limit_deref`) error[E0308]: mismatched types - --> $DIR/recursion_limit_deref.rs:50:22 + --> $DIR/recursion_limit_deref.rs:51:22 | LL | let x: &Bottom = &t; | ------- ^^ expected struct `Bottom`, found struct `Top` diff --git a/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr b/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr index b1fea6d33a7..272afc10b17 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr @@ -13,6 +13,11 @@ LL | fn f2<'a>(arg : Box<dyn X< { 1 } = 32 >>) {} | - ^ expected one of `,`, `:`, or `>` | | | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | fn f2<'a>(arg : Box<dyn X< { 1 }> = 32 >>) {} + | + error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr b/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr index bfb109fbfa4..7394393c05e 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr @@ -5,6 +5,11 @@ LL | fn f1<'a>(arg : Box<dyn X<X::Y = u32>>) {} | - ^ expected one of 8 possible tokens | | | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | fn f1<'a>(arg : Box<dyn X<X::Y> = u32>>) {} + | + error: expected one of `,`, `::`, `:`, or `>`, found `=` --> $DIR/trait-path-segments.rs:19:35 @@ -13,6 +18,11 @@ LL | impl<T : X<<Self as X>::Y<'a> = &'a u32>> Z for T {} | - ^ expected one of `,`, `::`, `:`, or `>` | | | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | impl<T : X<<Self as X>::Y<'a>> = &'a u32>> Z for T {} + | + error: expected one of `!`, `+`, `,`, `::`, `:`, or `>`, found `=` --> $DIR/trait-path-segments.rs:30:25 @@ -21,6 +31,11 @@ LL | impl<T : X<X::Y<'a> = &'a u32>> Z for T {} | - ^ expected one of `!`, `+`, `,`, `::`, `:`, or `>` | | | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | impl<T : X<X::Y<'a>> = &'a u32>> Z for T {} + | + error: aborting due to 3 previous errors diff --git a/src/test/ui/generic-associated-types/parse/trait-path-types.stderr b/src/test/ui/generic-associated-types/parse/trait-path-types.stderr index c0fa41b9e0e..fe9ed579e34 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-types.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-types.stderr @@ -5,6 +5,11 @@ LL | fn f<'a>(arg : Box<dyn X< [u8; 1] = u32>>) {} | - ^ expected one of `,`, `:`, or `>` | | | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | fn f<'a>(arg : Box<dyn X< [u8; 1]> = u32>>) {} + | + error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/trait-path-types.rs:13:37 @@ -13,6 +18,11 @@ LL | fn f1<'a>(arg : Box<dyn X<(Y<'a>) = &'a ()>>) {} | - ^ expected one of `,`, `:`, or `>` | | | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | fn f1<'a>(arg : Box<dyn X<(Y<'a>)> = &'a ()>>) {} + | + error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/trait-path-types.rs:18:33 @@ -21,6 +31,11 @@ LL | fn f1<'a>(arg : Box<dyn X< 'a = u32 >>) {} | -- ^ expected one of `,`, `:`, or `>` | | | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | fn f1<'a>(arg : Box<dyn X< 'a> = u32 >>) {} + | + error: aborting due to 3 previous errors diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr index 241485db49b..a6f8563a047 100644 --- a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr +++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/exclusive_range_pattern_syntax_collision.rs:6:13 | +LL | match [5..4, 99..105, 43..44] { + | ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]` LL | [_, 99.., _] => {}, | ^^ expected struct `std::ops::Range`, found integer | diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr index 777d029d7dd..4e0102c930d 100644 --- a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr +++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr @@ -7,6 +7,8 @@ LL | [_, 99..] => {}, error[E0308]: mismatched types --> $DIR/exclusive_range_pattern_syntax_collision2.rs:6:13 | +LL | match [5..4, 99..105, 43..44] { + | ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]` LL | [_, 99..] => {}, | ^^ expected struct `std::ops::Range`, found integer | diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr index 6119733a7d8..665eef2fcb9 100644 --- a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr +++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:12 | +LL | match [5..4, 99..105, 43..44] { + | ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]` LL | [..9, 99..100, _] => {}, | ^ expected struct `std::ops::Range`, found integer | @@ -10,6 +12,8 @@ LL | [..9, 99..100, _] => {}, error[E0308]: mismatched types --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:15 | +LL | match [5..4, 99..105, 43..44] { + | ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]` LL | [..9, 99..100, _] => {}, | ^^ --- this is of type `{integer}` | | @@ -21,6 +25,8 @@ LL | [..9, 99..100, _] => {}, error[E0308]: mismatched types --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:19 | +LL | match [5..4, 99..105, 43..44] { + | ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]` LL | [..9, 99..100, _] => {}, | -- ^^^ expected struct `std::ops::Range`, found integer | | diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr index c2c77290c43..7a2441047b5 100644 --- a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr @@ -50,17 +50,17 @@ LL ~ match $s { $($t)+ => {} LL ~ '\u{10fffe}'..='\u{10ffff}' => todo!() } | -error[E0004]: non-exhaustive patterns: `'\u{0}'` not covered +error[E0004]: non-exhaustive patterns: `'\0'` not covered --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8 | LL | m!('a', ALMOST_MIN..); - | ^^^ pattern `'\u{0}'` not covered + | ^^^ pattern `'\0'` not covered | = note: the matched value is of type `char` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ match $s { $($t)+ => {} -LL ~ '\u{0}' => todo!() } +LL ~ '\0' => todo!() } | error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr b/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr index 31ea3a17871..307ad711b74 100644 --- a/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr +++ b/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/pat-tuple-5.rs:8:10 | +LL | match (0, 1) { + | ------ this expression has type `({integer}, {integer})` LL | (PAT ..) => {} | ^^^ expected tuple, found `u8` | diff --git a/src/test/ui/impl-trait/equality.rs b/src/test/ui/impl-trait/equality.rs index 9610618ca11..828b5aac896 100644 --- a/src/test/ui/impl-trait/equality.rs +++ b/src/test/ui/impl-trait/equality.rs @@ -17,7 +17,7 @@ fn two(x: bool) -> impl Foo { //~| expected `i32`, found `u32` } -fn sum_to(n: u32) -> impl Foo { //~ ERROR type annotations needed +fn sum_to(n: u32) -> impl Foo { if n == 0 { 0 } else { diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index d9819484a96..536a4726c6d 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -34,22 +34,7 @@ LL | n + sum_to(n - 1) | = help: the trait `Add<impl Foo>` is not implemented for `u32` -error[E0283]: type annotations needed - --> $DIR/equality.rs:20:22 - | -LL | fn sum_to(n: u32) -> impl Foo { - | ^^^^^^^^ cannot infer type for type `{integer}` - | - = note: multiple `impl`s satisfying `{integer}: ToString` found in the `alloc` crate: - - impl ToString for i8; - - impl ToString for u8; -note: required because of the requirements on the impl of `Foo` for `{integer}` - --> $DIR/equality.rs:5:26 - | -LL | impl<T: Copy + ToString> Foo for T {} - | ^^^ ^ - -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted -Some errors have detailed explanations: E0277, E0283, E0308. +Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/impl_trait_projections.stderr b/src/test/ui/impl-trait/impl_trait_projections.stderr index e85ed0eda52..82d2422c407 100644 --- a/src/test/ui/impl-trait/impl_trait_projections.stderr +++ b/src/test/ui/impl-trait/impl_trait_projections.stderr @@ -30,4 +30,5 @@ LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item { error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0223`. +Some errors have detailed explanations: E0223, E0667. +For more information about an error, try `rustc --explain E0223`. diff --git a/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr b/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr index f64545d83b8..e31393181d7 100644 --- a/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr +++ b/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr @@ -6,3 +6,4 @@ LL | pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { } error: aborting due to previous error +For more information about this error, try `rustc --explain E0667`. diff --git a/src/test/ui/infinite/infinite-autoderef.rs b/src/test/ui/infinite/infinite-autoderef.rs index ca26252832b..cbbe1f81df8 100644 --- a/src/test/ui/infinite/infinite-autoderef.rs +++ b/src/test/ui/infinite/infinite-autoderef.rs @@ -1,6 +1,5 @@ // error-pattern: reached the recursion limit while auto-dereferencing - - +// compile-flags: -Zdeduplicate-diagnostics=yes use std::ops::Deref; diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr index 2d29f0592e1..2e950dbb8c7 100644 --- a/src/test/ui/infinite/infinite-autoderef.stderr +++ b/src/test/ui/infinite/infinite-autoderef.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/infinite-autoderef.rs:20:13 + --> $DIR/infinite-autoderef.rs:19:13 | LL | x = Box::new(x); | ^^^^^^^^^^^ cyclic type of infinite size @@ -10,7 +10,7 @@ LL | x = *Box::new(x); | + error[E0055]: reached the recursion limit while auto-dereferencing `Foo` - --> $DIR/infinite-autoderef.rs:25:5 + --> $DIR/infinite-autoderef.rs:24:5 | LL | Foo.foo; | ^^^^^^^ deref recursion limit reached @@ -18,7 +18,7 @@ LL | Foo.foo; = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`) error[E0055]: reached the recursion limit while auto-dereferencing `Foo` - --> $DIR/infinite-autoderef.rs:25:9 + --> $DIR/infinite-autoderef.rs:24:9 | LL | Foo.foo; | ^^^ deref recursion limit reached @@ -26,13 +26,13 @@ LL | Foo.foo; = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`) error[E0609]: no field `foo` on type `Foo` - --> $DIR/infinite-autoderef.rs:25:9 + --> $DIR/infinite-autoderef.rs:24:9 | LL | Foo.foo; | ^^^ unknown field error[E0055]: reached the recursion limit while auto-dereferencing `Foo` - --> $DIR/infinite-autoderef.rs:26:9 + --> $DIR/infinite-autoderef.rs:25:9 | LL | Foo.bar(); | ^^^ deref recursion limit reached @@ -40,7 +40,7 @@ LL | Foo.bar(); = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`) error[E0599]: no method named `bar` found for struct `Foo` in the current scope - --> $DIR/infinite-autoderef.rs:26:9 + --> $DIR/infinite-autoderef.rs:25:9 | LL | struct Foo; | ----------- method `bar` not found for this diff --git a/src/test/ui/issues/issue-11844.stderr b/src/test/ui/issues/issue-11844.stderr index ecab1074a29..9d7470e7af9 100644 --- a/src/test/ui/issues/issue-11844.stderr +++ b/src/test/ui/issues/issue-11844.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-11844.rs:6:9 | +LL | match a { + | - this expression has type `Option<Box<{integer}>>` LL | Ok(a) => | ^^^^^ expected enum `Option`, found enum `Result` | diff --git a/src/test/ui/issues/issue-12552.stderr b/src/test/ui/issues/issue-12552.stderr index 1ba6852b17c..3d8852ca748 100644 --- a/src/test/ui/issues/issue-12552.stderr +++ b/src/test/ui/issues/issue-12552.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-12552.rs:6:5 | +LL | match t { + | - this expression has type `Result<_, {integer}>` LL | Some(k) => match k { | ^^^^^^^ expected enum `Result`, found enum `Option` | @@ -10,6 +12,9 @@ LL | Some(k) => match k { error[E0308]: mismatched types --> $DIR/issue-12552.rs:9:5 | +LL | match t { + | - this expression has type `Result<_, {integer}>` +... LL | None => () | ^^^^ expected enum `Result`, found enum `Option` | diff --git a/src/test/ui/issues/issue-13466.stderr b/src/test/ui/issues/issue-13466.stderr index 15ee49a5fdd..c78466f4e8c 100644 --- a/src/test/ui/issues/issue-13466.stderr +++ b/src/test/ui/issues/issue-13466.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-13466.rs:8:9 | +LL | let _x: usize = match Some(1) { + | ------- this expression has type `Option<{integer}>` LL | Ok(u) => u, | ^^^^^ expected enum `Option`, found enum `Result` | @@ -10,6 +12,9 @@ LL | Ok(u) => u, error[E0308]: mismatched types --> $DIR/issue-13466.rs:14:9 | +LL | let _x: usize = match Some(1) { + | ------- this expression has type `Option<{integer}>` +... LL | Err(e) => panic!(e) | ^^^^^^ expected enum `Option`, found enum `Result` | diff --git a/src/test/ui/issues/issue-33504.stderr b/src/test/ui/issues/issue-33504.stderr index 1e61178f42e..ec15525ed06 100644 --- a/src/test/ui/issues/issue-33504.stderr +++ b/src/test/ui/issues/issue-33504.stderr @@ -5,7 +5,7 @@ LL | struct Test; | ------------ unit struct defined here ... LL | let Test = 1; - | ^^^^ + | ^^^^ - this expression has type `{integer}` | | | expected integer, found struct `Test` | `Test` is interpreted as a unit struct, not a new binding diff --git a/src/test/ui/issues/issue-33941.rs b/src/test/ui/issues/issue-33941.rs index ccaa6334856..a1213623e6f 100644 --- a/src/test/ui/issues/issue-33941.rs +++ b/src/test/ui/issues/issue-33941.rs @@ -1,6 +1,9 @@ +// compile-flags: -Zdeduplicate-diagnostics=yes + use std::collections::HashMap; fn main() { for _ in HashMap::new().iter().cloned() {} //~ ERROR type mismatch //~^ ERROR type mismatch + //~| ERROR type mismatch } diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index c6650d60c21..e1ce6eed98e 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -1,5 +1,5 @@ error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_` - --> $DIR/issue-33941.rs:4:36 + --> $DIR/issue-33941.rs:6:36 | LL | for _ in HashMap::new().iter().cloned() {} | ^^^^^^ expected reference, found tuple @@ -13,7 +13,7 @@ LL | Self: Sized + Iterator<Item = &'a T>, | ^^^^^^^^^^^^ required by this bound in `cloned` error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_` - --> $DIR/issue-33941.rs:4:14 + --> $DIR/issue-33941.rs:6:14 | LL | for _ in HashMap::new().iter().cloned() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference @@ -23,6 +23,16 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` = note: required because of the requirements on the impl of `IntoIterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` -error: aborting due to 2 previous errors +error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_` + --> $DIR/issue-33941.rs:6:14 + | +LL | for _ in HashMap::new().iter().cloned() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference + | + = note: expected tuple `(&_, &_)` + found reference `&_` + = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index 49d6709a860..cd697445faf 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -6,6 +6,11 @@ LL | let sr: Vec<(u32, _, _) = vec![]; | | | | | maybe try to close unmatched angle bracket | while parsing the type for `sr` + | +help: you might have meant to end the type parameters here + | +LL | let sr: Vec<(u32, _, _)> = vec![]; + | + error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterator over elements of type `()` --> $DIR/issue-34334.rs:5:87 diff --git a/src/test/ui/issues/issue-3680.stderr b/src/test/ui/issues/issue-3680.stderr index 8dc0dfa2356..e8fafa76b91 100644 --- a/src/test/ui/issues/issue-3680.stderr +++ b/src/test/ui/issues/issue-3680.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-3680.rs:3:9 | +LL | match None { + | ---- this expression has type `Option<_>` LL | Err(_) => () | ^^^^^^ expected enum `Option`, found enum `Result` | diff --git a/src/test/ui/issues/issue-4968.stderr b/src/test/ui/issues/issue-4968.stderr index 5451cf42355..57ff7fe09e5 100644 --- a/src/test/ui/issues/issue-4968.stderr +++ b/src/test/ui/issues/issue-4968.stderr @@ -5,11 +5,12 @@ LL | const A: (isize,isize) = (4,2); | ------------------------------- constant defined here LL | fn main() { LL | match 42 { A => () } - | ^ - | | - | expected integer, found tuple - | `A` is interpreted as a constant, not a new binding - | help: introduce a new binding instead: `other_a` + | -- ^ + | | | + | | expected integer, found tuple + | | `A` is interpreted as a constant, not a new binding + | | help: introduce a new binding instead: `other_a` + | this expression has type `{integer}` | = note: expected type `{integer}` found tuple `(isize, isize)` diff --git a/src/test/ui/issues/issue-66706.stderr b/src/test/ui/issues/issue-66706.stderr index 3e933a0f01b..e8cb18f5c1e 100644 --- a/src/test/ui/issues/issue-66706.stderr +++ b/src/test/ui/issues/issue-66706.stderr @@ -36,7 +36,7 @@ error[E0308]: mismatched types --> $DIR/issue-66706.rs:2:5 | LL | fn a() { - | - possibly return type missing here? + | - help: try adding a return type: `-> [i32; _]` LL | [0; [|_: _ &_| ()].len()] | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]` @@ -44,7 +44,7 @@ error[E0308]: mismatched types --> $DIR/issue-66706.rs:14:5 | LL | fn c() { - | - possibly return type missing here? + | - help: try adding a return type: `-> [i32; _]` LL | [0; [|&_: _ &_| {}; 0 ].len()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]` @@ -52,7 +52,7 @@ error[E0308]: mismatched types --> $DIR/issue-66706.rs:20:5 | LL | fn d() { - | - possibly return type missing here? + | - help: try adding a return type: `-> [i32; _]` LL | [0; match [|f @ &ref _| () ] {} ] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]` diff --git a/src/test/ui/issues/issue-72574-1.stderr b/src/test/ui/issues/issue-72574-1.stderr index 5d3d390a95d..653869a237d 100644 --- a/src/test/ui/issues/issue-72574-1.stderr +++ b/src/test/ui/issues/issue-72574-1.stderr @@ -21,6 +21,8 @@ LL | (_a, _x @ ..) => {} error[E0308]: mismatched types --> $DIR/issue-72574-1.rs:4:9 | +LL | match x { + | - this expression has type `({integer}, {integer}, {integer})` LL | (_a, _x @ ..) => {} | ^^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 2 elements | diff --git a/src/test/ui/issues/issue-72690.rs b/src/test/ui/issues/issue-72690.rs index 916a7832c68..8c0a0f51a21 100644 --- a/src/test/ui/issues/issue-72690.rs +++ b/src/test/ui/issues/issue-72690.rs @@ -10,7 +10,6 @@ fn err() { fn arg_pat_closure_err() { |x| String::from("x".as_ref()); //~ ERROR type annotations needed - //~^ ERROR type annotations needed //~| ERROR type annotations needed } diff --git a/src/test/ui/issues/issue-72690.stderr b/src/test/ui/issues/issue-72690.stderr index 629ccea2577..f1ec678b201 100644 --- a/src/test/ui/issues/issue-72690.stderr +++ b/src/test/ui/issues/issue-72690.stderr @@ -30,16 +30,6 @@ LL | |x| String::from("x".as_ref()); | ^ consider giving this closure parameter a type error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:12:9 - | -LL | |x| String::from("x".as_ref()); - | ^^^^^^^^^^^^ cannot infer type for reference `&_` - | - = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: - - impl<> From<&String> for String; - - impl<> From<&str> for String; - -error[E0283]: type annotations needed --> $DIR/issue-72690.rs:12:26 | LL | |x| String::from("x".as_ref()); @@ -55,7 +45,7 @@ LL | |x| String::from("x".as_ref()); - impl AsRef<str> for str; error[E0283]: type annotations needed for `&T` - --> $DIR/issue-72690.rs:18:17 + --> $DIR/issue-72690.rs:17:17 | LL | let _ = "x".as_ref(); | - ^^^^^^ cannot infer type for type parameter `T` declared on the trait `AsRef` @@ -69,7 +59,7 @@ LL | let _ = "x".as_ref(); - impl AsRef<str> for str; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:22:5 + --> $DIR/issue-72690.rs:21:5 | LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` @@ -79,7 +69,7 @@ LL | String::from("x".as_ref()); - impl<> From<&str> for String; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:22:22 + --> $DIR/issue-72690.rs:21:22 | LL | String::from("x".as_ref()); | ----^^^^^^-- @@ -94,7 +84,7 @@ LL | String::from("x".as_ref()); - impl AsRef<str> for str; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:29:5 + --> $DIR/issue-72690.rs:28:5 | LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` @@ -104,7 +94,7 @@ LL | String::from("x".as_ref()); - impl<> From<&str> for String; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:29:22 + --> $DIR/issue-72690.rs:28:22 | LL | String::from("x".as_ref()); | ----^^^^^^-- @@ -119,7 +109,7 @@ LL | String::from("x".as_ref()); - impl AsRef<str> for str; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:38:5 + --> $DIR/issue-72690.rs:37:5 | LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` @@ -129,7 +119,7 @@ LL | String::from("x".as_ref()); - impl<> From<&str> for String; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:38:22 + --> $DIR/issue-72690.rs:37:22 | LL | String::from("x".as_ref()); | ----^^^^^^-- @@ -144,7 +134,7 @@ LL | String::from("x".as_ref()); - impl AsRef<str> for str; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:47:5 + --> $DIR/issue-72690.rs:46:5 | LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` @@ -154,7 +144,7 @@ LL | String::from("x".as_ref()); - impl<> From<&str> for String; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:47:22 + --> $DIR/issue-72690.rs:46:22 | LL | String::from("x".as_ref()); | ----^^^^^^-- @@ -169,7 +159,7 @@ LL | String::from("x".as_ref()); - impl AsRef<str> for str; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:54:5 + --> $DIR/issue-72690.rs:53:5 | LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` @@ -179,7 +169,7 @@ LL | String::from("x".as_ref()); - impl<> From<&str> for String; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:54:22 + --> $DIR/issue-72690.rs:53:22 | LL | String::from("x".as_ref()); | ----^^^^^^-- @@ -194,7 +184,7 @@ LL | String::from("x".as_ref()); - impl AsRef<str> for str; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:63:5 + --> $DIR/issue-72690.rs:62:5 | LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` @@ -204,7 +194,7 @@ LL | String::from("x".as_ref()); - impl<> From<&str> for String; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:63:22 + --> $DIR/issue-72690.rs:62:22 | LL | String::from("x".as_ref()); | ----^^^^^^-- @@ -218,7 +208,7 @@ LL | String::from("x".as_ref()); - impl AsRef<[u8]> for str; - impl AsRef<str> for str; -error: aborting due to 18 previous errors +error: aborting due to 17 previous errors Some errors have detailed explanations: E0282, E0283. For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.fixed b/src/test/ui/iterators/into-iter-on-arrays-lint.fixed index 0055758a6a4..6e02a7024b9 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.fixed +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.fixed @@ -2,6 +2,7 @@ // run-rustfix // rustfix-only-machine-applicable +#[allow(unused_must_use)] fn main() { let small = [1, 2]; let big = [0u8; 33]; diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.rs b/src/test/ui/iterators/into-iter-on-arrays-lint.rs index 01857c78a73..582d5cadd06 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.rs +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.rs @@ -2,6 +2,7 @@ // run-rustfix // rustfix-only-machine-applicable +#[allow(unused_must_use)] fn main() { let small = [1, 2]; let big = [0u8; 33]; diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr index 634728096ed..e32d35d8638 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr @@ -1,5 +1,5 @@ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:10:11 + --> $DIR/into-iter-on-arrays-lint.rs:11:11 | LL | small.into_iter(); | ^^^^^^^^^ @@ -17,7 +17,7 @@ LL | IntoIterator::into_iter(small); | ++++++++++++++++++++++++ ~ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:13:12 + --> $DIR/into-iter-on-arrays-lint.rs:14:12 | LL | [1, 2].into_iter(); | ^^^^^^^^^ @@ -34,7 +34,7 @@ LL | IntoIterator::into_iter([1, 2]); | ++++++++++++++++++++++++ ~ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:16:9 + --> $DIR/into-iter-on-arrays-lint.rs:17:9 | LL | big.into_iter(); | ^^^^^^^^^ @@ -51,7 +51,7 @@ LL | IntoIterator::into_iter(big); | ++++++++++++++++++++++++ ~ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:19:15 + --> $DIR/into-iter-on-arrays-lint.rs:20:15 | LL | [0u8; 33].into_iter(); | ^^^^^^^^^ @@ -68,7 +68,7 @@ LL | IntoIterator::into_iter([0u8; 33]); | ++++++++++++++++++++++++ ~ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:23:21 + --> $DIR/into-iter-on-arrays-lint.rs:24:21 | LL | Box::new(small).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -77,7 +77,7 @@ LL | Box::new(small).into_iter(); = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:26:22 + --> $DIR/into-iter-on-arrays-lint.rs:27:22 | LL | Box::new([1, 2]).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -86,7 +86,7 @@ LL | Box::new([1, 2]).into_iter(); = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:29:19 + --> $DIR/into-iter-on-arrays-lint.rs:30:19 | LL | Box::new(big).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -95,7 +95,7 @@ LL | Box::new(big).into_iter(); = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:32:25 + --> $DIR/into-iter-on-arrays-lint.rs:33:25 | LL | Box::new([0u8; 33]).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -104,7 +104,7 @@ LL | Box::new([0u8; 33]).into_iter(); = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:36:31 + --> $DIR/into-iter-on-arrays-lint.rs:37:31 | LL | Box::new(Box::new(small)).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -113,7 +113,7 @@ LL | Box::new(Box::new(small)).into_iter(); = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:39:32 + --> $DIR/into-iter-on-arrays-lint.rs:40:32 | LL | Box::new(Box::new([1, 2])).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -122,7 +122,7 @@ LL | Box::new(Box::new([1, 2])).into_iter(); = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:42:29 + --> $DIR/into-iter-on-arrays-lint.rs:43:29 | LL | Box::new(Box::new(big)).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -131,7 +131,7 @@ LL | Box::new(Box::new(big)).into_iter(); = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:45:35 + --> $DIR/into-iter-on-arrays-lint.rs:46:35 | LL | Box::new(Box::new([0u8; 33])).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` diff --git a/src/test/ui/keyword/keyword-false-as-identifier.stderr b/src/test/ui/keyword/keyword-false-as-identifier.stderr index fcc30064018..6dcfa3a4811 100644 --- a/src/test/ui/keyword/keyword-false-as-identifier.stderr +++ b/src/test/ui/keyword/keyword-false-as-identifier.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/keyword-false-as-identifier.rs:2:9 | LL | let false = 22; - | ^^^^^ expected integer, found `bool` + | ^^^^^ -- this expression has type `{integer}` + | | + | expected integer, found `bool` error: aborting due to previous error diff --git a/src/test/ui/keyword/keyword-true-as-identifier.stderr b/src/test/ui/keyword/keyword-true-as-identifier.stderr index b8cc2ffd2a8..86f6e00064f 100644 --- a/src/test/ui/keyword/keyword-true-as-identifier.stderr +++ b/src/test/ui/keyword/keyword-true-as-identifier.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/keyword-true-as-identifier.rs:2:9 | LL | let true = 22; - | ^^^^ expected integer, found `bool` + | ^^^^ -- this expression has type `{integer}` + | | + | expected integer, found `bool` error: aborting due to previous error diff --git a/src/test/ui/lint/issue-17718-const-naming.stderr b/src/test/ui/lint/issue-17718-const-naming.stderr index ce4ebcb5e3e..a1fc99c9a3d 100644 --- a/src/test/ui/lint/issue-17718-const-naming.stderr +++ b/src/test/ui/lint/issue-17718-const-naming.stderr @@ -17,11 +17,6 @@ error: constant `foo` should have an upper case name LL | const foo: isize = 3; | ^^^ help: convert the identifier to upper case (notice the capitalization): `FOO` | -note: the lint level is defined here - --> $DIR/issue-17718-const-naming.rs:2:9 - | -LL | #![deny(warnings)] - | ^^^^^^^^ = note: `#[deny(non_upper_case_globals)]` implied by `#[deny(warnings)]` error: aborting due to 2 previous errors diff --git a/src/test/ui/lint/lint-group-nonstandard-style.stderr b/src/test/ui/lint/lint-group-nonstandard-style.stderr index 0ce33090f66..fcd01012371 100644 --- a/src/test/ui/lint/lint-group-nonstandard-style.stderr +++ b/src/test/ui/lint/lint-group-nonstandard-style.stderr @@ -43,11 +43,6 @@ error: static variable `bad` should have an upper case name LL | static bad: isize = 1; | ^^^ help: convert the identifier to upper case: `BAD` | -note: the lint level is defined here - --> $DIR/lint-group-nonstandard-style.rs:10:14 - | -LL | #[forbid(nonstandard_style)] - | ^^^^^^^^^^^^^^^^^ = note: `#[forbid(non_upper_case_globals)]` implied by `#[forbid(nonstandard_style)]` warning: function `CamelCase` should have a snake case name @@ -56,11 +51,6 @@ warning: function `CamelCase` should have a snake case name LL | fn CamelCase() {} | ^^^^^^^^^ help: convert the identifier to snake case: `camel_case` | -note: the lint level is defined here - --> $DIR/lint-group-nonstandard-style.rs:18:17 - | -LL | #![warn(nonstandard_style)] - | ^^^^^^^^^^^^^^^^^ = note: `#[warn(non_snake_case)]` implied by `#[warn(nonstandard_style)]` error: aborting due to 3 previous errors; 2 warnings emitted diff --git a/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr index 2ef655efdbd..26fa6eb9b9b 100644 --- a/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr +++ b/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr @@ -49,11 +49,6 @@ warning: value assigned to `hours_are_suns` is never read LL | hours_are_suns = false; | ^^^^^^^^^^^^^^ | -note: the lint level is defined here - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:5:9 - | -LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) - | ^^^^^^ = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]` = help: maybe it is overwritten before being read? @@ -107,11 +102,6 @@ LL | let mut mut_unused_var = 1; | | | help: remove this `mut` | -note: the lint level is defined here - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:5:9 - | -LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) - | ^^^^^^ = note: `#[warn(unused_mut)]` implied by `#[warn(unused)]` warning: variable does not need to be mutable diff --git a/src/test/ui/liveness/liveness-consts.stderr b/src/test/ui/liveness/liveness-consts.stderr index b1beec97df5..adaf5431629 100644 --- a/src/test/ui/liveness/liveness-consts.stderr +++ b/src/test/ui/liveness/liveness-consts.stderr @@ -18,11 +18,6 @@ warning: value assigned to `b` is never read LL | b += 1; | ^ | -note: the lint level is defined here - --> $DIR/liveness-consts.rs:2:9 - | -LL | #![warn(unused)] - | ^^^^^^ = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]` = help: maybe it is overwritten before being read? diff --git a/src/test/ui/liveness/liveness-upvars.stderr b/src/test/ui/liveness/liveness-upvars.stderr index d1723302513..cb104e0a3fd 100644 --- a/src/test/ui/liveness/liveness-upvars.stderr +++ b/src/test/ui/liveness/liveness-upvars.stderr @@ -18,11 +18,6 @@ warning: unused variable: `last` LL | last = Some(s); | ^^^^ | -note: the lint level is defined here - --> $DIR/liveness-upvars.rs:4:9 - | -LL | #![warn(unused)] - | ^^^^^^ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` = help: did you mean to capture by reference instead? diff --git a/src/test/ui/match/match-range-fail.stderr b/src/test/ui/match/match-range-fail.stderr index 938c05ac732..65db92df19f 100644 --- a/src/test/ui/match/match-range-fail.stderr +++ b/src/test/ui/match/match-range-fail.stderr @@ -27,6 +27,8 @@ LL | true ..= "what" => {} error[E0308]: mismatched types --> $DIR/match-range-fail.rs:18:9 | +LL | match 5 { + | - this expression has type `{integer}` LL | 'c' ..= 100 => { } | ^^^ --- this is of type `{integer}` | | diff --git a/src/test/ui/mismatched_types/E0409.stderr b/src/test/ui/mismatched_types/E0409.stderr index eb884bcc622..ef03b67b1b0 100644 --- a/src/test/ui/mismatched_types/E0409.stderr +++ b/src/test/ui/mismatched_types/E0409.stderr @@ -9,6 +9,8 @@ LL | (0, ref y) | (y, 0) => {} error[E0308]: mismatched types --> $DIR/E0409.rs:5:23 | +LL | match x { + | - this expression has type `({integer}, {integer})` LL | (0, ref y) | (y, 0) => {} | ----- ^ expected `&{integer}`, found integer | | diff --git a/src/test/ui/mut/mut-pattern-mismatched.stderr b/src/test/ui/mut/mut-pattern-mismatched.stderr index ccc8ac1278c..cad1cef5155 100644 --- a/src/test/ui/mut/mut-pattern-mismatched.stderr +++ b/src/test/ui/mut/mut-pattern-mismatched.stderr @@ -3,6 +3,9 @@ error[E0308]: mismatched types | LL | let &_ | ^^ types differ in mutability +... +LL | = foo; + | --- this expression has type `&mut {integer}` | = note: expected mutable reference `&mut {integer}` found reference `&_` @@ -12,6 +15,9 @@ error[E0308]: mismatched types | LL | let &mut _ | ^^^^^^ types differ in mutability +... +LL | = bar; + | --- this expression has type `&{integer}` | = note: expected reference `&{integer}` found mutable reference `&mut _` diff --git a/src/test/ui/never_type/diverging-tuple-parts-39485.stderr b/src/test/ui/never_type/diverging-tuple-parts-39485.stderr index e99a38aaaee..4b5b8c45d59 100644 --- a/src/test/ui/never_type/diverging-tuple-parts-39485.stderr +++ b/src/test/ui/never_type/diverging-tuple-parts-39485.stderr @@ -1,13 +1,15 @@ error[E0308]: mismatched types --> $DIR/diverging-tuple-parts-39485.rs:8:5 | -LL | fn g() { - | - possibly return type missing here? LL | &panic!() | ^^^^^^^^^ expected `()`, found reference | = note: expected unit type `()` found reference `&_` +help: a return type might be missing here + | +LL | fn g() -> _ { + | ++++ help: consider removing the borrow | LL - &panic!() diff --git a/src/test/ui/never_type/never-assign-dead-code.stderr b/src/test/ui/never_type/never-assign-dead-code.stderr index 5c5cafadc85..521b82023c9 100644 --- a/src/test/ui/never_type/never-assign-dead-code.stderr +++ b/src/test/ui/never_type/never-assign-dead-code.stderr @@ -27,11 +27,6 @@ warning: unused variable: `x` LL | let x: ! = panic!("aah"); | ^ help: if this is intentional, prefix it with an underscore: `_x` | -note: the lint level is defined here - --> $DIR/never-assign-dead-code.rs:6:9 - | -LL | #![warn(unused)] - | ^^^^^^ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` warning: 3 warnings emitted diff --git a/src/test/ui/or-patterns/already-bound-name.stderr b/src/test/ui/or-patterns/already-bound-name.stderr index 92416a0d5cb..66112165622 100644 --- a/src/test/ui/or-patterns/already-bound-name.stderr +++ b/src/test/ui/or-patterns/already-bound-name.stderr @@ -86,8 +86,9 @@ error[E0308]: mismatched types --> $DIR/already-bound-name.rs:30:32 | LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); - | - ^ expected integer, found enum `E` - | | + | - ^ ------- this expression has type `E<E<{integer}>>` + | | | + | | expected integer, found enum `E` | first introduced with type `{integer}` here | = note: expected type `{integer}` diff --git a/src/test/ui/or-patterns/inconsistent-modes.stderr b/src/test/ui/or-patterns/inconsistent-modes.stderr index 95e8618808c..dae6bb41e74 100644 --- a/src/test/ui/or-patterns/inconsistent-modes.stderr +++ b/src/test/ui/or-patterns/inconsistent-modes.stderr @@ -65,8 +65,9 @@ error[E0308]: mismatched types --> $DIR/inconsistent-modes.rs:13:32 | LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); - | ----- ^^^^^^^^^ types differ in mutability - | | + | ----- ^^^^^^^^^ ----------- this expression has type `Result<({integer}, &{integer}), (_, _)>` + | | | + | | types differ in mutability | first introduced with type `&{integer}` here | = note: expected type `&{integer}` diff --git a/src/test/ui/parser/issues/issue-20616-2.stderr b/src/test/ui/parser/issues/issue-20616-2.stderr index 01e3d3dd7cc..13e6aa7d605 100644 --- a/src/test/ui/parser/issues/issue-20616-2.stderr +++ b/src/test/ui/parser/issues/issue-20616-2.stderr @@ -3,6 +3,11 @@ error: expected one of `,`, `:`, `=`, or `>`, found `(` | LL | type Type_2 = Type_1_<'static ()>; | ^ expected one of `,`, `:`, `=`, or `>` + | +help: you might have meant to end the type parameters here + | +LL | type Type_2 = Type_1_<'static> ()>; + | + error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-20616-3.stderr b/src/test/ui/parser/issues/issue-20616-3.stderr index b535c7a3267..dbff116e505 100644 --- a/src/test/ui/parser/issues/issue-20616-3.stderr +++ b/src/test/ui/parser/issues/issue-20616-3.stderr @@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,` | LL | type Type_3<T> = Box<T,,>; | ^ expected one of `>`, a const expression, lifetime, or type + | +help: you might have meant to end the type parameters here + | +LL | type Type_3<T> = Box<T>,,>; + | + error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-20616-4.stderr b/src/test/ui/parser/issues/issue-20616-4.stderr index 2b3b75f3119..48a06e00b24 100644 --- a/src/test/ui/parser/issues/issue-20616-4.stderr +++ b/src/test/ui/parser/issues/issue-20616-4.stderr @@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,` | LL | type Type_4<T> = Type_1_<'static,, T>; | ^ expected one of `>`, a const expression, lifetime, or type + | +help: you might have meant to end the type parameters here + | +LL | type Type_4<T> = Type_1_<'static>,, T>; + | + error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-20616-5.stderr b/src/test/ui/parser/issues/issue-20616-5.stderr index 1ec1dbde695..84bee2ad184 100644 --- a/src/test/ui/parser/issues/issue-20616-5.stderr +++ b/src/test/ui/parser/issues/issue-20616-5.stderr @@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,` | LL | type Type_5<'a> = Type_1_<'a, (),,>; | ^ expected one of `>`, a const expression, lifetime, or type + | +help: you might have meant to end the type parameters here + | +LL | type Type_5<'a> = Type_1_<'a, ()>,,>; + | + error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-20616-6.stderr b/src/test/ui/parser/issues/issue-20616-6.stderr index 7401abdd091..67de41b9747 100644 --- a/src/test/ui/parser/issues/issue-20616-6.stderr +++ b/src/test/ui/parser/issues/issue-20616-6.stderr @@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,` | LL | type Type_6 = Type_5_<'a,,>; | ^ expected one of `>`, a const expression, lifetime, or type + | +help: you might have meant to end the type parameters here + | +LL | type Type_6 = Type_5_<'a>,,>; + | + error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-20616-7.stderr b/src/test/ui/parser/issues/issue-20616-7.stderr index e2c3efe8447..3b8e07fa0d0 100644 --- a/src/test/ui/parser/issues/issue-20616-7.stderr +++ b/src/test/ui/parser/issues/issue-20616-7.stderr @@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,` | LL | type Type_7 = Box<(),,>; | ^ expected one of `>`, a const expression, lifetime, or type + | +help: you might have meant to end the type parameters here + | +LL | type Type_7 = Box<()>,,>; + | + error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-62660.stderr b/src/test/ui/parser/issues/issue-62660.stderr index a50ada9056b..be0b9a524df 100644 --- a/src/test/ui/parser/issues/issue-62660.stderr +++ b/src/test/ui/parser/issues/issue-62660.stderr @@ -3,6 +3,11 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `) | LL | pub fn foo(_: i32, self: Box<Self) {} | ^ expected one of 9 possible tokens + | +help: you might have meant to end the type parameters here + | +LL | pub fn foo(_: i32, self: Box<Self>) {} + | + error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-84117.stderr b/src/test/ui/parser/issues/issue-84117.stderr index 5b9cc53baa5..a2407affeef 100644 --- a/src/test/ui/parser/issues/issue-84117.stderr +++ b/src/test/ui/parser/issues/issue-84117.stderr @@ -2,10 +2,18 @@ error: expected one of `>`, a const expression, lifetime, or type, found `}` --> $DIR/issue-84117.rs:2:67 | LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } - | ------------ ^ expected one of `>`, a const expression, lifetime, or type - | | | - | | help: use `=` if you meant to assign + | ----------- ^ expected one of `>`, a const expression, lifetime, or type + | | | while parsing the type for `inner_local` + | +help: you might have meant to end the type parameters here + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str>, } + | + +help: use `=` if you meant to assign + | +LL | let outer_local:e_outer<&str, { let inner_local =e_inner<&str, } + | ~ error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,` --> $DIR/issue-84117.rs:2:65 @@ -17,21 +25,36 @@ error: expected one of `,`, `:`, `=`, or `>`, found `}` --> $DIR/issue-84117.rs:8:1 | LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } - | ------------ help: use `=` if you meant to assign - expected one of `,`, `:`, `=`, or `>` - | | - | while parsing the type for `outer_local` + | ----------- while parsing the type for `outer_local` - expected one of `,`, `:`, `=`, or `>` ... LL | } | ^ unexpected token + | +help: you might have meant to end the type parameters here + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }> + | + +help: use `=` if you meant to assign + | +LL | let outer_local =e_outer<&str, { let inner_local:e_inner<&str, } + | ~ error: expected one of `>`, a const expression, lifetime, or type, found `}` --> $DIR/issue-84117.rs:2:67 | LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } - | ------------ ^ expected one of `>`, a const expression, lifetime, or type - | | | - | | help: use `=` if you meant to assign + | ----------- ^ expected one of `>`, a const expression, lifetime, or type + | | | while parsing the type for `inner_local` + | +help: you might have meant to end the type parameters here + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str>, } + | + +help: use `=` if you meant to assign + | +LL | let outer_local:e_outer<&str, { let inner_local =e_inner<&str, } + | ~ error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,` --> $DIR/issue-84117.rs:2:65 diff --git a/src/test/ui/parser/lifetime-semicolon.fixed b/src/test/ui/parser/lifetime-semicolon.fixed new file mode 100644 index 00000000000..89e87fe9988 --- /dev/null +++ b/src/test/ui/parser/lifetime-semicolon.fixed @@ -0,0 +1,10 @@ +// run-rustfix +#![allow(unused)] +struct Foo<'a, 'b> { + a: &'a &'b i32 +} + +fn foo<'a, 'b>(_x: &mut Foo<'a, 'b>) {} +//~^ ERROR expected one of `,`, `:`, `=`, or `>`, found `;` + +fn main() {} diff --git a/src/test/ui/parser/lifetime-semicolon.rs b/src/test/ui/parser/lifetime-semicolon.rs index 7cc14971f63..744c93fc7c7 100644 --- a/src/test/ui/parser/lifetime-semicolon.rs +++ b/src/test/ui/parser/lifetime-semicolon.rs @@ -1,8 +1,10 @@ +// run-rustfix +#![allow(unused)] struct Foo<'a, 'b> { a: &'a &'b i32 } -fn foo<'a, 'b>(x: &mut Foo<'a; 'b>) {} +fn foo<'a, 'b>(_x: &mut Foo<'a; 'b>) {} //~^ ERROR expected one of `,`, `:`, `=`, or `>`, found `;` fn main() {} diff --git a/src/test/ui/parser/lifetime-semicolon.stderr b/src/test/ui/parser/lifetime-semicolon.stderr index 3b67705aae9..5de7a5f2d5d 100644 --- a/src/test/ui/parser/lifetime-semicolon.stderr +++ b/src/test/ui/parser/lifetime-semicolon.stderr @@ -1,8 +1,13 @@ error: expected one of `,`, `:`, `=`, or `>`, found `;` - --> $DIR/lifetime-semicolon.rs:5:30 + --> $DIR/lifetime-semicolon.rs:7:31 | -LL | fn foo<'a, 'b>(x: &mut Foo<'a; 'b>) {} - | ^ expected one of `,`, `:`, `=`, or `>` +LL | fn foo<'a, 'b>(_x: &mut Foo<'a; 'b>) {} + | ^ expected one of `,`, `:`, `=`, or `>` + | +help: use a comma to separate type parameters + | +LL | fn foo<'a, 'b>(_x: &mut Foo<'a, 'b>) {} + | ~ error: aborting due to previous error diff --git a/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr b/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr index 93403372bcb..427234e97cf 100644 --- a/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr +++ b/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr @@ -6,6 +6,11 @@ LL | let v : Vec<(u32,_) = vec![]; | | | | | maybe try to close unmatched angle bracket | while parsing the type for `v` + | +help: you might have meant to end the type parameters here + | +LL | let v : Vec<(u32,_)> = vec![]; + | + error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `{` --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:13:32 @@ -14,6 +19,11 @@ LL | let foo : Foo::<T1, T2 = Foo {_a : arg1, _b : arg2}; | --- ^ expected one of 7 possible tokens | | | while parsing the type for `foo` + | +help: you might have meant to end the type parameters here + | +LL | let foo : Foo::<T1>, T2 = Foo {_a : arg1, _b : arg2}; + | + error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:18:18 @@ -23,6 +33,11 @@ LL | let v : Vec<'a = vec![]; | | | | | maybe try to close unmatched angle bracket | while parsing the type for `v` + | +help: you might have meant to end the type parameters here + | +LL | let v : Vec<'a> = vec![]; + | + error[E0282]: type annotations needed for `Vec<T>` --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:25 diff --git a/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.rs b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.rs new file mode 100644 index 00000000000..d69a56c51d3 --- /dev/null +++ b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.rs @@ -0,0 +1,11 @@ +// run-rustifx +#![allow(unused)] +use std::sync::{Arc, Mutex}; + +pub struct Foo { + a: Mutex<usize>, + b: Arc<Mutex<usize>, //~ HELP you might have meant to end the type parameters here + c: Arc<Mutex<usize>>, +} //~ ERROR expected one of + +fn main() {} diff --git a/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr new file mode 100644 index 00000000000..46ca1f06be6 --- /dev/null +++ b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr @@ -0,0 +1,15 @@ +error: expected one of `>`, a const expression, lifetime, or type, found `}` + --> $DIR/missing-closing-angle-bracket-struct-field-ty.rs:9:1 + | +LL | c: Arc<Mutex<usize>>, + | - expected one of `>`, a const expression, lifetime, or type +LL | } + | ^ unexpected token + | +help: you might have meant to end the type parameters here + | +LL | b: Arc<Mutex<usize>>, + | + + +error: aborting due to previous error + diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr index 9296ad2e335..8063ba8e9f7 100644 --- a/src/test/ui/parser/recover-range-pats.stderr +++ b/src/test/ui/parser/recover-range-pats.stderr @@ -303,8 +303,9 @@ error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:22:12 | LL | if let .0..Y = 0 {} - | ^^ - this is of type `u8` - | | + | ^^ - - this expression has type `{integer}` + | | | + | | this is of type `u8` | expected integer, found floating-point number error[E0308]: mismatched types @@ -336,8 +337,9 @@ error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:35:12 | LL | if let .0..=Y = 0 {} - | ^^ - this is of type `u8` - | | + | ^^ - - this expression has type `{integer}` + | | | + | | this is of type `u8` | expected integer, found floating-point number error[E0308]: mismatched types @@ -369,8 +371,9 @@ error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:60:12 | LL | if let .0...Y = 0 {} - | ^^ - this is of type `u8` - | | + | ^^ - - this expression has type `{integer}` + | | | + | | this is of type `u8` | expected integer, found floating-point number error[E0308]: mismatched types @@ -392,7 +395,9 @@ error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:75:12 | LL | if let .0.. = 0 {} - | ^^ expected integer, found floating-point number + | ^^ - this expression has type `{integer}` + | | + | expected integer, found floating-point number error[E0029]: only `char` and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:83:12 @@ -404,7 +409,9 @@ error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:85:12 | LL | if let .0..= = 0 {} - | ^^ expected integer, found floating-point number + | ^^ - this expression has type `{integer}` + | | + | expected integer, found floating-point number error[E0029]: only `char` and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:93:12 @@ -416,7 +423,9 @@ error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:95:12 | LL | if let .0... = 0 {} - | ^^ expected integer, found floating-point number + | ^^ - this expression has type `{integer}` + | | + | expected integer, found floating-point number error[E0029]: only `char` and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:103:14 @@ -428,7 +437,9 @@ error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:105:15 | LL | if let .. .0 = 0 {} - | ^^ expected integer, found floating-point number + | ^^ - this expression has type `{integer}` + | | + | expected integer, found floating-point number error[E0029]: only `char` and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:113:15 @@ -440,7 +451,9 @@ error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:115:15 | LL | if let ..=.0 = 0 {} - | ^^ expected integer, found floating-point number + | ^^ - this expression has type `{integer}` + | | + | expected integer, found floating-point number error[E0029]: only `char` and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:125:15 @@ -452,7 +465,9 @@ error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:128:15 | LL | if let ....3 = 0 {} - | ^^ expected integer, found floating-point number + | ^^ - this expression has type `{integer}` + | | + | expected integer, found floating-point number error: aborting due to 60 previous errors diff --git a/src/test/ui/parser/removed-syntax-closure-lifetime.stderr b/src/test/ui/parser/removed-syntax-closure-lifetime.stderr index 63b6e138ce5..e107c6b78b3 100644 --- a/src/test/ui/parser/removed-syntax-closure-lifetime.stderr +++ b/src/test/ui/parser/removed-syntax-closure-lifetime.stderr @@ -3,6 +3,11 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `/ | LL | type closure = Box<lt/fn()>; | ^ expected one of 9 possible tokens + | +help: you might have meant to end the type parameters here + | +LL | type closure = Box<lt>/fn()>; + | + error: aborting due to previous error diff --git a/src/test/ui/pattern/issue-74702.stderr b/src/test/ui/pattern/issue-74702.stderr index 53dcf97f81c..f2e2c8f021b 100644 --- a/src/test/ui/pattern/issue-74702.stderr +++ b/src/test/ui/pattern/issue-74702.stderr @@ -22,7 +22,9 @@ error[E0308]: mismatched types --> $DIR/issue-74702.rs:2:9 | LL | let (foo @ ..,) = (0, 0); - | ^^^^^^^^^^^ expected a tuple with 2 elements, found one with 1 element + | ^^^^^^^^^^^ ------ this expression has type `({integer}, {integer})` + | | + | expected a tuple with 2 elements, found one with 1 element | = note: expected tuple `({integer}, {integer})` found tuple `(_,)` diff --git a/src/test/ui/pattern/pat-tuple-overfield.stderr b/src/test/ui/pattern/pat-tuple-overfield.stderr index 64b6e5eec55..1c44f7e5f6f 100644 --- a/src/test/ui/pattern/pat-tuple-overfield.stderr +++ b/src/test/ui/pattern/pat-tuple-overfield.stderr @@ -150,6 +150,8 @@ LL | E1::Z0 => {} error[E0308]: mismatched types --> $DIR/pat-tuple-overfield.rs:19:9 | +LL | match (1, 2, 3) { + | --------- this expression has type `({integer}, {integer}, {integer})` LL | (1, 2, 3, 4) => {} | ^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 4 elements | @@ -159,6 +161,9 @@ LL | (1, 2, 3, 4) => {} error[E0308]: mismatched types --> $DIR/pat-tuple-overfield.rs:20:9 | +LL | match (1, 2, 3) { + | --------- this expression has type `({integer}, {integer}, {integer})` +LL | (1, 2, 3, 4) => {} LL | (1, 2, .., 3, 4) => {} | ^^^^^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 4 elements | diff --git a/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout b/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout index 0e7b429d621..4de8746a1b4 100644 --- a/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout +++ b/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout @@ -112,15 +112,9 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ spacing: Alone, span: $DIR/capture-macro-rules-invoke.rs:14:54: 14:55 (#8), }, - Group { - delimiter: None, - stream: TokenStream [ - Ident { - ident: "my_name", - span: $DIR/capture-macro-rules-invoke.rs:42:13: 42:20 (#0), - }, - ], - span: $DIR/capture-macro-rules-invoke.rs:14:56: 14:62 (#8), + Ident { + ident: "my_name", + span: $DIR/capture-macro-rules-invoke.rs:42:13: 42:20 (#0), }, Punct { ch: ',', diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr index a2c1b82b15f..f1a167e37b4 100644 --- a/src/test/ui/proc-macro/generate-mod.stderr +++ b/src/test/ui/proc-macro/generate-mod.stderr @@ -101,6 +101,7 @@ error: cannot find type `OuterDerive` in this scope LL | #[derive(generate_mod::CheckDerive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import | + = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -112,6 +113,7 @@ error: cannot find type `FromOutside` in this scope LL | #[derive(generate_mod::CheckDerive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import | + = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -123,6 +125,7 @@ error: cannot find type `OuterDerive` in this scope LL | #[derive(generate_mod::CheckDerive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import | + = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -150,6 +153,11 @@ warning: cannot find type `OuterDeriveLint` in this scope LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import | +note: the lint level is defined here + --> $DIR/generate-mod.rs:30:10 + | +LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/proc-macro/group-compat-hack/actix-web-2.0.0/src/extract.rs b/src/test/ui/proc-macro/group-compat-hack/actix-web-2.0.0/src/extract.rs deleted file mode 100644 index 2d4f6010012..00000000000 --- a/src/test/ui/proc-macro/group-compat-hack/actix-web-2.0.0/src/extract.rs +++ /dev/null @@ -1,7 +0,0 @@ -// ignore-test this is not a test - -macro_rules! tuple_from_req { - ($T:ident) => { - #[my_macro] struct Three($T); - } -} diff --git a/src/test/ui/proc-macro/group-compat-hack/actix-web/src/extract.rs b/src/test/ui/proc-macro/group-compat-hack/actix-web/src/extract.rs deleted file mode 100644 index 2d4f6010012..00000000000 --- a/src/test/ui/proc-macro/group-compat-hack/actix-web/src/extract.rs +++ /dev/null @@ -1,7 +0,0 @@ -// ignore-test this is not a test - -macro_rules! tuple_from_req { - ($T:ident) => { - #[my_macro] struct Three($T); - } -} diff --git a/src/test/ui/proc-macro/group-compat-hack/actori-web-2.0.0/src/extract.rs b/src/test/ui/proc-macro/group-compat-hack/actori-web-2.0.0/src/extract.rs deleted file mode 100644 index 9ec6aba63f3..00000000000 --- a/src/test/ui/proc-macro/group-compat-hack/actori-web-2.0.0/src/extract.rs +++ /dev/null @@ -1,7 +0,0 @@ -// ignore-test this is not a test - -macro_rules! tuple_from_req { - ($T:ident) => { - #[my_macro] struct Four($T); - } -} diff --git a/src/test/ui/proc-macro/group-compat-hack/actori-web/src/extract.rs b/src/test/ui/proc-macro/group-compat-hack/actori-web/src/extract.rs deleted file mode 100644 index 9ec6aba63f3..00000000000 --- a/src/test/ui/proc-macro/group-compat-hack/actori-web/src/extract.rs +++ /dev/null @@ -1,7 +0,0 @@ -// ignore-test this is not a test - -macro_rules! tuple_from_req { - ($T:ident) => { - #[my_macro] struct Four($T); - } -} diff --git a/src/test/ui/proc-macro/group-compat-hack/auxiliary/pin-project-internal-0.4.0.rs b/src/test/ui/proc-macro/group-compat-hack/auxiliary/pin-project-internal-0.4.0.rs deleted file mode 100644 index baa4fd3a105..00000000000 --- a/src/test/ui/proc-macro/group-compat-hack/auxiliary/pin-project-internal-0.4.0.rs +++ /dev/null @@ -1,17 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] -#![crate_name = "group_compat_hack"] - -// This file has an unusual name in order to trigger the back-compat -// code in the compiler - -extern crate proc_macro; -use proc_macro::TokenStream; - -#[proc_macro_attribute] -pub fn my_macro(_attr: TokenStream, input: TokenStream) -> TokenStream { - println!("Called proc_macro_hack with {:?}", input); - input -} diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs deleted file mode 100644 index 3a2a6fa2253..00000000000 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs +++ /dev/null @@ -1,87 +0,0 @@ -// aux-build:pin-project-internal-0.4.0.rs -// compile-flags: -Z span-debug - -#![no_std] // Don't load unnecessary hygiene information from std -extern crate std; - -#[macro_use] extern crate group_compat_hack; - -// Tests the backwards compatibility hack added for certain macros -// When an attribute macro named `proc_macro_hack` or `wasm_bindgen` -// has an `NtIdent` named `$name`, we pass a plain `Ident` token in -// place of a `None`-delimited group. This allows us to maintain -// backwards compatibility for older versions of these crates. - -mod no_version { - include!("js-sys/src/lib.rs"); - include!("time-macros-impl/src/lib.rs"); - - macro_rules! other { - ($name:ident) => { - #[my_macro] struct Three($name); - } - } - - struct Foo; - impl_macros!(Foo); //~ ERROR using an old version - //~| WARN this was previously - arrays!(Foo); - other!(Foo); -} - -mod with_version { - include!("js-sys-0.3.17/src/lib.rs"); - include!("time-macros-impl-0.1.0/src/lib.rs"); - - macro_rules! other { - ($name:ident) => { - #[my_macro] struct Three($name); - } - } - - struct Foo; - impl_macros!(Foo); //~ ERROR using an old version - //~| WARN this was previously - arrays!(Foo); //~ ERROR using an old version - //~| WARN this was previously - other!(Foo); -} - -mod actix_web_test { - include!("actix-web/src/extract.rs"); - - struct Foo; - tuple_from_req!(Foo); //~ ERROR using an old version - //~| WARN this was previously -} - -mod actix_web_version_test { - include!("actix-web-2.0.0/src/extract.rs"); - - struct Foo; - tuple_from_req!(Foo); //~ ERROR using an old version - //~| WARN this was previously -} - -mod actori_web_test { - include!("actori-web/src/extract.rs"); - - struct Foo; - tuple_from_req!(Foo); -} - -mod actori_web_version_test { - include!("actori-web-2.0.0/src/extract.rs"); - - struct Foo; - tuple_from_req!(Foo); -} - -mod with_good_js_sys_version { - include!("js-sys-0.3.40/src/lib.rs"); - struct Foo; - arrays!(Foo); -} - - -fn main() {} diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr deleted file mode 100644 index bd9ba6a09fc..00000000000 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr +++ /dev/null @@ -1,169 +0,0 @@ -error: using an old version of `time-macros-impl` - --> $DIR/time-macros-impl/src/lib.rs:5:32 - | -LL | #[my_macro] struct One($name); - | ^^^^^ - | - ::: $DIR/group-compat-hack.rs:26:5 - | -LL | impl_macros!(Foo); - | ----------------- in this macro invocation - | - = note: `#[deny(proc_macro_back_compat)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> - = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage - = note: this error originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: using an old version of `time-macros-impl` - --> $DIR/time-macros-impl-0.1.0/src/lib.rs:5:32 - | -LL | #[my_macro] struct One($name); - | ^^^^^ - | - ::: $DIR/group-compat-hack.rs:43:5 - | -LL | impl_macros!(Foo); - | ----------------- in this macro invocation - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> - = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage - = note: this error originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: using an old version of `js-sys` - --> $DIR/js-sys-0.3.17/src/lib.rs:5:32 - | -LL | #[my_macro] struct Two($name); - | ^^^^^ - | - ::: $DIR/group-compat-hack.rs:45:5 - | -LL | arrays!(Foo); - | ------------ in this macro invocation - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> - = note: older versions of the `js-sys` crate will stop compiling in future versions of Rust; please update to `js-sys` v0.3.40 or above - = note: this error originates in the macro `arrays` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: using an old version of `actix-web` - --> $DIR/actix-web/src/extract.rs:5:34 - | -LL | #[my_macro] struct Three($T); - | ^^ - | - ::: $DIR/group-compat-hack.rs:54:5 - | -LL | tuple_from_req!(Foo); - | -------------------- in this macro invocation - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> - = note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage - = note: this error originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: using an old version of `actix-web` - --> $DIR/actix-web-2.0.0/src/extract.rs:5:34 - | -LL | #[my_macro] struct Three($T); - | ^^ - | - ::: $DIR/group-compat-hack.rs:62:5 - | -LL | tuple_from_req!(Foo); - | -------------------- in this macro invocation - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> - = note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage - = note: this error originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 5 previous errors - -Future incompatibility report: Future breakage diagnostic: -error: using an old version of `time-macros-impl` - --> $DIR/time-macros-impl/src/lib.rs:5:32 - | -LL | #[my_macro] struct One($name); - | ^^^^^ - | - ::: $DIR/group-compat-hack.rs:26:5 - | -LL | impl_macros!(Foo); - | ----------------- in this macro invocation - | - = note: `#[deny(proc_macro_back_compat)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> - = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage - = note: this error originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) - -Future breakage diagnostic: -error: using an old version of `time-macros-impl` - --> $DIR/time-macros-impl-0.1.0/src/lib.rs:5:32 - | -LL | #[my_macro] struct One($name); - | ^^^^^ - | - ::: $DIR/group-compat-hack.rs:43:5 - | -LL | impl_macros!(Foo); - | ----------------- in this macro invocation - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> - = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage - = note: this error originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) - -Future breakage diagnostic: -error: using an old version of `js-sys` - --> $DIR/js-sys-0.3.17/src/lib.rs:5:32 - | -LL | #[my_macro] struct Two($name); - | ^^^^^ - | - ::: $DIR/group-compat-hack.rs:45:5 - | -LL | arrays!(Foo); - | ------------ in this macro invocation - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> - = note: older versions of the `js-sys` crate will stop compiling in future versions of Rust; please update to `js-sys` v0.3.40 or above - = note: this error originates in the macro `arrays` (in Nightly builds, run with -Z macro-backtrace for more info) - -Future breakage diagnostic: -error: using an old version of `actix-web` - --> $DIR/actix-web/src/extract.rs:5:34 - | -LL | #[my_macro] struct Three($T); - | ^^ - | - ::: $DIR/group-compat-hack.rs:54:5 - | -LL | tuple_from_req!(Foo); - | -------------------- in this macro invocation - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> - = note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage - = note: this error originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info) - -Future breakage diagnostic: -error: using an old version of `actix-web` - --> $DIR/actix-web-2.0.0/src/extract.rs:5:34 - | -LL | #[my_macro] struct Three($T); - | ^^ - | - ::: $DIR/group-compat-hack.rs:62:5 - | -LL | tuple_from_req!(Foo); - | -------------------- in this macro invocation - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> - = note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage - = note: this error originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info) - diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout deleted file mode 100644 index 51312b10ad1..00000000000 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout +++ /dev/null @@ -1,11 +0,0 @@ -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl/src/lib.rs:5:21: 5:27 (#6) }, Ident { ident: "One", span: $DIR/time-macros-impl/src/lib.rs:5:28: 5:31 (#6) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:26:18: 26:21 (#0) }], span: $DIR/time-macros-impl/src/lib.rs:5:31: 5:38 (#6) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl/src/lib.rs:5:38: 5:39 (#6) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys/src/lib.rs:5:21: 5:27 (#10) }, Ident { ident: "Two", span: $DIR/js-sys/src/lib.rs:5:28: 5:31 (#10) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:28:13: 28:16 (#0) }], span: $DIR/js-sys/src/lib.rs:5:32: 5:37 (#10) }], span: $DIR/js-sys/src/lib.rs:5:31: 5:38 (#10) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys/src/lib.rs:5:38: 5:39 (#10) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:21:25: 21:31 (#14) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:21:32: 21:37 (#14) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:12: 29:15 (#0) }], span: $DIR/group-compat-hack.rs:21:38: 21:43 (#14) }], span: $DIR/group-compat-hack.rs:21:37: 21:44 (#14) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:21:44: 21:45 (#14) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:21: 5:27 (#20) }, Ident { ident: "One", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:28: 5:31 (#20) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:43:18: 43:21 (#0) }], span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:31: 5:38 (#20) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:38: 5:39 (#20) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.17/src/lib.rs:5:21: 5:27 (#24) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.17/src/lib.rs:5:28: 5:31 (#24) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:45:13: 45:16 (#0) }], span: $DIR/js-sys-0.3.17/src/lib.rs:5:31: 5:38 (#24) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.17/src/lib.rs:5:38: 5:39 (#24) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:38:25: 38:31 (#28) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:38:32: 38:37 (#28) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:47:12: 47:15 (#0) }], span: $DIR/group-compat-hack.rs:38:38: 38:43 (#28) }], span: $DIR/group-compat-hack.rs:38:37: 38:44 (#28) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:38:44: 38:45 (#28) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web/src/extract.rs:5:21: 5:27 (#33) }, Ident { ident: "Three", span: $DIR/actix-web/src/extract.rs:5:28: 5:33 (#33) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:54:21: 54:24 (#0) }], span: $DIR/actix-web/src/extract.rs:5:33: 5:37 (#33) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web/src/extract.rs:5:37: 5:38 (#33) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web-2.0.0/src/extract.rs:5:21: 5:27 (#38) }, Ident { ident: "Three", span: $DIR/actix-web-2.0.0/src/extract.rs:5:28: 5:33 (#38) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:62:21: 62:24 (#0) }], span: $DIR/actix-web-2.0.0/src/extract.rs:5:33: 5:37 (#38) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web-2.0.0/src/extract.rs:5:37: 5:38 (#38) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web/src/extract.rs:5:21: 5:27 (#43) }, Ident { ident: "Four", span: $DIR/actori-web/src/extract.rs:5:28: 5:32 (#43) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:70:21: 70:24 (#0) }], span: $DIR/actori-web/src/extract.rs:5:33: 5:35 (#43) }], span: $DIR/actori-web/src/extract.rs:5:32: 5:36 (#43) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web/src/extract.rs:5:36: 5:37 (#43) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web-2.0.0/src/extract.rs:5:21: 5:27 (#48) }, Ident { ident: "Four", span: $DIR/actori-web-2.0.0/src/extract.rs:5:28: 5:32 (#48) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:77:21: 77:24 (#0) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:33: 5:35 (#48) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:32: 5:36 (#48) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web-2.0.0/src/extract.rs:5:36: 5:37 (#48) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.40/src/lib.rs:5:21: 5:27 (#53) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.40/src/lib.rs:5:28: 5:31 (#53) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:83:13: 83:16 (#0) }], span: $DIR/js-sys-0.3.40/src/lib.rs:5:32: 5:37 (#53) }], span: $DIR/js-sys-0.3.40/src/lib.rs:5:31: 5:38 (#53) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.40/src/lib.rs:5:38: 5:39 (#53) }] diff --git a/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.17/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.17/src/lib.rs deleted file mode 100644 index d1a66940ebf..00000000000 --- a/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.17/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -// ignore-test this is not a test - -macro_rules! arrays { - ($name:ident) => { - #[my_macro] struct Two($name); - } -} diff --git a/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.40/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.40/src/lib.rs deleted file mode 100644 index d1a66940ebf..00000000000 --- a/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.40/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -// ignore-test this is not a test - -macro_rules! arrays { - ($name:ident) => { - #[my_macro] struct Two($name); - } -} diff --git a/src/test/ui/proc-macro/group-compat-hack/js-sys/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/js-sys/src/lib.rs deleted file mode 100644 index d1a66940ebf..00000000000 --- a/src/test/ui/proc-macro/group-compat-hack/js-sys/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -// ignore-test this is not a test - -macro_rules! arrays { - ($name:ident) => { - #[my_macro] struct Two($name); - } -} diff --git a/src/test/ui/proc-macro/group-compat-hack/time-macros-impl-0.1.0/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/time-macros-impl-0.1.0/src/lib.rs deleted file mode 100644 index c94c3579209..00000000000 --- a/src/test/ui/proc-macro/group-compat-hack/time-macros-impl-0.1.0/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -// ignore-test this is not a test - -macro_rules! impl_macros { - ($name:ident) => { - #[my_macro] struct One($name); - } -} diff --git a/src/test/ui/proc-macro/group-compat-hack/time-macros-impl/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/time-macros-impl/src/lib.rs deleted file mode 100644 index c94c3579209..00000000000 --- a/src/test/ui/proc-macro/group-compat-hack/time-macros-impl/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -// ignore-test this is not a test - -macro_rules! impl_macros { - ($name:ident) => { - #[my_macro] struct One($name); - } -} diff --git a/src/test/ui/proc-macro/input-interpolated.stdout b/src/test/ui/proc-macro/input-interpolated.stdout index 44baa37577c..34566c78019 100644 --- a/src/test/ui/proc-macro/input-interpolated.stdout +++ b/src/test/ui/proc-macro/input-interpolated.stdout @@ -1,14 +1,8 @@ PRINT-BANG INPUT (DISPLAY): A PRINT-BANG INPUT (DEBUG): TokenStream [ - Group { - delimiter: None, - stream: TokenStream [ - Ident { - ident: "A", - span: #0 bytes(503..504), - }, - ], - span: #4 bytes(370..372), + Ident { + ident: "A", + span: #0 bytes(503..504), }, ] PRINT-ATTR INPUT (DISPLAY): const A : u8 = 0 ; @@ -17,15 +11,9 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ ident: "const", span: #4 bytes(416..421), }, - Group { - delimiter: None, - stream: TokenStream [ - Ident { - ident: "A", - span: #0 bytes(503..504), - }, - ], - span: #4 bytes(422..424), + Ident { + ident: "A", + span: #0 bytes(503..504), }, Punct { ch: ':', @@ -59,15 +47,9 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ ident: "struct", span: #4 bytes(468..474), }, - Group { - delimiter: None, - stream: TokenStream [ - Ident { - ident: "A", - span: #0 bytes(503..504), - }, - ], - span: #4 bytes(475..477), + Ident { + ident: "A", + span: #0 bytes(503..504), }, Group { delimiter: Brace, diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr index 554613be65a..be4239089e8 100644 --- a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr +++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr @@ -60,6 +60,7 @@ error: using `procedural-masquerade` crate LL | enum ProceduralMasqueradeDummyType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: `#[deny(proc_macro_back_compat)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling. @@ -71,6 +72,7 @@ error: using `procedural-masquerade` crate LL | enum ProceduralMasqueradeDummyType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: `#[deny(proc_macro_back_compat)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling. @@ -82,6 +84,7 @@ error: using `procedural-masquerade` crate LL | enum ProceduralMasqueradeDummyType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: `#[deny(proc_macro_back_compat)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling. diff --git a/src/test/ui/proc-macro/nested-macro-rules.stdout b/src/test/ui/proc-macro/nested-macro-rules.stdout index 68f30c23a8d..fa35e81148b 100644 --- a/src/test/ui/proc-macro/nested-macro-rules.stdout +++ b/src/test/ui/proc-macro/nested-macro-rules.stdout @@ -35,15 +35,9 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ ] PRINT-BANG INPUT (DISPLAY): SecondStruct PRINT-BANG INPUT (DEBUG): TokenStream [ - Group { - delimiter: None, - stream: TokenStream [ - Ident { - ident: "SecondStruct", - span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#16), - }, - ], - span: $DIR/auxiliary/nested-macro-rules.rs:9:30: 9:35 (#15), + Ident { + ident: "SecondStruct", + span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#16), }, ] PRINT-ATTR INPUT (DISPLAY): struct SecondAttrStruct {} @@ -52,15 +46,9 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ ident: "struct", span: $DIR/auxiliary/nested-macro-rules.rs:10:32: 10:38 (#15), }, - Group { - delimiter: None, - stream: TokenStream [ - Ident { - ident: "SecondAttrStruct", - span: $DIR/nested-macro-rules.rs:21:52: 21:68 (#16), - }, - ], - span: $DIR/auxiliary/nested-macro-rules.rs:10:39: 10:56 (#15), + Ident { + ident: "SecondAttrStruct", + span: $DIR/nested-macro-rules.rs:21:52: 21:68 (#16), }, Group { delimiter: Brace, diff --git a/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout b/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout index 7331a25abd3..6824395ae40 100644 --- a/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout +++ b/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout @@ -1,13 +1,7 @@ First recollected: TokenStream [ - Group { - delimiter: None, - stream: TokenStream [ - Ident { - ident: "pub", - span: $DIR/nonterminal-recollect-attr.rs:20:11: 20:14 (#0), - }, - ], - span: $DIR/nonterminal-recollect-attr.rs:14:9: 14:11 (#4), + Ident { + ident: "pub", + span: $DIR/nonterminal-recollect-attr.rs:20:11: 20:14 (#0), }, Ident { ident: "struct", diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr index e9a44ccb12e..66c68be2f09 100644 --- a/src/test/ui/proc-macro/span-preservation.stderr +++ b/src/test/ui/proc-macro/span-preservation.stderr @@ -38,7 +38,7 @@ error[E0308]: mismatched types --> $DIR/span-preservation.rs:39:5 | LL | extern "C" fn bar() { - | - possibly return type missing here? + | - help: try adding a return type: `-> i32` LL | 0 | ^ expected `()`, found integer @@ -46,7 +46,7 @@ error[E0308]: mismatched types --> $DIR/span-preservation.rs:44:5 | LL | extern "C" fn baz() { - | - possibly return type missing here? + | - help: try adding a return type: `-> i32` LL | 0 | ^ expected `()`, found integer @@ -54,7 +54,7 @@ error[E0308]: mismatched types --> $DIR/span-preservation.rs:49:5 | LL | extern "Rust" fn rust_abi() { - | - possibly return type missing here? + | - help: try adding a return type: `-> i32` LL | 0 | ^ expected `()`, found integer @@ -62,7 +62,7 @@ error[E0308]: mismatched types --> $DIR/span-preservation.rs:54:5 | LL | extern "\x43" fn c_abi_escaped() { - | - possibly return type missing here? + | - help: try adding a return type: `-> i32` LL | 0 | ^ expected `()`, found integer diff --git a/src/test/ui/return/return-type.stderr b/src/test/ui/return/return-type.stderr index f86209a651d..5af136e6011 100644 --- a/src/test/ui/return/return-type.stderr +++ b/src/test/ui/return/return-type.stderr @@ -1,15 +1,19 @@ error[E0308]: mismatched types --> $DIR/return-type.rs:10:5 | -LL | fn bar() { - | - possibly return type missing here? LL | foo(4 as usize) - | ^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;` - | | - | expected `()`, found struct `S` + | ^^^^^^^^^^^^^^^ expected `()`, found struct `S` | = note: expected unit type `()` found struct `S<usize>` +help: consider using a semicolon here + | +LL | foo(4 as usize); + | + +help: try adding a return type + | +LL | fn bar() -> S<usize> { + | +++++++++++ error: aborting due to previous error diff --git a/src/test/ui/slightly-nice-generic-literal-messages.stderr b/src/test/ui/slightly-nice-generic-literal-messages.stderr index 61eabed9504..14f01f0ebdf 100644 --- a/src/test/ui/slightly-nice-generic-literal-messages.stderr +++ b/src/test/ui/slightly-nice-generic-literal-messages.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/slightly-nice-generic-literal-messages.rs:7:9 | +LL | match Foo(1.1, marker::PhantomData) { + | ----------------------------- this expression has type `Foo<{float}, _>` LL | 1 => {} | ^ expected struct `Foo`, found integer | diff --git a/src/test/ui/structs/struct-record-suggestion.fixed b/src/test/ui/structs/struct-record-suggestion.fixed new file mode 100644 index 00000000000..48144cd1ce2 --- /dev/null +++ b/src/test/ui/structs/struct-record-suggestion.fixed @@ -0,0 +1,16 @@ +// run-rustfix +#[derive(Debug, Default, Eq, PartialEq)] +struct A { + b: u32, + c: u64, + d: usize, +} + +fn main() { + let q = A { c: 5, .. Default::default() }; + //~^ ERROR mismatched types + //~| ERROR missing fields + //~| HELP separate the last named field with a comma + let r = A { c: 5, .. Default::default() }; + assert_eq!(q, r); +} diff --git a/src/test/ui/structs/struct-record-suggestion.rs b/src/test/ui/structs/struct-record-suggestion.rs new file mode 100644 index 00000000000..6d169d5c6db --- /dev/null +++ b/src/test/ui/structs/struct-record-suggestion.rs @@ -0,0 +1,16 @@ +// run-rustfix +#[derive(Debug, Default, Eq, PartialEq)] +struct A { + b: u32, + c: u64, + d: usize, +} + +fn main() { + let q = A { c: 5 .. Default::default() }; + //~^ ERROR mismatched types + //~| ERROR missing fields + //~| HELP separate the last named field with a comma + let r = A { c: 5, .. Default::default() }; + assert_eq!(q, r); +} diff --git a/src/test/ui/structs/struct-record-suggestion.stderr b/src/test/ui/structs/struct-record-suggestion.stderr new file mode 100644 index 00000000000..e5bd03117b9 --- /dev/null +++ b/src/test/ui/structs/struct-record-suggestion.stderr @@ -0,0 +1,24 @@ +error[E0308]: mismatched types + --> $DIR/struct-record-suggestion.rs:10:20 + | +LL | let q = A { c: 5 .. Default::default() }; + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found struct `std::ops::Range` + | + = note: expected type `u64` + found struct `std::ops::Range<{integer}>` + +error[E0063]: missing fields `b` and `d` in initializer of `A` + --> $DIR/struct-record-suggestion.rs:10:13 + | +LL | let q = A { c: 5 .. Default::default() }; + | ^ missing `b` and `d` + | +help: to set the remaining fields from `Default::default()`, separate the last named field with a comma + | +LL | let q = A { c: 5, .. Default::default() }; + | + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0063, E0308. +For more information about an error, try `rustc --explain E0063`. diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.stderr b/src/test/ui/structs/structure-constructor-type-mismatch.stderr index 98972a12159..3d64fc601df 100644 --- a/src/test/ui/structs/structure-constructor-type-mismatch.stderr +++ b/src/test/ui/structs/structure-constructor-type-mismatch.stderr @@ -101,6 +101,8 @@ LL | type PointF = Point<f32>; error[E0308]: mismatched types --> $DIR/structure-constructor-type-mismatch.rs:54:9 | +LL | match (Point { x: 1, y: 2 }) { + | ---------------------- this expression has type `Point<{integer}>` LL | PointF::<u32> { .. } => {} | ^^^^^^^^^^^^^^^^^^^^ expected integer, found `f32` | @@ -110,6 +112,8 @@ LL | PointF::<u32> { .. } => {} error[E0308]: mismatched types --> $DIR/structure-constructor-type-mismatch.rs:59:9 | +LL | match (Point { x: 1, y: 2 }) { + | ---------------------- this expression has type `Point<{integer}>` LL | PointF { .. } => {} | ^^^^^^^^^^^^^ expected integer, found `f32` | @@ -119,6 +123,8 @@ LL | PointF { .. } => {} error[E0308]: mismatched types --> $DIR/structure-constructor-type-mismatch.rs:67:9 | +LL | match (Pair { x: 1, y: 2 }) { + | --------------------- this expression has type `Pair<{integer}, {integer}>` LL | PairF::<u32> { .. } => {} | ^^^^^^^^^^^^^^^^^^^ expected integer, found `f32` | diff --git a/src/test/ui/typeck/issue-91334.stderr b/src/test/ui/typeck/issue-91334.stderr index 0872e83ea2e..633c7b11aa2 100644 --- a/src/test/ui/typeck/issue-91334.stderr +++ b/src/test/ui/typeck/issue-91334.stderr @@ -40,7 +40,7 @@ error[E0308]: mismatched types LL | fn f(){||yield(((){), | -^^^^^^^^^^^^^^^ expected `()`, found generator | | - | possibly return type missing here? + | help: a return type might be missing here: `-> _` | = note: expected unit type `()` found generator `[generator@$DIR/issue-91334.rs:10:8: 10:23]` diff --git a/src/test/ui/typeck/return_type_containing_closure.rs b/src/test/ui/typeck/return_type_containing_closure.rs index aee9769b280..29624e08a2e 100644 --- a/src/test/ui/typeck/return_type_containing_closure.rs +++ b/src/test/ui/typeck/return_type_containing_closure.rs @@ -1,10 +1,10 @@ #[allow(unused)] -fn foo() { - //~^ NOTE possibly return type missing here? +fn foo() { //~ HELP a return type might be missing here vec!['a'].iter().map(|c| c) //~^ ERROR mismatched types [E0308] //~| NOTE expected `()`, found struct `Map` //~| NOTE expected unit type `()` + //~| HELP consider using a semicolon here } fn main() {} diff --git a/src/test/ui/typeck/return_type_containing_closure.stderr b/src/test/ui/typeck/return_type_containing_closure.stderr index b08152d6331..ae72b1477c8 100644 --- a/src/test/ui/typeck/return_type_containing_closure.stderr +++ b/src/test/ui/typeck/return_type_containing_closure.stderr @@ -1,16 +1,19 @@ error[E0308]: mismatched types - --> $DIR/return_type_containing_closure.rs:4:5 + --> $DIR/return_type_containing_closure.rs:3:5 | -LL | fn foo() { - | - possibly return type missing here? -LL | LL | vec!['a'].iter().map(|c| c) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;` - | | - | expected `()`, found struct `Map` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Map` | = note: expected unit type `()` - found struct `Map<std::slice::Iter<'_, char>, [closure@$DIR/return_type_containing_closure.rs:4:26: 4:31]>` + found struct `Map<std::slice::Iter<'_, char>, [closure@$DIR/return_type_containing_closure.rs:3:26: 3:31]>` +help: consider using a semicolon here + | +LL | vec!['a'].iter().map(|c| c); + | + +help: a return type might be missing here + | +LL | fn foo() -> _ { + | ++++ error: aborting due to previous error diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs index 5c33925a9ec..908cfc15c0d 100644 --- a/src/tools/cargotest/main.rs +++ b/src/tools/cargotest/main.rs @@ -26,7 +26,7 @@ const TEST_REPOS: &[Test] = &[ Test { name: "ripgrep", repo: "https://github.com/BurntSushi/ripgrep", - sha: "3de31f752729525d85a3d1575ac1978733b3f7e7", + sha: "ced5b92aa93eb47e892bd2fd26ab454008721730", lock: None, packages: &[], features: None, diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 8f8f1140a3d..855a6a6ef6a 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -178,8 +178,8 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { // a .span_bug or .bug call has already printed what // it wants to print. if !info.payload().is::<rustc_errors::ExplicitBug>() { - let d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic"); - handler.emit_diagnostic(&d); + let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic"); + handler.emit_diagnostic(&mut d); } let version_info = rustc_tools_util::get_version_info!(); diff --git a/src/tools/clippy/tests/ui/bytes_nth.fixed b/src/tools/clippy/tests/ui/bytes_nth.fixed index 46b7833f428..b1fb2e16bd5 100644 --- a/src/tools/clippy/tests/ui/bytes_nth.fixed +++ b/src/tools/clippy/tests/ui/bytes_nth.fixed @@ -5,7 +5,7 @@ fn main() { let s = String::from("String"); - s.as_bytes().get(3); + let _ = s.as_bytes().get(3); let _ = &s.as_bytes().get(3); - s[..].as_bytes().get(3); + let _ = s[..].as_bytes().get(3); } diff --git a/src/tools/clippy/tests/ui/bytes_nth.rs b/src/tools/clippy/tests/ui/bytes_nth.rs index c5e983d4d4e..034c54e6a42 100644 --- a/src/tools/clippy/tests/ui/bytes_nth.rs +++ b/src/tools/clippy/tests/ui/bytes_nth.rs @@ -5,7 +5,7 @@ fn main() { let s = String::from("String"); - s.bytes().nth(3); + let _ = s.bytes().nth(3); let _ = &s.bytes().nth(3); - s[..].bytes().nth(3); + let _ = s[..].bytes().nth(3); } diff --git a/src/tools/clippy/tests/ui/bytes_nth.stderr b/src/tools/clippy/tests/ui/bytes_nth.stderr index 536decf5e7f..8a7afa93450 100644 --- a/src/tools/clippy/tests/ui/bytes_nth.stderr +++ b/src/tools/clippy/tests/ui/bytes_nth.stderr @@ -1,8 +1,8 @@ error: called `.byte().nth()` on a `String` - --> $DIR/bytes_nth.rs:8:5 + --> $DIR/bytes_nth.rs:8:13 | -LL | s.bytes().nth(3); - | ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)` +LL | let _ = s.bytes().nth(3); + | ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)` | = note: `-D clippy::bytes-nth` implied by `-D warnings` @@ -13,10 +13,10 @@ LL | let _ = &s.bytes().nth(3); | ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)` error: called `.byte().nth()` on a `str` - --> $DIR/bytes_nth.rs:10:5 + --> $DIR/bytes_nth.rs:10:13 | -LL | s[..].bytes().nth(3); - | ^^^^^^^^^^^^^^^^^^^^ help: try: `s[..].as_bytes().get(3)` +LL | let _ = s[..].bytes().nth(3); + | ^^^^^^^^^^^^^^^^^^^^ help: try: `s[..].as_bytes().get(3)` error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/iter_next_slice.fixed b/src/tools/clippy/tests/ui/iter_next_slice.fixed index 79c1db87ac3..11ffc8edb14 100644 --- a/src/tools/clippy/tests/ui/iter_next_slice.fixed +++ b/src/tools/clippy/tests/ui/iter_next_slice.fixed @@ -6,16 +6,16 @@ fn main() { let s = [1, 2, 3]; let v = vec![1, 2, 3]; - s.get(0); + let _ = s.get(0); // Should be replaced by s.get(0) - s.get(2); + let _ = s.get(2); // Should be replaced by s.get(2) - v.get(5); + let _ = v.get(5); // Should be replaced by v.get(5) - v.get(0); + let _ = v.get(0); // Should be replaced by v.get(0) let o = Some(5); diff --git a/src/tools/clippy/tests/ui/iter_next_slice.rs b/src/tools/clippy/tests/ui/iter_next_slice.rs index ef9a55f3d99..e0d3aabd54a 100644 --- a/src/tools/clippy/tests/ui/iter_next_slice.rs +++ b/src/tools/clippy/tests/ui/iter_next_slice.rs @@ -6,16 +6,16 @@ fn main() { let s = [1, 2, 3]; let v = vec![1, 2, 3]; - s.iter().next(); + let _ = s.iter().next(); // Should be replaced by s.get(0) - s[2..].iter().next(); + let _ = s[2..].iter().next(); // Should be replaced by s.get(2) - v[5..].iter().next(); + let _ = v[5..].iter().next(); // Should be replaced by v.get(5) - v.iter().next(); + let _ = v.iter().next(); // Should be replaced by v.get(0) let o = Some(5); diff --git a/src/tools/clippy/tests/ui/iter_next_slice.stderr b/src/tools/clippy/tests/ui/iter_next_slice.stderr index 8c10a252ee0..a78d2c2d5e8 100644 --- a/src/tools/clippy/tests/ui/iter_next_slice.stderr +++ b/src/tools/clippy/tests/ui/iter_next_slice.stderr @@ -1,28 +1,28 @@ error: using `.iter().next()` on an array - --> $DIR/iter_next_slice.rs:9:5 + --> $DIR/iter_next_slice.rs:9:13 | -LL | s.iter().next(); - | ^^^^^^^^^^^^^^^ help: try calling: `s.get(0)` +LL | let _ = s.iter().next(); + | ^^^^^^^^^^^^^^^ help: try calling: `s.get(0)` | = note: `-D clippy::iter-next-slice` implied by `-D warnings` error: using `.iter().next()` on a Slice without end index - --> $DIR/iter_next_slice.rs:12:5 + --> $DIR/iter_next_slice.rs:12:13 | -LL | s[2..].iter().next(); - | ^^^^^^^^^^^^^^^^^^^^ help: try calling: `s.get(2)` +LL | let _ = s[2..].iter().next(); + | ^^^^^^^^^^^^^^^^^^^^ help: try calling: `s.get(2)` error: using `.iter().next()` on a Slice without end index - --> $DIR/iter_next_slice.rs:15:5 + --> $DIR/iter_next_slice.rs:15:13 | -LL | v[5..].iter().next(); - | ^^^^^^^^^^^^^^^^^^^^ help: try calling: `v.get(5)` +LL | let _ = v[5..].iter().next(); + | ^^^^^^^^^^^^^^^^^^^^ help: try calling: `v.get(5)` error: using `.iter().next()` on an array - --> $DIR/iter_next_slice.rs:18:5 + --> $DIR/iter_next_slice.rs:18:13 | -LL | v.iter().next(); - | ^^^^^^^^^^^^^^^ help: try calling: `v.get(0)` +LL | let _ = v.iter().next(); + | ^^^^^^^^^^^^^^^ help: try calling: `v.get(0)` error: aborting due to 4 previous errors diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index a34ceed3fc9..412f4434b9e 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -225,8 +225,10 @@ impl ParseSess { // Methods that should be restricted within the parse module. impl ParseSess { pub(super) fn emit_diagnostics(&self, diagnostics: Vec<Diagnostic>) { - for diagnostic in diagnostics { - self.parse_sess.span_diagnostic.emit_diagnostic(&diagnostic); + for mut diagnostic in diagnostics { + self.parse_sess + .span_diagnostic + .emit_diagnostic(&mut diagnostic); } } |
