diff --git a/external-crates/move/crates/move-compiler/src/cfgir/visitor.rs b/external-crates/move/crates/move-compiler/src/cfgir/visitor.rs index 4fbe1f3d9a6d9..11807f3a2aa62 100644 --- a/external-crates/move/crates/move-compiler/src/cfgir/visitor.rs +++ b/external-crates/move/crates/move-compiler/src/cfgir/visitor.rs @@ -319,6 +319,18 @@ pub trait CFGIRVisitorContext { } } +impl From for CFGIRVisitorObj { + fn from(value: V) -> Self { + Box::new(value) + } +} + +impl CFGIRVisitor for V { + fn visit(&mut self, env: &mut CompilationEnv, program: &mut G::Program) { + self.visit(env, program) + } +} + //************************************************************************************************** // simple absint visitor //************************************************************************************************** diff --git a/external-crates/move/crates/move-compiler/src/linters/meaningless_math_operation.rs b/external-crates/move/crates/move-compiler/src/linters/meaningless_math_operation.rs new file mode 100644 index 0000000000000..b1cc6bc4af7cf --- /dev/null +++ b/external-crates/move/crates/move-compiler/src/linters/meaningless_math_operation.rs @@ -0,0 +1,152 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! Detects meaningless math operations like `x * 0`, `x << 0`, `x >> 0`, `x * 1`, `x + 0`, `x - 0` +//! Aims to reduce code redundancy and improve clarity by flagging operations with no effect. +use crate::{ + cfgir::ast as G, + cfgir::visitor::{CFGIRVisitorConstructor, CFGIRVisitorContext}, + diag, + diagnostics::{ + codes::{custom, DiagnosticInfo, Severity}, + WarningFilters, + }, + hlir::ast::{self as H, Value_}, + parser::ast::BinOp_, + shared::CompilationEnv, +}; +use move_core_types::u256::U256; +use move_ir_types::location::Loc; + +use super::{LinterDiagnosticCategory, LINT_WARNING_PREFIX, MEANINGLESS_MATH_DIAG_CODE}; + +const MEANINGLESS_MATH_OP_DIAG: DiagnosticInfo = custom( + LINT_WARNING_PREFIX, + Severity::Warning, + LinterDiagnosticCategory::Complexity as u8, + MEANINGLESS_MATH_DIAG_CODE, + "math operation can be simplified", +); + +pub struct MeaninglessMathOperation; + +pub struct Context<'a> { + env: &'a mut CompilationEnv, +} + +impl CFGIRVisitorConstructor for MeaninglessMathOperation { + type Context<'a> = Context<'a>; + + fn context<'a>(env: &'a mut CompilationEnv, _program: &G::Program) -> Self::Context<'a> { + Context { env } + } +} + +impl CFGIRVisitorContext for Context<'_> { + fn add_warning_filter_scope(&mut self, filter: WarningFilters) { + self.env.add_warning_filter_scope(filter) + } + fn pop_warning_filter_scope(&mut self) { + self.env.pop_warning_filter_scope() + } + + fn visit_exp_custom(&mut self, exp: &mut H::Exp) -> bool { + let H::UnannotatedExp_::BinopExp(lhs, op, rhs) = &exp.exp.value else { + return false; + }; + + // unchanged operations + let is_unchanged = match op.value { + BinOp_::Mul => is_one(lhs).or(is_one(rhs)), + BinOp_::Div => is_one(rhs), + BinOp_::Add => is_zero(lhs).or(is_zero(rhs)), + BinOp_::Sub => is_zero(rhs), + BinOp_::Shl | BinOp_::Shr => is_zero(rhs), + _ => None, + }; + if let Some(meaningless_operand) = is_unchanged { + let msg = "This operation has no effect and can be removed"; + self.env.add_diag(diag!( + MEANINGLESS_MATH_OP_DIAG, + (exp.exp.loc, msg), + (meaningless_operand, "Because of this operand"), + )); + } + + // always zero + let is_always_zero = match op.value { + BinOp_::Mul => is_zero(lhs).or(is_zero(rhs)), + BinOp_::Div => is_zero(lhs), + BinOp_::Mod => is_zero(lhs).or(is_one(rhs)), + _ => None, + }; + if let Some(zero_operand) = is_always_zero { + let msg = "This operation is always zero and can be replaced with '0'"; + self.env.add_diag(diag!( + MEANINGLESS_MATH_OP_DIAG, + (exp.exp.loc, msg), + (zero_operand, "Because of this operand"), + )); + } + + // always one + let is_always_one = match op.value { + BinOp_::Mod => is_one(lhs), + _ => None, + }; + if let Some(one_operand) = is_always_one { + let msg = "This operation is always one and can be replaced with '1'"; + self.env.add_diag(diag!( + MEANINGLESS_MATH_OP_DIAG, + (exp.exp.loc, msg), + (one_operand, "Because of this operand"), + )); + } + + // for aborts, e.g. x / 0, we will let the optimizer give a warning + + false + } +} + +fn is_zero(exp: &H::Exp) -> Option { + let H::UnannotatedExp_::Value(sp!(loc, value_)) = &exp.exp.value else { + return None; + }; + match value_ { + Value_::U8(0) | Value_::U16(0) | Value_::U32(0) | Value_::U64(0) | Value_::U128(0) => { + Some(*loc) + } + Value_::U256(u) if u == &U256::zero() => Some(*loc), + Value_::U8(_) + | Value_::U16(_) + | Value_::U32(_) + | Value_::U64(_) + | Value_::U128(_) + | Value_::U256(_) + | Value_::Address(_) + | Value_::Bool(_) + | Value_::Vector(_, _) => None, + } +} + +fn is_one(exp: &H::Exp) -> Option { + let H::UnannotatedExp_::Value(sp!(loc, value_)) = &exp.exp.value else { + return None; + }; + match value_ { + Value_::U8(1) | Value_::U16(1) | Value_::U32(1) | Value_::U64(1) | Value_::U128(1) => { + Some(*loc) + } + Value_::U256(u) if u == &U256::one() => Some(*loc), + Value_::U8(_) + | Value_::U16(_) + | Value_::U32(_) + | Value_::U64(_) + | Value_::U128(_) + | Value_::U256(_) + | Value_::Address(_) + | Value_::Bool(_) + | Value_::Vector(_, _) => None, + } +} diff --git a/external-crates/move/crates/move-compiler/src/linters/mod.rs b/external-crates/move/crates/move-compiler/src/linters/mod.rs index 0457c5d511f51..bbd7cc3449677 100644 --- a/external-crates/move/crates/move-compiler/src/linters/mod.rs +++ b/external-crates/move/crates/move-compiler/src/linters/mod.rs @@ -4,10 +4,11 @@ use move_symbol_pool::Symbol; use crate::{ - command_line::compiler::Visitor, diagnostics::codes::WarningFilter, - linters::constant_naming::ConstantNamingVisitor, typing::visitor::TypingVisitor, + cfgir::visitor::CFGIRVisitor, command_line::compiler::Visitor, + diagnostics::codes::WarningFilter, typing::visitor::TypingVisitor, }; pub mod constant_naming; +pub mod meaningless_math_operation; mod unnecessary_while_loop; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -37,6 +38,8 @@ pub const CONSTANT_NAMING_FILTER_NAME: &str = "constant_naming"; pub const CONSTANT_NAMING_DIAG_CODE: u8 = 1; pub const WHILE_TRUE_TO_LOOP_FILTER_NAME: &str = "while_true"; pub const WHILE_TRUE_TO_LOOP_DIAG_CODE: u8 = 4; +pub const MEANINGLESS_MATH_FILTER_NAME: &str = "unnecessary_math"; +pub const MEANINGLESS_MATH_DIAG_CODE: u8 = 8; pub fn known_filters() -> (Option, Vec) { ( @@ -54,6 +57,12 @@ pub fn known_filters() -> (Option, Vec) { WHILE_TRUE_TO_LOOP_DIAG_CODE, Some(WHILE_TRUE_TO_LOOP_FILTER_NAME), ), + WarningFilter::code( + Some(LINT_WARNING_PREFIX), + LinterDiagnosticCategory::Complexity as u8, + MEANINGLESS_MATH_DIAG_CODE, + Some(MEANINGLESS_MATH_FILTER_NAME), + ), ], ) } @@ -63,10 +72,9 @@ pub fn linter_visitors(level: LintLevel) -> Vec { LintLevel::None | LintLevel::Default => vec![], LintLevel::All => { vec![ - constant_naming::ConstantNamingVisitor::visitor(ConstantNamingVisitor), - unnecessary_while_loop::WhileTrueToLoop::visitor( - unnecessary_while_loop::WhileTrueToLoop, - ), + constant_naming::ConstantNamingVisitor.visitor(), + unnecessary_while_loop::WhileTrueToLoop.visitor(), + meaningless_math_operation::MeaninglessMathOperation.visitor(), ] } } diff --git a/external-crates/move/crates/move-compiler/tests/linter/false_negative_meaningless_math_operation.move b/external-crates/move/crates/move-compiler/tests/linter/false_negative_meaningless_math_operation.move new file mode 100644 index 0000000000000..15c7022c87a49 --- /dev/null +++ b/external-crates/move/crates/move-compiler/tests/linter/false_negative_meaningless_math_operation.move @@ -0,0 +1,12 @@ +module 0x42::M { + public fun zero_shift_complex(x: u64, y: u64): u64 { + x * (y - y) // This is effectively * 0, but is not currently caught + } + + public fun ast_fold() { + // we do not lint on these because they are folded to a single value + let x = 0; + x * 1; + 1 * 0; + } +} diff --git a/external-crates/move/crates/move-compiler/tests/linter/suppress_meaningless_math_operation.move b/external-crates/move/crates/move-compiler/tests/linter/suppress_meaningless_math_operation.move new file mode 100644 index 0000000000000..8f2bc2d3a2a32 --- /dev/null +++ b/external-crates/move/crates/move-compiler/tests/linter/suppress_meaningless_math_operation.move @@ -0,0 +1,8 @@ +// tests suppression of unnecessary math operations +module 0x42::M { + + #[allow(lint(unnecessary_math))] + public fun add_zero(x: u64): u64 { + x + 0 + } +} diff --git a/external-crates/move/crates/move-compiler/tests/linter/true_negative_meaningless_math_operation.move b/external-crates/move/crates/move-compiler/tests/linter/true_negative_meaningless_math_operation.move new file mode 100644 index 0000000000000..8c75f70763938 --- /dev/null +++ b/external-crates/move/crates/move-compiler/tests/linter/true_negative_meaningless_math_operation.move @@ -0,0 +1,17 @@ +module 0x42::M { + public fun multiply_by_two(x: u64): u64 { + x * 2 // Should not trigger the linter + } + + public fun left_shift_by_one(x: u64): u64 { + x << 1 // Should not trigger the linter + } + + public fun add_one(x: u64): u64 { + x + 1 // Should not trigger the linter + } + + public fun divide_by_two(x: u64): u64 { + x / 2 // Should not trigger the linter + } +} diff --git a/external-crates/move/crates/move-compiler/tests/linter/true_positive_meaningless_math_operation.exp b/external-crates/move/crates/move-compiler/tests/linter/true_positive_meaningless_math_operation.exp new file mode 100644 index 0000000000000..3dab08d2dc99a --- /dev/null +++ b/external-crates/move/crates/move-compiler/tests/linter/true_positive_meaningless_math_operation.exp @@ -0,0 +1,340 @@ +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:3:9 + │ +3 │ x * 1; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation has no effect and can be removed + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:4:9 + │ +4 │ 1 * x; + │ ^^^^^ + │ │ + │ This operation has no effect and can be removed + │ Because of this operand + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:5:9 + │ +5 │ x / 1; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation has no effect and can be removed + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:6:9 + │ +6 │ x + 0; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation has no effect and can be removed + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:7:9 + │ +7 │ 0 + x; + │ ^^^^^ + │ │ + │ This operation has no effect and can be removed + │ Because of this operand + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:8:9 + │ +8 │ x - 0; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation has no effect and can be removed + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:9:9 + │ +9 │ x << 0; + │ ^^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation has no effect and can be removed + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:10:9 + │ +10 │ x << 0; + │ ^^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation has no effect and can be removed + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:14:9 + │ +14 │ x * 0; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation is always zero and can be replaced with '0' + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:15:9 + │ +15 │ 0 * x; + │ ^^^^^ + │ │ + │ This operation is always zero and can be replaced with '0' + │ Because of this operand + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:16:9 + │ +16 │ 0 / x; + │ ^^^^^ + │ │ + │ This operation is always zero and can be replaced with '0' + │ Because of this operand + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:17:9 + │ +17 │ 0 % x; + │ ^^^^^ + │ │ + │ This operation is always zero and can be replaced with '0' + │ Because of this operand + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:18:9 + │ +18 │ x % 1; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation is always zero and can be replaced with '0' + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:22:9 + │ +22 │ 1 % x; + │ ^^^^^ + │ │ + │ This operation is always one and can be replaced with '1' + │ Because of this operand + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:27:9 + │ +26 │ let y = 1; + │ - Because of this operand +27 │ x * y; + │ ^^^^^ This operation has no effect and can be removed + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:28:9 + │ +28 │ x - (1 - 1); + │ ^^^^^^^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation has no effect and can be removed + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:32:9 + │ +32 │ x * 1; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation has no effect and can be removed + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:33:9 + │ +33 │ x * 0; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation is always zero and can be replaced with '0' + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:34:9 + │ +34 │ 1 % x; + │ ^^^^^ + │ │ + │ This operation is always one and can be replaced with '1' + │ Because of this operand + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:38:9 + │ +38 │ x * 1; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation has no effect and can be removed + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:39:9 + │ +39 │ x * 0; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation is always zero and can be replaced with '0' + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:40:9 + │ +40 │ 1 % x; + │ ^^^^^ + │ │ + │ This operation is always one and can be replaced with '1' + │ Because of this operand + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:44:9 + │ +44 │ x * 1; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation has no effect and can be removed + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:45:9 + │ +45 │ x * 0; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation is always zero and can be replaced with '0' + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:46:9 + │ +46 │ 1 % x; + │ ^^^^^ + │ │ + │ This operation is always one and can be replaced with '1' + │ Because of this operand + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:50:9 + │ +50 │ x * 1; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation has no effect and can be removed + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:51:9 + │ +51 │ x * 0; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation is always zero and can be replaced with '0' + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:52:9 + │ +52 │ 1 % x; + │ ^^^^^ + │ │ + │ This operation is always one and can be replaced with '1' + │ Because of this operand + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:56:9 + │ +56 │ x * 1; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation has no effect and can be removed + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:57:9 + │ +57 │ x * 0; + │ ^^^^^ + │ │ │ + │ │ Because of this operand + │ This operation is always zero and can be replaced with '0' + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + +warning[Lint W01008]: math operation can be simplified + ┌─ tests/linter/true_positive_meaningless_math_operation.move:58:9 + │ +58 │ 1 % x; + │ ^^^^^ + │ │ + │ This operation is always one and can be replaced with '1' + │ Because of this operand + │ + = This warning can be suppressed with '#[allow(lint(unnecessary_math))]' applied to the 'module' or module member ('const', 'fun', or 'struct') + diff --git a/external-crates/move/crates/move-compiler/tests/linter/true_positive_meaningless_math_operation.move b/external-crates/move/crates/move-compiler/tests/linter/true_positive_meaningless_math_operation.move new file mode 100644 index 0000000000000..157cf274e08dc --- /dev/null +++ b/external-crates/move/crates/move-compiler/tests/linter/true_positive_meaningless_math_operation.move @@ -0,0 +1,60 @@ +module 0x42::M { + public fun unchanged(x: u64) { + x * 1; + 1 * x; + x / 1; + x + 0; + 0 + x; + x - 0; + x << 0; + x << 0; + } + + public fun always_zero(x: u64) { + x * 0; + 0 * x; + 0 / x; + 0 % x; + x % 1; + } + + public fun always_one(x: u64) { + 1 % x; + } + + public fun ast_fold(x: u64) { + let y = 1; + x * y; + x - (1 - 1); + } + + public fun t_u8(x: u8) { + x * 1; + x * 0; + 1 % x; + } + + public fun t_u16(x: u16) { + x * 1; + x * 0; + 1 % x; + } + + public fun t_u32(x: u32) { + x * 1; + x * 0; + 1 % x; + } + + public fun t_u128(x: u128) { + x * 1; + x * 0; + 1 % x; + } + + public fun t_u256(x: u256) { + x * 1; + x * 0; + 1 % x; + } +}