Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions forc-plugins/forc-client/tests/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ async fn test_simple_deploy() {
node.kill().unwrap();
let expected = vec![DeployedPackage::Contract(DeployedContract {
id: ContractId::from_str(
"e3e0f5c8c9585a7dc6673775a73104acc847905b5e7ea085db822241444fee7e",
"6d59c621e41a1648b637b1392505cd34501613108100bedf5f30b0020770b74a",
)
.unwrap(),
proxy: None,
Expand Down Expand Up @@ -421,7 +421,7 @@ async fn test_deploy_submit_only() {
node.kill().unwrap();
let expected = vec![DeployedPackage::Contract(DeployedContract {
id: ContractId::from_str(
"e3e0f5c8c9585a7dc6673775a73104acc847905b5e7ea085db822241444fee7e",
"6d59c621e41a1648b637b1392505cd34501613108100bedf5f30b0020770b74a",
)
.unwrap(),
proxy: None,
Expand Down Expand Up @@ -468,12 +468,12 @@ async fn test_deploy_fresh_proxy() {
node.kill().unwrap();
let impl_contract = DeployedPackage::Contract(DeployedContract {
id: ContractId::from_str(
"e3e0f5c8c9585a7dc6673775a73104acc847905b5e7ea085db822241444fee7e",
"6d59c621e41a1648b637b1392505cd34501613108100bedf5f30b0020770b74a",
)
.unwrap(),
proxy: Some(
ContractId::from_str(
"92343c25e373958aee4cecfe58ab6533261b5f54de471291c22ee05182d39122",
"49bde7ba2bd4bdd593411bdf2080026588df8a97546b48fe4cd4f03bd4bf916d",
)
.unwrap(),
),
Expand Down
8 changes: 4 additions & 4 deletions forc/tests/cli_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ fn test_forc_test_raw_logs() -> Result<(), rexpect::error::Error> {
// Assert that the output is correct
process.exp_string(" test test_log_4")?;
process.exp_string("raw logs:")?;
process.exp_string(r#"[{"LogData":{"data":"0000000000000004","digest":"8005f02d43fa06e7d0585fb64c961d57e318b27a145c857bcd3a6bdb413ff7fc","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12312,"ptr":67108856,"ra":0,"rb":1515152261580153489}}]"#)?;
process.exp_string(r#"[{"LogData":{"data":"0000000000000004","digest":"8005f02d43fa06e7d0585fb64c961d57e318b27a145c857bcd3a6bdb413ff7fc","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":11432,"ptr":67108856,"ra":0,"rb":1515152261580153489}}]"#)?;
process.exp_string(" test test_log_2")?;
process.exp_string("raw logs:")?;
process.exp_string(r#"[{"LogData":{"data":"0000000000000002","digest":"cd04a4754498e06db5a13c5f371f1f04ff6d2470f24aa9bd886540e5dce77f70","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12312,"ptr":67108856,"ra":0,"rb":1515152261580153489}}]"#)?;
process.exp_string(r#"[{"LogData":{"data":"0000000000000002","digest":"cd04a4754498e06db5a13c5f371f1f04ff6d2470f24aa9bd886540e5dce77f70","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":11432,"ptr":67108856,"ra":0,"rb":1515152261580153489}}]"#)?;

process.process.exit()?;
Ok(())
Expand All @@ -77,12 +77,12 @@ fn test_forc_test_both_logs() -> Result<(), rexpect::error::Error> {
process.exp_string("decoded log values:")?;
process.exp_string("4, log rb: 1515152261580153489")?;
process.exp_string("raw logs:")?;
process.exp_string(r#"[{"LogData":{"data":"0000000000000004","digest":"8005f02d43fa06e7d0585fb64c961d57e318b27a145c857bcd3a6bdb413ff7fc","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12312,"ptr":67108856,"ra":0,"rb":1515152261580153489}}]"#)?;
process.exp_string(r#"[{"LogData":{"data":"0000000000000004","digest":"8005f02d43fa06e7d0585fb64c961d57e318b27a145c857bcd3a6bdb413ff7fc","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":11432,"ptr":67108856,"ra":0,"rb":1515152261580153489}}]"#)?;
process.exp_string(" test test_log_2")?;
process.exp_string("decoded log values:")?;
process.exp_string("2, log rb: 1515152261580153489")?;
process.exp_string("raw logs:")?;
process.exp_string(r#"[{"LogData":{"data":"0000000000000002","digest":"cd04a4754498e06db5a13c5f371f1f04ff6d2470f24aa9bd886540e5dce77f70","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12312,"ptr":67108856,"ra":0,"rb":1515152261580153489}}]"#)?;
process.exp_string(r#"[{"LogData":{"data":"0000000000000002","digest":"cd04a4754498e06db5a13c5f371f1f04ff6d2470f24aa9bd886540e5dce77f70","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":11432,"ptr":67108856,"ra":0,"rb":1515152261580153489}}]"#)?;
process.process.exit()?;
Ok(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
Engines, TypeInfo, TypeParameter,
};
use itertools::Itertools;
use std::collections::BTreeMap;
use std::collections::{BTreeMap, BTreeSet};
use sway_error::{
error::CompileError,
handler::{ErrorEmitted, Handler},
Expand All @@ -31,6 +31,7 @@ where
name: &BaseIdent,
type_parameters: &[TypeParameter],
body: String,
is_trivial_body: &str,
) -> String {
let type_parameters_declaration_expanded =
self.generate_type_parameters_declaration_code(type_parameters, true);
Expand All @@ -43,13 +44,17 @@ where

if body.is_empty() {
format!("#[allow(dead_code, deprecated)] impl{type_parameters_declaration_expanded} AbiEncode for {name}{type_parameters_declaration}{type_parameters_constraints} {{
#[allow(dead_code, deprecated)]
fn is_encode_trivial() -> bool {{ {is_trivial_body} }}
#[allow(dead_code, deprecated)]
fn abi_encode(self, buffer: Buffer) -> Buffer {{
buffer
}}
}}")
} else {
format!("#[allow(dead_code, deprecated)] impl{type_parameters_declaration_expanded} AbiEncode for {name}{type_parameters_declaration}{type_parameters_constraints} {{
#[allow(dead_code, deprecated)]
fn is_encode_trivial() -> bool {{ {is_trivial_body} }}
#[allow(dead_code, deprecated)]
fn abi_encode(self, buffer: Buffer) -> Buffer {{
{body}
Expand All @@ -64,6 +69,7 @@ where
name: &BaseIdent,
type_parameters: &[TypeParameter],
body: String,
is_trivial_body: &str,
) -> String {
let type_parameters_declaration_expanded =
self.generate_type_parameters_declaration_code(type_parameters, true);
Expand All @@ -76,13 +82,17 @@ where

if body == "Self { }" {
format!("#[allow(dead_code, deprecated)] impl{type_parameters_declaration_expanded} AbiDecode for {name}{type_parameters_declaration}{type_parameters_constraints} {{
#[allow(dead_code, deprecated)]
fn is_decode_trivial() -> bool {{ {is_trivial_body} }}
#[allow(dead_code, deprecated)]
fn abi_decode(ref mut _buffer: BufferReader) -> Self {{
{body}
}}
}}")
} else {
format!("#[allow(dead_code, deprecated)] impl{type_parameters_declaration_expanded} AbiDecode for {name}{type_parameters_declaration}{type_parameters_constraints} {{
#[allow(dead_code, deprecated)]
fn is_decode_trivial() -> bool {{ {is_trivial_body} }}
#[allow(dead_code, deprecated)]
fn abi_decode(ref mut buffer: BufferReader) -> Self {{
{body}
Expand Down Expand Up @@ -114,7 +124,7 @@ where
code.push_str(&format!(
"{field_name}: buffer.decode::<{field_type_name}>(),",
field_name = f.name.as_raw_ident_str(),
field_type_name = Self::generate_type(engines, &f.type_argument)?,
field_type_name = Self::generate_type(engines, &f.type_argument),
));
}

Expand All @@ -136,7 +146,7 @@ where
format!("{} => {}::{}, \n", x.tag, enum_name, name)
},
_ => {
let variant_type_name = Self::generate_type(engines, &x.type_argument)?;
let variant_type_name = Self::generate_type(engines, &x.type_argument);
format!("{tag_value} => {enum_name}::{variant_name}(buffer.decode::<{variant_type}>()), \n",
tag_value = x.tag,
enum_name = enum_name,
Expand Down Expand Up @@ -213,11 +223,24 @@ where
let implementing_for_decl_id = decl.to_struct_decl(&Handler::default(), engines).unwrap();
let struct_decl = self.ctx.engines().de().get(&implementing_for_decl_id);

let fields_types = struct_decl
.fields
.iter()
.map(|x| Self::generate_type(engines, &x.type_argument))
.collect::<BTreeSet<String>>();
let mut is_encode_trivial =
"__runtime_mem_id::<Self>() == __encoding_mem_id::<Self>()".to_string();
for field_type in fields_types {
is_encode_trivial.push_str(" && ");
is_encode_trivial.push_str(&format!("is_encode_trivial::<{}>()", field_type));
}

let abi_encode_body = self.generate_abi_encode_struct_body(engines, &struct_decl);
let abi_encode_code = self.generate_abi_encode_code(
struct_decl.name(),
&struct_decl.generic_parameters,
abi_encode_body,
&is_encode_trivial,
);
let abi_encode_node = self.parse_impl_trait_to_ty_ast_node(
engines,
Expand All @@ -226,11 +249,24 @@ where
crate::build_config::DbgGeneration::None,
);

let fields_types = struct_decl
.fields
.iter()
.map(|x| Self::generate_type(engines, &x.type_argument))
.collect::<BTreeSet<String>>();
let mut is_decode_trivial =
"__runtime_mem_id::<Self>() == __encoding_mem_id::<Self>()".to_string();
for field_type in fields_types {
is_decode_trivial.push_str(" && ");
is_decode_trivial.push_str(&format!("is_decode_trivial::<{}>()", field_type));
}

let abi_decode_body = self.generate_abi_decode_struct_body(engines, &struct_decl);
let abi_decode_code = self.generate_abi_decode_code(
struct_decl.name(),
&struct_decl.generic_parameters,
abi_decode_body?,
&is_decode_trivial,
);
let abi_decode_node = self.parse_impl_trait_to_ty_ast_node(
engines,
Expand Down Expand Up @@ -260,11 +296,24 @@ where
let enum_decl_id = decl.to_enum_id(&Handler::default(), engines).unwrap();
let enum_decl = self.ctx.engines().de().get(&enum_decl_id);

let fields_types = enum_decl
.variants
.iter()
.map(|x| Self::generate_type(engines, &x.type_argument))
.collect::<BTreeSet<String>>();
let mut is_encode_trivial =
"__runtime_mem_id::<Self>() == __encoding_mem_id::<Self>()".to_string();
for field_type in fields_types {
is_encode_trivial.push_str(" && ");
is_encode_trivial.push_str(&format!("is_encode_trivial::<{}>()", field_type));
}

let abi_encode_body = self.generate_abi_encode_enum_body(engines, &enum_decl);
let abi_encode_code = self.generate_abi_encode_code(
enum_decl.name(),
&enum_decl.generic_parameters,
abi_encode_body,
&is_encode_trivial,
);
let abi_encode_node = self.parse_impl_trait_to_ty_ast_node(
engines,
Expand All @@ -278,6 +327,7 @@ where
enum_decl.name(),
&enum_decl.generic_parameters,
abi_decode_body?,
"false",
);
let abi_decode_node = self.parse_impl_trait_to_ty_ast_node(
engines,
Expand Down Expand Up @@ -348,17 +398,10 @@ where
}
}

let Some(args_types) = decl
let args_types = decl
.parameters
.iter()
.map(|x| Self::generate_type(engines, &x.type_argument))
.collect::<Option<Vec<String>>>()
else {
let err = handler.emit_err(CompileError::UnknownType {
span: Span::dummy(),
});
return Err(err);
};
.map(|x| Self::generate_type(engines, &x.type_argument));
let args_types = itertools::intersperse(args_types, ", ".into()).collect::<String>();

let args_types = if args_types.is_empty() {
Expand All @@ -376,12 +419,7 @@ where
)
.collect::<String>();

let Some(return_type) = Self::generate_type(engines, &decl.return_type) else {
let err = handler.emit_err(CompileError::UnknownType {
span: Span::dummy(),
});
return Err(err);
};
let return_type = Self::generate_type(engines, &decl.return_type);

let method_name = decl.name.as_str();
let offset = if let Some(offset) = method_names.find(method_name) {
Expand All @@ -405,18 +443,15 @@ where
));
} else {
code.push_str(&format!(
"let args: {args_types} = _buffer.decode::<{args_types}>();
"let args: {args_types} = decode_from_raw_ptr::<{args_types}>(_buffer_ptr);
let _result: {return_type} = __contract_entry_{method_name}({expanded_args});\n"
));
}

if return_type == "()" {
code.push_str("__contract_ret(asm() { zero: raw_ptr }, 0);");
} else {
code.push_str(&format!(
"let _result: raw_slice = encode::<{return_type}>(_result);
__contract_ret(_result.ptr(), _result.len::<u8>());"
));
code.push_str(&format!("encode_and_return::<{return_type}>(&_result);"));
}

code.push_str("\n}\n");
Expand All @@ -439,12 +474,7 @@ where

let fallback = if let Some(fallback_fn) = fallback_fn {
let fallback_fn = engines.de().get(&fallback_fn);
let Some(return_type) = Self::generate_type(engines, &fallback_fn.return_type) else {
let err = handler.emit_err(CompileError::UnknownType {
span: Span::dummy(),
});
return Err(err);
};
let return_type = Self::generate_type(engines, &fallback_fn.return_type);
let method_name = fallback_fn.name.as_raw_ident_str();
match fallback_fn.purity {
Purity::Pure => {}
Expand Down Expand Up @@ -475,12 +505,15 @@ where
let code = format!(
"{att} pub fn __entry() {{
let _method_names = \"{method_names}\";
let mut _buffer = BufferReader::from_second_parameter();

let mut _first_param_buffer = BufferReader::from_first_parameter();
let _method_len = _first_param_buffer.read::<u64>();
let _method_name_ptr = _first_param_buffer.ptr();
let _method_names_ptr = _method_names.as_ptr();

let mut _buffer_ptr = BufferReader::from_second_parameter();

let _method_name_ptr = BufferReader::from_first_parameter();
let mut _method_name = BufferReader {{ ptr: _method_name_ptr }};
let _method_len = _method_name.read::<u64>();
let _method_name_ptr = _method_name.ptr();

{code}
{fallback}
}}"
Expand Down Expand Up @@ -512,17 +545,10 @@ where
decl: &TyFunctionDecl,
handler: &Handler,
) -> Result<TyAstNode, ErrorEmitted> {
let Some(args_types) = decl
let args_types = decl
.parameters
.iter()
.map(|x| Self::generate_type(engines, &x.type_argument))
.collect::<Option<Vec<String>>>()
else {
let err = handler.emit_err(CompileError::UnknownType {
span: Span::dummy(),
});
return Err(err);
};
.map(|x| Self::generate_type(engines, &x.type_argument));
let args_types = itertools::intersperse(args_types, ", ".into()).collect::<String>();

let expanded_args = itertools::intersperse(
Expand Down Expand Up @@ -604,17 +630,10 @@ where
decl: &TyFunctionDecl,
handler: &Handler,
) -> Result<TyAstNode, ErrorEmitted> {
let Some(args_types) = decl
let args_types = decl
.parameters
.iter()
.map(|x| Self::generate_type(engines, &x.type_argument))
.collect::<Option<Vec<String>>>()
else {
let err = handler.emit_err(CompileError::UnknownType {
span: Span::dummy(),
});
return Err(err);
};
.map(|x| Self::generate_type(engines, &x.type_argument));
let args_types = itertools::intersperse(args_types, ", ".into()).collect::<String>();
let args_types = if args_types.is_empty() {
"()".into()
Expand All @@ -631,17 +650,12 @@ where
)
.collect::<String>();

let Some(return_type) = Self::generate_type(engines, &decl.return_type) else {
let err = handler.emit_err(CompileError::UnknownType {
span: Span::dummy(),
});
return Err(err);
};
let return_type = Self::generate_type(engines, &decl.return_type);

let return_encode = if return_type == "()" {
"__contract_ret(0, 0)".to_string()
} else {
format!("encode_and_return::<{return_type}>(_result)")
format!("encode_and_return::<{return_type}>(&_result)")
};

let code = if args_types == "()" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,13 +319,13 @@ where
/// The safest way would be to return a canonical fully qualified type path.
/// We do not have a way to do this at the moment, so the best way is to use
/// exactly what was typed by the user, to accommodate aliased imports.
fn generate_type(engines: &Engines, ta: &GenericTypeArgument) -> Option<String> {
fn generate_type(engines: &Engines, ta: &GenericTypeArgument) -> String {
match &*engines.te().get(ta.type_id) {
// A special case for function return type.
// When a function does not define a return type, the span points to the whole signature.
TypeInfo::Tuple(v) if v.is_empty() => Some("()".into()),
TypeInfo::Tuple(v) if v.is_empty() => "()".into(),
// Otherwise, take the type from the span.
_ => Some(ta.span.as_str().to_string()),
_ => ta.span.as_str().to_string(),
}
}
}
Expand Down
Loading
Loading