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)]
|
#[derive(Debug, Clone, PartialEq, Eq, Copy, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum AssignmentKind<T> {
|
pub enum AssignmentKind<T> {
|
||||||
|
Is,
|
||||||
Let { backpassing: T },
|
Let { backpassing: T },
|
||||||
Expect { backpassing: T },
|
Expect { backpassing: T },
|
||||||
}
|
}
|
||||||
|
@ -1686,6 +1687,7 @@ pub enum AssignmentKind<T> {
|
||||||
impl From<UntypedAssignmentKind> for TypedAssignmentKind {
|
impl From<UntypedAssignmentKind> for TypedAssignmentKind {
|
||||||
fn from(kind: UntypedAssignmentKind) -> TypedAssignmentKind {
|
fn from(kind: UntypedAssignmentKind) -> TypedAssignmentKind {
|
||||||
match kind {
|
match kind {
|
||||||
|
AssignmentKind::Is => AssignmentKind::Is,
|
||||||
AssignmentKind::Let { .. } => AssignmentKind::Let { backpassing: () },
|
AssignmentKind::Let { .. } => AssignmentKind::Let { backpassing: () },
|
||||||
AssignmentKind::Expect { .. } => AssignmentKind::Expect { backpassing: () },
|
AssignmentKind::Expect { .. } => AssignmentKind::Expect { backpassing: () },
|
||||||
}
|
}
|
||||||
|
@ -1701,8 +1703,13 @@ impl<T> AssignmentKind<T> {
|
||||||
matches!(self, AssignmentKind::Expect { .. })
|
matches!(self, AssignmentKind::Expect { .. })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn if_is(&self) -> bool {
|
||||||
|
matches!(self, AssignmentKind::Is)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn location_offset(&self) -> usize {
|
pub fn location_offset(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
|
AssignmentKind::Is => 2,
|
||||||
AssignmentKind::Let { .. } => 3,
|
AssignmentKind::Let { .. } => 3,
|
||||||
AssignmentKind::Expect { .. } => 6,
|
AssignmentKind::Expect { .. } => 6,
|
||||||
}
|
}
|
||||||
|
@ -1712,6 +1719,7 @@ impl<T> AssignmentKind<T> {
|
||||||
impl AssignmentKind<bool> {
|
impl AssignmentKind<bool> {
|
||||||
pub fn is_backpassing(&self) -> bool {
|
pub fn is_backpassing(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
|
Self::Is => unreachable!(),
|
||||||
Self::Let { backpassing } | Self::Expect { backpassing } => *backpassing,
|
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 {
|
pub fn expect() -> Self {
|
||||||
AssignmentKind::Expect {
|
AssignmentKind::Expect {
|
||||||
backpassing: Default::default(),
|
backpassing: Default::default(),
|
||||||
|
|
|
@ -703,6 +703,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
kind: UntypedAssignmentKind,
|
kind: UntypedAssignmentKind,
|
||||||
) -> Document<'a> {
|
) -> Document<'a> {
|
||||||
let keyword = match kind {
|
let keyword = match kind {
|
||||||
|
AssignmentKind::Is => unreachable!(),
|
||||||
AssignmentKind::Let { .. } => "let",
|
AssignmentKind::Let { .. } => "let",
|
||||||
AssignmentKind::Expect { .. } => "expect",
|
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!(
|
assert!(matches!(
|
||||||
warnings[0],
|
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 { .. }))
|
assert!(matches!(warnings[0], Warning::UseWhenInstead { .. }))
|
||||||
}
|
}
|
||||||
|
|
|
@ -510,7 +510,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
location: _,
|
location: _,
|
||||||
} = patterns.into_vec().swap_remove(0);
|
} = 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 {
|
UntypedExpr::Trace {
|
||||||
|
@ -1182,7 +1182,6 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
kind: UntypedAssignmentKind,
|
kind: UntypedAssignmentKind,
|
||||||
annotation: &Option<Annotation>,
|
annotation: &Option<Annotation>,
|
||||||
location: Span,
|
location: Span,
|
||||||
check_exhaustiveness: bool,
|
|
||||||
) -> Result<TypedExpr, Error> {
|
) -> Result<TypedExpr, Error> {
|
||||||
let typed_value = self.infer(untyped_value.clone())?;
|
let typed_value = self.infer(untyped_value.clone())?;
|
||||||
let mut value_typ = typed_value.tipo();
|
let mut value_typ = typed_value.tipo();
|
||||||
|
@ -1199,7 +1198,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
ann_typ.clone(),
|
ann_typ.clone(),
|
||||||
value_typ.clone(),
|
value_typ.clone(),
|
||||||
typed_value.type_defining_location(),
|
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();
|
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
|
// 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.
|
// error we emit a warning which explains that using `expect` is unnecessary.
|
||||||
match kind {
|
match kind {
|
||||||
AssignmentKind::Let { .. } if check_exhaustiveness => self
|
AssignmentKind::Is => (),
|
||||||
.environment
|
AssignmentKind::Let { .. } => {
|
||||||
.check_exhaustiveness(&[&pattern], location, true)?,
|
self.environment
|
||||||
|
.check_exhaustiveness(&[&pattern], location, true)?
|
||||||
|
}
|
||||||
|
|
||||||
AssignmentKind::Expect { .. } if check_exhaustiveness => {
|
AssignmentKind::Expect { .. } => {
|
||||||
let is_exaustive_pattern = self
|
let is_exaustive_pattern = self
|
||||||
.environment
|
.environment
|
||||||
.check_exhaustiveness(&[&pattern], location, false)
|
.check_exhaustiveness(&[&pattern], location, false)
|
||||||
|
@ -1292,7 +1293,6 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(TypedExpr::Assignment {
|
Ok(TypedExpr::Assignment {
|
||||||
|
@ -1749,10 +1749,9 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
let TypedExpr::Assignment { value, pattern, .. } = typer.infer_assignment(
|
let TypedExpr::Assignment { value, pattern, .. } = typer.infer_assignment(
|
||||||
pattern,
|
pattern,
|
||||||
branch.condition.clone(),
|
branch.condition.clone(),
|
||||||
AssignmentKind::expect(),
|
AssignmentKind::is(),
|
||||||
&annotation,
|
&annotation,
|
||||||
location,
|
location,
|
||||||
false,
|
|
||||||
)?
|
)?
|
||||||
else {
|
else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
@ -2104,6 +2103,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
.into(),
|
.into(),
|
||||||
// erase backpassing while preserving assignment kind.
|
// erase backpassing while preserving assignment kind.
|
||||||
kind: match kind {
|
kind: match kind {
|
||||||
|
AssignmentKind::Is => unreachable!(),
|
||||||
AssignmentKind::Let { .. } => AssignmentKind::let_(),
|
AssignmentKind::Let { .. } => AssignmentKind::let_(),
|
||||||
AssignmentKind::Expect { .. }
|
AssignmentKind::Expect { .. }
|
||||||
if pattern_is_var && annotation.is_none() =>
|
if pattern_is_var && annotation.is_none() =>
|
||||||
|
|
Loading…
Reference in New Issue