From 1da03e728b94bcdb447e35a3443a05202efdbbd3 Mon Sep 17 00:00:00 2001 From: gluax <16431709+gluax@users.noreply.github.com> Date: Mon, 30 May 2022 11:29:00 -0700 Subject: [PATCH] add checks for ident types being allowed built in types --- Cargo.lock | 1 + .../passes/src/type_checker/check_file.rs | 1 + .../src/type_checker/check_statements.rs | 17 +++++---- compiler/passes/src/type_checker/checker.rs | 18 +++++++++- compiler/stdlib/Cargo.toml | 4 ++- compiler/stdlib/src/account/mod.rs | 36 ++++++------------- compiler/stdlib/src/algorithms/mod.rs | 11 +++--- compiler/stdlib/src/lib.rs | 5 +-- .../errors/type_checker/type_checker_error.rs | 10 ++++++ 9 files changed, 61 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c3da4a33d6..e192474a47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1344,6 +1344,7 @@ dependencies = [ name = "leo-stdlib" version = "1.5.3" dependencies = [ + "indexmap", "leo-ast", "leo-errors", "leo-span", diff --git a/compiler/passes/src/type_checker/check_file.rs b/compiler/passes/src/type_checker/check_file.rs index b8c61e38ff..3258fc28f7 100644 --- a/compiler/passes/src/type_checker/check_file.rs +++ b/compiler/passes/src/type_checker/check_file.rs @@ -26,6 +26,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> { self.parent = Some(input.name()); input.input.iter().for_each(|i| { let input_var = i.get_variable(); + self.validate_ident_type(&Some(input_var.type_)); if let Err(err) = self.symbol_table.insert_variable( input_var.identifier.name, diff --git a/compiler/passes/src/type_checker/check_statements.rs b/compiler/passes/src/type_checker/check_statements.rs index 4205462cc8..5c2e3204fc 100644 --- a/compiler/passes/src/type_checker/check_statements.rs +++ b/compiler/passes/src/type_checker/check_statements.rs @@ -29,10 +29,10 @@ impl<'a> StatementVisitorDirector<'a> for Director<'a> { // statements should always have some parent block let parent = self.visitor.parent.unwrap(); - self.visit_expression( - &input.expression, - &self.visitor.symbol_table.lookup_fn(&parent).map(|f| f.output), - ); + let return_type = &self.visitor.symbol_table.lookup_fn(&parent).map(|f| f.output); + self.visitor.validate_ident_type(return_type); + + self.visit_expression(&input.expression, return_type); } fn visit_definition(&mut self, input: &'a DefinitionStatement) { @@ -43,6 +43,8 @@ impl<'a> StatementVisitorDirector<'a> for Director<'a> { }; input.variable_names.iter().for_each(|v| { + self.visitor.validate_ident_type(&Some(input.type_)); + if let Err(err) = self.visitor.symbol_table.insert_variable( v.identifier.name, VariableSymbol { @@ -83,6 +85,7 @@ impl<'a> StatementVisitorDirector<'a> for Director<'a> { }; if var_type.is_some() { + self.visitor.validate_ident_type(&var_type); self.visit_expression(&input.value, &var_type); } } @@ -103,8 +106,10 @@ impl<'a> StatementVisitorDirector<'a> for Director<'a> { self.visitor.handler.emit_err(err); } - self.visit_expression(&input.start, &Some(input.type_)); - self.visit_expression(&input.stop, &Some(input.type_)); + let iter_type = &Some(input.type_); + self.visitor.validate_ident_type(iter_type); + self.visit_expression(&input.start, iter_type); + self.visit_expression(&input.stop, iter_type); } fn visit_console(&mut self, input: &'a ConsoleStatement) { diff --git a/compiler/passes/src/type_checker/checker.rs b/compiler/passes/src/type_checker/checker.rs index 5807fd7ee6..ce44547b2f 100644 --- a/compiler/passes/src/type_checker/checker.rs +++ b/compiler/passes/src/type_checker/checker.rs @@ -14,9 +14,11 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_ast::{IntegerType, Type}; +use indexmap::IndexSet; +use leo_ast::{IntegerType, Node, Type}; use leo_errors::{emitter::Handler, TypeCheckerError}; use leo_span::{Span, Symbol}; +use leo_stdlib::*; use crate::SymbolTable; @@ -25,6 +27,8 @@ pub struct TypeChecker<'a> { pub(crate) handler: &'a Handler, pub(crate) parent: Option, pub(crate) negate: bool, + pub(crate) account_types: IndexSet, + pub(crate) algorithms_types: IndexSet, } const INT_TYPES: [Type; 10] = [ @@ -74,6 +78,18 @@ impl<'a> TypeChecker<'a> { handler, parent: None, negate: false, + account_types: Account::types(), + algorithms_types: Algorithms::types(), + } + } + + /// Validates that an ident type is a valid one. + pub(crate) fn validate_ident_type(&self, type_: &Option) { + if let Some(Type::Identifier(ident)) = type_ { + if !(self.account_types.contains(&ident.name) || self.algorithms_types.contains(&ident.name)) { + self.handler + .emit_err(TypeCheckerError::invalid_built_in_type(&ident.name, ident.span()).into()); + } } } diff --git a/compiler/stdlib/Cargo.toml b/compiler/stdlib/Cargo.toml index 90c1f9b756..2f75b2cf8e 100644 --- a/compiler/stdlib/Cargo.toml +++ b/compiler/stdlib/Cargo.toml @@ -28,7 +28,9 @@ version = "1.5.3" path = "../../leo/errors" version = "1.5.3" - [dependencies.leo-span] path = "../../leo/span" version = "1.5.3" + +[dependencies] +indexmap = "1.7.0" \ No newline at end of file diff --git a/compiler/stdlib/src/account/mod.rs b/compiler/stdlib/src/account/mod.rs index 84c0fefc2b..d6b63ff9ad 100644 --- a/compiler/stdlib/src/account/mod.rs +++ b/compiler/stdlib/src/account/mod.rs @@ -16,34 +16,20 @@ use crate::Types; -use leo_ast::{Identifier, Type}; -use leo_span::{Span, Symbol}; +use indexmap::IndexSet; + +use leo_span::Symbol; pub struct Account; impl Types for Account { - fn types() -> Vec { - vec![ - Type::Identifier(Identifier { - name: Symbol::intern("ComputeKey"), - span: Span::dummy(), - }), - Type::Identifier(Identifier { - name: Symbol::intern("PrivateKey"), - span: Span::dummy(), - }), - Type::Identifier(Identifier { - name: Symbol::intern("Record"), - span: Span::dummy(), - }), - Type::Identifier(Identifier { - name: Symbol::intern("Signature"), - span: Span::dummy(), - }), - Type::Identifier(Identifier { - name: Symbol::intern("ViewKey"), - span: Span::dummy(), - }), - ] + fn types() -> IndexSet { + IndexSet::from([ + Symbol::intern("ComputeKey"), + Symbol::intern("PrivateKey"), + Symbol::intern("Record"), + Symbol::intern("Signature"), + Symbol::intern("ViewKey"), + ]) } } diff --git a/compiler/stdlib/src/algorithms/mod.rs b/compiler/stdlib/src/algorithms/mod.rs index a8966275b2..2d77cb909f 100644 --- a/compiler/stdlib/src/algorithms/mod.rs +++ b/compiler/stdlib/src/algorithms/mod.rs @@ -16,16 +16,13 @@ use crate::Types; -use leo_ast::{Identifier, Type}; -use leo_span::{Span, Symbol}; +use indexmap::IndexSet; +use leo_span::Symbol; pub struct Algorithms; impl Types for Algorithms { - fn types() -> Vec { - vec![Type::Identifier(Identifier { - name: Symbol::intern("Poseidon"), - span: Span::dummy(), - })] + fn types() -> IndexSet { + IndexSet::from([Symbol::intern("Poseidon")]) } } diff --git a/compiler/stdlib/src/lib.rs b/compiler/stdlib/src/lib.rs index 4ecafecf86..6ebfa0d448 100644 --- a/compiler/stdlib/src/lib.rs +++ b/compiler/stdlib/src/lib.rs @@ -16,7 +16,8 @@ #![doc = include_str!("../README.md")] -use leo_ast::Type; +use indexmap::IndexSet; +use leo_span::Symbol; mod account; pub use account::*; @@ -25,5 +26,5 @@ mod algorithms; pub use algorithms::*; pub trait Types { - fn types() -> Vec; + fn types() -> IndexSet; } diff --git a/leo/errors/src/errors/type_checker/type_checker_error.rs b/leo/errors/src/errors/type_checker/type_checker_error.rs index 6646d294ca..2965891cf4 100644 --- a/leo/errors/src/errors/type_checker/type_checker_error.rs +++ b/leo/errors/src/errors/type_checker/type_checker_error.rs @@ -132,4 +132,14 @@ create_messages!( ), help: None, } + + /// For when an invalid built in type is used. + @formatted + invalid_built_in_type { + args: (type_: impl Display), + msg: format!( + "The type {type_} is not a valid built in type.", + ), + help: None, + } );