From b324fcb169cbb952a5ef87fe00989666a9695d89 Mon Sep 17 00:00:00 2001 From: Rajveer <rajveer.developer@icloud.com> Date: Fri, 23 Aug 2024 18:33:59 +0530 Subject: [PATCH 01/13] [testsuite][cleanup] Remove all usages of `dont_merge` hack to avoid function merging Resolves #129438 The `-Zmerge-functions=disabled` compile flag exists for this purpose. --- tests/assembly/asm/aarch64-modifiers.rs | 7 +------ tests/assembly/asm/aarch64-types.rs | 13 +------------ tests/assembly/asm/arm-modifiers.rs | 7 +------ tests/assembly/asm/arm-types.rs | 13 +------------ tests/assembly/asm/hexagon-types.rs | 25 +------------------------ tests/assembly/asm/loongarch-type.rs | 10 +--------- tests/assembly/asm/mips-types.rs | 10 +--------- tests/assembly/asm/powerpc-types.rs | 10 +--------- tests/assembly/asm/riscv-types.rs | 13 +------------ tests/assembly/asm/s390x-types.rs | 10 +--------- tests/assembly/asm/x86-modifiers.rs | 7 +------ tests/assembly/asm/x86-types.rs | 13 +------------ 12 files changed, 12 insertions(+), 126 deletions(-) diff --git a/tests/assembly/asm/aarch64-modifiers.rs b/tests/assembly/asm/aarch64-modifiers.rs index b7ef1d77ea0..a4a41dd96c1 100644 --- a/tests/assembly/asm/aarch64-modifiers.rs +++ b/tests/assembly/asm/aarch64-modifiers.rs @@ -1,6 +1,7 @@ //@ assembly-output: emit-asm //@ compile-flags: -O -C panic=abort //@ compile-flags: --target aarch64-unknown-linux-gnu +//@ compile-flags: -Zmerge-functions=disabled //@ needs-llvm-components: aarch64 #![feature(no_core, lang_items, rustc_attrs)] @@ -29,12 +30,6 @@ macro_rules! check { // -O and extern "C" guarantee that the selected register is always r0/s0/d0/q0 #[no_mangle] pub unsafe extern "C" fn $func() -> i32 { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - let y; asm!($code, out($reg) y); y diff --git a/tests/assembly/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs index f36345670e3..cf1882ba1a2 100644 --- a/tests/assembly/asm/aarch64-types.rs +++ b/tests/assembly/asm/aarch64-types.rs @@ -4,6 +4,7 @@ //@ [aarch64] needs-llvm-components: aarch64 //@ [arm64ec] compile-flags: --target arm64ec-pc-windows-msvc //@ [arm64ec] needs-llvm-components: aarch64 +//@ compile-flags: -Zmerge-functions=disabled #![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch, f16, f128)] #![crate_type = "rlib"] @@ -132,12 +133,6 @@ macro_rules! check { // LLVM issue: <https://github.com/llvm/llvm-project/issues/94434> #[no_mangle] pub unsafe fn $func(inp: &$ty, out: &mut $ty) { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - let x = *inp; let y; asm!( @@ -155,12 +150,6 @@ macro_rules! check_reg { // FIXME(f16_f128): See FIXME in `check!` #[no_mangle] pub unsafe fn $func(inp: &$ty, out: &mut $ty) { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - let x = *inp; let y; asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); diff --git a/tests/assembly/asm/arm-modifiers.rs b/tests/assembly/asm/arm-modifiers.rs index 0674e169d72..d421e0e6954 100644 --- a/tests/assembly/asm/arm-modifiers.rs +++ b/tests/assembly/asm/arm-modifiers.rs @@ -2,6 +2,7 @@ //@ compile-flags: -O -C panic=abort //@ compile-flags: --target armv7-unknown-linux-gnueabihf //@ compile-flags: -C target-feature=+neon +//@ compile-flags: -Zmerge-functions=disabled //@ needs-llvm-components: arm #![feature(no_core, lang_items, rustc_attrs, repr_simd)] @@ -40,12 +41,6 @@ macro_rules! check { // -O and extern "C" guarantee that the selected register is always r0/s0/d0/q0 #[no_mangle] pub unsafe extern "C" fn $func() -> $ty { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - let y; asm!(concat!($mov, " {0:", $modifier, "}, {0:", $modifier, "}"), out($reg) y); y diff --git a/tests/assembly/asm/arm-types.rs b/tests/assembly/asm/arm-types.rs index eeff1a070b4..448b92aa839 100644 --- a/tests/assembly/asm/arm-types.rs +++ b/tests/assembly/asm/arm-types.rs @@ -2,6 +2,7 @@ //@ assembly-output: emit-asm //@ compile-flags: --target armv7-unknown-linux-gnueabihf //@ compile-flags: -C opt-level=0 +//@ compile-flags: -Zmerge-functions=disabled //@[d32] compile-flags: -C target-feature=+d32 //@[neon] compile-flags: -C target-feature=+neon --cfg d32 //@[neon] filecheck-flags: --check-prefix d32 @@ -114,12 +115,6 @@ macro_rules! check { ($func:ident $ty:ident $class:ident $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - let y; asm!(concat!($mov, " {}, {}"), out($class) y, in($class) x); y @@ -131,12 +126,6 @@ macro_rules! check_reg { ($func:ident $ty:ident $reg:tt $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - let y; asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); y diff --git a/tests/assembly/asm/hexagon-types.rs b/tests/assembly/asm/hexagon-types.rs index 269c7582a1c..9389fcf9cba 100644 --- a/tests/assembly/asm/hexagon-types.rs +++ b/tests/assembly/asm/hexagon-types.rs @@ -1,5 +1,6 @@ //@ assembly-output: emit-asm //@ compile-flags: --target hexagon-unknown-linux-musl +//@ compile-flags: -Zmerge-functions=disabled //@ needs-llvm-components: hexagon #![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] @@ -41,12 +42,6 @@ macro_rules! check { ($func:ident $ty:ident $class:ident) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - let y; asm!("{} = {}", out($class) y, in($class) x); y @@ -58,12 +53,6 @@ macro_rules! check_reg { ($func:ident $ty:ident $reg:tt) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - let y; asm!(concat!($reg, " = ", $reg), lateout($reg) y, in($reg) x); y @@ -77,12 +66,6 @@ macro_rules! check_reg { // CHECK: InlineAsm End #[no_mangle] pub unsafe fn sym_static() { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - asm!("r0 = #{}", sym extern_static); } @@ -92,12 +75,6 @@ pub unsafe fn sym_static() { // CHECK: InlineAsm End #[no_mangle] pub unsafe fn sym_fn() { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - asm!("r0 = #{}", sym extern_func); } diff --git a/tests/assembly/asm/loongarch-type.rs b/tests/assembly/asm/loongarch-type.rs index e4c46cfcf81..1b097f41105 100644 --- a/tests/assembly/asm/loongarch-type.rs +++ b/tests/assembly/asm/loongarch-type.rs @@ -1,5 +1,6 @@ //@ assembly-output: emit-asm //@ compile-flags: --target loongarch64-unknown-linux-gnu +//@ compile-flags: -Zmerge-functions=disabled //@ needs-llvm-components: loongarch #![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)] @@ -39,11 +40,6 @@ extern "C" { static extern_static: u8; } -// Hack to avoid function merging -extern "Rust" { - fn dont_merge(s: &str); -} - // CHECK-LABEL: sym_fn: // CHECK: #APP // CHECK: pcalau12i $t0, %got_pc_hi20(extern_func) @@ -67,8 +63,6 @@ pub unsafe fn sym_static() { macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - dont_merge(stringify!($func)); - let y; asm!(concat!($mov," {}, {}"), out($class) y, in($class) x); y @@ -78,8 +72,6 @@ macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - dont_merge(stringify!($func)); - let y; asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); y diff --git a/tests/assembly/asm/mips-types.rs b/tests/assembly/asm/mips-types.rs index bd62f4a5236..f40a28be4a7 100644 --- a/tests/assembly/asm/mips-types.rs +++ b/tests/assembly/asm/mips-types.rs @@ -4,6 +4,7 @@ //@[mips32] needs-llvm-components: mips //@[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64 //@[mips64] needs-llvm-components: mips +//@ compile-flags: -Zmerge-functions=disabled #![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] #![crate_type = "rlib"] @@ -43,16 +44,9 @@ extern "C" { static extern_static: u8; } -// Hack to avoid function merging -extern "Rust" { - fn dont_merge(s: &str); -} - macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - dont_merge(stringify!($func)); - let y; asm!(concat!($mov," {}, {}"), out($class) y, in($class) x); y @@ -62,8 +56,6 @@ macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - dont_merge(stringify!($func)); - let y; asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); y diff --git a/tests/assembly/asm/powerpc-types.rs b/tests/assembly/asm/powerpc-types.rs index bc8af08ad11..85321e5f345 100644 --- a/tests/assembly/asm/powerpc-types.rs +++ b/tests/assembly/asm/powerpc-types.rs @@ -4,6 +4,7 @@ //@[powerpc] needs-llvm-components: powerpc //@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu //@[powerpc64] needs-llvm-components: powerpc +//@ compile-flags: -Zmerge-functions=disabled #![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] #![crate_type = "rlib"] @@ -43,16 +44,9 @@ extern "C" { static extern_static: u8; } -// Hack to avoid function merging -extern "Rust" { - fn dont_merge(s: &str); -} - macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - dont_merge(stringify!($func)); - let y; asm!(concat!($mov," {}, {}"), out($class) y, in($class) x); y @@ -62,8 +56,6 @@ macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { macro_rules! check_reg { ($func:ident, $ty:ty, $rego:tt, $regc:tt, $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - dont_merge(stringify!($func)); - let y; asm!(concat!($mov, " ", $rego, ", ", $rego), lateout($regc) y, in($regc) x); y diff --git a/tests/assembly/asm/riscv-types.rs b/tests/assembly/asm/riscv-types.rs index 51b3aaf99d9..1f5d7d85b0a 100644 --- a/tests/assembly/asm/riscv-types.rs +++ b/tests/assembly/asm/riscv-types.rs @@ -27,6 +27,7 @@ //@[riscv32-zfh] filecheck-flags: --check-prefix zfhmin //@ compile-flags: -C target-feature=+d +//@ compile-flags: -Zmerge-functions=disabled #![feature(no_core, lang_items, rustc_attrs, f16)] #![crate_type = "rlib"] @@ -90,12 +91,6 @@ macro_rules! check { ($func:ident $ty:ident $class:ident $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - let y; asm!(concat!($mov, " {}, {}"), out($class) y, in($class) x); y @@ -107,12 +102,6 @@ macro_rules! check_reg { ($func:ident $ty:ident $reg:tt $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - let y; asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); y diff --git a/tests/assembly/asm/s390x-types.rs b/tests/assembly/asm/s390x-types.rs index 661907360bd..e68b18d7aa6 100644 --- a/tests/assembly/asm/s390x-types.rs +++ b/tests/assembly/asm/s390x-types.rs @@ -2,6 +2,7 @@ //@ assembly-output: emit-asm //@[s390x] compile-flags: --target s390x-unknown-linux-gnu //@[s390x] needs-llvm-components: systemz +//@ compile-flags: -Zmerge-functions=disabled #![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] #![crate_type = "rlib"] @@ -42,16 +43,9 @@ extern "C" { static extern_static: u8; } -// Hack to avoid function merging -extern "Rust" { - fn dont_merge(s: &str); -} - macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - dont_merge(stringify!($func)); - let y; asm!(concat!($mov," {}, {}"), out($class) y, in($class) x); y @@ -61,8 +55,6 @@ macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - dont_merge(stringify!($func)); - let y; asm!(concat!($mov, " %", $reg, ", %", $reg), lateout($reg) y, in($reg) x); y diff --git a/tests/assembly/asm/x86-modifiers.rs b/tests/assembly/asm/x86-modifiers.rs index c5e393b1056..5a48af9205f 100644 --- a/tests/assembly/asm/x86-modifiers.rs +++ b/tests/assembly/asm/x86-modifiers.rs @@ -7,6 +7,7 @@ //@[i686] needs-llvm-components: x86 //@ compile-flags: -C llvm-args=--x86-asm-syntax=intel //@ compile-flags: -C target-feature=+avx512bw +//@ compile-flags: -Zmerge-functions=disabled #![feature(no_core, lang_items, rustc_attrs)] #![crate_type = "rlib"] @@ -38,12 +39,6 @@ macro_rules! check { // -O and extern "C" guarantee that the selected register is always ax/xmm0 #[no_mangle] pub unsafe extern "C" fn $func() -> i32 { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - let y; asm!(concat!($mov, " {0:", $modifier, "}, {0:", $modifier, "}"), out($reg) y); y diff --git a/tests/assembly/asm/x86-types.rs b/tests/assembly/asm/x86-types.rs index 8e229614420..a40bc10d991 100644 --- a/tests/assembly/asm/x86-types.rs +++ b/tests/assembly/asm/x86-types.rs @@ -6,6 +6,7 @@ //@[i686] needs-llvm-components: x86 //@ compile-flags: -C llvm-args=--x86-asm-syntax=intel //@ compile-flags: -C target-feature=+avx512bw +//@ compile-flags: -Zmerge-functions=disabled #![feature(no_core, lang_items, rustc_attrs, repr_simd, f16, f128)] #![crate_type = "rlib"] @@ -283,12 +284,6 @@ macro_rules! check { ($func:ident $ty:ident $class:ident $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - let y; asm!(concat!($mov, " {}, {}"), lateout($class) y, in($class) x); y @@ -300,12 +295,6 @@ macro_rules! check_reg { ($func:ident $ty:ident $reg:tt $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - let y; asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); y From 265cd14cd46e740bf2ac0fa68f0eeafcd83984e0 Mon Sep 17 00:00:00 2001 From: Veera <sveera.2001@gmail.com> Date: Sun, 1 Sep 2024 22:27:43 -0400 Subject: [PATCH 02/13] Update Tests --- .../parser/misspelled-keywords/assoc-type.rs | 6 ++++++ .../misspelled-keywords/assoc-type.stderr | 13 ++++++++++++ .../parser/misspelled-keywords/async-move.rs | 6 ++++++ .../misspelled-keywords/async-move.stderr | 8 ++++++++ .../ui/parser/misspelled-keywords/const-fn.rs | 5 +++++ .../misspelled-keywords/const-fn.stderr | 8 ++++++++ .../misspelled-keywords/const-generics.rs | 4 ++++ .../misspelled-keywords/const-generics.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/const.rs | 4 ++++ .../parser/misspelled-keywords/const.stderr | 8 ++++++++ .../ui/parser/misspelled-keywords/for-loop.rs | 4 ++++ .../misspelled-keywords/for-loop.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/hrdt.rs | 16 +++++++++++++++ .../ui/parser/misspelled-keywords/hrdt.stderr | 8 ++++++++ .../parser/misspelled-keywords/impl-block.rs | 6 ++++++ .../misspelled-keywords/impl-block.stderr | 8 ++++++++ .../parser/misspelled-keywords/impl-return.rs | 4 ++++ .../misspelled-keywords/impl-return.stderr | 8 ++++++++ .../misspelled-keywords/impl-trait-for.rs | 6 ++++++ .../misspelled-keywords/impl-trait-for.stderr | 8 ++++++++ .../parser/misspelled-keywords/impl-trait.rs | 4 ++++ .../misspelled-keywords/impl-trait.stderr | 13 ++++++++++++ .../ui/parser/misspelled-keywords/let-else.rs | 4 ++++ .../misspelled-keywords/let-else.stderr | 8 ++++++++ .../ui/parser/misspelled-keywords/let-mut.rs | 4 ++++ .../parser/misspelled-keywords/let-mut.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/let.rs | 9 +++++++++ .../ui/parser/misspelled-keywords/let.stderr | 14 +++++++++++++ tests/ui/parser/misspelled-keywords/match.rs | 5 +++++ .../parser/misspelled-keywords/match.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/mod.rs | 4 ++++ .../ui/parser/misspelled-keywords/mod.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/pub-fn.rs | 5 +++++ .../parser/misspelled-keywords/pub-fn.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/ref.rs | 9 +++++++++ .../ui/parser/misspelled-keywords/ref.stderr | 20 +++++++++++++++++++ tests/ui/parser/misspelled-keywords/return.rs | 7 +++++++ .../parser/misspelled-keywords/return.stderr | 8 ++++++++ .../parser/misspelled-keywords/static-mut.rs | 5 +++++ .../misspelled-keywords/static-mut.stderr | 19 ++++++++++++++++++ tests/ui/parser/misspelled-keywords/static.rs | 4 ++++ .../parser/misspelled-keywords/static.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/struct.rs | 4 ++++ .../parser/misspelled-keywords/struct.stderr | 8 ++++++++ .../parser/misspelled-keywords/unsafe-fn.rs | 4 ++++ .../misspelled-keywords/unsafe-fn.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/use.rs | 4 ++++ .../ui/parser/misspelled-keywords/use.stderr | 8 ++++++++ .../misspelled-keywords/where-clause.rs | 8 ++++++++ .../misspelled-keywords/where-clause.stderr | 10 ++++++++++ .../parser/misspelled-keywords/while-loop.rs | 7 +++++++ .../misspelled-keywords/while-loop.stderr | 8 ++++++++ .../while-without-identifiers.rs | 4 ++++ .../while-without-identifiers.stderr | 8 ++++++++ 54 files changed, 409 insertions(+) create mode 100644 tests/ui/parser/misspelled-keywords/assoc-type.rs create mode 100644 tests/ui/parser/misspelled-keywords/assoc-type.stderr create mode 100644 tests/ui/parser/misspelled-keywords/async-move.rs create mode 100644 tests/ui/parser/misspelled-keywords/async-move.stderr create mode 100644 tests/ui/parser/misspelled-keywords/const-fn.rs create mode 100644 tests/ui/parser/misspelled-keywords/const-fn.stderr create mode 100644 tests/ui/parser/misspelled-keywords/const-generics.rs create mode 100644 tests/ui/parser/misspelled-keywords/const-generics.stderr create mode 100644 tests/ui/parser/misspelled-keywords/const.rs create mode 100644 tests/ui/parser/misspelled-keywords/const.stderr create mode 100644 tests/ui/parser/misspelled-keywords/for-loop.rs create mode 100644 tests/ui/parser/misspelled-keywords/for-loop.stderr create mode 100644 tests/ui/parser/misspelled-keywords/hrdt.rs create mode 100644 tests/ui/parser/misspelled-keywords/hrdt.stderr create mode 100644 tests/ui/parser/misspelled-keywords/impl-block.rs create mode 100644 tests/ui/parser/misspelled-keywords/impl-block.stderr create mode 100644 tests/ui/parser/misspelled-keywords/impl-return.rs create mode 100644 tests/ui/parser/misspelled-keywords/impl-return.stderr create mode 100644 tests/ui/parser/misspelled-keywords/impl-trait-for.rs create mode 100644 tests/ui/parser/misspelled-keywords/impl-trait-for.stderr create mode 100644 tests/ui/parser/misspelled-keywords/impl-trait.rs create mode 100644 tests/ui/parser/misspelled-keywords/impl-trait.stderr create mode 100644 tests/ui/parser/misspelled-keywords/let-else.rs create mode 100644 tests/ui/parser/misspelled-keywords/let-else.stderr create mode 100644 tests/ui/parser/misspelled-keywords/let-mut.rs create mode 100644 tests/ui/parser/misspelled-keywords/let-mut.stderr create mode 100644 tests/ui/parser/misspelled-keywords/let.rs create mode 100644 tests/ui/parser/misspelled-keywords/let.stderr create mode 100644 tests/ui/parser/misspelled-keywords/match.rs create mode 100644 tests/ui/parser/misspelled-keywords/match.stderr create mode 100644 tests/ui/parser/misspelled-keywords/mod.rs create mode 100644 tests/ui/parser/misspelled-keywords/mod.stderr create mode 100644 tests/ui/parser/misspelled-keywords/pub-fn.rs create mode 100644 tests/ui/parser/misspelled-keywords/pub-fn.stderr create mode 100644 tests/ui/parser/misspelled-keywords/ref.rs create mode 100644 tests/ui/parser/misspelled-keywords/ref.stderr create mode 100644 tests/ui/parser/misspelled-keywords/return.rs create mode 100644 tests/ui/parser/misspelled-keywords/return.stderr create mode 100644 tests/ui/parser/misspelled-keywords/static-mut.rs create mode 100644 tests/ui/parser/misspelled-keywords/static-mut.stderr create mode 100644 tests/ui/parser/misspelled-keywords/static.rs create mode 100644 tests/ui/parser/misspelled-keywords/static.stderr create mode 100644 tests/ui/parser/misspelled-keywords/struct.rs create mode 100644 tests/ui/parser/misspelled-keywords/struct.stderr create mode 100644 tests/ui/parser/misspelled-keywords/unsafe-fn.rs create mode 100644 tests/ui/parser/misspelled-keywords/unsafe-fn.stderr create mode 100644 tests/ui/parser/misspelled-keywords/use.rs create mode 100644 tests/ui/parser/misspelled-keywords/use.stderr create mode 100644 tests/ui/parser/misspelled-keywords/where-clause.rs create mode 100644 tests/ui/parser/misspelled-keywords/where-clause.stderr create mode 100644 tests/ui/parser/misspelled-keywords/while-loop.rs create mode 100644 tests/ui/parser/misspelled-keywords/while-loop.stderr create mode 100644 tests/ui/parser/misspelled-keywords/while-without-identifiers.rs create mode 100644 tests/ui/parser/misspelled-keywords/while-without-identifiers.stderr diff --git a/tests/ui/parser/misspelled-keywords/assoc-type.rs b/tests/ui/parser/misspelled-keywords/assoc-type.rs new file mode 100644 index 00000000000..a6b694a2abe --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/assoc-type.rs @@ -0,0 +1,6 @@ +trait Animal { + Type Result = u8; + //~^ ERROR expected one of +} + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/assoc-type.stderr b/tests/ui/parser/misspelled-keywords/assoc-type.stderr new file mode 100644 index 00000000000..1318bee3da8 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/assoc-type.stderr @@ -0,0 +1,13 @@ +error: expected one of `!` or `::`, found `Result` + --> $DIR/assoc-type.rs:2:10 + | +LL | trait Animal { + | - while parsing this item list starting here +LL | Type Result = u8; + | ^^^^^^ expected one of `!` or `::` +LL | +LL | } + | - the item list ends here + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/async-move.rs b/tests/ui/parser/misspelled-keywords/async-move.rs new file mode 100644 index 00000000000..702a905e918 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/async-move.rs @@ -0,0 +1,6 @@ +//@ edition: 2018 + +fn main() { + async Move {} + //~^ ERROR expected one of +} diff --git a/tests/ui/parser/misspelled-keywords/async-move.stderr b/tests/ui/parser/misspelled-keywords/async-move.stderr new file mode 100644 index 00000000000..a98bb23f5d6 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/async-move.stderr @@ -0,0 +1,8 @@ +error: expected one of `move`, `|`, or `||`, found `Move` + --> $DIR/async-move.rs:4:11 + | +LL | async Move {} + | ^^^^ expected one of `move`, `|`, or `||` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/const-fn.rs b/tests/ui/parser/misspelled-keywords/const-fn.rs new file mode 100644 index 00000000000..c4174b6a2ef --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/const-fn.rs @@ -0,0 +1,5 @@ +cnst fn code() {} +//~^ ERROR expected one of + +fn main() { +} diff --git a/tests/ui/parser/misspelled-keywords/const-fn.stderr b/tests/ui/parser/misspelled-keywords/const-fn.stderr new file mode 100644 index 00000000000..bdca2657ef3 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/const-fn.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found keyword `fn` + --> $DIR/const-fn.rs:1:6 + | +LL | cnst fn code() {} + | ^^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/const-generics.rs b/tests/ui/parser/misspelled-keywords/const-generics.rs new file mode 100644 index 00000000000..2df64a87e27 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/const-generics.rs @@ -0,0 +1,4 @@ +fn foo<consta N: usize>(_arr: [i32; N]) {} +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/const-generics.stderr b/tests/ui/parser/misspelled-keywords/const-generics.stderr new file mode 100644 index 00000000000..f52544ac45c --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/const-generics.stderr @@ -0,0 +1,8 @@ +error: expected one of `,`, `:`, `=`, or `>`, found `N` + --> $DIR/const-generics.rs:1:15 + | +LL | fn foo<consta N: usize>(_arr: [i32; N]) {} + | ^ expected one of `,`, `:`, `=`, or `>` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/const.rs b/tests/ui/parser/misspelled-keywords/const.rs new file mode 100644 index 00000000000..b481408cb62 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/const.rs @@ -0,0 +1,4 @@ +cons A: u8 = 10; +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/const.stderr b/tests/ui/parser/misspelled-keywords/const.stderr new file mode 100644 index 00000000000..de1ad9d2bf7 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/const.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `A` + --> $DIR/const.rs:1:6 + | +LL | cons A: u8 = 10; + | ^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/for-loop.rs b/tests/ui/parser/misspelled-keywords/for-loop.rs new file mode 100644 index 00000000000..6aba581cf17 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/for-loop.rs @@ -0,0 +1,4 @@ +fn main() { + form i in 1..10 {} + //~^ ERROR expected one of +} diff --git a/tests/ui/parser/misspelled-keywords/for-loop.stderr b/tests/ui/parser/misspelled-keywords/for-loop.stderr new file mode 100644 index 00000000000..cbf3b43fa58 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/for-loop.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `i` + --> $DIR/for-loop.rs:2:10 + | +LL | form i in 1..10 {} + | ^ expected one of 8 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/hrdt.rs b/tests/ui/parser/misspelled-keywords/hrdt.rs new file mode 100644 index 00000000000..9ca9e1bfbee --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/hrdt.rs @@ -0,0 +1,16 @@ +struct Closure<F> { + data: (u8, u16), + func: F, +} + +impl<F> Closure<F> + Where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8, +//~^ ERROR expected one of +{ + fn call(&self) -> &u8 { + (self.func)(&self.data) + } +} + + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/hrdt.stderr b/tests/ui/parser/misspelled-keywords/hrdt.stderr new file mode 100644 index 00000000000..102ce7014e4 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/hrdt.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found keyword `for` + --> $DIR/hrdt.rs:7:11 + | +LL | Where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8, + | ^^^ expected one of 7 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/impl-block.rs b/tests/ui/parser/misspelled-keywords/impl-block.rs new file mode 100644 index 00000000000..dc2570c22c5 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-block.rs @@ -0,0 +1,6 @@ +struct Human; + +ipml Human {} +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/impl-block.stderr b/tests/ui/parser/misspelled-keywords/impl-block.stderr new file mode 100644 index 00000000000..e0f0f8ed18f --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-block.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `Human` + --> $DIR/impl-block.rs:3:6 + | +LL | ipml Human {} + | ^^^^^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/impl-return.rs b/tests/ui/parser/misspelled-keywords/impl-return.rs new file mode 100644 index 00000000000..c9d1973179e --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-return.rs @@ -0,0 +1,4 @@ +fn code() -> Impl Display {} +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/impl-return.stderr b/tests/ui/parser/misspelled-keywords/impl-return.stderr new file mode 100644 index 00000000000..bdcf831a88a --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-return.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `Display` + --> $DIR/impl-return.rs:1:19 + | +LL | fn code() -> Impl Display {} + | ^^^^^^^ expected one of 7 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/impl-trait-for.rs b/tests/ui/parser/misspelled-keywords/impl-trait-for.rs new file mode 100644 index 00000000000..c6f3fcda5ad --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-trait-for.rs @@ -0,0 +1,6 @@ +struct Human; + +impl Debug form Human {} +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr b/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr new file mode 100644 index 00000000000..64ca66794ad --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `Human` + --> $DIR/impl-trait-for.rs:3:17 + | +LL | impl Debug form Human {} + | ^^^^^ expected one of 7 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/impl-trait.rs b/tests/ui/parser/misspelled-keywords/impl-trait.rs new file mode 100644 index 00000000000..99380b8ac0e --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-trait.rs @@ -0,0 +1,4 @@ +fn code<T: impll Debug>() -> u8 {} +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/impl-trait.stderr b/tests/ui/parser/misspelled-keywords/impl-trait.stderr new file mode 100644 index 00000000000..ca0918e820f --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-trait.stderr @@ -0,0 +1,13 @@ +error: expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`, found `Debug` + --> $DIR/impl-trait.rs:1:18 + | +LL | fn code<T: impll Debug>() -> u8 {} + | ^^^^^ expected one of 7 possible tokens + | +help: you might have meant to end the type parameters here + | +LL | fn code<T: impll> Debug>() -> u8 {} + | + + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/let-else.rs b/tests/ui/parser/misspelled-keywords/let-else.rs new file mode 100644 index 00000000000..0d5a03e3e43 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/let-else.rs @@ -0,0 +1,4 @@ +fn main() { + let Some(a) = Some(10) elze {} + //~^ ERROR expected one of +} diff --git a/tests/ui/parser/misspelled-keywords/let-else.stderr b/tests/ui/parser/misspelled-keywords/let-else.stderr new file mode 100644 index 00000000000..826e7de4b11 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/let-else.stderr @@ -0,0 +1,8 @@ +error: expected one of `.`, `;`, `?`, `else`, or an operator, found `elze` + --> $DIR/let-else.rs:2:28 + | +LL | let Some(a) = Some(10) elze {} + | ^^^^ expected one of `.`, `;`, `?`, `else`, or an operator + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/let-mut.rs b/tests/ui/parser/misspelled-keywords/let-mut.rs new file mode 100644 index 00000000000..83228fe8c66 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/let-mut.rs @@ -0,0 +1,4 @@ +fn main() { + let muta a = 10; + //~^ ERROR expected one of +} diff --git a/tests/ui/parser/misspelled-keywords/let-mut.stderr b/tests/ui/parser/misspelled-keywords/let-mut.stderr new file mode 100644 index 00000000000..449f0133d65 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/let-mut.stderr @@ -0,0 +1,8 @@ +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `a` + --> $DIR/let-mut.rs:2:14 + | +LL | let muta a = 10; + | ^ expected one of `:`, `;`, `=`, `@`, or `|` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/let.rs b/tests/ui/parser/misspelled-keywords/let.rs new file mode 100644 index 00000000000..461c3e518db --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/let.rs @@ -0,0 +1,9 @@ +fn main() { + Let a = 10; + //~^ ERROR expected one of +} + +fn code() { + lett a = 10; + //~^ ERROR expected one of +} diff --git a/tests/ui/parser/misspelled-keywords/let.stderr b/tests/ui/parser/misspelled-keywords/let.stderr new file mode 100644 index 00000000000..77aeb21369c --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/let.stderr @@ -0,0 +1,14 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a` + --> $DIR/let.rs:2:9 + | +LL | Let a = 10; + | ^ expected one of 8 possible tokens + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a` + --> $DIR/let.rs:7:10 + | +LL | lett a = 10; + | ^ expected one of 8 possible tokens + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/misspelled-keywords/match.rs b/tests/ui/parser/misspelled-keywords/match.rs new file mode 100644 index 00000000000..a31840a2d71 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/match.rs @@ -0,0 +1,5 @@ +fn main() { + let a = 10; + matche a {} + //~^ ERROR expected one of +} diff --git a/tests/ui/parser/misspelled-keywords/match.stderr b/tests/ui/parser/misspelled-keywords/match.stderr new file mode 100644 index 00000000000..bc3eece1c9d --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/match.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a` + --> $DIR/match.rs:3:12 + | +LL | matche a {} + | ^ expected one of 8 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/mod.rs b/tests/ui/parser/misspelled-keywords/mod.rs new file mode 100644 index 00000000000..24f0101bc5a --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/mod.rs @@ -0,0 +1,4 @@ +mode parser; +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/mod.stderr b/tests/ui/parser/misspelled-keywords/mod.stderr new file mode 100644 index 00000000000..135f70ccfcb --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/mod.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `parser` + --> $DIR/mod.rs:1:6 + | +LL | mode parser; + | ^^^^^^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/pub-fn.rs b/tests/ui/parser/misspelled-keywords/pub-fn.rs new file mode 100644 index 00000000000..50d7129ce51 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/pub-fn.rs @@ -0,0 +1,5 @@ +puB fn code() {} +//~^ ERROR expected one of + +fn main() { +} diff --git a/tests/ui/parser/misspelled-keywords/pub-fn.stderr b/tests/ui/parser/misspelled-keywords/pub-fn.stderr new file mode 100644 index 00000000000..15715514e66 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/pub-fn.stderr @@ -0,0 +1,8 @@ +error: expected one of `#`, `async`, `auto`, `const`, `default`, `enum`, `extern`, `fn`, `gen`, `impl`, `macro_rules`, `macro`, `mod`, `pub`, `safe`, `static`, `struct`, `trait`, `type`, `unsafe`, or `use`, found `puB` + --> $DIR/pub-fn.rs:1:1 + | +LL | puB fn code() {} + | ^^^ expected one of 21 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/ref.rs b/tests/ui/parser/misspelled-keywords/ref.rs new file mode 100644 index 00000000000..76b367ae99b --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/ref.rs @@ -0,0 +1,9 @@ +fn main() { + let a = Some(vec![1, 2]); + match a { + Some(refe list) => println!("{list:?}"), + //~^ ERROR expected one of + //~| ERROR this pattern has 2 fields, + _ => println!("none"), + } +} diff --git a/tests/ui/parser/misspelled-keywords/ref.stderr b/tests/ui/parser/misspelled-keywords/ref.stderr new file mode 100644 index 00000000000..2c23fe7a0af --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/ref.stderr @@ -0,0 +1,20 @@ +error: expected one of `)`, `,`, `@`, or `|`, found `list` + --> $DIR/ref.rs:4:19 + | +LL | Some(refe list) => println!("{list:?}"), + | -^^^^ expected one of `)`, `,`, `@`, or `|` + | | + | help: missing `,` + +error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field + --> $DIR/ref.rs:4:14 + | +LL | Some(refe list) => println!("{list:?}"), + | ^^^^ ^^^^ expected 1 field, found 2 + --> $SRC_DIR/core/src/option.rs:LL:COL + | + = note: tuple variant has 1 field + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0023`. diff --git a/tests/ui/parser/misspelled-keywords/return.rs b/tests/ui/parser/misspelled-keywords/return.rs new file mode 100644 index 00000000000..4bbe55d37da --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/return.rs @@ -0,0 +1,7 @@ +fn code() -> u8 { + let a = 10; + returnn a; + //~^ ERROR expected one of +} + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/return.stderr b/tests/ui/parser/misspelled-keywords/return.stderr new file mode 100644 index 00000000000..94789e7a92c --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/return.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a` + --> $DIR/return.rs:3:13 + | +LL | returnn a; + | ^ expected one of 8 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/static-mut.rs b/tests/ui/parser/misspelled-keywords/static-mut.rs new file mode 100644 index 00000000000..6509f62470a --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/static-mut.rs @@ -0,0 +1,5 @@ +static muta a: u8 = 0; +//~^ ERROR expected one of +//~| ERROR missing type for + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/static-mut.stderr b/tests/ui/parser/misspelled-keywords/static-mut.stderr new file mode 100644 index 00000000000..1e5d25c709e --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/static-mut.stderr @@ -0,0 +1,19 @@ +error: expected one of `:`, `;`, or `=`, found `a` + --> $DIR/static-mut.rs:1:13 + | +LL | static muta a: u8 = 0; + | ^ expected one of `:`, `;`, or `=` + +error: missing type for `static` item + --> $DIR/static-mut.rs:1:12 + | +LL | static muta a: u8 = 0; + | ^ + | +help: provide a type for the item + | +LL | static muta: <type> a: u8 = 0; + | ++++++++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/misspelled-keywords/static.rs b/tests/ui/parser/misspelled-keywords/static.rs new file mode 100644 index 00000000000..240f4f52c8d --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/static.rs @@ -0,0 +1,4 @@ +Static a = 0; +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/static.stderr b/tests/ui/parser/misspelled-keywords/static.stderr new file mode 100644 index 00000000000..698cd47b169 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/static.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `a` + --> $DIR/static.rs:1:8 + | +LL | Static a = 0; + | ^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/struct.rs b/tests/ui/parser/misspelled-keywords/struct.rs new file mode 100644 index 00000000000..0f64dec6f56 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/struct.rs @@ -0,0 +1,4 @@ +Struct Foor { +//~^ ERROR expected one of + hello: String, +} diff --git a/tests/ui/parser/misspelled-keywords/struct.stderr b/tests/ui/parser/misspelled-keywords/struct.stderr new file mode 100644 index 00000000000..8f678f4ad2e --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/struct.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `Foor` + --> $DIR/struct.rs:1:8 + | +LL | Struct Foor { + | ^^^^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/unsafe-fn.rs b/tests/ui/parser/misspelled-keywords/unsafe-fn.rs new file mode 100644 index 00000000000..49a1322ad63 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/unsafe-fn.rs @@ -0,0 +1,4 @@ +unsafee fn code() {} +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr b/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr new file mode 100644 index 00000000000..2013df1c34a --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found keyword `fn` + --> $DIR/unsafe-fn.rs:1:9 + | +LL | unsafee fn code() {} + | ^^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/use.rs b/tests/ui/parser/misspelled-keywords/use.rs new file mode 100644 index 00000000000..f4911654354 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/use.rs @@ -0,0 +1,4 @@ +usee a::b; +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/use.stderr b/tests/ui/parser/misspelled-keywords/use.stderr new file mode 100644 index 00000000000..4ca01dedd6b --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/use.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `a` + --> $DIR/use.rs:1:6 + | +LL | usee a::b; + | ^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/where-clause.rs b/tests/ui/parser/misspelled-keywords/where-clause.rs new file mode 100644 index 00000000000..c03d04d5fee --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/where-clause.rs @@ -0,0 +1,8 @@ +fn code<T>() -> u8 +wheree +//~^ ERROR expected one of + T: Debug, +{ +} + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/where-clause.stderr b/tests/ui/parser/misspelled-keywords/where-clause.stderr new file mode 100644 index 00000000000..4b3f996c112 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/where-clause.stderr @@ -0,0 +1,10 @@ +error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `wheree` + --> $DIR/where-clause.rs:2:1 + | +LL | fn code<T>() -> u8 + | - expected one of 7 possible tokens +LL | wheree + | ^^^^^^ unexpected token + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/while-loop.rs b/tests/ui/parser/misspelled-keywords/while-loop.rs new file mode 100644 index 00000000000..8d19b3c5722 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/while-loop.rs @@ -0,0 +1,7 @@ +fn main() { + whilee a < b { + //~^ ERROR expected one of + + } +} + diff --git a/tests/ui/parser/misspelled-keywords/while-loop.stderr b/tests/ui/parser/misspelled-keywords/while-loop.stderr new file mode 100644 index 00000000000..8147a5de696 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/while-loop.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a` + --> $DIR/while-loop.rs:2:12 + | +LL | whilee a < b { + | ^ expected one of 8 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/while-without-identifiers.rs b/tests/ui/parser/misspelled-keywords/while-without-identifiers.rs new file mode 100644 index 00000000000..203db8306af --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/while-without-identifiers.rs @@ -0,0 +1,4 @@ +fn main() { + whilee 2 > 1 {} + //~^ ERROR expected one of +} diff --git a/tests/ui/parser/misspelled-keywords/while-without-identifiers.stderr b/tests/ui/parser/misspelled-keywords/while-without-identifiers.stderr new file mode 100644 index 00000000000..121e3931314 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/while-without-identifiers.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `2` + --> $DIR/while-without-identifiers.rs:2:12 + | +LL | whilee 2 > 1 {} + | ^ expected one of 8 possible tokens + +error: aborting due to 1 previous error + From e98e88bfdf810d74540fcc0a464608683a7eacc7 Mon Sep 17 00:00:00 2001 From: liushuyu <liushuyu011@gmail.com> Date: Tue, 3 Sep 2024 12:42:57 -0600 Subject: [PATCH 03/13] rustc_codegen_llvm: fix a regression where backchain feature ... ... can not be correctly gated using #[cfg] macro --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 618602ed70f..d55220ba5c3 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -353,9 +353,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> { None } }) - .filter(|feature| { - RUSTC_SPECIAL_FEATURES.contains(feature) || features.contains(&Symbol::intern(feature)) - }) + .filter(|feature| features.contains(&Symbol::intern(feature))) .map(|feature| Symbol::intern(feature)) .collect() } From 6e4c5c10b9b8740cecd62464c616cc82a01bc962 Mon Sep 17 00:00:00 2001 From: liushuyu <liushuyu011@gmail.com> Date: Tue, 3 Sep 2024 13:42:10 -0600 Subject: [PATCH 04/13] tests: add an assembly scanning test for s390x backchain switch --- tests/assembly/s390x-backchain-toggle.rs | 46 ++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/assembly/s390x-backchain-toggle.rs diff --git a/tests/assembly/s390x-backchain-toggle.rs b/tests/assembly/s390x-backchain-toggle.rs new file mode 100644 index 00000000000..8b6d0cf2123 --- /dev/null +++ b/tests/assembly/s390x-backchain-toggle.rs @@ -0,0 +1,46 @@ +//@ revisions: enable-backchain disable-backchain +//@ assembly-output: emit-asm +//@ compile-flags: -O --crate-type=lib --target=s390x-unknown-linux-gnu +//@ needs-llvm-components: systemz +//@[enable-backchain] compile-flags: -Ctarget-feature=+backchain +//@[disable-backchain] compile-flags: -Ctarget-feature=-backchain +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +extern "C" { + fn extern_func(); +} + +// CHECK-LABEL: test_backchain +#[no_mangle] +extern "C" fn test_backchain() -> i32 { + // Here we try to match if backchain register is saved to the parameter area (stored in r15/sp) + // And also if a new parameter area (160 bytes) is allocated for the upcoming function call + // enable-backchain: lgr [[REG1:.*]], %r15 + // enable-backchain-NEXT: aghi %r15, -160 + // enable-backchain: stg [[REG1]], 0(%r15) + // disable-backchain: aghi %r15, -160 + // disable-backchain-NOT: stg %r{{.*}}, 0(%r15) + unsafe { + extern_func(); + } + // enable-backchain-NEXT: brasl %r{{.*}}, extern_func@PLT + // disable-backchain: brasl %r{{.*}}, extern_func@PLT + + // Make sure that the expected return value is written into %r2 (return register): + // enable-backchain-NEXT: lghi %r2, 1 + // disable-backchain: lghi %r2, 0 + #[cfg(target_feature = "backchain")] + { + 1 + } + #[cfg(not(target_feature = "backchain"))] + { + 0 + } + // CHECK: br %r{{.*}} +} From e04ede46bb172c0723c243b97720af18a1959de9 Mon Sep 17 00:00:00 2001 From: Michael Goulet <michael@errs.io> Date: Thu, 5 Sep 2024 08:42:50 -0400 Subject: [PATCH 05/13] Don't store region in CapturedPlace --- compiler/rustc_hir_typeck/src/upvar.rs | 59 ++++++++----------------- compiler/rustc_middle/src/ty/closure.rs | 3 -- 2 files changed, 19 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 5789e60ebbe..7688a63a30a 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -39,7 +39,6 @@ use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::HirId; -use rustc_infer::infer::UpvarRegion; use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind}; use rustc_middle::mir::FakeReadCause; use rustc_middle::traits::ObligationCauseCode; @@ -425,7 +424,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx, upvar_ty, capture, - if needs_ref { Some(closure_env_region) } else { child_capture.region }, + if needs_ref { + closure_env_region + } else { + self.tcx.lifetimes.re_erased + }, ); }, ), @@ -587,7 +590,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!(?captured_place.place, ?upvar_ty, ?capture, ?captured_place.mutability); - apply_capture_kind_on_capture_ty(self.tcx, upvar_ty, capture, captured_place.region) + apply_capture_kind_on_capture_ty( + self.tcx, + upvar_ty, + capture, + self.tcx.lifetimes.re_erased, + ) }) .collect() } @@ -775,13 +783,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(min_cap_list) = root_var_min_capture_list.get_mut(&var_hir_id) else { let mutability = self.determine_capture_mutability(&typeck_results, &place); - let min_cap_list = vec![ty::CapturedPlace { - var_ident, - place, - info: capture_info, - mutability, - region: None, - }]; + let min_cap_list = + vec![ty::CapturedPlace { var_ident, place, info: capture_info, mutability }]; root_var_min_capture_list.insert(var_hir_id, min_cap_list); continue; }; @@ -874,34 +877,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Only need to insert when we don't have an ancestor in the existing min capture list if !ancestor_found { let mutability = self.determine_capture_mutability(&typeck_results, &place); - let captured_place = ty::CapturedPlace { - var_ident, - place, - info: updated_capture_info, - mutability, - region: None, - }; + let captured_place = + ty::CapturedPlace { var_ident, place, info: updated_capture_info, mutability }; min_cap_list.push(captured_place); } } - // For each capture that is determined to be captured by ref, add region info. - for (_, captures) in &mut root_var_min_capture_list { - for capture in captures { - match capture.info.capture_kind { - ty::UpvarCapture::ByRef(_) => { - let PlaceBase::Upvar(upvar_id) = capture.place.base else { - bug!("expected upvar") - }; - let origin = UpvarRegion(upvar_id, closure_span); - let upvar_region = self.next_region_var(origin); - capture.region = Some(upvar_region); - } - _ => (), - } - } - } - debug!( "For closure={:?}, min_captures before sorting={:?}", closure_def_id, root_var_min_capture_list @@ -1195,7 +1176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx, ty, max_capture_info.capture_kind, - Some(self.tcx.lifetimes.re_erased), + self.tcx.lifetimes.re_erased, ) } }; @@ -1217,7 +1198,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx, capture.place.ty(), capture.info.capture_kind, - Some(self.tcx.lifetimes.re_erased), + self.tcx.lifetimes.re_erased, ); // Checks if a capture implements any of the auto traits @@ -1935,13 +1916,11 @@ fn apply_capture_kind_on_capture_ty<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, capture_kind: UpvarCapture, - region: Option<ty::Region<'tcx>>, + region: ty::Region<'tcx>, ) -> Ty<'tcx> { match capture_kind { ty::UpvarCapture::ByValue => ty, - ty::UpvarCapture::ByRef(kind) => { - Ty::new_ref(tcx, region.unwrap(), ty, kind.to_mutbl_lossy()) - } + ty::UpvarCapture::ByRef(kind) => Ty::new_ref(tcx, region, ty, kind.to_mutbl_lossy()), } } diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 8eb3c015679..809801c33e1 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -88,9 +88,6 @@ pub struct CapturedPlace<'tcx> { /// Represents if `place` can be mutated or not. pub mutability: hir::Mutability, - - /// Region of the resulting reference if the upvar is captured by ref. - pub region: Option<ty::Region<'tcx>>, } impl<'tcx> CapturedPlace<'tcx> { From 96837dcade77185d270c90326f000fc057c29a8e Mon Sep 17 00:00:00 2001 From: Ulrik Mikaelsson <ulrik.mikaelsson@gmail.com> Date: Mon, 26 Aug 2024 17:19:45 +0200 Subject: [PATCH 06/13] Adjust doc comment of Condvar::wait_while The existing phrasing implies that a notification must be received for `wait_while` to return. The phrasing is changed to better reflect the behavior. --- library/std/src/sync/condvar.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs index 08d46f356d9..e41cbc1a65c 100644 --- a/library/std/src/sync/condvar.rs +++ b/library/std/src/sync/condvar.rs @@ -195,8 +195,11 @@ impl Condvar { if poisoned { Err(PoisonError::new(guard)) } else { Ok(guard) } } - /// Blocks the current thread until this condition variable receives a - /// notification and the provided condition is false. + /// Blocks the current thread until the provided condition becomes false. + /// + /// `condition` is checked immediately; if not met (returns `true`), this + /// will [`wait`] for the next notification then check again. This repeats + /// until `condition` returns `false`, in which case this function returns. /// /// This function will atomically unlock the mutex specified (represented by /// `guard`) and block the current thread. This means that any calls @@ -210,6 +213,7 @@ impl Condvar { /// poisoned when this thread re-acquires the lock. For more information, /// see information about [poisoning] on the [`Mutex`] type. /// + /// [`wait`]: Self::wait /// [`notify_one`]: Self::notify_one /// [`notify_all`]: Self::notify_all /// [poisoning]: super::Mutex#poisoning From 54ebb9d4897c2f372e3b20f833c2ea4eaf656a0e Mon Sep 17 00:00:00 2001 From: Nikita Popov <npopov@redhat.com> Date: Mon, 2 Sep 2024 15:45:06 +0200 Subject: [PATCH 07/13] Do not request sanitizers for naked functions Naked functions can only contain inline asm, so any instrumentation inserted by sanitizers is illegal. Don't request it. Fixes https://github.com/rust-lang/rust/issues/129224. --- compiler/rustc_codegen_llvm/src/attributes.rs | 46 ++++++++++--------- tests/codegen/naked-asan.rs | 22 +++++++++ 2 files changed, 47 insertions(+), 21 deletions(-) create mode 100644 tests/codegen/naked-asan.rs diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 92a857c2adc..9d4497d73a8 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -411,26 +411,31 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( // the string "false". Now it is disabled by absence of the attribute. to_add.push(llvm::CreateAttrStringValue(cx.llcx, "branch-target-enforcement", "false")); } - } else if llvm_util::get_version() >= (19, 0, 0) { - // For non-naked functions, set branch protection attributes on aarch64. - if let Some(BranchProtection { bti, pac_ret }) = - cx.sess().opts.unstable_opts.branch_protection - { - assert!(cx.sess().target.arch == "aarch64"); - if bti { - to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement")); - } - if let Some(PacRet { leaf, key }) = pac_ret { - to_add.push(llvm::CreateAttrStringValue( - cx.llcx, - "sign-return-address", - if leaf { "all" } else { "non-leaf" }, - )); - to_add.push(llvm::CreateAttrStringValue( - cx.llcx, - "sign-return-address-key", - if key == PAuthKey::A { "a_key" } else { "b_key" }, - )); + } else { + // Do not set sanitizer attributes for naked functions. + to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize)); + + if llvm_util::get_version() >= (19, 0, 0) { + // For non-naked functions, set branch protection attributes on aarch64. + if let Some(BranchProtection { bti, pac_ret }) = + cx.sess().opts.unstable_opts.branch_protection + { + assert!(cx.sess().target.arch == "aarch64"); + if bti { + to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement")); + } + if let Some(PacRet { leaf, key }) = pac_ret { + to_add.push(llvm::CreateAttrStringValue( + cx.llcx, + "sign-return-address", + if leaf { "all" } else { "non-leaf" }, + )); + to_add.push(llvm::CreateAttrStringValue( + cx.llcx, + "sign-return-address-key", + if key == PAuthKey::A { "a_key" } else { "b_key" }, + )); + } } } } @@ -485,7 +490,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( if let Some(backchain) = backchain_attr(cx) { to_add.push(backchain); } - to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize)); to_add.extend(patchable_function_entry_attrs(cx, codegen_fn_attrs.patchable_function_entry)); // Always annotate functions with the target-cpu they are compiled for. diff --git a/tests/codegen/naked-asan.rs b/tests/codegen/naked-asan.rs new file mode 100644 index 00000000000..a45b95780f7 --- /dev/null +++ b/tests/codegen/naked-asan.rs @@ -0,0 +1,22 @@ +// Make sure we do not request sanitizers for naked functions. + +//@ only-x86_64 +//@ needs-sanitizer-address +//@ compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static + +#![crate_type = "lib"] +#![no_std] +#![feature(abi_x86_interrupt, naked_functions)] + +// CHECK: define x86_intrcc void @page_fault_handler(ptr {{.*}}%0, i64 {{.*}}%1){{.*}}#[[ATTRS:[0-9]+]] { +// CHECK-NOT: memcpy +#[naked] +#[no_mangle] +pub extern "x86-interrupt" fn page_fault_handler(_: u64, _: u64) { + unsafe { + core::arch::asm!("ud2", options(noreturn)); + } +} + +// CHECK: #[[ATTRS]] = +// CHECK-NOT: sanitize_address From e38764d73b84eb625102233623e79f36515345e2 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko <GrigorenkoPV@ya.ru> Date: Sun, 1 Sep 2024 01:14:06 +0300 Subject: [PATCH 08/13] elided_named_lifetimes: unify lint def & pass MissingLifetimeKind --- .../rustc_lint/src/context/diagnostics.rs | 23 +++++++++++-------- compiler/rustc_lint_defs/src/lib.rs | 17 ++++++++------ compiler/rustc_resolve/src/late.rs | 14 +++++++---- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index fd43afa1743..b1c1e4f4dd6 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -8,7 +8,7 @@ use rustc_errors::{ elided_lifetime_in_path_suggestion, Applicability, Diag, DiagArgValue, LintDiagnostic, }; use rustc_middle::middle::stability; -use rustc_session::lint::BuiltinLintDiag; +use rustc_session::lint::{BuiltinLintDiag, ElidedLifetimeResolution}; use rustc_session::Session; use rustc_span::symbol::kw; use rustc_span::BytePos; @@ -442,15 +442,18 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => { lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag) } - BuiltinLintDiag::ElidedIsStatic { elided } => { - lints::ElidedNamedLifetime { elided, name: kw::StaticLifetime, named_declaration: None } - .decorate_lint(diag) - } - BuiltinLintDiag::ElidedIsParam { elided, param: (param_name, param_span) } => { - lints::ElidedNamedLifetime { - elided, - name: param_name, - named_declaration: Some(param_span), + BuiltinLintDiag::ElidedNamedLifetimes { elided: (elided, _kind), resolution } => { + match resolution { + ElidedLifetimeResolution::Static => lints::ElidedNamedLifetime { + elided, + name: kw::StaticLifetime, + named_declaration: None, + }, + ElidedLifetimeResolution::Param(name, declaration) => lints::ElidedNamedLifetime { + elided, + name, + named_declaration: Some(declaration), + }, } .decorate_lint(diag) } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 6ee33041623..9a72e4f6739 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -10,7 +10,7 @@ use rustc_data_structures::stable_hasher::{ }; use rustc_error_messages::{DiagMessage, MultiSpan}; use rustc_hir::def::Namespace; -use rustc_hir::{HashStableContext, HirId}; +use rustc_hir::{HashStableContext, HirId, MissingLifetimeKind}; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::edition::Edition; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent}; @@ -556,6 +556,12 @@ pub enum DeprecatedSinceKind { InVersion(String), } +#[derive(Debug)] +pub enum ElidedLifetimeResolution { + Static, + Param(Symbol, Span), +} + // This could be a closure, but then implementing derive trait // becomes hacky (and it gets allocated). #[derive(Debug)] @@ -568,12 +574,9 @@ pub enum BuiltinLintDiag { }, MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), ElidedLifetimesInPaths(usize, Span, bool, Span), - ElidedIsStatic { - elided: Span, - }, - ElidedIsParam { - elided: Span, - param: (Symbol, Span), + ElidedNamedLifetimes { + elided: (Span, MissingLifetimeKind), + resolution: ElidedLifetimeResolution, }, UnknownCrateTypes { span: Span, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 79c42456cf8..917cb81aa51 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2062,7 +2062,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { lint::builtin::ELIDED_NAMED_LIFETIMES, missing.id_for_lint, missing.span, - BuiltinLintDiag::ElidedIsStatic { elided: missing.span }, + BuiltinLintDiag::ElidedNamedLifetimes { + elided: (missing.span, missing.kind), + resolution: lint::ElidedLifetimeResolution::Static, + }, ); } } @@ -2072,9 +2075,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { lint::builtin::ELIDED_NAMED_LIFETIMES, missing.id_for_lint, missing.span, - BuiltinLintDiag::ElidedIsParam { - elided: missing.span, - param: (tcx.item_name(param.into()), tcx.source_span(param)), + BuiltinLintDiag::ElidedNamedLifetimes { + elided: (missing.span, missing.kind), + resolution: lint::ElidedLifetimeResolution::Param( + tcx.item_name(param.into()), + tcx.source_span(param), + ), }, ); } From dcfc71310d560a77b4813f60511c2b15c5125b80 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko <GrigorenkoPV@ya.ru> Date: Sun, 1 Sep 2024 03:42:18 +0300 Subject: [PATCH 09/13] elided_named_lifetimes: add suggestions --- compiler/rustc_lint/messages.ftl | 2 + .../rustc_lint/src/context/diagnostics.rs | 44 ++++++++++++------- compiler/rustc_lint/src/lints.rs | 2 +- .../async-await/issues/issue-63388-1.stderr | 4 ++ .../type-dependent/issue-71348.full.stderr | 4 ++ .../type-dependent/issue-71348.min.stderr | 4 ++ .../consts/min_const_fn/min_const_fn.stderr | 9 ++++ .../ui/impl-trait/impl-fn-hrtb-bounds.stderr | 4 ++ .../impl-fn-predefined-lifetimes.stderr | 4 ++ .../rpit-assoc-pair-with-lifetime.stderr | 4 ++ ...urn-type-requires-explicit-lifetime.stderr | 4 ++ ...-existing-name-if-else-using-impl-3.stderr | 4 ++ .../example-from-issue48686.stderr | 4 ++ .../missing-lifetime-kind.stderr | 19 ++++++++ .../not-tied-to-crate.stderr | 8 ++++ .../lint/elided-named-lifetimes/static.stderr | 19 ++++++++ .../object-lifetime-default-elision.stderr | 4 ++ .../ignore-non-reference-lifetimes.stderr | 9 ++++ tests/ui/self/self_lifetime-async.stderr | 9 ++++ tests/ui/self/self_lifetime.stderr | 9 ++++ .../impl-trait-missing-lifetime-gated.stderr | 4 ++ .../missing-lifetimes-in-signature.stderr | 4 ++ .../missing_lifetime_bound.stderr | 4 ++ 23 files changed, 166 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 759320b9eb6..fe211355ac3 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -256,6 +256,8 @@ lint_elided_named_lifetime = elided lifetime has a name .label_elided = this elided lifetime gets resolved as `{$name}` .label_named = lifetime `{$name}` declared here +lint_elided_named_lifetime_suggestion = consider specifying it explicitly + lint_enum_intrinsics_mem_discriminant = the return value of `mem::discriminant` is unspecified when called with a non-enum type .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index b1c1e4f4dd6..a1a371a032e 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -7,6 +7,7 @@ use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; use rustc_errors::{ elided_lifetime_in_path_suggestion, Applicability, Diag, DiagArgValue, LintDiagnostic, }; +use rustc_hir::MissingLifetimeKind; use rustc_middle::middle::stability; use rustc_session::lint::{BuiltinLintDiag, ElidedLifetimeResolution}; use rustc_session::Session; @@ -14,7 +15,8 @@ use rustc_span::symbol::kw; use rustc_span::BytePos; use tracing::debug; -use crate::lints; +use crate::fluent_generated; +use crate::lints::{self, ElidedNamedLifetime}; mod check_cfg; @@ -442,20 +444,32 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => { lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag) } - BuiltinLintDiag::ElidedNamedLifetimes { elided: (elided, _kind), resolution } => { - match resolution { - ElidedLifetimeResolution::Static => lints::ElidedNamedLifetime { - elided, - name: kw::StaticLifetime, - named_declaration: None, - }, - ElidedLifetimeResolution::Param(name, declaration) => lints::ElidedNamedLifetime { - elided, - name, - named_declaration: Some(declaration), - }, - } - .decorate_lint(diag) + BuiltinLintDiag::ElidedNamedLifetimes { elided: (span, kind), resolution } => { + let (name, named_declaration) = match resolution { + ElidedLifetimeResolution::Static => (kw::StaticLifetime, None), + ElidedLifetimeResolution::Param(name, declaration) => (name, Some(declaration)), + }; + ElidedNamedLifetime { span, name, named_declaration }.decorate_lint(diag); + + let (applicability, suggestion) = match kind { + MissingLifetimeKind::Underscore => { + (Applicability::MachineApplicable, format!("{name}")) + } + MissingLifetimeKind::Ampersand => { + (Applicability::MachineApplicable, format!("&{name} ")) + } + MissingLifetimeKind::Comma => (Applicability::Unspecified, format!("<{name}, ")), + MissingLifetimeKind::Brackets => ( + Applicability::Unspecified, + format!("{}<{name}>", sess.source_map().span_to_snippet(span).unwrap()), + ), + }; + diag.span_suggestion_verbose( + span, + fluent_generated::lint_elided_named_lifetime_suggestion, + suggestion, + applicability, + ); } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 9050f36acba..426d671f8e0 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2627,7 +2627,7 @@ pub(crate) struct ElidedLifetimesInPaths { #[diag(lint_elided_named_lifetime)] pub(crate) struct ElidedNamedLifetime { #[label(lint_label_elided)] - pub elided: Span, + pub span: Span, pub name: Symbol, #[label(lint_label_named)] pub named_declaration: Option<Span>, diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr index ef74bfe3237..c8b55977faf 100644 --- a/tests/ui/async-await/issues/issue-63388-1.stderr +++ b/tests/ui/async-await/issues/issue-63388-1.stderr @@ -8,6 +8,10 @@ LL | ) -> &dyn Foo | ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | ) -> &'a dyn Foo + | ~~~ error[E0621]: explicit lifetime required in the type of `foo` --> $DIR/issue-63388-1.rs:13:5 diff --git a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr index 177ff20fbf9..8d1c1ea23a8 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr @@ -5,6 +5,10 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Ta | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<'a, N>>::Target + | ~~~~ warning: 1 warning emitted diff --git a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr index 5aee282952a..57da3ce21ce 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -5,6 +5,10 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Ta | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<'a, N>>::Target + | ~~~~ error: `&'static str` is forbidden as the type of a const generic parameter --> $DIR/issue-71348.rs:10:24 diff --git a/tests/ui/consts/min_const_fn/min_const_fn.stderr b/tests/ui/consts/min_const_fn/min_const_fn.stderr index 4b348a182b8..b7db403ad16 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn.stderr @@ -8,6 +8,10 @@ LL | const fn get_lt(&'a self) -> &T { &self.0 } | ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | const fn get_lt(&'a self) -> &'a T { &self.0 } + | ~~~ warning: elided lifetime has a name --> $DIR/min_const_fn.rs:48:42 @@ -17,6 +21,11 @@ LL | impl<'a, T> Foo<T> { ... LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } | ^ this elided lifetime gets resolved as `'a` + | +help: consider specifying it explicitly + | +LL | const fn get_mut_lt(&'a mut self) -> &'a mut T { &mut self.0 } + | ~~~ error[E0493]: destructor of `Foo<T>` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:37:25 diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr index d0f8f7689d1..ccea9d5e6e9 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -17,6 +17,10 @@ LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { + | ~~ error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/impl-fn-hrtb-bounds.rs:4:41 diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr index 50a9f3ebeab..a60f3986843 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -5,6 +5,10 @@ LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) { + | ~~ error[E0792]: expected generic lifetime parameter, found `'_` --> $DIR/impl-fn-predefined-lifetimes.rs:7:9 diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr index bff3ffd934a..ec0f0708b15 100644 --- a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr @@ -5,6 +5,10 @@ LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item = | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item = (u32, &'a u32)> { + | ~~~ warning: 1 warning emitted diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index f835d2655bb..a7512158661 100644 --- a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -114,6 +114,10 @@ LL | fn m<'a>(_: &'a Foo<'a>) -> &str { "" } | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn m<'a>(_: &'a Foo<'a>) -> &'a str { "" } + | ~~~ error: aborting due to 7 previous errors; 1 warning emitted diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr index 2d5d4fb0e72..0943e0cc0d9 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -7,6 +7,10 @@ LL | fn foo<'a>(&'a self, x: &i32) -> &i32 { | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn foo<'a>(&'a self, x: &i32) -> &'a i32 { + | ~~~ error[E0621]: explicit lifetime required in the type of `x` --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:9:36 diff --git a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr index 8c5426a60cb..5af5123c032 100644 --- a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr +++ b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr @@ -9,6 +9,10 @@ note: the lint level is defined here | LL | #![deny(elided_named_lifetimes)] | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider specifying it explicitly + | +LL | pub fn get_mut(&'static self, x: &mut u8) -> &'static mut u8 { + | ~~~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr index 249ae146b16..6abaad7f5d2 100644 --- a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr +++ b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr @@ -11,6 +11,10 @@ note: the lint level is defined here | LL | #![deny(elided_named_lifetimes)] | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider specifying it explicitly + | +LL | fn ampersand<'a>(x: &'a u8) -> &'a u8 { + | ~~~ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:10:31 @@ -19,6 +23,11 @@ LL | fn brackets<'a>(x: &'a u8) -> Brackets { | -- ^^^^^^^^ this elided lifetime gets resolved as `'a` | | | lifetime `'a` declared here + | +help: consider specifying it explicitly + | +LL | fn brackets<'a>(x: &'a u8) -> Brackets<'a> { + | ~~~~~~~~~~~~ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:17:33 @@ -27,6 +36,11 @@ LL | fn comma<'a>(x: &'a u8) -> Comma<u8> { | -- ^ this elided lifetime gets resolved as `'a` | | | lifetime `'a` declared here + | +help: consider specifying it explicitly + | +LL | fn comma<'a>(x: &'a u8) -> Comma<'a, u8> { + | ~~~~ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:22:34 @@ -35,6 +49,11 @@ LL | fn underscore<'a>(x: &'a u8) -> &'_ u8 { | -- ^^ this elided lifetime gets resolved as `'a` | | | lifetime `'a` declared here + | +help: consider specifying it explicitly + | +LL | fn underscore<'a>(x: &'a u8) -> &'a u8 { + | ~~ error: aborting due to 4 previous errors diff --git a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr index c465aab1a03..cbc1b862caa 100644 --- a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr +++ b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr @@ -9,6 +9,10 @@ note: the lint level is defined here | LL | #[warn(elided_named_lifetimes)] | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider specifying it explicitly + | +LL | fn bar(x: &'static u8) -> &'static u8 { + | ~~~~~~~~ error: elided lifetime has a name --> $DIR/not-tied-to-crate.rs:11:31 @@ -21,6 +25,10 @@ note: the lint level is defined here | LL | #[deny(elided_named_lifetimes)] | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider specifying it explicitly + | +LL | fn baz(x: &'static u8) -> &'static u8 { + | ~~~~~~~~ error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/lint/elided-named-lifetimes/static.stderr b/tests/ui/lint/elided-named-lifetimes/static.stderr index d2e9776cb4f..6c3944e5ea5 100644 --- a/tests/ui/lint/elided-named-lifetimes/static.stderr +++ b/tests/ui/lint/elided-named-lifetimes/static.stderr @@ -9,24 +9,43 @@ note: the lint level is defined here | LL | #![deny(elided_named_lifetimes)] | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider specifying it explicitly + | +LL | fn ampersand(x: &'static u8) -> &'static u8 { + | ~~~~~~~~ error: elided lifetime has a name --> $DIR/static.rs:23:32 | LL | fn brackets(x: &'static u8) -> Brackets { | ^^^^^^^^ this elided lifetime gets resolved as `'static` + | +help: consider specifying it explicitly + | +LL | fn brackets(x: &'static u8) -> Brackets<'static> { + | ~~~~~~~~~~~~~~~~~ error: elided lifetime has a name --> $DIR/static.rs:30:34 | LL | fn comma(x: &'static u8) -> Comma<u8> { | ^ this elided lifetime gets resolved as `'static` + | +help: consider specifying it explicitly + | +LL | fn comma(x: &'static u8) -> Comma<'static, u8> { + | ~~~~~~~~~ error: elided lifetime has a name --> $DIR/static.rs:35:35 | LL | fn underscore(x: &'static u8) -> &'_ u8 { | ^^ this elided lifetime gets resolved as `'static` + | +help: consider specifying it explicitly + | +LL | fn underscore(x: &'static u8) -> &'static u8 { + | ~~~~~~~ error: aborting due to 4 previous errors diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr index b44a184c684..7d239a54eda 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -7,6 +7,10 @@ LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait { | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &'a dyn SomeTrait { + | ~~~ error: lifetime may not live long enough --> $DIR/object-lifetime-default-elision.rs:73:5 diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr index 4465dbae529..460d2ce2cc9 100644 --- a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr +++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr @@ -5,12 +5,21 @@ LL | fn a<'a>(self: Self, a: &'a str) -> &str { | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn a<'a>(self: Self, a: &'a str) -> &'a str { + | ~~~ warning: elided lifetime has a name --> $DIR/ignore-non-reference-lifetimes.rs:10:44 | LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &str { | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | +help: consider specifying it explicitly + | +LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &'a str { + | ~~~ warning: 2 warnings emitted diff --git a/tests/ui/self/self_lifetime-async.stderr b/tests/ui/self/self_lifetime-async.stderr index 32de3fd18c9..fd167cf392f 100644 --- a/tests/ui/self/self_lifetime-async.stderr +++ b/tests/ui/self/self_lifetime-async.stderr @@ -7,12 +7,21 @@ LL | async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } | lifetime `'b` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | async fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } + | ~~~ warning: elided lifetime has a name --> $DIR/self_lifetime-async.rs:12:52 | LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | +help: consider specifying it explicitly + | +LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg } + | ~~~ warning: 2 warnings emitted diff --git a/tests/ui/self/self_lifetime.stderr b/tests/ui/self/self_lifetime.stderr index cd8f4d8adf8..52189084f04 100644 --- a/tests/ui/self/self_lifetime.stderr +++ b/tests/ui/self/self_lifetime.stderr @@ -7,12 +7,21 @@ LL | fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } | lifetime `'b` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } + | ~~~ warning: elided lifetime has a name --> $DIR/self_lifetime.rs:13:46 | LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | +help: consider specifying it explicitly + | +LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg } + | ~~~ warning: 2 warnings emitted diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr index 30f4509d49d..92f774767c8 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -131,6 +131,10 @@ LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &T) { | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &'a T) { + | ~~~ error[E0658]: anonymous lifetimes in `impl Trait` are unstable --> $DIR/impl-trait-missing-lifetime-gated.rs:6:35 diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index ea01dcd5020..baa5fa949ec 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -13,6 +13,10 @@ LL | fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a + 'a + | ~~ error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not appear in bounds --> $DIR/missing-lifetimes-in-signature.rs:19:5 diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr index e2c21f1636b..73a362d28e7 100644 --- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr @@ -7,6 +7,10 @@ LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x } | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn defining<'a, T>(x: &'a i32) -> Opaque<'a, T> { x } + | ~~~~ error[E0700]: hidden type for `Opaque2<T>` captures lifetime that does not appear in bounds --> $DIR/missing_lifetime_bound.rs:5:47 From 547db4a4b7c9bfea52b519d0095510126a0a1cb0 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko <GrigorenkoPV@ya.ru> Date: Sun, 1 Sep 2024 04:08:55 +0300 Subject: [PATCH 10/13] elided_named_lifetimes: manually implement `LintDiagnostic` --- compiler/rustc_lint/messages.ftl | 3 +- .../rustc_lint/src/context/diagnostics.rs | 32 +++---------- compiler/rustc_lint/src/lints.rs | 47 ++++++++++++++++--- .../async-await/issues/issue-63388-1.stderr | 2 +- .../type-dependent/issue-71348.full.stderr | 2 +- .../type-dependent/issue-71348.min.stderr | 2 +- .../consts/min_const_fn/min_const_fn.stderr | 4 +- .../rpit-assoc-pair-with-lifetime.stderr | 2 +- ...urn-type-requires-explicit-lifetime.stderr | 2 +- ...-existing-name-if-else-using-impl-3.stderr | 2 +- .../example-from-issue48686.stderr | 2 +- .../missing-lifetime-kind.stderr | 6 +-- .../not-tied-to-crate.stderr | 4 +- .../lint/elided-named-lifetimes/static.stderr | 6 +-- .../object-lifetime-default-elision.stderr | 2 +- .../ignore-non-reference-lifetimes.stderr | 4 +- tests/ui/self/self_lifetime-async.stderr | 4 +- tests/ui/self/self_lifetime.stderr | 4 +- .../impl-trait-missing-lifetime-gated.stderr | 2 +- .../missing_lifetime_bound.stderr | 2 +- 20 files changed, 75 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index fe211355ac3..5a368f4ed9a 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -255,8 +255,7 @@ lint_duplicate_matcher_binding = duplicate matcher binding lint_elided_named_lifetime = elided lifetime has a name .label_elided = this elided lifetime gets resolved as `{$name}` .label_named = lifetime `{$name}` declared here - -lint_elided_named_lifetime_suggestion = consider specifying it explicitly + .suggestion = consider specifying it explicitly lint_enum_intrinsics_mem_discriminant = the return value of `mem::discriminant` is unspecified when called with a non-enum type diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index a1a371a032e..de34b9bebe9 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -7,7 +7,6 @@ use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; use rustc_errors::{ elided_lifetime_in_path_suggestion, Applicability, Diag, DiagArgValue, LintDiagnostic, }; -use rustc_hir::MissingLifetimeKind; use rustc_middle::middle::stability; use rustc_session::lint::{BuiltinLintDiag, ElidedLifetimeResolution}; use rustc_session::Session; @@ -15,7 +14,6 @@ use rustc_span::symbol::kw; use rustc_span::BytePos; use tracing::debug; -use crate::fluent_generated; use crate::lints::{self, ElidedNamedLifetime}; mod check_cfg; @@ -445,31 +443,15 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag) } BuiltinLintDiag::ElidedNamedLifetimes { elided: (span, kind), resolution } => { - let (name, named_declaration) = match resolution { - ElidedLifetimeResolution::Static => (kw::StaticLifetime, None), - ElidedLifetimeResolution::Param(name, declaration) => (name, Some(declaration)), - }; - ElidedNamedLifetime { span, name, named_declaration }.decorate_lint(diag); - - let (applicability, suggestion) = match kind { - MissingLifetimeKind::Underscore => { - (Applicability::MachineApplicable, format!("{name}")) + match resolution { + ElidedLifetimeResolution::Static => { + ElidedNamedLifetime { span, kind, name: kw::StaticLifetime, declaration: None } } - MissingLifetimeKind::Ampersand => { - (Applicability::MachineApplicable, format!("&{name} ")) + ElidedLifetimeResolution::Param(name, declaration) => { + ElidedNamedLifetime { span, kind, name, declaration: Some(declaration) } } - MissingLifetimeKind::Comma => (Applicability::Unspecified, format!("<{name}, ")), - MissingLifetimeKind::Brackets => ( - Applicability::Unspecified, - format!("{}<{name}>", sess.source_map().span_to_snippet(span).unwrap()), - ), - }; - diag.span_suggestion_verbose( - span, - fluent_generated::lint_elided_named_lifetime_suggestion, - suggestion, - applicability, - ); + } + .decorate_lint(diag) } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 426d671f8e0..693f1b22587 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -9,7 +9,7 @@ use rustc_errors::{ }; use rustc_hir::def::Namespace; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir}; +use rustc_hir::{self as hir, MissingLifetimeKind}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::inhabitedness::InhabitedPredicate; use rustc_middle::ty::{Clause, PolyExistentialTraitRef, Ty, TyCtxt}; @@ -2623,14 +2623,49 @@ pub(crate) struct ElidedLifetimesInPaths { pub subdiag: ElidedLifetimeInPathSubdiag, } -#[derive(LintDiagnostic)] -#[diag(lint_elided_named_lifetime)] pub(crate) struct ElidedNamedLifetime { - #[label(lint_label_elided)] pub span: Span, + pub kind: MissingLifetimeKind, pub name: Symbol, - #[label(lint_label_named)] - pub named_declaration: Option<Span>, + pub declaration: Option<Span>, +} + +impl<G: EmissionGuarantee> LintDiagnostic<'_, G> for ElidedNamedLifetime { + fn decorate_lint(self, diag: &mut rustc_errors::Diag<'_, G>) { + let Self { span, kind, name, declaration } = self; + diag.primary_message(fluent::lint_elided_named_lifetime); + diag.arg("name", name); + diag.span_label(span, fluent::lint_label_elided); + if let Some(declaration) = declaration { + diag.span_label(declaration, fluent::lint_label_named); + } + match kind { + MissingLifetimeKind::Underscore => diag.span_suggestion_verbose( + span, + fluent::lint_suggestion, + format!("{name}"), + Applicability::MachineApplicable, + ), + MissingLifetimeKind::Ampersand => diag.span_suggestion_verbose( + span.shrink_to_hi(), + fluent::lint_suggestion, + format!("{name} "), + Applicability::MachineApplicable, + ), + MissingLifetimeKind::Comma => diag.span_suggestion_verbose( + span.shrink_to_hi(), + fluent::lint_suggestion, + format!("{name}, "), + Applicability::MachineApplicable, + ), + MissingLifetimeKind::Brackets => diag.span_suggestion_verbose( + span.shrink_to_hi(), + fluent::lint_suggestion, + format!("<{name}>"), + Applicability::MachineApplicable, + ), + }; + } } #[derive(LintDiagnostic)] diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr index c8b55977faf..713e4e4dcf5 100644 --- a/tests/ui/async-await/issues/issue-63388-1.stderr +++ b/tests/ui/async-await/issues/issue-63388-1.stderr @@ -11,7 +11,7 @@ LL | ) -> &dyn Foo help: consider specifying it explicitly | LL | ) -> &'a dyn Foo - | ~~~ + | ++ error[E0621]: explicit lifetime required in the type of `foo` --> $DIR/issue-63388-1.rs:13:5 diff --git a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr index 8d1c1ea23a8..394259ce55d 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr @@ -8,7 +8,7 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Ta help: consider specifying it explicitly | LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<'a, N>>::Target - | ~~~~ + | +++ warning: 1 warning emitted diff --git a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr index 57da3ce21ce..0f0d75dbac1 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -8,7 +8,7 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Ta help: consider specifying it explicitly | LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<'a, N>>::Target - | ~~~~ + | +++ error: `&'static str` is forbidden as the type of a const generic parameter --> $DIR/issue-71348.rs:10:24 diff --git a/tests/ui/consts/min_const_fn/min_const_fn.stderr b/tests/ui/consts/min_const_fn/min_const_fn.stderr index b7db403ad16..1e88a908af0 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn.stderr @@ -11,7 +11,7 @@ LL | const fn get_lt(&'a self) -> &T { &self.0 } help: consider specifying it explicitly | LL | const fn get_lt(&'a self) -> &'a T { &self.0 } - | ~~~ + | ++ warning: elided lifetime has a name --> $DIR/min_const_fn.rs:48:42 @@ -25,7 +25,7 @@ LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } help: consider specifying it explicitly | LL | const fn get_mut_lt(&'a mut self) -> &'a mut T { &mut self.0 } - | ~~~ + | ++ error[E0493]: destructor of `Foo<T>` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:37:25 diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr index ec0f0708b15..6eea25b4fc8 100644 --- a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr @@ -8,7 +8,7 @@ LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item = help: consider specifying it explicitly | LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item = (u32, &'a u32)> { - | ~~~ + | ++ warning: 1 warning emitted diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index a7512158661..1339c644f53 100644 --- a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -117,7 +117,7 @@ LL | fn m<'a>(_: &'a Foo<'a>) -> &str { "" } help: consider specifying it explicitly | LL | fn m<'a>(_: &'a Foo<'a>) -> &'a str { "" } - | ~~~ + | ++ error: aborting due to 7 previous errors; 1 warning emitted diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr index 0943e0cc0d9..144f9454513 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -10,7 +10,7 @@ LL | fn foo<'a>(&'a self, x: &i32) -> &i32 { help: consider specifying it explicitly | LL | fn foo<'a>(&'a self, x: &i32) -> &'a i32 { - | ~~~ + | ++ error[E0621]: explicit lifetime required in the type of `x` --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:9:36 diff --git a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr index 5af5123c032..2d8c6e99643 100644 --- a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr +++ b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr @@ -12,7 +12,7 @@ LL | #![deny(elided_named_lifetimes)] help: consider specifying it explicitly | LL | pub fn get_mut(&'static self, x: &mut u8) -> &'static mut u8 { - | ~~~~~~~~ + | +++++++ error: aborting due to 1 previous error diff --git a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr index 6abaad7f5d2..834292d103d 100644 --- a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr +++ b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr @@ -14,7 +14,7 @@ LL | #![deny(elided_named_lifetimes)] help: consider specifying it explicitly | LL | fn ampersand<'a>(x: &'a u8) -> &'a u8 { - | ~~~ + | ++ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:10:31 @@ -27,7 +27,7 @@ LL | fn brackets<'a>(x: &'a u8) -> Brackets { help: consider specifying it explicitly | LL | fn brackets<'a>(x: &'a u8) -> Brackets<'a> { - | ~~~~~~~~~~~~ + | ++++ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:17:33 @@ -40,7 +40,7 @@ LL | fn comma<'a>(x: &'a u8) -> Comma<u8> { help: consider specifying it explicitly | LL | fn comma<'a>(x: &'a u8) -> Comma<'a, u8> { - | ~~~~ + | +++ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:22:34 diff --git a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr index cbc1b862caa..3c01375d501 100644 --- a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr +++ b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr @@ -12,7 +12,7 @@ LL | #[warn(elided_named_lifetimes)] help: consider specifying it explicitly | LL | fn bar(x: &'static u8) -> &'static u8 { - | ~~~~~~~~ + | +++++++ error: elided lifetime has a name --> $DIR/not-tied-to-crate.rs:11:31 @@ -28,7 +28,7 @@ LL | #[deny(elided_named_lifetimes)] help: consider specifying it explicitly | LL | fn baz(x: &'static u8) -> &'static u8 { - | ~~~~~~~~ + | +++++++ error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/lint/elided-named-lifetimes/static.stderr b/tests/ui/lint/elided-named-lifetimes/static.stderr index 6c3944e5ea5..fa2a2d3460f 100644 --- a/tests/ui/lint/elided-named-lifetimes/static.stderr +++ b/tests/ui/lint/elided-named-lifetimes/static.stderr @@ -12,7 +12,7 @@ LL | #![deny(elided_named_lifetimes)] help: consider specifying it explicitly | LL | fn ampersand(x: &'static u8) -> &'static u8 { - | ~~~~~~~~ + | +++++++ error: elided lifetime has a name --> $DIR/static.rs:23:32 @@ -23,7 +23,7 @@ LL | fn brackets(x: &'static u8) -> Brackets { help: consider specifying it explicitly | LL | fn brackets(x: &'static u8) -> Brackets<'static> { - | ~~~~~~~~~~~~~~~~~ + | +++++++++ error: elided lifetime has a name --> $DIR/static.rs:30:34 @@ -34,7 +34,7 @@ LL | fn comma(x: &'static u8) -> Comma<u8> { help: consider specifying it explicitly | LL | fn comma(x: &'static u8) -> Comma<'static, u8> { - | ~~~~~~~~~ + | ++++++++ error: elided lifetime has a name --> $DIR/static.rs:35:35 diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr index 7d239a54eda..f8ed92111a9 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -10,7 +10,7 @@ LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait { help: consider specifying it explicitly | LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &'a dyn SomeTrait { - | ~~~ + | ++ error: lifetime may not live long enough --> $DIR/object-lifetime-default-elision.rs:73:5 diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr index 460d2ce2cc9..13cc3a431a5 100644 --- a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr +++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr @@ -8,7 +8,7 @@ LL | fn a<'a>(self: Self, a: &'a str) -> &str { help: consider specifying it explicitly | LL | fn a<'a>(self: Self, a: &'a str) -> &'a str { - | ~~~ + | ++ warning: elided lifetime has a name --> $DIR/ignore-non-reference-lifetimes.rs:10:44 @@ -19,7 +19,7 @@ LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &str { help: consider specifying it explicitly | LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &'a str { - | ~~~ + | ++ warning: 2 warnings emitted diff --git a/tests/ui/self/self_lifetime-async.stderr b/tests/ui/self/self_lifetime-async.stderr index fd167cf392f..2892d790ac7 100644 --- a/tests/ui/self/self_lifetime-async.stderr +++ b/tests/ui/self/self_lifetime-async.stderr @@ -10,7 +10,7 @@ LL | async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } help: consider specifying it explicitly | LL | async fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } - | ~~~ + | ++ warning: elided lifetime has a name --> $DIR/self_lifetime-async.rs:12:52 @@ -21,7 +21,7 @@ LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } help: consider specifying it explicitly | LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg } - | ~~~ + | ++ warning: 2 warnings emitted diff --git a/tests/ui/self/self_lifetime.stderr b/tests/ui/self/self_lifetime.stderr index 52189084f04..ceb0ce345a3 100644 --- a/tests/ui/self/self_lifetime.stderr +++ b/tests/ui/self/self_lifetime.stderr @@ -10,7 +10,7 @@ LL | fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } help: consider specifying it explicitly | LL | fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } - | ~~~ + | ++ warning: elided lifetime has a name --> $DIR/self_lifetime.rs:13:46 @@ -21,7 +21,7 @@ LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } help: consider specifying it explicitly | LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg } - | ~~~ + | ++ warning: 2 warnings emitted diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr index 92f774767c8..3744dd9f996 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -134,7 +134,7 @@ LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &T) { help: consider specifying it explicitly | LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &'a T) { - | ~~~ + | ++ error[E0658]: anonymous lifetimes in `impl Trait` are unstable --> $DIR/impl-trait-missing-lifetime-gated.rs:6:35 diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr index 73a362d28e7..376e58ef9e0 100644 --- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr @@ -10,7 +10,7 @@ LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x } help: consider specifying it explicitly | LL | fn defining<'a, T>(x: &'a i32) -> Opaque<'a, T> { x } - | ~~~~ + | +++ error[E0700]: hidden type for `Opaque2<T>` captures lifetime that does not appear in bounds --> $DIR/missing_lifetime_bound.rs:5:47 From 9e2d264fa251f98780084382a071e10a123770d6 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko <GrigorenkoPV@ya.ru> Date: Sun, 1 Sep 2024 16:49:55 +0300 Subject: [PATCH 11/13] Hack around a conflict with `clippy::needless_lifetimes` --- compiler/rustc_lint/src/lints.rs | 7 +++++++ .../async-await/issues/issue-63388-1.stderr | 4 ---- .../type-dependent/issue-71348.full.stderr | 4 ---- .../type-dependent/issue-71348.min.stderr | 4 ---- .../consts/min_const_fn/min_const_fn.stderr | 9 --------- .../ui/impl-trait/impl-fn-hrtb-bounds.stderr | 4 ---- .../impl-fn-predefined-lifetimes.stderr | 4 ---- .../rpit-assoc-pair-with-lifetime.stderr | 4 ---- ...urn-type-requires-explicit-lifetime.stderr | 4 ---- ...-existing-name-if-else-using-impl-3.stderr | 4 ---- .../missing-lifetime-kind.stderr | 19 ------------------- .../object-lifetime-default-elision.stderr | 4 ---- .../ignore-non-reference-lifetimes.stderr | 9 --------- tests/ui/self/self_lifetime-async.stderr | 9 --------- tests/ui/self/self_lifetime.stderr | 9 --------- .../impl-trait-missing-lifetime-gated.stderr | 4 ---- .../missing-lifetimes-in-signature.stderr | 4 ---- .../missing_lifetime_bound.stderr | 4 ---- 18 files changed, 7 insertions(+), 103 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 693f1b22587..ae7e9659856 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2639,6 +2639,13 @@ impl<G: EmissionGuarantee> LintDiagnostic<'_, G> for ElidedNamedLifetime { if let Some(declaration) = declaration { diag.span_label(declaration, fluent::lint_label_named); } + // FIXME(GrigorenkoPV): this `if` and `return` should be removed, + // but currently this lint's suggestions can conflict with those of `clippy::needless_lifetimes`: + // https://github.com/rust-lang/rust/pull/129840#issuecomment-2323349119 + // HACK: `'static` suggestions will never sonflict, emit only those for now. + if name != rustc_span::symbol::kw::StaticLifetime { + return; + } match kind { MissingLifetimeKind::Underscore => diag.span_suggestion_verbose( span, diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr index 713e4e4dcf5..ef74bfe3237 100644 --- a/tests/ui/async-await/issues/issue-63388-1.stderr +++ b/tests/ui/async-await/issues/issue-63388-1.stderr @@ -8,10 +8,6 @@ LL | ) -> &dyn Foo | ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | ) -> &'a dyn Foo - | ++ error[E0621]: explicit lifetime required in the type of `foo` --> $DIR/issue-63388-1.rs:13:5 diff --git a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr index 394259ce55d..177ff20fbf9 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr @@ -5,10 +5,6 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Ta | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<'a, N>>::Target - | +++ warning: 1 warning emitted diff --git a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr index 0f0d75dbac1..5aee282952a 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -5,10 +5,6 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Ta | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<'a, N>>::Target - | +++ error: `&'static str` is forbidden as the type of a const generic parameter --> $DIR/issue-71348.rs:10:24 diff --git a/tests/ui/consts/min_const_fn/min_const_fn.stderr b/tests/ui/consts/min_const_fn/min_const_fn.stderr index 1e88a908af0..4b348a182b8 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn.stderr @@ -8,10 +8,6 @@ LL | const fn get_lt(&'a self) -> &T { &self.0 } | ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | const fn get_lt(&'a self) -> &'a T { &self.0 } - | ++ warning: elided lifetime has a name --> $DIR/min_const_fn.rs:48:42 @@ -21,11 +17,6 @@ LL | impl<'a, T> Foo<T> { ... LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } | ^ this elided lifetime gets resolved as `'a` - | -help: consider specifying it explicitly - | -LL | const fn get_mut_lt(&'a mut self) -> &'a mut T { &mut self.0 } - | ++ error[E0493]: destructor of `Foo<T>` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:37:25 diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr index ccea9d5e6e9..d0f8f7689d1 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -17,10 +17,6 @@ LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { - | ~~ error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/impl-fn-hrtb-bounds.rs:4:41 diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr index a60f3986843..50a9f3ebeab 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -5,10 +5,6 @@ LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) { - | ~~ error[E0792]: expected generic lifetime parameter, found `'_` --> $DIR/impl-fn-predefined-lifetimes.rs:7:9 diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr index 6eea25b4fc8..bff3ffd934a 100644 --- a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr @@ -5,10 +5,6 @@ LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item = | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item = (u32, &'a u32)> { - | ++ warning: 1 warning emitted diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index 1339c644f53..f835d2655bb 100644 --- a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -114,10 +114,6 @@ LL | fn m<'a>(_: &'a Foo<'a>) -> &str { "" } | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn m<'a>(_: &'a Foo<'a>) -> &'a str { "" } - | ++ error: aborting due to 7 previous errors; 1 warning emitted diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr index 144f9454513..2d5d4fb0e72 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -7,10 +7,6 @@ LL | fn foo<'a>(&'a self, x: &i32) -> &i32 { | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn foo<'a>(&'a self, x: &i32) -> &'a i32 { - | ++ error[E0621]: explicit lifetime required in the type of `x` --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:9:36 diff --git a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr index 834292d103d..249ae146b16 100644 --- a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr +++ b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr @@ -11,10 +11,6 @@ note: the lint level is defined here | LL | #![deny(elided_named_lifetimes)] | ^^^^^^^^^^^^^^^^^^^^^^ -help: consider specifying it explicitly - | -LL | fn ampersand<'a>(x: &'a u8) -> &'a u8 { - | ++ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:10:31 @@ -23,11 +19,6 @@ LL | fn brackets<'a>(x: &'a u8) -> Brackets { | -- ^^^^^^^^ this elided lifetime gets resolved as `'a` | | | lifetime `'a` declared here - | -help: consider specifying it explicitly - | -LL | fn brackets<'a>(x: &'a u8) -> Brackets<'a> { - | ++++ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:17:33 @@ -36,11 +27,6 @@ LL | fn comma<'a>(x: &'a u8) -> Comma<u8> { | -- ^ this elided lifetime gets resolved as `'a` | | | lifetime `'a` declared here - | -help: consider specifying it explicitly - | -LL | fn comma<'a>(x: &'a u8) -> Comma<'a, u8> { - | +++ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:22:34 @@ -49,11 +35,6 @@ LL | fn underscore<'a>(x: &'a u8) -> &'_ u8 { | -- ^^ this elided lifetime gets resolved as `'a` | | | lifetime `'a` declared here - | -help: consider specifying it explicitly - | -LL | fn underscore<'a>(x: &'a u8) -> &'a u8 { - | ~~ error: aborting due to 4 previous errors diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr index f8ed92111a9..b44a184c684 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -7,10 +7,6 @@ LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait { | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &'a dyn SomeTrait { - | ++ error: lifetime may not live long enough --> $DIR/object-lifetime-default-elision.rs:73:5 diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr index 13cc3a431a5..4465dbae529 100644 --- a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr +++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr @@ -5,21 +5,12 @@ LL | fn a<'a>(self: Self, a: &'a str) -> &str { | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn a<'a>(self: Self, a: &'a str) -> &'a str { - | ++ warning: elided lifetime has a name --> $DIR/ignore-non-reference-lifetimes.rs:10:44 | LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &str { | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` - | -help: consider specifying it explicitly - | -LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &'a str { - | ++ warning: 2 warnings emitted diff --git a/tests/ui/self/self_lifetime-async.stderr b/tests/ui/self/self_lifetime-async.stderr index 2892d790ac7..32de3fd18c9 100644 --- a/tests/ui/self/self_lifetime-async.stderr +++ b/tests/ui/self/self_lifetime-async.stderr @@ -7,21 +7,12 @@ LL | async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } | lifetime `'b` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | async fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } - | ++ warning: elided lifetime has a name --> $DIR/self_lifetime-async.rs:12:52 | LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` - | -help: consider specifying it explicitly - | -LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg } - | ++ warning: 2 warnings emitted diff --git a/tests/ui/self/self_lifetime.stderr b/tests/ui/self/self_lifetime.stderr index ceb0ce345a3..cd8f4d8adf8 100644 --- a/tests/ui/self/self_lifetime.stderr +++ b/tests/ui/self/self_lifetime.stderr @@ -7,21 +7,12 @@ LL | fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } | lifetime `'b` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } - | ++ warning: elided lifetime has a name --> $DIR/self_lifetime.rs:13:46 | LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` - | -help: consider specifying it explicitly - | -LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg } - | ++ warning: 2 warnings emitted diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr index 3744dd9f996..30f4509d49d 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -131,10 +131,6 @@ LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &T) { | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &'a T) { - | ++ error[E0658]: anonymous lifetimes in `impl Trait` are unstable --> $DIR/impl-trait-missing-lifetime-gated.rs:6:35 diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index baa5fa949ec..ea01dcd5020 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -13,10 +13,6 @@ LL | fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a + 'a - | ~~ error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not appear in bounds --> $DIR/missing-lifetimes-in-signature.rs:19:5 diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr index 376e58ef9e0..e2c21f1636b 100644 --- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr @@ -7,10 +7,6 @@ LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x } | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn defining<'a, T>(x: &'a i32) -> Opaque<'a, T> { x } - | +++ error[E0700]: hidden type for `Opaque2<T>` captures lifetime that does not appear in bounds --> $DIR/missing_lifetime_bound.rs:5:47 From be10d56039a7299ac0110b2fc70ec155f680b97a Mon Sep 17 00:00:00 2001 From: cuishuang <imcusg@gmail.com> Date: Sat, 7 Sep 2024 09:23:28 +0800 Subject: [PATCH 12/13] Add missing quotation marks Signed-off-by: cuishuang <imcusg@gmail.com> --- tests/ui/const-generics/invariant.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/const-generics/invariant.rs b/tests/ui/const-generics/invariant.rs index ee4ad4e7c4e..95a28b61dde 100644 --- a/tests/ui/const-generics/invariant.rs +++ b/tests/ui/const-generics/invariant.rs @@ -5,7 +5,7 @@ use std::marker::PhantomData; trait SadBee { const ASSOC: usize; } -// fn(&'static ())` is a supertype of `for<'a> fn(&'a ())` while +// `fn(&'static ())` is a supertype of `for<'a> fn(&'a ())` while // we allow two different impls for these types, leading // to different const eval results. impl SadBee for for<'a> fn(&'a ()) { From 14e86eb7d93ebda57d2008ae37e88ac2a0604570 Mon Sep 17 00:00:00 2001 From: Veera <sveera.2001@gmail.com> Date: Mon, 2 Sep 2024 12:43:35 -0400 Subject: [PATCH 13/13] Add Suggestions for Misspelled Keywords This PR detects misspelled keywords using two heuristics: 1. Lowercasing the unexpected identifier. 2. Using edit distance to find a keyword similar to the unexpected identifier. However, it does not detect each and every misspelled keyword to minimize false positives and ambiguities. More details about the implementation can be found in the comments. --- compiler/rustc_parse/messages.ftl | 6 ++ .../rustc_parse/src/parser/diagnostics.rs | 85 ++++++++++++++++++- compiler/rustc_span/src/symbol.rs | 42 ++++++++- .../extern-crate-unexpected-token.stderr | 5 ++ ...9-resolve-after-recovered-self-ctor.stderr | 33 +++++-- .../misspelled-keywords/assoc-type.stderr | 5 ++ .../misspelled-keywords/async-move.stderr | 5 ++ .../misspelled-keywords/const-fn.stderr | 5 ++ .../misspelled-keywords/const-generics.stderr | 5 ++ .../parser/misspelled-keywords/const.stderr | 5 ++ .../misspelled-keywords/for-loop.stderr | 5 ++ .../ui/parser/misspelled-keywords/hrdt.stderr | 5 ++ .../misspelled-keywords/impl-block.stderr | 5 ++ .../misspelled-keywords/impl-return.stderr | 5 ++ .../misspelled-keywords/impl-trait-for.stderr | 5 ++ .../misspelled-keywords/impl-trait.stderr | 4 + .../misspelled-keywords/let-else.stderr | 5 ++ .../parser/misspelled-keywords/let-mut.stderr | 5 ++ .../ui/parser/misspelled-keywords/let.stderr | 10 +++ .../parser/misspelled-keywords/match.stderr | 5 ++ .../ui/parser/misspelled-keywords/mod.stderr | 5 ++ .../parser/misspelled-keywords/pub-fn.stderr | 5 ++ .../ui/parser/misspelled-keywords/ref.stderr | 13 ++- .../parser/misspelled-keywords/return.stderr | 5 ++ .../misspelled-keywords/static-mut.stderr | 5 ++ .../parser/misspelled-keywords/static.stderr | 5 ++ .../parser/misspelled-keywords/struct.stderr | 5 ++ .../misspelled-keywords/unsafe-fn.stderr | 5 ++ .../ui/parser/misspelled-keywords/use.stderr | 5 ++ .../misspelled-keywords/where-clause.stderr | 5 ++ .../parser/misspelled-keywords/while-loop.rs | 2 - .../misspelled-keywords/while-loop.stderr | 5 ++ 32 files changed, 298 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 8e8d91ce4d0..ec9a676ea31 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -381,6 +381,7 @@ parse_invalid_char_in_escape_msg = invalid character in {$is_hex -> *[false] unicode } escape + parse_invalid_comparison_operator = invalid comparison operator `{$invalid}` .use_instead = `{$invalid}` is not a valid comparison operator, use `{$correct}` .spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering` @@ -581,6 +582,11 @@ parse_missing_trait_in_trait_impl = missing trait in a trait impl .suggestion_add_trait = add a trait here .suggestion_remove_for = for an inherent impl, drop this `for` +parse_misspelled_kw = {$is_incorrect_case -> + [true] write keyword `{$similar_kw}` in lowercase + *[false] there is a keyword `{$similar_kw}` with a similar name +} + parse_modifier_lifetime = `{$modifier}` may only modify trait bounds, not lifetime bounds .suggestion = remove the `{$modifier}` diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index fcdc10c0837..f6f66821df7 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -19,8 +19,9 @@ use rustc_errors::{ Subdiagnostic, }; use rustc_session::errors::ExprParenthesesNeeded; +use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::source_map::Spanned; -use rustc_span::symbol::{kw, sym, Ident}; +use rustc_span::symbol::{kw, sym, AllKeywords, Ident}; use rustc_span::{BytePos, Span, SpanSnippetError, Symbol, DUMMY_SP}; use thin_vec::{thin_vec, ThinVec}; use tracing::{debug, trace}; @@ -203,6 +204,37 @@ impl std::fmt::Display for UnaryFixity { } } +#[derive(Debug, rustc_macros::Subdiagnostic)] +#[suggestion( + parse_misspelled_kw, + applicability = "machine-applicable", + code = "{similar_kw}", + style = "verbose" +)] +struct MisspelledKw { + similar_kw: String, + #[primary_span] + span: Span, + is_incorrect_case: bool, +} + +/// Checks if the given `lookup` identifier is similar to any keyword symbol in `candidates`. +fn find_similar_kw(lookup: Ident, candidates: &[Symbol]) -> Option<MisspelledKw> { + let lowercase = lookup.name.as_str().to_lowercase(); + let lowercase_sym = Symbol::intern(&lowercase); + if candidates.contains(&lowercase_sym) { + Some(MisspelledKw { similar_kw: lowercase, span: lookup.span, is_incorrect_case: true }) + } else if let Some(similar_sym) = find_best_match_for_name(candidates, lookup.name, None) { + Some(MisspelledKw { + similar_kw: similar_sym.to_string(), + span: lookup.span, + is_incorrect_case: false, + }) + } else { + None + } +} + struct MultiSugg { msg: String, patches: Vec<(Span, String)>, @@ -638,9 +670,9 @@ impl<'a> Parser<'a> { let concat = Symbol::intern(&format!("{prev}{cur}")); let ident = Ident::new(concat, DUMMY_SP); if ident.is_used_keyword() || ident.is_reserved() || ident.is_raw_guess() { - let span = self.prev_token.span.to(self.token.span); + let concat_span = self.prev_token.span.to(self.token.span); err.span_suggestion_verbose( - span, + concat_span, format!("consider removing the space to spell keyword `{concat}`"), concat, Applicability::MachineApplicable, @@ -741,9 +773,55 @@ impl<'a> Parser<'a> { err.span_label(sp, label_exp); err.span_label(self.token.span, "unexpected token"); } + + // Check for misspelled keywords if there are no suggestions added to the diagnostic. + if err.suggestions.as_ref().is_ok_and(|code_suggestions| code_suggestions.is_empty()) { + self.check_for_misspelled_kw(&mut err, &expected); + } Err(err) } + /// Checks if the current token or the previous token are misspelled keywords + /// and adds a helpful suggestion. + fn check_for_misspelled_kw(&self, err: &mut Diag<'_>, expected: &[TokenType]) { + let Some((curr_ident, _)) = self.token.ident() else { + return; + }; + let expected_tokens: &[TokenType] = + expected.len().checked_sub(10).map_or(&expected, |index| &expected[index..]); + let expected_keywords: Vec<Symbol> = expected_tokens + .iter() + .filter_map(|token| if let TokenType::Keyword(kw) = token { Some(*kw) } else { None }) + .collect(); + + // When there are a few keywords in the last ten elements of `self.expected_tokens` and the current + // token is an identifier, it's probably a misspelled keyword. + // This handles code like `async Move {}`, misspelled `if` in match guard, misspelled `else` in `if`-`else` + // and mispelled `where` in a where clause. + if !expected_keywords.is_empty() + && !curr_ident.is_used_keyword() + && let Some(misspelled_kw) = find_similar_kw(curr_ident, &expected_keywords) + { + err.subdiagnostic(misspelled_kw); + } else if let Some((prev_ident, _)) = self.prev_token.ident() + && !prev_ident.is_used_keyword() + { + // We generate a list of all keywords at runtime rather than at compile time + // so that it gets generated only when the diagnostic needs it. + // Also, it is unlikely that this list is generated multiple times because the + // parser halts after execution hits this path. + let all_keywords = AllKeywords::new().collect_used(|| prev_ident.span.edition()); + + // Otherwise, check the previous token with all the keywords as possible candidates. + // This handles code like `Struct Human;` and `While a < b {}`. + // We check the previous token only when the current token is an identifier to avoid false + // positives like suggesting keyword `for` for `extern crate foo {}`. + if let Some(misspelled_kw) = find_similar_kw(prev_ident, &all_keywords) { + err.subdiagnostic(misspelled_kw); + } + } + } + /// The user has written `#[attr] expr` which is unsupported. (#106020) pub(super) fn attr_on_non_tail_expr(&self, expr: &Expr) -> ErrorGuaranteed { // Missing semicolon typo error. @@ -846,6 +924,7 @@ impl<'a> Parser<'a> { ); } } + err.emit() } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 34765209605..cabbdb02092 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -20,7 +20,8 @@ mod tests; // The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`. symbols! { - // If you modify this list, adjust `is_special` and `is_used_keyword`/`is_unused_keyword`. + // If you modify this list, adjust `is_special`, `is_used_keyword`/`is_unused_keyword` + // and `AllKeywords`. // But this should rarely be necessary if the keywords are kept in alphabetic order. Keywords { // Special reserved identifiers used internally for elided lifetimes, @@ -2577,3 +2578,42 @@ impl Ident { self.name.can_be_raw() && self.is_reserved() } } + +/// An iterator over all the keywords in Rust. +#[derive(Copy, Clone)] +pub struct AllKeywords { + curr_idx: u32, + end_idx: u32, +} + +impl AllKeywords { + /// Initialize a new iterator over all the keywords. + /// + /// *Note:* Please update this if a new keyword is added beyond the current + /// range. + pub fn new() -> Self { + AllKeywords { curr_idx: kw::Empty.as_u32(), end_idx: kw::Yeet.as_u32() } + } + + /// Collect all the keywords in a given edition into a vector. + pub fn collect_used(&self, edition: impl Copy + FnOnce() -> Edition) -> Vec<Symbol> { + self.filter(|&keyword| { + keyword.is_used_keyword_always() || keyword.is_used_keyword_conditional(edition) + }) + .collect() + } +} + +impl Iterator for AllKeywords { + type Item = Symbol; + + fn next(&mut self) -> Option<Self::Item> { + if self.curr_idx <= self.end_idx { + let keyword = Symbol::new(self.curr_idx); + self.curr_idx += 1; + Some(keyword) + } else { + None + } + } +} diff --git a/tests/ui/parser/extern-crate-unexpected-token.stderr b/tests/ui/parser/extern-crate-unexpected-token.stderr index f83bb3e3e35..951b0274b0d 100644 --- a/tests/ui/parser/extern-crate-unexpected-token.stderr +++ b/tests/ui/parser/extern-crate-unexpected-token.stderr @@ -3,6 +3,11 @@ error: expected one of `crate` or `{`, found `crte` | LL | extern crte foo; | ^^^^ expected one of `crate` or `{` + | +help: there is a keyword `crate` with a similar name + | +LL | extern crate foo; + | ~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr b/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr index 79c574ead61..00f372bc008 100644 --- a/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr +++ b/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr @@ -8,10 +8,16 @@ error: expected one of `:`, `@`, or `|`, found keyword `Self` --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:4:17 | LL | fn foo(&mur Self) {} - | -----^^^^ - | | | - | | expected one of `:`, `@`, or `|` - | help: declare the type after the parameter binding: `<identifier>: <type>` + | ^^^^ expected one of `:`, `@`, or `|` + | +help: there is a keyword `mut` with a similar name + | +LL | fn foo(&mut Self) {} + | ~~~ +help: declare the type after the parameter binding + | +LL | fn foo(<identifier>: <type>) {} + | ~~~~~~~~~~~~~~~~~~~~ error: unexpected lifetime `'static` in pattern --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:8:13 @@ -35,16 +41,27 @@ error: expected one of `:`, `@`, or `|`, found keyword `Self` --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:8:25 | LL | fn bar(&'static mur Self) {} - | -------------^^^^ - | | | - | | expected one of `:`, `@`, or `|` - | help: declare the type after the parameter binding: `<identifier>: <type>` + | ^^^^ expected one of `:`, `@`, or `|` + | +help: there is a keyword `mut` with a similar name + | +LL | fn bar(&'static mut Self) {} + | ~~~ +help: declare the type after the parameter binding + | +LL | fn bar(<identifier>: <type>) {} + | ~~~~~~~~~~~~~~~~~~~~ error: expected one of `:`, `@`, or `|`, found keyword `Self` --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:14:17 | LL | fn baz(&mur Self @ _) {} | ^^^^ expected one of `:`, `@`, or `|` + | +help: there is a keyword `mut` with a similar name + | +LL | fn baz(&mut Self @ _) {} + | ~~~ error[E0533]: expected unit struct, found self constructor `Self` --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:4:17 diff --git a/tests/ui/parser/misspelled-keywords/assoc-type.stderr b/tests/ui/parser/misspelled-keywords/assoc-type.stderr index 1318bee3da8..677da53e340 100644 --- a/tests/ui/parser/misspelled-keywords/assoc-type.stderr +++ b/tests/ui/parser/misspelled-keywords/assoc-type.stderr @@ -8,6 +8,11 @@ LL | Type Result = u8; LL | LL | } | - the item list ends here + | +help: write keyword `type` in lowercase + | +LL | type Result = u8; + | ~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/async-move.stderr b/tests/ui/parser/misspelled-keywords/async-move.stderr index a98bb23f5d6..4be4b56e505 100644 --- a/tests/ui/parser/misspelled-keywords/async-move.stderr +++ b/tests/ui/parser/misspelled-keywords/async-move.stderr @@ -3,6 +3,11 @@ error: expected one of `move`, `|`, or `||`, found `Move` | LL | async Move {} | ^^^^ expected one of `move`, `|`, or `||` + | +help: write keyword `move` in lowercase + | +LL | async move {} + | ~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/const-fn.stderr b/tests/ui/parser/misspelled-keywords/const-fn.stderr index bdca2657ef3..5646b26143c 100644 --- a/tests/ui/parser/misspelled-keywords/const-fn.stderr +++ b/tests/ui/parser/misspelled-keywords/const-fn.stderr @@ -3,6 +3,11 @@ error: expected one of `!` or `::`, found keyword `fn` | LL | cnst fn code() {} | ^^ expected one of `!` or `::` + | +help: there is a keyword `const` with a similar name + | +LL | const fn code() {} + | ~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/const-generics.stderr b/tests/ui/parser/misspelled-keywords/const-generics.stderr index f52544ac45c..fd59999ab63 100644 --- a/tests/ui/parser/misspelled-keywords/const-generics.stderr +++ b/tests/ui/parser/misspelled-keywords/const-generics.stderr @@ -3,6 +3,11 @@ error: expected one of `,`, `:`, `=`, or `>`, found `N` | LL | fn foo<consta N: usize>(_arr: [i32; N]) {} | ^ expected one of `,`, `:`, `=`, or `>` + | +help: there is a keyword `const` with a similar name + | +LL | fn foo<const N: usize>(_arr: [i32; N]) {} + | ~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/const.stderr b/tests/ui/parser/misspelled-keywords/const.stderr index de1ad9d2bf7..35e4d731db7 100644 --- a/tests/ui/parser/misspelled-keywords/const.stderr +++ b/tests/ui/parser/misspelled-keywords/const.stderr @@ -3,6 +3,11 @@ error: expected one of `!` or `::`, found `A` | LL | cons A: u8 = 10; | ^ expected one of `!` or `::` + | +help: there is a keyword `const` with a similar name + | +LL | const A: u8 = 10; + | ~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/for-loop.stderr b/tests/ui/parser/misspelled-keywords/for-loop.stderr index cbf3b43fa58..d2236ab074d 100644 --- a/tests/ui/parser/misspelled-keywords/for-loop.stderr +++ b/tests/ui/parser/misspelled-keywords/for-loop.stderr @@ -3,6 +3,11 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found | LL | form i in 1..10 {} | ^ expected one of 8 possible tokens + | +help: there is a keyword `for` with a similar name + | +LL | for i in 1..10 {} + | ~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/hrdt.stderr b/tests/ui/parser/misspelled-keywords/hrdt.stderr index 102ce7014e4..5393a730506 100644 --- a/tests/ui/parser/misspelled-keywords/hrdt.stderr +++ b/tests/ui/parser/misspelled-keywords/hrdt.stderr @@ -3,6 +3,11 @@ error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found keyword | LL | Where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8, | ^^^ expected one of 7 possible tokens + | +help: write keyword `where` in lowercase (notice the capitalization difference) + | +LL | where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8, + | ~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/impl-block.stderr b/tests/ui/parser/misspelled-keywords/impl-block.stderr index e0f0f8ed18f..d86ae326ce2 100644 --- a/tests/ui/parser/misspelled-keywords/impl-block.stderr +++ b/tests/ui/parser/misspelled-keywords/impl-block.stderr @@ -3,6 +3,11 @@ error: expected one of `!` or `::`, found `Human` | LL | ipml Human {} | ^^^^^ expected one of `!` or `::` + | +help: there is a keyword `impl` with a similar name + | +LL | impl Human {} + | ~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/impl-return.stderr b/tests/ui/parser/misspelled-keywords/impl-return.stderr index bdcf831a88a..883f5cea73e 100644 --- a/tests/ui/parser/misspelled-keywords/impl-return.stderr +++ b/tests/ui/parser/misspelled-keywords/impl-return.stderr @@ -3,6 +3,11 @@ error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `Display | LL | fn code() -> Impl Display {} | ^^^^^^^ expected one of 7 possible tokens + | +help: write keyword `impl` in lowercase (notice the capitalization difference) + | +LL | fn code() -> impl Display {} + | ~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr b/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr index 64ca66794ad..8dd5a4645f3 100644 --- a/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr +++ b/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr @@ -3,6 +3,11 @@ error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `Human` | LL | impl Debug form Human {} | ^^^^^ expected one of 7 possible tokens + | +help: there is a keyword `for` with a similar name + | +LL | impl Debug for Human {} + | ~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/impl-trait.stderr b/tests/ui/parser/misspelled-keywords/impl-trait.stderr index ca0918e820f..15a8f99b8b1 100644 --- a/tests/ui/parser/misspelled-keywords/impl-trait.stderr +++ b/tests/ui/parser/misspelled-keywords/impl-trait.stderr @@ -4,6 +4,10 @@ error: expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`, found `Debug` LL | fn code<T: impll Debug>() -> u8 {} | ^^^^^ expected one of 7 possible tokens | +help: there is a keyword `impl` with a similar name + | +LL | fn code<T: impl Debug>() -> u8 {} + | ~~~~ help: you might have meant to end the type parameters here | LL | fn code<T: impll> Debug>() -> u8 {} diff --git a/tests/ui/parser/misspelled-keywords/let-else.stderr b/tests/ui/parser/misspelled-keywords/let-else.stderr index 826e7de4b11..6f41a0d99db 100644 --- a/tests/ui/parser/misspelled-keywords/let-else.stderr +++ b/tests/ui/parser/misspelled-keywords/let-else.stderr @@ -3,6 +3,11 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `elze` | LL | let Some(a) = Some(10) elze {} | ^^^^ expected one of `.`, `;`, `?`, `else`, or an operator + | +help: there is a keyword `else` with a similar name + | +LL | let Some(a) = Some(10) else {} + | ~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/let-mut.stderr b/tests/ui/parser/misspelled-keywords/let-mut.stderr index 449f0133d65..766d2a04909 100644 --- a/tests/ui/parser/misspelled-keywords/let-mut.stderr +++ b/tests/ui/parser/misspelled-keywords/let-mut.stderr @@ -3,6 +3,11 @@ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `a` | LL | let muta a = 10; | ^ expected one of `:`, `;`, `=`, `@`, or `|` + | +help: there is a keyword `mut` with a similar name + | +LL | let mut a = 10; + | ~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/let.stderr b/tests/ui/parser/misspelled-keywords/let.stderr index 77aeb21369c..c2dcdef541d 100644 --- a/tests/ui/parser/misspelled-keywords/let.stderr +++ b/tests/ui/parser/misspelled-keywords/let.stderr @@ -3,12 +3,22 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found | LL | Let a = 10; | ^ expected one of 8 possible tokens + | +help: write keyword `let` in lowercase + | +LL | let a = 10; + | ~~~ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a` --> $DIR/let.rs:7:10 | LL | lett a = 10; | ^ expected one of 8 possible tokens + | +help: there is a keyword `let` with a similar name + | +LL | let a = 10; + | ~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/parser/misspelled-keywords/match.stderr b/tests/ui/parser/misspelled-keywords/match.stderr index bc3eece1c9d..90780ebd38e 100644 --- a/tests/ui/parser/misspelled-keywords/match.stderr +++ b/tests/ui/parser/misspelled-keywords/match.stderr @@ -3,6 +3,11 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found | LL | matche a {} | ^ expected one of 8 possible tokens + | +help: there is a keyword `match` with a similar name + | +LL | match a {} + | ~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/mod.stderr b/tests/ui/parser/misspelled-keywords/mod.stderr index 135f70ccfcb..6daeb4e5a15 100644 --- a/tests/ui/parser/misspelled-keywords/mod.stderr +++ b/tests/ui/parser/misspelled-keywords/mod.stderr @@ -3,6 +3,11 @@ error: expected one of `!` or `::`, found `parser` | LL | mode parser; | ^^^^^^ expected one of `!` or `::` + | +help: there is a keyword `mod` with a similar name + | +LL | mod parser; + | ~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/pub-fn.stderr b/tests/ui/parser/misspelled-keywords/pub-fn.stderr index 15715514e66..82ca7105a49 100644 --- a/tests/ui/parser/misspelled-keywords/pub-fn.stderr +++ b/tests/ui/parser/misspelled-keywords/pub-fn.stderr @@ -3,6 +3,11 @@ error: expected one of `#`, `async`, `auto`, `const`, `default`, `enum`, `extern | LL | puB fn code() {} | ^^^ expected one of 21 possible tokens + | +help: write keyword `pub` in lowercase + | +LL | pub fn code() {} + | ~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/ref.stderr b/tests/ui/parser/misspelled-keywords/ref.stderr index 2c23fe7a0af..3a79b7bdb00 100644 --- a/tests/ui/parser/misspelled-keywords/ref.stderr +++ b/tests/ui/parser/misspelled-keywords/ref.stderr @@ -2,9 +2,16 @@ error: expected one of `)`, `,`, `@`, or `|`, found `list` --> $DIR/ref.rs:4:19 | LL | Some(refe list) => println!("{list:?}"), - | -^^^^ expected one of `)`, `,`, `@`, or `|` - | | - | help: missing `,` + | ^^^^ expected one of `)`, `,`, `@`, or `|` + | +help: there is a keyword `ref` with a similar name + | +LL | Some(ref list) => println!("{list:?}"), + | ~~~ +help: missing `,` + | +LL | Some(refe, list) => println!("{list:?}"), + | + error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field --> $DIR/ref.rs:4:14 diff --git a/tests/ui/parser/misspelled-keywords/return.stderr b/tests/ui/parser/misspelled-keywords/return.stderr index 94789e7a92c..efa45f32299 100644 --- a/tests/ui/parser/misspelled-keywords/return.stderr +++ b/tests/ui/parser/misspelled-keywords/return.stderr @@ -3,6 +3,11 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found | LL | returnn a; | ^ expected one of 8 possible tokens + | +help: there is a keyword `return` with a similar name + | +LL | return a; + | ~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/static-mut.stderr b/tests/ui/parser/misspelled-keywords/static-mut.stderr index 1e5d25c709e..3c25af548a3 100644 --- a/tests/ui/parser/misspelled-keywords/static-mut.stderr +++ b/tests/ui/parser/misspelled-keywords/static-mut.stderr @@ -3,6 +3,11 @@ error: expected one of `:`, `;`, or `=`, found `a` | LL | static muta a: u8 = 0; | ^ expected one of `:`, `;`, or `=` + | +help: there is a keyword `mut` with a similar name + | +LL | static mut a: u8 = 0; + | ~~~ error: missing type for `static` item --> $DIR/static-mut.rs:1:12 diff --git a/tests/ui/parser/misspelled-keywords/static.stderr b/tests/ui/parser/misspelled-keywords/static.stderr index 698cd47b169..003aa3929bc 100644 --- a/tests/ui/parser/misspelled-keywords/static.stderr +++ b/tests/ui/parser/misspelled-keywords/static.stderr @@ -3,6 +3,11 @@ error: expected one of `!` or `::`, found `a` | LL | Static a = 0; | ^ expected one of `!` or `::` + | +help: write keyword `static` in lowercase (notice the capitalization difference) + | +LL | static a = 0; + | ~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/struct.stderr b/tests/ui/parser/misspelled-keywords/struct.stderr index 8f678f4ad2e..559182f9c8f 100644 --- a/tests/ui/parser/misspelled-keywords/struct.stderr +++ b/tests/ui/parser/misspelled-keywords/struct.stderr @@ -3,6 +3,11 @@ error: expected one of `!` or `::`, found `Foor` | LL | Struct Foor { | ^^^^ expected one of `!` or `::` + | +help: write keyword `struct` in lowercase (notice the capitalization difference) + | +LL | struct Foor { + | ~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr b/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr index 2013df1c34a..b13281b0395 100644 --- a/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr +++ b/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr @@ -3,6 +3,11 @@ error: expected one of `!` or `::`, found keyword `fn` | LL | unsafee fn code() {} | ^^ expected one of `!` or `::` + | +help: there is a keyword `unsafe` with a similar name + | +LL | unsafe fn code() {} + | ~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/use.stderr b/tests/ui/parser/misspelled-keywords/use.stderr index 4ca01dedd6b..db6dffdb613 100644 --- a/tests/ui/parser/misspelled-keywords/use.stderr +++ b/tests/ui/parser/misspelled-keywords/use.stderr @@ -3,6 +3,11 @@ error: expected one of `!` or `::`, found `a` | LL | usee a::b; | ^ expected one of `!` or `::` + | +help: there is a keyword `use` with a similar name + | +LL | use a::b; + | ~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/where-clause.stderr b/tests/ui/parser/misspelled-keywords/where-clause.stderr index 4b3f996c112..5143c30ca51 100644 --- a/tests/ui/parser/misspelled-keywords/where-clause.stderr +++ b/tests/ui/parser/misspelled-keywords/where-clause.stderr @@ -5,6 +5,11 @@ LL | fn code<T>() -> u8 | - expected one of 7 possible tokens LL | wheree | ^^^^^^ unexpected token + | +help: there is a keyword `where` with a similar name + | +LL | where + | error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/while-loop.rs b/tests/ui/parser/misspelled-keywords/while-loop.rs index 8d19b3c5722..37d337f3f19 100644 --- a/tests/ui/parser/misspelled-keywords/while-loop.rs +++ b/tests/ui/parser/misspelled-keywords/while-loop.rs @@ -1,7 +1,5 @@ fn main() { whilee a < b { //~^ ERROR expected one of - } } - diff --git a/tests/ui/parser/misspelled-keywords/while-loop.stderr b/tests/ui/parser/misspelled-keywords/while-loop.stderr index 8147a5de696..7d150443f57 100644 --- a/tests/ui/parser/misspelled-keywords/while-loop.stderr +++ b/tests/ui/parser/misspelled-keywords/while-loop.stderr @@ -3,6 +3,11 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found | LL | whilee a < b { | ^ expected one of 8 possible tokens + | +help: there is a keyword `while` with a similar name + | +LL | while a < b { + | ~~~~~ error: aborting due to 1 previous error