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,
+ }
);