fix: only allow casting on top level Data

This commit is contained in:
rvcas 2024-03-21 11:53:49 -04:00 committed by Lucas
parent c20ff6b160
commit ee280bc309
2 changed files with 45 additions and 7 deletions

View File

@ -1847,6 +1847,44 @@ fn allow_expect_into_type_from_data() {
assert!(check(parse(source_code)).is_ok()) assert!(check(parse(source_code)).is_ok())
} }
#[test]
fn forbid_partial_down_casting() {
let source_code = r#"
type Foo {
x: Int
}
fn bar(n: List<Foo>) {
expect a: List<Data> = n
a
}
"#;
assert!(matches!(
dbg!(check(parse(source_code))),
Err((_, Error::CouldNotUnify { .. }))
))
}
#[test]
fn forbid_partial_up_casting() {
let source_code = r#"
type Foo {
x: Int
}
fn bar(n: List<Data>) {
expect a: List<Foo> = n
a
}
"#;
assert!(matches!(
dbg!(check(parse(source_code))),
Err((_, Error::CouldNotUnify { .. }))
))
}
#[test] #[test]
fn allow_expect_into_type_from_data_2() { fn allow_expect_into_type_from_data_2() {
let source_code = r#" let source_code = r#"

View File

@ -1431,7 +1431,7 @@ impl<'a> Environment<'a> {
lhs, lhs,
Type::with_alias(tipo.clone(), alias.clone()), Type::with_alias(tipo.clone(), alias.clone()),
location, location,
allow_cast, false,
); );
} }
} }
@ -1470,7 +1470,7 @@ impl<'a> Environment<'a> {
Ok(()) Ok(())
} }
Action::Unify(t) => self.unify(t, rhs, location, allow_cast), Action::Unify(t) => self.unify(t, rhs, location, false),
Action::CouldNotUnify => Err(Error::CouldNotUnify { Action::CouldNotUnify => Err(Error::CouldNotUnify {
location, location,
@ -1484,7 +1484,7 @@ impl<'a> Environment<'a> {
if let Type::Var { .. } = rhs.deref() { if let Type::Var { .. } = rhs.deref() {
return self return self
.unify(rhs, lhs, location, allow_cast) .unify(rhs, lhs, location, false)
.map_err(|e| e.flip_unify()); .map_err(|e| e.flip_unify());
} }
@ -1511,7 +1511,7 @@ impl<'a> Environment<'a> {
unify_enclosed_type( unify_enclosed_type(
lhs.clone(), lhs.clone(),
rhs.clone(), rhs.clone(),
self.unify(a.clone(), b.clone(), location, allow_cast), self.unify(a.clone(), b.clone(), location, false),
)?; )?;
} }
Ok(()) Ok(())
@ -1531,7 +1531,7 @@ impl<'a> Environment<'a> {
unify_enclosed_type( unify_enclosed_type(
lhs.clone(), lhs.clone(),
rhs.clone(), rhs.clone(),
self.unify(a.clone(), b.clone(), location, allow_cast), self.unify(a.clone(), b.clone(), location, false),
)?; )?;
} }
Ok(()) Ok(())
@ -1550,7 +1550,7 @@ impl<'a> Environment<'a> {
}, },
) if args1.len() == args2.len() => { ) if args1.len() == args2.len() => {
for (a, b) in args1.iter().zip(args2) { for (a, b) in args1.iter().zip(args2) {
self.unify(a.clone(), b.clone(), location, allow_cast) self.unify(a.clone(), b.clone(), location, false)
.map_err(|_| Error::CouldNotUnify { .map_err(|_| Error::CouldNotUnify {
location, location,
expected: lhs.clone(), expected: lhs.clone(),
@ -1559,7 +1559,7 @@ impl<'a> Environment<'a> {
rigid_type_names: HashMap::new(), rigid_type_names: HashMap::new(),
})?; })?;
} }
self.unify(retrn1.clone(), retrn2.clone(), location, allow_cast) self.unify(retrn1.clone(), retrn2.clone(), location, false)
.map_err(|_| Error::CouldNotUnify { .map_err(|_| Error::CouldNotUnify {
location, location,
expected: lhs.clone(), expected: lhs.clone(),