From 73a4be0641e512a7947ce418963341893dad7a6b Mon Sep 17 00:00:00 2001 From: Daniel Frederico Lins Leite Date: Mon, 4 Nov 2024 19:39:23 -0300 Subject: [PATCH] better error messages --- sway-core/src/ir_generation/function.rs | 18 ++++- .../ast_node/expression/intrinsic_function.rs | 44 ++++++++++--- sway-error/src/error.rs | 3 + .../language/intrinsics/transmute/.gitignore | 2 + .../language/intrinsics/transmute/Forc.lock | 8 +++ .../language/intrinsics/transmute/Forc.toml | 8 +++ .../transmute/debug/transmute-abi.json | 28 ++++++++ .../transmute/debug/transmute-bin-hash | 1 + .../intrinsics/transmute/debug/transmute.bin | Bin 0 -> 1088 bytes .../intrinsics/transmute/snapshot.toml | 0 .../language/intrinsics/transmute/src/main.sw | 16 +++++ .../language/intrinsics/transmute/stdout.snap | 62 ++++++++++++++++++ .../json_abi_oracle_new_encoding.json | 23 +++++++ .../language/intrinsics/transmute/src/main.sw | 5 +- .../language/intrinsics/transmute/test.toml | 2 +- 15 files changed, 206 insertions(+), 14 deletions(-) create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/.gitignore create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/debug/transmute-abi.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/debug/transmute-bin-hash create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/debug/transmute.bin create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/snapshot.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/stdout.snap create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/transmute/json_abi_oracle_new_encoding.json diff --git a/sway-core/src/ir_generation/function.rs b/sway-core/src/ir_generation/function.rs index 4049eb32627..95843738e28 100644 --- a/sway-core/src/ir_generation/function.rs +++ b/sway-core/src/ir_generation/function.rs @@ -2194,11 +2194,16 @@ impl<'eng> FnCompiler<'eng> { let te = self.engines.te(); let de = self.engines.de(); + let u8 = Type::get_uint8(context); + let ptr_u8 = Type::new_ptr(context, u8); + let first_argument_expr = &arguments[0]; let first_argument_value = return_on_termination_or_extract!( self.compile_expression_to_value(context, md_mgr, first_argument_expr)? ); + let first_argument_type = first_argument_value.get_type(context).unwrap(); // TODO unwrap let first_argument_ptr = save_to_local_return_ptr(self, context, first_argument_value)?; + let first_argument_ptr = self.current_block.append(context).cast_ptr(first_argument_ptr, ptr_u8); let return_type_elem_ir_type = convert_resolved_type_id( te, @@ -2212,12 +2217,21 @@ impl<'eng> FnCompiler<'eng> { .new_local_var(context, temp_arg_name, return_type_elem_ir_type, None, false) .map_err(|ir_error| CompileError::InternalOwned(ir_error.to_string(), Span::dummy()))?; let dst_local_var_ptr = self.current_block.append(context).get_local(dst_local_var); + let dst_local_var_ptr_as_u8 = self.current_block.append(context).cast_ptr(dst_local_var_ptr, ptr_u8); - // TODO assert both types have the same size + // type check must not allows this to fail + let first_arg_size = first_argument_type.size(&context).in_bytes(); + let return_type_size = return_type_elem_ir_type.size(&context).in_bytes(); + if first_arg_size != return_type_size { + return Err(CompileError::Internal( + "Types size do not match", + Span::dummy(), // TODO + )); + } let byte_len = return_type_elem_ir_type.size(&context).in_bytes(); self.current_block.append(context) - .mem_copy_bytes(dst_local_var_ptr, first_argument_ptr, byte_len); + .mem_copy_bytes(dst_local_var_ptr_as_u8, first_argument_ptr, byte_len); let final_value = self.current_block.append(context).load(dst_local_var_ptr); Ok(TerminatorValue::new(final_value, context)) diff --git a/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs b/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs index 17f45d8c212..f438b8b9067 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs @@ -134,23 +134,49 @@ fn type_check_transmute( let mut ctx = ctx; + // Both type arguments needs to be explicitly defined + if type_arguments.len() != 2 { + return Err(handler.emit_err(CompileError::IntrinsicIncorrectNumTArgs { + name: kind.to_string(), + expected: 2, + span, + })); + } + + let src_type = type_arguments[0].type_id; + let return_type = type_arguments[1].type_id; + + // Forbid ref and ptr types + fn forbid_ref_ptr_types(engines: &Engines, handler: &Handler, t: TypeId, span: &Span) -> Result<(), ErrorEmitted> { + let types = t.extract_any_including_self(engines, &|t| matches!(t, + TypeInfo::StringSlice | + TypeInfo::RawUntypedPtr | + TypeInfo::RawUntypedSlice | + TypeInfo::Ptr(_) | + TypeInfo::Slice(_) | + TypeInfo::Ref { .. }), vec![], 0); + if !types.is_empty() { + return Err(handler.emit_err(CompileError::TypeNotAllowed { + reason: sway_error::error::TypeNotAllowedReason::NotAllowedInTransmute, + span: span.clone() + })); + } else { + Ok(()) + } + } + + forbid_ref_ptr_types(engines, handler, src_type, &type_arguments[0].span)?; + forbid_ref_ptr_types(engines, handler, return_type, &type_arguments[1].span)?; + // check first argument - let first_argument_span = arguments[0].span.clone(); - let first_argument_type = type_engine.insert(engines, TypeInfo::Unknown, None); let first_argument_typed_expr = { let ctx = ctx .by_ref() .with_help_text("") - .with_type_annotation(first_argument_type); + .with_type_annotation(src_type); ty::TyExpression::type_check(handler, ctx, &arguments[0])? }; - let src_type = type_arguments[0].clone(); - // TODO: check types match - // TODO: check they have the same size - - let return_type = type_arguments[1].type_id; - Ok(( TyIntrinsicFunctionKind { kind, diff --git a/sway-error/src/error.rs b/sway-error/src/error.rs index 3998426f92e..fb129fa9903 100644 --- a/sway-error/src/error.rs +++ b/sway-error/src/error.rs @@ -2812,6 +2812,9 @@ pub enum TypeNotAllowedReason { #[error("slices or types containing slices on `const` are not allowed.")] SliceInConst, + + #[error("references, pointers, slices, string slices or types containing any of these are not allowed.")] + NotAllowedInTransmute, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/.gitignore b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/Forc.lock new file mode 100644 index 00000000000..f9932679777 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/Forc.lock @@ -0,0 +1,8 @@ +[[package]] +name = "core" +source = "path+from-root-E4EB5F90E61EC58F" + +[[package]] +name = "transmute" +source = "member" +dependencies = ["core"] diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/Forc.toml new file mode 100644 index 00000000000..457f84ef26a --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +license = "Apache-2.0" +entry = "main.sw" +name = "transmute" + +[dependencies] +core = { path = "../../../../../../../../sway-lib-core" } diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/debug/transmute-abi.json b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/debug/transmute-abi.json new file mode 100644 index 00000000000..c42f6cefac2 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/debug/transmute-abi.json @@ -0,0 +1,28 @@ +{ + "programType": "script", + "specVersion": "1", + "encodingVersion": "1", + "concreteTypes": [ + { + "type": "u64", + "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + } + ], + "metadataTypes": [], + "functions": [ + { + "inputs": [], + "name": "main", + "output": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0", + "attributes": null + } + ], + "loggedTypes": [ + { + "logId": "1515152261580153489", + "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + } + ], + "messagesTypes": [], + "configurables": [] +} \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/debug/transmute-bin-hash b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/debug/transmute-bin-hash new file mode 100644 index 00000000000..86a358e416a --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/debug/transmute-bin-hash @@ -0,0 +1 @@ +0x82d76771fa3e7e2cc3c0f9904b45673c9066384f3077cd97e20892c965a096db \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/debug/transmute.bin b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/debug/transmute.bin new file mode 100644 index 0000000000000000000000000000000000000000..4c9d69d93cbd0cdf9999c405362669932f70c5c3 GIT binary patch literal 1088 zcmd5*&2G~`82lXE#QcaZ#gU>75k8d4M@!_;<64g8ghuKLgopsw6(^37g%ILWA30JG z&|@FLmN;MS@DHdI+*>i>ujti+c6q6%H>Lj2ORwSVB|nCDM{M5rI``na@;lcB zdL0z+%6o6Df%AH}k=|%)`a|4P!G4LkI_8xwtCgP;eIQEsnL~TX#usGd!Gu&+c4k@8 z_V}}X;!oZae>9?4=(HxFMGOhLhM4zFg<)NePKd#$1~RDp`vxryl|vb10{t|UkJ8JO zrwvzT<~m&k6liT8)Z z{5D1Ywwj5ddIZN|lsi1ittK?yfi9=y!P#WSpABYsmR!Q2GgEoH(4Tf^b?JVIL#ru$ z#_*5+08dN0mJ#=nUDrGS=Qi{(+g(+&7~>k!fZ>Hi@4~_<%W|iPDE1ecVR`mGnczX6a`6ny{y literal 0 HcmV?d00001 diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/snapshot.toml b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/snapshot.toml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/src/main.sw new file mode 100644 index 00000000000..6873ab62973 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/src/main.sw @@ -0,0 +1,16 @@ +script; + +fn main() { + // Missing type arguments + let _ = __transmute(1u64); + let _ = __transmute::(1u64); + + // Wrong source type + let _ = __transmute::(1u32); + + // Different sizes + let _ = __transmute::(1u64); + + // Invalid types + let _ = __transmute::<&u64, &u8>(&1u64); +} diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/stdout.snap new file mode 100644 index 00000000000..70f758a10e0 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/stdout.snap @@ -0,0 +1,62 @@ +--- +source: test/tests/tests.rs +snapshot_kind: text +--- +> forc build --path test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute +exit status: 1 +output: + Building test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute + Compiling library core (sway-lib-core) + Compiling script transmute (test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute) +error + --> test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/src/main.sw:5:13 + | +3 | fn main() { +4 | // Missing type arguments +5 | let _ = __transmute(1u64); + | ^^^^^^^^^^^^^^^^^ Call to "transmute" expects 2 type arguments +6 | let _ = __transmute::(1u64); +7 | + | +____ + +error + --> test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/src/main.sw:6:13 + | +4 | // Missing type arguments +5 | let _ = __transmute(1u64); +6 | let _ = __transmute::(1u64); + | ^^^^^^^^^^^^^^^^^^^^^^^^ Call to "transmute" expects 2 type arguments +7 | +8 | // Wrong source type + | +____ + +error + --> test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/src/main.sw:9:36 + | + 7 | + 8 | // Wrong source type + 9 | let _ = __transmute::(1u32); + | ^^^^ Mismatched types. +expected: u64 +found: u32. + +10 | +11 | // Different sizes + | +____ + +error + --> test/src/e2e_vm_tests/test_programs/should_fail/language/intrinsics/transmute/src/main.sw:15:27 + | +13 | +14 | // Invalid types +15 | let _ = __transmute::<&u64, &u8>(&1u64); + | ^^^^ references, pointers, slices, string slices or types containing any of these are not allowed. +16 | } + | +____ + + Aborting due to 4 errors. +error: Failed to compile transmute diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/transmute/json_abi_oracle_new_encoding.json b/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/transmute/json_abi_oracle_new_encoding.json new file mode 100644 index 00000000000..05b0f04b2d3 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/transmute/json_abi_oracle_new_encoding.json @@ -0,0 +1,23 @@ +{ + "concreteTypes": [ + { + "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0", + "type": "u64" + } + ], + "configurables": [], + "encodingVersion": "1", + "functions": [ + { + "attributes": null, + "inputs": [], + "name": "main", + "output": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + } + ], + "loggedTypes": [], + "messagesTypes": [], + "metadataTypes": [], + "programType": "script", + "specVersion": "1" +} \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/transmute/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/transmute/src/main.sw index aa713678def..35edf16b2da 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/transmute/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/transmute/src/main.sw @@ -1,6 +1,7 @@ script; fn main() -> u64 { - let a = 1u8; - __transmute::<[u8;4], u64>([0u8, 0u8, 0u8, a]) + let a = __transmute::<[u8; 8], u64>([0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8]); + let b = __transmute::<(u64,), u64>((2,)); + a + b } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/transmute/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/transmute/test.toml index 53fb5ce9a94..60cfbe5045c 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/transmute/test.toml +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/transmute/test.toml @@ -1,4 +1,4 @@ category = "run" expected_result = { action = "return", value = 1 } -expected_result_new_encoding = { action = "return_data", value = "01" } +expected_result_new_encoding = { action = "return_data", value = "00 00 00 00 00 00 00 03" } validate_abi = true