Skip to content
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/src/elaborator/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1375,8 +1375,8 @@ impl Elaborator<'_> {
},
};

let typ = self.resolve_type(constraint.typ.clone());
let Some(trait_bound) = self.resolve_trait_bound(&constraint.trait_bound) else {
let typ = self.use_type(constraint.typ.clone());
let Some(trait_bound) = self.use_trait_bound(&constraint.trait_bound) else {
// resolve_trait_bound only returns None if it has already issued an error, so don't
// issue another here.
let error = self.interner.push_expr_full(HirExpression::Error, location, Type::Error);
Expand Down
22 changes: 17 additions & 5 deletions compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ impl<'context> Elaborator<'context> {
if let UnresolvedGeneric::Numeric { ident, typ } = generic {
let unresolved_typ = typ.clone();
let typ = if unresolved_typ.is_type_expression() {
self.resolve_type_inner(
self.resolve_type_with_kind(
unresolved_typ.clone(),
&Kind::numeric(Type::default_int_type()),
)
Expand Down Expand Up @@ -889,12 +889,24 @@ impl<'context> Elaborator<'context> {
}

pub fn resolve_trait_bound(&mut self, bound: &TraitBound) -> Option<ResolvedTraitBound> {
self.resolve_trait_bound_inner(bound, false)
}

pub fn use_trait_bound(&mut self, bound: &TraitBound) -> Option<ResolvedTraitBound> {
self.resolve_trait_bound_inner(bound, true)
}

fn resolve_trait_bound_inner(
&mut self,
bound: &TraitBound,
r#use: bool,
) -> Option<ResolvedTraitBound> {
let the_trait = self.lookup_trait_or_error(bound.trait_path.clone())?;
let trait_id = the_trait.id;
let location = bound.trait_path.location;

let (ordered, named) =
self.resolve_type_args(bound.trait_generics.clone(), trait_id, location);
self.resolve_type_args_inner(bound.trait_generics.clone(), trait_id, location, r#use);

let trait_generics = TraitGenerics { ordered, named };
Some(ResolvedTraitBound { trait_id, trait_generics, location })
Expand Down Expand Up @@ -957,7 +969,7 @@ impl<'context> Elaborator<'context> {
self.desugar_impl_trait_arg(path, args, &mut generics, &mut trait_constraints)
}
// Function parameters have Kind::Normal
_ => self.resolve_type_inner(typ, &Kind::Normal),
_ => self.resolve_type_with_kind(typ, &Kind::Normal),
};

self.check_if_type_is_valid_for_program_input(
Expand All @@ -983,7 +995,7 @@ impl<'context> Elaborator<'context> {
parameter_types.push(typ);
}

let return_type = Box::new(self.resolve_type(func.return_type()));
let return_type = Box::new(self.use_type(func.return_type()));

let mut typ = Type::Function(
parameter_types,
Expand Down Expand Up @@ -1649,7 +1661,7 @@ impl<'context> Elaborator<'context> {

let generics = self.add_generics(&alias.type_alias_def.generics);
self.current_item = Some(DependencyId::Alias(alias_id));
let typ = self.resolve_type(alias.type_alias_def.typ);
let typ = self.use_type(alias.type_alias_def.typ);

if visibility != ItemVisibility::Private {
self.check_type_is_not_more_private_then_item(name, visibility, &typ, location);
Expand Down
49 changes: 43 additions & 6 deletions compiler/noirc_frontend/src/elaborator/path_resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,22 @@ impl Elaborator<'_> {
&mut self,
path: Path,
) -> Result<PathResolutionItem, ResolverError> {
let path_resolution = self.resolve_path(path)?;
self.resolve_path_or_error_inner(path, false)
}

pub(super) fn use_path_or_error(
&mut self,
path: Path,
) -> Result<PathResolutionItem, ResolverError> {
self.resolve_path_or_error_inner(path, true)
}

pub(super) fn resolve_path_or_error_inner(
&mut self,
path: Path,
r#use: bool,
) -> Result<PathResolutionItem, ResolverError> {
let path_resolution = self.resolve_path_inner(path, r#use)?;

for error in path_resolution.errors {
self.push_err(error);
Expand All @@ -116,11 +131,23 @@ impl Elaborator<'_> {
Ok(path_resolution.item)
}

pub(super) fn resolve_path(&mut self, path: Path) -> PathResolutionResult {
self.resolve_path_inner(path, false)
}

pub(super) fn use_path(&mut self, path: Path) -> PathResolutionResult {
self.resolve_path_inner(path, true)
}

/// Resolves a path in the current module.
/// If the referenced name can't be found, `Err` will be returned. If it can be found, `Ok`
/// will be returned with a potential list of errors if, for example, one of the segments
/// is not accessible from the current module (e.g. because it's private).
pub(super) fn resolve_path(&mut self, mut path: Path) -> PathResolutionResult {
pub(super) fn resolve_path_inner(
&mut self,
mut path: Path,
r#use: bool,
) -> PathResolutionResult {
let mut module_id = self.module_id();

if path.kind == PathKind::Plain && path.first_name() == Some(SELF_TYPE_NAME) {
Expand All @@ -138,7 +165,7 @@ impl Elaborator<'_> {
}
}

self.resolve_path_in_module(path, module_id)
self.resolve_path_in_module(path, module_id, r#use)
}

/// Resolves a path in `current_module`.
Expand All @@ -147,6 +174,7 @@ impl Elaborator<'_> {
&mut self,
path: Path,
importing_module: ModuleId,
r#use: bool,
) -> PathResolutionResult {
let references_tracker = if self.interner.is_in_lsp_mode() {
Some(ReferencesTracker::new(self.interner))
Expand All @@ -155,7 +183,7 @@ impl Elaborator<'_> {
};
let (path, module_id, _) =
resolve_path_kind(path, importing_module, self.def_maps, references_tracker)?;
self.resolve_name_in_module(path, module_id, importing_module)
self.resolve_name_in_module(path, module_id, importing_module, r#use)
}

/// Resolves a Path assuming we are inside `starting_module`.
Expand All @@ -165,6 +193,7 @@ impl Elaborator<'_> {
path: Path,
starting_module: ModuleId,
importing_module: ModuleId,
r#use: bool,
) -> PathResolutionResult {
// There is a possibility that the import path is empty. In that case, early return.
if path.segments.is_empty() {
Expand All @@ -189,7 +218,11 @@ impl Elaborator<'_> {
return Err(PathResolutionError::Unresolved(first_segment.clone()));
}

self.usage_tracker.mark_as_referenced(current_module_id, first_segment);
if r#use {
self.usage_tracker.mark_as_used(current_module_id, first_segment);
} else {
self.usage_tracker.mark_as_referenced(current_module_id, first_segment);
}

let mut errors = Vec::new();
for (index, (last_segment, current_segment)) in
Expand Down Expand Up @@ -313,7 +346,11 @@ impl Elaborator<'_> {
return Err(PathResolutionError::Unresolved(current_ident.clone()));
}

self.usage_tracker.mark_as_referenced(current_module_id, current_ident);
if r#use {
self.usage_tracker.mark_as_used(current_module_id, current_ident);
} else {
self.usage_tracker.mark_as_referenced(current_module_id, current_ident);
}

current_ns = found_ns;
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/noirc_frontend/src/elaborator/patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ impl Elaborator<'_> {
) -> Vec<Type> {
let kinds_with_types = kinds.into_iter().zip(turbofish_generics);
vecmap(kinds_with_types, |(kind, unresolved_type)| {
self.resolve_type_inner(unresolved_type, &kind)
self.use_type_with_kind(unresolved_type, &kind)
})
}

Expand Down Expand Up @@ -874,7 +874,7 @@ impl Elaborator<'_> {
pub(super) fn elaborate_type_path(&mut self, path: TypePath) -> (ExprId, Type) {
let location = path.item.location();
let object_location = path.typ.location;
let typ = self.resolve_type(path.typ);
let typ = self.use_type(path.typ);
let check_self_param = false;

let Some(method) = self.lookup_method(
Expand All @@ -893,7 +893,7 @@ impl Elaborator<'_> {
.expect("Expected trait function to be a DefinitionKind::Function");

let generics =
path.turbofish.map(|turbofish| self.resolve_type_args(turbofish, func_id, location).0);
path.turbofish.map(|turbofish| self.use_type_args(turbofish, func_id, location).0);

let id = self.interner.function_definition_id(func_id);

Expand Down
20 changes: 14 additions & 6 deletions compiler/noirc_frontend/src/elaborator/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl Elaborator<'_> {
path: Path,
) -> Result<(DefinitionId, PathResolutionItem), ResolverError> {
let location = path.location;
let item = self.resolve_path_or_error(path)?;
let item = self.use_path_or_error(path)?;

if let Some(function) = item.function_id() {
return Ok((self.interner.function_definition_id(function), item));
Expand Down Expand Up @@ -158,9 +158,13 @@ impl Elaborator<'_> {
}

/// Lookup a given struct type by name.
pub fn lookup_datatype_or_error(&mut self, path: Path) -> Option<Shared<DataType>> {
pub(super) fn lookup_datatype_or_error(
&mut self,
path: Path,
r#use: bool,
) -> Option<Shared<DataType>> {
let location = path.location;
match self.resolve_path_or_error(path) {
match self.resolve_path_or_error_inner(path, r#use) {
Ok(item) => {
if let PathResolutionItem::Type(struct_id) = item {
Some(self.get_type(struct_id))
Expand Down Expand Up @@ -191,7 +195,7 @@ impl Elaborator<'_> {
}

let location = path.location;
match self.resolve_path_or_error(path) {
match self.use_path_or_error(path) {
Ok(PathResolutionItem::Type(struct_id)) => {
let struct_type = self.get_type(struct_id);
let generics = struct_type.borrow().instantiate(self.interner);
Expand All @@ -217,8 +221,12 @@ impl Elaborator<'_> {
}
}

pub fn lookup_type_alias(&mut self, path: Path) -> Option<Shared<TypeAlias>> {
match self.resolve_path_or_error(path) {
pub(super) fn lookup_type_alias(
&mut self,
path: Path,
r#use: bool,
) -> Option<Shared<TypeAlias>> {
match self.resolve_path_or_error_inner(path, r#use) {
Ok(PathResolutionItem::TypeAlias(type_alias_id)) => {
Some(self.interner.get_type_alias(type_alias_id))
}
Expand Down
Loading
Loading