Repository: gleam-lang/gleam (rust)

Issue:
Using `use` together with pattern matches compiles, when it shouldn't
The following code compiles, when it shouldn't:
```gleam
import gleam/io
import gleam/result

pub fn main() {
  use <<var:8>> <- result.try(wibble())
  Ok(io.debug(var))
}

fn wibble() -> Result(BitArray, Nil) {
  Ok(<<42, 0>>)
}
```

On Erlang, it will result in a runtime error, while on JS, it will just print `42`.

Gleam version 1.6.1

Pull request:
Reintroduce exhaustiveness checking for `use`
Fixes #3879 
As explained in [this comment](https://github.com/gleam-lang/gleam/issues/3879#issuecomment-2494971447)

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a8cbdb93d..7c9d88004 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -121,6 +121,10 @@
 - Variant inference on prelude types now works correctly if the variant is constant.
   ([Surya Rose](https://github.com/GearsDatapacks))
 
+- Fixed a bug where patterns in `use` expressions would not be checked to ensure that
+  they were exhaustive.
+  ([Surya Rose](https://github.com/GearsDatapacks))
+
 ## v1.6.1 - 2024-11-19
 
 ### Bug fixed
diff --git a/compiler-core/src/type_/expression.rs b/compiler-core/src/type_/expression.rs
index ab459a4c3..ee7beb279 100644
--- a/compiler-core/src/type_/expression.rs
+++ b/compiler-core/src/type_/expression.rs
@@ -1366,10 +1366,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
         // Do not perform exhaustiveness checking if user explicitly used `let assert ... = ...`.
         let exhaustiveness_check = self.check_let_exhaustiveness(location, value.type_(), &pattern);
         match (kind, exhaustiveness_check) {
-            // Generated assignments should be checked before they are generated
-            (AssignmentKind::Generated, _) => {}
-            (AssignmentKind::Let, Ok(_)) => {}
-            (AssignmentKind::Let, Err(e)) => {
+            (AssignmentKind::Let | AssignmentKind::Generated, Ok(_)) => {}
+            (AssignmentKind::Let | AssignmentKind::Generated, Err(e)) => {
                 self.problems.error(e);
             }
             (AssignmentKind::Assert { location }, Ok(_)) => self


Test patch:
diff --git a/compiler-core/src/type_/tests/errors.rs b/compiler-core/src/type_/tests/errors.rs
index 30d6d8a78..63cf94fe4 100644
--- a/compiler-core/src/type_/tests/errors.rs
+++ b/compiler-core/src/type_/tests/errors.rs
@@ -2644,3 +2644,14 @@ pub fn b_to_a(value: Wibble(a)) -> Wibble(Int) {
 "#
     );
 }
+
+#[test]
+// https://github.com/gleam-lang/gleam/issues/3879
+fn inexhaustive_use_reports_error() {
+    assert_error!(
+        r#"
+use [1, 2, 3] <- todo
+todo
+"#
+    );
+}
diff --git a/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__errors__inexhaustive_use_reports_error.snap b/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__errors__inexhaustive_use_reports_error.snap
new file mode 100644
index 000000000..e2d47e9d6
--- /dev/null
+++ b/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__errors__inexhaustive_use_reports_error.snap
@@ -0,0 +1,29 @@
+---
+source: compiler-core/src/type_/tests/errors.rs
+expression: "\nuse [1, 2, 3] <- todo\ntodo\n"
+---
+----- SOURCE CODE
+
+use [1, 2, 3] <- todo
+todo
+
+
+----- ERROR
+error: Inexhaustive pattern
+  ┌─ /src/one/two.gleam:2:5
+  │
+2 │ use [1, 2, 3] <- todo
+  │     ^^^^^^^^^
+
+This assignment uses a pattern that does not match all possible values. If
+one of the other values is used then the assignment will crash.
+
+The missing patterns are:
+
+    []
+    [_, _, _, _, ..]
+    [_, _, _]
+    [_, _]
+    [_]
+
+Hint: Use a more general pattern or use `let assert` instead.