Skip to content

Commit

Permalink
feat: Implement type aliases (#2112)
Browse files Browse the repository at this point in the history
* .

* .

* .

* .

* stash

* .

* .

* .

* remove tyalias as an hir type

* namings

* .

* clippy

* move to collector

* working?

* working?

* move test to new_ssa

* resolve type alias name in module

* .

* comments

* review

* move test to test_data folder

* type aliases cannot be used in type namespace

* more efficient?

* remove comment

* use interner for id

* .

* Rework def_interner storage of aliases

* Update crates/noirc_frontend/src/ast/type_alias.rs

Co-authored-by: Maxim Vezenov <mvezenov@gmail.com>

* Update crates/noirc_frontend/src/ast/type_alias.rs

Co-authored-by: Maxim Vezenov <mvezenov@gmail.com>

* Update crates/noirc_frontend/src/ast/type_alias.rs

Co-authored-by: Maxim Vezenov <mvezenov@gmail.com>

* Update crates/noirc_frontend/src/hir/def_collector/dc_mod.rs

Co-authored-by: Maxim Vezenov <mvezenov@gmail.com>

* Update crates/noirc_frontend/src/hir/resolution/resolver.rs

Co-authored-by: Maxim Vezenov <mvezenov@gmail.com>

* typ -> type

---------

Co-authored-by: ethan-000 <ethan_000@outlook.com>
Co-authored-by: Ethan-000 <s2026080@ed.ac.uk>
Co-authored-by: Maxim Vezenov <mvezenov@gmail.com>
  • Loading branch information
4 people authored Aug 1, 2023
1 parent 920a900 commit ce94cb4
Show file tree
Hide file tree
Showing 16 changed files with 393 additions and 29 deletions.
6 changes: 6 additions & 0 deletions crates/nargo_cli/tests/test_data/type_aliases/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "type_aliases"
authors = [""]
compiler_version = "0.1"

[dependencies]
1 change: 1 addition & 0 deletions crates/nargo_cli/tests/test_data/type_aliases/Prover.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x = [2, 3]
31 changes: 31 additions & 0 deletions crates/nargo_cli/tests/test_data/type_aliases/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use dep::std;

type Foo<T> = [T; 2];

type Bar = Field;

type Three = Two<u8>;
type Two<A> = One<A, u32>;
type One<A, B> = (A, B);

struct MyStruct {
foo: Bar,
}

fn main(x : [Field; 2]) {
let a: Foo<Field> = [1, 2];
assert(a[0] != x[0]);

let b: Bar = 2;
assert(x[0] == b);

let c: u8 = 1;
let d: u32 = 2;
let e: Three = (c, d);
assert(e.0 == 1);

let s = MyStruct {
foo: 10
};
assert(s.foo == 10);
}
2 changes: 2 additions & 0 deletions crates/noirc_frontend/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod function;
mod statement;
mod structure;
mod traits;
mod type_alias;

pub use expression::*;
pub use function::*;
Expand All @@ -17,6 +18,7 @@ use noirc_errors::Span;
pub use statement::*;
pub use structure::*;
pub use traits::*;
pub use type_alias::*;

use crate::{
parser::{ParserError, ParserErrorReason},
Expand Down
31 changes: 31 additions & 0 deletions crates/noirc_frontend/src/ast/type_alias.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use crate::{Ident, UnresolvedGenerics, UnresolvedType};
use iter_extended::vecmap;
use noirc_errors::Span;
use std::fmt::Display;

/// Ast node for type aliases
#[derive(Clone, Debug)]
pub struct NoirTypeAlias {
pub name: Ident,
pub generics: UnresolvedGenerics,
pub typ: UnresolvedType,
pub span: Span,
}

impl NoirTypeAlias {
pub fn new(
name: Ident,
generics: UnresolvedGenerics,
typ: UnresolvedType,
span: Span,
) -> NoirTypeAlias {
NoirTypeAlias { name, generics, typ, span }
}
}

impl Display for NoirTypeAlias {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let generics = vecmap(&self.generics, |generic| generic.to_string());
write!(f, "type {}<{}> = {}", self.name, generics.join(", "), self.typ)
}
}
38 changes: 35 additions & 3 deletions crates/noirc_frontend/src/hir/def_collector/dc_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ use crate::hir::resolution::{
};
use crate::hir::type_check::{type_check_func, TypeChecker};
use crate::hir::Context;
use crate::node_interner::{FuncId, NodeInterner, StmtId, StructId};
use crate::node_interner::{FuncId, NodeInterner, StmtId, StructId, TypeAliasId};
use crate::{
ExpressionKind, Generics, Ident, LetStatement, NoirFunction, NoirStruct, ParsedModule, Shared,
Type, TypeBinding, UnresolvedGenerics, UnresolvedType,
ExpressionKind, Generics, Ident, LetStatement, NoirFunction, NoirStruct, NoirTypeAlias,
ParsedModule, Shared, Type, TypeBinding, UnresolvedGenerics, UnresolvedType,
};
use fm::FileId;
use iter_extended::vecmap;
Expand All @@ -40,6 +40,13 @@ pub struct UnresolvedStruct {
pub struct_def: NoirStruct,
}

#[derive(Clone)]
pub struct UnresolvedTypeAlias {
pub file_id: FileId,
pub module_id: LocalModuleId,
pub type_alias_def: NoirTypeAlias,
}

#[derive(Clone)]
pub struct UnresolvedGlobal {
pub file_id: FileId,
Expand All @@ -54,6 +61,7 @@ pub struct DefCollector {
pub(crate) collected_imports: Vec<ImportDirective>,
pub(crate) collected_functions: Vec<UnresolvedFunctions>,
pub(crate) collected_types: HashMap<StructId, UnresolvedStruct>,
pub(crate) collected_type_aliases: HashMap<TypeAliasId, UnresolvedTypeAlias>,
pub(crate) collected_globals: Vec<UnresolvedGlobal>,
pub(crate) collected_impls: ImplMap,
}
Expand All @@ -71,6 +79,7 @@ impl DefCollector {
collected_imports: vec![],
collected_functions: vec![],
collected_types: HashMap::new(),
collected_type_aliases: HashMap::new(),
collected_impls: HashMap::new(),
collected_globals: vec![],
}
Expand Down Expand Up @@ -157,6 +166,8 @@ impl DefCollector {

let mut file_global_ids = resolve_globals(context, integer_globals, crate_id, errors);

resolve_type_aliases(context, def_collector.collected_type_aliases, crate_id, errors);

// Must resolve structs before we resolve globals.
resolve_structs(context, def_collector.collected_types, crate_id, errors);

Expand Down Expand Up @@ -358,6 +369,27 @@ fn resolve_struct_fields(
(generics, fields)
}

fn resolve_type_aliases(
context: &mut Context,
type_aliases: HashMap<TypeAliasId, UnresolvedTypeAlias>,
crate_id: CrateId,
all_errors: &mut Vec<FileDiagnostic>,
) {
for (type_id, unresolved_typ) in type_aliases {
let path_resolver = StandardPathResolver::new(ModuleId {
local_id: unresolved_typ.module_id,
krate: crate_id,
});
let file = unresolved_typ.file_id;
let (typ, generics, errors) =
Resolver::new(&mut context.def_interner, &path_resolver, &context.def_maps, file)
.resolve_type_aliases(unresolved_typ.type_alias_def);
extend_errors(all_errors, file, errors);

context.def_interner.set_type_alias(type_id, typ, generics);
}
}

fn resolve_impls(
interner: &mut NodeInterner,
crate_id: CrateId,
Expand Down
40 changes: 38 additions & 2 deletions crates/noirc_frontend/src/hir/def_collector/dc_mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ use noirc_errors::FileDiagnostic;

use crate::{
graph::CrateId, hir::def_collector::dc_crate::UnresolvedStruct, node_interner::StructId,
parser::SubModule, Ident, LetStatement, NoirFunction, NoirStruct, ParsedModule, TypeImpl,
parser::SubModule, Ident, LetStatement, NoirFunction, NoirStruct, NoirTypeAlias, ParsedModule,
TypeImpl,
};

use super::{
dc_crate::{DefCollector, UnresolvedFunctions, UnresolvedGlobal},
dc_crate::{DefCollector, UnresolvedFunctions, UnresolvedGlobal, UnresolvedTypeAlias},
errors::DefCollectorErrorKind,
};
use crate::hir::def_map::{parse_file, LocalModuleId, ModuleData, ModuleId, ModuleOrigin};
Expand Down Expand Up @@ -55,6 +56,8 @@ pub fn collect_defs(

collector.collect_structs(ast.types, crate_id, errors);

collector.collect_type_aliases(context, ast.type_aliases, errors);

collector.collect_functions(context, ast.functions, errors);

collector.collect_impls(context, ast.impls);
Expand Down Expand Up @@ -183,6 +186,39 @@ impl<'a> ModCollector<'a> {
}
}

/// Collect any type aliases definitions declared within the ast.
/// Returns a vector of errors if any type aliases were already defined.
fn collect_type_aliases(
&mut self,
context: &mut Context,
type_aliases: Vec<NoirTypeAlias>,
errors: &mut Vec<FileDiagnostic>,
) {
for type_alias in type_aliases {
let name = type_alias.name.clone();

// And store the TypeId -> TypeAlias mapping somewhere it is reachable
let unresolved = UnresolvedTypeAlias {
file_id: self.file_id,
module_id: self.module_id,
type_alias_def: type_alias,
};

let type_alias_id = context.def_interner.push_type_alias(&unresolved);

// Add the type alias to scope so its path can be looked up later
let result = self.def_collector.def_map.modules[self.module_id.0]
.declare_type_alias(name, type_alias_id);

if let Err((first_def, second_def)) = result {
let err = DefCollectorErrorKind::DuplicateFunction { first_def, second_def };
errors.push(err.into_file_diagnostic(self.file_id));
}

self.def_collector.collected_type_aliases.insert(type_alias_id, unresolved);
}
}

fn collect_submodules(
&mut self,
context: &mut Context,
Expand Down
1 change: 1 addition & 0 deletions crates/noirc_frontend/src/hir/def_map/item_scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ impl ItemScope {
ModuleDefId::ModuleId(_) => add_item(&mut self.types),
ModuleDefId::FunctionId(_) => add_item(&mut self.values),
ModuleDefId::TypeId(_) => add_item(&mut self.types),
ModuleDefId::TypeAliasId(_) => add_item(&mut self.types),
ModuleDefId::GlobalId(_) => add_item(&mut self.values),
}
}
Expand Down
10 changes: 9 additions & 1 deletion crates/noirc_frontend/src/hir/def_map/module_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::collections::HashMap;
use fm::FileId;

use crate::{
node_interner::{FuncId, StmtId, StructId},
node_interner::{FuncId, StmtId, StructId, TypeAliasId},
Ident,
};

Expand Down Expand Up @@ -65,6 +65,14 @@ impl ModuleData {
self.declare(name, ModuleDefId::TypeId(id))
}

pub fn declare_type_alias(
&mut self,
name: Ident,
id: TypeAliasId,
) -> Result<(), (Ident, Ident)> {
self.declare(name, id.into())
}

pub fn declare_child_module(
&mut self,
name: Ident,
Expand Down
31 changes: 30 additions & 1 deletion crates/noirc_frontend/src/hir/def_map/module_def.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::node_interner::{FuncId, StmtId, StructId};
use crate::node_interner::{FuncId, StmtId, StructId, TypeAliasId};

use super::ModuleId;

Expand All @@ -8,6 +8,7 @@ pub enum ModuleDefId {
ModuleId(ModuleId),
FunctionId(FuncId),
TypeId(StructId),
TypeAliasId(TypeAliasId),
GlobalId(StmtId),
}

Expand All @@ -26,6 +27,13 @@ impl ModuleDefId {
}
}

pub fn as_type_alias(&self) -> Option<TypeAliasId> {
match self {
ModuleDefId::TypeAliasId(type_alias_id) => Some(*type_alias_id),
_ => None,
}
}

pub fn as_global(&self) -> Option<StmtId> {
match self {
ModuleDefId::GlobalId(stmt_id) => Some(*stmt_id),
Expand All @@ -39,6 +47,7 @@ impl ModuleDefId {
match self {
ModuleDefId::FunctionId(_) => "function",
ModuleDefId::TypeId(_) => "type",
ModuleDefId::TypeAliasId(_) => "type alias",
ModuleDefId::ModuleId(_) => "module",
ModuleDefId::GlobalId(_) => "global",
}
Expand All @@ -57,6 +66,12 @@ impl From<FuncId> for ModuleDefId {
}
}

impl From<TypeAliasId> for ModuleDefId {
fn from(fid: TypeAliasId) -> Self {
ModuleDefId::TypeAliasId(fid)
}
}

impl From<StmtId> for ModuleDefId {
fn from(stmt_id: StmtId) -> Self {
ModuleDefId::GlobalId(stmt_id)
Expand Down Expand Up @@ -97,6 +112,20 @@ impl TryFromModuleDefId for StructId {
}
}

impl TryFromModuleDefId for TypeAliasId {
fn try_from(id: ModuleDefId) -> Option<Self> {
id.as_type_alias()
}

fn dummy_id() -> Self {
TypeAliasId::dummy_id()
}

fn description() -> String {
"type alias".to_string()
}
}

impl TryFromModuleDefId for StmtId {
fn try_from(id: ModuleDefId) -> Option<Self> {
id.as_global()
Expand Down
1 change: 1 addition & 0 deletions crates/noirc_frontend/src/hir/resolution/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ fn resolve_name_in_module(
ModuleDefId::FunctionId(_) => panic!("functions cannot be in the type namespace"),
// TODO: If impls are ever implemented, types can be used in a path
ModuleDefId::TypeId(id) => id.0,
ModuleDefId::TypeAliasId(_) => panic!("type aliases cannot be used in type namespace"),
ModuleDefId::GlobalId(_) => panic!("globals cannot be in the type namespace"),
};

Expand Down
Loading

0 comments on commit ce94cb4

Please sign in to comment.