diff --git a/crates/abi/src/elements.rs b/crates/abi/src/elements.rs index ef8b1e8f10..63fd9e1567 100644 --- a/crates/abi/src/elements.rs +++ b/crates/abi/src/elements.rs @@ -106,7 +106,7 @@ impl JsonAbi for Base { Base::Numeric(Integer::I8) => "int8".to_string(), Base::Address => "address".to_string(), Base::Bool => "bool".to_string(), - Base::Unit => panic!("unit type is not abi encodable"), + Base::Unit => "".to_string(), } } } diff --git a/crates/yulgen/src/db/queries/functions.rs b/crates/yulgen/src/db/queries/functions.rs index 464160b584..c7c36019d5 100644 --- a/crates/yulgen/src/db/queries/functions.rs +++ b/crates/yulgen/src/db/queries/functions.rs @@ -39,6 +39,13 @@ pub fn function_def(db: &dyn YulgenDb, function: FunctionId) -> yul::Statement { let function_name = identifier! { (db.function_yul_name(function)) }; // all user-defined functions are given a return value during lowering + + // ^ this is no longer true. functions that return the unit type do not + // get a return statement. Need a way to identify what functions don't have a + // return statement from here, so we can remove the '-> return_val' in those cases. + + // let has_return_value = function_statements.iter().any(|x| x); + function_definition! { function [function_name]([param_names...]) -> return_val { [function_statements...] diff --git a/crates/yulgen/src/mappers/expressions.rs b/crates/yulgen/src/mappers/expressions.rs index fdbd51c180..b86f230d68 100644 --- a/crates/yulgen/src/mappers/expressions.rs +++ b/crates/yulgen/src/mappers/expressions.rs @@ -39,7 +39,13 @@ pub fn expr(context: &mut FnContext, exp: &Node) -> yul::Expression { fe::Expr::List { .. } => panic!("list expressions should be lowered"), fe::Expr::Tuple { .. } => panic!("tuple expressions should be lowered"), fe::Expr::Str(_) => expr_str(exp), - fe::Expr::Unit => expression! { 0x0 }, + // fe::Expr::Unit => expression! { 0x0 }, + fe::Expr::Unit => yultsur::yul::Expression::Literal({ + yul::Literal { + literal: "".to_string(), + yultype: None + } + }) }; let attributes = context.expression_attributes(exp); diff --git a/crates/yulgen/src/mappers/functions.rs b/crates/yulgen/src/mappers/functions.rs index fe92f75786..3d840c986c 100644 --- a/crates/yulgen/src/mappers/functions.rs +++ b/crates/yulgen/src/mappers/functions.rs @@ -224,9 +224,16 @@ fn func_return(context: &mut FnContext, stmt: &Node) -> yul::State .expect("valueless return made it to Yul codegen"); let value = expressions::expr(context, value); - block_statement! { - (return_val := [value]) - (leave) + if let yul::Expression::Literal(yultype) = value { + block_statement! { + (leave) + } + } + else { + block_statement! { + (return_val := [value]) + (leave) + } } } else { unreachable!() diff --git a/crates/yulgen/src/types.rs b/crates/yulgen/src/types.rs index ed7a53c307..e6ce3aeca9 100644 --- a/crates/yulgen/src/types.rs +++ b/crates/yulgen/src/types.rs @@ -171,11 +171,11 @@ impl AbiType { } pub trait AsAbiType { - fn as_abi_type(&self, db: &dyn AnalyzerDb) -> AbiType; + fn as_abi_type(&self, db: &dyn AnalyzerDb) -> Option; } impl AsAbiType for FixedSize { - fn as_abi_type(&self, db: &dyn AnalyzerDb) -> AbiType { + fn as_abi_type(&self, db: &dyn AnalyzerDb) -> Option { match self { FixedSize::Base(base) => base.as_abi_type(db), FixedSize::Array(array) => array.as_abi_type(db), @@ -188,38 +188,38 @@ impl AsAbiType for FixedSize { } impl AsAbiType for Base { - fn as_abi_type(&self, _db: &dyn AnalyzerDb) -> AbiType { + fn as_abi_type(&self, _db: &dyn AnalyzerDb) -> Option { match self { Base::Numeric(integer) => { let size = integer.size(); if integer.is_signed() { - AbiType::Int { size } + Some(AbiType::Int { size }) } else { - AbiType::Uint { size } + Some(AbiType::Uint { size }) } } - Base::Address => AbiType::Address, - Base::Bool => AbiType::Bool, - Base::Unit => panic!("unit type is not abi encodable"), + Base::Address => Some(AbiType::Address), + Base::Bool => Some(AbiType::Bool), + Base::Unit => None, } } } impl AsAbiType for Array { - fn as_abi_type(&self, db: &dyn AnalyzerDb) -> AbiType { + fn as_abi_type(&self, db: &dyn AnalyzerDb) -> Option { if matches!(self.inner, Base::Numeric(Integer::U8)) { - AbiType::Bytes { size: self.size } + Some(AbiType::Bytes { size: self.size }) } else { - AbiType::StaticArray { - inner: Box::new(self.inner.as_abi_type(db)), + Some(AbiType::StaticArray { + inner: Box::new(self.inner.as_abi_type(db).unwrap()), size: self.size, - } + }) } } } impl AsAbiType for Struct { - fn as_abi_type(&self, db: &dyn AnalyzerDb) -> AbiType { + fn as_abi_type(&self, db: &dyn AnalyzerDb) -> Option { let components = self .id .fields(db) @@ -231,22 +231,22 @@ impl AsAbiType for Struct { .as_abi_type(db) }) .collect(); - AbiType::Tuple { components } + Some(AbiType::Tuple { components }) } } impl AsAbiType for Tuple { - fn as_abi_type(&self, db: &dyn AnalyzerDb) -> AbiType { - AbiType::Tuple { + fn as_abi_type(&self, db: &dyn AnalyzerDb) -> Option { + Some(AbiType::Tuple { components: self.items.iter().map(|typ| typ.as_abi_type(db)).collect(), - } + }) } } impl AsAbiType for FeString { - fn as_abi_type(&self, _db: &dyn AnalyzerDb) -> AbiType { - AbiType::String { + fn as_abi_type(&self, _db: &dyn AnalyzerDb) -> Option { + Some(AbiType::String { max_size: self.max_size, - } + }) } }