diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/auto_impl.rs b/sway-core/src/semantic_analysis/ast_node/declaration/auto_impl.rs index 98def2c187f..9efcc2392d3 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/auto_impl.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/auto_impl.rs @@ -8,14 +8,14 @@ use crate::{ Purity, }, semantic_analysis::TypeCheckContext, - Engines, TypeId, TypeInfo, TypeParameter, + Engines, TypeArgument, TypeInfo, TypeParameter, }; use sway_error::{ error::CompileError, handler::{ErrorEmitted, Handler}, }; use sway_parse::Parse; -use sway_types::{integer_bits::IntegerBits, BaseIdent, Named, ProgramId, Span, Spanned}; +use sway_types::{BaseIdent, Named, ProgramId, Span, Spanned}; /// Contains all information needed to implement AbiEncode pub struct EncodingAutoImplContext<'a, 'b> @@ -38,7 +38,7 @@ where T: Parse, { // Uncomment this to see what is being generated - //println!("{}", input); + // println!("{}", input); let handler = <_>::default(); let source_id = @@ -195,7 +195,7 @@ where code.push_str(&format!( "{field_name}: buffer.decode::<{field_type_name}>(),", field_name = f.name.as_str(), - field_type_name = Self::generate_type(engines, f.type_argument.type_id)?, + field_type_name = Self::generate_type(engines, &f.type_argument)?, )); } @@ -217,7 +217,7 @@ where format!("{} => {}::{}, \n", x.tag, enum_name, name) }, _ => { - let variant_type_name = Self::generate_type(engines, x.type_argument.type_id)?; + 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, @@ -496,92 +496,15 @@ where } } - fn generate_type(engines: &Engines, type_id: TypeId) -> Option { - let name = match &*engines.te().get(type_id) { - TypeInfo::UnknownGeneric { name, .. } => name.to_string(), - TypeInfo::Placeholder(type_param) => type_param.name.to_string(), - TypeInfo::StringSlice => "str".into(), - TypeInfo::StringArray(x) => format!("str[{}]", x.val()), - TypeInfo::UnsignedInteger(x) => match x { - IntegerBits::Eight => "u8", - IntegerBits::Sixteen => "u16", - IntegerBits::ThirtyTwo => "u32", - IntegerBits::SixtyFour => "u64", - IntegerBits::V256 => "u256", - } - .into(), - TypeInfo::Boolean => "bool".into(), - TypeInfo::Custom { - qualified_call_path: call_path, - .. - } => call_path.call_path.suffix.to_string(), - TypeInfo::Tuple(fields) => { - if fields.is_empty() { - return Some("()".into()); - } - let field_strs = fields - .iter() - .map(|field| Self::generate_type(engines, field.type_id)) - .collect::>>()?; - format!("({},)", field_strs.join(", ")) - } - TypeInfo::B256 => "b256".into(), - TypeInfo::Enum(decl_id) => { - let decl = engines.de().get_enum(decl_id); - - let type_parameters = decl - .type_parameters - .iter() - .map(|x| Self::generate_type(engines, x.type_id)) - .collect::>>()? - .join(", "); - - let type_parameters = if !type_parameters.is_empty() { - format!("<{type_parameters}>") - } else { - type_parameters - }; - - format!("{}{type_parameters}", decl.call_path.suffix.as_str()) - } - TypeInfo::Struct(decl_id) => { - let decl = engines.de().get(decl_id); - - let type_parameters = decl - .type_parameters - .iter() - .map(|x| Self::generate_type(engines, x.type_id)) - .collect::>>()? - .join(", "); - - let type_parameters = if !type_parameters.is_empty() { - format!("<{type_parameters}>") - } else { - type_parameters - }; - - format!("{}{type_parameters}", decl.call_path.suffix.as_str()) - } - TypeInfo::Array(elem_ty, count) => { - format!( - "[{}; {}]", - Self::generate_type(engines, elem_ty.type_id)?, - count.val() - ) - } - TypeInfo::Slice(elem_ty) => { - format!( - "__slice[{}]", - Self::generate_type(engines, elem_ty.type_id)? - ) - } - TypeInfo::RawUntypedPtr => "raw_ptr".into(), - TypeInfo::RawUntypedSlice => "raw_slice".into(), - TypeInfo::Alias { name, .. } => name.to_string(), - _ => return None, - }; - - Some(name) + // 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, t: &TypeArgument) -> Option { + match &*engines.te().get(t.type_id) { + // 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()), + _ => Some(t.span().as_str().to_string()), + } } pub(crate) fn generate_contract_entry( @@ -613,7 +536,7 @@ where let Some(args_types) = decl .parameters .iter() - .map(|x| Self::generate_type(engines, x.type_argument.type_id)) + .map(|x| Self::generate_type(engines, &x.type_argument)) .collect::>>() else { let err = handler.emit_err(CompileError::UnknownType { @@ -638,7 +561,7 @@ where ) .collect::(); - let Some(return_type) = Self::generate_type(engines, decl.return_type.type_id) else { + let Some(return_type) = Self::generate_type(engines, &decl.return_type) else { let err = handler.emit_err(CompileError::UnknownType { span: Span::dummy(), }); @@ -674,8 +597,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.type_id) - else { + let Some(return_type) = Self::generate_type(engines, &fallback_fn.return_type) else { let err = handler.emit_err(CompileError::UnknownType { span: Span::dummy(), }); @@ -743,7 +665,7 @@ where let Some(args_types) = decl .parameters .iter() - .map(|x| Self::generate_type(engines, x.type_argument.type_id)) + .map(|x| Self::generate_type(engines, &x.type_argument)) .collect::>>() else { let err = handler.emit_err(CompileError::UnknownType { @@ -836,7 +758,7 @@ where let Some(args_types) = decl .parameters .iter() - .map(|x| Self::generate_type(engines, x.type_argument.type_id)) + .map(|x| Self::generate_type(engines, &x.type_argument)) .collect::>>() else { let err = handler.emit_err(CompileError::UnknownType { @@ -860,7 +782,7 @@ where ) .collect::(); - let Some(return_type) = Self::generate_type(engines, decl.return_type.type_id) else { + let Some(return_type) = Self::generate_type(engines, &decl.return_type) else { let err = handler.emit_err(CompileError::UnknownType { span: Span::dummy(), }); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/main_args/main_args_various_types/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/main_args/main_args_various_types/Forc.toml index a06f647ef58..79e3031d8bd 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/main_args/main_args_various_types/Forc.toml +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/main_args/main_args_various_types/Forc.toml @@ -5,4 +5,4 @@ license = "Apache-2.0" name = "main_args_various_types" [dependencies] -std = { path = "../../../../../reduced_std_libs/sway-lib-std-assert" } +std = { path = "../../../../../../../../sway-lib-std" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/main_args/main_args_various_types/json_abi_oracle_new_encoding.json b/test/src/e2e_vm_tests/test_programs/should_pass/language/main_args/main_args_various_types/json_abi_oracle_new_encoding.json index 6d95b04580f..ee7cb119623 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/main_args/main_args_various_types/json_abi_oracle_new_encoding.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/main_args/main_args_various_types/json_abi_oracle_new_encoding.json @@ -6,8 +6,8 @@ "type": "[(struct OpName, enum SignedNum); 2]" }, { - "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0", - "type": "u64" + "concreteTypeId": "d489af6a272dc02bb98c58446e5250345c65721ecfef3f43b26c263819725668", + "type": "generic AliasedS" } ], "configurables": [], @@ -22,7 +22,7 @@ } ], "name": "main", - "output": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + "output": "d489af6a272dc02bb98c58446e5250345c65721ecfef3f43b26c263819725668" } ], "loggedTypes": [ @@ -61,11 +61,11 @@ "components": [ { "name": "Positive", - "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + "typeId": 5 }, { "name": "Negative", - "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + "typeId": 5 } ], "metadataTypeId": 2, @@ -84,6 +84,10 @@ ], "metadataTypeId": 4, "type": "struct OpName" + }, + { + "metadataTypeId": 5, + "type": "u64" } ], "programType": "script", diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/main_args/main_args_various_types/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/main_args/main_args_various_types/src/main.sw index cf8cb142ee1..55cf6bae4d3 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/main_args/main_args_various_types/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/main_args/main_args_various_types/src/main.sw @@ -1,5 +1,9 @@ script; +mod types; + +use types::{S as AliasedS}; + fn eq_str_3(a: str[3], b: str) -> bool { let ptr_b = b.as_ptr(); asm(a: a, b: ptr_b, len: 3, r) { @@ -17,7 +21,7 @@ struct OpName { val: str[3] } -fn main(ops: [(OpName, SignedNum); 2]) -> u64 { +fn main(ops: [(OpName, SignedNum); 2]) -> AliasedS { __log(ops); assert(eq_str_3(ops[0].0.val, "set")); assert(match ops[0].1 { @@ -31,5 +35,7 @@ fn main(ops: [(OpName, SignedNum); 2]) -> u64 { _ => revert(2), } == 1); - 1 + AliasedS{ + v: 1 + } } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/main_args/main_args_various_types/src/types.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/main_args/main_args_various_types/src/types.sw new file mode 100644 index 00000000000..8e5e9741521 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/main_args/main_args_various_types/src/types.sw @@ -0,0 +1,5 @@ +library; + +pub struct S { + pub v: u64 +} \ No newline at end of file