mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 16:44:33 +00:00
Report effectful statement in pure function
This commit is contained in:
parent
fd2493ee51
commit
b62665e49e
3 changed files with 69 additions and 35 deletions
|
@ -601,24 +601,6 @@ pub fn constrain_expr(
|
||||||
|
|
||||||
let category = Category::CallResult(opt_symbol, *called_via);
|
let category = Category::CallResult(opt_symbol, *called_via);
|
||||||
|
|
||||||
let fx_expected_type = match env.enclosing_fx {
|
|
||||||
Some(enclosing_fn) => {
|
|
||||||
let enclosing_fx_index = constraints.push_variable(enclosing_fn.fx_var);
|
|
||||||
|
|
||||||
constraints.push_expected_type(ForReason(
|
|
||||||
Reason::CallInFunction(enclosing_fn.ann_region),
|
|
||||||
enclosing_fx_index,
|
|
||||||
region,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
None => constraints.push_expected_type(ForReason(
|
|
||||||
Reason::CallInTopLevelDef,
|
|
||||||
// top-level defs are only allowed to call pure functions
|
|
||||||
constraints.push_variable(Variable::PURE),
|
|
||||||
region,
|
|
||||||
)),
|
|
||||||
};
|
|
||||||
|
|
||||||
let and_cons = [
|
let and_cons = [
|
||||||
fn_con,
|
fn_con,
|
||||||
constraints.equal_types_var(*fn_var, expected_fn_type, category.clone(), fn_region),
|
constraints.equal_types_var(*fn_var, expected_fn_type, category.clone(), fn_region),
|
||||||
|
@ -629,7 +611,7 @@ pub fn constrain_expr(
|
||||||
category.clone(),
|
category.clone(),
|
||||||
region,
|
region,
|
||||||
),
|
),
|
||||||
constraints.equal_types_var(*fx_var, fx_expected_type, category, region),
|
constrain_call_fx(env, constraints, region, *fx_var, category),
|
||||||
];
|
];
|
||||||
|
|
||||||
let and_constraint = constraints.and_constraint(and_cons);
|
let and_constraint = constraints.and_constraint(and_cons);
|
||||||
|
@ -1891,6 +1873,34 @@ pub fn constrain_expr(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn constrain_call_fx(
|
||||||
|
env: &mut Env,
|
||||||
|
constraints: &mut Constraints,
|
||||||
|
region: Region,
|
||||||
|
fx_var: Variable,
|
||||||
|
category: Category,
|
||||||
|
) -> Constraint {
|
||||||
|
let fx_expected_type = match env.enclosing_fx {
|
||||||
|
Some(enclosing_fn) => {
|
||||||
|
let enclosing_fx_index = constraints.push_variable(enclosing_fn.fx_var);
|
||||||
|
|
||||||
|
constraints.push_expected_type(ForReason(
|
||||||
|
Reason::CallInFunction(enclosing_fn.ann_region),
|
||||||
|
enclosing_fx_index,
|
||||||
|
region,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
None => constraints.push_expected_type(ForReason(
|
||||||
|
Reason::CallInTopLevelDef,
|
||||||
|
// top-level defs are only allowed to call pure functions
|
||||||
|
constraints.push_variable(Variable::PURE),
|
||||||
|
region,
|
||||||
|
)),
|
||||||
|
};
|
||||||
|
|
||||||
|
constraints.equal_types_var(fx_var, fx_expected_type, category, region)
|
||||||
|
}
|
||||||
|
|
||||||
fn constrain_function_def(
|
fn constrain_function_def(
|
||||||
types: &mut Types,
|
types: &mut Types,
|
||||||
constraints: &mut Constraints,
|
constraints: &mut Constraints,
|
||||||
|
@ -3517,21 +3527,8 @@ fn constrain_stmt_def(
|
||||||
|
|
||||||
// We have to unify the stmt fx with the enclosing fx
|
// We have to unify the stmt fx with the enclosing fx
|
||||||
// since we used the former to constrain the expr.
|
// since we used the former to constrain the expr.
|
||||||
let enclosing_fx_index = match env.enclosing_fx {
|
|
||||||
Some(enclosing_fn) => {
|
|
||||||
let enclosing_fx_index = constraints.push_variable(enclosing_fn.fx_var);
|
|
||||||
|
|
||||||
constraints.push_expected_type(ForReason(Reason::Stmt, enclosing_fx_index, region))
|
|
||||||
}
|
|
||||||
None => constraints.push_expected_type(ForReason(
|
|
||||||
// Statements are not allowed in top-level defs
|
|
||||||
Reason::Stmt,
|
|
||||||
constraints.push_variable(Variable::PURE),
|
|
||||||
region,
|
|
||||||
)),
|
|
||||||
};
|
|
||||||
let enclosing_fx_constraint =
|
let enclosing_fx_constraint =
|
||||||
constraints.equal_types_var(fx_var, enclosing_fx_index, Category::Unknown, region);
|
constrain_call_fx(env, constraints, region, fx_var, Category::Unknown);
|
||||||
|
|
||||||
constraints.and_constraint([body_con, effectful_constraint, enclosing_fx_constraint])
|
constraints.and_constraint([body_con, effectful_constraint, enclosing_fx_constraint])
|
||||||
}
|
}
|
||||||
|
|
|
@ -14716,7 +14716,7 @@ All branches in an `if` must have the same type!
|
||||||
10│ name = Effect.getLine! {}
|
10│ name = Effect.getLine! {}
|
||||||
^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
However, the type of the enclosing function indicates it must be pure:
|
However, the type of the enclosing function requires that it's pure:
|
||||||
|
|
||||||
8│ getCheer : Str -> Str
|
8│ getCheer : Str -> Str
|
||||||
^^^^^^^^^^
|
^^^^^^^^^^
|
||||||
|
@ -14728,6 +14728,43 @@ All branches in an `if` must have the same type!
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test_report!(
|
||||||
|
fx_fn_annotated_as_pure_stmt,
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
app [main!] { pf: platform "../../../../../examples/cli/effects-platform/main.roc" }
|
||||||
|
|
||||||
|
import pf.Effect
|
||||||
|
|
||||||
|
main! = \{} ->
|
||||||
|
trim "hello "
|
||||||
|
|
||||||
|
trim : Str -> Str
|
||||||
|
trim = \msg ->
|
||||||
|
Effect.putLine! "Trimming $(msg)"
|
||||||
|
Str.trim msg
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
@r###"
|
||||||
|
── EFFECT IN PURE FUNCTION in /code/proj/Main.roc ──────────────────────────────
|
||||||
|
|
||||||
|
This expression calls an effectful function:
|
||||||
|
|
||||||
|
10│ Effect.putLine! "Trimming $(msg)"
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
However, the type of the enclosing function requires that it's pure:
|
||||||
|
|
||||||
|
8│ trim : Str -> Str
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
Tip: Replace `->` with `=>` to annotate it as effectful.
|
||||||
|
|
||||||
|
You can still run the program with this error, which can be helpful
|
||||||
|
when you're debugging.
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
|
||||||
test_report!(
|
test_report!(
|
||||||
nested_function_def_fx_no_bang,
|
nested_function_def_fx_no_bang,
|
||||||
indoc!(
|
indoc!(
|
||||||
|
|
|
@ -1737,7 +1737,7 @@ fn to_expr_report<'b>(
|
||||||
match ann_region {
|
match ann_region {
|
||||||
Some(ann_region) => alloc.stack([
|
Some(ann_region) => alloc.stack([
|
||||||
alloc.reflow(
|
alloc.reflow(
|
||||||
"However, the type of the enclosing function indicates it must be pure:",
|
"However, the type of the enclosing function requires that it's pure:",
|
||||||
),
|
),
|
||||||
alloc.region(lines.convert_region(ann_region), Severity::Warning),
|
alloc.region(lines.convert_region(ann_region), Severity::Warning),
|
||||||
alloc.concat([
|
alloc.concat([
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue