From 9a29081b49540b84ea13994494d7ed0f599387bc Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 9 Aug 2024 12:22:00 +0300 Subject: [PATCH 01/15] call `Cargo::configure_linker` only for specific commands Calling `Cargo::configure_linker` unconditionally slows down certain commands (e.g., "check" command) without providing any benefit. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 84c23c059e97e..b21572016b446 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -2446,7 +2446,15 @@ impl Cargo { cmd_kind: Kind, ) -> Cargo { let mut cargo = builder.cargo(compiler, mode, source_type, target, cmd_kind); - cargo.configure_linker(builder); + + match cmd_kind { + // No need to configure the target linker for these command types. + Kind::Clean | Kind::Check | Kind::Suggest | Kind::Format | Kind::Setup => {} + _ => { + cargo.configure_linker(builder); + } + } + cargo } From 94fbe141558bb866c07f7c5138fba0d186c4ce85 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 9 Aug 2024 12:30:36 +0300 Subject: [PATCH 02/15] don't try to find target tools on certain commands For commands like check/clean there is no need to check for target tools. Avoiding this check can also speed up the process. Signed-off-by: onur-ozkan --- src/bootstrap/src/utils/cc_detect.rs | 32 ++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs index 29e6b74aaceb8..a2c7ab31df8a5 100644 --- a/src/bootstrap/src/utils/cc_detect.rs +++ b/src/bootstrap/src/utils/cc_detect.rs @@ -87,15 +87,29 @@ fn new_cc_build(build: &Build, target: TargetSelection) -> cc::Build { } pub fn find(build: &Build) { - // For all targets we're going to need a C compiler for building some shims - // and such as well as for being a linker for Rust code. - let targets = build - .targets - .iter() - .chain(&build.hosts) - .cloned() - .chain(iter::once(build.build)) - .collect::>(); + let targets: HashSet<_> = match build.config.cmd { + // We don't need to check cross targets for these commands. + crate::Subcommand::Clean { .. } + | crate::Subcommand::Check { .. } + | crate::Subcommand::Suggest { .. } + | crate::Subcommand::Format { .. } + | crate::Subcommand::Setup { .. } => { + build.hosts.iter().cloned().chain(iter::once(build.build)).collect() + } + + _ => { + // For all targets we're going to need a C compiler for building some shims + // and such as well as for being a linker for Rust code. + build + .targets + .iter() + .chain(&build.hosts) + .cloned() + .chain(iter::once(build.build)) + .collect() + } + }; + for target in targets.into_iter() { find_target(build, target); } From b324fcb169cbb952a5ef87fe00989666a9695d89 Mon Sep 17 00:00:00 2001 From: Rajveer Date: Fri, 23 Aug 2024 18:33:59 +0530 Subject: [PATCH 03/15] [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 b7ef1d77ea023..a4a41dd96c169 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 f36345670e329..cf1882ba1a22e 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: #[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 0674e169d72e6..d421e0e6954cc 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 eeff1a070b492..448b92aa8399a 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 269c7582a1cee..9389fcf9cbac9 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 e4c46cfcf81b1..1b097f4110501 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 bd62f4a5236c2..f40a28be4a7e1 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 bc8af08ad1133..85321e5f345ad 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 51b3aaf99d944..1f5d7d85b0ad9 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 661907360bd28..e68b18d7aa690 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 c5e393b10564e..5a48af9205f75 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 8e229614420b6..a40bc10d9915c 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 Date: Sun, 1 Sep 2024 22:27:43 -0400 Subject: [PATCH 04/15] 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 0000000000000..a6b694a2abe6b --- /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 0000000000000..1318bee3da83d --- /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 0000000000000..702a905e918c3 --- /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 0000000000000..a98bb23f5d65e --- /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 0000000000000..c4174b6a2efb5 --- /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 0000000000000..bdca2657ef39b --- /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 0000000000000..2df64a87e2776 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/const-generics.rs @@ -0,0 +1,4 @@ +fn foo(_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 0000000000000..f52544ac45ce2 --- /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(_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 0000000000000..b481408cb62d2 --- /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 0000000000000..de1ad9d2bf76d --- /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 0000000000000..6aba581cf17fa --- /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 0000000000000..cbf3b43fa585b --- /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 0000000000000..9ca9e1bfbeecc --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/hrdt.rs @@ -0,0 +1,16 @@ +struct Closure { + data: (u8, u16), + func: F, +} + +impl Closure + 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 0000000000000..102ce7014e470 --- /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 0000000000000..dc2570c22c5df --- /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 0000000000000..e0f0f8ed18f91 --- /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 0000000000000..c9d1973179e47 --- /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 0000000000000..bdcf831a88a39 --- /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 0000000000000..c6f3fcda5ad71 --- /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 0000000000000..64ca66794adba --- /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 0000000000000..99380b8ac0ecd --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-trait.rs @@ -0,0 +1,4 @@ +fn code() -> 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 0000000000000..ca0918e820f87 --- /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() -> u8 {} + | ^^^^^ expected one of 7 possible tokens + | +help: you might have meant to end the type parameters here + | +LL | fn code 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 0000000000000..0d5a03e3e43e4 --- /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 0000000000000..826e7de4b11a5 --- /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 0000000000000..83228fe8c6682 --- /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 0000000000000..449f0133d6536 --- /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 0000000000000..461c3e518db82 --- /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 0000000000000..77aeb21369c13 --- /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 0000000000000..a31840a2d7111 --- /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 0000000000000..bc3eece1c9d9a --- /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 0000000000000..24f0101bc5aaa --- /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 0000000000000..135f70ccfcbba --- /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 0000000000000..50d7129ce51ee --- /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 0000000000000..15715514e6651 --- /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 0000000000000..76b367ae99b75 --- /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 0000000000000..2c23fe7a0afe8 --- /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 0000000000000..4bbe55d37da72 --- /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 0000000000000..94789e7a92cd8 --- /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 0000000000000..6509f62470a9c --- /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 0000000000000..1e5d25c709e7d --- /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: 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 0000000000000..240f4f52c8dc8 --- /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 0000000000000..698cd47b16972 --- /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 0000000000000..0f64dec6f56b3 --- /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 0000000000000..8f678f4ad2e03 --- /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 0000000000000..49a1322ad637f --- /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 0000000000000..2013df1c34aa8 --- /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 0000000000000..f4911654354e2 --- /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 0000000000000..4ca01dedd6b28 --- /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 0000000000000..c03d04d5fee50 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/where-clause.rs @@ -0,0 +1,8 @@ +fn code() -> 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 0000000000000..4b3f996c11254 --- /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() -> 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 0000000000000..8d19b3c572264 --- /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 0000000000000..8147a5de69673 --- /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 0000000000000..203db8306af9c --- /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 0000000000000..121e39313148a --- /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 Date: Tue, 3 Sep 2024 12:42:57 -0600 Subject: [PATCH 05/15] 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 618602ed70f44..d55220ba5c3a4 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 { 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 Date: Tue, 3 Sep 2024 13:42:10 -0600 Subject: [PATCH 06/15] 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 0000000000000..8b6d0cf212320 --- /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 Date: Thu, 5 Sep 2024 08:42:50 -0400 Subject: [PATCH 07/15] 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 5789e60ebbebe..7688a63a30a45 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>, + 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 8eb3c0156796a..809801c33e1ad 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>, } impl<'tcx> CapturedPlace<'tcx> { From 96837dcade77185d270c90326f000fc057c29a8e Mon Sep 17 00:00:00 2001 From: Ulrik Mikaelsson Date: Mon, 26 Aug 2024 17:19:45 +0200 Subject: [PATCH 08/15] 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 08d46f356d9f2..e41cbc1a65c0f 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 Date: Mon, 2 Sep 2024 15:45:06 +0200 Subject: [PATCH 09/15] 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 92a857c2adcf4..9d4497d73a8ae 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 0000000000000..a45b95780f793 --- /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 Date: Sun, 1 Sep 2024 01:14:06 +0300 Subject: [PATCH 10/15] 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 fd43afa174383..b1c1e4f4dd686 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 6ee330416236f..9a72e4f673934 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 79c42456cf8c9..917cb81aa511f 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 Date: Sun, 1 Sep 2024 03:42:18 +0300 Subject: [PATCH 11/15] 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 759320b9eb65f..fe211355ac38a 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 b1c1e4f4dd686..a1a371a032e90 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 9050f36acba7b..426d671f8e0a6 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, diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr index ef74bfe32375e..c8b55977faf3a 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 177ff20fbf9ea..8d1c1ea23a81c 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 >::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 >::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 5aee282952aa2..57da3ce21cecd 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 >::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 >::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 4b348a182b87f..b7db403ad16b2 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 { ... 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` 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 d0f8f7689d17c..ccea9d5e6e92a 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 50a9f3ebeabb8..a60f398684330 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 bff3ffd934ac6..ec0f0708b156f 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(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { + | ~~~ 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 f835d2655bb01..a7512158661fb 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 2d5d4fb0e72ec..0943e0cc0d9d4 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 8c5426a60cb72..5af5123c03237 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 249ae146b1675..6abaad7f5d218 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 { | -- ^ 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 c465aab1a03d2..cbc1b862caabd 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 d2e9776cb4f0e..6c3944e5ea580 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 { | ^ 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 b44a184c6848f..7d239a54eda4f 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 4465dbae52989..460d2ce2cc907 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 32de3fd18c97f..fd167cf392fb6 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 cd8f4d8adf8b1..52189084f04c0 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 30f4509d49dee..92f774767c863 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 ea01dcd5020cf..baa5fa949ec41 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 e2c21f1636b0c..73a362d28e7d7 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 { 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` 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 Date: Sun, 1 Sep 2024 04:08:55 +0300 Subject: [PATCH 12/15] 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 fe211355ac38a..5a368f4ed9a54 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 a1a371a032e90..de34b9bebe9f5 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 426d671f8e0a6..693f1b2258745 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, + pub declaration: Option, +} + +impl 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 c8b55977faf3a..713e4e4dcf5ca 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 8d1c1ea23a81c..394259ce55ddb 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 >::Ta help: consider specifying it explicitly | LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::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 57da3ce21cecd..0f0d75dbac13e 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 >::Ta help: consider specifying it explicitly | LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::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 b7db403ad16b2..1e88a908af083 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` 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 ec0f0708b156f..6eea25b4fc8f8 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(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { - | ~~~ + | ++ 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 a7512158661fb..1339c644f5339 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 0943e0cc0d9d4..144f9454513c5 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 5af5123c03237..2d8c6e996439d 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 6abaad7f5d218..834292d103dc8 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 { 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 cbc1b862caabd..3c01375d50191 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 6c3944e5ea580..fa2a2d3460fea 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 { 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 7d239a54eda4f..f8ed92111a967 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 460d2ce2cc907..13cc3a431a5d2 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 fd167cf392fb6..2892d790ac7b8 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 52189084f04c0..ceb0ce345a3eb 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 92f774767c863..3744dd9f996ce 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 73a362d28e7d7..376e58ef9e07e 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 { x } help: consider specifying it explicitly | LL | fn defining<'a, T>(x: &'a i32) -> Opaque<'a, T> { x } - | ~~~~ + | +++ error[E0700]: hidden type for `Opaque2` 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 Date: Sun, 1 Sep 2024 16:49:55 +0300 Subject: [PATCH 13/15] 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 693f1b2258745..ae7e965985635 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2639,6 +2639,13 @@ impl 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 713e4e4dcf5ca..ef74bfe32375e 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 394259ce55ddb..177ff20fbf9ea 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 >::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 >::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 0f0d75dbac13e..5aee282952aa2 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 >::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 >::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 1e88a908af083..4b348a182b87f 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 { ... 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` 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 ccea9d5e6e92a..d0f8f7689d17c 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 a60f398684330..50a9f3ebeabb8 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 6eea25b4fc8f8..bff3ffd934ac6 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(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { - | ++ 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 1339c644f5339..f835d2655bb01 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 144f9454513c5..2d5d4fb0e72ec 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 834292d103dc8..249ae146b1675 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 { | -- ^ 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 f8ed92111a967..b44a184c6848f 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 13cc3a431a5d2..4465dbae52989 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 2892d790ac7b8..32de3fd18c97f 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 ceb0ce345a3eb..cd8f4d8adf8b1 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 3744dd9f996ce..30f4509d49dee 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 baa5fa949ec41..ea01dcd5020cf 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 376e58ef9e07e..e2c21f1636b0c 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 { 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` 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 Date: Sat, 7 Sep 2024 09:23:28 +0800 Subject: [PATCH 14/15] Add missing quotation marks Signed-off-by: cuishuang --- 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 ee4ad4e7c4e7b..95a28b61dde3a 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 Date: Mon, 2 Sep 2024 12:43:35 -0400 Subject: [PATCH 15/15] 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 8e8d91ce4d038..ec9a676ea3135 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 fcdc10c0837e5..f6f66821df7fb 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 { + 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 = 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 3476520960585..cabbdb0209222 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 { + 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 { + 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 f83bb3e3e35ae..951b0274b0d46 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 79c574ead61c3..00f372bc0082c 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: `: ` + | ^^^^ 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(: ) {} + | ~~~~~~~~~~~~~~~~~~~~ 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: `: ` + | ^^^^ 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(: ) {} + | ~~~~~~~~~~~~~~~~~~~~ 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 1318bee3da83d..677da53e3400d 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 a98bb23f5d65e..4be4b56e5056a 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 bdca2657ef39b..5646b26143c40 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 f52544ac45ce2..fd59999ab635f 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(_arr: [i32; N]) {} | ^ expected one of `,`, `:`, `=`, or `>` + | +help: there is a keyword `const` with a similar name + | +LL | fn foo(_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 de1ad9d2bf76d..35e4d731db768 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 cbf3b43fa585b..d2236ab074da7 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 102ce7014e470..5393a730506d9 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 e0f0f8ed18f91..d86ae326ce2e3 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 bdcf831a88a39..883f5cea73eff 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 64ca66794adba..8dd5a4645f362 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 ca0918e820f87..15a8f99b8b10d 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() -> u8 {} | ^^^^^ expected one of 7 possible tokens | +help: there is a keyword `impl` with a similar name + | +LL | fn code() -> u8 {} + | ~~~~ help: you might have meant to end the type parameters here | LL | fn code Debug>() -> u8 {} diff --git a/tests/ui/parser/misspelled-keywords/let-else.stderr b/tests/ui/parser/misspelled-keywords/let-else.stderr index 826e7de4b11a5..6f41a0d99dba9 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 449f0133d6536..766d2a049090b 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 77aeb21369c13..c2dcdef541d81 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 bc3eece1c9d9a..90780ebd38ef0 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 135f70ccfcbba..6daeb4e5a152e 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 15715514e6651..82ca7105a4965 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 2c23fe7a0afe8..3a79b7bdb0023 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 94789e7a92cd8..efa45f3229909 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 1e5d25c709e7d..3c25af548a3df 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 698cd47b16972..003aa3929bc22 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 8f678f4ad2e03..559182f9c8f68 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 2013df1c34aa8..b13281b039511 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 4ca01dedd6b28..db6dffdb613c5 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 4b3f996c11254..5143c30ca5103 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() -> 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 8d19b3c572264..37d337f3f1959 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 8147a5de69673..7d150443f57e7 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