Skip to content

Commit 7b6cc79

Browse files
branchseerclaude
andauthored
chore: allow future_not_send lint at workspace level (#267)
The task scheduling workflow is a single-threaded async task, so Send bounds are unnecessary. Remove 22 per-item `#[expect]` annotations in favor of a single workspace-level allow in Cargo.toml. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 89bddcd commit 7b6cc79

File tree

12 files changed

+2
-67
lines changed

12 files changed

+2
-67
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ nursery = { level = "warn", priority = -1 }
3434
cargo = { level = "warn", priority = -1 }
3535
cargo_common_metadata = "allow"
3636
multiple_crate_versions = "allow"
37+
# The task scheduling workflow is a single-threaded async task, so Send bounds are unnecessary.
38+
future_not_send = "allow"
3739

3840
[workspace.dependencies]
3941
allocator-api2 = { version = "0.2.21", default-features = false, features = ["alloc", "std"] }

crates/fspy/src/arena.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
#![expect(
2-
clippy::future_not_send,
3-
reason = "ouroboros generates async builder methods that cannot satisfy Send bounds"
4-
)]
5-
61
use allocator_api2::vec::Vec;
72
use bumpalo::Bump;
83

crates/fspy/src/ipc.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
#![expect(
2-
clippy::future_not_send,
3-
reason = "ouroboros generates async builder methods that cannot satisfy Send bounds"
4-
)]
5-
61
use std::io;
72

83
use bincode::borrow_decode_from_slice;

crates/vite_task/src/session/cache/mod.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,6 @@ fn detect_globbed_input_change(
323323

324324
// Basic database operations
325325
impl ExecutionCache {
326-
#[expect(
327-
clippy::future_not_send,
328-
reason = "tokio MutexGuard is !Send but this future only runs on a single-threaded runtime"
329-
)]
330326
#[expect(
331327
clippy::significant_drop_tightening,
332328
reason = "lock guard cannot be dropped earlier because prepared statement borrows connection"
@@ -370,10 +366,6 @@ impl ExecutionCache {
370366
self.get_key_by_value("task_fingerprints", execution_cache_key).await
371367
}
372368

373-
#[expect(
374-
clippy::future_not_send,
375-
reason = "tokio MutexGuard is !Send but this future only runs on a single-threaded runtime"
376-
)]
377369
#[expect(
378370
clippy::significant_drop_tightening,
379371
reason = "lock guard must be held while executing the prepared statement"

crates/vite_task/src/session/execute/mod.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ impl ExecutionContext<'_> {
7878
///
7979
/// Returns `true` if all tasks succeeded, `false` if any task failed.
8080
#[tracing::instrument(level = "debug", skip_all)]
81-
#[expect(clippy::future_not_send, reason = "uses !Send types internally")]
8281
async fn execute_expanded_graph(
8382
&mut self,
8483
graph: &ExecutionGraph,
@@ -132,7 +131,6 @@ impl ExecutionContext<'_> {
132131
///
133132
/// Returns `true` if the execution failed (non-zero exit or infrastructure error).
134133
#[tracing::instrument(level = "debug", skip_all)]
135-
#[expect(clippy::future_not_send, reason = "uses !Send types internally")]
136134
async fn execute_leaf(
137135
&mut self,
138136
display: &ExecutionItemDisplay,
@@ -196,7 +194,6 @@ impl ExecutionContext<'_> {
196194
/// Errors (cache lookup failure, spawn failure, cache update failure) are reported
197195
/// through `leaf_reporter.finish()` and do not abort the caller.
198196
#[tracing::instrument(level = "debug", skip_all)]
199-
#[expect(clippy::future_not_send, reason = "uses !Send types internally")]
200197
#[expect(
201198
clippy::too_many_lines,
202199
reason = "sequential cache check, execute, and update steps are clearer in one function"
@@ -531,7 +528,6 @@ impl Session<'_> {
531528
/// Returns `Err(ExitStatus)` to indicate the caller should exit with the given status code.
532529
/// Returns `Ok(())` when all tasks succeeded.
533530
#[tracing::instrument(level = "debug", skip_all)]
534-
#[expect(clippy::future_not_send, reason = "uses !Send types internally")]
535531
pub(crate) async fn execute_graph(
536532
&self,
537533
execution_graph: ExecutionGraph,

crates/vite_task/src/session/execute/spawn.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ pub struct TrackedPathAccesses {
6565
/// - `path_accesses` if provided, fspy will be used to track file accesses. If `None`, fspy is disabled.
6666
/// - `resolved_negatives` - resolved negative glob patterns for filtering fspy-tracked paths.
6767
#[tracing::instrument(level = "debug", skip_all)]
68-
#[expect(clippy::future_not_send, reason = "uses !Send dyn AsyncWrite writers internally")]
6968
#[expect(
7069
clippy::too_many_lines,
7170
reason = "spawn logic is inherently sequential and splitting would reduce clarity"

crates/vite_task/src/session/mod.rs

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,6 @@ impl<'a> Session<'a> {
201201
///
202202
/// Returns an error if the task graph cannot be loaded from the workspace configuration.
203203
#[tracing::instrument(level = "debug", skip_all)]
204-
#[expect(
205-
clippy::future_not_send,
206-
reason = "session is single-threaded, futures do not need to be Send"
207-
)]
208204
pub async fn ensure_task_graph_loaded(
209205
&mut self,
210206
) -> Result<&IndexedTaskGraph, TaskGraphLoadError> {
@@ -251,10 +247,6 @@ impl<'a> Session<'a> {
251247
///
252248
/// Returns an error if planning or execution fails.
253249
#[tracing::instrument(level = "debug", skip_all)]
254-
#[expect(
255-
clippy::future_not_send,
256-
reason = "session is single-threaded, futures do not need to be Send"
257-
)]
258250
pub async fn main(mut self, command: Command) -> anyhow::Result<ExitStatus> {
259251
match self.main_inner(command).await {
260252
Ok(()) => Ok(ExitStatus::SUCCESS),
@@ -266,10 +258,6 @@ impl<'a> Session<'a> {
266258
/// # Panics
267259
///
268260
/// Panics if parsing a hardcoded bare `RunCommand` fails (should never happen).
269-
#[expect(
270-
clippy::future_not_send,
271-
reason = "session is single-threaded, futures do not need to be Send"
272-
)]
273261
async fn main_inner(&mut self, command: Command) -> Result<(), SessionError> {
274262
match command.into_resolved() {
275263
ResolvedCommand::Cache { ref subcmd } => self.handle_cache_command(subcmd),
@@ -343,10 +331,6 @@ impl<'a> Session<'a> {
343331
///
344332
/// In non-interactive mode, prints the task list (or "did you mean" suggestions)
345333
/// and returns `Err(SessionError::EarlyExit(_))` — no further execution needed.
346-
#[expect(
347-
clippy::future_not_send,
348-
reason = "session is single-threaded, futures do not need to be Send"
349-
)]
350334
#[expect(
351335
clippy::too_many_lines,
352336
reason = "builds interactive/non-interactive select items and handles selection"
@@ -594,10 +578,6 @@ impl<'a> Session<'a> {
594578
///
595579
/// Returns an error if planning or execution of the synthetic command fails.
596580
#[tracing::instrument(level = "debug", skip_all)]
597-
#[expect(
598-
clippy::future_not_send,
599-
reason = "session is single-threaded, futures do not need to be Send"
600-
)]
601581
#[expect(
602582
clippy::large_futures,
603583
reason = "execution plan future is large but only awaited once"
@@ -657,10 +637,6 @@ impl<'a> Session<'a> {
657637
///
658638
/// Returns an error if the plan request cannot be parsed or if planning fails.
659639
#[tracing::instrument(level = "debug", skip_all)]
660-
#[expect(
661-
clippy::future_not_send,
662-
reason = "session is single-threaded, futures do not need to be Send"
663-
)]
664640
pub async fn plan_from_cli_run(
665641
&mut self,
666642
cwd: Arc<AbsolutePath>,
@@ -672,10 +648,6 @@ impl<'a> Session<'a> {
672648

673649
/// Internal: plans execution from a resolved run command.
674650
#[tracing::instrument(level = "debug", skip_all)]
675-
#[expect(
676-
clippy::future_not_send,
677-
reason = "session is single-threaded, futures do not need to be Send"
678-
)]
679651
async fn plan_from_cli_run_resolved(
680652
&mut self,
681653
cwd: Arc<AbsolutePath>,
@@ -711,10 +683,6 @@ impl<'a> Session<'a> {
711683
///
712684
/// Used by the interactive task selector, which constructs the request
713685
/// directly (bypassing CLI specifier parsing).
714-
#[expect(
715-
clippy::future_not_send,
716-
reason = "session is single-threaded, futures do not need to be Send"
717-
)]
718686
async fn plan_from_query(
719687
&mut self,
720688
request: QueryPlanRequest,

crates/vite_task/src/session/reporter/labeled.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -347,10 +347,6 @@ mod tests {
347347
reporter.new_leaf_execution(display, leaf_kind, all_ancestors_single_node)
348348
}
349349

350-
#[expect(
351-
clippy::future_not_send,
352-
reason = "LeafExecutionReporter futures are !Send in single-threaded reporter tests"
353-
)]
354350
async fn suggestion_for(
355351
display: &ExecutionItemDisplay,
356352
leaf_kind: &LeafExecutionKind,

crates/vite_task_bin/src/main.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ async fn main() -> anyhow::Result<ExitCode> {
1515
Ok(exit_status.0.into())
1616
}
1717

18-
#[expect(clippy::future_not_send, reason = "Session contains !Send types; single-threaded runtime")]
1918
async fn run() -> anyhow::Result<ExitStatus> {
2019
let args = Args::parse();
2120
let mut owned_config = OwnedSessionConfig::default();

crates/vite_task_graph/src/lib.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,6 @@ impl IndexedTaskGraph {
215215
clippy::too_many_lines,
216216
reason = "graph loading is inherently sequential and multi-step"
217217
)]
218-
#[expect(
219-
clippy::future_not_send,
220-
reason = "UserConfigLoader uses async_trait(?Send) so the future is intentionally not Send"
221-
)]
222218
pub async fn load(
223219
workspace_root: &WorkspaceRoot,
224220
config_loader: &dyn loader::UserConfigLoader,

0 commit comments

Comments
 (0)