Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Panics when resizing #1408

Merged
merged 4 commits into from
Jan 16, 2022
Merged

Conversation

k2d222
Copy link
Contributor

@k2d222 k2d222 commented Dec 30, 2021

FIxes #1403

The editor crashes when the window is very small. Two reasons:

  • some widgets have a minimum size (e.g. boxes) -> integer calculations may overflow.
  • buffer panics when accessed out-of-range
  • Changed Buffer::get and Buffer::get_mut to return an Option, like std::Vec
  • Implemented traits Index and IndexMut for Buffer with a pair of coordinates, i.e. buf[(x, y)]
  • Replaced calls to Buffer::get and Buffer.get_mut with the Index, which is known to panic. Makes code clearer with the intent not to perform bounds checks.
  • Fixed a few divisions by zero and integer substraction underflows.

helix-term/src/ui/picker.rs Outdated Show resolved Hide resolved
Comment on lines 165 to 172
pub fn get(&self, x: u16, y: u16) -> Option<&Cell> {
self.index_of_opt(x, y).map(|i| &self.content[i])
}

/// Returns a mutable reference to Cell at the given coordinates
pub fn get_mut(&mut self, x: u16, y: u16) -> &mut Cell {
let i = self.index_of(x, y);
&mut self.content[i]
pub fn get_mut(&mut self, x: u16, y: u16) -> Option<&mut Cell> {
self.index_of_opt(x, y).map(|i| &mut self.content[i])
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather see you use the original method and then use self.content.get(i). That way you're not doing bounds checks twice (once in index_of_opt, once internally in self.content[]).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that would work. There is no way to avoid bounds checks on a Vec (to my knowledge) and the check performed by index_of is actually different:
Say the buffer is of size (2, 2), then asking for out-of-bounds cell at (2, 0) will compute index=2, which is in bounds of vec but correspond to incorrect cell at (0,1).

(We could accept that and tolerate that buffer can return bad cells when out of bounds, but I don't think optimizing performance for this kind of double checks is worth it)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well there's unsafe get_unchecked() if you previously validate the index.

We inherited the Buffer implementation from https://github.com/fdehau/tui-rs/ and I think this explains why it panics and only uses a debug_assert! rather than Option: Buffer::get_mut is a hot path that gets called a lot on every render. On frequent re-renders the slowdown will be noticeable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want me to use get_unchecked or do you overall disagree with the proposed solution?

I think it's best to have safe functions in Buffer at the cost of (what I think to be) unnoticeable performance gains. I could be wrong, but I think the terminal emulator is more responsible of refresh latency than the editor.

Also, 'premature optimization is the root of all evil' :) Helix is in alpha state, it should be stable and feature-full before being optimized for speed / latency.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this again, I think the change is OK since now in most cases we use [] instead of get_mut anyway (like set_stringn).

helix-tui/src/buffer.rs Outdated Show resolved Hide resolved
@archseer archseer merged commit f5b0821 into helix-editor:master Jan 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Rust panics when terminal is too small
3 participants