From 7ac0cb0ec1152a9a64da0d444b5f21c801f9ca77 Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Tue, 3 Aug 2021 11:19:35 -0400 Subject: [PATCH 1/2] Add test for naked function unused variables lint This test proves that naked functions are treated the same as regular functions regarding unused function parameters. We will change this behavior in the next patch. --- src/test/ui/asm/naked-functions-unused.rs | 91 ++++++++++++ src/test/ui/asm/naked-functions-unused.stderr | 129 ++++++++++++++++++ 2 files changed, 220 insertions(+) create mode 100644 src/test/ui/asm/naked-functions-unused.rs create mode 100644 src/test/ui/asm/naked-functions-unused.stderr diff --git a/src/test/ui/asm/naked-functions-unused.rs b/src/test/ui/asm/naked-functions-unused.rs new file mode 100644 index 0000000000000..1790541e00904 --- /dev/null +++ b/src/test/ui/asm/naked-functions-unused.rs @@ -0,0 +1,91 @@ +// only-x86_64 +#![deny(unused)] +#![feature(asm)] +#![feature(naked_functions)] +#![crate_type = "lib"] + +pub trait Trait { + extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize; + extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize; +} + +pub mod normal { + pub extern "sysv64" fn function(a: usize, b: usize) -> usize { + //~^ ERROR unused variable: `a` + //~| ERROR unused variable: `b` + unsafe { asm!("", options(noreturn)); } + } + + pub struct Normal; + + impl Normal { + pub extern "sysv64" fn associated(a: usize, b: usize) -> usize { + //~^ ERROR unused variable: `a` + //~| ERROR unused variable: `b` + unsafe { asm!("", options(noreturn)); } + } + + pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize { + //~^ ERROR unused variable: `a` + //~| ERROR unused variable: `b` + unsafe { asm!("", options(noreturn)); } + } + } + + impl super::Trait for Normal { + extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize { + //~^ ERROR unused variable: `a` + //~| ERROR unused variable: `b` + unsafe { asm!("", options(noreturn)); } + } + + extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize { + //~^ ERROR unused variable: `a` + //~| ERROR unused variable: `b` + unsafe { asm!("", options(noreturn)); } + } + } +} + +pub mod naked { + #[naked] + pub extern "sysv64" fn function(a: usize, b: usize) -> usize { + //~^ ERROR unused variable: `a` + //~| ERROR unused variable: `b` + unsafe { asm!("", options(noreturn)); } + } + + pub struct Naked; + + impl Naked { + #[naked] + pub extern "sysv64" fn associated(a: usize, b: usize) -> usize { + //~^ ERROR unused variable: `a` + //~| ERROR unused variable: `b` + unsafe { asm!("", options(noreturn)); } + } + + #[naked] + pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize { + //~^ ERROR unused variable: `a` + //~| ERROR unused variable: `b` + unsafe { asm!("", options(noreturn)); } + } + } + + impl super::Trait for Naked { + #[naked] + extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize { + //~^ ERROR unused variable: `a` + //~| ERROR unused variable: `b` + unsafe { asm!("", options(noreturn)); } + } + + #[naked] + extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize { + //~^ ERROR unused variable: `a` + //~| ERROR unused variable: `b` + unsafe { asm!("", options(noreturn)); } + } + } +} diff --git a/src/test/ui/asm/naked-functions-unused.stderr b/src/test/ui/asm/naked-functions-unused.stderr new file mode 100644 index 0000000000000..3fffd09e7a54b --- /dev/null +++ b/src/test/ui/asm/naked-functions-unused.stderr @@ -0,0 +1,129 @@ +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:13:37 + | +LL | pub extern "sysv64" fn function(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + | +note: the lint level is defined here + --> $DIR/naked-functions-unused.rs:2:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:13:47 + | +LL | pub extern "sysv64" fn function(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:22:43 + | +LL | pub extern "sysv64" fn associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:22:53 + | +LL | pub extern "sysv64" fn associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:28:46 + | +LL | pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:28:56 + | +LL | pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:36:45 + | +LL | extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:36:55 + | +LL | extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:42:48 + | +LL | extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:42:58 + | +LL | extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:52:37 + | +LL | pub extern "sysv64" fn function(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:52:47 + | +LL | pub extern "sysv64" fn function(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:62:43 + | +LL | pub extern "sysv64" fn associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:62:53 + | +LL | pub extern "sysv64" fn associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:69:46 + | +LL | pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:69:56 + | +LL | pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:78:45 + | +LL | extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:78:55 + | +LL | extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:85:48 + | +LL | extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:85:58 + | +LL | extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: aborting due to 20 previous errors + From 9c0147c02d7a58d41d25d7604d65bbb02b6d21b0 Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Tue, 3 Aug 2021 16:45:55 -0400 Subject: [PATCH 2/2] Disable unused variable lint for naked functions In most calling conventions, accessing function parameters may require stack access. However, naked functions have no assembly prelude to set up stack access. This is why naked functions may only contain a single `asm!()` block. All parameter access is done inside the `asm!()` block, so we cannot validate the liveness of the input parameters. Therefore, we should disable the lint for naked functions. rust-lang/rfcs#2774 rust-lang/rfcs#2972 --- compiler/rustc_passes/src/liveness.rs | 5 ++ src/test/ui/asm/naked-functions-unused.rs | 10 --- src/test/ui/asm/naked-functions-unused.stderr | 62 +------------------ 3 files changed, 6 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 4ceefa17bcf3d..f2c2521ab43e4 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -332,6 +332,11 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { } } + // Don't run unused pass for #[naked] + if self.tcx.has_attr(def_id, sym::naked) { + return; + } + if let Some(captures) = maps.tcx.typeck(local_def_id).closure_min_captures.get(&def_id) { for &var_hir_id in captures.keys() { let var_name = maps.tcx.hir().name(var_hir_id); diff --git a/src/test/ui/asm/naked-functions-unused.rs b/src/test/ui/asm/naked-functions-unused.rs index 1790541e00904..e1f2362bb6fd0 100644 --- a/src/test/ui/asm/naked-functions-unused.rs +++ b/src/test/ui/asm/naked-functions-unused.rs @@ -50,8 +50,6 @@ pub mod normal { pub mod naked { #[naked] pub extern "sysv64" fn function(a: usize, b: usize) -> usize { - //~^ ERROR unused variable: `a` - //~| ERROR unused variable: `b` unsafe { asm!("", options(noreturn)); } } @@ -60,15 +58,11 @@ pub mod naked { impl Naked { #[naked] pub extern "sysv64" fn associated(a: usize, b: usize) -> usize { - //~^ ERROR unused variable: `a` - //~| ERROR unused variable: `b` unsafe { asm!("", options(noreturn)); } } #[naked] pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize { - //~^ ERROR unused variable: `a` - //~| ERROR unused variable: `b` unsafe { asm!("", options(noreturn)); } } } @@ -76,15 +70,11 @@ pub mod naked { impl super::Trait for Naked { #[naked] extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize { - //~^ ERROR unused variable: `a` - //~| ERROR unused variable: `b` unsafe { asm!("", options(noreturn)); } } #[naked] extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize { - //~^ ERROR unused variable: `a` - //~| ERROR unused variable: `b` unsafe { asm!("", options(noreturn)); } } } diff --git a/src/test/ui/asm/naked-functions-unused.stderr b/src/test/ui/asm/naked-functions-unused.stderr index 3fffd09e7a54b..840353366b670 100644 --- a/src/test/ui/asm/naked-functions-unused.stderr +++ b/src/test/ui/asm/naked-functions-unused.stderr @@ -65,65 +65,5 @@ error: unused variable: `b` LL | extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` -error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:52:37 - | -LL | pub extern "sysv64" fn function(a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_a` - -error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:52:47 - | -LL | pub extern "sysv64" fn function(a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_b` - -error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:62:43 - | -LL | pub extern "sysv64" fn associated(a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_a` - -error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:62:53 - | -LL | pub extern "sysv64" fn associated(a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_b` - -error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:69:46 - | -LL | pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_a` - -error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:69:56 - | -LL | pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_b` - -error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:78:45 - | -LL | extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_a` - -error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:78:55 - | -LL | extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_b` - -error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:85:48 - | -LL | extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_a` - -error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:85:58 - | -LL | extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_b` - -error: aborting due to 20 previous errors +error: aborting due to 10 previous errors