mirror of
https://github.com/roc-lang/roc.git
synced 2025-11-02 22:01:20 +00:00
Report effect call in pure function
This commit is contained in:
parent
839078b5d1
commit
fd2493ee51
2 changed files with 88 additions and 43 deletions
|
|
@ -14543,37 +14543,6 @@ All branches in an `if` must have the same type!
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
test_report!(
|
|
||||||
leftover_statement,
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
app [main!] { pf: platform "../../../../../examples/cli/effects-platform/main.roc" }
|
|
||||||
|
|
||||||
import pf.Effect
|
|
||||||
|
|
||||||
main! = \{} ->
|
|
||||||
identity {}
|
|
||||||
|
|
||||||
Effect.putLine! "hello"
|
|
||||||
|
|
||||||
identity = \x -> x
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
@r###"
|
|
||||||
── LEFTOVER STATEMENT in /code/proj/Main.roc ───────────────────────────────────
|
|
||||||
|
|
||||||
This statement does not produce any effects:
|
|
||||||
|
|
||||||
6│ identity {}
|
|
||||||
^^^^^^^^^^^
|
|
||||||
|
|
||||||
Standalone statements are only useful if they call effectful
|
|
||||||
functions.
|
|
||||||
|
|
||||||
Did you forget to use its result? If not, feel free to remove it.
|
|
||||||
"###
|
|
||||||
);
|
|
||||||
|
|
||||||
test_report!(
|
test_report!(
|
||||||
return_outside_of_function,
|
return_outside_of_function,
|
||||||
indoc!(
|
indoc!(
|
||||||
|
|
@ -14691,7 +14660,7 @@ All branches in an `if` must have the same type!
|
||||||
);
|
);
|
||||||
|
|
||||||
test_report!(
|
test_report!(
|
||||||
function_def_fx_no_bang,
|
leftover_statement,
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
app [main!] { pf: platform "../../../../../examples/cli/effects-platform/main.roc" }
|
app [main!] { pf: platform "../../../../../examples/cli/effects-platform/main.roc" }
|
||||||
|
|
@ -14699,25 +14668,63 @@ All branches in an `if` must have the same type!
|
||||||
import pf.Effect
|
import pf.Effect
|
||||||
|
|
||||||
main! = \{} ->
|
main! = \{} ->
|
||||||
printHello {}
|
identity {}
|
||||||
|
|
||||||
printHello = \{} ->
|
|
||||||
Effect.putLine! "hello"
|
Effect.putLine! "hello"
|
||||||
|
|
||||||
|
identity = \x -> x
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
@r###"
|
@r###"
|
||||||
── MISSING EXCLAMATION in /code/proj/Main.roc ──────────────────────────────────
|
── LEFTOVER STATEMENT in /code/proj/Main.roc ───────────────────────────────────
|
||||||
|
|
||||||
This function is effectful, but its name does not indicate so:
|
This statement does not produce any effects:
|
||||||
|
|
||||||
8│ printHello = \{} ->
|
6│ identity {}
|
||||||
^^^^^^^^^^
|
^^^^^^^^^^^
|
||||||
|
|
||||||
Add an exclamation mark at the end of its name, like:
|
Standalone statements are only useful if they call effectful
|
||||||
|
functions.
|
||||||
|
|
||||||
printHello!
|
Did you forget to use its result? If not, feel free to remove it.
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
|
||||||
This will help readers identify it as a source of effects.
|
test_report!(
|
||||||
|
fx_fn_annotated_as_pure,
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
app [main!] { pf: platform "../../../../../examples/cli/effects-platform/main.roc" }
|
||||||
|
|
||||||
|
import pf.Effect
|
||||||
|
|
||||||
|
main! = \{} ->
|
||||||
|
Effect.putLine! (getCheer "hello")
|
||||||
|
|
||||||
|
getCheer : Str -> Str
|
||||||
|
getCheer = \msg ->
|
||||||
|
name = Effect.getLine! {}
|
||||||
|
|
||||||
|
"$(msg), $(name)!"
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
@r###"
|
||||||
|
── EFFECT IN PURE FUNCTION in /code/proj/Main.roc ──────────────────────────────
|
||||||
|
|
||||||
|
This expression calls an effectful function:
|
||||||
|
|
||||||
|
10│ name = Effect.getLine! {}
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
However, the type of the enclosing function indicates it must be pure:
|
||||||
|
|
||||||
|
8│ getCheer : 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.
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -14809,4 +14816,6 @@ All branches in an `if` must have the same type!
|
||||||
This will help readers identify it as a source of effects.
|
This will help readers identify it as a source of effects.
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// [purity-inference] TODO: check ! in records, tuples, tags, opaques, and arguments
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -351,7 +351,9 @@ pub fn type_problem<'b>(
|
||||||
let stack = [
|
let stack = [
|
||||||
alloc.reflow("This function is pure, but its name suggests otherwise:"),
|
alloc.reflow("This function is pure, but its name suggests otherwise:"),
|
||||||
alloc.region(lines.convert_region(region), severity),
|
alloc.region(lines.convert_region(region), severity),
|
||||||
alloc.reflow("Remove the exclamation mark to give an accurate impression of its behavior."),
|
alloc.reflow(
|
||||||
|
"Remove the exclamation mark to give an accurate impression of its behavior.",
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
Some(Report {
|
Some(Report {
|
||||||
|
|
@ -1692,6 +1694,7 @@ fn to_expr_report<'b>(
|
||||||
unimplemented!("record default field is not implemented yet")
|
unimplemented!("record default field is not implemented yet")
|
||||||
}
|
}
|
||||||
Reason::ImportParams(_) => unreachable!(),
|
Reason::ImportParams(_) => unreachable!(),
|
||||||
|
|
||||||
Reason::FunctionOutput => {
|
Reason::FunctionOutput => {
|
||||||
let problem = alloc.concat([
|
let problem = alloc.concat([
|
||||||
alloc.text("This "),
|
alloc.text("This "),
|
||||||
|
|
@ -1726,7 +1729,40 @@ fn to_expr_report<'b>(
|
||||||
severity,
|
severity,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reason::CallInFunction(_) => todo!("[purity-inference] CallInFunction"),
|
|
||||||
|
Reason::CallInFunction(ann_region) => {
|
||||||
|
let lines = [
|
||||||
|
alloc.reflow("This expression calls an effectful function:"),
|
||||||
|
alloc.region(lines.convert_region(region), severity),
|
||||||
|
match ann_region {
|
||||||
|
Some(ann_region) => alloc.stack([
|
||||||
|
alloc.reflow(
|
||||||
|
"However, the type of the enclosing function indicates it must be pure:",
|
||||||
|
),
|
||||||
|
alloc.region(lines.convert_region(ann_region), Severity::Warning),
|
||||||
|
alloc.concat([
|
||||||
|
alloc.tip(),
|
||||||
|
alloc.text("Replace "),
|
||||||
|
alloc.keyword("->"),
|
||||||
|
alloc.text(" with "),
|
||||||
|
alloc.keyword("=>"),
|
||||||
|
alloc.text(" to annotate it as effectful."),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
None => {
|
||||||
|
alloc.reflow("However, the enclosing function is required to be pure.")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
alloc.reflow("You can still run the program with this error, which can be helpful when you're debugging."),
|
||||||
|
];
|
||||||
|
|
||||||
|
Report {
|
||||||
|
filename,
|
||||||
|
title: "EFFECT IN PURE FUNCTION".to_string(),
|
||||||
|
doc: alloc.stack(lines),
|
||||||
|
severity,
|
||||||
|
}
|
||||||
|
}
|
||||||
Reason::CallInTopLevelDef => todo!("[purity-inference] CallInTopLevelDef"),
|
Reason::CallInTopLevelDef => todo!("[purity-inference] CallInTopLevelDef"),
|
||||||
Reason::Stmt => todo!("[purity-inference] Stmt"),
|
Reason::Stmt => todo!("[purity-inference] Stmt"),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue