diff --git a/tooling/ast_fuzzer/src/program/func.rs b/tooling/ast_fuzzer/src/program/func.rs index 23b759f147d..71e138a3abf 100644 --- a/tooling/ast_fuzzer/src/program/func.rs +++ b/tooling/ast_fuzzer/src/program/func.rs @@ -715,12 +715,17 @@ impl<'a> FunctionContext<'a> { typ: &Type, max_depth: usize, ) -> arbitrary::Result> { + // Negation can cause overflow: for example `-1*i8::MIN` does not fit into `i8`, because `i8` is [-128, 127]. + let avoid_overflow = self.ctx.config.avoid_overflow || self.in_no_dynamic; + let mut make_unary = |op| { self.gen_expr(u, typ, max_depth.saturating_sub(1), Flags::NESTED) .map(|(rhs, is_dyn)| Some((expr::unary(op, rhs, typ.clone()), is_dyn))) }; - if types::is_numeric(typ) { - // Assume we already checked with `can_unary_return` that it's signed. + + if matches!(typ, Type::Field) + || matches!(typ, Type::Integer(Signedness::Signed, _)) && !avoid_overflow + { make_unary(UnaryOp::Minus) } else if types::is_bool(typ) { make_unary(UnaryOp::Not)