Repository: osa1/tiny (language: rust)

Issue:
Panic after `/clear`
I run `/clear` today on a tab and after a few minutes got this panic:

![Screenshot_2021-09-13_08-18-34](https://user-images.githubusercontent.com/448274/133027885-0661cab8-9344-4d1e-8302-7b977a73927c.png)

Unfortunately I didn't have backtraces enabled but I'll enable it now and try again. I'll update if it panics again.


Discussion / hints:
Here's a backtrace:

```
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', crates/libtiny_tui/src/msg_area/mod.rs:77:61
stack backtrace:
   0: rust_begin_unwind
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:493:5
   1: core::panicking::panic_fmt
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/panicking.rs:92:14
   2: core::panicking::panic
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/panicking.rs:50:5
   3: core::option::Option<T>::unwrap
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/option.rs:386:21
   4: libtiny_tui::msg_area::MsgArea::resize
             at ./crates/libtiny_tui/src/msg_area/mod.rs:77:45
   5: libtiny_tui::messaging::MessagingUI::resize
             at ./crates/libtiny_tui/src/messaging.rs:201:9
   6: libtiny_tui::messaging::MessagingUI::set_nick
             at ./crates/libtiny_tui/src/messaging.rs:117:9
   7: libtiny_tui::tui::TUI::set_nick::{{closure}}
             at ./crates/libtiny_tui/src/tui.rs:1345:13
   8: libtiny_tui::tui::TUI::apply_to_target
             at ./crates/libtiny_tui/src/tui.rs:1206:13
   9: libtiny_tui::tui::TUI::set_nick
             at ./crates/libtiny_tui/src/tui.rs:1344:9
  10: libtiny_tui::TUI::set_nick
             at ./crates/libtiny_tui/src/lib.rs:216:17
  11: tiny::ui::UI::set_nick
             at ./crates/tiny/src/ui.rs:29:13
  12: tiny::conn::handle_conn_ev
             at ./crates/tiny/src/conn.rs:124:13
  13: tiny::conn::task::{{closure}}
             at ./crates/tiny/src/conn.rs:43:9
  14: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/future/mod.rs:80:19
  15: tokio::runtime::task::core::CoreStage<T>::poll::{{closure}}
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/task/core.rs:243:17
  16: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/loom/std/unsafe_cell.rs:14:9
  17: tokio::runtime::task::core::CoreStage<T>::poll
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/task/core.rs:233:13
  18: tokio::runtime::task::harness::poll_future::{{closure}}
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/task/harness.rs:427:23
  19: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panic.rs:344:9
  20: std::panicking::try::do_call
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:379:40
  21: __rust_try
  22: std::panicking::try
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:343:19
  23: std::panic::catch_unwind
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panic.rs:431:14
  24: tokio::runtime::task::harness::poll_future
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/task/harness.rs:414:19
  25: tokio::runtime::task::harness::Harness<T,S>::poll_inner
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/task/harness.rs:89:9
  26: tokio::runtime::task::harness::Harness<T,S>::poll
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/task/harness.rs:59:15
  27: tokio::runtime::task::raw::poll
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/task/raw.rs:104:5
  28: tokio::runtime::task::raw::RawTask::poll
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/task/raw.rs:66:18
  29: tokio::runtime::task::Notified<S>::run
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/task/mod.rs:171:9
  30: tokio::task::local::LocalSet::tick::{{closure}}
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/task/local.rs:514:54
  31: tokio::coop::with_budget::{{closure}}
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/coop.rs:106:9
  32: std::thread::local::LocalKey<T>::try_with
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/thread/local.rs:376:16
  33: std::thread::local::LocalKey<T>::with
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/thread/local.rs:352:9
  34: tokio::coop::with_budget
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/coop.rs:99:5
  35: tokio::coop::budget
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/coop.rs:76:5
  36: tokio::task::local::LocalSet::tick
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/task/local.rs:514:31
  37: <tokio::task::local::RunUntil<T> as core::future::future::Future>::poll::{{closure}}
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/task/local.rs:638:16
  38: tokio::macros::scoped_tls::ScopedKey<T>::set
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/macros/scoped_tls.rs:61:9
  39: tokio::task::local::LocalSet::with
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/task/local.rs:548:9
  40: <tokio::task::local::RunUntil<T> as core::future::future::Future>::poll
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/task/local.rs:624:9
  41: tokio::task::local::LocalSet::run_until::{{closure}}
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/task/local.rs:498:9
  42: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/future/mod.rs:80:19
  43: <core::pin::Pin<P> as core::future::future::Future>::poll
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/future/future.rs:120:9
  44: tokio::runtime::basic_scheduler::Inner<P>::block_on::{{closure}}::{{closure}}
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/basic_scheduler.rs:213:62
  45: tokio::coop::with_budget::{{closure}}
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/coop.rs:106:9
  46: std::thread::local::LocalKey<T>::try_with
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/thread/local.rs:376:16
  47: std::thread::local::LocalKey<T>::with
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/thread/local.rs:352:9
  48: tokio::coop::with_budget
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/coop.rs:99:5
  49: tokio::coop::budget
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/coop.rs:76:5
  50: tokio::runtime::basic_scheduler::Inner<P>::block_on::{{closure}}
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/basic_scheduler.rs:213:39
  51: tokio::runtime::basic_scheduler::enter::{{closure}}
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/basic_scheduler.rs:323:29
  52: tokio::macros::scoped_tls::ScopedKey<T>::set
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/macros/scoped_tls.rs:61:9
  53: tokio::runtime::basic_scheduler::enter
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/basic_scheduler.rs:323:5
  54: tokio::runtime::basic_scheduler::Inner<P>::block_on
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/basic_scheduler.rs:202:9
  55: tokio::runtime::basic_scheduler::InnerGuard<P>::block_on
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/basic_scheduler.rs:516:9
  56: tokio::runtime::basic_scheduler::BasicScheduler<P>::block_on
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/basic_scheduler.rs:162:24
  57: tokio::runtime::Runtime::block_on
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/runtime/mod.rs:450:46
  58: tokio::task::local::LocalSet::block_on
             at /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/tokio-1.7.1/src/task/local.rs:459:9
  59: tiny::run
             at ./crates/tiny/src/main.rs:104:5
  60: tiny::main
             at ./crates/tiny/src/main.rs:72:17
  61: core::ops::function::FnOnce::call_once
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
```

It's very easy to get various panics after using `/clear`, but I suspect they may all be the same issue manifesting in different ways.

Fix patch:
diff --git a/crates/libtiny_tui/src/msg_area/mod.rs b/crates/libtiny_tui/src/msg_area/mod.rs
index 32b204ec..6930b9c7 100644
--- a/crates/libtiny_tui/src/msg_area/mod.rs
+++ b/crates/libtiny_tui/src/msg_area/mod.rs
@@ -228,7 +228,7 @@ impl MsgArea {
     pub(crate) fn clear(&mut self) {
         self.lines.clear();
         self.scroll = 0;
-        self.lines_height = None;
+        self.lines_height = Some(0);
     }
 }
 


Test patch:
diff --git a/crates/libtiny_tui/src/tests/resize.rs b/crates/libtiny_tui/src/tests/resize.rs
index df1b9d92..103a7fdf 100644
--- a/crates/libtiny_tui/src/tests/resize.rs
+++ b/crates/libtiny_tui/src/tests/resize.rs
@@ -315,3 +315,45 @@ fn test_resize_scroll_resize() {
 
     expect_screen(screen1, &tui.get_front_buffer(), 20, 15, Location::caller());
 }
+
+// https://github.com/osa1/tiny/issues/355
+#[test]
+fn test_clear_resize_recalc_scroll() {
+    let mut tui = TUI::new_test(15, 5);
+    let serv = "irc.server_1.org";
+    let chan = ChanNameRef::new("#chan");
+    tui.new_server_tab(serv, None);
+    tui.set_nick(serv, "osa1");
+    tui.new_chan_tab(serv, chan);
+    tui.next_tab();
+    tui.next_tab();
+
+    let target = MsgTarget::Chan { serv, chan };
+    let ts = time::at_utc(time::Timespec::new(0, 0));
+    for _ in 0..6 {
+        tui.add_privmsg("osa1", &"1111 ".repeat(3), ts, &target, false, false);
+    }
+
+    tui.draw();
+
+    // scroll up
+    tui.handle_input_event(term_input::Event::Key(Key::PageUp), &mut None);
+
+    // clear the screen
+    tui.clear(&target);
+
+    // resize window (testing for panic)
+    tui.set_size(20, 6);
+
+    // at bottom with no scroll
+    #[rustfmt::skip]
+    let screen1 =
+       "|                    |
+        |                    |
+        |                    |
+        |                    |
+        |osa1:               |
+        |< #chan             |";
+
+    expect_screen(screen1, &tui.get_front_buffer(), 20, 6, Location::caller());
+}