From 5bdea11cc173717dd11dc154efe63702f4d85082 Mon Sep 17 00:00:00 2001 From: rvcas Date: Tue, 25 Jun 2024 18:35:42 -0400 Subject: [PATCH] fix: add a new assignment kind instead of using a boolean --- crates/aiken-lang/src/ast.rs | 12 ++++++++++++ crates/aiken-lang/src/format.rs | 1 + crates/aiken-lang/src/tests/check.rs | 4 ++-- crates/aiken-lang/src/tipo/expr.rs | 20 ++++++++++---------- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/crates/aiken-lang/src/ast.rs b/crates/aiken-lang/src/ast.rs index 9dded2404..20e7b373d 100644 --- a/crates/aiken-lang/src/ast.rs +++ b/crates/aiken-lang/src/ast.rs @@ -1679,6 +1679,7 @@ pub type TypedAssignmentKind = AssignmentKind<()>; #[derive(Debug, Clone, PartialEq, Eq, Copy, serde::Serialize, serde::Deserialize)] pub enum AssignmentKind { + Is, Let { backpassing: T }, Expect { backpassing: T }, } @@ -1686,6 +1687,7 @@ pub enum AssignmentKind { impl From for TypedAssignmentKind { fn from(kind: UntypedAssignmentKind) -> TypedAssignmentKind { match kind { + AssignmentKind::Is => AssignmentKind::Is, AssignmentKind::Let { .. } => AssignmentKind::Let { backpassing: () }, AssignmentKind::Expect { .. } => AssignmentKind::Expect { backpassing: () }, } @@ -1701,8 +1703,13 @@ impl AssignmentKind { matches!(self, AssignmentKind::Expect { .. }) } + pub fn if_is(&self) -> bool { + matches!(self, AssignmentKind::Is) + } + pub fn location_offset(&self) -> usize { match self { + AssignmentKind::Is => 2, AssignmentKind::Let { .. } => 3, AssignmentKind::Expect { .. } => 6, } @@ -1712,6 +1719,7 @@ impl AssignmentKind { impl AssignmentKind { pub fn is_backpassing(&self) -> bool { match self { + Self::Is => unreachable!(), Self::Let { backpassing } | Self::Expect { backpassing } => *backpassing, } } @@ -1724,6 +1732,10 @@ impl AssignmentKind { } } + pub fn is() -> Self { + AssignmentKind::Is + } + pub fn expect() -> Self { AssignmentKind::Expect { backpassing: Default::default(), diff --git a/crates/aiken-lang/src/format.rs b/crates/aiken-lang/src/format.rs index 33677aadc..4bcded89f 100644 --- a/crates/aiken-lang/src/format.rs +++ b/crates/aiken-lang/src/format.rs @@ -703,6 +703,7 @@ impl<'comments> Formatter<'comments> { kind: UntypedAssignmentKind, ) -> Document<'a> { let keyword = match kind { + AssignmentKind::Is => unreachable!(), AssignmentKind::Let { .. } => "let", AssignmentKind::Expect { .. } => "expect", }; diff --git a/crates/aiken-lang/src/tests/check.rs b/crates/aiken-lang/src/tests/check.rs index 3f4f77b4b..b3bb32f02 100644 --- a/crates/aiken-lang/src/tests/check.rs +++ b/crates/aiken-lang/src/tests/check.rs @@ -2691,7 +2691,7 @@ fn if_soft_cast_unused_pattern() { } "#; - let (warnings, _ast) = dbg!(check(parse(source_code))).unwrap(); + let (warnings, _ast) = check(parse(source_code)).unwrap(); assert!(matches!( warnings[0], @@ -2716,7 +2716,7 @@ fn if_soft_cast_not_data() { } "#; - let (warnings, _ast) = dbg!(check(parse(source_code))).unwrap(); + let (warnings, _ast) = check(parse(source_code)).unwrap(); assert!(matches!(warnings[0], Warning::UseWhenInstead { .. })) } diff --git a/crates/aiken-lang/src/tipo/expr.rs b/crates/aiken-lang/src/tipo/expr.rs index aeaa93279..cc5733c76 100644 --- a/crates/aiken-lang/src/tipo/expr.rs +++ b/crates/aiken-lang/src/tipo/expr.rs @@ -510,7 +510,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { location: _, } = patterns.into_vec().swap_remove(0); - self.infer_assignment(pattern, *value, kind, &annotation, location, true) + self.infer_assignment(pattern, *value, kind, &annotation, location) } UntypedExpr::Trace { @@ -1182,7 +1182,6 @@ impl<'a, 'b> ExprTyper<'a, 'b> { kind: UntypedAssignmentKind, annotation: &Option, location: Span, - check_exhaustiveness: bool, ) -> Result { let typed_value = self.infer(untyped_value.clone())?; let mut value_typ = typed_value.tipo(); @@ -1199,7 +1198,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { ann_typ.clone(), value_typ.clone(), typed_value.type_defining_location(), - (kind.is_let() && ann_typ.is_data()) || kind.is_expect(), + (kind.is_let() && ann_typ.is_data()) || kind.is_expect() || kind.if_is(), )?; value_typ = ann_typ.clone(); @@ -1240,11 +1239,13 @@ impl<'a, 'b> ExprTyper<'a, 'b> { // If `expect` is explicitly used, we still check exhaustiveness but instead of returning an // error we emit a warning which explains that using `expect` is unnecessary. match kind { - AssignmentKind::Let { .. } if check_exhaustiveness => self - .environment - .check_exhaustiveness(&[&pattern], location, true)?, + AssignmentKind::Is => (), + AssignmentKind::Let { .. } => { + self.environment + .check_exhaustiveness(&[&pattern], location, true)? + } - AssignmentKind::Expect { .. } if check_exhaustiveness => { + AssignmentKind::Expect { .. } => { let is_exaustive_pattern = self .environment .check_exhaustiveness(&[&pattern], location, false) @@ -1292,7 +1293,6 @@ impl<'a, 'b> ExprTyper<'a, 'b> { }); } } - _ => (), } Ok(TypedExpr::Assignment { @@ -1749,10 +1749,9 @@ impl<'a, 'b> ExprTyper<'a, 'b> { let TypedExpr::Assignment { value, pattern, .. } = typer.infer_assignment( pattern, branch.condition.clone(), - AssignmentKind::expect(), + AssignmentKind::is(), &annotation, location, - false, )? else { unreachable!() @@ -2104,6 +2103,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { .into(), // erase backpassing while preserving assignment kind. kind: match kind { + AssignmentKind::Is => unreachable!(), AssignmentKind::Let { .. } => AssignmentKind::let_(), AssignmentKind::Expect { .. } if pattern_is_var && annotation.is_none() =>