mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Allow ignored defs with an effectful RHS
This commit is contained in:
parent
175a2b5683
commit
c9f001b041
13 changed files with 136 additions and 126 deletions
|
@ -663,7 +663,7 @@ impl Constraints {
|
|||
| Constraint::Store(..)
|
||||
| Constraint::Lookup(..)
|
||||
| Constraint::Pattern(..)
|
||||
| Constraint::EffectfulStmt(..)
|
||||
| Constraint::ExpectEffectful(..)
|
||||
| Constraint::FxCall(_)
|
||||
| Constraint::FxSuffix(_)
|
||||
| Constraint::FlexToPure(_)
|
||||
|
@ -845,8 +845,8 @@ pub enum Constraint {
|
|||
FxSuffix(Index<FxSuffixConstraint>),
|
||||
/// Set an fx var as pure if flex (no effectful functions were called)
|
||||
FlexToPure(Variable),
|
||||
/// Expect statement to be effectful
|
||||
EffectfulStmt(Variable, Region),
|
||||
/// Expect statement or ignored def to be effectful
|
||||
ExpectEffectful(Variable, ExpectEffectfulReason, Region),
|
||||
/// Used for things that always unify, e.g. blanks and runtime errors
|
||||
True,
|
||||
SaveTheEnvironment,
|
||||
|
@ -937,6 +937,7 @@ pub struct FxExpectation {
|
|||
pub enum FxCallKind {
|
||||
Call(Option<Symbol>),
|
||||
Stmt,
|
||||
Ignored,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
@ -962,6 +963,12 @@ impl FxSuffixKind {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum ExpectEffectfulReason {
|
||||
Stmt,
|
||||
Ignored,
|
||||
}
|
||||
|
||||
/// Custom impl to limit vertical space used by the debug output
|
||||
impl std::fmt::Debug for Constraint {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
|
@ -984,8 +991,8 @@ impl std::fmt::Debug for Constraint {
|
|||
Self::FxSuffix(arg0) => {
|
||||
write!(f, "FxSuffix({arg0:?})")
|
||||
}
|
||||
Self::EffectfulStmt(arg0, arg1) => {
|
||||
write!(f, "EffectfulStmt({arg0:?}, {arg1:?})")
|
||||
Self::ExpectEffectful(arg0, arg1, arg2) => {
|
||||
write!(f, "EffectfulStmt({arg0:?}, {arg1:?}, {arg2:?})")
|
||||
}
|
||||
Self::FlexToPure(arg0) => {
|
||||
write!(f, "FlexToPure({arg0:?})")
|
||||
|
|
|
@ -390,6 +390,7 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
|
|||
kind: match kind {
|
||||
DefKind::Let => DefKind::Let,
|
||||
DefKind::Stmt(v) => DefKind::Stmt(sub!(*v)),
|
||||
DefKind::Ignored(v) => DefKind::Ignored(sub!(*v)),
|
||||
},
|
||||
},
|
||||
)
|
||||
|
|
|
@ -112,6 +112,7 @@ fn def<'a>(c: &Ctx, f: &'a Arena<'a>, d: &'a Def) -> DocBuilder<'a, Arena<'a>> {
|
|||
|
||||
match kind {
|
||||
DefKind::Let => def_help(c, f, &loc_pattern.value, &loc_expr.value),
|
||||
DefKind::Ignored(_) => def_help(c, f, &loc_pattern.value, &loc_expr.value),
|
||||
DefKind::Stmt(_) => expr(c, EPrec::Free, f, &loc_expr.value),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,6 +97,8 @@ pub enum DefKind {
|
|||
Let,
|
||||
/// A standalone statement with an fx variable
|
||||
Stmt(Variable),
|
||||
/// Ignored result, must be effectful
|
||||
Ignored(Variable),
|
||||
}
|
||||
|
||||
impl DefKind {
|
||||
|
@ -104,6 +106,19 @@ impl DefKind {
|
|||
match self {
|
||||
DefKind::Let => DefKind::Let,
|
||||
DefKind::Stmt(v) => DefKind::Stmt(f(v)),
|
||||
DefKind::Ignored(v) => DefKind::Ignored(f(v)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_pattern(var_store: &mut VarStore, pattern: &Loc<Pattern>) -> Self {
|
||||
if BindingsFromPattern::new(pattern)
|
||||
.peekable()
|
||||
.peek()
|
||||
.is_none()
|
||||
{
|
||||
DefKind::Ignored(var_store.fresh())
|
||||
} else {
|
||||
DefKind::Let
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1212,11 +1227,7 @@ fn canonicalize_value_defs<'a>(
|
|||
|
||||
for (def_index, pending_def) in pending_value_defs.iter().enumerate() {
|
||||
if let Some(loc_pattern) = pending_def.loc_pattern() {
|
||||
let mut new_bindings = BindingsFromPattern::new(loc_pattern).peekable();
|
||||
|
||||
if new_bindings.peek().is_none() {
|
||||
env.problem(Problem::NoIdentifiersIntroduced(loc_pattern.region));
|
||||
}
|
||||
let new_bindings = BindingsFromPattern::new(loc_pattern).peekable();
|
||||
|
||||
for (s, r) in new_bindings {
|
||||
// store the top-level defs, used to ensure that closures won't capture them
|
||||
|
@ -2439,6 +2450,8 @@ fn canonicalize_pending_value_def<'a>(
|
|||
}
|
||||
Body(loc_can_pattern, loc_expr) => {
|
||||
//
|
||||
let def_kind = DefKind::from_pattern(var_store, &loc_can_pattern);
|
||||
|
||||
canonicalize_pending_body(
|
||||
env,
|
||||
output,
|
||||
|
@ -2447,7 +2460,7 @@ fn canonicalize_pending_value_def<'a>(
|
|||
loc_can_pattern,
|
||||
loc_expr,
|
||||
None,
|
||||
DefKind::Let,
|
||||
def_kind,
|
||||
)
|
||||
}
|
||||
Stmt(loc_expr) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue