Skip to content

refactor(completer)!: don't require Send on the Completer trait#1092

Open
kronberger-droid wants to merge 1 commit into
nushell:mainfrom
kronberger-droid:completer-send-bound
Open

refactor(completer)!: don't require Send on the Completer trait#1092
kronberger-droid wants to merge 1 commit into
nushell:mainfrom
kronberger-droid:completer-send-bound

Conversation

@kronberger-droid
Copy link
Copy Markdown
Collaborator

@kronberger-droid kronberger-droid commented Jun 2, 2026

The unsafe impl Send on HistoryCompleter was actually sound: it's a pub(crate) type only ever created as a stack local and borrowed into menus, never sent across threads.
But it pointed at a trait that's too tight, since Completer: Send forces every completer to be Send.

So instead of asserting Send where it isn't required, this drops it from the Completer trait and requires it only on the completers that are actually owned and stored, thus in Reedline and ReedlineMenu::WithCompleter, now Box<dyn Completer + Send>.
The unsafe falls away naturally, with no new bound on History, so SqliteBackedHistory (whose rusqlite::Connection is !Sync) is untouched.

This is an alternative to #929, which tightened History: Sync to fix the same unsafe but broke the sqlite backend as a result.

Added reedline_is_send as a compile-time guard on the relocated bound.

API note: with_completer and ReedlineMenu::WithCompleter now take Box<dyn Completer + Send>. Source-compatible (the old Completer: Send already required it), but visible in signatures.

The `unsafe impl Send` on `HistoryCompleter` was sound (a pub(crate)
stack-local, never sent across threads) but it revealed that
`Completer: Send` is too tight: not every completer needs to be Send.

Drop `Send` from the `Completer` trait and require it only on the owned
completers stored in `Reedline` and `ReedlineMenu::WithCompleter`, now
`Box<dyn Completer + Send>`. The `unsafe` falls away with no new bound on
`History`, so `SqliteBackedHistory` (`!Sync` connection) stays untouched.

Alternative to nushell#929, which fixed the same `unsafe` via `History: Sync`
but broke the sqlite backend. Adds `reedline_is_send` as a compile-time
guard.

BREAKING CHANGE: `Completer` no longer requires `Send`. `with_completer`
and `ReedlineMenu::WithCompleter` now take `Box<dyn Completer + Send>`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant