From 26ef25ba8da4d8f41600996920bfde0ca09ec8b9 Mon Sep 17 00:00:00 2001 From: KtorZ Date: Tue, 14 May 2024 10:45:15 +0200 Subject: [PATCH] Make comparison of non-serialisable types illegal. Fixes #940. --- crates/aiken-lang/src/tests/check.rs | 18 ++++++++++++++++++ crates/aiken-lang/src/tipo/error.rs | 16 +++++++++++++++- crates/aiken-lang/src/tipo/expr.rs | 5 +++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/crates/aiken-lang/src/tests/check.rs b/crates/aiken-lang/src/tests/check.rs index aae85d07..274fabcd 100644 --- a/crates/aiken-lang/src/tests/check.rs +++ b/crates/aiken-lang/src/tests/check.rs @@ -185,6 +185,24 @@ fn illegal_inhabitants_nested() { )) } +#[test] +fn illegal_function_comparison() { + let source_code = r#" + fn not(x: Bool) -> Bool { + todo + } + + fn foo() -> Bool { + not == not + } + "#; + + assert!(matches!( + dbg!(check_validator(parse(source_code))), + Err((_, Error::IllegalComparison { .. })) + )) +} + #[test] fn illegal_inhabitants_returned() { let source_code = r#" diff --git a/crates/aiken-lang/src/tipo/error.rs b/crates/aiken-lang/src/tipo/error.rs index a056385b..58639924 100644 --- a/crates/aiken-lang/src/tipo/error.rs +++ b/crates/aiken-lang/src/tipo/error.rs @@ -292,11 +292,24 @@ You can use '{discard}' and numbers to distinguish between similar names. Fuzzer = "Fuzzer".if_supports_color(Stdout, |s| s.cyan()), ))] IllegalTypeInData { - #[label] + #[label("non-serialisable inhabitants")] location: Span, tipo: Rc, }, + #[error("I noticed an inadequate use of '=='.\n")] + #[diagnostic(code("illegal::comparison"))] + #[diagnostic(help( + r#"I can compare any value that is serializable to {Data}. This excludes values that are functions, {Fuzzer} or {MillerLoopResult} for example."#, + Data = "Data".if_supports_color(Stdout, |s| s.cyan()), + Fuzzer = "Fuzzer".if_supports_color(Stdout, |s| s.cyan()), + MillerLoopResult = "MillerLoopResult".if_supports_color(Stdout, |s| s.cyan()), + ))] + IllegalComparison { + #[label("non-serialisable operands")] + location: Span, + }, + #[error("I found a discarded expression not bound to a variable.\n")] #[diagnostic(code("implicit_discard"))] #[diagnostic(help( @@ -1033,6 +1046,7 @@ impl ExtraData for Error { | Error::ExtraVarInAlternativePattern { .. } | Error::FunctionTypeInData { .. } | Error::IllegalTypeInData { .. } + | Error::IllegalComparison { .. } | Error::ImplicitlyDiscardedExpression { .. } | Error::IncorrectFieldsArity { .. } | Error::IncorrectFunctionCallArity { .. } diff --git a/crates/aiken-lang/src/tipo/expr.rs b/crates/aiken-lang/src/tipo/expr.rs index 05f27aa7..6bab1702 100644 --- a/crates/aiken-lang/src/tipo/expr.rs +++ b/crates/aiken-lang/src/tipo/expr.rs @@ -624,6 +624,11 @@ impl<'a, 'b> ExprTyper<'a, 'b> { self.unify(left.tipo(), right.tipo(), right.location(), false)?; + for tipo in &[left.tipo(), right.tipo()] { + ensure_serialisable(false, tipo.clone(), location) + .map_err(|_| Error::IllegalComparison { location })?; + } + return Ok(TypedExpr::BinOp { location, name,