Fixes #921: top-level Miller-loop needs not to be serialisable
This is a bit tricky, but in a similar way where we allow functions to be returned by functions, this must also work for MillerLoopResult.
This commit is contained in:
parent
83c0566afb
commit
8c67be55ce
29
CHANGELOG.md
29
CHANGELOG.md
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- **aiken**: added export command that exporting of regular function definitons. @rvcas
|
||||||
- **aiken-lsp**: hover and goto definition support on list tail. @rvcas
|
- **aiken-lsp**: hover and goto definition support on list tail. @rvcas
|
||||||
- **aiken-lsp**: hover on prop test via expression. @rvcas
|
- **aiken-lsp**: hover on prop test via expression. @rvcas
|
||||||
- **aiken**: added export command that exporting of regular function definitons. @rvcas
|
|
||||||
- **aiken-lang**: a new way to emit logs that don't get erased. @micahkendall
|
- **aiken-lang**: a new way to emit logs that don't get erased. @micahkendall
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@ -14,14 +14,29 @@
|
||||||
- **aiken-lang**: formatter should not erase `pub` on validators. @rvcas
|
- **aiken-lang**: formatter should not erase `pub` on validators. @rvcas
|
||||||
- **aiken-lang**: error on using tuple index when a tuple is returned by a generic function. @rvcas
|
- **aiken-lang**: error on using tuple index when a tuple is returned by a generic function. @rvcas
|
||||||
- **aiken-lang**: fix a regression in the Type-checker introduced in v1.0.25-alpha regarding types comparison. See #917. @KtorZ
|
- **aiken-lang**: fix a regression in the Type-checker introduced in v1.0.25-alpha regarding types comparison. See #917. @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 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
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- **aiken-lang**: **MAJOR CHANGE** 2-tuples are now treated the same as 3+ tuples. To replace the representation of pairs at the uplc level, we now have a new Prelude type called Pair with 2 generic arguments. The main place you will see its usage is in the script context. For existing contracts you can continue to use 2-tuples, just note the offchain representation is an array of 2 items in CBOR. @KtorZ @Microproofs
|
|
||||||
- **aiken-lang**: Some more code gen cleanup. @Microproofs
|
> [!WARNING]
|
||||||
- **aiken-lang**: New optimization for wrapped builtins found in the stdlib. @Microproofs
|
>
|
||||||
|
> **BREAKING-CHANGE**
|
||||||
|
>
|
||||||
|
> 2-tuples `(a, b)` are now treated the same as 3+ tuples -- which directly impacts the way that Aiken now deserialise those, especially when nested inside a `List`.
|
||||||
|
>
|
||||||
|
> To deserialize into a list of 2-tuple (`List<(a, b)>`), one is now expected to provide a CBOR array of arrays (of 2 elements). Previously, this would require to provide a CBOR map! The downside of the latter is that CBOR serialization libraries do not necessarily preserve the order of keys in a map which could cause issues down the line, in particular with Aiken's dictionnaries.
|
||||||
|
>
|
||||||
|
>
|
||||||
|
> To recover the old behavior when desired, Aiken introduces a new type `Pair<a, b>` to the language. So any existing program can be migrated by switching any occurences of `(a, b)` to `Pair<a, b>`.
|
||||||
|
>
|
||||||
|
> However, it is often preferable to use 2-tuples where possible. The main place you will see usage of `Pair` is in the script context because its form is imposed by the ledger.
|
||||||
|
|
||||||
|
- **aiken-lang**: altered internal representation of 2-tuples to distinguish them from pairs. @KtorZ @Microproofs
|
||||||
|
- **aiken-lang**: some more code gen cleanup. @Microproofs
|
||||||
|
- **aiken-lang**: new optimization for wrapped builtins found in the stdlib. @Microproofs
|
||||||
|
|
||||||
|
|
||||||
## v1.0.26-alpha - 2024-03-25
|
## v1.0.26-alpha - 2024-03-25
|
||||||
|
|
|
@ -207,6 +207,53 @@ fn illegal_inhabitants_returned() {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn not_illegal_top_level_unserialisable() {
|
||||||
|
let source_code = r#"
|
||||||
|
fn foo() -> MillerLoopResult {
|
||||||
|
todo
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
assert!(check(parse(source_code)).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn illegal_unserialisable_in_generic_fn() {
|
||||||
|
let source_code = r#"
|
||||||
|
type Foo<a> {
|
||||||
|
foo: a
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Foo<fn(Int) -> Bool> {
|
||||||
|
todo
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
assert!(matches!(
|
||||||
|
check(parse(source_code)),
|
||||||
|
Err((_, Error::IllegalTypeInData { .. }))
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn illegal_unserialisable_in_generic_miller_loop() {
|
||||||
|
let source_code = r#"
|
||||||
|
type Foo<a> {
|
||||||
|
foo: a
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Foo<MillerLoopResult> {
|
||||||
|
todo
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
assert!(matches!(
|
||||||
|
check(parse(source_code)),
|
||||||
|
Err((_, Error::IllegalTypeInData { .. }))
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn mark_constructors_as_used_via_field_access() {
|
fn mark_constructors_as_used_via_field_access() {
|
||||||
let source_code = r#"
|
let source_code = r#"
|
||||||
|
|
|
@ -2563,7 +2563,7 @@ fn assert_assignment(expr: TypedExpr) -> Result<TypedExpr, Error> {
|
||||||
Ok(expr)
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ensure_serialisable(allow_fn: bool, t: Rc<Type>, location: Span) -> Result<(), Error> {
|
pub fn ensure_serialisable(is_top_level: bool, t: Rc<Type>, location: Span) -> Result<(), Error> {
|
||||||
match t.deref() {
|
match t.deref() {
|
||||||
Type::App {
|
Type::App {
|
||||||
args,
|
args,
|
||||||
|
@ -2573,7 +2573,7 @@ pub fn ensure_serialisable(allow_fn: bool, t: Rc<Type>, location: Span) -> Resul
|
||||||
contains_opaque: _,
|
contains_opaque: _,
|
||||||
alias: _,
|
alias: _,
|
||||||
} => {
|
} => {
|
||||||
if t.is_ml_result() {
|
if !is_top_level && t.is_ml_result() {
|
||||||
return Err(Error::IllegalTypeInData {
|
return Err(Error::IllegalTypeInData {
|
||||||
tipo: t.clone(),
|
tipo: t.clone(),
|
||||||
location,
|
location,
|
||||||
|
@ -2601,7 +2601,7 @@ pub fn ensure_serialisable(allow_fn: bool, t: Rc<Type>, location: Span) -> Resul
|
||||||
ret,
|
ret,
|
||||||
alias: _,
|
alias: _,
|
||||||
} => {
|
} => {
|
||||||
if !allow_fn {
|
if !is_top_level {
|
||||||
return Err(Error::IllegalTypeInData {
|
return Err(Error::IllegalTypeInData {
|
||||||
tipo: t.clone(),
|
tipo: t.clone(),
|
||||||
location,
|
location,
|
||||||
|
@ -2609,21 +2609,22 @@ pub fn ensure_serialisable(allow_fn: bool, t: Rc<Type>, location: Span) -> Resul
|
||||||
}
|
}
|
||||||
|
|
||||||
args.iter()
|
args.iter()
|
||||||
.map(|e| ensure_serialisable(allow_fn, e.clone(), location))
|
.map(|e| ensure_serialisable(true, e.clone(), location))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
ensure_serialisable(allow_fn, ret.clone(), location)
|
ensure_serialisable(true, ret.clone(), location)
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Var { tipo, alias } => match tipo.borrow().deref() {
|
Type::Var { tipo, alias } => match tipo.borrow().deref() {
|
||||||
TypeVar::Unbound { .. } => Ok(()),
|
TypeVar::Unbound { .. } => Ok(()),
|
||||||
TypeVar::Generic { .. } => Ok(()),
|
TypeVar::Generic { .. } => Ok(()),
|
||||||
TypeVar::Link { tipo } => ensure_serialisable(
|
TypeVar::Link { tipo } => ensure_serialisable(
|
||||||
allow_fn,
|
is_top_level,
|
||||||
Type::with_alias(tipo.clone(), alias.clone()),
|
Type::with_alias(tipo.clone(), alias.clone()),
|
||||||
location,
|
location,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
Type::Pair { fst, snd, .. } => {
|
Type::Pair { fst, snd, .. } => {
|
||||||
ensure_serialisable(false, fst.clone(), location)?;
|
ensure_serialisable(false, fst.clone(), location)?;
|
||||||
ensure_serialisable(false, snd.clone(), location)
|
ensure_serialisable(false, snd.clone(), location)
|
||||||
|
|
Loading…
Reference in New Issue