diff --git a/crates/aiken-lang/src/parser/expr/if_else.rs b/crates/aiken-lang/src/parser/expr/if_else.rs index b15d4f8f..4855bc78 100644 --- a/crates/aiken-lang/src/parser/expr/if_else.rs +++ b/crates/aiken-lang/src/parser/expr/if_else.rs @@ -1,12 +1,10 @@ -use chumsky::prelude::*; - +use super::block; use crate::{ ast, expr::UntypedExpr, parser::{annotation, error::ParseError, pattern, token::Token}, }; - -use super::block; +use chumsky::prelude::*; pub fn parser<'a>( sequence: Recursive<'a, Token, UntypedExpr, ParseError>, @@ -133,4 +131,30 @@ mod tests { "# ); } + + #[test] + fn if_soft_cast_discard_assign() { + assert_expr!( + r#" + if foo() is Foo { + todo + } else { + todo + } + "# + ); + } + + #[test] + fn if_soft_cast_not_var_condition() { + assert_expr!( + r#" + if foo() is Foo { a }: Foo { + todo + } else { + todo + } + "# + ); + } } diff --git a/crates/aiken-lang/src/parser/expr/snapshots/if_soft_cast_discard_assign.snap b/crates/aiken-lang/src/parser/expr/snapshots/if_soft_cast_discard_assign.snap new file mode 100644 index 00000000..aab73ee8 --- /dev/null +++ b/crates/aiken-lang/src/parser/expr/snapshots/if_soft_cast_discard_assign.snap @@ -0,0 +1,59 @@ +--- +source: crates/aiken-lang/src/parser/expr/if_else.rs +description: "Code:\n\nif foo() is Foo {\n todo\n} else {\n todo\n}\n" +--- +If { + location: 0..42, + branches: [ + IfBranch { + condition: Call { + arguments: [], + fun: Var { + location: 3..6, + name: "foo", + }, + location: 3..8, + }, + body: Trace { + kind: Todo, + location: 20..24, + then: ErrorTerm { + location: 20..24, + }, + text: String { + location: 20..24, + value: "aiken::todo", + }, + }, + is: Some( + AssignmentPattern { + pattern: Discard { + name: "_", + location: 12..15, + }, + annotation: Some( + Constructor { + location: 12..15, + module: None, + name: "Foo", + arguments: [], + }, + ), + location: 12..15, + }, + ), + location: 3..26, + }, + ], + final_else: Trace { + kind: Todo, + location: 36..40, + then: ErrorTerm { + location: 36..40, + }, + text: String { + location: 36..40, + value: "aiken::todo", + }, + }, +} diff --git a/crates/aiken-lang/src/parser/expr/snapshots/if_soft_cast_not_var_condition.snap b/crates/aiken-lang/src/parser/expr/snapshots/if_soft_cast_not_var_condition.snap new file mode 100644 index 00000000..e8fd4f35 --- /dev/null +++ b/crates/aiken-lang/src/parser/expr/snapshots/if_soft_cast_not_var_condition.snap @@ -0,0 +1,76 @@ +--- +source: crates/aiken-lang/src/parser/expr/if_else.rs +description: "Code:\n\nif foo() is Foo { a }: Foo {\n todo\n} else {\n todo\n}\n" +--- +If { + location: 0..53, + branches: [ + IfBranch { + condition: Call { + arguments: [], + fun: Var { + location: 3..6, + name: "foo", + }, + location: 3..8, + }, + body: Trace { + kind: Todo, + location: 31..35, + then: ErrorTerm { + location: 31..35, + }, + text: String { + location: 31..35, + value: "aiken::todo", + }, + }, + is: Some( + AssignmentPattern { + pattern: Constructor { + is_record: true, + location: 12..21, + name: "Foo", + arguments: [ + CallArg { + label: Some( + "a", + ), + location: 18..19, + value: Var { + location: 18..19, + name: "a", + }, + }, + ], + module: None, + constructor: (), + spread_location: None, + tipo: (), + }, + annotation: Some( + Constructor { + location: 23..26, + module: None, + name: "Foo", + arguments: [], + }, + ), + location: 12..26, + }, + ), + location: 3..37, + }, + ], + final_else: Trace { + kind: Todo, + location: 47..51, + then: ErrorTerm { + location: 47..51, + }, + text: String { + location: 47..51, + value: "aiken::todo", + }, + }, +} diff --git a/crates/aiken-lang/src/tests/check.rs b/crates/aiken-lang/src/tests/check.rs index 99b968e4..3f4f77b4 100644 --- a/crates/aiken-lang/src/tests/check.rs +++ b/crates/aiken-lang/src/tests/check.rs @@ -2653,6 +2653,52 @@ fn if_soft_cast_no_scope_leak() { )) } +#[test] +fn if_soft_cast_no_scope_leak_2() { + let source_code = r#" + pub type Foo { + a: Int + } + + pub fn foo(foo: Data) -> Int { + if foo is Foo { a }: Foo { + a + } else { + a + } + } + "#; + + assert!(matches!( + check_validator(parse(source_code)), + Err((_, Error::UnknownVariable { name, .. })) if name == "a" + )) +} + +#[test] +fn if_soft_cast_unused_pattern() { + let source_code = r#" + pub type Foo { + a: Int + } + + pub fn foo(foo: Data) -> Int { + if foo is Foo { a }: Foo { + 1 + } else { + 0 + } + } + "#; + + let (warnings, _ast) = dbg!(check(parse(source_code))).unwrap(); + + assert!(matches!( + warnings[0], + Warning::UnusedVariable { ref name, .. } if name == "a" + )) +} + #[test] fn if_soft_cast_not_data() { let source_code = r#"