From 90903bb2b1f633916ffbe1539ed6b86ab4367c59 Mon Sep 17 00:00:00 2001 From: Abdullah Talayhan Date: Tue, 12 Nov 2024 23:24:16 +0100 Subject: [PATCH 01/10] implement pub attribute for struct fields --- src/circuit_writer/writer.rs | 4 ++-- src/error.rs | 3 +++ src/inputs.rs | 2 +- src/mast/mod.rs | 6 +++--- src/name_resolution/context.rs | 2 +- src/parser/structs.rs | 28 +++++++++++++++++++++---- src/type_checker/checker.rs | 38 +++++++++++++++++++++++++++------- src/type_checker/fn_env.rs | 13 +++++++++++- src/type_checker/mod.rs | 6 ++++-- 9 files changed, 81 insertions(+), 21 deletions(-) diff --git a/src/circuit_writer/writer.rs b/src/circuit_writer/writer.rs index 46c499c8d..8fb92b418 100644 --- a/src/circuit_writer/writer.rs +++ b/src/circuit_writer/writer.rs @@ -320,7 +320,7 @@ impl CircuitWriter { .clone(); let mut offset = 0; - for (_field_name, field_typ) in &struct_info.fields { + for (_field_name, field_typ, _attribute) in &struct_info.fields { let len = self.size_of(field_typ); let range = offset..(offset + len); self.constrain_inputs_to_main(&input[range], field_typ, span)?; @@ -473,7 +473,7 @@ impl CircuitWriter { // find range of field let mut start = 0; let mut len = 0; - for (field, field_typ) in &struct_info.fields { + for (field, field_typ, _attribute) in &struct_info.fields { if field == &rhs.value { len = self.size_of(field_typ); break; diff --git a/src/error.rs b/src/error.rs index b6ec94e24..2e9682227 100644 --- a/src/error.rs +++ b/src/error.rs @@ -362,4 +362,7 @@ pub enum ErrorKind { #[error("division by zero")] DivisionByZero, + + #[error("cannot access private field `{1}` of struct `{0}` from outside its methods.")] + PrivateFieldAccess(String, String), } diff --git a/src/inputs.rs b/src/inputs.rs index a1a5f6048..7ccffae95 100644 --- a/src/inputs.rs +++ b/src/inputs.rs @@ -140,7 +140,7 @@ impl CompiledCircuit { // parse each field let mut res = vec![]; - for (field_name, field_ty) in fields { + for (field_name, field_ty, attribute) in fields { let value = map.remove(field_name).ok_or_else(|| { ParsingError::MissingStructFieldIdent(field_name.to_string()) })?; diff --git a/src/mast/mod.rs b/src/mast/mod.rs index 17b990b8a..0ccec18ac 100644 --- a/src/mast/mod.rs +++ b/src/mast/mod.rs @@ -446,7 +446,7 @@ impl Mast { let mut sum = 0; - for (_, t) in &struct_info.fields { + for (_, t, _) in &struct_info.fields { sum += self.size_of(t); } @@ -548,8 +548,8 @@ fn monomorphize_expr( let typ = struct_info .fields .iter() - .find(|(name, _)| name == &rhs.value) - .map(|(_, typ)| typ.clone()); + .find(|(name, _, _)| name == &rhs.value) + .map(|(_, typ, _)| typ.clone()); let mexpr = expr.to_mast( ctx, diff --git a/src/name_resolution/context.rs b/src/name_resolution/context.rs index d4d196eea..f1e23eddd 100644 --- a/src/name_resolution/context.rs +++ b/src/name_resolution/context.rs @@ -150,7 +150,7 @@ impl NameResCtx { self.resolve(module, true)?; // we resolve the fully-qualified types of the fields - for (_field_name, field_typ) in fields { + for (_field_name, field_typ, attribute) in fields { self.resolve_typ_kind(&mut field_typ.kind)?; } diff --git a/src/parser/structs.rs b/src/parser/structs.rs index 6bfed47a1..f4408a9e6 100644 --- a/src/parser/structs.rs +++ b/src/parser/structs.rs @@ -3,12 +3,12 @@ use serde::{Deserialize, Serialize}; use crate::{ constants::Span, error::{ErrorKind, Result}, - lexer::{Token, TokenKind, Tokens}, + lexer::{Keyword, Token, TokenKind, Tokens}, syntax::is_type, }; use super::{ - types::{Ident, ModulePath, Ty, TyKind}, + types::{Attribute, AttributeKind, Ident, ModulePath, Ty, TyKind}, Error, ParserCtx, }; @@ -17,7 +17,7 @@ pub struct StructDef { //pub attribute: Attribute, pub module: ModulePath, // name resolution pub name: CustomType, - pub fields: Vec<(Ident, Ty)>, + pub fields: Vec<(Ident, Ty, Option)>, pub span: Span, } @@ -55,6 +55,26 @@ impl StructDef { tokens.bump(ctx); break; } + + // check for pub keyword + // struct Foo { pub a: Field, b: Field } + // ^ + let attribute = if matches!( + tokens.peek(), + Some(Token { + kind: TokenKind::Keyword(Keyword::Pub), + .. + }) + ) { + tokens.bump(ctx); + Some(Attribute { + kind: AttributeKind::Pub, + span: ctx.last_span(), + }) + } else { + None + }; + // struct Foo { a: Field, b: Field } // ^ let field_name = Ident::parse(ctx, tokens)?; @@ -67,7 +87,7 @@ impl StructDef { // ^^^^^ let field_ty = Ty::parse(ctx, tokens)?; span = span.merge_with(field_ty.span); - fields.push((field_name, field_ty)); + fields.push((field_name, field_ty, attribute)); // struct Foo { a: Field, b: Field } // ^ ^ diff --git a/src/type_checker/checker.rs b/src/type_checker/checker.rs index cf8dda009..b7d44695b 100644 --- a/src/type_checker/checker.rs +++ b/src/type_checker/checker.rs @@ -10,7 +10,8 @@ use crate::{ imports::FnKind, parser::{ types::{ - is_numeric, FnSig, ForLoopArgument, FunctionDef, Stmt, StmtKind, Symbolic, Ty, TyKind, + is_numeric, Attribute, AttributeKind, FnSig, ForLoopArgument, FuncOrMethod, + FunctionDef, Stmt, StmtKind, Symbolic, Ty, TyKind, }, CustomType, Expr, ExprKind, Op2, }, @@ -55,7 +56,7 @@ impl FnInfo { #[derive(Deserialize, Serialize, Default, Debug, Clone)] pub struct StructInfo { pub name: String, - pub fields: Vec<(String, TyKind)>, + pub fields: Vec<(String, TyKind, Option)>, pub methods: HashMap, } @@ -116,14 +117,37 @@ impl TypeChecker { .expect("this struct is not defined, or you're trying to access a field of a struct defined in a third-party library (TODO: better error)"); // find field type - let res = struct_info + if let Some((_, field_typ, attribute)) = struct_info .fields .iter() - .find(|(name, _)| name == &rhs.value) - .map(|(_, typ)| typ.clone()); + .find(|(field_name, _, _)| field_name == &rhs.value) + { + // check for the pub attribute + let is_public = attribute + .as_ref() + .map(|attr| matches!(attr.kind, AttributeKind::Pub)) + .unwrap_or(false); + + // check if we're inside a method of the same struct + let in_method = if let Some(fn_kind) = typed_fn_env.current_fn_kind() { + match fn_kind { + FuncOrMethod::Method(method_struct) => method_struct.name == struct_name, + FuncOrMethod::Function(_) => false + } + } else { + false + }; - if let Some(res) = res { - Some(ExprTyInfo::new(lhs_node.var_name, res)) + if is_public || in_method { + // allow access + Some(ExprTyInfo::new(lhs_node.var_name, field_typ.clone())) + } else { + // block access + Err(self.error( + ErrorKind::PrivateFieldAccess(struct_name.clone(), rhs.value.clone()), + expr.span, + ))? + } } else { return Err(self.error( ErrorKind::UndefinedField(struct_info.name.clone(), rhs.value.clone()), diff --git a/src/type_checker/fn_env.rs b/src/type_checker/fn_env.rs index a8540cfd6..8d3030d3d 100644 --- a/src/type_checker/fn_env.rs +++ b/src/type_checker/fn_env.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use crate::{ constants::Span, error::{Error, ErrorKind, Result}, - parser::types::TyKind, + parser::types::{FuncOrMethod, TyKind}, }; /// Some type information on local variables that we want to track in the [TypedFnEnv] environment. @@ -55,6 +55,9 @@ pub struct TypedFnEnv { /// Determines if forloop variables are allowed to be accessed. forbid_forloop_scope: bool, + + /// The kind of function we're currently type checking + current_fn_kind: Option, } impl TypedFnEnv { @@ -182,4 +185,12 @@ impl TypedFnEnv { Ok(None) } } + + pub fn current_fn_kind(&self) -> Option<&FuncOrMethod> { + self.current_fn_kind.as_ref() + } + + pub fn set_current_fn_kind(&mut self, kind: FuncOrMethod) { + self.current_fn_kind = Some(kind); + } } diff --git a/src/type_checker/mod.rs b/src/type_checker/mod.rs index 86c97e4c1..1bab2a409 100644 --- a/src/type_checker/mod.rs +++ b/src/type_checker/mod.rs @@ -298,8 +298,8 @@ impl TypeChecker { let fields: Vec<_> = fields .iter() .map(|field| { - let (name, typ) = field; - (name.value.clone(), typ.kind.clone()) + let (name, typ, attribute) = field; + (name.value.clone(), typ.kind.clone(), attribute.clone()) }) .collect(); @@ -331,6 +331,8 @@ impl TypeChecker { // create a new typed fn environment to type check the function let mut typed_fn_env = TypedFnEnv::default(); + typed_fn_env.set_current_fn_kind(function.sig.kind.clone()); + // if we're expecting a library, this should not be the main function let is_main = function.is_main(); if is_main && is_lib { From 3ba79be5615996f2393543d54e823fbb60aafba4 Mon Sep 17 00:00:00 2001 From: Abdullah Talayhan Date: Tue, 12 Nov 2024 23:24:50 +0100 Subject: [PATCH 02/10] fix tests with private field access. --- examples/assignment.no | 2 +- examples/types.no | 4 ++-- examples/types_array.no | 4 ++-- examples/types_array_output.no | 4 ++-- src/negative_tests.rs | 31 +++++++++++++++++++++++++++++-- src/stdlib/native/int/lib.no | 2 +- src/tests/modules.rs | 2 +- 7 files changed, 38 insertions(+), 11 deletions(-) diff --git a/examples/assignment.no b/examples/assignment.no index 20d8ae4e7..d5f11b4fa 100644 --- a/examples/assignment.no +++ b/examples/assignment.no @@ -1,5 +1,5 @@ struct Thing { - xx: Field, + pub xx: Field, } fn try_to_mutate(thing: Thing) { diff --git a/examples/types.no b/examples/types.no index 7aa792d6d..d219d3f3c 100644 --- a/examples/types.no +++ b/examples/types.no @@ -1,6 +1,6 @@ struct Thing { - xx: Field, - yy: Field, + pub xx: Field, + pub yy: Field, } fn main(pub xx: Field, pub yy: Field) { diff --git a/examples/types_array.no b/examples/types_array.no index ef08c51bf..e50830164 100644 --- a/examples/types_array.no +++ b/examples/types_array.no @@ -1,6 +1,6 @@ struct Thing { - xx: Field, - yy: Field, + pub xx: Field, + pub yy: Field, } fn main(pub xx: Field, pub yy: Field) { diff --git a/examples/types_array_output.no b/examples/types_array_output.no index 43c75493e..1693be0c7 100644 --- a/examples/types_array_output.no +++ b/examples/types_array_output.no @@ -1,6 +1,6 @@ struct Thing { - xx: Field, - yy: Field, + pub xx: Field, + pub yy: Field, } fn main(pub xx: Field, pub yy: Field) -> [Thing; 2] { diff --git a/src/negative_tests.rs b/src/negative_tests.rs index b50f86f46..bab66699f 100644 --- a/src/negative_tests.rs +++ b/src/negative_tests.rs @@ -700,7 +700,7 @@ fn test_nonhint_call_with_unsafe() { fn test_no_cst_struct_field_prop() { let code = r#" struct Thing { - val: Field, + pub val: Field, } fn gen(const LEN: Field) -> [Field; LEN] { @@ -725,7 +725,7 @@ fn test_no_cst_struct_field_prop() { fn test_mut_cst_struct_field_prop() { let code = r#" struct Thing { - val: Field, + pub val: Field, } fn gen(const LEN: Field) -> [Field; LEN] { @@ -747,3 +747,30 @@ fn test_mut_cst_struct_field_prop() { ErrorKind::ArgumentTypeMismatch(..) )); } + +#[test] +fn test_private_field_access() { + let code = r#" + struct Room { + pub beds: Field, // public + size: Field // private + } + + fn Room.access_size(self) { + let room2 = Room {beds: self.beds, size: self.size}; + } + + fn main(pub beds: Field) { + let mut room = Room {beds: 2, size: 10}; + room.beds = beds; // allowed + room.size = 5; // not allowed + room.access_size(); // allowed + } + "#; + + let res = tast_pass(code).0; + assert!(matches!( + res.unwrap_err().kind, + ErrorKind::PrivateFieldAccess(..) + )); +} \ No newline at end of file diff --git a/src/stdlib/native/int/lib.no b/src/stdlib/native/int/lib.no index 09bdbf16a..7e0605fc9 100644 --- a/src/stdlib/native/int/lib.no +++ b/src/stdlib/native/int/lib.no @@ -8,7 +8,7 @@ hint fn divmod(dividend: Field, divisor: Field) -> [Field; 2]; // u8 // must use new() to create a Uint8, so the value is range checked struct Uint8 { - inner: Field, + pub inner: Field, } fn Uint8.new(val: Field) -> Uint8 { diff --git a/src/tests/modules.rs b/src/tests/modules.rs index 374286ecf..f5f205c1e 100644 --- a/src/tests/modules.rs +++ b/src/tests/modules.rs @@ -31,7 +31,7 @@ use mimoo::liblib; // test a library's type that links to its own type struct Inner { - inner: Field, + pub inner: Field, } struct Lib { From c39bcdec4c9f36e9679059774d6bae56690d16bd Mon Sep 17 00:00:00 2001 From: Abdullah Talayhan Date: Mon, 18 Nov 2024 17:18:30 +0100 Subject: [PATCH 03/10] formatting and fixing unused variables. --- src/inputs.rs | 2 +- src/name_resolution/context.rs | 2 +- src/negative_tests.rs | 2 +- src/type_checker/checker.rs | 6 ++++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/inputs.rs b/src/inputs.rs index 7ccffae95..7b56e01f5 100644 --- a/src/inputs.rs +++ b/src/inputs.rs @@ -140,7 +140,7 @@ impl CompiledCircuit { // parse each field let mut res = vec![]; - for (field_name, field_ty, attribute) in fields { + for (field_name, field_ty, _attribute) in fields { let value = map.remove(field_name).ok_or_else(|| { ParsingError::MissingStructFieldIdent(field_name.to_string()) })?; diff --git a/src/name_resolution/context.rs b/src/name_resolution/context.rs index f1e23eddd..304cb4171 100644 --- a/src/name_resolution/context.rs +++ b/src/name_resolution/context.rs @@ -150,7 +150,7 @@ impl NameResCtx { self.resolve(module, true)?; // we resolve the fully-qualified types of the fields - for (_field_name, field_typ, attribute) in fields { + for (_field_name, field_typ, _attribute) in fields { self.resolve_typ_kind(&mut field_typ.kind)?; } diff --git a/src/negative_tests.rs b/src/negative_tests.rs index bab66699f..fffdfd6cd 100644 --- a/src/negative_tests.rs +++ b/src/negative_tests.rs @@ -773,4 +773,4 @@ fn test_private_field_access() { res.unwrap_err().kind, ErrorKind::PrivateFieldAccess(..) )); -} \ No newline at end of file +} diff --git a/src/type_checker/checker.rs b/src/type_checker/checker.rs index b7d44695b..1813e6842 100644 --- a/src/type_checker/checker.rs +++ b/src/type_checker/checker.rs @@ -131,8 +131,10 @@ impl TypeChecker { // check if we're inside a method of the same struct let in_method = if let Some(fn_kind) = typed_fn_env.current_fn_kind() { match fn_kind { - FuncOrMethod::Method(method_struct) => method_struct.name == struct_name, - FuncOrMethod::Function(_) => false + FuncOrMethod::Method(method_struct) => { + method_struct.name == struct_name + } + FuncOrMethod::Function(_) => false, } } else { false From f811633c1e5778cd485b556ce134b05a2bf6c97e Mon Sep 17 00:00:00 2001 From: Abdullah Talayhan Date: Mon, 18 Nov 2024 17:27:36 +0100 Subject: [PATCH 04/10] fix ir.s --- src/circuit_writer/ir.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/circuit_writer/ir.rs b/src/circuit_writer/ir.rs index 0561701e5..87457ce53 100644 --- a/src/circuit_writer/ir.rs +++ b/src/circuit_writer/ir.rs @@ -706,7 +706,7 @@ impl IRWriter { // find range of field let mut start = 0; let mut len = 0; - for (field, field_typ) in &struct_info.fields { + for (field, field_typ, _attribute) in &struct_info.fields { if field == &rhs.value { len = self.size_of(field_typ); break; From e472009679aa3c269b111712b3c084128971c1c1 Mon Sep 17 00:00:00 2001 From: Abdullah Talayhan Date: Mon, 18 Nov 2024 21:54:32 +0100 Subject: [PATCH 05/10] fix hint example to use pub --- examples/hint.no | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/hint.no b/examples/hint.no index e8ac1bc2d..bea559acf 100644 --- a/examples/hint.no +++ b/examples/hint.no @@ -1,6 +1,6 @@ struct Thing { - xx: Field, - yy: Field, + pub xx: Field, + pub yy: Field, } hint fn mul(lhs: Field, rhs: Field) -> Field { From 5eebfa97ae4498b6d73a68c1af8fd5e8922424fa Mon Sep 17 00:00:00 2001 From: Abdullah Talayhan Date: Fri, 22 Nov 2024 18:35:13 +0100 Subject: [PATCH 06/10] Simplify negative test --- src/negative_tests.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/negative_tests.rs b/src/negative_tests.rs index fffdfd6cd..ede96982c 100644 --- a/src/negative_tests.rs +++ b/src/negative_tests.rs @@ -755,16 +755,10 @@ fn test_private_field_access() { pub beds: Field, // public size: Field // private } - - fn Room.access_size(self) { - let room2 = Room {beds: self.beds, size: self.size}; - } - + fn main(pub beds: Field) { - let mut room = Room {beds: 2, size: 10}; - room.beds = beds; // allowed + let room = Room {beds: beds, size: 10}; room.size = 5; // not allowed - room.access_size(); // allowed } "#; From 48e4e5a24d8d90059222225d0c1fcb50055eb772 Mon Sep 17 00:00:00 2001 From: Abdullah Talayhan Date: Fri, 22 Nov 2024 18:35:43 +0100 Subject: [PATCH 07/10] fix: token span --- src/parser/structs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parser/structs.rs b/src/parser/structs.rs index f4408a9e6..9e5a7a328 100644 --- a/src/parser/structs.rs +++ b/src/parser/structs.rs @@ -66,10 +66,10 @@ impl StructDef { .. }) ) { - tokens.bump(ctx); + let token = tokens.bump(ctx).unwrap(); Some(Attribute { kind: AttributeKind::Pub, - span: ctx.last_span(), + span: token.span, }) } else { None From 8085c27ef5c726888b9103f87fc35465576fcd62 Mon Sep 17 00:00:00 2001 From: Abdullah Talayhan Date: Fri, 22 Nov 2024 18:36:19 +0100 Subject: [PATCH 08/10] change Uint visibility to private --- src/stdlib/native/int/lib.no | 22 ++++++++++++++++++++-- src/tests/stdlib/uints/mod.rs | 2 +- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/stdlib/native/int/lib.no b/src/stdlib/native/int/lib.no index 7e0605fc9..8673ff501 100644 --- a/src/stdlib/native/int/lib.no +++ b/src/stdlib/native/int/lib.no @@ -8,7 +8,7 @@ hint fn divmod(dividend: Field, divisor: Field) -> [Field; 2]; // u8 // must use new() to create a Uint8, so the value is range checked struct Uint8 { - pub inner: Field, + inner: Field, } fn Uint8.new(val: Field) -> Uint8 { @@ -287,4 +287,22 @@ fn Uint32.mod(self, rhs: Uint32) -> Uint32 { fn Uint64.mod(self, rhs: Uint64) -> Uint64 { let res = self.divmod(rhs); return res[1]; -} \ No newline at end of file +} + +// implement to field +fn Uint8.to_field(self) -> Field { + return self.inner; +} + +fn Uint16.to_field(self) -> Field { + return self.inner; +} + +fn Uint32.to_field(self) -> Field { + return self.inner; +} + +fn Uint64.to_field(self) -> Field { + return self.inner; +} + \ No newline at end of file diff --git a/src/tests/stdlib/uints/mod.rs b/src/tests/stdlib/uints/mod.rs index efd1ede83..474c017bf 100644 --- a/src/tests/stdlib/uints/mod.rs +++ b/src/tests/stdlib/uints/mod.rs @@ -14,7 +14,7 @@ fn main(pub lhs: Field, rhs: Field) -> Field { let res = lhs_u.{opr}(rhs_u); - return res.inner; + return res.to_field(); } "#; From 99fc9cc7e5839a1b71971a7a2e9b0bac2194bb25 Mon Sep 17 00:00:00 2001 From: Abdullah Talayhan Date: Fri, 22 Nov 2024 18:37:01 +0100 Subject: [PATCH 09/10] Simplify type checker --- src/type_checker/checker.rs | 19 +++++-------------- src/type_checker/fn_env.rs | 24 +++++++++++++----------- src/type_checker/mod.rs | 4 +--- 3 files changed, 19 insertions(+), 28 deletions(-) diff --git a/src/type_checker/checker.rs b/src/type_checker/checker.rs index 1813e6842..de7c4b7b7 100644 --- a/src/type_checker/checker.rs +++ b/src/type_checker/checker.rs @@ -123,22 +123,13 @@ impl TypeChecker { .find(|(field_name, _, _)| field_name == &rhs.value) { // check for the pub attribute - let is_public = attribute - .as_ref() - .map(|attr| matches!(attr.kind, AttributeKind::Pub)) - .unwrap_or(false); + let is_public = matches!(attribute, &Some(Attribute { kind: AttributeKind::Pub, .. })); // check if we're inside a method of the same struct - let in_method = if let Some(fn_kind) = typed_fn_env.current_fn_kind() { - match fn_kind { - FuncOrMethod::Method(method_struct) => { - method_struct.name == struct_name - } - FuncOrMethod::Function(_) => false, - } - } else { - false - }; + let in_method = matches!( + typed_fn_env.current_fn_kind(), + FuncOrMethod::Method(method_struct) if method_struct.name == struct_name + ); if is_public || in_method { // allow access diff --git a/src/type_checker/fn_env.rs b/src/type_checker/fn_env.rs index 8d3030d3d..3c6b8eb7a 100644 --- a/src/type_checker/fn_env.rs +++ b/src/type_checker/fn_env.rs @@ -39,7 +39,7 @@ impl TypeInfo { } /// The environment we use to type check functions. -#[derive(Default, Debug, Clone)] +#[derive(Debug, Clone)] pub struct TypedFnEnv { /// The current nesting level. /// Starting at 0 (top level), and increasing as we go into a block. @@ -57,13 +57,19 @@ pub struct TypedFnEnv { forbid_forloop_scope: bool, /// The kind of function we're currently type checking - current_fn_kind: Option, + current_fn_kind: FuncOrMethod, } impl TypedFnEnv { - /// Creates a new TypeEnv - pub fn new() -> Self { - Self::default() + /// Creates a new TypeEnv with the given function kind + pub fn new(fn_kind: &FuncOrMethod) -> Self { + Self { + current_scope: 0, + vars: HashMap::new(), + forloop_scopes: Vec::new(), + forbid_forloop_scope: false, + current_fn_kind: fn_kind.clone(), + } } /// Enters a scoped block. @@ -186,11 +192,7 @@ impl TypedFnEnv { } } - pub fn current_fn_kind(&self) -> Option<&FuncOrMethod> { - self.current_fn_kind.as_ref() - } - - pub fn set_current_fn_kind(&mut self, kind: FuncOrMethod) { - self.current_fn_kind = Some(kind); + pub fn current_fn_kind(&self) -> &FuncOrMethod { + &self.current_fn_kind } } diff --git a/src/type_checker/mod.rs b/src/type_checker/mod.rs index abfa39052..dfc304f93 100644 --- a/src/type_checker/mod.rs +++ b/src/type_checker/mod.rs @@ -329,9 +329,7 @@ impl TypeChecker { // `fn main() { ... }` RootKind::FunctionDef(function) => { // create a new typed fn environment to type check the function - let mut typed_fn_env = TypedFnEnv::default(); - - typed_fn_env.set_current_fn_kind(function.sig.kind.clone()); + let mut typed_fn_env = TypedFnEnv::new(&function.sig.kind); // if we're expecting a library, this should not be the main function let is_main = function.is_main(); From 416884f6850bd35400cac5b19cc46a462313b870 Mon Sep 17 00:00:00 2001 From: Abdullah Talayhan Date: Fri, 22 Nov 2024 18:41:11 +0100 Subject: [PATCH 10/10] fix formatting --- src/type_checker/checker.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/type_checker/checker.rs b/src/type_checker/checker.rs index de7c4b7b7..a0fd0d2d0 100644 --- a/src/type_checker/checker.rs +++ b/src/type_checker/checker.rs @@ -123,7 +123,13 @@ impl TypeChecker { .find(|(field_name, _, _)| field_name == &rhs.value) { // check for the pub attribute - let is_public = matches!(attribute, &Some(Attribute { kind: AttributeKind::Pub, .. })); + let is_public = matches!( + attribute, + &Some(Attribute { + kind: AttributeKind::Pub, + .. + }) + ); // check if we're inside a method of the same struct let in_method = matches!(