diff --git a/compiler/ast/src/expressions/locator.rs b/compiler/ast/src/expressions/locator.rs index 89a5c88b90..5c0ce3e8c5 100644 --- a/compiler/ast/src/expressions/locator.rs +++ b/compiler/ast/src/expressions/locator.rs @@ -58,7 +58,7 @@ impl LocatorExpression { /// Check if the Locator name and program matches the other name and program. pub fn matches(&self, other: &Self) -> bool { self.name == other.name && self.program == other.program - } + } } impl fmt::Display for LocatorExpression { @@ -134,7 +134,7 @@ impl<'de> Deserialize<'de> for LocatorExpression { Some(name) => Symbol::intern(name), None => return Err(E::custom("missing 'name' in serialized Identifier struct")), }; - + let program = match key.get("program") { Some(program) => Symbol::intern(program), None => return Err(E::custom("missing 'program' in serialized Identifier struct")), diff --git a/compiler/ast/src/passes/consumer.rs b/compiler/ast/src/passes/consumer.rs index 8987545894..ae6ff53664 100644 --- a/compiler/ast/src/passes/consumer.rs +++ b/compiler/ast/src/passes/consumer.rs @@ -61,7 +61,7 @@ pub trait ExpressionConsumer { fn consume_identifier(&mut self, _input: Identifier) -> Self::Output; fn consume_literal(&mut self, _input: Literal) -> Self::Output; - + fn consume_locator(&mut self, _input: LocatorExpression) -> Self::Output; fn consume_ternary(&mut self, _input: TernaryExpression) -> Self::Output; diff --git a/compiler/ast/src/passes/reconstructor.rs b/compiler/ast/src/passes/reconstructor.rs index 23b4de9528..9204b9da18 100644 --- a/compiler/ast/src/passes/reconstructor.rs +++ b/compiler/ast/src/passes/reconstructor.rs @@ -198,12 +198,9 @@ pub trait ExpressionReconstructor { fn reconstruct_literal(&mut self, input: Literal) -> (Expression, Self::AdditionalOutput) { (Expression::Literal(input), Default::default()) } - + fn reconstruct_locator(&mut self, input: LocatorExpression) -> (Expression, Self::AdditionalOutput) { - ( - Expression::Locator(input), - Default::default(), - ) + (Expression::Locator(input), Default::default()) } fn reconstruct_ternary(&mut self, input: TernaryExpression) -> (Expression, Self::AdditionalOutput) { diff --git a/compiler/ast/src/passes/visitor.rs b/compiler/ast/src/passes/visitor.rs index dc27dc943c..9974bac79f 100644 --- a/compiler/ast/src/passes/visitor.rs +++ b/compiler/ast/src/passes/visitor.rs @@ -107,8 +107,8 @@ pub trait ExpressionVisitor<'a> { fn visit_literal(&mut self, _input: &'a Literal, _additional: &Self::AdditionalInput) -> Self::Output { Default::default() } - - fn visit_locator(&mut self, input: &'a LocatorExpression, additional: &Self::AdditionalInput) -> Self::Output { + + fn visit_locator(&mut self, _input: &'a LocatorExpression, _additional: &Self::AdditionalInput) -> Self::Output { Default::default() } diff --git a/compiler/ast/src/types/mapping.rs b/compiler/ast/src/types/mapping.rs index 06439f89fd..5a2d3dd157 100644 --- a/compiler/ast/src/types/mapping.rs +++ b/compiler/ast/src/types/mapping.rs @@ -16,9 +16,9 @@ use crate::Type; +use leo_span::Symbol; use serde::{Deserialize, Serialize}; use std::fmt; -use leo_span::Symbol; /// A mapping type of a key and value type. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] diff --git a/compiler/parser/src/parser/expression.rs b/compiler/parser/src/parser/expression.rs index 07c156eb5a..7296cc0ecf 100644 --- a/compiler/parser/src/parser/expression.rs +++ b/compiler/parser/src/parser/expression.rs @@ -494,7 +494,6 @@ impl ParserContext<'_> { } else if self.eat(&Token::Leo) { return Err(ParserError::only_aleo_external_calls(expr.span()).into()); } else if self.eat(&Token::Aleo) { - expr = self.parse_external_resource(expr)?; } else { // Parse identifier name. diff --git a/compiler/passes/src/code_generation/visit_expressions.rs b/compiler/passes/src/code_generation/visit_expressions.rs index 83546c29ff..12732d419d 100644 --- a/compiler/passes/src/code_generation/visit_expressions.rs +++ b/compiler/passes/src/code_generation/visit_expressions.rs @@ -15,7 +15,31 @@ // along with the Leo library. If not, see . use crate::{CodeGenerator, Location}; -use leo_ast::{AccessExpression, ArrayAccess, ArrayExpression, AssociatedConstant, AssociatedFunction, BinaryExpression, BinaryOperation, CallExpression, CastExpression, ErrExpression, Expression, Identifier, Literal, LocatorExpression, MemberAccess, ProgramScope, StructExpression, TernaryExpression, TupleExpression, Type, UnaryExpression, UnaryOperation, UnitExpression}; +use leo_ast::{ + AccessExpression, + ArrayAccess, + ArrayExpression, + AssociatedConstant, + AssociatedFunction, + BinaryExpression, + BinaryOperation, + CallExpression, + CastExpression, + ErrExpression, + Expression, + Identifier, + Literal, + LocatorExpression, + MemberAccess, + ProgramScope, + StructExpression, + TernaryExpression, + TupleExpression, + Type, + UnaryExpression, + UnaryOperation, + UnitExpression, +}; use leo_span::sym; use std::borrow::Borrow; @@ -515,7 +539,8 @@ impl<'a> CodeGenerator<'a> { // Initialize storage for the destination registers. let mut destinations = Vec::new(); - let return_type = &self.symbol_table.lookup_fn_symbol(Location::new(Some(main_program), function_name)).unwrap().output_type; + let return_type = + &self.symbol_table.lookup_fn_symbol(Location::new(Some(main_program), function_name)).unwrap().output_type; match return_type { Type::Unit => {} // Do nothing Type::Tuple(tuple) => match tuple.length() { diff --git a/compiler/passes/src/common/symbol_table/location.rs b/compiler/passes/src/common/symbol_table/location.rs index bda2edfca2..a191f00480 100644 --- a/compiler/passes/src/common/symbol_table/location.rs +++ b/compiler/passes/src/common/symbol_table/location.rs @@ -37,8 +37,8 @@ impl Serialize for Location { S: Serializer, { let condensed_str = match self.program { - Some(program) => format!("{}/{}", program, self.name), - None => format!("{}", self.name), + Some(program) => format!("{}/{}", program, self.name), + None => format!("{}", self.name), }; serializer.serialize_str(&condensed_str) } @@ -51,12 +51,8 @@ impl<'de> Deserialize<'de> for Location { { let s = String::deserialize(deserializer)?; let mut parts: Vec<&str> = s.split('/').collect(); - let program = if parts.len() == 1 { - None - } else { - Some(Symbol::intern(parts.remove(0))) - }; - let name = Symbol::intern(parts.get(0).unwrap()); + let program = if parts.len() == 1 { None } else { Some(Symbol::intern(parts.remove(0))) }; + let name = Symbol::intern(parts.first().unwrap()); Ok(Location::new(program, name)) } } diff --git a/compiler/passes/src/common/symbol_table/mod.rs b/compiler/passes/src/common/symbol_table/mod.rs index ae24c0b471..4e8dcafcaf 100644 --- a/compiler/passes/src/common/symbol_table/mod.rs +++ b/compiler/passes/src/common/symbol_table/mod.rs @@ -28,7 +28,7 @@ use std::cell::RefCell; use leo_ast::{normalize_json_value, remove_key_from_json, Composite, Function}; use leo_errors::{AstError, Result}; -use leo_span::{Span, Symbol}; +use leo_span::Span; use indexmap::IndexMap; use serde::{Deserialize, Serialize}; @@ -60,7 +60,7 @@ impl SymbolTable { /// Recursively checks if the symbol table contains an entry for the given symbol. /// Leo does not allow any variable shadowing or overlap between different symbols. pub fn check_shadowing(&self, location: &Location, span: Span) -> Result<()> { - if let Some(_) = location.program { + if location.program.is_some() { if self.functions.contains_key(location) { return Err(AstError::shadowed_function(location.name, span).into()); } else if let Some(existing) = self.structs.get(location) { @@ -68,16 +68,11 @@ impl SymbolTable { true => Err(AstError::shadowed_record(location.name, span).into()), false => Err(AstError::shadowed_struct(location.name, span).into()), }; + } else if self.variables.contains_key(location) { + return Err(AstError::shadowed_variable(location.name, span).into()); } - else if self.variables.contains_key(location) { - return Err(AstError::shadowed_variable(location.name, span).into()) - } - } - if let Some(parent) = self.parent.as_ref() { - return parent.check_shadowing(location, span) - } else { - Ok(()) } + if let Some(parent) = self.parent.as_ref() { parent.check_shadowing(location, span) } else { Ok(()) } } /// Returns the current scope index. @@ -244,30 +239,29 @@ mod tests { block: Default::default(), }; symbol_table.insert_fn(func_loc, &insert).unwrap(); - symbol_table.insert_variable( - Location::new(Some(Symbol::intern("credits")), Symbol::intern("accounts")), - VariableSymbol { - type_: Type::Address, - span: Default::default(), - declaration: VariableType::Const, - }).unwrap(); - symbol_table.insert_struct( - Location::new(Some(Symbol::intern("credits")), Symbol::intern("token")), - &Composite { + symbol_table + .insert_variable( + Location::new(Some(Symbol::intern("credits")), Symbol::intern("accounts")), + VariableSymbol { type_: Type::Address, span: Default::default(), declaration: VariableType::Const }, + ) + .unwrap(); + symbol_table + .insert_struct(Location::new(Some(Symbol::intern("credits")), Symbol::intern("token")), &Composite { is_record: false, span: Default::default(), id: 0, identifier: Identifier::new(Symbol::intern("token"), Default::default()), members: Vec::new(), external: None, - }).unwrap(); - symbol_table.insert_variable( - Location::new(None, Symbol::intern("foo")), - VariableSymbol { + }) + .unwrap(); + symbol_table + .insert_variable(Location::new(None, Symbol::intern("foo")), VariableSymbol { type_: Type::Address, span: Default::default(), declaration: VariableType::Const, - }).unwrap(); + }) + .unwrap(); let json = symbol_table.to_json_string().unwrap(); let deserialized = SymbolTable::from_json_string(&json).unwrap(); assert_eq!(symbol_table, deserialized); diff --git a/compiler/passes/src/flattening/flatten_expression.rs b/compiler/passes/src/flattening/flatten_expression.rs index 1b3a3d2887..52af8cb53b 100644 --- a/compiler/passes/src/flattening/flatten_expression.rs +++ b/compiler/passes/src/flattening/flatten_expression.rs @@ -89,8 +89,10 @@ impl ExpressionReconstructor for Flattener<'_> { Type::Array(first_type) => self.ternary_array(first_type, &input.condition, &first, &second), Type::Composite(first_type) => { // Get the struct definitions. - let first_type = - self.symbol_table.lookup_struct(Location::new(first_type.program, first_type.id.name)).unwrap(); + let first_type = self + .symbol_table + .lookup_struct(Location::new(first_type.program, first_type.id.name)) + .unwrap(); self.ternary_struct(first_type, &input.condition, &first, &second) } Type::Tuple(first_type) => self.ternary_tuple(first_type, &input.condition, &first, &second), diff --git a/compiler/passes/src/loop_unrolling/unroll_statement.rs b/compiler/passes/src/loop_unrolling/unroll_statement.rs index 6abc322fb6..6abcdff47e 100644 --- a/compiler/passes/src/loop_unrolling/unroll_statement.rs +++ b/compiler/passes/src/loop_unrolling/unroll_statement.rs @@ -19,7 +19,7 @@ use leo_ast::{Expression::Literal, Type::Integer, *}; use leo_errors::loop_unroller::LoopUnrollerError; use leo_span::{Span, Symbol}; -use crate::{Location, unroller::Unroller, VariableSymbol, VariableType}; +use crate::{unroller::Unroller, Location, VariableSymbol, VariableType}; impl StatementReconstructor for Unroller<'_> { fn reconstruct_block(&mut self, input: Block) -> (Block, Self::AdditionalOutput) { @@ -60,7 +60,7 @@ impl StatementReconstructor for Unroller<'_> { } // Remove from symbol table - self.symbol_table.borrow_mut().remove_variable_from_current_scope(Location::new(None,input.place.name)); + self.symbol_table.borrow_mut().remove_variable_from_current_scope(Location::new(None, input.place.name)); ( Statement::Const(ConstDeclaration { @@ -77,11 +77,13 @@ impl StatementReconstructor for Unroller<'_> { fn reconstruct_definition(&mut self, input: DefinitionStatement) -> (Statement, Self::AdditionalOutput) { // Helper function to add variables to symbol table let insert_variable = |symbol: Symbol, type_: Type, span: Span| { - if let Err(err) = self.symbol_table.borrow_mut().insert_variable(Location::new(None, symbol), VariableSymbol { - type_, - span, - declaration: VariableType::Mut, - }) { + if let Err(err) = + self.symbol_table.borrow_mut().insert_variable(Location::new(None, symbol), VariableSymbol { + type_, + span, + declaration: VariableType::Mut, + }) + { self.handler.emit_err(err); } }; diff --git a/compiler/passes/src/static_single_assignment/rename_expression.rs b/compiler/passes/src/static_single_assignment/rename_expression.rs index e4377e8ee2..e9805e6e99 100644 --- a/compiler/passes/src/static_single_assignment/rename_expression.rs +++ b/compiler/passes/src/static_single_assignment/rename_expression.rs @@ -16,7 +16,30 @@ use crate::{Location, StaticSingleAssigner}; -use leo_ast::{AccessExpression, ArrayAccess, ArrayExpression, AssociatedFunction, BinaryExpression, CallExpression, CastExpression, Composite, Expression, ExpressionConsumer, Identifier, Literal, LocatorExpression, MemberAccess, Statement, StructExpression, StructVariableInitializer, TernaryExpression, TupleAccess, TupleExpression, UnaryExpression, UnitExpression}; +use leo_ast::{ + AccessExpression, + ArrayAccess, + ArrayExpression, + AssociatedFunction, + BinaryExpression, + CallExpression, + CastExpression, + Composite, + Expression, + ExpressionConsumer, + Identifier, + Literal, + LocatorExpression, + MemberAccess, + Statement, + StructExpression, + StructVariableInitializer, + TernaryExpression, + TupleAccess, + TupleExpression, + UnaryExpression, + UnitExpression, +}; use leo_span::{sym, Symbol}; use indexmap::IndexMap; @@ -295,14 +318,13 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> { let (place, statement) = self.unique_simple_assign_statement(Expression::Literal(input)); (Expression::Identifier(place), vec![statement]) } - - /// Consumes and returns the locator expression without making any modifciations + + /// Consumes and returns the locator expression without making any modifciations fn consume_locator(&mut self, input: LocatorExpression) -> Self::Output { // Construct and accumulate a new assignment statement for the locator expression. let (place, statement) = self.unique_simple_assign_statement(Expression::Locator(input)); (Expression::Identifier(place), vec![statement]) } - /// Consumes a ternary expression, accumulating any statements that are generated. fn consume_ternary(&mut self, input: TernaryExpression) -> Self::Output { diff --git a/compiler/passes/src/symbol_table_creation/creator.rs b/compiler/passes/src/symbol_table_creation/creator.rs index 62cfe5b656..b106bd2865 100644 --- a/compiler/passes/src/symbol_table_creation/creator.rs +++ b/compiler/passes/src/symbol_table_creation/creator.rs @@ -72,20 +72,22 @@ impl<'a> ProgramVisitor<'a> for SymbolTableCreator<'a> { fn visit_mapping(&mut self, input: &'a Mapping) { // Check if mapping is external. - let program = match self.is_stub { + let program = match self.is_stub { true => self.program_name, false => None, }; // Add the variable associated with the mapping to the symbol table. - if let Err(err) = self.symbol_table.insert_variable(Location::new(program, input.identifier.name), VariableSymbol { - type_: Type::Mapping(MappingType { - key: Box::new(input.key_type.clone()), - value: Box::new(input.value_type.clone()), - program: self.program_name.unwrap(), - }), - span: input.span, - declaration: VariableType::Mut, - }) { + if let Err(err) = + self.symbol_table.insert_variable(Location::new(program, input.identifier.name), VariableSymbol { + type_: Type::Mapping(MappingType { + key: Box::new(input.key_type.clone()), + value: Box::new(input.value_type.clone()), + program: self.program_name.unwrap(), + }), + span: input.span, + declaration: VariableType::Mut, + }) + { self.handler.emit_err(err); } } diff --git a/compiler/passes/src/type_checking/check_expressions.rs b/compiler/passes/src/type_checking/check_expressions.rs index 6fd099c100..1b39450dec 100644 --- a/compiler/passes/src/type_checking/check_expressions.rs +++ b/compiler/passes/src/type_checking/check_expressions.rs @@ -53,7 +53,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> { Expression::Err(err) => self.visit_err(err, additional), Expression::Identifier(identifier) => self.visit_identifier(identifier, additional), Expression::Literal(literal) => self.visit_literal(literal, additional), - Expression::Locator(locator) => panic!("aiya"), // TODO: self.visit_locator(locator, additional), + Expression::Locator(locator) => self.visit_locator(locator, additional), Expression::Ternary(ternary) => self.visit_ternary(ternary, additional), Expression::Tuple(tuple) => self.visit_tuple(tuple, additional), Expression::Unary(unary) => self.visit_unary(unary, additional), @@ -571,7 +571,8 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> { Expression::Identifier(ident) => { // Note: The function symbol lookup is performed outside of the `if let Some(func) ...` block to avoid a RefCell lifetime bug in Rust. // Do not move it into the `if let Some(func) ...` block or it will keep `self.symbol_table_creation` alive for the entire block and will be very memory inefficient! - let func = self.symbol_table.borrow().lookup_fn_symbol(Location::new(input.program, ident.name)).cloned(); + let func = + self.symbol_table.borrow().lookup_fn_symbol(Location::new(input.program, ident.name)).cloned(); if let Some(func) = func { // Check that the call is valid. // Note that this unwrap is safe since we always set the variant before traversing the body of the function. @@ -650,7 +651,8 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> { } fn visit_struct_init(&mut self, input: &'a StructExpression, additional: &Self::AdditionalInput) -> Self::Output { - let struct_ = self.symbol_table.borrow().lookup_struct(Location::new(self.program_name, input.name.name)).cloned(); + let struct_ = + self.symbol_table.borrow().lookup_struct(Location::new(self.program_name, input.name.name)).cloned(); if let Some(struct_) = struct_ { // Check struct type name. let ret = self.check_expected_struct(&struct_, additional, input.name.span()); @@ -767,6 +769,16 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> { }) } + fn visit_locator(&mut self, input: &'a LocatorExpression, expected: &Self::AdditionalInput) -> Self::Output { + // Check that the locator points to a valid resource in the ST. + if let Some(var) = self.symbol_table.borrow().lookup_variable(Location::new(Some(input.program), input.name)) { + Some(self.assert_and_return_type(var.type_.clone(), expected, input.span())) + } else { + self.emit_err(TypeCheckerError::unknown_sym("variable", input.name, input.span())); + None + } + } + fn visit_ternary(&mut self, input: &'a TernaryExpression, expected: &Self::AdditionalInput) -> Self::Output { self.visit_expression(&input.condition, &Some(Type::Boolean)); diff --git a/compiler/passes/src/type_checking/check_program.rs b/compiler/passes/src/type_checking/check_program.rs index b144ca241a..bce7521f0f 100644 --- a/compiler/passes/src/type_checking/check_program.rs +++ b/compiler/passes/src/type_checking/check_program.rs @@ -69,8 +69,12 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> { // Lookup function metadata in the symbol table. // Note that this unwrap is safe since function metadata is stored in a prior pass. - let function_index = - self.symbol_table.borrow().lookup_fn_symbol(Location::new(self.program_name, input.identifier.name)).unwrap().id; + let function_index = self + .symbol_table + .borrow() + .lookup_fn_symbol(Location::new(self.program_name, input.identifier.name)) + .unwrap() + .id; // Enter the function's scope. self.enter_scope(function_index); diff --git a/compiler/passes/src/type_checking/check_statements.rs b/compiler/passes/src/type_checking/check_statements.rs index ebfb50ce84..4dbd1ebd0a 100644 --- a/compiler/passes/src/type_checking/check_statements.rs +++ b/compiler/passes/src/type_checking/check_statements.rs @@ -68,7 +68,9 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { } }; - let var_type = if let Some(var) = self.symbol_table.borrow_mut().lookup_variable(Location::new(None, var_name.name)) { + let var_type = if let Some(var) = + self.symbol_table.borrow_mut().lookup_variable(Location::new(None, var_name.name)) + { match &var.declaration { VariableType::Const => self.emit_err(TypeCheckerError::cannot_assign_to_const_var(var_name, var.span)), VariableType::Input(Mode::Constant) => { @@ -192,11 +194,13 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { self.visit_expression(&input.value, &Some(input.type_.clone())); // Add constants to symbol table so that any references to them in later statements will pass TC - if let Err(err) = self.symbol_table.borrow_mut().insert_variable(Location::new(None, input.place.name), VariableSymbol { - type_: input.type_.clone(), - span: input.place.span, - declaration: VariableType::Const, - }) { + if let Err(err) = + self.symbol_table.borrow_mut().insert_variable(Location::new(None, input.place.name), VariableSymbol { + type_: input.type_.clone(), + span: input.place.span, + declaration: VariableType::Const, + }) + { self.handler.emit_err(err); } } @@ -240,11 +244,13 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { // TODO: Dedup with unrolling pass. // Helper to insert the variables into the symbol table. let insert_variable = |symbol: Symbol, type_: Type, span: Span| { - if let Err(err) = self.symbol_table.borrow_mut().insert_variable(Location::new(None, symbol), VariableSymbol { - type_, - span, - declaration: VariableType::Mut, - }) { + if let Err(err) = + self.symbol_table.borrow_mut().insert_variable(Location::new(None, symbol), VariableSymbol { + type_, + span, + declaration: VariableType::Mut, + }) + { self.handler.emit_err(err); } }; @@ -308,11 +314,13 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { let scope_index = self.create_child_scope(); // Add the loop variable to the scope of the loop body. - if let Err(err) = self.symbol_table.borrow_mut().insert_variable(Location::new(None, input.variable.name), VariableSymbol { - type_: input.type_.clone(), - span: input.span(), - declaration: VariableType::Const, - }) { + if let Err(err) = + self.symbol_table.borrow_mut().insert_variable(Location::new(None, input.variable.name), VariableSymbol { + type_: input.type_.clone(), + span: input.span(), + declaration: VariableType::Const, + }) + { self.handler.emit_err(err); } @@ -381,14 +389,15 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { // We can safely unwrap all self.parent instances because // statements should always have some parent block let parent = self.function.unwrap(); - let return_type = &self.symbol_table.borrow().lookup_fn_symbol(Location::new(self.program_name, parent)).map(|f| { - match self.is_finalize { - // TODO: Check this. - // Note that this `unwrap()` is safe since we checked that the function has a finalize block. - true => f.finalize.as_ref().unwrap().output_type.clone(), - false => f.output_type.clone(), - } - }); + let return_type = + &self.symbol_table.borrow().lookup_fn_symbol(Location::new(self.program_name, parent)).map(|f| { + match self.is_finalize { + // TODO: Check this. + // Note that this `unwrap()` is safe since we checked that the function has a finalize block. + true => f.finalize.as_ref().unwrap().output_type.clone(), + false => f.output_type.clone(), + } + }); // Set the `has_return` flag. self.has_return = true; diff --git a/compiler/passes/src/type_checking/checker.rs b/compiler/passes/src/type_checking/checker.rs index 906037e26d..d66d1b2239 100644 --- a/compiler/passes/src/type_checking/checker.rs +++ b/compiler/passes/src/type_checking/checker.rs @@ -976,10 +976,7 @@ impl<'a> TypeChecker<'a> { if let Some(mapping_type) = self.assert_mapping_type(&arguments[0].0, arguments[0].1) { // Cannot modify external mappings. if mapping_type.program != self.program_name.unwrap() { - self.handler.emit_err(TypeCheckerError::cannot_modify_external_mapping( - "set", - function_span, - )); + self.handler.emit_err(TypeCheckerError::cannot_modify_external_mapping("set", function_span)); } // Check that the second argument matches the key type of the mapping. self.assert_type(&arguments[1].0, &mapping_type.key, arguments[1].1); @@ -1003,10 +1000,8 @@ impl<'a> TypeChecker<'a> { if let Some(mapping_type) = self.assert_mapping_type(&arguments[0].0, arguments[0].1) { // Cannot modify external mappings. if mapping_type.program != self.program_name.unwrap() { - self.handler.emit_err(TypeCheckerError::cannot_modify_external_mapping( - "remove", - function_span, - )); + self.handler + .emit_err(TypeCheckerError::cannot_modify_external_mapping("remove", function_span)); } // Check that the second argument matches the key type of the mapping. self.assert_type(&arguments[1].0, &mapping_type.key, arguments[1].1); @@ -1078,7 +1073,10 @@ impl<'a> TypeChecker<'a> { pub(crate) fn check_duplicate_struct(&self, name: Symbol, program_1: Symbol, program_2: Symbol) -> bool { // Make sure that both structs have been defined already. let st = self.symbol_table.borrow(); - let (struct_1, struct_2) = match (st.lookup_struct(Location::new(Some(program_1), name)), st.lookup_struct(Location::new(Some(program_2), name))) { + let (struct_1, struct_2) = match ( + st.lookup_struct(Location::new(Some(program_1), name)), + st.lookup_struct(Location::new(Some(program_2), name)), + ) { (Some(struct_1), Some(struct_2)) => (struct_1, struct_2), _ => return false, }; @@ -1148,7 +1146,11 @@ impl<'a> TypeChecker<'a> { } // Check that the named composite type has been defined. Type::Composite(struct_) - if self.symbol_table.borrow().lookup_struct(Location::new(struct_.program, struct_.id.name)).is_none() => + if self + .symbol_table + .borrow() + .lookup_struct(Location::new(struct_.program, struct_.id.name)) + .is_none() => { is_valid = false; self.emit_err(TypeCheckerError::undefined_type(struct_.id.name, span)); @@ -1181,8 +1183,10 @@ impl<'a> TypeChecker<'a> { // Array elements cannot be records. Type::Composite(struct_type) => { // Look up the type. - if let Some(struct_) = - self.symbol_table.borrow().lookup_struct(Location::new(struct_type.program, struct_type.id.name)) + if let Some(struct_) = self + .symbol_table + .borrow() + .lookup_struct(Location::new(struct_type.program, struct_type.id.name)) { // Check that the type is not a record. if struct_.is_record { @@ -1241,7 +1245,9 @@ impl<'a> TypeChecker<'a> { // If the function is not a transition function, then it cannot have a record as input if let Type::Composite(struct_) = input_var.type_() { - if let Some(val) = self.symbol_table.borrow().lookup_struct(Location::new(struct_.program, struct_.id.name)) { + if let Some(val) = + self.symbol_table.borrow().lookup_struct(Location::new(struct_.program, struct_.id.name)) + { if val.is_record && !matches!(function.variant, Variant::Transition) { self.emit_err(TypeCheckerError::function_cannot_input_or_output_a_record(input_var.span())); } @@ -1250,13 +1256,14 @@ impl<'a> TypeChecker<'a> { // Add non-stub inputs to the symbol table. if !self.is_stub { - if let Err(err) = - self.symbol_table.borrow_mut().insert_variable(Location::new(None, input_var.identifier().name), VariableSymbol { + if let Err(err) = self.symbol_table.borrow_mut().insert_variable( + Location::new(None, input_var.identifier().name), + VariableSymbol { type_: input_var.type_(), span: input_var.identifier().span(), declaration: VariableType::Input(input_var.mode()), - }) - { + }, + ) { self.handler.emit_err(err); } } @@ -1349,13 +1356,14 @@ impl<'a> TypeChecker<'a> { } // Add non-stub inputs to the symbol table. if !self.is_stub { - if let Err(err) = - self.symbol_table.borrow_mut().insert_variable(Location::new(None, input_var.identifier().name), VariableSymbol { + if let Err(err) = self.symbol_table.borrow_mut().insert_variable( + Location::new(None, input_var.identifier().name), + VariableSymbol { type_: input_var.type_(), span: input_var.identifier().span(), declaration: VariableType::Input(input_var.mode()), - }) - { + }, + ) { self.handler.emit_err(err); } } diff --git a/errors/src/errors/type_checker/type_checker_error.rs b/errors/src/errors/type_checker/type_checker_error.rs index c784baf75c..253063b1b7 100644 --- a/errors/src/errors/type_checker/type_checker_error.rs +++ b/errors/src/errors/type_checker/type_checker_error.rs @@ -768,7 +768,7 @@ create_messages!( msg: format!("The definition for `{struct_}` in program `{program_1}.aleo` does not match the definition in program `{program_2}.aleo`"), help: Some("Check that the struct definition in the current program matches the definition in the imported program.".to_string()), } - + @formatted cannot_modify_external_mapping { args: (operation: impl Display),