Attribute for checking of trivial encoding and decoding#7575
Attribute for checking of trivial encoding and decoding#7575
Conversation
PR SummaryMedium Risk Overview Introduces stdlib helpers Written by Cursor Bugbot for commit 2a26feb. This will update automatically on new commits. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 4 potential issues.
Autofix Details
Bugbot Autofix prepared fixes for all 4 issues found in the latest run.
- ✅ Fixed: Debug statement accidentally committed to production
- Removed the stray
dbg!(&t.decls_to_check)call fromcompile_to_asmso compilation no longer emits unintended stderr output.
- Removed the stray
- ✅ Fixed: Misplaced test: non-trivially-decodable struct in should_pass
- Updated the
attribute_requireshould-pass program to use trivially decodable field types (u64and nestedu64struct) so it now matches its expected passing placement.
- Updated the
- ✅ Fixed: Attribute value required but silently ignored in check
- The require check now reads
arg.valueand only enforcestrivially_decodablewhen the value is explicitly true ("true"ortrue).
- The require check now reads
- ✅ Fixed: Require attribute check skipped for predicates and contracts
- Threaded
decls_to_checkthrough predicate and contract compilation paths so#[require(trivially_decodable = "true")]is validated there too.
- Threaded
Or push these changes by commenting:
@cursor push 73287ee042
Preview (73287ee042)
diff --git a/sway-core/src/ir_generation.rs b/sway-core/src/ir_generation.rs
--- a/sway-core/src/ir_generation.rs
+++ b/sway-core/src/ir_generation.rs
@@ -399,6 +399,7 @@
&mut panicking_fn_cache,
&test_fns,
&mut compiled_fn_cache,
+ decls_to_check,
),
ty::TyProgramKind::Contract {
entry_function,
@@ -409,6 +410,7 @@
abi_entries,
namespace,
declarations,
+ decls_to_check,
&logged_types,
&messages_types,
panic_occurrences,
diff --git a/sway-core/src/ir_generation/compile.rs b/sway-core/src/ir_generation/compile.rs
--- a/sway-core/src/ir_generation/compile.rs
+++ b/sway-core/src/ir_generation/compile.rs
@@ -1,9 +1,19 @@
use crate::{
- Engines, PanicOccurrences, PanickingCallOccurrences, TypeInfo, decl_engine::{DeclEngineGet, DeclId, DeclRefFunction}, ir_generation::{
- KeyedTyFunctionDecl, PanickingFunctionCache, convert::convert_resolved_typeid_no_span
- }, language::{
- Visibility, ty::{self, StructDecl, TyDecl}
- }, metadata::MetadataManager, namespace::ResolvedDeclaration, semantic_analysis::namespace, transform::AttributeKind, type_system::TypeId, types::{LogId, MessageId}
+ decl_engine::{DeclEngineGet, DeclId, DeclRefFunction},
+ ir_generation::{
+ convert::convert_resolved_typeid_no_span, KeyedTyFunctionDecl, PanickingFunctionCache,
+ },
+ language::{
+ ty::{self, StructDecl, TyDecl},
+ Visibility,
+ },
+ metadata::MetadataManager,
+ namespace::ResolvedDeclaration,
+ semantic_analysis::namespace,
+ transform::AttributeKind,
+ type_system::TypeId,
+ types::{LogId, MessageId},
+ Engines, PanicOccurrences, PanickingCallOccurrences, TypeInfo,
};
use super::{
@@ -13,7 +23,7 @@
CompiledFunctionCache,
};
-use sway_ast::attribute::REQUIRE_ARG_NAME_TRIVIALLY_DECODABLE;
+use sway_ast::{attribute::REQUIRE_ARG_NAME_TRIVIALLY_DECODABLE, Literal};
use sway_error::{error::CompileError, handler::Handler};
use sway_ir::{metadata::combine as md_combine, *};
use sway_types::{Ident, Span, Spanned};
@@ -104,6 +114,7 @@
panicking_fn_cache: &mut PanickingFunctionCache,
test_fns: &[(Arc<ty::TyFunctionDecl>, DeclRefFunction)],
compiled_fn_cache: &mut CompiledFunctionCache,
+ decls_to_check: &[TyDecl],
) -> Result<Module, Vec<CompileError>> {
let module = Module::new(context, Kind::Predicate);
@@ -138,7 +149,7 @@
panicking_fn_cache,
None,
compiled_fn_cache,
- &[],
+ decls_to_check,
)?;
compile_tests(
engines,
@@ -164,6 +175,7 @@
abi_entries: &[DeclId<ty::TyFunctionDecl>],
namespace: &namespace::Namespace,
declarations: &[ty::TyDecl],
+ decls_to_check: &[TyDecl],
logged_types_map: &HashMap<TypeId, LogId>,
messages_types_map: &HashMap<TypeId, MessageId>,
panic_occurrences: &mut PanicOccurrences,
@@ -217,7 +229,7 @@
panicking_fn_cache,
None,
compiled_fn_cache,
- &[],
+ decls_to_check,
)?;
} else {
// In the case of the encoding v0, we need to compile individual ABI entries
@@ -602,7 +614,18 @@
for (_, atts) in atts {
for att in atts.iter() {
for arg in att.args.iter() {
- if arg.name.as_str() == REQUIRE_ARG_NAME_TRIVIALLY_DECODABLE && !is_type_trivially_decodable(*decl_id) {
+ let requires_trivially_decodable = matches!(
+ &arg.value,
+ Some(Literal::String(val)) if val.parsed == "true"
+ ) || matches!(
+ &arg.value,
+ Some(Literal::Bool(val)) if val.kind.into()
+ );
+
+ if arg.name.as_str() == REQUIRE_ARG_NAME_TRIVIALLY_DECODABLE
+ && requires_trivially_decodable
+ && !is_type_trivially_decodable(*decl_id)
+ {
let mut infos = vec![];
let mut helps = vec![];
let mut bottom_helps = BTreeSet::new();
diff --git a/sway-core/src/lib.rs b/sway-core/src/lib.rs
--- a/sway-core/src/lib.rs
+++ b/sway-core/src/lib.rs
@@ -1188,10 +1188,6 @@
experimental,
)?;
- if let Ok(t) = ast_res.typed.as_ref() {
- dbg!(&t.decls_to_check);
- }
-
ast_to_asm(handler, engines, &ast_res, build_config, experimental)
}
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes/attribute_require/src/another_file.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes/attribute_require/src/another_file.sw
--- a/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes/attribute_require/src/another_file.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes/attribute_require/src/another_file.sw
@@ -1,5 +1,5 @@
library;
pub struct InnerStruct {
- pub a: bool,
-}
\ No newline at end of file
+ pub a: u64,
+}
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes/attribute_require/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes/attribute_require/src/main.sw
--- a/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes/attribute_require/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes/attribute_require/src/main.sw
@@ -5,21 +5,15 @@
#[require(trivially_decodable = "true")]
struct MyStruct {
- a: bool,
+ a: u64,
b: InnerStruct,
- c: SomeEnum,
- d: Vec<u64>,
+ c: u64,
+ d: u64,
}
-enum SomeEnum {
- A: ()
-}
-
fn main(s: MyStruct) {
__log(s.a);
__log(s.b.a);
__log(s.c);
__log(s.d);
- let a = SomeEnum::A;
- __log(a);
}This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
...src/e2e_vm_tests/test_programs/should_pass/language/attributes/attribute_require/src/main.sw
Show resolved
Hide resolved
Merging this PR will degrade performance by 20.02%
Performance Changes
Comparing |
...src/e2e_vm_tests/test_programs/should_pass/language/attributes/attribute_require/stdout.snap
Show resolved
Hide resolved
sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs
Show resolved
Hide resolved
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
There are 11 total unresolved issues (including 8 from previous reviews).
Autofix Details
Bugbot Autofix prepared fixes for all 3 issues found in the latest run.
- ✅ Fixed: Debug
eprintln!left in production code path- I removed the unconditional
eprintln!block fromtype_check_finalizeforEnumVariantsValuesso no debug output is emitted during normal compilation.
- I removed the unconditional
- ✅ Fixed:
EnumVariantsValuesintrinsic hardcodestruefor all variants- I replaced the hardcoded
truewith per-variant triviality computation by comparing each variant type’s encoding and runtime memory representations.
- I replaced the hardcoded
- ✅ Fixed: Type check hardcodes literal
3, panics otherwise- I removed the literal-
3match andtodo!()panic path, corrected the expected argument count to 1, and return a proper intrinsic type error for non-enum type arguments.
- I removed the literal-
Or push these changes by commenting:
@cursor push 64daa5eea7
Preview (64daa5eea7)
diff --git a/sway-core/src/ir_generation/function.rs b/sway-core/src/ir_generation/function.rs
--- a/sway-core/src/ir_generation/function.rs
+++ b/sway-core/src/ir_generation/function.rs
@@ -2477,7 +2477,7 @@
let elems = decl
.variants
.iter()
- .map(|_variant| {
+ .map(|variant| {
// let codec = namespace.module_from_absolute_path(&[
// BaseIdent::new_no_span("std".to_string()),
// BaseIdent::new_no_span("codec".to_string()),
@@ -2526,9 +2526,27 @@
// let value = r.get_content(context).as_bool().unwrap();
// dbg!(value);
- ConstantContent::new_bool(context, true)
+ let variant_type_info =
+ engines.te().get(variant.type_argument.type_id);
+ let encoding_representation =
+ get_encoding_representation(engines, &variant_type_info);
+ let runtime_type = convert_resolved_type_id(
+ self.engines,
+ context,
+ md_mgr,
+ self.module,
+ Some(self),
+ variant.type_argument.type_id,
+ &variant.type_argument.span,
+ )?;
+ let runtime_representation =
+ Some(get_runtime_representation(context, runtime_type));
+
+ let is_decode_trivial =
+ encoding_representation == runtime_representation;
+ Ok(ConstantContent::new_bool(context, is_decode_trivial))
})
- .collect::<Vec<_>>();
+ .collect::<Result<Vec<_>, CompileError>>()?;
let elems_len = ConstantContent::new_uint(context, 64, elems.len() as u64);
let elems_len = Constant::unique(context, elems_len);
diff --git a/sway-core/src/language/ty/expression/expression_variant.rs b/sway-core/src/language/ty/expression/expression_variant.rs
--- a/sway-core/src/language/ty/expression/expression_variant.rs
+++ b/sway-core/src/language/ty/expression/expression_variant.rs
@@ -1330,13 +1330,6 @@
for expr in kind.arguments.iter_mut() {
expr.type_check_finalize(handler, ctx)?;
}
-
- if let sway_ast::Intrinsic::EnumVariantsValues = kind.kind {
- eprintln!(
- "type_check_finalize: {:?}",
- ctx.engines.help_out(&kind.type_arguments)
- );
- }
}
TyExpressionVariant::AbiName(_) => {
todo!("")
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
--- a/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs
+++ b/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs
@@ -187,7 +187,7 @@
if arguments.len() != 1 {
return Err(handler.emit_err(CompileError::IntrinsicIncorrectNumArgs {
name: kind.to_string(),
- expected: 0,
+ expected: 1,
span,
}));
}
@@ -198,11 +198,6 @@
ty::TyExpression::type_check(handler, ctx, &arguments[0])?
};
- let _value_id = match first_argument_typed_expr.expression {
- ty::TyExpressionVariant::Literal(Literal::U64(3)) => 3,
- _ => todo!(),
- };
-
let arguments = vec![first_argument_typed_expr];
if type_arguments.len() != 1 {
@@ -233,12 +228,13 @@
let return_type = ctx.engines.te().insert_slice(ctx.engines, elem_type);
match &*ctx.engines.te().get(arg) {
- TypeInfo::UnknownGeneric { .. } => {}
- TypeInfo::Enum(_) => {
- todo!();
- }
+ TypeInfo::UnknownGeneric { .. } | TypeInfo::Enum(_) => {}
_ => {
- todo!()
+ return Err(handler.emit_err(CompileError::IntrinsicUnsupportedArgType {
+ name: kind.to_string(),
+ span: span.clone(),
+ hint: "Type argument must be an enum type.".to_string(),
+ }));
}
};This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs
Show resolved
Hide resolved
sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs
Show resolved
Hide resolved
sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs
Outdated
Show resolved
Hide resolved
65ab635 to
8b042ca
Compare
87e2c0e to
e90a678
Compare

Description
Closes #7567.
Checklist
Breaking*orNew Featurelabels where relevant.