Repository: neovim/neovim
File: src/nvim/api/win_config.c (C)

Code before:
    // then we can just change the size of the window.
    if ((!has_vertical && !has_split)
        || (was_split && !HAS_KEY_X(config, win) && old_split == fconfig.split)) {
      if (HAS_KEY_X(config, width)) {
        win_setwidth_win(fconfig.width, win);
      }
      if (HAS_KEY_X(config, height)) {
        win_setheight_win(fconfig.height, win);
      }
      redraw_later(win, UPD_NOT_VALID);
      return;
    }

    if (!check_split_disallowed_err(win, err)) {
      return;  // error already set
    }

    bool to_split_ok = false;
    int dir = 0;
    // If we are moving curwin to another tabpage, switch windows *before* we remove it from the
    // window list or remove its frame (if non-floating), so it's valid for autocommands.
    const bool curwin_moving_tp = win == curwin && parent && win_tp != parent_tp;
    if (curwin_moving_tp) {
      win_T *target_wp = was_split ? winframe_find_altwin(win, &dir, NULL,
                                                          NULL) : win_float_find_altwin(win, NULL);
      assert(target_wp);
      dir = 0;
      win_goto(target_wp);

      // Autocommands may have been a real nuisance and messed things up...
      if (curwin == win) {
        api_set_error(err, kErrorTypeException, "Failed to switch away from window %d",
                      win->handle);
        return;
      }
      win_tp = win_find_tabpage(win);
      if (!win_tp || !win_valid_any_tab(parent)) {
        api_set_error(err, kErrorTypeException, "Windows to split were closed");
        goto restore_curwin;
      }
      if (was_split == win->w_floating || parent->w_floating) {
        api_set_error(err, kErrorTypeException, "Floating state of windows to split changed");
        goto restore_curwin;
      }
    }

    frame_T *unflat_altfr = NULL;
    win_T *altwin = NULL;
    if (was_split) {
      // If the window is the last in the tabpage or `fconfig.win` is
      // a handle to itself, we can't split it.

Review comment (bug):
Not what I meant; the crash _is_ possible, but if we check that this is the last non-float window here, this shouldn't ever be `NULL`.

Code after:
    // then we can just change the size of the window.
    if ((!has_vertical && !has_split)
        || (was_split && !HAS_KEY_X(config, win) && old_split == fconfig.split)) {
      if (HAS_KEY_X(config, width)) {
        win_setwidth_win(fconfig.width, win);
      }
      if (HAS_KEY_X(config, height)) {
        win_setheight_win(fconfig.height, win);
      }
      redraw_later(win, UPD_NOT_VALID);
      return;
    }

    if (!check_split_disallowed_err(win, err)) {
      return;  // error already set
    }

    bool to_split_ok = false;
    // If we are moving curwin to another tabpage, switch windows *before* we remove it from the
    // window list or remove its frame (if non-floating), so it's valid for autocommands.
    const bool curwin_moving_tp = win == curwin && parent && win_tp != parent_tp;
    if (curwin_moving_tp) {
      if (was_split) {
        int dir;
        win_T *altwin = winframe_find_altwin(win, &dir, NULL, NULL);
        // Autocommands may still make this the last non-float after this check.
        // That case will be caught later when trying to move the window.
        if (!altwin) {
          api_set_error(err, kErrorTypeException, "Cannot move last non-floating window");
          return;
        }
        win_goto(altwin);
      } else {
        win_goto(win_float_find_altwin(win, NULL));
      }

      // Autocommands may have been a real nuisance and messed things up...
      if (curwin == win) {
        api_set_error(err, kErrorTypeException, "Failed to switch away from window %d",
                      win->handle);
        return;
      }
      win_tp = win_find_tabpage(win);
      if (!win_tp || !win_valid_any_tab(parent)) {
        api_set_error(err, kErrorTypeException, "Windows to split were closed");
        goto restore_curwin;
      }
      if (was_split == win->w_floating || parent->w_floating) {
        api_set_error(err, kErrorTypeException, "Floating state of windows to split changed");
        goto restore_curwin;
      }