Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/elaborator/statements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ impl Elaborator<'_> {
}

let warn_if_unused =
!let_stmt.attributes.iter().any(|attr| attr.kind.is_allow_unused_variables());
!let_stmt.attributes.iter().any(|attr| attr.kind.is_allow("unused_variables"));

let r#type = annotated_type;
let pattern = self.elaborate_pattern_and_store_ids(
Expand Down
34 changes: 25 additions & 9 deletions compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,8 @@
let mut trait_definition = trait_definition.item;
let name = trait_definition.name.clone();
let location = trait_definition.location;
let has_allow_dead_code =
trait_definition.attributes.iter().any(|attr| attr.kind.is_allow("dead_code"));

// Create the corresponding module for the trait namespace
let trait_id = match self.push_child_module(
Expand Down Expand Up @@ -481,12 +483,14 @@
);

let parent_module_id = ModuleId { krate, local_id: self.module_id };
context.usage_tracker.add_unused_item(
parent_module_id,
name.clone(),
UnusedItem::Trait(trait_id),
visibility,
);
if !has_allow_dead_code {
context.usage_tracker.add_unused_item(
parent_module_id,
name.clone(),
UnusedItem::Trait(trait_id),
visibility,
);
}

if let Err((first_def, second_def)) = result {
let error = DefCollectorErrorKind::Duplicate {
Expand Down Expand Up @@ -922,7 +926,7 @@
// if it's an inline module, or the first char of a the file if it's an external module.
// - `location` will always point to the token "foo" in `mod foo` regardless of whether
// it's inline or external.
// Eventually the location put in `ModuleData` is used for codelenses about `contract`s,

Check warning on line 929 in compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (codelenses)
// so we keep using `location` so that it continues to work as usual.
let location = Location::new(mod_name.span(), mod_location.file);
let new_module = ModuleData::new(
Expand Down Expand Up @@ -1013,6 +1017,7 @@
function.name() == MAIN_FUNCTION
};
let has_export = function.def.attributes.has_export();
let has_allow_dead_code = function.def.attributes.has_allow("dead_code");

let name = function.name_ident().clone();
let func_id = interner.push_empty_fn();
Expand All @@ -1023,7 +1028,12 @@
interner.register_function(func_id, &function.def);
}

if !is_test && !is_fuzzing_harness && !is_entry_point_function && !has_export {
if !is_test
&& !is_fuzzing_harness
&& !is_entry_point_function
&& !has_export
&& !has_allow_dead_code
{
let item = UnusedItem::Function(func_id);
usage_tracker.add_unused_item(module, name.clone(), item, visibility);
}
Expand Down Expand Up @@ -1109,7 +1119,10 @@

let parent_module_id = ModuleId { krate, local_id: module_id };

if !unresolved.struct_def.is_abi() {
let has_allow_dead_code =
unresolved.struct_def.attributes.iter().any(|attr| attr.kind.is_allow("dead_code"));

if !unresolved.struct_def.is_abi() && !has_allow_dead_code {
usage_tracker.add_unused_item(
parent_module_id,
name.clone(),
Expand Down Expand Up @@ -1200,7 +1213,10 @@

let parent_module_id = ModuleId { krate, local_id: module_id };

if !unresolved.enum_def.is_abi() {
let has_allow_dead_code =
unresolved.enum_def.attributes.iter().any(|attr| attr.kind.is_allow("dead_code"));

if !unresolved.enum_def.is_abi() && !has_allow_dead_code {
usage_tracker.add_unused_item(
parent_module_id,
name.clone(),
Expand Down
8 changes: 6 additions & 2 deletions compiler/noirc_frontend/src/lexer/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,7 @@
}
}

/// FuzzingScopr is used to specify additional annotations for fuzzing harnesses

Check warning on line 751 in compiler/noirc_frontend/src/lexer/token.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (Scopr)
#[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)]
pub enum FuzzingScope {
/// If a fuzzing harness has a scope of OnlyFailWith, then it will only detect an assert
Expand Down Expand Up @@ -859,6 +859,10 @@
self.has_secondary_attr(&SecondaryAttributeKind::Export)
}

pub fn has_allow(&self, name: &'static str) -> bool {
self.secondary.iter().any(|attr| attr.kind.is_allow(name))
}

/// Check if secondary attributes contain a specific instance.
pub fn has_secondary_attr(&self, kind: &SecondaryAttributeKind) -> bool {
self.secondary.iter().any(|attr| &attr.kind == kind)
Expand Down Expand Up @@ -1028,9 +1032,9 @@
}

impl SecondaryAttributeKind {
pub(crate) fn is_allow_unused_variables(&self) -> bool {
pub(crate) fn is_allow(&self, name: &'static str) -> bool {
match self {
SecondaryAttributeKind::Allow(string) => string == "unused_variables",
SecondaryAttributeKind::Allow(string) => string == name,
_ => false,
}
}
Expand Down
52 changes: 52 additions & 0 deletions compiler/noirc_frontend/src/tests/unused_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,3 +409,55 @@ fn does_not_consider_struct_as_constructed_if_mentioned_in_function_argument() {
";
check_errors!(src);
}

#[named]
#[test]
fn allow_dead_code_on_unused_function() {
let src = "
#[allow(dead_code)]
fn foo() {}

fn main() {
}
";
assert_no_errors!(src);
}

#[named]
#[test]
fn allow_dead_code_on_unused_struct() {
let src = "
#[allow(dead_code)]
struct Foo {}

fn main() {
}
";
assert_no_errors!(src);
}

#[named]
#[test]
fn allow_dead_code_on_unused_trait() {
let src = "
#[allow(dead_code)]
trait Foo {}

fn main() {
}
";
assert_no_errors!(src);
}

#[named]
#[test]
fn allow_dead_code_on_unused_enum() {
let src = "
#[allow(dead_code)]
enum Foo {}

fn main() {
}
";
assert_no_errors!(src);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

[package]
name = "noirc_frontend_tests_unused_items_allow_dead_code_on_unused_enum"
type = "bin"
authors = [""]

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

#[allow(dead_code)]
enum Foo {}

fn main() {
}

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2912787966510288424
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

[package]
name = "noirc_frontend_tests_unused_items_allow_dead_code_on_unused_function"
type = "bin"
authors = [""]

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

#[allow(dead_code)]
fn foo() {}

fn main() {
}

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8138537160766711355
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

[package]
name = "noirc_frontend_tests_unused_items_allow_dead_code_on_unused_struct"
type = "bin"
authors = [""]

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

#[allow(dead_code)]
struct Foo {}

fn main() {
}

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
14645872963190054969
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

[package]
name = "noirc_frontend_tests_unused_items_allow_dead_code_on_unused_trait"
type = "bin"
authors = [""]

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

#[allow(dead_code)]
trait Foo {}

fn main() {
}

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
14851478487121828974
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

[package]
name = "noirc_frontend_tests_unused_items_allow_dead_code_on_unused_type_alias"
type = "bin"
authors = [""]

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

#[allow(dead_code)]
type Foo = Field;

fn main() {
}

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
10281445062708207909
27 changes: 19 additions & 8 deletions tooling/lsp/src/requests/completion/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,17 @@ impl NodeFinder<'_> {

pub(super) fn suggest_builtin_attributes(&mut self, prefix: &str, target: AttributeTarget) {
match target {
AttributeTarget::Module | AttributeTarget::Trait => (),
AttributeTarget::Module => (),
AttributeTarget::Trait => {
self.suggest_allow("dead_code", prefix);
}
AttributeTarget::Struct => {
self.suggest_one_argument_attributes(prefix, &["abi"]);
self.suggest_allow("dead_code", prefix);
}
AttributeTarget::Enum => {
self.suggest_one_argument_attributes(prefix, &["abi"]);
self.suggest_allow("dead_code", prefix);
}
AttributeTarget::Function => {
let no_arguments_attributes = &[
Expand Down Expand Up @@ -147,18 +152,24 @@ impl NodeFinder<'_> {
None,
));
}

self.suggest_allow("dead_code", prefix);
}
AttributeTarget::Let => {
if name_matches("allow", prefix) || name_matches("unused_variables", prefix) {
self.completion_items.push(simple_completion_item(
"allow(unused_variables)",
CompletionItemKind::METHOD,
None,
));
}
self.suggest_allow("unused_variables", prefix);
}
}
}

fn suggest_allow(&mut self, name: &'static str, prefix: &str) {
if name_matches("allow", prefix) || name_matches(name, prefix) {
self.completion_items.push(simple_completion_item(
format!("allow({name})"),
CompletionItemKind::METHOD,
None,
));
}
}
}

pub(super) fn builtin_integer_types() -> [&'static str; 9] {
Expand Down
14 changes: 14 additions & 0 deletions tooling/lsp/src/requests/completion/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2414,6 +2414,20 @@ fn main() {
.await;
}

#[test]
async fn test_suggests_built_in_allow_function_attribute() {
let src = r#"
#[dead_c>|<]
fn foo() {}
"#;

assert_completion_excluding_auto_import(
src,
vec![simple_completion_item("allow(dead_code)", CompletionItemKind::METHOD, None)],
)
.await;
}

#[test]
async fn test_suggests_built_in_let_attribute() {
let src = r#"
Expand Down
Loading