fix: add a new assignment kind instead of using a boolean
This commit is contained in:
parent
f1cfc84e67
commit
5bdea11cc1
|
@ -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(),
|
||||
|
|
|
@ -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",
|
||||
};
|
||||
|
|
|
@ -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 { .. }))
|
||||
}
|
||||
|
|
|
@ -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() =>
|
||||
|
|
Loading…
Reference in New Issue