-
Notifications
You must be signed in to change notification settings - Fork 221
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: separate methods in
dc_crate
into their own modules (#3585)
Co-authored-by: Tom French <[email protected]>
- Loading branch information
1 parent
824039b
commit 1b5db48
Showing
8 changed files
with
883 additions
and
747 deletions.
There are no files selected for viewing
770 changes: 23 additions & 747 deletions
770
compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
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)> { | ||
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() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
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 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); | ||
|
||
(global.file_id, global.stmt_id) | ||
}); | ||
ResolvedGlobals { globals, errors } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
Oops, something went wrong.