fix: Fix diagnostics being leaked when diagnostics panic

This commit is contained in:
Lukas Wirth 2026-01-30 16:00:31 +01:00
parent 7d2eec2538
commit 85f2923dc5
2 changed files with 42 additions and 34 deletions

View file

@ -289,34 +289,40 @@ pub(crate) fn fetch_native_diagnostics(
let mut diagnostics = subscriptions[slice]
.iter()
.copied()
.filter_map(|file_id| {
let line_index = snapshot.file_line_index(file_id).ok()?;
let source_root = snapshot.analysis.source_root_id(file_id).ok()?;
.map(|file_id| {
let diagnostics = (|| {
let line_index = snapshot.file_line_index(file_id).ok()?;
let source_root = snapshot.analysis.source_root_id(file_id).ok()?;
let config = &snapshot.config.diagnostics(Some(source_root));
let diagnostics = match kind {
NativeDiagnosticsFetchKind::Syntax => {
snapshot.analysis.syntax_diagnostics(config, file_id).ok()?
}
NativeDiagnosticsFetchKind::Semantic if config.enabled => snapshot
.analysis
.semantic_diagnostics(config, ide::AssistResolveStrategy::None, file_id)
.ok()?,
NativeDiagnosticsFetchKind::Semantic => return None,
};
let diagnostics = diagnostics
.into_iter()
.filter_map(|d| {
if d.range.file_id == file_id {
Some(convert_diagnostic(&line_index, d))
} else {
odd_ones.push(d);
None
let config = &snapshot.config.diagnostics(Some(source_root));
let diagnostics = match kind {
NativeDiagnosticsFetchKind::Syntax => {
snapshot.analysis.syntax_diagnostics(config, file_id).ok()?
}
})
.collect::<Vec<_>>();
Some((file_id, diagnostics))
NativeDiagnosticsFetchKind::Semantic if config.enabled => snapshot
.analysis
.semantic_diagnostics(config, ide::AssistResolveStrategy::None, file_id)
.ok()?,
NativeDiagnosticsFetchKind::Semantic => return None,
};
Some(
diagnostics
.into_iter()
.filter_map(|d| {
if d.range.file_id == file_id {
Some(convert_diagnostic(&line_index, d))
} else {
odd_ones.push(d);
None
}
})
.collect::<Vec<_>>(),
)
})()
.unwrap_or_default();
(file_id, diagnostics)
})
.collect::<Vec<_>>();

View file

@ -666,31 +666,33 @@ impl GlobalState {
move |sender| {
// We aren't observing the semantics token cache here
let snapshot = AssertUnwindSafe(&snapshot);
let Ok(diags) = std::panic::catch_unwind(|| {
let diags = std::panic::catch_unwind(|| {
fetch_native_diagnostics(
&snapshot,
subscriptions.clone(),
slice.clone(),
NativeDiagnosticsFetchKind::Syntax,
)
}) else {
return;
};
})
.unwrap_or_else(|_| {
subscriptions.iter().map(|&id| (id, Vec::new())).collect::<Vec<_>>()
});
sender
.send(Task::Diagnostics(DiagnosticsTaskKind::Syntax(generation, diags)))
.unwrap();
if fetch_semantic {
let Ok(diags) = std::panic::catch_unwind(|| {
let diags = std::panic::catch_unwind(|| {
fetch_native_diagnostics(
&snapshot,
subscriptions.clone(),
slice.clone(),
NativeDiagnosticsFetchKind::Semantic,
)
}) else {
return;
};
})
.unwrap_or_else(|_| {
subscriptions.iter().map(|&id| (id, Vec::new())).collect::<Vec<_>>()
});
sender
.send(Task::Diagnostics(DiagnosticsTaskKind::Semantic(
generation, diags,