Check for data-type serialisability after generic instantiation
Fixes #939.
This commit is contained in:
parent
26ef25ba8d
commit
81219cfbdd
|
@ -17,7 +17,9 @@
|
||||||
- **aiken-lang**: fix incongruous generics after type-checking which caused [] to be treated as a list in cases where it needed to be an empty map primitive. See #922. @KtorZ
|
- **aiken-lang**: fix incongruous generics after type-checking which caused [] to be treated as a list in cases where it needed to be an empty map primitive. See #922. @KtorZ
|
||||||
- **aiken-lang**: fix for generic constrs being used as functions causing type mismatch errors. @Microproofs
|
- **aiken-lang**: fix for generic constrs being used as functions causing type mismatch errors. @Microproofs
|
||||||
- **aiken-lang**: fix for error occuring when a field holds Data that is not a constr type when compiler traces are on. @Microproofs
|
- **aiken-lang**: fix for error occuring when a field holds Data that is not a constr type when compiler traces are on. @Microproofs
|
||||||
- **aiken-lang**: fix compiler wrongly requiring MillerLoopResult to be 'serialisable' when manipulated as a top-level value. @KtorZ
|
- **aiken-lang**: fix compiler wrongly requiring MillerLoopResult to be 'serialisable' when manipulated as a top-level value. See #921. @KtorZ
|
||||||
|
- **aiken-lang**: fix type-checker oversight regarding serialisation of generics. See #939. @KtorZ
|
||||||
|
- **aiken-lang**: fix type-checker not raising error when comparing non-serialisable types. See #940. @KtorZ
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -225,6 +225,26 @@ fn illegal_inhabitants_returned() {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn illegal_generic_instantiation() {
|
||||||
|
let source_code = r#"
|
||||||
|
type Rec<t> {
|
||||||
|
get_t: t,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn use_dict(dict: Rec<fn(Bool) -> Bool>, b: Bool) -> Bool {
|
||||||
|
let f = dict.get_t
|
||||||
|
f(b)
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
assert!(matches!(
|
||||||
|
check_validator(parse(source_code)),
|
||||||
|
Err((_, Error::IllegalTypeInData { .. }))
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn not_illegal_top_level_unserialisable() {
|
fn not_illegal_top_level_unserialisable() {
|
||||||
let source_code = r#"
|
let source_code = r#"
|
||||||
|
@ -267,7 +287,7 @@ fn illegal_unserialisable_in_generic_miller_loop() {
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
check(parse(source_code)),
|
dbg!(check(parse(source_code))),
|
||||||
Err((_, Error::IllegalTypeInData { .. }))
|
Err((_, Error::IllegalTypeInData { .. }))
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -744,7 +744,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let spread = self.infer(*spread.base)?;
|
let spread = self.infer(*spread.base)?;
|
||||||
let return_type = self.instantiate(ret.clone(), &mut HashMap::new());
|
let return_type = self.instantiate(ret.clone(), &mut HashMap::new(), location)?;
|
||||||
|
|
||||||
// Check that the spread variable unifies with the return type of the constructor
|
// Check that the spread variable unifies with the return type of the constructor
|
||||||
self.unify(return_type, spread.tipo(), spread.location(), false)?;
|
self.unify(return_type, spread.tipo(), spread.location(), false)?;
|
||||||
|
@ -903,7 +903,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
(module.name.clone(), constructor.clone())
|
(module.name.clone(), constructor.clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
let tipo = self.instantiate(constructor.tipo, &mut HashMap::new());
|
let tipo = self.instantiate(constructor.tipo, &mut HashMap::new(), select_location)?;
|
||||||
|
|
||||||
let constructor = match &constructor.variant {
|
let constructor = match &constructor.variant {
|
||||||
variant @ ValueConstructorVariant::ModuleFn { name, module, .. } => {
|
variant @ ValueConstructorVariant::ModuleFn { name, module, .. } => {
|
||||||
|
@ -1001,9 +1001,10 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
|
|
||||||
let mut type_vars = HashMap::new();
|
let mut type_vars = HashMap::new();
|
||||||
|
|
||||||
let accessor_record_type = self.instantiate(accessor_record_type, &mut type_vars);
|
let accessor_record_type =
|
||||||
|
self.instantiate(accessor_record_type, &mut type_vars, record.location())?;
|
||||||
|
|
||||||
let tipo = self.instantiate(tipo, &mut type_vars);
|
let tipo = self.instantiate(tipo, &mut type_vars, record.location())?;
|
||||||
|
|
||||||
self.unify(
|
self.unify(
|
||||||
accessor_record_type,
|
accessor_record_type,
|
||||||
|
@ -1078,7 +1079,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
let ann_typ = if let Some(ann) = annotation {
|
let ann_typ = if let Some(ann) = annotation {
|
||||||
let ann_typ = self
|
let ann_typ = self
|
||||||
.type_from_annotation(ann)
|
.type_from_annotation(ann)
|
||||||
.map(|t| self.instantiate(t, &mut HashMap::new()))?;
|
.map(|t| self.instantiate(t, &mut HashMap::new(), location))??;
|
||||||
|
|
||||||
self.unify(
|
self.unify(
|
||||||
ann_typ.clone(),
|
ann_typ.clone(),
|
||||||
|
@ -2401,7 +2402,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
} = constructor;
|
} = constructor;
|
||||||
|
|
||||||
// Instantiate generic variables into unbound variables for this usage
|
// Instantiate generic variables into unbound variables for this usage
|
||||||
let tipo = self.instantiate(tipo, &mut HashMap::new());
|
let tipo = self.instantiate(tipo, &mut HashMap::new(), *location)?;
|
||||||
|
|
||||||
Ok(ValueConstructor {
|
Ok(ValueConstructor {
|
||||||
public,
|
public,
|
||||||
|
@ -2480,8 +2481,15 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn instantiate(&mut self, t: Rc<Type>, ids: &mut HashMap<u64, Rc<Type>>) -> Rc<Type> {
|
fn instantiate(
|
||||||
self.environment.instantiate(t, ids, &self.hydrator)
|
&mut self,
|
||||||
|
t: Rc<Type>,
|
||||||
|
ids: &mut HashMap<u64, Rc<Type>>,
|
||||||
|
location: Span,
|
||||||
|
) -> Result<Rc<Type>, Error> {
|
||||||
|
let result = self.environment.instantiate(t, ids, &self.hydrator);
|
||||||
|
ensure_serialisable(true, result.clone(), location)?;
|
||||||
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_unbound_var(&mut self) -> Rc<Type> {
|
pub fn new_unbound_var(&mut self) -> Rc<Type> {
|
||||||
|
|
Loading…
Reference in New Issue