fix: add a new assignment kind instead of using a boolean

This commit is contained in:
rvcas 2024-06-25 18:35:42 -04:00 committed by Lucas
parent f1cfc84e67
commit 5bdea11cc1
4 changed files with 25 additions and 12 deletions

View File

@ -1679,6 +1679,7 @@ pub type TypedAssignmentKind = AssignmentKind<()>;
#[derive(Debug, Clone, PartialEq, Eq, Copy, serde::Serialize, serde::Deserialize)]
pub enum AssignmentKind<T> {
Is,
Let { backpassing: T },
Expect { backpassing: T },
}
@ -1686,6 +1687,7 @@ pub enum AssignmentKind<T> {
impl From<UntypedAssignmentKind> 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<T> AssignmentKind<T> {
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<T> AssignmentKind<T> {
impl AssignmentKind<bool> {
pub fn is_backpassing(&self) -> bool {
match self {
Self::Is => unreachable!(),
Self::Let { backpassing } | Self::Expect { backpassing } => *backpassing,
}
}
@ -1724,6 +1732,10 @@ impl<T: Default> AssignmentKind<T> {
}
}
pub fn is() -> Self {
AssignmentKind::Is
}
pub fn expect() -> Self {
AssignmentKind::Expect {
backpassing: Default::default(),

View File

@ -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",
};

View File

@ -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 { .. }))
}

View File

@ -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<Annotation>,
location: Span,
check_exhaustiveness: bool,
) -> Result<TypedExpr, Error> {
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() =>