Skip to content

Commit fc282d1

Browse files
committed
Add better unreachable code warnings when a panic is before a use expression.
With previous changes, a test was broken when a panic was right before a use expression. The test was like that: ```gleam pub fn wibble(_) { 1 } pub fn main() { panic use <- wibble 1 } ``` This was the case because, before these changes, `UntypedExpr::Var` has not special call path in `do_infer_call` function. `infer` and `infer_or_error` was called has expected and a warning was emitted by `warn_for_unreachable_code` in case of a previous panic expression. Actually, `UntypedExpr::FieldAccess` has a special call path in `do_infer_call` and compiler does not warned about a program like that: ```gleam // Define pub fn wibble(_) { 1 } import mylib/mymod pub fn main() { panic use <- mymod.wibble 1 } ``` With this change, use expression are always warned after a panic expression.
1 parent 81dcee5 commit fc282d1

File tree

4 files changed

+56
-5
lines changed

4 files changed

+56
-5
lines changed

compiler-core/src/type_/expression.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,14 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
852852
// We use `stacker` to prevent overflowing the stack when many `use`
853853
// expressions are chained. See https://github.com/gleam-lang/gleam/issues/4287
854854
let infer_call = || {
855+
// We need this in the case where `call.function` has a special call path depending
856+
// on the type such as `UntypedExpr::Var`. In these cases, `infer_call` does not call
857+
// `infer_or_error`. `infer_or_error` is responsible for registering warnings about
858+
// unreachable code and thus, warnings about unreachable code are not registered.
859+
if self.previous_panics {
860+
self.warn_for_unreachable_code(call_location, PanicPosition::PreviousExpression);
861+
}
862+
855863
self.infer_call(
856864
*call.function,
857865
call.arguments,
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ expression: "\n pub fn wibble(_) { 1 }\n pub fn main() {\n
1414

1515
----- WARNING
1616
warning: Unreachable code
17-
┌─ /src/warning/wrn.gleam:5:20
18-
19-
5use <- wibble
20-
^^^^^^
17+
┌─ /src/warning/wrn.gleam:5:13
18+
19+
5 │ ╭ use <- wibble
20+
6 │ │ 1
21+
│ ╰─────────────^
2122

2223
This code is unreachable because it comes after a `panic`.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
source: compiler-core/src/type_/tests/warnings.rs
3+
expression: "\n import module\n pub fn a() {\n panic\n use <- module.wibble\n 1\n }\n "
4+
---
5+
----- SOURCE CODE
6+
-- module.gleam
7+
pub fn wibble(_) { 1 }
8+
9+
-- main.gleam
10+
11+
import module
12+
pub fn a() {
13+
panic
14+
use <- module.wibble
15+
1
16+
}
17+
18+
19+
----- WARNING
20+
warning: Unreachable code
21+
┌─ /src/warning/wrn.gleam:5:13
22+
23+
5 │ ╭ use <- module.wibble
24+
6 │ │ 1
25+
│ ╰─────────────^
26+
27+
This code is unreachable because it comes after a `panic`.

compiler-core/src/type_/tests/warnings.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1921,7 +1921,7 @@ fn doesnt_warn_twice_for_unreachable_code_if_has_already_warned_in_a_block_2() {
19211921
}
19221922

19231923
#[test]
1924-
fn unreachable_use_after_panic() {
1924+
fn unreachable_use_after_panic_1() {
19251925
assert_warning!(
19261926
r#"
19271927
pub fn wibble(_) { 1 }
@@ -1934,6 +1934,21 @@ fn unreachable_use_after_panic() {
19341934
);
19351935
}
19361936

1937+
#[test]
1938+
fn unreachable_use_after_panic_2() {
1939+
assert_warning!(
1940+
("package", "module", r#"pub fn wibble(_) { 1 }"#),
1941+
r#"
1942+
import module
1943+
pub fn a() {
1944+
panic
1945+
use <- module.wibble
1946+
1
1947+
}
1948+
"#
1949+
);
1950+
}
1951+
19371952
#[test]
19381953
fn unreachable_code_after_case_subject_panics_1() {
19391954
assert_warning!(

0 commit comments

Comments
 (0)