Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reject zero type when declare event fields #774

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
12 changes: 11 additions & 1 deletion crates/analyzer/src/db/queries/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,17 @@ pub fn event_type(db: &dyn AnalyzerDb, event: EventId) -> Analysis<Rc<types::Eve
} = &field.kind;

let typ = type_desc(&mut scope, typ_node).and_then(|typ| match typ {
typ if typ.has_fixed_size(scope.db()) => Ok(typ),
typ if typ.has_fixed_size(scope.db()) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to reject all zero-sized fields. It'd be better to reject a field iff its type is zero-sized and it is indexed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if !typ.is_zero_size(scope.db()) {
Ok(typ)
} else {
Err(TypeError::new(scope.error(
"event field type must have a non-zero types",
typ_node.span,
"this type can't be used as an event field",
)))
}
}
_ => Err(TypeError::new(scope.error(
"event field type must have a fixed size",
typ_node.span,
Expand Down
11 changes: 11 additions & 0 deletions crates/analyzer/src/namespace/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ impl TypeId {
pub fn is_base(&self, db: &dyn AnalyzerDb) -> bool {
self.typ(db).is_base()
}
pub fn is_zero_size(&self, db: &dyn AnalyzerDb) -> bool {
self.typ(db).is_zero_size(db)
}
pub fn is_bool(&self, db: &dyn AnalyzerDb) -> bool {
matches!(self.typ(db), Type::Base(Base::Bool))
}
Expand Down Expand Up @@ -494,6 +497,14 @@ impl Type {
false
}

pub fn is_zero_size(&self, db: &dyn AnalyzerDb) -> bool {
match &self {
Type::Base(Base::Unit) => true,
Type::Contract(inner) => inner.fields(db).is_empty(),
Type::Struct(inner) => inner.fields(db).is_empty(),
_ => false,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

contract/struct can be zero-sized even if their fields are not empty.

Example.

struct Zero {
    x: ()
}

Also, other types can be zero-sized.

  • Tuple becomes a zero-sized type if it has no elements or all elements are zero-sized type.
  • Array becomes a zero-sized type if its length is 0 or its element type is a zero-sized type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I create salsa query is_zero_sized to handle it. I think about this should be type_size will more general.

}
}
/// Creates an instance of bool.
pub fn bool() -> Self {
Type::Base(Base::Bool)
Expand Down
1 change: 1 addition & 0 deletions crates/analyzer/tests/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ test_file! { external_call_type_error }
test_file! { external_call_wrong_number_of_params }
test_file! { contract_function_with_generic_params }
test_file! { indexed_event }
test_file! { invalid_type_in_event_zero_sized }
test_file! { invalid_compiler_version }
test_file! { invalid_block_field }
test_file! { invalid_chain_field }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
source: crates/analyzer/tests/errors.rs
expression: "error_string(&path, test_files::fixture(path))"
---
error: event field type must have a non-zero types
┌─ compile_errors/invalid_type_in_event_zero_sized.fe:8:8
8 │ x: ()
│ ^^ this type can't be used as an event field

error: event field type must have a non-zero types
┌─ compile_errors/invalid_type_in_event_zero_sized.fe:9:8
9 │ y: EmptyStruct
│ ^^^^^^^^^^^ this type can't be used as an event field

error: event field type must have a non-zero types
┌─ compile_errors/invalid_type_in_event_zero_sized.fe:10:8
10 │ z: EmptyContract
│ ^^^^^^^^^^^^^ this type can't be used as an event field


Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
contract EmptyContract {
}

struct EmptyStruct {
}

event Event {
x: ()
y: EmptyStruct
z: EmptyContract
}