diff --git a/compiler/src/typed/typecore.re b/compiler/src/typed/typecore.re
index 76b37d21b8..d5a2f2401c 100644
--- a/compiler/src/typed/typecore.re
+++ b/compiler/src/typed/typecore.re
@@ -2254,11 +2254,10 @@ and type_statement_expr = (~explanation=?, ~in_function=?, env, sexp) => {
     /*| Tarrow _ -> [not really applicable with our syntax]
       Location.prerr_warning loc Warnings.Partial_application*/
     | TTyConstr(p, _, _) when Path.same(p, Builtin_types.path_void) => ()
+    | TTyVar(None) => ()
     /*| Tvar _ ->
       add_delayed_check (fun () -> check_application_result env true exp)*/
-    | _ => ()
-    /* This isn't quite relevant to Grain mechanics
-       Location.prerr_warning loc Grain_utils.Warnings.StatementType */
+    | _ => Location.prerr_warning(loc, Grain_utils.Warnings.StatementType)
     };
     unify_var(env, tv, ty);
     exp;
diff --git a/compiler/src/utils/warnings.re b/compiler/src/utils/warnings.re
index fd513fddf2..77bfd42ca7 100644
--- a/compiler/src/utils/warnings.re
+++ b/compiler/src/utils/warnings.re
@@ -101,7 +101,7 @@ let message =
     "these field labels belong to several types: "
     ++ String.concat(" ", tl)
     ++ "\nThe first one was selected. Please disambiguate if this is wrong."
-  | StatementType => "this expression should have type void."
+  | StatementType => "this expression should have type void. Use `ignore` to ignore the result of the expression"
   | NonreturningStatement => "this statement never returns (or has an unsound type)."
   | AllClausesGuarded => "this pattern-matching is not exhaustive.\nAll clauses in this pattern-matching are guarded."
   | PartialMatch("") => "this pattern-matching is not exhaustive."
diff --git a/compiler/test/input/wasiPolyfill.gr b/compiler/test/input/wasiPolyfill.gr
index a5eb6c8909..ace9c951d5 100644
--- a/compiler/test/input/wasiPolyfill.gr
+++ b/compiler/test/input/wasiPolyfill.gr
@@ -14,8 +14,8 @@ provide let fd_write: (WasmI32, WasmI32, WasmI32, WasmI32) => WasmI32 =
     iovs_len,
     nwritten,
   ) => {
-  fd_write(fd, iovs, iovs_len, nwritten)
-  fd_write(fd, iovs, iovs_len, nwritten)
+  let _ = fd_write(fd, iovs, iovs_len, nwritten)
+  let _ = fd_write(fd, iovs, iovs_len, nwritten)
   fd_write(fd, iovs, iovs_len, nwritten)
 }
 
diff --git a/compiler/test/runner.re b/compiler/test/runner.re
index de1b3d3c60..130039dd01 100644
--- a/compiler/test/runner.re
+++ b/compiler/test/runner.re
@@ -221,6 +221,7 @@ let makeSnapshotRunner =
     (~config_fn=?, test, ~module_header=module_header, name, prog) => {
   test(name, ({expect}) => {
     Config.preserve_all_configs(() => {
+      Config.print_warnings := false;
       ignore @@
       compile(
         ~hook=stop_after_object_file_emitted,
@@ -249,6 +250,7 @@ let makeFilesizeRunner =
 let makeSnapshotFileRunner = (test, ~config_fn=?, name, filename) => {
   test(name, ({expect}) => {
     Config.preserve_all_configs(() => {
+      Config.print_warnings := false;
       let infile = grainfile(filename);
       let outfile = wasmfile(name);
       ignore @@
diff --git a/compiler/test/stdlib/array.test.gr b/compiler/test/stdlib/array.test.gr
index 9757f120f8..3ff9a2a04a 100644
--- a/compiler/test/stdlib/array.test.gr
+++ b/compiler/test/stdlib/array.test.gr
@@ -835,7 +835,7 @@ module Immutable {
 
   // Array.rotate
   let arr1 = fromList([1, 2, 3, 4, 5])
-  Array.rotate(0, arr1)
+  ignore(Array.rotate(0, arr1))
   assert arr1 == fromList([1, 2, 3, 4, 5])
 
   let arr2 = fromList([1, 2, 3, 4, 5])
diff --git a/compiler/test/stdlib/char.test.gr b/compiler/test/stdlib/char.test.gr
index e2e55645af..2c3e420fe7 100644
--- a/compiler/test/stdlib/char.test.gr
+++ b/compiler/test/stdlib/char.test.gr
@@ -51,7 +51,7 @@ while (!done) {
     break
   }
 
-  Char.code(chars[charPosition])
+  ignore(Char.code(chars[charPosition]))
   charPosition += 1
 }
 
diff --git a/compiler/test/stdlib/path.test.gr b/compiler/test/stdlib/path.test.gr
index 99ae147694..a788edf9f3 100644
--- a/compiler/test/stdlib/path.test.gr
+++ b/compiler/test/stdlib/path.test.gr
@@ -216,8 +216,8 @@ List.forEach(({ base, toAppend, final }) => {
   assert append == Ok(expPath)
 }, appendTests)
 
-Path.append(fs("file"), fs("f")) == Err(Path.AppendToFile)
-Path.append(fs("/d/"), fs("/f")) == Err(Path.AppendAbsolute)
+assert Path.append(fs("file"), fs("f")) == Err(Path.AppendToFile)
+assert Path.append(fs("/d/"), fs("/f")) == Err(Path.AppendAbsolute)
 
 record RelativeToDirTestData {
   source: String,
diff --git a/compiler/test/stdlib/queue.test.gr b/compiler/test/stdlib/queue.test.gr
index d31a914828..caec75d2fc 100644
--- a/compiler/test/stdlib/queue.test.gr
+++ b/compiler/test/stdlib/queue.test.gr
@@ -29,7 +29,7 @@ Queue.push(4, queue)
 assert Queue.size(queue) == 3
 assert Queue.peek(queue) == Some(2)
 let copy = Queue.copy(queue)
-Queue.pop(copy)
+ignore(Queue.pop(copy))
 assert Queue.size(copy) == 2
 assert Queue.size(queue) == 3
 Queue.clear(queue)
@@ -61,11 +61,11 @@ Queue.push(1, queue)
 Queue.push(2, queue)
 Queue.push(3, queue)
 assert Queue.toList(queue) == [0, 1, 2, 3]
-Queue.pop(queue)
+ignore(Queue.pop(queue))
 assert Queue.toList(queue) == [1, 2, 3]
 Queue.push(3, queue)
 assert Queue.toList(queue) == [1, 2, 3, 3]
-Queue.pop(queue)
+ignore(Queue.pop(queue))
 Queue.push(4, queue)
 Queue.push(5, queue)
 assert Queue.toList(queue) == [2, 3, 3, 4, 5]
@@ -121,12 +121,12 @@ Queue.push(1, queue2)
 Queue.push(2, queue2)
 Queue.push(3, queue2)
 Queue.push(4, queue2)
-Queue.pop(queue2)
-Queue.pop(queue2)
+ignore(Queue.pop(queue2))
+ignore(Queue.pop(queue2))
 Queue.push(5, queue2)
-Queue.pop(queue2)
-Queue.pop(queue2)
-Queue.pop(queue2)
+ignore(Queue.pop(queue2))
+ignore(Queue.pop(queue2))
+ignore(Queue.pop(queue2))
 Queue.push(6, queue2)
 Queue.push(7, queue2)
 Queue.push(8, queue2)
@@ -149,7 +149,7 @@ Queue.push(2, queue3)
 Queue.push(3, queue3)
 assert Queue.toArray(queue3) == [> 1, 2, 3]
 let queue4 = Queue.copy(queue3)
-Queue.pop(queue4)
+ignore(Queue.pop(queue4))
 assert Queue.toArray(queue4) == [> 2, 3]
 
 // Queue.fromArray
@@ -169,12 +169,12 @@ Queue.push(1, queue2)
 Queue.push(2, queue2)
 Queue.push(3, queue2)
 Queue.push(4, queue2)
-Queue.pop(queue2)
-Queue.pop(queue2)
+ignore(Queue.pop(queue2))
+ignore(Queue.pop(queue2))
 Queue.push(5, queue2)
-Queue.pop(queue2)
-Queue.pop(queue2)
-Queue.pop(queue2)
+ignore(Queue.pop(queue2))
+ignore(Queue.pop(queue2))
+ignore(Queue.pop(queue2))
 Queue.push(6, queue2)
 Queue.push(7, queue2)
 Queue.push(8, queue2)
@@ -194,7 +194,7 @@ Queue.push(1, queue3)
 Queue.push(2, queue3)
 Queue.push(3, queue3)
 let queue4 = Queue.copy(queue3)
-Queue.pop(queue4)
+ignore(Queue.pop(queue4))
 let queue5 = Queue.make()
 Queue.push(6, queue5)
 Queue.push(7, queue5)
@@ -222,7 +222,7 @@ Queue.push(3, queue7)
 assert queue4 == queue7
 let queue8 = Queue.make()
 Queue.push(1, queue8)
-Queue.pop(queue8)
+ignore(Queue.pop(queue8))
 assert queue8 == queue1
 
 assert !(queue2 == queue3)
diff --git a/compiler/test/stdlib/set.test.gr b/compiler/test/stdlib/set.test.gr
index ff73fd7373..e8abf4e784 100644
--- a/compiler/test/stdlib/set.test.gr
+++ b/compiler/test/stdlib/set.test.gr
@@ -327,7 +327,7 @@ module Immutable {
 
   let mut filterTestSet = makeTestSet()
 
-  Set.filter(key => fail "Shouldn't be called", Set.empty)
+  ignore(Set.filter(key => fail "Shouldn't be called", Set.empty))
   filterTestSet = Set.filter(key => key == Sheep, filterTestSet)
 
   assert !Set.contains(Grain, filterTestSet)
@@ -338,7 +338,7 @@ module Immutable {
 
   let mut rejectTestSet = makeTestSet()
 
-  Set.reject(key => fail "Shouldn't be called", Set.empty)
+  ignore(Set.reject(key => fail "Shouldn't be called", Set.empty))
   rejectTestSet = Set.reject(key => key == Sheep, rejectTestSet)
 
   assert Set.contains(Grain, rejectTestSet)
diff --git a/compiler/test/stdlib/stack.test.gr b/compiler/test/stdlib/stack.test.gr
index 8f56a3ae99..cc4477d5cc 100644
--- a/compiler/test/stdlib/stack.test.gr
+++ b/compiler/test/stdlib/stack.test.gr
@@ -28,7 +28,7 @@ Stack.push(4, stack)
 assert Stack.size(stack) == 3
 assert Stack.peek(stack) == Some(4)
 let copy = Stack.copy(stack)
-Stack.pop(copy)
+ignore(Stack.pop(copy))
 assert Stack.size(copy) == 2
 assert Stack.size(stack) == 3
 Stack.clear(stack)
diff --git a/compiler/test/stdlib/wasi.file.test.gr b/compiler/test/stdlib/wasi.file.test.gr
index 90432f3893..6c1968a399 100644
--- a/compiler/test/stdlib/wasi.file.test.gr
+++ b/compiler/test/stdlib/wasi.file.test.gr
@@ -11,7 +11,7 @@ let foo = Result.unwrap(
 
 let (buf, nread) = Result.unwrap(Fs.fdRead(foo, 40))
 
-Fs.fdClose(foo)
+ignore(Fs.fdClose(foo))
 
 assert buf == Bytes.fromString("foo, bar, & baz")
 assert nread == 15
@@ -23,7 +23,7 @@ let foo = Result.unwrap(
 
 let (buf, nread) = Result.unwrap(Fs.fdRead(foo, 40))
 
-Fs.fdClose(foo)
+ignore(Fs.fdClose(foo))
 
 assert buf == Bytes.fromString("foo, bar, & baz")
 assert nread == 15
@@ -35,7 +35,7 @@ let foo = Result.unwrap(
 
 let (buf, nread) = Result.unwrap(Fs.fdRead(foo, 40))
 
-Fs.fdClose(foo)
+ignore(Fs.fdClose(foo))
 
 assert buf == Bytes.fromString("foo, bar, & baz")
 assert nread == 15
@@ -53,7 +53,7 @@ let foo = Result.unwrap(
 
 let (buf, nread) = Result.unwrap(Fs.fdRead(foo, 40))
 
-Fs.fdClose(foo)
+ignore(Fs.fdClose(foo))
 
 assert buf == Bytes.fromString("foo, bar, & baz")
 assert nread == 15
@@ -71,13 +71,13 @@ let foo = Result.unwrap(
 
 assert Fs.fdWrite(foo, Bytes.fromString("this and that")) == Ok(13)
 
-Fs.fdSeek(foo, 0L, Fs.Set)
+ignore(Fs.fdSeek(foo, 0L, Fs.Set))
 
 let (buf, nread) = Result.unwrap(Fs.fdRead(foo, 40))
 
-Fs.fdSetSize(foo, 0L)
+ignore(Fs.fdSetSize(foo, 0L))
 
-Fs.fdClose(foo)
+ignore(Fs.fdClose(foo))
 
 assert buf == Bytes.fromString("this and that")
 assert nread == 13
diff --git a/compiler/test/stdlib/wasi.process.test.gr b/compiler/test/stdlib/wasi.process.test.gr
index a9a9b81286..ad868570f9 100644
--- a/compiler/test/stdlib/wasi.process.test.gr
+++ b/compiler/test/stdlib/wasi.process.test.gr
@@ -15,4 +15,4 @@ match (Process.env()) {
   Err(err) => throw err,
 }
 
-Process.exit(5)
+let _ = Process.exit(5)
diff --git a/compiler/test/suites/arrays.re b/compiler/test/suites/arrays.re
index bb4c8387ba..cd3bad5c8c 100644
--- a/compiler/test/suites/arrays.re
+++ b/compiler/test/suites/arrays.re
@@ -30,42 +30,42 @@ describe("arrays", ({test, testSkip}) => {
   assertSnapshot("array_access5", "[> 1, 2, 3][-3]");
   assertRunError(
     "array_access_err",
-    "let x = [> 1, 2, 3]; x[3]",
+    "let x = [> 1, 2, 3]; ignore(x[3])",
     "Index out of bounds",
   );
   assertRunError(
     "array_access_err2",
-    "let x = [> 1, 2, 3]; x[-4]",
+    "let x = [> 1, 2, 3]; ignore(x[-4])",
     "Index out of bounds",
   );
   assertRunError(
     "array_access_err3",
-    "let x = [> 1, 2, 3]; x[99]",
+    "let x = [> 1, 2, 3]; ignore(x[99])",
     "Index out of bounds",
   );
   assertRunError(
     "array_access_err4",
-    "let x = [> 1, 2, 3]; x[-99]",
+    "let x = [> 1, 2, 3]; ignore(x[-99])",
     "Index out of bounds",
   );
   assertRunError(
     "array_access_err5",
-    "let x = [> 1, 2, 3]; let i = 1.5; x[i]",
+    "let x = [> 1, 2, 3]; let i = 1.5; ignore(x[i])",
     "Index not an integer",
   );
   assertRunError(
     "array_access_err6",
-    "let x = [> 1, 2, 3]; let i = 1/3; x[i]",
+    "let x = [> 1, 2, 3]; let i = 1/3; ignore(x[i])",
     "Index not an integer",
   );
   assertRunError(
     "array_access_err7",
-    "let x = [> 1, 2, 3]; x[987654321987654321]",
+    "let x = [> 1, 2, 3]; ignore(x[987654321987654321])",
     "Index out of bounds",
   );
   assertCompileError(
     "array_access_err8",
-    "let x = [> 1, 2, 3]; x[false]",
+    "let x = [> 1, 2, 3]; ignore(x[false])",
     "has type Bool but",
   );
   assertRun(
diff --git a/compiler/test/suites/basic_functionality.re b/compiler/test/suites/basic_functionality.re
index 4607d39675..9d3e1fd937 100644
--- a/compiler/test/suites/basic_functionality.re
+++ b/compiler/test/suites/basic_functionality.re
@@ -78,10 +78,10 @@ describe("basic functionality", ({test, testSkip}) => {
   assertSnapshot("binop6", "9 % 5");
   assertRunError(
     "division_by_zero",
-    "let nine = 9; nine / 0",
+    "let nine = 9; ignore(nine / 0)",
     "Division by zero",
   );
-  assertRunError("modulo_by_zero", "9 % 0", "Modulo by zero");
+  assertRunError("modulo_by_zero", "ignore(9 % 0)", "Modulo by zero");
   assertSnapshot("division1", "5 / 2");
   assertSnapshot("modulo1", "-17 % 4");
   assertSnapshot("modulo2", "17 % -4");
@@ -240,7 +240,7 @@ describe("basic functionality", ({test, testSkip}) => {
   assertRunError("fail1", "ignore(fail \"boo\")", "Failure: boo");
   assertRunError(
     "fail2",
-    "if (false) { 3 } else { fail \"boo\" }",
+    "ignore(if (false) { 3 } else { fail \"boo\" })",
     "Failure: boo",
   );
   assertSnapshotFile("toplevel_statements", "toplevelStatements");
diff --git a/compiler/test/suites/expressions.re b/compiler/test/suites/expressions.re
new file mode 100644
index 0000000000..9cb6759ba3
--- /dev/null
+++ b/compiler/test/suites/expressions.re
@@ -0,0 +1,60 @@
+open Grain_tests.TestFramework;
+open Grain_tests.Runner;
+
+let {describe} =
+  describeConfig |> withCustomMatchers(customMatchers) |> build;
+
+describe("expressions", ({test, testSkip}) => {
+  let assertNoWarning = makeNoWarningRunner(test);
+  let assertWarning = makeWarningRunner(test);
+
+  assertWarning(
+    "non_void_non_returning_expression1",
+    {|
+    1
+    print(2)
+    |},
+    Grain_utils.Warnings.StatementType,
+  );
+
+  assertWarning(
+    "non_void_non_returning_expression2",
+    {|
+    let f = () => {
+      1
+      print(2)
+    }
+    |},
+    Grain_utils.Warnings.StatementType,
+  );
+
+  assertNoWarning(
+    "non_void_non_returning_expression3",
+    {|
+    ignore(1)
+    print(2)
+    |},
+  );
+
+  assertNoWarning(
+    "non_void_non_returning_expression4",
+    {|
+    let f = () => {
+      ignore(1)
+      print(2)
+    }
+    |},
+  );
+
+  assertNoWarning(
+    "non_void_non_returning_expression5",
+    {|
+    let rec f = () => {
+      if (true) {
+        f()
+        void
+      }
+    }
+    |},
+  );
+});
diff --git a/compiler/test/suites/gc.re b/compiler/test/suites/gc.re
index 0d15556187..23be71ea22 100644
--- a/compiler/test/suites/gc.re
+++ b/compiler/test/suites/gc.re
@@ -43,6 +43,7 @@ describe("garbage collection", ({test, testSkip}) => {
   let assertMemoryLimitedFileRun = makeFileRunner(~num_pages=1, test_or_skip);
   let assertRunGC = (name, heapSize, prog, expected) =>
     makeRunner(
+      ~config_fn=() => {Grain_utils.Config.print_warnings := false},
       ~num_pages=1,
       ~max_pages=2,
       test_or_skip,
@@ -52,6 +53,7 @@ describe("garbage collection", ({test, testSkip}) => {
     );
   let assertRunGCError = (name, heapSize, prog, expected) =>
     makeErrorRunner(
+      ~config_fn=() => {Grain_utils.Config.print_warnings := false},
       test_or_skip,
       ~num_pages=1,
       ~max_pages=2,
diff --git a/compiler/test/suites/grainlsp.re b/compiler/test/suites/grainlsp.re
index c2f0fcf4e1..9c3bae9360 100644
--- a/compiler/test/suites/grainlsp.re
+++ b/compiler/test/suites/grainlsp.re
@@ -81,7 +81,7 @@ describe("grainlsp", ({test, testSkip}) => {
     "goto_definition1",
     "file:///a.gr",
     {|module A
-let func = x => x
+let func = x => print(x)
 func(1)
 |},
     lsp_input(
@@ -99,7 +99,7 @@ func(1)
     "goto_definition2",
     "file:///a.gr",
     {|module A
-let func = x => x
+let func = x => print(x)
 func(1)
 |},
     lsp_input(
@@ -118,15 +118,15 @@ func(1)
     make_test_utils_uri("a.gr"),
     {|module A
 from "./provideAll.gr" include ProvideAll
-ProvideAll.y(1)
+ignore(ProvideAll.y(1))
 |},
     lsp_input(
       "textDocument/definition",
-      lsp_text_document_position(make_test_utils_uri("a.gr"), 2, 11),
+      lsp_text_document_position(make_test_utils_uri("a.gr"), 2, 18),
     ),
     lsp_location_link(
       make_test_utils_uri("provideAll.gr"),
-      ((2, 0), (2, 12)),
+      ((2, 7), (2, 19)),
       ((3, 12), (3, 13)),
     ),
   );
@@ -269,7 +269,7 @@ let abc: T = { x: 1 }
     "code_action_add_function_label1",
     "file:///a.gr",
     {|module A
-let f = (x, y, z) => x ++ y ++ z
+let f = (x, y, z) => print(x ++ y ++ z)
 f("y", x="x", "z")
 |},
     lsp_input(
@@ -300,7 +300,7 @@ f("y", x="x", "z")
     "code_action_add_function_label2",
     "file:///a.gr",
     {|module A
-let f = (x, y, z) => x ++ y ++ z
+let f = (x, y, z) => print(x ++ y ++ z)
 f("y", x="x", "z")
 |},
     lsp_input(
@@ -331,7 +331,7 @@ f("y", x="x", "z")
     "code_action_add_function_label3",
     "file:///a.gr",
     {|module A
-let f = (x) => x
+let f = (x) => print(x)
 f(x="x")
 |},
     lsp_input(
@@ -506,7 +506,7 @@ from "./provideAll.gr" include ProvideAll
 record T { x: Number }
 let a = 1
 let b = 2 and c = 3
-"abc"
+print("abc")
 |},
     lsp_input(
       "textDocument/codeLens",
@@ -549,10 +549,7 @@ let b = 2 and c = 3
         ("range", lsp_range((4, 1), (4, 1))),
         (
           "command",
-          `Assoc([
-            ("title", `String("String")),
-            ("command", `String("")),
-          ]),
+          `Assoc([("title", `String("Void")), ("command", `String(""))]),
         ),
       ]),
     ]),
diff --git a/compiler/test/suites/linking.re b/compiler/test/suites/linking.re
index 9ff4975ce6..749820c4bd 100644
--- a/compiler/test/suites/linking.re
+++ b/compiler/test/suites/linking.re
@@ -23,7 +23,12 @@ describe("linking", ({test, testSkip}) => {
     {|from "list" include List; print(List.map(n => n + 1, [1, 2, 3]))|},
     "[2, 3, 4]\n",
   );
-  assertRun("link_issue_994_no_generated_code", {|0|}, "");
+  assertRun(
+    ~config_fn=() => {Grain_utils.Config.print_warnings := false},
+    "link_issue_994_no_generated_code",
+    {|0|},
+    "",
+  );
   assertRun(
     "link_issue_994_unexported_type",
     {|record Foo { foo: String }|},
diff --git a/compiler/test/suites/optimizations.re b/compiler/test/suites/optimizations.re
index f2041a3fba..30ef8c2cca 100644
--- a/compiler/test/suites/optimizations.re
+++ b/compiler/test/suites/optimizations.re
@@ -27,6 +27,7 @@ describe("optimizations", ({test, testSkip}) => {
       ) => {
     test(outfile, ({expect}) => {
       Config.preserve_all_configs(() => {
+        Config.print_warnings := false;
         switch (config_fn) {
         | None => ()
         | Some(fn) => fn()
@@ -64,7 +65,7 @@ describe("optimizations", ({test, testSkip}) => {
   );
   assertRun(
     "regression_no_elim_impure_call",
-    "let foo = (f) => { let g = print(f(5)); 5 }; foo(toString)",
+    "let foo = (f) => { let g = print(f(5)); 5 }; let _ = foo(toString)",
     "5\n",
   );
   assertAnf(
@@ -510,6 +511,7 @@ describe("optimizations", ({test, testSkip}) => {
   );
   // Binaryen optimizations disabled
   assertBinaryenOptimizationsDisabledFileRun(
+    ~config_fn=() => {Grain_utils.Config.print_warnings := false},
     "test_binaryen_optimizations_disabled",
     "toplevelStatements",
     "1\n2\n3\n4\n5\n",
@@ -524,8 +526,8 @@ describe("optimizations", ({test, testSkip}) => {
       from "runtime/unsafe/wasmi32" include WasmI32
       @disableGC
       provide let foo = (x, y, z) => {
-        Memory.incRef(WasmI32.fromGrain((+)))
-        Memory.incRef(WasmI32.fromGrain((+)))
+        let _ = Memory.incRef(WasmI32.fromGrain((+)))
+        let _ = Memory.incRef(WasmI32.fromGrain((+)))
         // x, y, and z will get decRef'd by `+`
         x + y + z
       }
diff --git a/compiler/test/suites/pattern_matching.re b/compiler/test/suites/pattern_matching.re
index 8171d7f0a0..ec53f3896e 100644
--- a/compiler/test/suites/pattern_matching.re
+++ b/compiler/test/suites/pattern_matching.re
@@ -403,7 +403,7 @@ describe("pattern matching", ({test, testSkip}) => {
         () => b
       }
 
-      run()
+      ignore(run())
     |},
     "2\n",
   );
diff --git a/compiler/test/suites/records.re b/compiler/test/suites/records.re
index c11947ddd7..57387931ec 100644
--- a/compiler/test/suites/records.re
+++ b/compiler/test/suites/records.re
@@ -244,7 +244,7 @@ describe("records", ({test, testSkip}) => {
     {|
       record A { field: Number }
       record B { field: Number }
-      (x: A) => x.field
+      let _ = (x: A) => x.field
     |},
   );
   assertNoWarning(
@@ -252,7 +252,7 @@ describe("records", ({test, testSkip}) => {
     {|
       record A { field: Number }
       record B { field: Number }
-      (x: B) => x.field
+      let _ = (x: B) => x.field
     |},
   );
   // well_formedness field omission warning
diff --git a/docs/contributor/memory_management.md b/docs/contributor/memory_management.md
index de54e0af51..5bd5bdbd05 100644
--- a/docs/contributor/memory_management.md
+++ b/docs/contributor/memory_management.md
@@ -142,8 +142,8 @@ When calling function from inside a GC-disabled function:
 // @disableGC-safe wrapper
 @disableGC
 let wasmSafeLength = (s: String) => {
-  Memory.incRef(WasmI32.fromGrain(length)) // <- incRef closure being invoked
-  Memory.incRef(WasmI32.fromGrain(s)) // <- incRef argument before call
+  let _ = Memory.incRef(WasmI32.fromGrain(length)) // <- incRef closure being invoked
+  let _ = Memory.incRef(WasmI32.fromGrain(s)) // <- incRef argument before call
   length(s)
 }
 ```
@@ -156,8 +156,8 @@ Before returning from a GC-disabled function which follows the Grain calling con
 export let rec sqrt = (x: Number) => {
   // ...
   let ret = ...
-  Memory.decRef(WasmI32.fromGrain(x))   // <- decrement argument
-  Memory.decRef(WasmI32.fromGrain(sqrt)) // <- decrement closure (note that this function needs to be recursive)
+  let _ = Memory.decRef(WasmI32.fromGrain(x))   // <- decrement argument
+  let _ = Memory.decRef(WasmI32.fromGrain(sqrt)) // <- decrement closure (note that this function needs to be recursive)
   ret
 }
 ```
diff --git a/stdlib/exception.gr b/stdlib/exception.gr
index d4c784f02c..5a0ecb4b15 100644
--- a/stdlib/exception.gr
+++ b/stdlib/exception.gr
@@ -46,6 +46,6 @@ provide let rec registerPrinter = (printer: Exception => Option<String>) => {
 
   // no need to increment refcount on f; we just don't decRef it at the end of the function
   Exception.printers = WasmI32.fromGrain((printer, Exception.printers))
-  Memory.decRef(WasmI32.fromGrain(registerPrinter))
+  let _ = Memory.decRef(WasmI32.fromGrain(registerPrinter))
   void
 }
diff --git a/stdlib/json.gr b/stdlib/json.gr
index ad6d40a5cc..3f78cb9a7c 100644
--- a/stdlib/json.gr
+++ b/stdlib/json.gr
@@ -1367,7 +1367,7 @@ let skipWhiteSpace = (parserState: JsonParserState) => {
     isInterTokenWhiteSpace(parserState.currentCodePoint) &&
     !isAtEndOfInput(parserState)
   ) {
-    next(parserState)
+    ignore(next(parserState))
     void
   }
 }
@@ -1423,7 +1423,7 @@ let expectCodePointAndAdvance = (
 ) => {
   let c = parserState.currentCodePoint
   if (c == expectedCodePoint) {
-    next(parserState)
+    ignore(next(parserState))
     None
   } else {
     let detail = "expected " ++
@@ -1569,7 +1569,7 @@ and parseString = (parserState: JsonParserState) => {
       while (true) {
         match (parserState.currentCodePoint) {
           0x22 => { // '"'
-            next(parserState)
+            ignore(next(parserState))
             break
           },
           -1 => { // EOF
@@ -1584,7 +1584,7 @@ and parseString = (parserState: JsonParserState) => {
             // Keep the starting position for better error reporting.
             let escapeStartPos = parserState.pos
 
-            next(parserState)
+            ignore(next(parserState))
 
             match (parserState.currentCodePoint) {
               0x22 => { // '"'
@@ -1625,7 +1625,7 @@ and parseString = (parserState: JsonParserState) => {
                 ignore(next(parserState))
               },
               0x75 => { // 'u' (start of hexadecimal UTF-16 escape sequence)
-                next(parserState)
+                ignore(next(parserState))
 
                 // The escape sequence can either be a standalone code point or
                 // a UTF-16 surrogate pair made of two code units that have to
@@ -1758,7 +1758,7 @@ and parseString = (parserState: JsonParserState) => {
               )
             }
             // Finally the happy case of a simple unescaped code point.
-            next(parserState)
+            ignore(next(parserState))
             Buffer.addCharFromCodePoint(c, buffer)
           },
         }
@@ -1918,11 +1918,11 @@ and parseArray = (parserState: JsonParserState) => {
               )
             }
             trailingComma = true
-            next(parserState)
+            ignore(next(parserState))
             skipWhiteSpace(parserState)
           },
           0x5D => { // ']'
-            next(parserState)
+            ignore(next(parserState))
             break
           },
           -1 => { // EOF
@@ -1989,7 +1989,7 @@ and parseObject = (parserState: JsonParserState) => {
               let detail = "unexpected trailing comma in object"
               return Err(buildUnexpectedTokenError(parserState, detail))
             }
-            next(parserState)
+            ignore(next(parserState))
             break
           },
           _ => {
diff --git a/stdlib/map.gr b/stdlib/map.gr
index 4ec222da92..974b8686b4 100644
--- a/stdlib/map.gr
+++ b/stdlib/map.gr
@@ -446,7 +446,7 @@ provide let toArray = (map: Map<a, b>) => {
     ignore(array)
     i + 1
   }
-  reduce(reducer, 0, map)
+  ignore(reduce(reducer, 0, map))
   array: Array<(a, b)>
 }
 
diff --git a/stdlib/marshal.gr b/stdlib/marshal.gr
index 2873bcfc83..76c0180d76 100644
--- a/stdlib/marshal.gr
+++ b/stdlib/marshal.gr
@@ -433,7 +433,7 @@ provide let marshal = value => {
   let size = size(valuePtr)
   let buf = allocateBytes(size)
   Memory.fill(buf + 8n, 0n, size)
-  marshal(valuePtr, buf + 8n)
+  let _ = marshal(valuePtr, buf + 8n)
   ignore(value)
   toGrain(buf): Bytes
 }
diff --git a/stdlib/runtime/atoi/parse.gr b/stdlib/runtime/atoi/parse.gr
index fd5f057816..0aa4cb4d8b 100644
--- a/stdlib/runtime/atoi/parse.gr
+++ b/stdlib/runtime/atoi/parse.gr
@@ -166,10 +166,10 @@ provide let parseInt = (string: String, radix: Number) => {
         valueBigInt = BI.makeWrappedUint64(prevValue * -1N)
         radixBigInt = BI.makeWrappedUint64(radix)
         let newvalue = BI.mul(valueBigInt, radixBigInt)
-        Memory.decRef(valueBigInt)
+        let _ = Memory.decRef(valueBigInt)
         valueBigInt = newvalue
         let newvalue = BI.addInt(valueBigInt, digit)
-        Memory.decRef(valueBigInt)
+        let _ = Memory.decRef(valueBigInt)
         valueBigInt = newvalue
       } else {
         use WasmI64.{ (-) }
@@ -185,10 +185,10 @@ provide let parseInt = (string: String, radix: Number) => {
       }
     } else {
       let newvalue = BI.mul(valueBigInt, radixBigInt)
-      Memory.decRef(valueBigInt)
+      let _ = Memory.decRef(valueBigInt)
       valueBigInt = newvalue
       let newvalue = BI.addInt(valueBigInt, digit)
-      Memory.decRef(valueBigInt)
+      let _ = Memory.decRef(valueBigInt)
       valueBigInt = newvalue
     }
   }
@@ -205,7 +205,7 @@ provide let parseInt = (string: String, radix: Number) => {
   // BigInt number is accumulated in positive form
   if (negative) {
     let newvalue = BI.negate(valueBigInt)
-    Memory.decRef(valueBigInt)
+    let _ = Memory.decRef(valueBigInt)
     return Ok(WasmI32.toGrain(newvalue))
   }
 
diff --git a/stdlib/runtime/bigint.gr b/stdlib/runtime/bigint.gr
index 458e69f35c..a27809aa28 100644
--- a/stdlib/runtime/bigint.gr
+++ b/stdlib/runtime/bigint.gr
@@ -842,7 +842,7 @@ provide let bigIntToString = (num: WasmI32, base: WasmI32) => {
             c = tmpInner % d
           }
         }
-        Memory.decRef(tmpCopy)
+        let _ = Memory.decRef(tmpCopy)
         tmp = trimNumberInPlace(tmp)
         result = [
           DS.tagChar(getDigit(WasmI32.wrapI64(WasmI64.remU(c, base)))),
@@ -1123,7 +1123,7 @@ provide let addInt = (num1: WasmI32, int: WasmI64) => {
     } else {
       unsignedSubInt(num1, int)
     }
-    negateInPlace(ret)
+    let _ = negateInPlace(ret)
     ret
   } else {
     if (int < 0N) {
@@ -1170,7 +1170,7 @@ provide let subInt = (num1: WasmI32, int: WasmI64) => {
     } else {
       unsignedAddInt(num1, int)
     }
-    negateInPlace(ret)
+    let _ = negateInPlace(ret)
     ret
   } else {
     if (int < 0N) {
@@ -1363,7 +1363,7 @@ provide let shrS = (num: WasmI32, places: WasmI32) => {
       }
       if (underflow) {
         let newRet = decr(ret)
-        Memory.decRef(ret)
+        let _ = Memory.decRef(ret)
         newRet
       } else {
         ret
@@ -1459,7 +1459,7 @@ provide let bitwiseNot = (num: WasmI32) => {
   // ~x == -x - 1
   let numNegated = negate(num)
   let result = decr(numNegated)
-  Memory.decRef(numNegated)
+  let _ = Memory.decRef(numNegated)
   result
 }
 
@@ -1475,11 +1475,11 @@ provide let bitwiseAnd = (num1: WasmI32, num2: WasmI32) => {
       // A & -B == A & ~(B-1)
       let num2Neg = negate(num2)
       let num2Sub1 = decr(num2Neg)
-      Memory.decRef(num2Neg)
+      let _ = Memory.decRef(num2Neg)
       let notNum2Sub1 = bitwiseNotUnsigned(num2Sub1)
-      Memory.decRef(num2Sub1)
+      let _ = Memory.decRef(num2Sub1)
       let combined = bitwiseAndPositive(num1, notNum2Sub1, 1n)
-      Memory.decRef(notNum2Sub1)
+      let _ = Memory.decRef(notNum2Sub1)
       combined
     }
   } else {
@@ -1487,11 +1487,11 @@ provide let bitwiseAnd = (num1: WasmI32, num2: WasmI32) => {
       // -A & B == ~(A-1) & B
       let num1Neg = negate(num1) // A
       let num1Sub1 = decr(num1Neg) // A-1
-      Memory.decRef(num1Neg)
+      let _ = Memory.decRef(num1Neg)
       let notNum1Sub1 = bitwiseNotUnsigned(num1Sub1) // ~(A-1)
-      Memory.decRef(num1Sub1)
+      let _ = Memory.decRef(num1Sub1)
       let combined = bitwiseAndPositive(notNum1Sub1, num2, 2n) // ~(A-1) & B
-      Memory.decRef(notNum1Sub1)
+      let _ = Memory.decRef(notNum1Sub1)
       combined
     } else {
       // -A & -B == -((A-1) | (B-1) + 1)
@@ -1501,11 +1501,11 @@ provide let bitwiseAnd = (num1: WasmI32, num2: WasmI32) => {
       let num2Sub1 = decr(num2Neg)
       let orResult = bitwiseOrPositive(num1Sub1, num2Sub1)
       let ret = incr(orResult)
-      Memory.decRef(num1Neg)
-      Memory.decRef(num2Neg)
-      Memory.decRef(num1Sub1)
-      Memory.decRef(num2Sub1)
-      Memory.decRef(orResult)
+      let _ = Memory.decRef(num1Neg)
+      let _ = Memory.decRef(num2Neg)
+      let _ = Memory.decRef(num1Sub1)
+      let _ = Memory.decRef(num2Sub1)
+      let _ = Memory.decRef(orResult)
       // avoid extra allocation on negate()
       setFlag(ret, _IS_NEGATIVE, 1n)
       ret
@@ -1526,14 +1526,14 @@ provide let bitwiseOr = (num1: WasmI32, num2: WasmI32) => {
       // A | -B == -(((B-1) & ~A) + 1)
       let num2Neg = negate(num2) // B
       let num2Sub1 = decr(num2Neg) // B-1
-      Memory.decRef(num2Neg)
+      let _ = Memory.decRef(num2Neg)
       let notNum1 = bitwiseNotUnsigned(num1) // ~A
       let retSub1 = bitwiseAndPositive(notNum1, num2Sub1, 2n) // (B-1) & ~A
-      Memory.decRef(num2Sub1)
-      Memory.decRef(notNum1)
+      let _ = Memory.decRef(num2Sub1)
+      let _ = Memory.decRef(notNum1)
       let ret = incr(retSub1)
-      Memory.decRef(retSub1)
-      negateInPlace(ret)
+      let _ = Memory.decRef(retSub1)
+      let _ = negateInPlace(ret)
       ret
     }
   } else {
@@ -1541,14 +1541,14 @@ provide let bitwiseOr = (num1: WasmI32, num2: WasmI32) => {
       // A | -B == -(((A-1) & ~B) + 1)
       let num1Neg = negate(num1) // A
       let num1Sub1 = decr(num1Neg) // A-1
-      Memory.decRef(num1Neg)
+      let _ = Memory.decRef(num1Neg)
       let notNum2 = bitwiseNotUnsigned(num2) // ~B
       let retSub1 = bitwiseAndPositive(num1Sub1, notNum2, 1n) // (A-1) & ~B
-      Memory.decRef(num1Sub1)
-      Memory.decRef(notNum2)
+      let _ = Memory.decRef(num1Sub1)
+      let _ = Memory.decRef(notNum2)
       let ret = incr(retSub1)
-      Memory.decRef(retSub1)
-      negateInPlace(ret)
+      let _ = Memory.decRef(retSub1)
+      let _ = negateInPlace(ret)
       ret
     } else {
       // -A | -B == -((A-1) & (B-1) + 1)
@@ -1558,11 +1558,11 @@ provide let bitwiseOr = (num1: WasmI32, num2: WasmI32) => {
       let num2Sub1 = decr(num2Neg) // (B-1)
       let andResult = bitwiseAndPositive(num1Sub1, num2Sub1, 0n) // (A-1) & (B-1)
       let ret = incr(andResult) // ((A-1) & (B-1)) + 1
-      Memory.decRef(num1Neg)
-      Memory.decRef(num2Neg)
-      Memory.decRef(num1Sub1)
-      Memory.decRef(num2Sub1)
-      Memory.decRef(andResult)
+      let _ = Memory.decRef(num1Neg)
+      let _ = Memory.decRef(num2Neg)
+      let _ = Memory.decRef(num1Sub1)
+      let _ = Memory.decRef(num2Sub1)
+      let _ = Memory.decRef(andResult)
       // avoid extra allocation on negate()
       setFlag(ret, _IS_NEGATIVE, 1n)
       ret
@@ -1583,11 +1583,11 @@ provide let bitwiseXor = (num1: WasmI32, num2: WasmI32) => {
       // A ^ -B == A ^ (B-1)+1
       let num2Neg = negate(num2) // B
       let num2Sub1 = decr(num2Neg) // B-1
-      Memory.decRef(num2Neg)
+      let _ = Memory.decRef(num2Neg)
       let retSub1 = bitwiseXorPositive(num2Sub1, num1) // (A^(B-1))
-      Memory.decRef(num2Sub1)
+      let _ = Memory.decRef(num2Sub1)
       let ret = incr(retSub1)
-      Memory.decRef(retSub1)
+      let _ = Memory.decRef(retSub1)
       // avoid extra allocation on negate()
       setFlag(ret, _IS_NEGATIVE, 1n)
       ret
@@ -1597,11 +1597,11 @@ provide let bitwiseXor = (num1: WasmI32, num2: WasmI32) => {
       // -A ^ B == (B^(A-1))+1
       let num1Neg = negate(num1) // A
       let num1Sub1 = decr(num1Neg) // A-1
-      Memory.decRef(num1Neg)
+      let _ = Memory.decRef(num1Neg)
       let retSub1 = bitwiseXorPositive(num1Sub1, num2) // (B^(A-1))
-      Memory.decRef(num1Sub1)
+      let _ = Memory.decRef(num1Sub1)
       let ret = incr(retSub1)
-      Memory.decRef(retSub1)
+      let _ = Memory.decRef(retSub1)
       // avoid extra allocation on negate()
       setFlag(ret, _IS_NEGATIVE, 1n)
       ret
@@ -1612,10 +1612,10 @@ provide let bitwiseXor = (num1: WasmI32, num2: WasmI32) => {
       let num1Sub1 = decr(num1Neg)
       let num2Sub1 = decr(num2Neg)
       let ret = bitwiseXorPositive(num1Sub1, num2Sub1)
-      Memory.decRef(num1Neg)
-      Memory.decRef(num2Neg)
-      Memory.decRef(num1Sub1)
-      Memory.decRef(num2Sub1)
+      let _ = Memory.decRef(num1Neg)
+      let _ = Memory.decRef(num2Neg)
+      let _ = Memory.decRef(num1Sub1)
+      let _ = Memory.decRef(num2Sub1)
       ret
     }
   }
@@ -1691,8 +1691,8 @@ provide let gcd = (num1: WasmI32, num2: WasmI32) => {
   let k = minu32(i, j)
   let mut newu = shrS(u, i)
   let mut newv = shrS(v, j)
-  Memory.decRef(u)
-  Memory.decRef(v)
+  let _ = Memory.decRef(u)
+  let _ = Memory.decRef(v)
   u = newu
   v = newv
   while (true) {
@@ -1702,13 +1702,13 @@ provide let gcd = (num1: WasmI32, num2: WasmI32) => {
       u = tmp
     }
     newv = sub(v, u)
-    Memory.decRef(v)
+    let _ = Memory.decRef(v)
     v = newv
     if (eqz(v)) {
       return shl(u, k)
     }
     newv = shrS(v, countTrailingZeroBits(v))
-    Memory.decRef(v)
+    let _ = Memory.decRef(v)
     v = newv
   }
   return 0n
@@ -1750,7 +1750,7 @@ let baseCaseDivRem = (a: WasmI32, b: WasmI32, result: WasmI32) => {
     // (clone for sane reference management)
     a = clone(aOrig)
   }
-  Memory.decRef(bTimesBetaM)
+  let _ = Memory.decRef(bTimesBetaM)
   for (let mut j = m - 1n; j >= 0n; j -= 1n) {
     use WasmI64.{ divU as (/), (|), (<<) }
     let anjBeta = WasmI64.extendI32U(getHalfLimb(a, n + j)) << 32N // a_{n+j}\beta
@@ -1761,17 +1761,17 @@ let baseCaseDivRem = (a: WasmI32, b: WasmI32, result: WasmI32) => {
     let bTimesBetaJ = shl(b, j * 32n) // b * \beta^j == b * (2^32)^j == b*2^(32*j)
     let qjWrapped = makeWrappedUint32(qj)
     let qjTimesBTimesBetaJ = mul(bTimesBetaJ, qjWrapped)
-    Memory.decRef(qjWrapped)
+    let _ = Memory.decRef(qjWrapped)
     let anew = sub(a, qjTimesBTimesBetaJ)
-    Memory.decRef(a)
+    let _ = Memory.decRef(a)
     a = anew
     while (flagIsSet(a, _IS_NEGATIVE)) {
       qj -= 1n
       let anew = add(a, bTimesBetaJ)
-      Memory.decRef(a)
+      let _ = Memory.decRef(a)
       a = anew
     }
-    Memory.decRef(bTimesBetaJ)
+    let _ = Memory.decRef(bTimesBetaJ)
     setHalfLimb(q, j, qj)
   }
   WasmI32.store(result, trimNumberInPlace(q), 0n) // Q := q
@@ -1792,11 +1792,11 @@ let baseCaseDivRemUnnormalized = (a: WasmI32, b: WasmI32, result: WasmI32) => {
     let anew = shl(a, k)
     let bnew = shl(b, k)
     baseCaseDivRem(anew, bnew, result)
-    Memory.decRef(anew)
-    Memory.decRef(bnew)
+    let _ = Memory.decRef(anew)
+    let _ = Memory.decRef(bnew)
     let rold = WasmI32.load(result, 4n)
     let rnew = shrS(rold, k)
-    Memory.decRef(rold)
+    let _ = Memory.decRef(rold)
     WasmI32.store(result, rnew, 4n) // R := R' / 2^k
   } else {
     baseCaseDivRem(a, b, result)
@@ -1846,8 +1846,8 @@ let division = (
     let num1abs = abs(num1)
     let num2abs = abs(num2)
     baseCaseDivRemUnnormalized(num1abs, num2abs, result)
-    Memory.decRef(num1abs)
-    Memory.decRef(num2abs)
+    let _ = Memory.decRef(num1abs)
+    let _ = Memory.decRef(num2abs)
     q = WasmI32.load(result, 0n)
     r = WasmI32.load(result, 4n)
     Memory.free(result)
@@ -1877,9 +1877,9 @@ let division = (
     )
   ) {
     let newr = add(r, num2)
-    Memory.decRef(r)
+    let _ = Memory.decRef(r)
     let newq = decr(q)
-    Memory.decRef(q)
+    let _ = Memory.decRef(q)
     r = newr
     q = newq
   }
diff --git a/stdlib/runtime/debugPrint.gr b/stdlib/runtime/debugPrint.gr
index 194a7d1af2..eec9b0a150 100644
--- a/stdlib/runtime/debugPrint.gr
+++ b/stdlib/runtime/debugPrint.gr
@@ -24,7 +24,7 @@ provide let print = (s: String) => {
   WasmI32.store8(lf, 10n, 0n)
   WasmI32.store(iov, lf, 8n)
   WasmI32.store(iov, 1n, 12n)
-  fd_write(1n, iov, 2n, written)
+  let _ = fd_write(1n, iov, 2n, written)
   Memory.free(buf)
   void
 }
diff --git a/stdlib/runtime/exception.gr b/stdlib/runtime/exception.gr
index e0a35e7fb6..cf89ba38d9 100644
--- a/stdlib/runtime/exception.gr
+++ b/stdlib/runtime/exception.gr
@@ -83,7 +83,7 @@ provide let panic = (msg: String) => {
   WasmI32.store8(lf, 10n, 0n)
   WasmI32.store(iov, lf, 8n)
   WasmI32.store(iov, 1n, 12n)
-  fd_write(2n, iov, 2n, written)
+  let _ = fd_write(2n, iov, 2n, written)
   unreachable()
 }
 
diff --git a/stdlib/runtime/gc.gr b/stdlib/runtime/gc.gr
index a9c764ef01..2a09a4895e 100644
--- a/stdlib/runtime/gc.gr
+++ b/stdlib/runtime/gc.gr
@@ -96,7 +96,7 @@ let rec decRef = (userPtr: WasmI32, ignoreZeros: Bool) => {
       setRefCount(userPtr, refCount)
 
       if (WasmI32.eqz(refCount)) {
-        decRefChildren(userPtr)
+        let _ = decRefChildren(userPtr)
         free(userPtr)
       }
 
diff --git a/stdlib/runtime/numbers.gr b/stdlib/runtime/numbers.gr
index 8c9b95d216..f52bf96767 100644
--- a/stdlib/runtime/numbers.gr
+++ b/stdlib/runtime/numbers.gr
@@ -271,7 +271,7 @@ let reducedBigInteger = x => {
     //             the original input is no longer used after
     //             this function returns.
     let ret = reducedInteger(BI.toInt64(x))
-    Memory.decRef(x)
+    let _ = Memory.decRef(x)
     ret
   } else {
     x
@@ -305,23 +305,23 @@ let reducedFractionBigInt = (x, y, keepRational) => {
   let ret = if (!keepRational && BI.eqz(r)) {
     // if remainder is zero, then return the quotient.
     // We decRef the remainder, since we no longer need it
-    Memory.decRef(r)
+    let _ = Memory.decRef(r)
     reducedBigInteger(q)
   } else {
     // remainder is nonzero. we don't need the quotient and
     // remainder anymore, so we discard them.
-    Memory.decRef(q)
-    Memory.decRef(r)
+    let _ = Memory.decRef(q)
+    let _ = Memory.decRef(r)
     let factor = BI.gcd(x, y)
     let xdiv = BI.div(x, factor)
     let ydiv = BI.div(y, factor)
     let ret = newRational(xdiv, ydiv)
-    Memory.decRef(factor)
+    let _ = Memory.decRef(factor)
     ret
   }
   if (needsDecref) {
-    Memory.decRef(x)
-    Memory.decRef(y)
+    let _ = Memory.decRef(x)
+    let _ = Memory.decRef(y)
     void
   }
   ret
@@ -602,7 +602,7 @@ let coerceNumberToBigInt = (x: Number) => {
         BI.makeWrappedInt64(boxedInt64Number(xVal))
       },
       t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
-        Memory.incRef(xVal)
+        let _ = Memory.incRef(xVal)
         xVal
       },
       _ => {
@@ -890,8 +890,8 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
           } else {
             BI.add(xBig, yBig)
           }
-          Memory.decRef(xBig)
-          Memory.decRef(yBig)
+          let _ = Memory.decRef(xBig)
+          let _ = Memory.decRef(yBig)
           reducedBigInteger(res)
         } else {
           reducedInteger(result)
@@ -901,7 +901,7 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
         // Promote x to bigint and do operation
         let xBig = BI.makeWrappedInt32(xval)
         let result = if (isSub) BI.sub(xBig, y) else BI.add(xBig, y)
-        Memory.decRef(xBig)
+        let _ = Memory.decRef(xBig)
         reducedBigInteger(result)
       },
       t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
@@ -909,14 +909,14 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
         let yNumerator = boxedRationalNumerator(y)
         let yDenominator = boxedRationalDenominator(y)
         let expandedXNumerator = BI.mul(xBig, yDenominator)
-        Memory.decRef(xBig)
+        let _ = Memory.decRef(xBig)
         let result = if (isSub)
           BI.sub(expandedXNumerator, yNumerator)
         else
           BI.add(expandedXNumerator, yNumerator)
         let ret = reducedFractionBigInt(result, yDenominator, false)
-        Memory.decRef(expandedXNumerator)
-        Memory.decRef(result)
+        let _ = Memory.decRef(expandedXNumerator)
+        let _ = Memory.decRef(result)
         ret
       },
       t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
@@ -948,8 +948,8 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
       } else {
         BI.add(xBig, yBig)
       }
-      Memory.decRef(xBig)
-      Memory.decRef(yBig)
+      let _ = Memory.decRef(xBig)
+      let _ = Memory.decRef(yBig)
       reducedBigInteger(res)
     } else {
       reducedInteger(result)
@@ -973,8 +973,8 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
           } else {
             BI.add(xBig, yBig)
           }
-          Memory.decRef(xBig)
-          Memory.decRef(yBig)
+          let _ = Memory.decRef(xBig)
+          let _ = Memory.decRef(yBig)
           reducedBigInteger(res)
         } else {
           reducedInteger(result)
@@ -984,7 +984,7 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
         // Promote x to bigint and do operation
         let xBig = BI.makeWrappedInt64(xval)
         let result = if (isSub) BI.sub(xBig, y) else BI.add(xBig, y)
-        Memory.decRef(xBig)
+        let _ = Memory.decRef(xBig)
         reducedBigInteger(result)
       },
       t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
@@ -992,14 +992,14 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
         let yNumerator = boxedRationalNumerator(y)
         let yDenominator = boxedRationalDenominator(y)
         let expandedXNumerator = BI.mul(xBig, yDenominator)
-        Memory.decRef(xBig)
+        let _ = Memory.decRef(xBig)
         let result = if (isSub)
           BI.sub(expandedXNumerator, yNumerator)
         else
           BI.add(expandedXNumerator, yNumerator)
         let ret = reducedFractionBigInt(result, yDenominator, false)
-        Memory.decRef(expandedXNumerator)
-        Memory.decRef(result)
+        let _ = Memory.decRef(expandedXNumerator)
+        let _ = Memory.decRef(result)
         ret
       },
       t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
@@ -1020,7 +1020,7 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
 let numberAddSubFloat64Help = (xval, y, isSub) => {
   use WasmF64.{ (+), (-) }
   // incRef y to reuse it via WasmI32.toGrain
-  Memory.incRef(y)
+  let _ = Memory.incRef(y)
   let yval = coerceNumberToWasmF64(WasmI32.toGrain(y): Number)
   let result = if (isSub) xval - yval else xval + yval
   newFloat64(result)
@@ -1036,7 +1036,7 @@ let numberAddSubBigIntHelp = (x, y, isSub) => {
     } else {
       BI.add(x, yBig)
     }
-    Memory.decRef(yBig)
+    let _ = Memory.decRef(yBig)
     reducedBigInteger(res)
   } else {
     let yBoxedNumberTag = boxedNumberTag(y)
@@ -1049,7 +1049,7 @@ let numberAddSubBigIntHelp = (x, y, isSub) => {
         } else {
           BI.add(x, yBig)
         }
-        Memory.decRef(yBig)
+        let _ = Memory.decRef(yBig)
         reducedBigInteger(res)
       },
       t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
@@ -1068,9 +1068,9 @@ let numberAddSubBigIntHelp = (x, y, isSub) => {
           BI.sub(expandedXNumerator, yNumerator)
         else
           BI.add(expandedXNumerator, yNumerator)
-        Memory.decRef(expandedXNumerator)
+        let _ = Memory.decRef(expandedXNumerator)
         let ret = reducedFractionBigInt(result, yDenominator, false)
-        Memory.decRef(result)
+        let _ = Memory.decRef(result)
         ret
       },
       t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
@@ -1099,7 +1099,7 @@ provide let addSubRational = (x, y, isSub, keepRational) => {
     else
       BI.add(xNumerator, yNumerator)
     let ret = reducedFractionBigInt(newNumerator, xDenominator, keepRational)
-    Memory.decRef(newNumerator)
+    let _ = Memory.decRef(newNumerator)
     ret
   } else {
     let numerator1 = BI.mul(xNumerator, yDenominator)
@@ -1110,9 +1110,9 @@ provide let addSubRational = (x, y, isSub, keepRational) => {
       BI.add(numerator1, numerator2)
     let denominator = BI.mul(xDenominator, yDenominator)
     let ret = reducedFractionBigInt(numerator, denominator, keepRational)
-    Memory.decRef(numerator1)
-    Memory.decRef(numerator2)
-    Memory.decRef(numerator)
+    let _ = Memory.decRef(numerator1)
+    let _ = Memory.decRef(numerator2)
+    let _ = Memory.decRef(numerator)
     ret
   }
 }
@@ -1182,7 +1182,7 @@ provide let rationalNumerator = (x: Rational) => {
   let xVal = WasmI32.fromGrain(x)
   let num = boxedRationalNumerator(xVal)
   ignore(x)
-  Memory.incRef(num)
+  let _ = Memory.incRef(num)
   WasmI32.toGrain(reducedBigInteger(num)): Number
 }
 
@@ -1199,7 +1199,7 @@ provide let rationalDenominator = (x: Rational) => {
   let xVal = WasmI32.fromGrain(x)
   let num = boxedRationalDenominator(xVal)
   ignore(x)
-  Memory.incRef(num)
+  let _ = Memory.incRef(num)
   WasmI32.toGrain(reducedBigInteger(num)): Number
 }
 
@@ -1215,10 +1215,10 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
       BI.sub(xNumerator, expandedYNumerator)
     else
       BI.add(xNumerator, expandedYNumerator)
-    Memory.decRef(expandedYNumerator)
-    Memory.decRef(yBig)
+    let _ = Memory.decRef(expandedYNumerator)
+    let _ = Memory.decRef(yBig)
     let ret = reducedFractionBigInt(result, xDenominator, false)
-    Memory.decRef(result)
+    let _ = Memory.decRef(result)
     ret
   } else {
     let ytag = boxedNumberTag(y)
@@ -1230,14 +1230,14 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
       t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
         let yBig = BI.makeWrappedInt64(boxedInt64Number(y))
         let expandedYNumerator = BI.mul(yBig, xDenominator)
-        Memory.decRef(yBig)
+        let _ = Memory.decRef(yBig)
         let result = if (isSub)
           BI.sub(xNumerator, expandedYNumerator)
         else
           BI.add(xNumerator, expandedYNumerator)
         let ret = reducedFractionBigInt(result, xDenominator, false)
-        Memory.decRef(expandedYNumerator)
-        Memory.decRef(result)
+        let _ = Memory.decRef(expandedYNumerator)
+        let _ = Memory.decRef(result)
         ret
       },
       t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
@@ -1246,9 +1246,9 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
           BI.sub(xNumerator, expandedYNumerator)
         else
           BI.add(xNumerator, expandedYNumerator)
-        Memory.decRef(expandedYNumerator)
+        let _ = Memory.decRef(expandedYNumerator)
         let ret = reducedFractionBigInt(result, xDenominator, false)
-        Memory.decRef(result)
+        let _ = Memory.decRef(result)
         ret
       },
       t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
@@ -1318,8 +1318,8 @@ let safeI64Multiply = (x, y) => {
       let xBig = BI.makeWrappedInt64(x)
       let yBig = BI.makeWrappedInt64(y)
       let result = BI.mul(xBig, yBig)
-      Memory.decRef(xBig)
-      Memory.decRef(yBig)
+      let _ = Memory.decRef(xBig)
+      let _ = Memory.decRef(yBig)
       result
     } else {
       reducedInteger(prod)
@@ -1355,7 +1355,7 @@ let numberTimesDivideInt64Help = (xval, y, isDivide) => {
         } else {
           reducedBigInteger(BI.mul(xBig, y))
         }
-        Memory.decRef(xBig)
+        let _ = Memory.decRef(xBig)
         ret
       },
       t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
@@ -1366,16 +1366,16 @@ let numberTimesDivideInt64Help = (xval, y, isDivide) => {
           // x / (a / b) == (x * b) / a
           let numerator = BI.mul(xBig, yDenominator)
           let ret = reducedFractionBigInt(numerator, yNumerator, false)
-          Memory.decRef(numerator)
+          let _ = Memory.decRef(numerator)
           ret
         } else {
           // x * (a / b) == (x * a) / b
           let numerator = BI.mul(xBig, yNumerator)
           let ret = reducedFractionBigInt(numerator, yDenominator, false)
-          Memory.decRef(numerator)
+          let _ = Memory.decRef(numerator)
           ret
         }
-        Memory.decRef(xBig)
+        let _ = Memory.decRef(xBig)
         ret
       },
       t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
@@ -1404,7 +1404,7 @@ let numberTimesDivideBigIntHelp = (x, y, isDivide) => {
     } else {
       reducedBigInteger(BI.mul(x, yBig))
     }
-    Memory.decRef(yBig)
+    let _ = Memory.decRef(yBig)
     ret
   } else {
     let yBoxedNumberTag = boxedNumberTag(y)
@@ -1417,7 +1417,7 @@ let numberTimesDivideBigIntHelp = (x, y, isDivide) => {
         } else {
           reducedBigInteger(BI.mul(x, yBig))
         }
-        Memory.decRef(yBig)
+        let _ = Memory.decRef(yBig)
         ret
       },
       t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
@@ -1434,13 +1434,13 @@ let numberTimesDivideBigIntHelp = (x, y, isDivide) => {
           // x / (a / b) == (x * b) / a
           let numerator = BI.mul(x, yDenominator)
           let ret = reducedFractionBigInt(numerator, yNumerator, false)
-          Memory.decRef(numerator)
+          let _ = Memory.decRef(numerator)
           ret
         } else {
           // x * (a / b) == (x * a) / b
           let numerator = BI.mul(x, yNumerator)
           let ret = reducedFractionBigInt(numerator, yDenominator, false)
-          Memory.decRef(numerator)
+          let _ = Memory.decRef(numerator)
           ret
         }
       },
@@ -1480,17 +1480,17 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
       // (a / b) / y == a / (b * y)
       let denominator = BI.mul(xDenominator, yBig)
       let ret = reducedFractionBigInt(xNumerator, denominator, false)
-      Memory.decRef(denominator)
+      let _ = Memory.decRef(denominator)
       ret
     } else {
       // (a / b) * y == (a * y) / b
       let numerator = BI.mul(xNumerator, yBig)
       let ret = reducedFractionBigInt(numerator, xDenominator, false)
-      Memory.decRef(numerator)
+      let _ = Memory.decRef(numerator)
       ret
     }
     if (yBig != ret) {
-      Memory.decRef(yBig)
+      let _ = Memory.decRef(yBig)
       void
     }
     ret
@@ -1504,16 +1504,16 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
           // (a / b) / y == a / (b * y)
           let denominator = BI.mul(xDenominator, yBig)
           let ret = reducedFractionBigInt(xNumerator, denominator, false)
-          Memory.decRef(denominator)
+          let _ = Memory.decRef(denominator)
           ret
         } else {
           // (a / b) * y == (a * y) / b
           let numerator = BI.mul(xNumerator, yBig)
           let ret = reducedFractionBigInt(numerator, xDenominator, false)
-          Memory.decRef(numerator)
+          let _ = Memory.decRef(numerator)
           ret
         }
-        Memory.decRef(yBig)
+        let _ = Memory.decRef(yBig)
         ret
       },
       t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
@@ -1521,13 +1521,13 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
           // (a / b) / y == a / (b * y)
           let denominator = BI.mul(xDenominator, y)
           let ret = reducedFractionBigInt(xNumerator, denominator, false)
-          Memory.decRef(denominator)
+          let _ = Memory.decRef(denominator)
           ret
         } else {
           // (a / b) * y == (a * y) / b
           let numerator = BI.mul(xNumerator, y)
           let ret = reducedFractionBigInt(numerator, xDenominator, false)
-          Memory.decRef(numerator)
+          let _ = Memory.decRef(numerator)
           ret
         }
       },
@@ -1555,7 +1555,7 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
 let numberTimesDivideFloat64Help = (x, y, isDivide) => {
   use WasmF64.{ (/), (*) }
   // incRef y to reuse it via WasmI32.toGrain
-  Memory.incRef(y)
+  let _ = Memory.incRef(y)
   let yAsFloat = coerceNumberToWasmF64(WasmI32.toGrain(y): Number)
   if (isDivide) {
     newFloat64(x / yAsFloat)
@@ -1615,8 +1615,8 @@ let i64abs = x => {
 let numberMod = (x, y) => {
   use WasmI64.{ (!=), (-), (*), (<), (>), (^) }
   // incRef x and y to reuse them via WasmI32.toGrain
-  Memory.incRef(x)
-  Memory.incRef(y)
+  let _ = Memory.incRef(x)
+  let _ = Memory.incRef(y)
   if (isFloat(x) || isFloat(y) || isRational(x) || isRational(y)) {
     use WasmF64.{ (==), (/), (*), (-) }
     let xval = coerceNumberToWasmF64(WasmI32.toGrain(x): Number)
@@ -1681,7 +1681,7 @@ let cmpBigInt = (x: WasmI32, y: WasmI32) => {
       t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
         let tmp = BI.mul(x, boxedRationalDenominator(y))
         let ret = BI.cmp(tmp, boxedRationalNumerator(y))
-        Memory.decRef(tmp)
+        let _ = Memory.decRef(tmp)
         ret
       },
       t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
@@ -2131,11 +2131,11 @@ provide let (&) = (value1: Number, value2: Number) => {
     let ret = WasmI32.toGrain(reducedBigInteger(BI.bitwiseAnd(xval, yval))):
       Number
     if (!(xw32 == xval)) {
-      Memory.decRef(xval)
+      let _ = Memory.decRef(xval)
       void
     }
     if (!(yw32 == yval)) {
-      Memory.decRef(yval)
+      let _ = Memory.decRef(yval)
       void
     }
     ret
@@ -2171,11 +2171,11 @@ provide let (|) = (value1: Number, value2: Number) => {
     let ret = WasmI32.toGrain(reducedBigInteger(BI.bitwiseOr(xval, yval))):
       Number
     if (!(xw32 == xval)) {
-      Memory.decRef(xval)
+      let _ = Memory.decRef(xval)
       void
     }
     if (!(yw32 == yval)) {
-      Memory.decRef(yval)
+      let _ = Memory.decRef(yval)
       void
     }
     ret
@@ -2212,11 +2212,11 @@ provide let (^) = (value1: Number, value2: Number) => {
     let ret = WasmI32.toGrain(reducedBigInteger(BI.bitwiseXor(xval, yval))):
       Number
     if (!(xw32 == xval)) {
-      Memory.decRef(xval)
+      let _ = Memory.decRef(xval)
       void
     }
     if (!(yw32 == yval)) {
-      Memory.decRef(yval)
+      let _ = Memory.decRef(yval)
       void
     }
     ret
@@ -2430,11 +2430,11 @@ provide let coerceNumberToInt64 = (number: Number) => {
     boxedNumberTag(x) == Tags._GRAIN_INT64_BOXED_NUM_TAG
   ) {
     // avoid extra malloc and prevent x from being freed
-    Memory.incRef(x)
+    let _ = Memory.incRef(x)
     x
   } else {
     // incRef x to reuse it via WasmI32.toGrain
-    Memory.incRef(x)
+    let _ = Memory.incRef(x)
     newInt64(coerceNumberToWasmI64(WasmI32.toGrain(x): Number))
   }
   ignore(number)
@@ -2471,11 +2471,11 @@ provide let coerceNumberToRational = (number: Number) => {
     let tag = boxedNumberTag(x)
     if (tag == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) {
       // avoid extra malloc and prevent x from being freed
-      Memory.incRef(x)
+      let _ = Memory.incRef(x)
       x
     } else if (tag == Tags._GRAIN_INT64_BOXED_NUM_TAG) {
       // incRef x to reuse it via WasmI32.toGrain
-      Memory.incRef(x)
+      let _ = Memory.incRef(x)
       newRational(
         BI.makeWrappedInt32(coerceNumberToWasmI32(WasmI32.toGrain(x): Number)),
         BI.makeWrappedInt32(1n)
@@ -2518,11 +2518,11 @@ provide let coerceNumberToFloat64 = (number: Number) => {
     boxedNumberTag(x) == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG
   ) {
     // avoid extra malloc and prevent x from being freed
-    Memory.incRef(x)
+    let _ = Memory.incRef(x)
     x
   } else {
     // incRef x to reuse it via WasmI32.toGrain
-    Memory.incRef(x)
+    let _ = Memory.incRef(x)
     newFloat64(coerceNumberToWasmF64(WasmI32.toGrain(x): Number))
   }
   ignore(number)
@@ -2630,7 +2630,7 @@ provide let coerceBigIntToNumber = (num: BigInt) => {
   let x = WasmI32.fromGrain(num)
   // reducedBigInteger assumes that the bigint is dead,
   // but in our case, it is not
-  Memory.incRef(x)
+  let _ = Memory.incRef(x)
   let result = WasmI32.toGrain(reducedBigInteger(x)): Number
   ignore(num)
   result
@@ -2654,7 +2654,7 @@ provide let coerceRationalToNumber = (rational: Rational) => {
     x
   }
   // incRef x to reuse it via WasmI32.toGrain
-  Memory.incRef(x)
+  let _ = Memory.incRef(x)
   let result = WasmI32.toGrain(x): Number
   ignore(rational)
   result
@@ -2689,7 +2689,7 @@ provide let coerceFloat32ToNumber = (float: Float32) => {
 provide let coerceFloat64ToNumber = (float: Float64) => {
   let x = WasmI32.fromGrain(float)
   // incRef x to reuse it via WasmI32.toGrain
-  Memory.incRef(x)
+  let _ = Memory.incRef(x)
   let result = WasmI32.toGrain(x): Number
   ignore(float)
   result
@@ -2713,7 +2713,7 @@ let convertInexactToExactHelp = x => {
       tag == Tags._GRAIN_BIGINT_BOXED_NUM_TAG ||
       tag == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG
     ) {
-      Memory.incRef(x)
+      let _ = Memory.incRef(x)
       x
     } else {
       match (tag) {
@@ -3296,11 +3296,11 @@ provide let (**) = (base, power) => {
   } else if (isRational(basePtr) && isInteger(powerPtr)) {
     // Apply expBySquaring to numerator and denominator
     let numerator = WasmI32.fromGrain(base)
-    Memory.incRef(numerator)
+    let _ = Memory.incRef(numerator)
     let numerator = WasmI32.toGrain(numerator): Rational
     let numerator = rationalNumerator(numerator)
     let denominator = WasmI32.fromGrain(base)
-    Memory.incRef(denominator)
+    let _ = Memory.incRef(denominator)
     let denominator = WasmI32.toGrain(denominator): Rational
     let denominator = rationalDenominator(denominator)
     let numerator = if (power < 0)
diff --git a/stdlib/runtime/string.gr b/stdlib/runtime/string.gr
index 630df21284..2e14e5bebe 100644
--- a/stdlib/runtime/string.gr
+++ b/stdlib/runtime/string.gr
@@ -195,7 +195,7 @@ let getFieldArray = (fields, arity) => {
   for (let mut i = 0n; i < arity; i += 1n) {
     let fieldLength = WasmI32.load(fields + fieldOffset, 4n)
     let fieldName = allocateString(fieldLength)
-    Memory.incRef(fieldName)
+    let _ = Memory.incRef(fieldName)
     Memory.copy(fieldName + 8n, fields + fieldOffset + 8n, fieldLength)
     WasmI32.store(fieldArray + i * 4n, fieldName, 8n)
 
@@ -451,7 +451,7 @@ let rec heapValueToString = (ptr, extraIndents, toplevel, cycles) => {
   match (tag) {
     t when t == Tags._GRAIN_STRING_HEAP_TAG => {
       // In both cases, we incRef ptr so we can use it again via WasmI32.toGrain
-      Memory.incRef(ptr)
+      let _ = Memory.incRef(ptr)
       if (toplevel) {
         WasmI32.toGrain(ptr): String
       } else {
@@ -534,7 +534,7 @@ let rec heapValueToString = (ptr, extraIndents, toplevel, cycles) => {
               extraIndents,
               cycles
             )
-            Memory.decRef(recordVariantFields)
+            let _ = Memory.decRef(recordVariantFields)
             let strings = [variantName, recordString]
 
             join(strings)
@@ -562,7 +562,7 @@ let rec heapValueToString = (ptr, extraIndents, toplevel, cycles) => {
             extraIndents,
             cycles
           )
-          Memory.decRef(fields)
+          let _ = Memory.decRef(fields)
           WasmI32.store(ptr, recordArity, 12n)
           join([cyclePrefix(ptr, cycles), result])
         }
@@ -656,7 +656,7 @@ let rec heapValueToString = (ptr, extraIndents, toplevel, cycles) => {
         }
         WasmI32.store(ptr, tupleLength, 4n)
 
-        Memory.incRef(WasmI32.fromGrain(strings))
+        let _ = Memory.incRef(WasmI32.fromGrain(strings))
         strings = [lparen, ...strings]
         if (tupleLength <= 1n) {
           // Special case: unary tuple, which is not valid Grain syntax; however, boxed values
@@ -872,7 +872,7 @@ provide let print = (value, suffix="\n") => {
   let written = buf + 16n
   WasmI32.store(iov, ptr + 8n, 0n)
   WasmI32.store(iov, WasmI32.load(ptr, 4n), 4n)
-  fd_write(1n, iov, 1n, written)
+  let _ = fd_write(1n, iov, 1n, written)
   Memory.free(buf)
   ignore(value)
   ignore(suffix)
diff --git a/stdlib/runtime/utils/printing.gr b/stdlib/runtime/utils/printing.gr
index 96b267a9cb..fba0d17bf4 100644
--- a/stdlib/runtime/utils/printing.gr
+++ b/stdlib/runtime/utils/printing.gr
@@ -32,7 +32,7 @@ provide let printNumber = (n: WasmI64) => {
   WasmI32.store8(lf, 10n, 0n)
   WasmI32.store(iov, lf, 8n)
   WasmI32.store(iov, 1n, 12n)
-  fd_write(1n, iov, 2n, written)
+  let _ = fd_write(1n, iov, 2n, written)
   Memory.free(buf)
   void
 }
@@ -54,7 +54,7 @@ provide let printString = (s: String) => {
   WasmI32.store8(lf, 10n, 0n)
   WasmI32.store(iov, lf, 8n)
   WasmI32.store(iov, 1n, 12n)
-  fd_write(1n, iov, 2n, written)
+  let _ = fd_write(1n, iov, 2n, written)
   Memory.free(buf)
   void
 }