Make comparison of non-serialisable types illegal.

Fixes #940.
This commit is contained in:
KtorZ 2024-05-14 10:45:15 +02:00
parent ff0407a245
commit 26ef25ba8d
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
3 changed files with 38 additions and 1 deletions

View File

@ -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#"

View File

@ -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<Type>,
},
#[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 { .. }

View File

@ -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,