From e4bcf7d6fc602c822083c7c0b7bf462feb20a80b Mon Sep 17 00:00:00 2001 From: simba Date: Thu, 24 Sep 2026 22:39:45 -0700 Subject: [PATCH] fix: remove Swift 6 captured-var warnings in Server startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three `var`s were captured by concurrently-executing closures, which is a warning today and an error in the Swift 6 language mode: - Server.swift:1337 `isVision`: made mutable by the VLM→LLM fallback (#173) and read in the /health handler. - Server.swift:1056 / 1368 `mtpAssistantModelRef`: read inside `container.perform` and in the chat-completion route. Each is now captured through a `let` snapshot taken after its last mutation (`loadedAsVision`, `loadedMTPAssistant`, and a local `assistant` for the mainModelRef wiring; DualModelMTP is class-bound via Module, so setting through the `let` still reaches the same object). Clean rebuild on Xcode 27 / Swift 6.4 shows no captured-var warnings. Smoke-tested on a Mac mini M6: Qwen3.6-35B (VLM fallback) /health "vision":false, Qwen3.8-27B "vision":true, Gemma 4 + bf16 MTP assistant "MTP assistant ready (3 tokens/round)", and all three answer. Co-Authored-By: Claude Opus 5.5 --- Sources/SwiftLM/Server.swift | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Sources/SwiftLM/Server.swift b/Sources/SwiftLM/Server.swift index 4e0e185..3cc7cb0 100644 --- a/Sources/SwiftLM/Server.swift +++ b/Sources/SwiftLM/Server.swift @@ -964,6 +964,9 @@ struct MLXServer: AsyncParsableCommand { } } + // Final after the VLM→LLM fallback above; later closures capture this `let`. + let loadedAsVision = isVision + print("[SwiftLM] Loaded model configuration. Inferred tool call format: \(String(describing: await container.configuration.toolCallFormat))") // ── Check if target model supports DFlash ── @@ -1052,12 +1055,14 @@ struct MLXServer: AsyncParsableCommand { print("[SwiftLM] Ignoring --mtp-assistant-model; generation will not use MTP.") } else { // The assistant drafts *for* this trunk, so it needs a reference to it. + let assistant = mtpAssistantModelRef await container.perform { mainContext in - mtpAssistantModelRef?.mainModelRef = mainContext.model + assistant?.mainModelRef = mainContext.model } print("[SwiftLM] MTP assistant ready (\(self.numMtpTokens) tokens/round)") } } + let loadedMTPAssistant = mtpAssistantModelRef // ── Load DFlash draft model for block-diffusion speculative decoding ── let dflashModel: DFlashDraftModel? @@ -1249,7 +1254,7 @@ struct MLXServer: AsyncParsableCommand { minP: self.minP, repeatPenalty: self.repeatPenalty, thinking: self.thinking, - isVision: isVision, + isVision: loadedAsVision, prefillSize: self.prefillSize, turboKV: self.turboKV, mtp: self.mtp, @@ -1334,7 +1339,7 @@ struct MLXServer: AsyncParsableCommand { } } let payload = """ -{"status":"ok","model":"\(modelId)","vision":\(isVision),"memory":{"active_mb":\(activeMemMB),"peak_mb":\(peakMemMB),"cache_mb":\(cacheMemMB),"total_system_mb":\(totalMemMB),"gpu_architecture":"\(deviceInfo.architecture)"},"stats":{"requests_total":\(snapshot.requestsTotal),"requests_active":\(snapshot.requestsActive),"tokens_generated":\(snapshot.tokensGenerated),"avg_tokens_per_sec":\(String(format: "%.2f", snapshot.avgTokensPerSec))}\(partitionJson)} +{"status":"ok","model":"\(modelId)","vision":\(loadedAsVision),"memory":{"active_mb":\(activeMemMB),"peak_mb":\(peakMemMB),"cache_mb":\(cacheMemMB),"total_system_mb":\(totalMemMB),"gpu_architecture":"\(deviceInfo.architecture)"},"stats":{"requests_total":\(snapshot.requestsTotal),"requests_active":\(snapshot.requestsActive),"tokens_generated":\(snapshot.tokensGenerated),"avg_tokens_per_sec":\(String(format: "%.2f", snapshot.avgTokensPerSec))}\(partitionJson)} """ return Response( status: .ok, @@ -1365,7 +1370,7 @@ struct MLXServer: AsyncParsableCommand { draftModelRef: draftModelRef, numDraftTokens: numDraftTokensConfig, dflashModel: dflashModel, dflashBlockSize: dflashBlockSizeConfig, dflashTargetModel: dflashTargetModel, - mtpAssistant: mtpAssistantModelRef + mtpAssistant: loadedMTPAssistant ) } catch { return Response( @@ -1465,7 +1470,7 @@ struct MLXServer: AsyncParsableCommand { "port": port, "model": modelId, "engine": "mlx", - "vision": isVision + "vision": loadedAsVision ] if let plan = partitionPlan { var info = plan.healthInfo