diff options
250 files changed, 3205 insertions, 1862 deletions
diff --git a/compiler/rustc_ast/src/ast_like.rs b/compiler/rustc_ast/src/ast_like.rs index 9a24158ba35..1a271b0adef 100644 --- a/compiler/rustc_ast/src/ast_like.rs +++ b/compiler/rustc_ast/src/ast_like.rs @@ -51,7 +51,6 @@ impl AstLike for crate::token::Nonterminal { | Nonterminal::NtMeta(_) | Nonterminal::NtPath(_) | Nonterminal::NtVis(_) - | Nonterminal::NtTT(_) | Nonterminal::NtBlock(_) | Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(_) => &[], @@ -67,7 +66,6 @@ impl AstLike for crate::token::Nonterminal { | Nonterminal::NtMeta(_) | Nonterminal::NtPath(_) | Nonterminal::NtVis(_) - | Nonterminal::NtTT(_) | Nonterminal::NtBlock(_) | Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(_) => {} @@ -84,7 +82,7 @@ impl AstLike for crate::token::Nonterminal { Nonterminal::NtPath(path) => path.tokens_mut(), Nonterminal::NtVis(vis) => vis.tokens_mut(), Nonterminal::NtBlock(block) => block.tokens_mut(), - Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) | Nonterminal::NtTT(..) => None, + Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) => None, } } } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 9d79fe53d5c..32621eb5f2f 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -787,7 +787,6 @@ pub fn visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut visit_lazy_tts(tokens, vis); } token::NtPath(path) => vis.visit_path(path), - token::NtTT(tt) => visit_tt(tt, vis), token::NtVis(visib) => vis.visit_vis(visib), } } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index c367573de8a..7df385873c1 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -6,7 +6,6 @@ pub use TokenKind::*; use crate::ast; use crate::ptr::P; -use crate::tokenstream::TokenTree; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; @@ -680,7 +679,6 @@ pub enum Nonterminal { NtMeta(P<ast::AttrItem>), NtPath(ast::Path), NtVis(ast::Visibility), - NtTT(TokenTree), } // `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger. @@ -778,7 +776,6 @@ impl Nonterminal { NtMeta(attr_item) => attr_item.span(), NtPath(path) => path.span, NtVis(vis) => vis.span, - NtTT(tt) => tt.span(), } } } @@ -790,7 +787,6 @@ impl PartialEq for Nonterminal { ident_lhs == ident_rhs && is_raw_lhs == is_raw_rhs } (NtLifetime(ident_lhs), NtLifetime(ident_rhs)) => ident_lhs == ident_rhs, - (NtTT(tt_lhs), NtTT(tt_rhs)) => tt_lhs == tt_rhs, // FIXME: Assume that all "complex" nonterminal are not equal, we can't compare them // correctly based on data from AST. This will prevent them from matching each other // in macros. The comparison will become possible only when each nonterminal has an @@ -813,7 +809,6 @@ impl fmt::Debug for Nonterminal { NtLiteral(..) => f.pad("NtLiteral(..)"), NtMeta(..) => f.pad("NtMeta(..)"), NtPath(..) => f.pad("NtPath(..)"), - NtTT(..) => f.pad("NtTT(..)"), NtVis(..) => f.pad("NtVis(..)"), NtLifetime(..) => f.pad("NtLifetime(..)"), } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 8ba6a914c4a..aba0b6a7463 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -122,7 +122,10 @@ impl<'a> AstValidator<'a> { diag.note("only supported directly in conditions of `if` and `while` expressions"); diag.note("as well as when nested within `&&` and parentheses in those conditions"); if let ForbiddenLetReason::ForbiddenWithOr(span) = forbidden_let_reason { - diag.span_note(span, "`||` operators are not allowed in let chain expressions"); + diag.span_note( + span, + "`||` operators are not currently supported in let chain expressions", + ); } diag.emit(); } else { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index b2c62383fb6..719fd271093 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -714,7 +714,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(e, is_raw).to_string(), token::NtLifetime(e) => e.to_string(), token::NtLiteral(ref e) => self.expr_to_string(e), - token::NtTT(ref tree) => self.tt_to_string(tree), token::NtVis(ref e) => self.vis_to_string(e), } } 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_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index 39f53235e2c..76caa3ceaaf 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -23,25 +23,26 @@ pub fn compute_mir_scopes<'ll, 'tcx>( fn_dbg_scope: &'ll DIScope, debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>, ) { - // Find all the scopes with variables defined in them. - let mut has_variables = BitSet::new_empty(mir.source_scopes.len()); - - // Only consider variables when they're going to be emitted. - // FIXME(eddyb) don't even allocate `has_variables` otherwise. - if cx.sess().opts.debuginfo == DebugInfo::Full { + // Find all scopes with variables defined in them. + let variables = if cx.sess().opts.debuginfo == DebugInfo::Full { + let mut vars = BitSet::new_empty(mir.source_scopes.len()); // FIXME(eddyb) take into account that arguments always have debuginfo, // irrespective of their name (assuming full debuginfo is enabled). // NOTE(eddyb) actually, on second thought, those are always in the // function scope, which always exists. for var_debug_info in &mir.var_debug_info { - has_variables.insert(var_debug_info.source_info.scope); + vars.insert(var_debug_info.source_info.scope); } - } + Some(vars) + } else { + // Nothing to emit, of course. + None + }; // Instantiate all scopes. for idx in 0..mir.source_scopes.len() { let scope = SourceScope::new(idx); - make_mir_scope(cx, instance, mir, fn_dbg_scope, &has_variables, debug_context, scope); + make_mir_scope(cx, instance, mir, fn_dbg_scope, &variables, debug_context, scope); } } @@ -50,7 +51,7 @@ fn make_mir_scope<'ll, 'tcx>( instance: Instance<'tcx>, mir: &Body<'tcx>, fn_dbg_scope: &'ll DIScope, - has_variables: &BitSet<SourceScope>, + variables: &Option<BitSet<SourceScope>>, debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>, scope: SourceScope, ) { @@ -60,7 +61,7 @@ fn make_mir_scope<'ll, 'tcx>( let scope_data = &mir.source_scopes[scope]; let parent_scope = if let Some(parent) = scope_data.parent_scope { - make_mir_scope(cx, instance, mir, fn_dbg_scope, has_variables, debug_context, parent); + make_mir_scope(cx, instance, mir, fn_dbg_scope, variables, debug_context, parent); debug_context.scopes[parent] } else { // The root is the function itself. @@ -74,7 +75,7 @@ fn make_mir_scope<'ll, 'tcx>( return; }; - if !has_variables.contains(scope) && scope_data.inlined.is_none() { + if let Some(vars) = variables && !vars.contains(scope) && scope_data.inlined.is_none() { // Do not create a DIScope if there are no variables defined in this // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat. debug_context.scopes[scope] = parent_scope; diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 875b4f033d1..3152c505af0 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -7,6 +7,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] +#![feature(let_chains)] #![feature(let_else)] #![feature(extern_types)] #![feature(once_cell)] 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_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/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 088f6091528..853243ef3f0 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -198,6 +198,45 @@ impl EmissionGuarantee for () { } } +impl<'a> DiagnosticBuilder<'a, !> { + /// Convenience function for internal use, clients should use one of the + /// `struct_*` methods on [`Handler`]. + crate fn new_fatal(handler: &'a Handler, message: &str) -> Self { + let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message); + Self::new_diagnostic_fatal(handler, diagnostic) + } + + /// Creates a new `DiagnosticBuilder` with an already constructed + /// diagnostic. + crate fn new_diagnostic_fatal(handler: &'a Handler, diagnostic: Diagnostic) -> Self { + debug!("Created new diagnostic"); + Self { + inner: DiagnosticBuilderInner { + state: DiagnosticBuilderState::Emittable(handler), + diagnostic: Box::new(diagnostic), + }, + _marker: PhantomData, + } + } +} + +impl EmissionGuarantee for ! { + fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { + match db.inner.state { + // First `.emit()` call, the `&Handler` is still available. + DiagnosticBuilderState::Emittable(handler) => { + db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + + handler.emit_diagnostic(&mut db.inner.diagnostic); + } + // `.emit()` was previously called, disallowed from repeating it. + DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} + } + // Then fatally error, returning `!` + crate::FatalError.raise() + } +} + /// In general, the `DiagnosticBuilder` uses deref to allow access to /// the fields and methods of the embedded `diagnostic` in a /// transparent way. *However,* many of the methods are intended to diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 2f2f6ed1a5a..ec00910ec8b 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -8,6 +8,7 @@ #![feature(backtrace)] #![feature(if_let_guard)] #![feature(let_else)] +#![feature(never_type)] #![feature(nll)] #![feature(adt_const_params)] #![allow(incomplete_features)] @@ -758,7 +759,7 @@ impl Handler { &self, span: impl Into<MultiSpan>, msg: &str, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_, !> { let mut result = self.struct_fatal(msg); result.set_span(span); result @@ -770,15 +771,15 @@ impl Handler { span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_, !> { let mut result = self.struct_span_fatal(span, msg); result.code(code); result } /// Construct a builder at the `Error` level with the `msg`. - pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - DiagnosticBuilder::new_guaranteeing_error::<{ Level::Fatal }>(self, msg) + pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, !> { + DiagnosticBuilder::new_fatal(self, msg) } /// Construct a builder at the `Help` level with the `msg`. 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/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 5e97fc90320..5a6a2b2c57b 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -76,7 +76,7 @@ crate use ParseResult::*; use crate::mbe::{self, SequenceRepetition, TokenTree}; use rustc_ast::token::{self, DocComment, Nonterminal, Token}; -use rustc_parse::parser::Parser; +use rustc_parse::parser::{NtOrTt, Parser}; use rustc_session::parse::ParseSess; use rustc_span::symbol::MacroRulesNormalizedIdent; @@ -275,7 +275,7 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize { } /// `NamedMatch` is a pattern-match result for a single metavar. All -/// `MatchedNtNonTt`s in the `NamedMatch` have the same non-terminal type +/// `MatchedNonterminal`s in the `NamedMatch` have the same non-terminal type /// (expr, item, etc). /// /// The in-memory structure of a particular `NamedMatch` represents the match @@ -306,17 +306,17 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize { /// ```rust /// MatchedSeq([ /// MatchedSeq([ -/// MatchedNtNonTt(a), -/// MatchedNtNonTt(b), -/// MatchedNtNonTt(c), -/// MatchedNtNonTt(d), +/// MatchedNonterminal(a), +/// MatchedNonterminal(b), +/// MatchedNonterminal(c), +/// MatchedNonterminal(d), /// ]), /// MatchedSeq([ -/// MatchedNtNonTt(a), -/// MatchedNtNonTt(b), -/// MatchedNtNonTt(c), -/// MatchedNtNonTt(d), -/// MatchedNtNonTt(e), +/// MatchedNonterminal(a), +/// MatchedNonterminal(b), +/// MatchedNonterminal(c), +/// MatchedNonterminal(d), +/// MatchedNonterminal(e), /// ]) /// ]) /// ``` @@ -324,14 +324,11 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize { crate enum NamedMatch { MatchedSeq(Lrc<NamedMatchVec>), - // This variant should never hold an `NtTT`. `MatchedNtTt` should be used - // for that case. - MatchedNtNonTt(Lrc<Nonterminal>), + // A metavar match of type `tt`. + MatchedTokenTree(rustc_ast::tokenstream::TokenTree), - // `NtTT` is handled without any cloning when transcribing, unlike other - // nonterminals. Therefore, an `Lrc` isn't helpful and causes unnecessary - // allocations. Hence this separate variant. - MatchedNtTt(rustc_ast::tokenstream::TokenTree), + // A metavar match of any type other than `tt`. + MatchedNonterminal(Lrc<Nonterminal>), } /// Takes a slice of token trees `ms` representing a matcher which successfully matched input @@ -519,13 +516,14 @@ impl<'tt> TtParser<'tt> { } TokenTree::Token(t) => { - // Doc comments cannot appear in a matcher. - debug_assert!(!matches!(t, Token { kind: DocComment(..), .. })); - - // If the token matches, we can just advance the parser. Otherwise, this - // match hash failed, there is nothing to do, and hopefully another item in - // `cur_items` will match. - if token_name_eq(&t, token) { + // If it's a doc comment, we just ignore it and move on to the next tt in + // the matcher. If the token matches, we can just advance the parser. + // Otherwise, this match has failed, there is nothing to do, and hopefully + // another item in `cur_items` will match. + if matches!(t, Token { kind: DocComment(..), .. }) { + item.idx += 1; + self.cur_items.push(item); + } else if token_name_eq(&t, token) { item.idx += 1; self.next_items.push(item); } @@ -677,8 +675,8 @@ impl<'tt> TtParser<'tt> { Ok(nt) => nt, }; let m = match nt { - Nonterminal::NtTT(tt) => MatchedNtTt(tt), - _ => MatchedNtNonTt(Lrc::new(nt)), + NtOrTt::Nt(nt) => MatchedNonterminal(Lrc::new(nt)), + NtOrTt::Tt(tt) => MatchedTokenTree(tt), }; item.push_match(match_cur, m); item.idx += 1; diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 7837de5c18d..10b2b9f07e2 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -4,7 +4,7 @@ use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstF use crate::mbe; use crate::mbe::macro_check; use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success, TtParser}; -use crate::mbe::macro_parser::{MatchedNtTt, MatchedSeq}; +use crate::mbe::macro_parser::{MatchedSeq, MatchedTokenTree}; use crate::mbe::transcribe::transcribe; use rustc_ast as ast; @@ -470,7 +470,7 @@ pub fn compile_declarative_macro( MatchedSeq(ref s) => s .iter() .map(|m| { - if let MatchedNtTt(ref tt) = *m { + if let MatchedTokenTree(ref tt) = *m { let mut tts = vec![]; mbe::quoted::parse( tt.clone().into(), @@ -495,7 +495,7 @@ pub fn compile_declarative_macro( MatchedSeq(ref s) => s .iter() .map(|m| { - if let MatchedNtTt(ref tt) = *m { + if let MatchedTokenTree(ref tt) = *m { let mut tts = vec![]; mbe::quoted::parse( tt.clone().into(), diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 228ed04548d..cd016bfd8f4 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -1,8 +1,8 @@ use crate::base::ExtCtxt; -use crate::mbe::macro_parser::{MatchedNtNonTt, MatchedNtTt, MatchedSeq, NamedMatch}; +use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, MatchedTokenTree, NamedMatch}; use crate::mbe::{self, MetaVarExpr}; use rustc_ast::mut_visit::{self, MutVisitor}; -use rustc_ast::token::{self, Nonterminal, Token, TokenKind}; +use rustc_ast::token::{self, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndSpacing}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; @@ -234,17 +234,16 @@ pub(super) fn transcribe<'a>( let ident = MacroRulesNormalizedIdent::new(orignal_ident); if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { match cur_matched { - MatchedNtTt(ref tt) => { + MatchedTokenTree(ref tt) => { // `tt`s are emitted into the output stream directly as "raw tokens", // without wrapping them into groups. let token = tt.clone(); result.push(token.into()); } - MatchedNtNonTt(ref nt) => { + MatchedNonterminal(ref nt) => { // Other variables are emitted into the output stream as groups with // `Delimiter::None` to maintain parsing priorities. // `Interpolated` is currently used for such groups in rustc parser. - debug_assert!(!matches!(**nt, Nonterminal::NtTT(_))); marker.visit_span(&mut sp); let token = TokenTree::token(token::Interpolated(nt.clone()), sp); result.push(token.into()); @@ -312,7 +311,7 @@ fn lookup_cur_matched<'a>( let mut matched = matched; for &(idx, _) in repeats { match matched { - MatchedNtTt(_) | MatchedNtNonTt(_) => break, + MatchedTokenTree(_) | MatchedNonterminal(_) => break, MatchedSeq(ref ads) => matched = ads.get(idx).unwrap(), } } @@ -402,7 +401,7 @@ fn lockstep_iter_size( let name = MacroRulesNormalizedIdent::new(name); match lookup_cur_matched(name, interpolations, repeats) { Some(matched) => match matched { - MatchedNtTt(_) | MatchedNtNonTt(_) => LockstepIterSize::Unconstrained, + MatchedTokenTree(_) | MatchedNonterminal(_) => LockstepIterSize::Unconstrained, MatchedSeq(ref ads) => LockstepIterSize::Constraint(ads.len(), name), }, _ => LockstepIterSize::Unconstrained, @@ -449,7 +448,7 @@ fn count_repetitions<'a>( sp: &DelimSpan, ) -> PResult<'a, usize> { match matched { - MatchedNtTt(_) | MatchedNtNonTt(_) => { + MatchedTokenTree(_) | MatchedNonterminal(_) => { if declared_lhs_depth == 0 { return Err(cx.struct_span_err( sp.entire(), diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 5bd4bee3adf..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); @@ -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_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/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_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 93ece753728..dc16460ca43 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -999,6 +999,15 @@ impl<'tcx> PolyTraitRef<'tcx> { polarity: ty::ImplPolarity::Positive, }) } + + /// Same as [`PolyTraitRef::to_poly_trait_predicate`] but sets a negative polarity instead. + pub fn to_poly_trait_predicate_negative_polarity(&self) -> ty::PolyTraitPredicate<'tcx> { + self.map_bound(|trait_ref| ty::TraitPredicate { + trait_ref, + constness: ty::BoundConstness::NotConst, + polarity: ty::ImplPolarity::Negative, + }) + } } /// An existential reference to a trait, where `Self` is erased. 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_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index a9dcc484b9e..1477bc28cff 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -180,7 +180,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator}; -use rustc_errors::FatalError; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; @@ -560,8 +559,7 @@ fn check_recursion_limit<'tcx>( if let Some(path) = written_to_path { err.note(&format!("the full type name has been written to '{}'", path.display())); } - err.emit(); - FatalError.raise(); + err.emit() } recursion_depths.insert(def_id, recursion_depth + 1); @@ -598,8 +596,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { "consider adding a `#![type_length_limit=\"{}\"]` attribute to your crate", type_length )); - diag.emit(); - tcx.sess.abort_if_errors(); + diag.emit() } } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 601a39e69ab..92c5d329f6e 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -3,9 +3,7 @@ use rustc_ast::ast::{self, AttrStyle}; use rustc_ast::token::{self, CommentKind, Token, TokenKind}; use rustc_ast::tokenstream::{Spacing, TokenStream}; use rustc_ast::util::unicode::contains_text_flow_control_chars; -use rustc_errors::{ - error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, PResult, -}; +use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult}; use rustc_lexer::unescape::{self, Mode}; use rustc_lexer::{Base, DocStyle, RawStrError}; use rustc_session::lint::builtin::{ @@ -104,7 +102,7 @@ impl<'a> StringReader<'a> { } /// Report a fatal lexical error with a given span. - fn fatal_span(&self, sp: Span, m: &str) -> FatalError { + fn fatal_span(&self, sp: Span, m: &str) -> ! { self.sess.span_diagnostic.span_fatal(sp, m) } @@ -114,7 +112,7 @@ impl<'a> StringReader<'a> { } /// Report a fatal error spanning [`from_pos`, `to_pos`). - fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> FatalError { + fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> ! { self.fatal_span(self.mk_sp(from_pos, to_pos), m) } @@ -129,12 +127,24 @@ impl<'a> StringReader<'a> { to_pos: BytePos, m: &str, c: char, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'a, !> { self.sess .span_diagnostic .struct_span_fatal(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c))) } + fn struct_err_span_char( + &self, + from_pos: BytePos, + to_pos: BytePos, + m: &str, + c: char, + ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + self.sess + .span_diagnostic + .struct_span_err(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c))) + } + /// Detect usages of Unicode codepoints changing the direction of the text on screen and loudly /// complain about it. fn lint_unicode_text_flow(&self, start: BytePos) { @@ -311,7 +321,7 @@ impl<'a> StringReader<'a> { rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => { let c = self.str_from(start).chars().next().unwrap(); let mut err = - self.struct_fatal_span_char(start, self.pos, "unknown start of token", c); + self.struct_err_span_char(start, self.pos, "unknown start of token", c); // FIXME: the lexer could be used to turn the ASCII version of unicode homoglyphs, // instead of keeping a table in `check_for_substitution`into the token. Ideally, // this should be inside `rustc_lexer`. However, we should first remove compound @@ -503,8 +513,7 @@ impl<'a> StringReader<'a> { "found invalid character; only `#` is allowed in raw string delimitation", bad_char, ) - .emit(); - FatalError.raise() + .emit() } fn report_unterminated_raw_string( @@ -541,8 +550,7 @@ impl<'a> StringReader<'a> { ); } - err.emit(); - FatalError.raise() + err.emit() } // RFC 3101 introduced the idea of (reserved) prefixes. As of Rust 2021, @@ -601,7 +609,6 @@ impl<'a> StringReader<'a> { found ), ) - .raise(); } fn validate_literal_escape( diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 0ce86a764f4..28c2a63db27 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -6,6 +6,7 @@ #![feature(if_let_guard)] #![feature(let_chains)] #![feature(let_else)] +#![feature(never_type)] #![recursion_limit = "256"] #[macro_use] @@ -289,7 +290,6 @@ pub fn nt_to_tokenstream( Nonterminal::NtMeta(ref attr) => convert_tokens(attr.tokens.as_ref()), Nonterminal::NtPath(ref path) => convert_tokens(path.tokens.as_ref()), Nonterminal::NtVis(ref vis) => convert_tokens(vis.tokens.as_ref()), - Nonterminal::NtTT(ref tt) => Some(tt.clone().into()), Nonterminal::NtExpr(ref expr) | Nonterminal::NtLiteral(ref expr) => { prepend_attrs(&expr.attrs, expr.tokens.as_ref()) } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 3a2f193d319..5d244ef9118 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -19,7 +19,7 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma}; pub use path::PathStyle; use rustc_ast::ptr::P; -use rustc_ast::token::{self, DelimToken, Token, TokenKind}; +use rustc_ast::token::{self, DelimToken, Nonterminal, Token, TokenKind}; use rustc_ast::tokenstream::AttributesData; use rustc_ast::tokenstream::{self, DelimSpan, Spacing}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; @@ -1507,3 +1507,9 @@ pub enum FlatToken { /// handling of replace ranges. Empty, } + +#[derive(Debug)] +pub enum NtOrTt { + Nt(Nonterminal), + Tt(TokenTree), +} diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 40902fa1833..c105fbfaee0 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -1,12 +1,12 @@ use rustc_ast::ptr::P; -use rustc_ast::token::{self, Nonterminal, NonterminalKind, Token}; +use rustc_ast::token::{self, NonterminalKind, Token}; use rustc_ast::AstLike; use rustc_ast_pretty::pprust; use rustc_errors::PResult; use rustc_span::symbol::{kw, Ident}; use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma}; -use crate::parser::{FollowedByType, ForceCollect, Parser, PathStyle}; +use crate::parser::{FollowedByType, ForceCollect, NtOrTt, Parser, PathStyle}; impl<'a> Parser<'a> { /// Checks whether a non-terminal may begin with a particular token. @@ -85,7 +85,7 @@ impl<'a> Parser<'a> { NonterminalKind::Lifetime => match token.kind { token::Lifetime(_) => true, token::Interpolated(ref nt) => { - matches!(**nt, token::NtLifetime(_) | token::NtTT(_)) + matches!(**nt, token::NtLifetime(_)) } _ => false, }, @@ -96,7 +96,7 @@ impl<'a> Parser<'a> { } /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`). - pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonterminal> { + pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt> { // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`) // needs to have them force-captured here. // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro, @@ -104,6 +104,8 @@ impl<'a> Parser<'a> { // in advance whether or not a proc-macro will be (transitively) invoked, // we always capture tokens for any `Nonterminal` which needs them. let mut nt = match kind { + // Note that TT is treated differently to all the others. + NonterminalKind::TT => return Ok(NtOrTt::Tt(self.parse_token_tree())), NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? { Some(item) => token::NtItem(item), None => { @@ -124,9 +126,12 @@ impl<'a> Parser<'a> { NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => { token::NtPat(self.collect_tokens_no_attrs(|this| match kind { NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None), - NonterminalKind::PatWithOr { .. } => { - this.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No, CommaRecoveryMode::EitherTupleOrPipe) - } + NonterminalKind::PatWithOr { .. } => this.parse_pat_allow_top_alt( + None, + RecoverComma::No, + RecoverColon::No, + CommaRecoveryMode::EitherTupleOrPipe, + ), _ => unreachable!(), })?) } @@ -139,9 +144,10 @@ impl<'a> Parser<'a> { ) } - NonterminalKind::Ty => { - token::NtTy(self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?) - } + NonterminalKind::Ty => token::NtTy( + self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?, + ), + // this could be handled like a token, since it is one NonterminalKind::Ident if let Some((ident, is_raw)) = get_macro_ident(&self.token) => @@ -158,7 +164,6 @@ impl<'a> Parser<'a> { self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?, ), NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)), - NonterminalKind::TT => token::NtTT(self.parse_token_tree()), NonterminalKind::Vis => token::NtVis( self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?, ), @@ -183,7 +188,7 @@ impl<'a> Parser<'a> { ); } - Ok(nt) + Ok(NtOrTt::Nt(nt)) } } 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_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 038ba220608..c8ca51348cc 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -696,14 +696,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { ) = &bounded_ty.kind { // use this to verify that ident is a type param. - let Ok(Some(partial_res)) = self.resolve_qpath_anywhere( - None, - &Segment::from_path(path), - Namespace::TypeNS, - span, - true, - Finalize::No, - ) else { + let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else { return false; }; if !(matches!( @@ -718,16 +711,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { return false; }; - if let ast::TyKind::Path(None, type_param_path) = &ty.peel_refs().kind { + let peeled_ty = ty.peel_refs(); + if let ast::TyKind::Path(None, type_param_path) = &peeled_ty.kind { // Confirm that the `SelfTy` is a type parameter. - let Ok(Some(partial_res)) = self.resolve_qpath_anywhere( - None, - &Segment::from_path(type_param_path), - Namespace::TypeNS, - span, - true, - Finalize::No, - ) else { + let Some(partial_res) = self.r.partial_res_map.get(&peeled_ty.id) else { return false; }; if !(matches!( diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index bd4e37f1ab7..14273b07ebd 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -3,6 +3,7 @@ #![feature(let_chains)] #![feature(let_else)] #![feature(min_specialization)] +#![feature(never_type)] #![feature(once_cell)] #![feature(option_get_or_insert_default)] #![recursion_limit = "256"] diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 4876e2eb851..eed0f1e09ff 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -341,7 +341,7 @@ impl Session { &self, sp: S, msg: &str, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_, !> { self.diagnostic().struct_span_fatal(sp, msg) } pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>( @@ -349,10 +349,10 @@ impl Session { sp: S, msg: &str, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_, !> { self.diagnostic().struct_span_fatal_with_code(sp, msg, code) } - pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, !> { self.diagnostic().struct_fatal(msg) } @@ -1384,7 +1384,7 @@ pub enum IncrCompSession { InvalidBecauseOfErrors { session_directory: PathBuf }, } -pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed { +fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler { let emitter: Box<dyn Emitter + sync::Send> = match output { config::ErrorOutputType::HumanReadable(kind) => { let (short, color_config) = kind.unzip(); @@ -1394,26 +1394,17 @@ pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> Error Box::new(JsonEmitter::basic(pretty, json_rendered, None, false)) } }; - let handler = rustc_errors::Handler::with_emitter(true, None, emitter); - let reported = handler.struct_fatal(msg).emit(); - reported + rustc_errors::Handler::with_emitter(true, None, emitter) +} + +pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed { + early_error_handler(output).struct_err(msg).emit() } pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { - early_error_no_abort(output, msg); - rustc_errors::FatalError.raise(); + early_error_handler(output).struct_fatal(msg).emit() } pub fn early_warn(output: config::ErrorOutputType, msg: &str) { - let emitter: Box<dyn Emitter + sync::Send> = match output { - config::ErrorOutputType::HumanReadable(kind) => { - let (short, color_config) = kind.unzip(); - Box::new(EmitterWriter::stderr(color_config, None, short, false, None, false)) - } - config::ErrorOutputType::Json { pretty, json_rendered } => { - Box::new(JsonEmitter::basic(pretty, json_rendered, None, false)) - } - }; - let handler = rustc_errors::Handler::with_emitter(true, None, emitter); - handler.struct_warn(msg).emit(); + early_error_handler(output).struct_warn(msg).emit() } diff --git a/compiler/rustc_span/src/fatal_error.rs b/compiler/rustc_span/src/fatal_error.rs index 718c0ddbc63..fa84c486df5 100644 --- a/compiler/rustc_span/src/fatal_error.rs +++ b/compiler/rustc_span/src/fatal_error.rs @@ -19,7 +19,7 @@ impl FatalError { impl std::fmt::Display for FatalError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "parser fatal error") + write!(f, "fatal error") } } 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_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index c9398d746d7..ee9983ee8b8 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -87,7 +87,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { let trait_pred = ty::Binder::dummy(trait_ref); let bail_out = tcx.infer_ctxt().enter(|infcx| { - let mut selcx = SelectionContext::with_negative(&infcx, true); + let mut selcx = SelectionContext::new(&infcx); let result = selcx.select(&Obligation::new( ObligationCause::dummy(), orig_env, @@ -101,6 +101,24 @@ impl<'tcx> AutoTraitFinder<'tcx> { manual impl found, bailing out", trait_ref ); + return true; + } + _ => {} + } + + let result = selcx.select(&Obligation::new( + ObligationCause::dummy(), + orig_env, + trait_pred.to_poly_trait_predicate_negative_polarity(), + )); + + match result { + Ok(Some(ImplSource::UserDefined(_))) => { + debug!( + "find_auto_trait_generics({:?}): \ + manual impl found, bailing out", + trait_ref + ); true } _ => false, @@ -277,7 +295,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { fresh_preds.insert(self.clean_pred(infcx, predicate)); } - let mut select = SelectionContext::with_negative(&infcx, true); + let mut select = SelectionContext::new(&infcx); let mut already_visited = FxHashSet::default(); let mut predicates = VecDeque::new(); diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 959b644becd..d114515eca1 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -168,8 +168,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( "#![feature(generic_const_exprs)]\n".to_string(), rustc_errors::Applicability::MaybeIncorrect, ) - .emit(); - rustc_errors::FatalError.raise(); + .emit() } debug!(?concrete, "is_const_evaluatable"); 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 1303155ce54..468c7a3c55b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1954,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_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 6d232d86d8a..72d156067a1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -119,11 +119,6 @@ pub struct SelectionContext<'cx, 'tcx> { intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>, - /// Controls whether or not to filter out negative impls when selecting. - /// This is used in librustdoc to distinguish between the lack of an impl - /// and a negative impl - allow_negative_impls: bool, - /// The mode that trait queries run in, which informs our error handling /// policy. In essence, canonicalized queries need their errors propagated /// rather than immediately reported because we do not have accurate spans. @@ -215,7 +210,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { freshener: infcx.freshener_keep_static(), intercrate: false, intercrate_ambiguity_causes: None, - allow_negative_impls: false, query_mode: TraitQueryMode::Standard, } } @@ -226,22 +220,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { freshener: infcx.freshener_keep_static(), intercrate: true, intercrate_ambiguity_causes: None, - allow_negative_impls: false, - query_mode: TraitQueryMode::Standard, - } - } - - pub fn with_negative( - infcx: &'cx InferCtxt<'cx, 'tcx>, - allow_negative_impls: bool, - ) -> SelectionContext<'cx, 'tcx> { - debug!(?allow_negative_impls, "with_negative"); - SelectionContext { - infcx, - freshener: infcx.freshener_keep_static(), - intercrate: false, - intercrate_ambiguity_causes: None, - allow_negative_impls, query_mode: TraitQueryMode::Standard, } } @@ -256,7 +234,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { freshener: infcx.freshener_keep_static(), intercrate: false, intercrate_ambiguity_causes: None, - allow_negative_impls: false, query_mode, } } @@ -1192,7 +1169,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let ImplCandidate(def_id) = candidate { if ty::ImplPolarity::Reservation == tcx.impl_polarity(def_id) || obligation.polarity() == tcx.impl_polarity(def_id) - || self.allow_negative_impls { result.push(candidate); } @@ -1272,7 +1248,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // the master cache. Since coherence executes pretty quickly, // it's not worth going to more trouble to increase the // hit-rate, I don't think. - if self.intercrate || self.allow_negative_impls { + if self.intercrate { return false; } @@ -1289,7 +1265,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // mode, so don't do any caching. In particular, we might // re-use the same `InferCtxt` with both an intercrate // and non-intercrate `SelectionContext` - if self.intercrate || self.allow_negative_impls { + if self.intercrate { return None; } let tcx = self.tcx(); 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/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 1c4fbbbb9bf..d66230acb8b 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1258,7 +1258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.field_ty(span, f, substs) }) .unwrap_or_else(|| { - inexistent_fields.push(field.ident); + inexistent_fields.push(field); no_field_errors = false; tcx.ty_error() }) @@ -1276,13 +1276,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect::<Vec<_>>(); let inexistent_fields_err = if !(inexistent_fields.is_empty() || variant.is_recovered()) - && !inexistent_fields.iter().any(|field| field.name == kw::Underscore) + && !inexistent_fields.iter().any(|field| field.ident.name == kw::Underscore) { Some(self.error_inexistent_fields( adt.variant_descr(), &inexistent_fields, &mut unmentioned_fields, variant, + substs, )) } else { None @@ -1448,20 +1449,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn error_inexistent_fields( &self, kind_name: &str, - inexistent_fields: &[Ident], - unmentioned_fields: &mut Vec<(&ty::FieldDef, Ident)>, + inexistent_fields: &[&hir::PatField<'tcx>], + unmentioned_fields: &mut Vec<(&'tcx ty::FieldDef, Ident)>, variant: &ty::VariantDef, + substs: &'tcx ty::List<ty::subst::GenericArg<'tcx>>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let tcx = self.tcx; let (field_names, t, plural) = if inexistent_fields.len() == 1 { - (format!("a field named `{}`", inexistent_fields[0]), "this", "") + (format!("a field named `{}`", inexistent_fields[0].ident), "this", "") } else { ( format!( "fields named {}", inexistent_fields .iter() - .map(|ident| format!("`{}`", ident)) + .map(|field| format!("`{}`", field.ident)) .collect::<Vec<String>>() .join(", ") ), @@ -1469,7 +1471,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "s", ) }; - let spans = inexistent_fields.iter().map(|ident| ident.span).collect::<Vec<_>>(); + let spans = inexistent_fields.iter().map(|field| field.ident.span).collect::<Vec<_>>(); let mut err = struct_span_err!( tcx.sess, spans, @@ -1479,9 +1481,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.def_path_str(variant.def_id), field_names ); - if let Some(ident) = inexistent_fields.last() { + if let Some(pat_field) = inexistent_fields.last() { err.span_label( - ident.span, + pat_field.ident.span, format!( "{} `{}` does not have {} field{}", kind_name, @@ -1494,10 +1496,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if unmentioned_fields.len() == 1 { let input = unmentioned_fields.iter().map(|(_, field)| field.name).collect::<Vec<_>>(); - let suggested_name = find_best_match_for_name(&input, ident.name, None); + let suggested_name = find_best_match_for_name(&input, pat_field.ident.name, None); if let Some(suggested_name) = suggested_name { err.span_suggestion( - ident.span, + pat_field.ident.span, "a field with a similar name exists", suggested_name.to_string(), Applicability::MaybeIncorrect, @@ -1513,17 +1515,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { unmentioned_fields.retain(|&(_, x)| x.name != suggested_name); } } else if inexistent_fields.len() == 1 { - let unmentioned_field = unmentioned_fields[0].1.name; - err.span_suggestion_short( - ident.span, - &format!( - "`{}` has a field named `{}`", - tcx.def_path_str(variant.def_id), - unmentioned_field - ), - unmentioned_field.to_string(), - Applicability::MaybeIncorrect, - ); + match pat_field.pat.kind { + PatKind::Lit(expr) + if !self.can_coerce( + self.typeck_results.borrow().expr_ty(expr), + self.field_ty( + unmentioned_fields[0].1.span, + unmentioned_fields[0].0, + substs, + ), + ) => {} + _ => { + let unmentioned_field = unmentioned_fields[0].1.name; + err.span_suggestion_short( + pat_field.ident.span, + &format!( + "`{}` has a field named `{}`", + tcx.def_path_str(variant.def_id), + unmentioned_field + ), + unmentioned_field.to_string(), + Applicability::MaybeIncorrect, + ); + } + } } } } diff --git a/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs index 79965c1dc28..e2bd018cb20 100644 --- a/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs +++ b/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs @@ -21,7 +21,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx> { } fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let mut err = self.sess.struct_span_fatal_with_code( + let mut err = self.sess.struct_span_err_with_code( self.span, &format!("can't pass `{}` to variadic function", self.ty), self.code(), diff --git a/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs index 9b058d32f79..afc5c1fe6cc 100644 --- a/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs +++ b/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs @@ -21,7 +21,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> { } fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let mut err = self.sess.struct_span_fatal_with_code( + let mut err = self.sess.struct_span_err_with_code( self.span, &format!( "cannot cast thin pointer `{}` to fat pointer `{}`", 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/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 9a66e69bdc0..1ca5ee55375 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -479,12 +479,14 @@ impl<T> Vec<T> { /// /// * `ptr` needs to have been previously allocated via [`String`]/`Vec<T>` /// (at least, it's highly likely to be incorrect if it wasn't). - /// * `T` needs to have the same size and alignment as what `ptr` was allocated with. + /// * `T` needs to have the same alignment as what `ptr` was allocated with. /// (`T` having a less strict alignment is not sufficient, the alignment really /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be /// allocated and deallocated with the same layout.) + /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs + /// to be the same size as the pointer was allocated with. (Because similar to + /// alignment, [`dealloc`] must be called with the same layout `size`.) /// * `length` needs to be less than or equal to `capacity`. - /// * `capacity` needs to be the capacity that the pointer was allocated with. /// /// Violating these may cause problems like corrupting the allocator's /// internal data structures. For example it is **not** safe @@ -492,7 +494,9 @@ impl<T> Vec<T> { /// It's also not safe to build one from a `Vec<u16>` and its length, because /// the allocator cares about the alignment, and these two types have different /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after - /// turning it into a `Vec<u8>` it'll be deallocated with alignment 1. + /// turning it into a `Vec<u8>` it'll be deallocated with alignment 1. To avoid + /// these issues, it is often preferable to do casting/transmuting using + /// [`slice::from_raw_parts`] instead. /// /// The ownership of `ptr` is effectively transferred to the /// `Vec<T>` which may then deallocate, reallocate or change the @@ -2929,6 +2933,48 @@ impl<T, const N: usize> From<[T; N]> for Vec<T> { } } +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "vec_from_array_ref", since = "1.61.0")] +impl<T: Clone, const N: usize> From<&[T; N]> for Vec<T> { + /// Allocate a `Vec<T>` and fill it by cloning `s`'s items. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from(b"raw"), vec![b'r', b'a', b'w']); + /// ``` + #[cfg(not(test))] + fn from(s: &[T; N]) -> Vec<T> { + s.to_vec() + } + + #[cfg(test)] + fn from(s: &[T; N]) -> Vec<T> { + crate::slice::to_vec(s, Global) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "vec_from_array_ref", since = "1.61.0")] +impl<T: Clone, const N: usize> From<&mut [T; N]> for Vec<T> { + /// Allocate a `Vec<T>` and fill it by cloning `s`'s items. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]); + /// ``` + #[cfg(not(test))] + fn from(s: &mut [T; N]) -> Vec<T> { + s.to_vec() + } + + #[cfg(test)] + fn from(s: &mut [T; N]) -> Vec<T> { + crate::slice::to_vec(s, Global) + } +} + #[stable(feature = "vec_from_cow_slice", since = "1.14.0")] impl<'a, T> From<Cow<'a, [T]>> for Vec<T> where diff --git a/library/alloc/src/vec/partial_eq.rs b/library/alloc/src/vec/partial_eq.rs index 50e14096105..b0cf72577a1 100644 --- a/library/alloc/src/vec/partial_eq.rs +++ b/library/alloc/src/vec/partial_eq.rs @@ -20,7 +20,7 @@ macro_rules! __impl_slice_eq1 { } } -__impl_slice_eq1! { [A: Allocator] Vec<T, A>, Vec<U, A>, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A1: Allocator, A2: Allocator] Vec<T, A1>, Vec<U, A2>, #[stable(feature = "rust1", since = "1.0.0")] } __impl_slice_eq1! { [A: Allocator] Vec<T, A>, &[U], #[stable(feature = "rust1", since = "1.0.0")] } __impl_slice_eq1! { [A: Allocator] Vec<T, A>, &mut [U], #[stable(feature = "rust1", since = "1.0.0")] } __impl_slice_eq1! { [A: Allocator] &[T], Vec<U, A>, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } 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/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/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index f577f102e8d..3d719afe49e 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -4,11 +4,12 @@ use crate::ptr; /// A wrapper to inhibit compiler from automatically calling `T`’s destructor. /// This wrapper is 0-cost. /// -/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`. -/// As a consequence, it has *no effect* on the assumptions that the compiler makes -/// about its contents. For example, initializing a `ManuallyDrop<&mut T>` -/// with [`mem::zeroed`] is undefined behavior. -/// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead. +/// `ManuallyDrop<T>` is guaranteed to have the same layout as `T`, and is subject +/// to the same layout optimizations as `T`. As a consequence, it has *no effect* +/// on the assumptions that the compiler makes about its contents. For example, +/// initializing a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined +/// behavior. If you need to handle uninitialized data, use [`MaybeUninit<T>`] +/// instead. /// /// Note that accessing the value inside a `ManuallyDrop<T>` is safe. /// This means that a `ManuallyDrop<T>` whose content has been dropped must not 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/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 32ccca8bcdd..e7511888114 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -231,10 +231,10 @@ impl StepDescription { } if !builder.config.exclude.is_empty() { - eprintln!( + builder.verbose(&format!( "{:?} not skipped for {:?} -- not in {:?}", pathset, self.name, builder.config.exclude - ); + )); } false } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index e6c7745c6e1..efeb2e0d463 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -376,17 +376,26 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl let stab = myitem.stability_class(cx.tcx()); let add = if stab.is_some() { " " } else { "" }; + let visibility_emoji = match myitem.visibility { + clean::Visibility::Restricted(_) => { + "<span title=\"Restricted Visibility\"> 🔒</span> " + } + _ => "", + }; + let doc_value = myitem.doc_value().unwrap_or_default(); w.write_str(ITEM_TABLE_ROW_OPEN); write!( w, "<div class=\"item-left {stab}{add}module-item\">\ - <a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\ - {unsafety_flag}\ - {stab_tags}\ + <a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\ + {visibility_emoji}\ + {unsafety_flag}\ + {stab_tags}\ </div>\ <div class=\"item-right docblock-short\">{docs}</div>", name = myitem.name.unwrap(), + visibility_emoji = visibility_emoji, stab_tags = extra_info_tags(myitem, item, cx.tcx()), docs = MarkdownSummaryLine(&doc_value, &myitem.links(cx)).into_string(), class = myitem.type_(), diff --git a/src/test/rustdoc/visibility.rs b/src/test/rustdoc/visibility.rs index cd284dad390..c573e1b77f9 100644 --- a/src/test/rustdoc/visibility.rs +++ b/src/test/rustdoc/visibility.rs @@ -4,42 +4,68 @@ #![crate_name = "foo"] +// @!has 'foo/index.html' '//a[@href="struct.FooPublic.html"]/..' 'FooPublic 🔒' // @has 'foo/struct.FooPublic.html' '//pre' 'pub struct FooPublic' pub struct FooPublic; +// @has 'foo/index.html' '//a[@href="struct.FooJustCrate.html"]/..' 'FooJustCrate 🔒' // @has 'foo/struct.FooJustCrate.html' '//pre' 'pub(crate) struct FooJustCrate' crate struct FooJustCrate; +// @has 'foo/index.html' '//a[@href="struct.FooPubCrate.html"]/..' 'FooPubCrate 🔒' // @has 'foo/struct.FooPubCrate.html' '//pre' 'pub(crate) struct FooPubCrate' pub(crate) struct FooPubCrate; +// @has 'foo/index.html' '//a[@href="struct.FooSelf.html"]/..' 'FooSelf 🔒' // @has 'foo/struct.FooSelf.html' '//pre' 'pub(crate) struct FooSelf' pub(self) struct FooSelf; +// @has 'foo/index.html' '//a[@href="struct.FooInSelf.html"]/..' 'FooInSelf 🔒' // @has 'foo/struct.FooInSelf.html' '//pre' 'pub(crate) struct FooInSelf' pub(in self) struct FooInSelf; +// @has 'foo/index.html' '//a[@href="struct.FooPriv.html"]/..' 'FooPriv 🔒' // @has 'foo/struct.FooPriv.html' '//pre' 'pub(crate) struct FooPriv' struct FooPriv; +// @!has 'foo/index.html' '//a[@href="pub_mod/index.html"]/..' 'pub_mod 🔒' +pub mod pub_mod {} + +// @has 'foo/index.html' '//a[@href="pub_crate_mod/index.html"]/..' 'pub_crate_mod 🔒' +pub(crate) mod pub_crate_mod {} + +// @has 'foo/index.html' '//a[@href="a/index.html"]/..' 'a 🔒' mod a { + // @has 'foo/a/index.html' '//a[@href="struct.FooASuper.html"]/..' 'FooASuper 🔒' // @has 'foo/a/struct.FooASuper.html' '//pre' 'pub(crate) struct FooASuper' pub(super) struct FooASuper; + // @has 'foo/a/index.html' '//a[@href="struct.FooAInSuper.html"]/..' 'FooAInSuper 🔒' // @has 'foo/a/struct.FooAInSuper.html' '//pre' 'pub(crate) struct FooAInSuper' pub(in super) struct FooAInSuper; + // @has 'foo/a/index.html' '//a[@href="struct.FooAInA.html"]/..' 'FooAInA 🔒' // @has 'foo/a/struct.FooAInA.html' '//pre' 'struct FooAInA' // @!has 'foo/a/struct.FooAInA.html' '//pre' 'pub' pub(in a) struct FooAInA; + // @has 'foo/a/index.html' '//a[@href="struct.FooAPriv.html"]/..' 'FooAPriv 🔒' // @has 'foo/a/struct.FooAPriv.html' '//pre' 'struct FooAPriv' // @!has 'foo/a/struct.FooAPriv.html' '//pre' 'pub' struct FooAPriv; + // @has 'foo/a/index.html' '//a[@href="b/index.html"]/..' 'b 🔒' mod b { + // @has 'foo/a/b/index.html' '//a[@href="struct.FooBSuper.html"]/..' 'FooBSuper 🔒' // @has 'foo/a/b/struct.FooBSuper.html' '//pre' 'pub(super) struct FooBSuper' pub(super) struct FooBSuper; + // @has 'foo/a/b/index.html' '//a[@href="struct.FooBInSuperSuper.html"]/..' 'FooBInSuperSuper 🔒' // @has 'foo/a/b/struct.FooBInSuperSuper.html' '//pre' 'pub(crate) struct FooBInSuperSuper' pub(in super::super) struct FooBInSuperSuper; + // @has 'foo/a/b/index.html' '//a[@href="struct.FooBInAB.html"]/..' 'FooBInAB 🔒' // @has 'foo/a/b/struct.FooBInAB.html' '//pre' 'struct FooBInAB' // @!has 'foo/a/b/struct.FooBInAB.html' '//pre' 'pub' pub(in a::b) struct FooBInAB; + // @has 'foo/a/b/index.html' '//a[@href="struct.FooBPriv.html"]/..' 'FooBPriv 🔒' // @has 'foo/a/b/struct.FooBPriv.html' '//pre' 'struct FooBPriv' // @!has 'foo/a/b/struct.FooBPriv.html' '//pre' 'pub' struct FooBPriv; + + // @!has 'foo/a/b/index.html' '//a[@href="struct.FooBPub.html"]/..' 'FooBPub 🔒' + // @has 'foo/a/b/struct.FooBPub.html' '//pre' 'pub struct FooBPub' + pub struct FooBPub; } } @@ -53,6 +79,8 @@ mod a { // // @has 'foo/trait.PubTrait.html' '//pre' 'fn function();' // @!has 'foo/trait.PubTrait.html' '//pre' 'pub fn function();' +// +// @!has 'foo/index.html' '//a[@href="trait.PubTrait.html"]/..' 'PubTrait 🔒' pub trait PubTrait { type Type; @@ -60,6 +88,9 @@ pub trait PubTrait { fn function(); } +// @has 'foo/index.html' '//a[@href="trait.PrivTrait.html"]/..' 'PrivTrait 🔒' +trait PrivTrait {} + // @has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'type Type' // @!has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'pub type Type' // 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/auxiliary/empty-struct.rs b/src/test/ui/auxiliary/empty-struct.rs deleted file mode 100644 index 3fb40f6bfa9..00000000000 --- a/src/test/ui/auxiliary/empty-struct.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub struct XEmpty1 {} -pub struct XEmpty2; -pub struct XEmpty6(); - -pub enum XE { - XEmpty3 {}, - XEmpty4, - XEmpty5(), -} diff --git a/src/test/ui/auxiliary/stability-cfg2.rs b/src/test/ui/auxiliary/stability-cfg2.rs deleted file mode 100644 index c995038e5a8..00000000000 --- a/src/test/ui/auxiliary/stability-cfg2.rs +++ /dev/null @@ -1,5 +0,0 @@ -// compile-flags:--cfg foo - -#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "none"))] -#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))] -#![feature(staged_api)] diff --git a/src/test/ui/auxiliary/weak-lang-items.rs b/src/test/ui/auxiliary/weak-lang-items.rs deleted file mode 100644 index 7a698cf76ae..00000000000 --- a/src/test/ui/auxiliary/weak-lang-items.rs +++ /dev/null @@ -1,22 +0,0 @@ -// no-prefer-dynamic - -// This aux-file will require the eh_personality function to be codegen'd, but -// it hasn't been defined just yet. Make sure we don't explode. - -#![no_std] -#![crate_type = "rlib"] - -struct A; - -impl core::ops::Drop for A { - fn drop(&mut self) {} -} - -pub fn foo() { - let _a = A; - panic!("wut"); -} - -mod std { - pub use core::{option, fmt}; -} 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/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/cross-crate/auxiliary/anon_trait_static_method_lib.rs b/src/test/ui/cross-crate/auxiliary/anon_trait_static_method_lib.rs deleted file mode 100644 index dceec7e3ec1..00000000000 --- a/src/test/ui/cross-crate/auxiliary/anon_trait_static_method_lib.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub struct Foo { - pub x: isize -} - -impl Foo { - pub fn new() -> Foo { - Foo { x: 3 } - } -} diff --git a/src/test/ui/cross-crate/auxiliary/newtype_struct_xc.rs b/src/test/ui/cross-crate/auxiliary/newtype_struct_xc.rs deleted file mode 100644 index 9d1e0742e3c..00000000000 --- a/src/test/ui/cross-crate/auxiliary/newtype_struct_xc.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![crate_type="lib"] - -pub struct Au(pub isize); diff --git a/src/test/ui/cross-crate/auxiliary/xcrate_unit_struct.rs b/src/test/ui/cross-crate/auxiliary/xcrate_unit_struct.rs deleted file mode 100644 index 69ed498e7e1..00000000000 --- a/src/test/ui/cross-crate/auxiliary/xcrate_unit_struct.rs +++ /dev/null @@ -1,28 +0,0 @@ -#![crate_type = "lib"] - -// used by the rpass test - -#[derive(Copy, Clone)] -pub struct Struct; - -#[derive(Copy, Clone)] -pub enum Unit { - UnitVariant, - Argument(Struct) -} - -#[derive(Copy, Clone)] -pub struct TupleStruct(pub usize, pub &'static str); - -// used by the cfail test - -#[derive(Copy, Clone)] -pub struct StructWithFields { - foo: isize, -} - -#[derive(Copy, Clone)] -pub enum EnumWithVariants { - EnumVariant, - EnumVariantArg(isize) -} 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/issues/issue-37026.rs b/src/test/ui/empty/issue-37026.rs index fd678a717d0..fd678a717d0 100644 --- a/src/test/ui/issues/issue-37026.rs +++ b/src/test/ui/empty/issue-37026.rs diff --git a/src/test/ui/issues/issue-37026.stderr b/src/test/ui/empty/issue-37026.stderr index 48a4a5bcad2..48a4a5bcad2 100644 --- a/src/test/ui/issues/issue-37026.stderr +++ b/src/test/ui/empty/issue-37026.stderr diff --git a/src/test/ui/no-link.rs b/src/test/ui/empty/no-link.rs index c80e61b4511..c80e61b4511 100644 --- a/src/test/ui/no-link.rs +++ b/src/test/ui/empty/no-link.rs 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/issues/auxiliary/empty-struct.rs b/src/test/ui/issues/auxiliary/empty-struct.rs deleted file mode 100644 index 3fb40f6bfa9..00000000000 --- a/src/test/ui/issues/auxiliary/empty-struct.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub struct XEmpty1 {} -pub struct XEmpty2; -pub struct XEmpty6(); - -pub enum XE { - XEmpty3 {}, - XEmpty4, - XEmpty5(), -} 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-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-51244.rs b/src/test/ui/issues/issue-51244.rs deleted file mode 100644 index d634b8bf800..00000000000 --- a/src/test/ui/issues/issue-51244.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - let ref my_ref @ _ = 0; - *my_ref = 0; //~ ERROR cannot assign to `*my_ref`, which is behind a `&` reference [E0594] -} diff --git a/src/test/ui/issues/issue-51244.stderr b/src/test/ui/issues/issue-51244.stderr deleted file mode 100644 index 19f0223a357..00000000000 --- a/src/test/ui/issues/issue-51244.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0594]: cannot assign to `*my_ref`, which is behind a `&` reference - --> $DIR/issue-51244.rs:3:5 - | -LL | let ref my_ref @ _ = 0; - | -------------- help: consider changing this to be a mutable reference: `ref mut my_ref @ _` -LL | *my_ref = 0; - | ^^^^^^^^^^^ `my_ref` is a `&` reference, so the data it refers to cannot be written - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0594`. 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/macros/issue-95267.rs b/src/test/ui/macros/issue-95267.rs new file mode 100644 index 00000000000..4d59c7ea5e9 --- /dev/null +++ b/src/test/ui/macros/issue-95267.rs @@ -0,0 +1,13 @@ +// check-pass + +// This is a valid macro. Commit 4 in #95159 broke things such that it failed +// with a "missing tokens in macro arguments" error, as reported in #95267. +macro_rules! f { + ( + /// ab + ) => {}; +} + +fn main() { + f!(); +} 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/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/weak-lang-item.rs b/src/test/ui/panic-handler/weak-lang-item-2.rs index a429d8fabc7..a429d8fabc7 100644 --- a/src/test/ui/weak-lang-item.rs +++ b/src/test/ui/panic-handler/weak-lang-item-2.rs 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/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 acba357b0d3..00000000000 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr +++ /dev/null @@ -1,173 +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 - | - = 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 `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 - | - = 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: 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 - | - = 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 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 - | - = 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 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/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/regions/regions-enum-not-wf.rs b/src/test/ui/regions/regions-enum-not-wf.rs deleted file mode 100644 index 8b491ee4e30..00000000000 --- a/src/test/ui/regions/regions-enum-not-wf.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Various examples of structs whose fields are not well-formed. - -#![allow(dead_code)] - -trait Dummy<'a> { - type Out; -} -impl<'a, T> Dummy<'a> for T -where - T: 'a, -{ - type Out = (); -} -type RequireOutlives<'a, T> = <T as Dummy<'a>>::Out; - -enum Ref1<'a, T> { - Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough -} - -enum Ref2<'a, T> { - Ref2Variant1, - Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough -} - -enum RefOk<'a, T: 'a> { - RefOkVariant1(&'a T), -} - -// This is now well formed. RFC 2093 -enum RefIndirect<'a, T> { - RefIndirectVariant1(isize, RefOk<'a, T>), -} - -enum RefDouble<'a, 'b, T> { - RefDoubleVariant1(&'a RequireOutlives<'b, T>), - //~^ the parameter type `T` may not live long enough [E0309] -} - -fn main() {} diff --git a/src/test/ui/regions/regions-enum-not-wf.stderr b/src/test/ui/regions/regions-enum-not-wf.stderr deleted file mode 100644 index 553a3e71c16..00000000000 --- a/src/test/ui/regions/regions-enum-not-wf.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:17:18 - | -LL | enum Ref1<'a, T> { - | - help: consider adding an explicit lifetime bound...: `T: 'a` -LL | Ref1Variant1(RequireOutlives<'a, T>), - | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds - -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:22:25 - | -LL | enum Ref2<'a, T> { - | - help: consider adding an explicit lifetime bound...: `T: 'a` -LL | Ref2Variant1, -LL | Ref2Variant2(isize, RequireOutlives<'a, T>), - | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds - -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:35:23 - | -LL | enum RefDouble<'a, 'b, T> { - | - help: consider adding an explicit lifetime bound...: `T: 'b` -LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0309`. 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/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index dd090a3a548..34f059248b6 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -62,7 +62,7 @@ LL | if true || let 0 = 0 {} | = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions -note: `||` operators are not allowed in let chain expressions +note: `||` operators are not currently supported in let chain expressions --> $DIR/disallowed-positions.rs:47:13 | LL | if true || let 0 = 0 {} @@ -76,7 +76,7 @@ LL | if (true || let 0 = 0) {} | = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions -note: `||` operators are not allowed in let chain expressions +note: `||` operators are not currently supported in let chain expressions --> $DIR/disallowed-positions.rs:48:14 | LL | if (true || let 0 = 0) {} @@ -90,7 +90,7 @@ LL | if true && (true || let 0 = 0) {} | = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions -note: `||` operators are not allowed in let chain expressions +note: `||` operators are not currently supported in let chain expressions --> $DIR/disallowed-positions.rs:49:22 | LL | if true && (true || let 0 = 0) {} @@ -104,7 +104,7 @@ LL | if true || (true && let 0 = 0) {} | = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions -note: `||` operators are not allowed in let chain expressions +note: `||` operators are not currently supported in let chain expressions --> $DIR/disallowed-positions.rs:50:13 | LL | if true || (true && let 0 = 0) {} @@ -244,7 +244,7 @@ LL | while true || let 0 = 0 {} | = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions -note: `||` operators are not allowed in let chain expressions +note: `||` operators are not currently supported in let chain expressions --> $DIR/disallowed-positions.rs:111:16 | LL | while true || let 0 = 0 {} @@ -258,7 +258,7 @@ LL | while (true || let 0 = 0) {} | = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions -note: `||` operators are not allowed in let chain expressions +note: `||` operators are not currently supported in let chain expressions --> $DIR/disallowed-positions.rs:112:17 | LL | while (true || let 0 = 0) {} @@ -272,7 +272,7 @@ LL | while true && (true || let 0 = 0) {} | = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions -note: `||` operators are not allowed in let chain expressions +note: `||` operators are not currently supported in let chain expressions --> $DIR/disallowed-positions.rs:113:25 | LL | while true && (true || let 0 = 0) {} @@ -286,7 +286,7 @@ LL | while true || (true && let 0 = 0) {} | = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions -note: `||` operators are not allowed in let chain expressions +note: `||` operators are not currently supported in let chain expressions --> $DIR/disallowed-positions.rs:114:16 | LL | while true || (true && let 0 = 0) {} @@ -426,7 +426,7 @@ LL | true || let 0 = 0; | = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions -note: `||` operators are not allowed in let chain expressions +note: `||` operators are not currently supported in let chain expressions --> $DIR/disallowed-positions.rs:184:10 | LL | true || let 0 = 0; @@ -440,7 +440,7 @@ LL | (true || let 0 = 0); | = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions -note: `||` operators are not allowed in let chain expressions +note: `||` operators are not currently supported in let chain expressions --> $DIR/disallowed-positions.rs:185:11 | LL | (true || let 0 = 0); @@ -454,7 +454,7 @@ LL | true && (true || let 0 = 0); | = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions -note: `||` operators are not allowed in let chain expressions +note: `||` operators are not currently supported in let chain expressions --> $DIR/disallowed-positions.rs:186:19 | LL | true && (true || let 0 = 0); 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/span/E0057.rs b/src/test/ui/span/E0057.rs deleted file mode 100644 index 83f941f65b9..00000000000 --- a/src/test/ui/span/E0057.rs +++ /dev/null @@ -1,6 +0,0 @@ -fn main() { - let f = |x| x * 3; - let a = f(); //~ ERROR E0057 - let b = f(4); - let c = f(2, 3); //~ ERROR E0057 -} diff --git a/src/test/ui/span/E0057.stderr b/src/test/ui/span/E0057.stderr deleted file mode 100644 index 31579e28289..00000000000 --- a/src/test/ui/span/E0057.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0057]: this function takes 1 argument but 0 arguments were supplied - --> $DIR/E0057.rs:3:13 - | -LL | let a = f(); - | ^-- supplied 0 arguments - | | - | expected 1 argument - -error[E0057]: this function takes 1 argument but 2 arguments were supplied - --> $DIR/E0057.rs:5:13 - | -LL | let c = f(2, 3); - | ^ - - supplied 2 arguments - | | - | expected 1 argument - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0057`. diff --git a/src/test/ui/cross-crate/cross-crate-newtype-struct-pat.rs b/src/test/ui/structs-enums/cross-crate-newtype-struct-pat.rs index eabffc16170..eabffc16170 100644 --- a/src/test/ui/cross-crate/cross-crate-newtype-struct-pat.rs +++ b/src/test/ui/structs-enums/cross-crate-newtype-struct-pat.rs 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/suggestions/suggest-private-fields.rs b/src/test/ui/structs/suggest-private-fields.rs index 8267a82fe2a..8267a82fe2a 100644 --- a/src/test/ui/suggestions/suggest-private-fields.rs +++ b/src/test/ui/structs/suggest-private-fields.rs diff --git a/src/test/ui/suggestions/suggest-private-fields.stderr b/src/test/ui/structs/suggest-private-fields.stderr index d628bd16208..d628bd16208 100644 --- a/src/test/ui/suggestions/suggest-private-fields.stderr +++ b/src/test/ui/structs/suggest-private-fields.stderr diff --git a/src/test/ui/structs/suggest-replacing-field-when-specifying-same-type.rs b/src/test/ui/structs/suggest-replacing-field-when-specifying-same-type.rs new file mode 100644 index 00000000000..dd2fe79731e --- /dev/null +++ b/src/test/ui/structs/suggest-replacing-field-when-specifying-same-type.rs @@ -0,0 +1,28 @@ +enum Foo { + Bar { a: u8, b: i8, c: u8 }, + Baz { a: f32 }, + None, +} + +fn main() { + let foo = Foo::None; + match foo { + Foo::Bar { a, aa: 1, c } => (), + //~^ ERROR variant `Foo::Bar` does not have a field named `aa` [E0026] + //~| ERROR pattern does not mention field `b` [E0027] + Foo::Baz { bb: 1.0 } => (), + //~^ ERROR variant `Foo::Baz` does not have a field named `bb` [E0026] + //~| ERROR pattern does not mention field `a` [E0027] + _ => (), + } + + match foo { + Foo::Bar { a, aa: "", c } => (), + //~^ ERROR variant `Foo::Bar` does not have a field named `aa` [E0026] + //~| ERROR pattern does not mention field `b` [E0027] + Foo::Baz { bb: "" } => (), + //~^ ERROR variant `Foo::Baz` does not have a field named `bb` [E0026] + //~| pattern does not mention field `a` [E0027] + _ => (), + } +} diff --git a/src/test/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr b/src/test/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr new file mode 100644 index 00000000000..e8503f540c2 --- /dev/null +++ b/src/test/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr @@ -0,0 +1,94 @@ +error[E0026]: variant `Foo::Bar` does not have a field named `aa` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:10:23 + | +LL | Foo::Bar { a, aa: 1, c } => (), + | ^^ + | | + | variant `Foo::Bar` does not have this field + | help: `Foo::Bar` has a field named `b` + +error[E0027]: pattern does not mention field `b` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:10:9 + | +LL | Foo::Bar { a, aa: 1, c } => (), + | ^^^^^^^^^^^^^^^^^^^^^^^^ missing field `b` + | +help: include the missing field in the pattern + | +LL | Foo::Bar { a, aa: 1, c, b } => (), + | ~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | Foo::Bar { a, aa: 1, c, .. } => (), + | ~~~~~~ + +error[E0026]: variant `Foo::Baz` does not have a field named `bb` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:13:20 + | +LL | Foo::Baz { bb: 1.0 } => (), + | ^^ + | | + | variant `Foo::Baz` does not have this field + | help: `Foo::Baz` has a field named `a` + +error[E0027]: pattern does not mention field `a` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:13:9 + | +LL | Foo::Baz { bb: 1.0 } => (), + | ^^^^^^^^^^^^^^^^^^^^ missing field `a` + | +help: include the missing field in the pattern + | +LL | Foo::Baz { bb: 1.0, a } => (), + | ~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | Foo::Baz { bb: 1.0, .. } => (), + | ~~~~~~ + +error[E0026]: variant `Foo::Bar` does not have a field named `aa` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:20:23 + | +LL | Foo::Bar { a, aa: "", c } => (), + | ^^ variant `Foo::Bar` does not have this field + +error[E0027]: pattern does not mention field `b` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:20:9 + | +LL | Foo::Bar { a, aa: "", c } => (), + | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `b` + | +help: include the missing field in the pattern + | +LL | Foo::Bar { a, aa: "", c, b } => (), + | ~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | Foo::Bar { a, aa: "", c, .. } => (), + | ~~~~~~ + +error[E0026]: variant `Foo::Baz` does not have a field named `bb` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:23:20 + | +LL | Foo::Baz { bb: "" } => (), + | ^^ variant `Foo::Baz` does not have this field + +error[E0027]: pattern does not mention field `a` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:23:9 + | +LL | Foo::Baz { bb: "" } => (), + | ^^^^^^^^^^^^^^^^^^^ missing field `a` + | +help: include the missing field in the pattern + | +LL | Foo::Baz { bb: "", a } => (), + | ~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | Foo::Baz { bb: "", .. } => (), + | ~~~~~~ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0026, E0027. +For more information about an error, try `rustc --explain E0026`. diff --git a/src/test/ui/suggestions/auxiliary/struct_field_privacy.rs b/src/test/ui/suggestions/auxiliary/struct_field_privacy.rs deleted file mode 100644 index 9765af1a7f6..00000000000 --- a/src/test/ui/suggestions/auxiliary/struct_field_privacy.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub struct A { - a: isize, - pub b: isize, -} - -pub struct B { - pub a: isize, - b: isize, -} diff --git a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs index c66009fe24c..471a6b836b5 100644 --- a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs +++ b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs @@ -16,4 +16,8 @@ fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String { //~ ERROR expected trait, f fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { //~ ERROR expected trait, found } +fn issue_95327() where <u8 as Unresolved>::Assoc: String {} +//~^ ERROR expected trait, found struct +//~| ERROR use of undeclared type `Unresolved` + fn main() {} diff --git a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr index 38b2e5ae9b9..9ca446a0a89 100644 --- a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr +++ b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr @@ -1,3 +1,9 @@ +error[E0433]: failed to resolve: use of undeclared type `Unresolved` + --> $DIR/assoc_type_bound_with_struct.rs:19:31 + | +LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {} + | ^^^^^^^^^^ use of undeclared type `Unresolved` + error[E0404]: expected trait, found struct `String` --> $DIR/assoc_type_bound_with_struct.rs:5:46 | @@ -78,6 +84,18 @@ help: a trait with a similar name exists LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: ToString { | ~~~~~~~~ -error: aborting due to 4 previous errors +error[E0404]: expected trait, found struct `String` + --> $DIR/assoc_type_bound_with_struct.rs:19:51 + | +LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {} + | ^^^^^^ help: a trait with a similar name exists: `ToString` + | + ::: $SRC_DIR/alloc/src/string.rs:LL:COL + | +LL | pub trait ToString { + | ------------------ similarly named trait `ToString` defined here + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0404`. +Some errors have detailed explanations: E0404, E0433. +For more information about an error, try `rustc --explain E0404`. 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/test/ui/cross-crate/xcrate-unit-struct.rs b/src/test/ui/xcrate/xcrate-unit-struct-2.rs index 7aa3eb0d6c4..7aa3eb0d6c4 100644 --- a/src/test/ui/cross-crate/xcrate-unit-struct.rs +++ b/src/test/ui/xcrate/xcrate-unit-struct-2.rs 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/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 |
