Skip to content

Commit

Permalink
Perform type checking on event constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
cburgdorf committed Jan 22, 2021
1 parent 93ed841 commit 6e83637
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 33 deletions.
2 changes: 1 addition & 1 deletion compiler/src/yul/operations/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub fn emit_event(event: Event, vals: Vec<yul::Expression>) -> yul::Statement {
let mut topics = vec![literal_expression! { (event.topic) }];

let (field_vals, field_types): (Vec<yul::Expression>, Vec<FixedSize>) = event
.fields()
.non_indexed_fields()
.into_iter()
.map(|(index, typ)| (vals[index].to_owned(), typ))
.unzip();
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/yul/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub fn build(context: &Context, contract: &Spanned<fe::ModuleStmt>) -> Vec<yul::
let events_batch = attributes
.events
.iter()
.map(|event| event.field_types())
.map(|event| event.non_indexed_field_types())
.collect::<Vec<_>>();

let batch = [public_functions_batch, events_batch].concat();
Expand Down
1 change: 1 addition & 0 deletions compiler/tests/compile_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::fs;
#[rstest(
fixture_file,
expected_error,
case("call_event_with_wrong_types.fe", "TypeError"),
case("continue_without_loop.fe", "ContinueWithoutLoop"),
case("continue_without_loop_2.fe", "ContinueWithoutLoop"),
case("break_without_loop.fe", "BreakWithoutLoop"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
contract Foo:
event MyEvent:
val_1: string100
val_2: u8

pub def foo():
emit MyEvent("foo", 1000)
16 changes: 16 additions & 0 deletions newsfragments/202.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Perform type checking when calling event constructors

Previously, the following would not raise an error even though it should:

```
contract Foo:
event MyEvent:
val_1: string100
val_2: u8
pub def foo():
emit MyEvent("foo", 1000)
```

Wit this change, the code fails with a type error as expected.
22 changes: 19 additions & 3 deletions semantics/src/namespace/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ impl Event {
/// The event's non-indexed fields.
///
/// These should be logged in the data section.
pub fn fields(&self) -> Vec<(usize, FixedSize)> {
pub fn non_indexed_fields(&self) -> Vec<(usize, FixedSize)> {
self.fields
.to_owned()
.into_iter()
Expand All @@ -50,8 +50,15 @@ impl Event {
}

/// The event's non-indexed field types.
pub fn non_indexed_field_types(&self) -> Vec<FixedSize> {
self.non_indexed_fields()
.into_iter()
.map(|(_, typ)| typ)
.collect()
}
/// The event's field types.
pub fn field_types(&self) -> Vec<FixedSize> {
self.fields().into_iter().map(|(_, typ)| typ).collect()
self.fields.clone()
}
}

Expand Down Expand Up @@ -81,7 +88,16 @@ mod tests {
);

assert_eq!(
event.fields(),
event.field_types(),
vec![
FixedSize::Base(Base::Address),
FixedSize::Base(Base::Address),
FixedSize::Base(Base::Bool),
],
);

assert_eq!(
event.non_indexed_fields(),
vec![
(0, FixedSize::Base(Base::Address)),
(2, FixedSize::Base(Base::Bool))
Expand Down
3 changes: 2 additions & 1 deletion semantics/src/traversal/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,9 @@ fn expr_str(
if let fe::Expr::Str(lines) = &exp.node {
let string_length = lines.iter().map(|val| val.len()).sum();
let string_val = lines.join("");

scope
.borrow_mut()
.borrow()
.contract_scope()
.borrow_mut()
.add_string(string_val);
Expand Down
45 changes: 18 additions & 27 deletions semantics/src/traversal/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ use crate::namespace::types::{
Tuple,
Type,
};
use crate::traversal::_utils::spanned_expression;
use crate::traversal::_utils::{
expression_attributes_to_types,
fixed_sizes_to_types,
spanned_expression,
};
use crate::traversal::{
assignments,
declarations,
Expand Down Expand Up @@ -358,11 +362,19 @@ fn emit(
let event_name = expressions::expr_name_string(func)?;

if let Some(event) = scope.borrow().contract_event_def(event_name) {
context.borrow_mut().add_emit(stmt, event);
}

for arg in args.node.iter() {
call_arg(Rc::clone(&scope), Rc::clone(&context), arg)?;
context.borrow_mut().add_emit(stmt, event.clone());

let argument_attributes = args
.node
.iter()
.map(|arg| expressions::call_arg(Rc::clone(&scope), Rc::clone(&context), arg))
.collect::<Result<Vec<_>, _>>()?;

if fixed_sizes_to_types(event.field_types())
!= expression_attributes_to_types(argument_attributes)
{
return Err(SemanticError::type_error());
}
}

return Ok(());
Expand All @@ -389,27 +401,6 @@ fn assert(
unreachable!()
}

fn call_arg(
scope: Shared<BlockScope>,
context: Shared<Context>,
arg: &Spanned<fe::CallArg>,
) -> Result<(), SemanticError> {
match &arg.node {
fe::CallArg::Arg(value) => {
let spanned = spanned_expression(&arg.span, value);
let _attributes = expressions::assignable_expr(scope, Rc::clone(&context), &spanned)?;

// TODO: Perform type checking
}
fe::CallArg::Kwarg(fe::Kwarg { name: _, value }) => {
let _attributes = expressions::expr(scope, context, value)?;
// TODO: Perform type checking
}
};

Ok(())
}

fn func_return(
scope: Shared<BlockScope>,
context: Shared<Context>,
Expand Down

0 comments on commit 6e83637

Please sign in to comment.