Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 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
40 changes: 19 additions & 21 deletions compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::hir::resolution::errors::ResolverError;
use crate::hir::resolution::path_resolver;
use crate::hir::type_check::TypeCheckError;
use crate::token::SecondaryAttribute;
use crate::usage_tracker::UnusedItem;
use crate::{Generics, Type};

use crate::hir::resolution::import::{resolve_import, ImportDirective, PathResolution};
Expand Down Expand Up @@ -271,7 +272,7 @@ impl DefCollector {
root_file_id: FileId,
debug_comptime_in_file: Option<&str>,
enable_arithmetic_generics: bool,
error_on_usage_tracker: bool,
error_on_unused_items: bool,
macro_processors: &[&dyn MacroProcessor],
) -> Vec<(CompilationError, FileId)> {
let mut errors: Vec<(CompilationError, FileId)> = vec![];
Expand Down Expand Up @@ -406,20 +407,14 @@ impl DefCollector {
let result = current_def_map.modules[resolved_import.module_scope.0]
.import(name.clone(), visibility, module_def_id, is_prelude);

// Empty spans could come from implicitly injected imports, and we don't want to track those
if visibility != ItemVisibility::Public
&& name.span().start() < name.span().end()
{
let module_id = ModuleId {
krate: crate_id,
local_id: resolved_import.module_scope,
};

context
.def_interner
.usage_tracker
.add_unused_import(module_id, name.clone());
}
let module_id =
ModuleId { krate: crate_id, local_id: resolved_import.module_scope };
context.def_interner.usage_tracker.add_unused_item(
module_id,
name.clone(),
UnusedItem::Import,
visibility,
);

if visibility != ItemVisibility::Private {
let local_id = resolved_import.module_scope;
Expand Down Expand Up @@ -494,26 +489,29 @@ impl DefCollector {
);
}

if error_on_usage_tracker {
Self::check_usage_tracker(context, crate_id, &mut errors);
if error_on_unused_items {
Self::check_unused_items(context, crate_id, &mut errors);
}

errors
}

fn check_usage_tracker(
fn check_unused_items(
context: &Context,
crate_id: CrateId,
errors: &mut Vec<(CompilationError, FileId)>,
) {
let unused_imports = context.def_interner.usage_tracker.unused_imports().iter();
let unused_imports = context.def_interner.usage_tracker.unused_items().iter();
let unused_imports = unused_imports.filter(|(module_id, _)| module_id.krate == crate_id);

errors.extend(unused_imports.flat_map(|(module_id, usage_tracker)| {
let module = &context.def_maps[&crate_id].modules()[module_id.local_id.0];
usage_tracker.iter().map(|ident| {
usage_tracker.iter().map(|(ident, unused_item)| {
let ident = ident.clone();
let error = CompilationError::ResolverError(ResolverError::UnusedImport { ident });
let error = CompilationError::ResolverError(ResolverError::UnusedItem {
ident,
item_type: unused_item.item_type(),
});
(error, module.location.file)
})
}));
Expand Down
24 changes: 21 additions & 3 deletions compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::hir::resolution::errors::ResolverError;
use crate::macros_api::{Expression, NodeInterner, StructId, UnresolvedType, UnresolvedTypeData};
use crate::node_interner::ModuleAttributes;
use crate::token::SecondaryAttribute;
use crate::usage_tracker::UnusedItem;
use crate::{
graph::CrateId,
hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait},
Expand All @@ -36,7 +37,7 @@ use super::{
},
errors::{DefCollectorErrorKind, DuplicateType},
};
use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleData, ModuleId};
use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleData, ModuleId, MAIN_FUNCTION};
use crate::hir::resolution::import::ImportDirective;
use crate::hir::Context;

Expand Down Expand Up @@ -268,6 +269,15 @@ impl<'a> ModCollector<'a> {
context.def_interner.register_function(func_id, &function.def);
}

let module_data = &mut self.def_collector.def_map.modules[self.module_id.0];

let is_test = function.def.attributes.is_test_function();
let is_entry_point_function = if module_data.is_contract {
function.attributes().is_contract_entry_point()
} else {
function.name() == MAIN_FUNCTION
};

// Now link this func_id to a crate level map with the noir function and the module id
// Encountering a NoirFunction, we retrieve it's module_data to get the namespace
// Once we have lowered it to a HirFunction, we retrieve it's Id from the DefInterner
Expand All @@ -277,8 +287,16 @@ impl<'a> ModCollector<'a> {
unresolved_functions.push_fn(self.module_id, func_id, function);

// Add function to scope/ns of the module
let result = self.def_collector.def_map.modules[self.module_id.0]
.declare_function(name, visibility, func_id);
let result = module_data.declare_function(name.clone(), visibility, func_id);

if !is_test && !is_entry_point_function {
let module_id = ModuleId { krate, local_id: self.module_id };
let item = UnusedItem::Function(func_id);
context
.def_interner
.usage_tracker
.add_unused_item(module_id, name, item, visibility);
}

if let Err((first_def, second_def)) = result {
let error = DefCollectorErrorKind::Duplicate {
Expand Down
10 changes: 5 additions & 5 deletions compiler/noirc_frontend/src/hir/resolution/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ pub enum ResolverError {
DuplicateDefinition { name: String, first_span: Span, second_span: Span },
#[error("Unused variable")]
UnusedVariable { ident: Ident },
#[error("Unused import")]
UnusedImport { ident: Ident },
#[error("Unused {item_type}")]
UnusedItem { ident: Ident, item_type: &'static str },
#[error("Could not find variable in this scope")]
VariableNotDeclared { name: String, span: Span },
#[error("path is not an identifier")]
Expand Down Expand Up @@ -158,12 +158,12 @@ impl<'a> From<&'a ResolverError> for Diagnostic {
diagnostic.unnecessary = true;
diagnostic
}
ResolverError::UnusedImport { ident } => {
ResolverError::UnusedItem { ident, item_type } => {
let name = &ident.0.contents;

let mut diagnostic = Diagnostic::simple_warning(
format!("unused import {name}"),
"unused import ".to_string(),
format!("unused {item_type} {name}"),
format!("unused {item_type}"),
ident.span(),
);
diagnostic.unnecessary = true;
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/node_interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ impl Default for NodeInterner {
auto_import_names: HashMap::default(),
comptime_scopes: vec![HashMap::default()],
trait_impl_associated_types: HashMap::default(),
usage_tracker: UsageTracker::default(),
usage_tracker: UsageTracker::new(),
}
}
}
Expand Down
Loading