Skip to content

Commit

Permalink
move methods from dc_crate into their own modules
Browse files Browse the repository at this point in the history
  • Loading branch information
kevaundray committed Nov 26, 2023
1 parent 70ccb7e commit 240e908
Show file tree
Hide file tree
Showing 8 changed files with 885 additions and 748 deletions.
771 changes: 23 additions & 748 deletions compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs

Large diffs are not rendered by default.

86 changes: 86 additions & 0 deletions compiler/noirc_frontend/src/hir/resolution/functions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use std::{collections::BTreeMap, rc::Rc};

use fm::FileId;
use iter_extended::vecmap;
use noirc_errors::Span;

use crate::{
graph::CrateId,
hir::{
def_collector::dc_crate::{CompilationError, UnresolvedFunctions},
def_map::{CrateDefMap, ModuleId},
},
node_interner::{FuncId, NodeInterner, TraitImplId},
Shared, Type, TypeBinding,
};

use super::{path_resolver::StandardPathResolver, resolver::Resolver};

#[allow(clippy::too_many_arguments)]
pub(crate) fn resolve_function_set(
interner: &mut NodeInterner,
crate_id: CrateId,
def_maps: &BTreeMap<CrateId, CrateDefMap>,
mut unresolved_functions: UnresolvedFunctions,
self_type: Option<Type>,
trait_impl_id: Option<TraitImplId>,
impl_generics: Vec<(Rc<String>, Shared<TypeBinding>, Span)>,
errors: &mut Vec<(CompilationError, FileId)>,
) -> Vec<(FileId, FuncId)> {
let file_id = unresolved_functions.file_id;

let where_clause_errors =
unresolved_functions.resolve_trait_bounds_trait_ids(def_maps, crate_id);
errors.extend(where_clause_errors.iter().cloned().map(|e| (e.into(), file_id)));

vecmap(unresolved_functions.functions, |(mod_id, func_id, func)| {
let module_id = ModuleId { krate: crate_id, local_id: mod_id };
let path_resolver = StandardPathResolver::new(module_id);

let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file_id);
// Must use set_generics here to ensure we re-use the same generics from when
// the impl was originally collected. Otherwise the function will be using different
// TypeVariables for the same generic, causing it to instantiate incorrectly.
resolver.set_generics(impl_generics.clone());
resolver.set_self_type(self_type.clone());
resolver.set_trait_id(unresolved_functions.trait_id);
resolver.set_trait_impl_id(trait_impl_id);

// Without this, impl methods can accidentally be placed in contracts. See #3254
if self_type.is_some() {
resolver.set_in_contract(false);
}

let (hir_func, func_meta, errs) = resolver.resolve_function(func, func_id);
interner.push_fn_meta(func_meta, func_id);
interner.update_fn(func_id, hir_func);
errors.extend(errs.iter().cloned().map(|e| (e.into(), file_id)));
(file_id, func_id)
})
}

pub(crate) fn resolve_free_functions(
interner: &mut NodeInterner,
crate_id: CrateId,
def_maps: &BTreeMap<CrateId, CrateDefMap>,
collected_functions: Vec<UnresolvedFunctions>,
self_type: Option<Type>,
errors: &mut Vec<(CompilationError, FileId)>,
) -> Vec<(FileId, FuncId)> {
// Lower each function in the crate. This is now possible since imports have been resolved
collected_functions
.into_iter()
.flat_map(|unresolved_functions| {
resolve_function_set(
interner,
crate_id,
def_maps,
unresolved_functions,
self_type.clone(),
None,
vec![], // no impl generics
errors,
)
})
.collect()
}
56 changes: 56 additions & 0 deletions compiler/noirc_frontend/src/hir/resolution/globals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use super::{path_resolver::StandardPathResolver, resolver::Resolver, take_errors};
use crate::{
graph::CrateId,
hir::{
def_collector::dc_crate::{CompilationError, UnresolvedGlobal},
def_map::ModuleId,
Context,
},
node_interner::StmtId,
};
use fm::FileId;
use iter_extended::vecmap;

pub(crate) struct ResolvedGlobals {
pub(crate) globals: Vec<(FileId, StmtId)>,
pub(crate) errors: Vec<(CompilationError, FileId)>,
}

impl ResolvedGlobals {
pub(crate) fn extend(&mut self, oth: Self) {
self.globals.extend(oth.globals);
self.errors.extend(oth.errors);
}
}

pub(crate) fn resolve_globals(
context: &mut Context,
globals: Vec<UnresolvedGlobal>,
crate_id: CrateId,
) -> ResolvedGlobals {
let mut errors: Vec<(CompilationError, FileId)> = vec![];
let globals = vecmap(globals, |global| {
let module_id = ModuleId { local_id: global.module_id, krate: crate_id };
let path_resolver = StandardPathResolver::new(module_id);
let storage_slot = context.next_storage_slot(module_id);

let mut resolver = Resolver::new(
&mut context.def_interner,
&path_resolver,
&context.def_maps,
global.file_id,
);

let name = global.stmt_def.pattern.name_ident().clone();

let hir_stmt = resolver.resolve_global_let(global.stmt_def);
errors.extend(take_errors(global.file_id, resolver));

context.def_interner.update_global(global.stmt_id, hir_stmt);

context.def_interner.push_global(global.stmt_id, name, global.module_id, storage_slot);

(global.file_id, global.stmt_id)
});
ResolvedGlobals { globals, errors }
}
137 changes: 137 additions & 0 deletions compiler/noirc_frontend/src/hir/resolution/impls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use std::collections::BTreeMap;

use fm::FileId;

use crate::{
graph::CrateId,
hir::{
def_collector::{
dc_crate::{CompilationError, ImplMap},
errors::DefCollectorErrorKind,
},
def_map::{CrateDefMap, ModuleId},
Context,
},
node_interner::{FuncId, NodeInterner},
Type,
};

use super::{
errors::ResolverError, functions, get_module_mut, get_struct_type,
path_resolver::StandardPathResolver, resolver::Resolver, take_errors,
};

/// Go through the list of impls and add each function within to the scope
/// of the module defined by its type.
pub(crate) fn collect_impls(
context: &mut Context,
crate_id: CrateId,
collected_impls: &ImplMap,
) -> Vec<(CompilationError, FileId)> {
let interner = &mut context.def_interner;
let def_maps = &mut context.def_maps;
let mut errors: Vec<(CompilationError, FileId)> = vec![];

for ((unresolved_type, module_id), methods) in collected_impls {
let path_resolver =
StandardPathResolver::new(ModuleId { local_id: *module_id, krate: crate_id });

let file = def_maps[&crate_id].file_id(*module_id);

for (generics, span, unresolved) in methods {
let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file);
resolver.add_generics(generics);
let typ = resolver.resolve_type(unresolved_type.clone());

errors.extend(take_errors(unresolved.file_id, resolver));

if let Some(struct_type) = get_struct_type(&typ) {
let struct_type = struct_type.borrow();

// `impl`s are only allowed on types defined within the current crate
if struct_type.id.krate() != crate_id {
let span = *span;
let type_name = struct_type.name.to_string();
let error = DefCollectorErrorKind::ForeignImpl { span, type_name };
errors.push((error.into(), unresolved.file_id));
continue;
}

// Grab the module defined by the struct type. Note that impls are a case
// where the module the methods are added to is not the same as the module
// they are resolved in.
let module = get_module_mut(def_maps, struct_type.id.module_id());

for (_, method_id, method) in &unresolved.functions {
// If this method was already declared, remove it from the module so it cannot
// be accessed with the `TypeName::method` syntax. We'll check later whether the
// object types in each method overlap or not. If they do, we issue an error.
// If not, that is specialization which is allowed.
if module.declare_function(method.name_ident().clone(), *method_id).is_err() {
module.remove_function(method.name_ident());
}
}
// Prohibit defining impls for primitive types if we're not in the stdlib
} else if typ != Type::Error && !crate_id.is_stdlib() {
let span = *span;
let error = DefCollectorErrorKind::NonStructTypeInImpl { span };
errors.push((error.into(), unresolved.file_id));
}
}
}
errors
}

pub(crate) fn resolve_impls(
interner: &mut NodeInterner,
crate_id: CrateId,
def_maps: &BTreeMap<CrateId, CrateDefMap>,
collected_impls: ImplMap,
errors: &mut Vec<(CompilationError, FileId)>,
) -> Vec<(FileId, FuncId)> {
let mut file_method_ids = Vec::new();

for ((unresolved_type, module_id), methods) in collected_impls {
let path_resolver =
StandardPathResolver::new(ModuleId { local_id: module_id, krate: crate_id });

let file = def_maps[&crate_id].file_id(module_id);

for (generics, _, functions) in methods {
let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file);
resolver.add_generics(&generics);
let generics = resolver.get_generics().to_vec();
let self_type = resolver.resolve_type(unresolved_type.clone());

let mut file_func_ids = functions::resolve_function_set(
interner,
crate_id,
def_maps,
functions,
Some(self_type.clone()),
None,
generics,
errors,
);
if self_type != Type::Error {
for (file_id, method_id) in &file_func_ids {
let method_name = interner.function_name(method_id).to_owned();

if let Some(first_fn) =
interner.add_method(&self_type, method_name.clone(), *method_id, false)
{
let error = ResolverError::DuplicateDefinition {
name: method_name,
first_span: interner.function_ident(&first_fn).span(),
second_span: interner.function_ident(method_id).span(),
};
errors.push((error.into(), *file_id));
}
}
}
file_method_ids.append(&mut file_func_ids);
}
}

file_method_ids
}
47 changes: 47 additions & 0 deletions compiler/noirc_frontend/src/hir/resolution/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,50 @@ pub mod errors;
pub mod import;
pub mod path_resolver;
pub mod resolver;

mod functions;
mod globals;
mod impls;
mod structs;
mod traits;
mod type_aliases;

pub(crate) use functions::resolve_free_functions;
pub(crate) use globals::resolve_globals;
pub(crate) use impls::{collect_impls, resolve_impls};
pub(crate) use structs::resolve_structs;
pub(crate) use traits::{
collect_trait_impls, resolve_trait_by_path, resolve_trait_impls, resolve_traits,
};
pub(crate) use type_aliases::resolve_type_aliases;

use crate::{
graph::CrateId,
hir::{
def_collector::dc_crate::CompilationError,
def_map::{CrateDefMap, ModuleData, ModuleId},
},
Shared, StructType, Type,
};
use fm::FileId;
use iter_extended::vecmap;
use resolver::Resolver;
use std::collections::BTreeMap;

fn take_errors(file_id: FileId, resolver: Resolver<'_>) -> Vec<(CompilationError, FileId)> {
vecmap(resolver.take_errors(), |e| (e.into(), file_id))
}

fn get_module_mut(
def_maps: &mut BTreeMap<CrateId, CrateDefMap>,
module: ModuleId,
) -> &mut ModuleData {
&mut def_maps.get_mut(&module.krate).unwrap().modules[module.local_id.0]
}

fn get_struct_type(typ: &Type) -> Option<&Shared<StructType>> {
match typ {
Type::Struct(definition, _) => Some(definition),
_ => None,
}
}
53 changes: 53 additions & 0 deletions compiler/noirc_frontend/src/hir/resolution/structs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use std::collections::BTreeMap;

use fm::FileId;
use iter_extended::vecmap;

use crate::{
graph::CrateId,
hir::{
def_collector::dc_crate::{CompilationError, UnresolvedStruct},
def_map::ModuleId,
Context,
},
node_interner::StructId,
Generics, Ident, Type,
};

use super::{errors::ResolverError, path_resolver::StandardPathResolver, resolver::Resolver};

/// Create the mappings from TypeId -> StructType
/// so that expressions can access the fields of structs
pub(crate) fn resolve_structs(
context: &mut Context,
structs: BTreeMap<StructId, UnresolvedStruct>,
crate_id: CrateId,
) -> Vec<(CompilationError, FileId)> {
let mut errors: Vec<(CompilationError, FileId)> = vec![];
// Resolve each field in each struct.
// Each struct should already be present in the NodeInterner after def collection.
for (type_id, typ) in structs {
let file_id = typ.file_id;
let (generics, fields, resolver_errors) = resolve_struct_fields(context, crate_id, typ);
errors.extend(vecmap(resolver_errors, |err| (err.into(), file_id)));
context.def_interner.update_struct(type_id, |struct_def| {
struct_def.set_fields(fields);
struct_def.generics = generics;
});
}
errors
}

fn resolve_struct_fields(
context: &mut Context,
krate: CrateId,
unresolved: UnresolvedStruct,
) -> (Generics, Vec<(Ident, Type)>, Vec<ResolverError>) {
let path_resolver =
StandardPathResolver::new(ModuleId { local_id: unresolved.module_id, krate });
let file_id = unresolved.file_id;
let (generics, fields, errors) =
Resolver::new(&mut context.def_interner, &path_resolver, &context.def_maps, file_id)
.resolve_struct_fields(unresolved.struct_def);
(generics, fields, errors)
}
Loading

0 comments on commit 240e908

Please sign in to comment.