Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(experimental elaborator): Fix panic in the elaborator #5082

Merged
merged 48 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
d0afc12
Add elaborator
jfecher May 2, 2024
1c433ec
Merge branch 'master' into jf/elaborator
jfecher May 3, 2024
225303f
More expressions
jfecher May 6, 2024
29e67a1
Finish each expression kind
jfecher May 7, 2024
0177c12
Merge branch 'master' into jf/elaborator
jfecher May 7, 2024
6b30028
Add compiler flag
jfecher May 8, 2024
7550fb8
Move expressions into their own file
jfecher May 8, 2024
39d23dc
Merge branch 'jf/elaborator' into jf/integrate-elaborator
jfecher May 8, 2024
2e77d87
Connect elaborator
jfecher May 8, 2024
e542d32
Code review
jfecher May 8, 2024
fd287df
Finish removing Scope
jfecher May 8, 2024
73dc473
Merge branch 'jf/elaborator' into jf/integrate-elaborator
jfecher May 8, 2024
9614b87
Finish functions
jfecher May 8, 2024
b44c98a
Add should_panic
jfecher May 8, 2024
9579646
clippy
jfecher May 8, 2024
e4d5f61
Fix test
jfecher May 8, 2024
556e6ef
Fix test
jfecher May 9, 2024
7487b03
Elaborate impls
jfecher May 9, 2024
82d5871
Fix yet another missed line
jfecher May 9, 2024
a3872e0
Merge branch 'jf/integrate-elaborator' into jf/elaborator-impls
jfecher May 9, 2024
3fb05dc
Merge branch 'master' into jf/integrate-elaborator
jfecher May 9, 2024
4fa4677
Merge branch 'jf/integrate-elaborator' into jf/elaborator-impls
jfecher May 9, 2024
e9e69f4
Resolve weird git merge
jfecher May 9, 2024
d7d91ae
Wrong arg order
jfecher May 9, 2024
e9afa1a
Merge branch 'jf/integrate-elaborator' into jf/elaborator-impls
jfecher May 9, 2024
13564f8
Merge branch 'master' into jf/elaborator-impls
jfecher May 9, 2024
75c6451
Code review
jfecher May 10, 2024
bbecf41
Start work on traits + types (+ globals)?
jfecher May 10, 2024
0029558
Merge branch 'master' into jf/elaborator-types
jfecher May 21, 2024
7a37bf3
Add globals
jfecher May 21, 2024
464d58c
Format
jfecher May 21, 2024
ba893ae
Merge branch 'jf/elaborator-types' into jf/elaborator-globals
jfecher May 21, 2024
397fe78
Copy over comments from dc_crate
jfecher May 22, 2024
afcf26e
Remove unneeded comment
jfecher May 22, 2024
1f3e79b
Merge branch 'master' into jf/elaborator-globals
jfecher May 22, 2024
8522936
Re-add accidentally removed collect_traits call
jfecher May 22, 2024
bbb7228
Fix panic in the elaborator
jfecher May 22, 2024
1f9b6d0
Merge branch 'master' into jf/elaborator-fixes
jfecher May 22, 2024
78e6a27
Undo unnecessary change
jfecher May 22, 2024
3b59749
Remove more unnecessary code
jfecher May 22, 2024
bf999d9
Remove unnecessary import
jfecher May 22, 2024
7be1561
Remove outdated assert
jfecher May 22, 2024
f48280d
Merge branch 'master' into jf/elaborator-fixes
jfecher May 22, 2024
5c11a5f
Merge branch 'master' into jf/elaborator-fixes
TomAFrench May 22, 2024
5156727
chore(elaborator): Remove unused imports & code (#5085)
jfecher May 28, 2024
5b857d9
Merge branch 'master' into jf/elaborator-fixes
jfecher May 28, 2024
229976c
Remove unused FieldElement import
jfecher May 28, 2024
e2226d7
Update compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs
jfecher May 28, 2024
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
6 changes: 3 additions & 3 deletions compiler/noirc_frontend/src/elaborator/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ impl<'context> Elaborator<'context> {
expr_type: inner_expr_type.clone(),
expr_span: span,
});
}

if i + 1 == statements.len() {
block_type = stmt_type;
}
if i + 1 == statements.len() {
block_type = stmt_type;
jfecher marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down
143 changes: 116 additions & 27 deletions compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
#![allow(unused)]
use std::{
collections::{BTreeMap, BTreeSet},
collections::{BTreeMap, BTreeSet, HashMap},
rc::Rc,
};

use crate::{
ast::{
ArrayLiteral, ConstructorExpression, FunctionKind, IfExpression, InfixExpression, Lambda,
UnresolvedTraitConstraint, UnresolvedTypeExpression,
TraitItem, UnresolvedTraitConstraint, UnresolvedTypeExpression,
},
hir::{
def_collector::{
dc_crate::{
filter_literal_globals, CompilationError, UnresolvedGlobal, UnresolvedStruct,
UnresolvedTrait, UnresolvedTypeAlias,
filter_literal_globals, CompilationError, ImplMap, UnresolvedGlobal,
UnresolvedStruct, UnresolvedTrait, UnresolvedTypeAlias,
},
errors::DuplicateType,
},
Expand All @@ -28,6 +28,7 @@ use crate::{
HirInfixExpression, HirLambda, HirMemberAccess, HirMethodCallExpression,
HirMethodReference, HirPrefixExpression,
},
function::Parameters,
stmt::HirLetStatement,
traits::TraitConstraint,
},
Expand Down Expand Up @@ -80,6 +81,7 @@ mod types;

use fm::FileId;
use iter_extended::vecmap;
use noirc_arena::Index;
use noirc_errors::{Location, Span};
use regex::Regex;
use rustc_hash::FxHashSet as HashSet;
Expand Down Expand Up @@ -226,6 +228,8 @@ impl<'context> Elaborator<'context> {
this.define_type_alias(alias_id, alias);
}

this.define_function_metas(&mut items.functions, &mut items.impls, &mut items.trait_impls);

this.collect_traits(items.traits);

// Must resolve structs before we resolve globals.
Expand Down Expand Up @@ -268,7 +272,6 @@ impl<'context> Elaborator<'context> {

let cycle_errors = this.interner.check_for_dependency_cycles();
this.errors.extend(cycle_errors);

this.errors
}

Expand All @@ -285,7 +288,6 @@ impl<'context> Elaborator<'context> {

fn elaborate_function(&mut self, mut function: NoirFunction, id: FuncId) {
self.current_function = Some(id);
self.resolve_where_clause(&mut function.def.where_clause);
jfecher marked this conversation as resolved.
Show resolved Hide resolved

// Without this, impl methods can accidentally be placed in contracts. See #3254
if self.self_type.is_some() {
Expand All @@ -297,9 +299,6 @@ impl<'context> Elaborator<'context> {

// Check whether the function has globals in the local module and add them to the scope
self.resolve_local_globals();
self.add_generics(&function.def.generics);

self.desugar_impl_trait_args(&mut function, id);
self.trait_bounds = function.def.where_clause.clone();

let is_low_level_or_oracle = function
Expand All @@ -312,8 +311,21 @@ impl<'context> Elaborator<'context> {
self.in_unconstrained_fn = true;
}

let func_meta = self.extract_meta(&function, id);
let func_meta = self
.interner
.func_meta
.get(&id)
.expect("FuncMetas should be declared before a function is elaborated")
.clone();

for (parameter, param2) in function.def.parameters.iter().zip(&func_meta.parameters.0) {
let definition_kind = DefinitionKind::Local(None);
self.elaborate_pattern(parameter.pattern.clone(), param2.1.clone(), definition_kind);
jfecher marked this conversation as resolved.
Show resolved Hide resolved
}

self.add_generics(&function.def.generics);
self.desugar_impl_trait_args(&mut function, id);
self.declare_numeric_generics(&func_meta.parameters, func_meta.return_type());
self.add_trait_constraints_to_scope(&func_meta);

let (hir_func, body_type) = match function.kind {
Expand Down Expand Up @@ -369,7 +381,6 @@ impl<'context> Elaborator<'context> {

self.trait_bounds.clear();

self.interner.push_fn_meta(func_meta, id);
self.interner.update_fn(id, hir_func);
self.current_function = None;
}
Expand Down Expand Up @@ -531,9 +542,23 @@ impl<'context> Elaborator<'context> {

/// Extract metadata from a NoirFunction
/// to be used in analysis and intern the function parameters
/// Prerequisite: self.add_generics() has already been called with the given
/// function's generics, including any generics from the impl, if any.
fn extract_meta(&mut self, func: &NoirFunction, func_id: FuncId) -> FuncMeta {
/// Prerequisite: any implicit generics, including any generics from the impl,
/// have already been added to scope via `self.add_generics`.
fn define_function_meta(&mut self, func: &mut NoirFunction, func_id: FuncId) {
self.current_function = Some(func_id);
self.resolve_where_clause(&mut func.def.where_clause);

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

self.scopes.start_function();
self.current_item = Some(DependencyId::Function(func_id));

// Check whether the function has globals in the local module and add them to the scope
self.resolve_local_globals();

let location = Location::new(func.name_ident().span(), self.file);
let id = self.interner.function_definition_id(func_id);
let name_ident = HirIdent::non_trait_method(id, location);
Expand All @@ -558,6 +583,8 @@ impl<'context> Elaborator<'context> {
let has_inline_attribute = has_no_predicates_attribute || should_fold;
let is_entry_point = self.is_entry_point_function(func);

self.add_generics(&func.def.generics);

let mut generics = vecmap(&self.generics, |(_, typevar, _)| typevar.clone());
let mut parameters = vec![];
let mut parameter_types = vec![];
Expand Down Expand Up @@ -586,8 +613,6 @@ impl<'context> Elaborator<'context> {

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

self.declare_numeric_generics(&parameter_types, &return_type);

if !self.pub_allowed(func) && func.def.return_visibility == Visibility::Public {
self.push_err(ResolverError::UnnecessaryPub {
ident: func.name_ident().clone(),
Expand Down Expand Up @@ -640,7 +665,7 @@ impl<'context> Elaborator<'context> {
.map(|(name, typevar, _span)| (name.clone(), typevar.clone()))
.collect();

FuncMeta {
let meta = FuncMeta {
name: name_ident,
kind: func.kind,
location,
Expand All @@ -654,7 +679,12 @@ impl<'context> Elaborator<'context> {
trait_constraints: self.resolve_trait_constraints(&func.def.where_clause),
is_entry_point,
has_inline_attribute,
}
};

self.interner.push_fn_meta(meta, func_id);
self.current_function = None;
self.scopes.end_function();
self.current_item = None;
}

/// Only sized types are valid to be used as main's parameters or the parameters to a contract
Expand Down Expand Up @@ -694,7 +724,7 @@ impl<'context> Elaborator<'context> {
}
}

fn declare_numeric_generics(&mut self, params: &[Type], return_type: &Type) {
fn declare_numeric_generics(&mut self, params: &Parameters, return_type: &Type) {
if self.generics.is_empty() {
return;
}
Expand All @@ -717,11 +747,11 @@ impl<'context> Elaborator<'context> {
}

fn find_numeric_generics(
parameters: &[Type],
parameters: &Parameters,
return_type: &Type,
) -> Vec<(String, TypeVariable)> {
let mut found = BTreeMap::new();
for parameter in parameters {
for (_, parameter, _) in &parameters.0 {
jfecher marked this conversation as resolved.
Show resolved Hide resolved
Self::find_numeric_generics_in_type(parameter, &mut found);
}
Self::find_numeric_generics_in_type(return_type, &mut found);
Expand Down Expand Up @@ -835,10 +865,9 @@ impl<'context> Elaborator<'context> {
module: LocalModuleId,
impls: Vec<(Vec<Ident>, Span, UnresolvedFunctions)>,
) {
self.generics.clear();

for (generics, _, functions) in impls {
self.file = functions.file_id;
let old_generics_length = self.generics.len();
self.add_generics(&generics);
let self_type = self.resolve_type(typ.clone());
self.self_type = Some(self_type.clone());
Expand All @@ -862,6 +891,8 @@ impl<'context> Elaborator<'context> {
}
}
}

self.generics.truncate(old_generics_length);
}
}

Expand All @@ -871,16 +902,18 @@ impl<'context> Elaborator<'context> {

let unresolved_type = trait_impl.object_type;
let self_type_span = unresolved_type.span;
let old_generics_length = self.generics.len();
self.add_generics(&trait_impl.generics);

let trait_generics =
vecmap(&trait_impl.trait_generics, |generic| self.resolve_type(generic.clone()));

let self_type = self.resolve_type(unresolved_type.clone());
let impl_id = self.interner.next_trait_impl_id();
let self_type = trait_impl.resolved_object_type.unwrap_or(Type::Error);
let impl_id =
trait_impl.impl_id.expect("An impls' id should be set during define_function_metas");

self.self_type = Some(self_type.clone());
self.current_trait_impl = Some(impl_id);
self.current_trait_impl = trait_impl.impl_id;

let mut methods = trait_impl.methods.function_ids();

Expand Down Expand Up @@ -937,7 +970,7 @@ impl<'context> Elaborator<'context> {

self.self_type = None;
self.current_trait_impl = None;
self.generics.clear();
self.generics.truncate(old_generics_length);
}

fn collect_impls(
Expand Down Expand Up @@ -1229,4 +1262,60 @@ impl<'context> Elaborator<'context> {
self.interner.get_global_definition_mut(global_id).kind = definition_kind;
self.interner.replace_statement(statement_id, let_statement);
}

fn define_function_metas(
&mut self,
functions: &mut [UnresolvedFunctions],
impls: &mut ImplMap,
trait_impls: &mut [UnresolvedTraitImpl],
) {
for function_set in functions {
self.define_function_metas_for_functions(function_set);
}

for ((_typ, local_module), function_sets) in impls {
self.local_module = *local_module;

for (_generics, _, function_set) in function_sets {
self.define_function_metas_for_functions(function_set);
}
}

for trait_impl in trait_impls {
self.file = trait_impl.file_id;
self.local_module = trait_impl.module_id;

let unresolved_type = &trait_impl.object_type;
let self_type_span = unresolved_type.span;
let old_generics_length = self.generics.len();
self.add_generics(&trait_impl.generics);

let trait_generics =
vecmap(&trait_impl.trait_generics, |generic| self.resolve_type(generic.clone()));

let self_type = self.resolve_type(unresolved_type.clone());
let impl_id = self.interner.next_trait_impl_id();

self.self_type = Some(self_type.clone());
self.current_trait_impl = Some(impl_id);

let mut methods = trait_impl.methods.function_ids();
self.define_function_metas_for_functions(&mut trait_impl.methods);

trait_impl.resolved_object_type = self.self_type.take();
trait_impl.impl_id = self.current_trait_impl.take();
self.generics.truncate(old_generics_length);
}
}

fn define_function_metas_for_functions(&mut self, function_set: &mut UnresolvedFunctions) {
self.file = function_set.file_id;

for (local_module, id, func) in &mut function_set.functions {
self.local_module = *local_module;
let old_generics_length = self.generics.len();
self.define_function_meta(func, *id);
self.generics.truncate(old_generics_length);
}
}
}
1 change: 1 addition & 0 deletions compiler/noirc_frontend/src/elaborator/patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
},
hir_def::{
expr::{HirIdent, ImplKind},
function::FuncMeta,
stmt::HirPattern,
},
macros_api::{HirExpression, Ident, Path, Pattern},
Expand Down
8 changes: 3 additions & 5 deletions compiler/noirc_frontend/src/elaborator/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ use super::Elaborator;

impl<'context> Elaborator<'context> {
pub fn collect_traits(&mut self, traits: BTreeMap<TraitId, UnresolvedTrait>) {
for (trait_id, unresolved_trait) in &traits {
self.interner.push_empty_trait(*trait_id, unresolved_trait);
}

for (trait_id, unresolved_trait) in traits {
let generics = vecmap(&unresolved_trait.trait_def.generics, |_| {
TypeVariable::unbound(self.interner.next_type_variable_id())
Expand Down Expand Up @@ -187,7 +183,9 @@ impl<'context> Elaborator<'context> {
return_visibility: Visibility::Private,
};

self.elaborate_function(NoirFunction { kind, def }, func_id);
let mut function = NoirFunction { kind, def };
self.define_function_meta(&mut function, func_id);
self.elaborate_function(function, func_id);
let _ = self.scopes.end_function();
// Don't check the scope tree for unused variables, they can't be used in a declaration anyway.
self.trait_bounds.clear();
Expand Down
Loading
Loading