parent
9533903acc
commit
5737556efc
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- **aiken-lang**: Fix compiler crash on trace + expect as last expression of a clause. See #1029. @KtorZ
|
||||||
- **uplc**: Fix (again :grimacing:) cost-models for PlutusV1 & PlutusV2. @MicroProofs
|
- **uplc**: Fix (again :grimacing:) cost-models for PlutusV1 & PlutusV2. @MicroProofs
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
|
@ -203,6 +203,28 @@ impl<T> From<Vec1Ref<T>> for Vec1<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypedExpr {
|
impl TypedExpr {
|
||||||
|
pub fn and_then(self, next: Self) -> Self {
|
||||||
|
if let TypedExpr::Trace {
|
||||||
|
tipo,
|
||||||
|
location,
|
||||||
|
then,
|
||||||
|
text,
|
||||||
|
} = self
|
||||||
|
{
|
||||||
|
return TypedExpr::Trace {
|
||||||
|
tipo,
|
||||||
|
location,
|
||||||
|
then: Box::new(then.and_then(next)),
|
||||||
|
text,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
TypedExpr::Sequence {
|
||||||
|
location: self.location(),
|
||||||
|
expressions: vec![self, next],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn sequence(exprs: &[TypedExpr]) -> Self {
|
pub fn sequence(exprs: &[TypedExpr]) -> Self {
|
||||||
TypedExpr::Sequence {
|
TypedExpr::Sequence {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
|
|
|
@ -3295,3 +3295,50 @@ fn softcasting_unused_let_binding() {
|
||||||
let (warnings, _) = result.unwrap();
|
let (warnings, _) = result.unwrap();
|
||||||
assert!(warnings.is_empty(), "should not contain any warnings");
|
assert!(warnings.is_empty(), "should not contain any warnings");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dangling_trace_let_standalone() {
|
||||||
|
let source_code = r#"
|
||||||
|
test foo() {
|
||||||
|
trace @"foo"
|
||||||
|
let True = True
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
assert!(matches!(
|
||||||
|
check_validator(parse(source_code)),
|
||||||
|
Err((_, Error::LastExpressionIsAssignment { .. }))
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dangling_trace_let_in_sequence() {
|
||||||
|
let source_code = r#"
|
||||||
|
test foo() {
|
||||||
|
let predicate = True
|
||||||
|
trace @"foo"
|
||||||
|
let result = predicate
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
assert!(matches!(
|
||||||
|
check_validator(parse(source_code)),
|
||||||
|
Err((_, Error::LastExpressionIsAssignment { .. }))
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dangling_trace_let_in_trace() {
|
||||||
|
let source_code = r#"
|
||||||
|
test foo() {
|
||||||
|
trace @"foo"
|
||||||
|
trace @"bar"
|
||||||
|
let result = True
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
assert!(matches!(
|
||||||
|
check_validator(parse(source_code)),
|
||||||
|
Err((_, Error::LastExpressionIsAssignment { .. }))
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
|
@ -1565,10 +1565,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
let then = if let Some(filler) =
|
let then = if let Some(filler) =
|
||||||
recover_from_no_assignment(assert_no_assignment(&then), then.location())?
|
recover_from_no_assignment(assert_no_assignment(&then), then.location())?
|
||||||
{
|
{
|
||||||
TypedExpr::Sequence {
|
scope.infer(then)?.and_then(filler)
|
||||||
location,
|
|
||||||
expressions: vec![scope.infer(then)?, filler],
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
scope.infer(then)?
|
scope.infer(then)?
|
||||||
};
|
};
|
||||||
|
@ -1638,10 +1635,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
let typed_final_else = if let Some(filler) =
|
let typed_final_else = if let Some(filler) =
|
||||||
recover_from_no_assignment(assert_no_assignment(&final_else), final_else.location())?
|
recover_from_no_assignment(assert_no_assignment(&final_else), final_else.location())?
|
||||||
{
|
{
|
||||||
TypedExpr::Sequence {
|
self.infer(final_else)?.and_then(filler)
|
||||||
location: final_else.location(),
|
|
||||||
expressions: vec![self.infer(final_else)?, filler],
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.infer(final_else)?
|
self.infer(final_else)?
|
||||||
};
|
};
|
||||||
|
@ -1696,10 +1690,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
assert_no_assignment(&branch.body),
|
assert_no_assignment(&branch.body),
|
||||||
branch.body.location(),
|
branch.body.location(),
|
||||||
)? {
|
)? {
|
||||||
TypedExpr::Sequence {
|
typer.infer(branch.body.clone())?.and_then(filler)
|
||||||
location: branch.body.location(),
|
|
||||||
expressions: vec![typer.infer(branch.body.clone())?, filler],
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
typer.infer(branch.body.clone())?
|
typer.infer(branch.body.clone())?
|
||||||
};
|
};
|
||||||
|
@ -1720,10 +1711,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
assert_no_assignment(&branch.body),
|
assert_no_assignment(&branch.body),
|
||||||
branch.body.location(),
|
branch.body.location(),
|
||||||
)? {
|
)? {
|
||||||
TypedExpr::Sequence {
|
self.infer(branch.body.clone())?.and_then(filler)
|
||||||
location: branch.body.location(),
|
|
||||||
expressions: vec![self.infer(branch.body.clone())?, filler],
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.infer(branch.body.clone())?
|
self.infer(branch.body.clone())?
|
||||||
};
|
};
|
||||||
|
@ -1815,10 +1803,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
body_infer.map_err(|e| e.with_unify_error_rigid_names(&body_rigid_names));
|
body_infer.map_err(|e| e.with_unify_error_rigid_names(&body_rigid_names));
|
||||||
|
|
||||||
let body = if let Some(filler) = recover_from_no_assignment(no_assignment, location)? {
|
let body = if let Some(filler) = recover_from_no_assignment(no_assignment, location)? {
|
||||||
TypedExpr::Sequence {
|
inferred_body?.and_then(filler)
|
||||||
location,
|
|
||||||
expressions: vec![inferred_body?, filler],
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
inferred_body?
|
inferred_body?
|
||||||
};
|
};
|
||||||
|
@ -2206,8 +2191,12 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
if let Some(filler) =
|
if let Some(filler) =
|
||||||
recover_from_no_assignment(no_assignment, typed_expression.location())?
|
recover_from_no_assignment(no_assignment, typed_expression.location())?
|
||||||
{
|
{
|
||||||
expressions.push(typed_expression);
|
match typed_expression.and_then(filler) {
|
||||||
expressions.push(filler);
|
TypedExpr::Sequence {
|
||||||
|
expressions: seq, ..
|
||||||
|
} => expressions.extend(seq),
|
||||||
|
trace => expressions.push(trace),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
expressions.push(typed_expression);
|
expressions.push(typed_expression);
|
||||||
}
|
}
|
||||||
|
@ -2391,6 +2380,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
.collect::<Result<Vec<_>, Error>>()?;
|
.collect::<Result<Vec<_>, Error>>()?;
|
||||||
|
|
||||||
let then = self.infer(then)?;
|
let then = self.infer(then)?;
|
||||||
|
|
||||||
let tipo = then.tipo();
|
let tipo = then.tipo();
|
||||||
|
|
||||||
if let TraceKind::Todo = kind {
|
if let TraceKind::Todo = kind {
|
||||||
|
|
|
@ -6477,3 +6477,63 @@ fn hard_soft_cast() {
|
||||||
|
|
||||||
assert_uplc(src, program, false, false);
|
assert_uplc(src, program, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dangling_trace_expect_standalone() {
|
||||||
|
let src = r#"
|
||||||
|
test foo() {
|
||||||
|
trace @"foo"
|
||||||
|
expect True
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let program = Term::bool(true)
|
||||||
|
.delayed_if_then_else(
|
||||||
|
Term::unit(),
|
||||||
|
Term::Error.delayed_trace(Term::string("expect True")),
|
||||||
|
)
|
||||||
|
.delayed_trace(Term::string("foo"));
|
||||||
|
|
||||||
|
assert_uplc(src, program, false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dangling_trace_expect_in_sequence() {
|
||||||
|
let src = r#"
|
||||||
|
test foo() {
|
||||||
|
let predicate = True
|
||||||
|
trace @"foo"
|
||||||
|
expect predicate
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let program = Term::bool(true)
|
||||||
|
.delayed_if_then_else(
|
||||||
|
Term::unit(),
|
||||||
|
Term::Error.delayed_trace(Term::string("expect predicate")),
|
||||||
|
)
|
||||||
|
.delayed_trace(Term::string("foo"));
|
||||||
|
|
||||||
|
assert_uplc(src, program, false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dangling_trace_expect_in_trace() {
|
||||||
|
let src = r#"
|
||||||
|
test foo() {
|
||||||
|
trace @"foo"
|
||||||
|
trace @"bar"
|
||||||
|
expect True
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let program = Term::bool(true)
|
||||||
|
.delayed_if_then_else(
|
||||||
|
Term::unit(),
|
||||||
|
Term::Error.delayed_trace(Term::string("expect True")),
|
||||||
|
)
|
||||||
|
.delayed_trace(Term::string("bar"))
|
||||||
|
.delayed_trace(Term::string("foo"));
|
||||||
|
|
||||||
|
assert_uplc(src, program, false, true)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue