Generally optimize diagnostics performance

This commit is contained in:
Lukas Wirth 2024-04-15 20:38:54 +02:00
parent 94e38261b3
commit 531a270d91
15 changed files with 115 additions and 85 deletions

View file

@ -45,7 +45,7 @@ pub trait Upcast<T: ?Sized> {
pub const DEFAULT_FILE_TEXT_LRU_CAP: usize = 16; pub const DEFAULT_FILE_TEXT_LRU_CAP: usize = 16;
pub const DEFAULT_PARSE_LRU_CAP: usize = 128; pub const DEFAULT_PARSE_LRU_CAP: usize = 128;
pub const DEFAULT_BORROWCK_LRU_CAP: usize = 1024; pub const DEFAULT_BORROWCK_LRU_CAP: usize = 2024;
pub trait FileLoader { pub trait FileLoader {
/// Text of the file. /// Text of the file.

View file

@ -510,6 +510,7 @@ pub struct ConstData {
pub type_ref: Interned<TypeRef>, pub type_ref: Interned<TypeRef>,
pub visibility: RawVisibility, pub visibility: RawVisibility,
pub rustc_allow_incoherent_impl: bool, pub rustc_allow_incoherent_impl: bool,
pub has_body: bool,
} }
impl ConstData { impl ConstData {
@ -533,6 +534,7 @@ impl ConstData {
type_ref: konst.type_ref.clone(), type_ref: konst.type_ref.clone(),
visibility, visibility,
rustc_allow_incoherent_impl, rustc_allow_incoherent_impl,
has_body: konst.has_body,
}) })
} }
} }

View file

@ -26,8 +26,7 @@ use crate::{
tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree}, tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree},
type_ref::TypeRef, type_ref::TypeRef,
visibility::RawVisibility, visibility::RawVisibility,
AdtId, EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId,
VariantId,
}; };
/// Note that we use `StructData` for unions as well! /// Note that we use `StructData` for unions as well!
@ -380,6 +379,7 @@ impl VariantData {
} }
} }
#[allow(clippy::self_named_constructors)]
pub(crate) fn variant_data(db: &dyn DefDatabase, id: VariantId) -> Arc<VariantData> { pub(crate) fn variant_data(db: &dyn DefDatabase, id: VariantId) -> Arc<VariantData> {
match id { match id {
VariantId::StructId(it) => db.struct_data(it).variant_data.clone(), VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),

View file

@ -22,13 +22,13 @@ use crate::{
lang_item::{self, LangItem, LangItemTarget, LangItems}, lang_item::{self, LangItem, LangItemTarget, LangItems},
nameres::{diagnostics::DefDiagnostics, DefMap}, nameres::{diagnostics::DefDiagnostics, DefMap},
visibility::{self, Visibility}, visibility::{self, Visibility},
AdtId, AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, DefWithBodyId,
DefWithBodyId, EnumId, EnumLoc, EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, EnumId, EnumLoc, EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId,
ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, ExternCrateLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId,
InTypeConstId, InTypeConstLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, InTypeConstLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, MacroRulesLoc,
MacroRulesLoc, MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc,
StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc,
UnionLoc, UseId, UseLoc, VariantId, UseId, UseLoc, VariantId,
}; };
#[salsa::query_group(InternDatabaseStorage)] #[salsa::query_group(InternDatabaseStorage)]

View file

@ -716,6 +716,7 @@ pub struct Const {
pub visibility: RawVisibilityId, pub visibility: RawVisibilityId,
pub type_ref: Interned<TypeRef>, pub type_ref: Interned<TypeRef>,
pub ast_id: FileAstId<ast::Const>, pub ast_id: FileAstId<ast::Const>,
pub has_body: bool,
} }
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]

View file

@ -446,7 +446,7 @@ impl<'a> Ctx<'a> {
let type_ref = self.lower_type_ref_opt(konst.ty()); let type_ref = self.lower_type_ref_opt(konst.ty());
let visibility = self.lower_visibility(konst); let visibility = self.lower_visibility(konst);
let ast_id = self.source_ast_id_map.ast_id(konst); let ast_id = self.source_ast_id_map.ast_id(konst);
let res = Const { name, visibility, type_ref, ast_id }; let res = Const { name, visibility, type_ref, ast_id, has_body: konst.body().is_some() };
id(self.data().consts.alloc(res)) id(self.data().consts.alloc(res))
} }

View file

@ -357,7 +357,7 @@ impl Printer<'_> {
wln!(self, "}}"); wln!(self, "}}");
} }
ModItem::Const(it) => { ModItem::Const(it) => {
let Const { name, visibility, type_ref, ast_id } = &self.tree[it]; let Const { name, visibility, type_ref, ast_id, has_body: _ } = &self.tree[it];
self.print_ast_id(ast_id.erase()); self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "const "); w!(self, "const ");

View file

@ -43,7 +43,7 @@ mod allow {
} }
pub fn incorrect_case(db: &dyn HirDatabase, owner: ModuleDefId) -> Vec<IncorrectCase> { pub fn incorrect_case(db: &dyn HirDatabase, owner: ModuleDefId) -> Vec<IncorrectCase> {
let _p = tracing::span!(tracing::Level::INFO, "validate_module_item").entered(); let _p = tracing::span!(tracing::Level::INFO, "incorrect_case").entered();
let mut validator = DeclValidator::new(db); let mut validator = DeclValidator::new(db);
validator.validate_item(owner); validator.validate_item(owner);
validator.sink validator.sink

View file

@ -191,45 +191,45 @@ impl ExprValidator {
let pattern_arena = Arena::new(); let pattern_arena = Arena::new();
let mut m_arms = Vec::with_capacity(arms.len()); let mut m_arms = Vec::with_capacity(arms.len());
let mut has_lowering_errors = false; let mut has_lowering_errors = false;
// Note: Skipping the entire diagnostic rather than just not including a faulty match arm is
// preferred to avoid the chance of false positives.
for arm in arms { for arm in arms {
if let Some(pat_ty) = self.infer.type_of_pat.get(arm.pat) { let Some(pat_ty) = self.infer.type_of_pat.get(arm.pat) else {
// We only include patterns whose type matches the type return;
// of the scrutinee expression. If we had an InvalidMatchArmPattern };
// diagnostic or similar we could raise that in an else
// block here. // We only include patterns whose type matches the type
// // of the scrutinee expression. If we had an InvalidMatchArmPattern
// When comparing the types, we also have to consider that rustc // diagnostic or similar we could raise that in an else
// will automatically de-reference the scrutinee expression type if // block here.
// necessary. //
// // When comparing the types, we also have to consider that rustc
// FIXME we should use the type checker for this. // will automatically de-reference the scrutinee expression type if
if (pat_ty == scrut_ty // necessary.
|| scrut_ty //
.as_reference() // FIXME we should use the type checker for this.
.map(|(match_expr_ty, ..)| match_expr_ty == pat_ty) if (pat_ty == scrut_ty
.unwrap_or(false)) || scrut_ty
&& types_of_subpatterns_do_match(arm.pat, &self.body, &self.infer) .as_reference()
{ .map(|(match_expr_ty, ..)| match_expr_ty == pat_ty)
// If we had a NotUsefulMatchArm diagnostic, we could .unwrap_or(false))
// check the usefulness of each pattern as we added it && types_of_subpatterns_do_match(arm.pat, &self.body, &self.infer)
// to the matrix here. {
let pat = self.lower_pattern(&cx, arm.pat, db, &mut has_lowering_errors); // If we had a NotUsefulMatchArm diagnostic, we could
let m_arm = pat_analysis::MatchArm { // check the usefulness of each pattern as we added it
pat: pattern_arena.alloc(pat), // to the matrix here.
has_guard: arm.guard.is_some(), let pat = self.lower_pattern(&cx, arm.pat, db, &mut has_lowering_errors);
arm_data: (), let m_arm = pat_analysis::MatchArm {
}; pat: pattern_arena.alloc(pat),
m_arms.push(m_arm); has_guard: arm.guard.is_some(),
if !has_lowering_errors { arm_data: (),
continue; };
} m_arms.push(m_arm);
if !has_lowering_errors {
continue;
} }
} }
// If the pattern type doesn't fit the match expression, we skip this diagnostic.
// If we can't resolve the type of a pattern, or the pattern type doesn't
// fit the match expression, we skip this diagnostic. Skipping the entire
// diagnostic rather than just not including this match arm is preferred
// to avoid the chance of false positives.
cov_mark::hit!(validate_match_bailed_out); cov_mark::hit!(validate_match_bailed_out);
return; return;
} }
@ -534,8 +534,16 @@ fn types_of_subpatterns_do_match(pat: PatId, body: &Body, infer: &InferenceResul
fn walk(pat: PatId, body: &Body, infer: &InferenceResult, has_type_mismatches: &mut bool) { fn walk(pat: PatId, body: &Body, infer: &InferenceResult, has_type_mismatches: &mut bool) {
match infer.type_mismatch_for_pat(pat) { match infer.type_mismatch_for_pat(pat) {
Some(_) => *has_type_mismatches = true, Some(_) => *has_type_mismatches = true,
None if *has_type_mismatches => (),
None => { None => {
body[pat].walk_child_pats(|subpat| walk(subpat, body, infer, has_type_mismatches)) let pat = &body[pat];
if let Pat::ConstBlock(expr) | Pat::Lit(expr) = *pat {
*has_type_mismatches |= infer.type_mismatch_for_expr(expr).is_some();
if *has_type_mismatches {
return;
}
}
pat.walk_child_pats(|subpat| walk(subpat, body, infer, has_type_mismatches))
} }
} }
} }

View file

@ -4,7 +4,7 @@
use hir_def::{ use hir_def::{
body::Body, body::Body,
hir::{Expr, ExprId, UnaryOp}, hir::{Expr, ExprId, UnaryOp},
resolver::{resolver_for_expr, ResolveValueResult, ValueNs}, resolver::{resolver_for_expr, ResolveValueResult, Resolver, ValueNs},
DefWithBodyId, DefWithBodyId,
}; };
@ -13,9 +13,9 @@ use crate::{
}; };
pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> Vec<ExprId> { pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> Vec<ExprId> {
let infer = db.infer(def); let _p = tracing::span!(tracing::Level::INFO, "missing_unsafe",);
let mut res = Vec::new();
let mut res = Vec::new();
let is_unsafe = match def { let is_unsafe = match def {
DefWithBodyId::FunctionId(it) => db.function_data(it).has_unsafe_kw(), DefWithBodyId::FunctionId(it) => db.function_data(it).has_unsafe_kw(),
DefWithBodyId::StaticId(_) DefWithBodyId::StaticId(_)
@ -28,6 +28,7 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> Vec<ExprId> {
} }
let body = db.body(def); let body = db.body(def);
let infer = db.infer(def);
unsafe_expressions(db, &infer, def, &body, body.body_expr, &mut |expr| { unsafe_expressions(db, &infer, def, &body, body.body_expr, &mut |expr| {
if !expr.inside_unsafe_block { if !expr.inside_unsafe_block {
res.push(expr.expr); res.push(expr.expr);
@ -51,14 +52,24 @@ pub fn unsafe_expressions(
current: ExprId, current: ExprId,
unsafe_expr_cb: &mut dyn FnMut(UnsafeExpr), unsafe_expr_cb: &mut dyn FnMut(UnsafeExpr),
) { ) {
walk_unsafe(db, infer, def, body, current, false, unsafe_expr_cb) walk_unsafe(
db,
infer,
body,
&mut resolver_for_expr(db.upcast(), def, current),
def,
current,
false,
unsafe_expr_cb,
)
} }
fn walk_unsafe( fn walk_unsafe(
db: &dyn HirDatabase, db: &dyn HirDatabase,
infer: &InferenceResult, infer: &InferenceResult,
def: DefWithBodyId,
body: &Body, body: &Body,
resolver: &mut Resolver,
def: DefWithBodyId,
current: ExprId, current: ExprId,
inside_unsafe_block: bool, inside_unsafe_block: bool,
unsafe_expr_cb: &mut dyn FnMut(UnsafeExpr), unsafe_expr_cb: &mut dyn FnMut(UnsafeExpr),
@ -73,13 +84,14 @@ fn walk_unsafe(
} }
} }
Expr::Path(path) => { Expr::Path(path) => {
let resolver = resolver_for_expr(db.upcast(), def, current); let g = resolver.update_to_inner_scope(db.upcast(), def, current);
let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path); let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path);
if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial { if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial {
if db.static_data(id).mutable { if db.static_data(id).mutable {
unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block }); unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block });
} }
} }
resolver.reset_to_guard(g);
} }
Expr::MethodCall { .. } => { Expr::MethodCall { .. } => {
if infer if infer
@ -97,13 +109,13 @@ fn walk_unsafe(
} }
Expr::Unsafe { .. } => { Expr::Unsafe { .. } => {
return expr.walk_child_exprs(|child| { return expr.walk_child_exprs(|child| {
walk_unsafe(db, infer, def, body, child, true, unsafe_expr_cb); walk_unsafe(db, infer, body, resolver, def, child, true, unsafe_expr_cb);
}); });
} }
_ => {} _ => {}
} }
expr.walk_child_exprs(|child| { expr.walk_child_exprs(|child| {
walk_unsafe(db, infer, def, body, child, inside_unsafe_block, unsafe_expr_cb); walk_unsafe(db, infer, body, resolver, def, child, inside_unsafe_block, unsafe_expr_cb);
}); });
} }

View file

@ -432,6 +432,7 @@ pub struct InferenceResult {
/// Whether there are any type-mismatching errors in the result. /// Whether there are any type-mismatching errors in the result.
pub(crate) has_errors: bool, pub(crate) has_errors: bool,
/// Interned common types to return references to. /// Interned common types to return references to.
// FIXME: Move this into `InferenceContext`
standard_types: InternedStandardTypes, standard_types: InternedStandardTypes,
/// Stores the types which were implicitly dereferenced in pattern binding modes. /// Stores the types which were implicitly dereferenced in pattern binding modes.
pub pat_adjustments: FxHashMap<PatId, Vec<Ty>>, pub pat_adjustments: FxHashMap<PatId, Vec<Ty>>,

View file

@ -548,8 +548,7 @@ impl Module {
acc: &mut Vec<AnyDiagnostic>, acc: &mut Vec<AnyDiagnostic>,
style_lints: bool, style_lints: bool,
) { ) {
let name = self.name(db); let _p = tracing::span!(tracing::Level::INFO, "Module::diagnostics", name = ?self.name(db));
let _p = tracing::span!(tracing::Level::INFO, "Module::diagnostics", ?name);
let def_map = self.id.def_map(db.upcast()); let def_map = self.id.def_map(db.upcast());
for diag in def_map.diagnostics() { for diag in def_map.diagnostics() {
if diag.in_module != self.id.local_id { if diag.in_module != self.id.local_id {
@ -684,7 +683,7 @@ impl Module {
let items = &db.trait_data(trait_.into()).items; let items = &db.trait_data(trait_.into()).items;
let required_items = items.iter().filter(|&(_, assoc)| match *assoc { let required_items = items.iter().filter(|&(_, assoc)| match *assoc {
AssocItemId::FunctionId(it) => !db.function_data(it).has_body(), AssocItemId::FunctionId(it) => !db.function_data(it).has_body(),
AssocItemId::ConstId(id) => Const::from(id).value(db).is_none(), AssocItemId::ConstId(id) => !db.const_data(id).has_body,
AssocItemId::TypeAliasId(it) => db.type_alias_data(it).type_ref.is_none(), AssocItemId::TypeAliasId(it) => db.type_alias_data(it).type_ref.is_none(),
}); });
impl_assoc_items_scratch.extend(db.impl_data(impl_def.id).items.iter().filter_map( impl_assoc_items_scratch.extend(db.impl_data(impl_def.id).items.iter().filter_map(
@ -1628,7 +1627,6 @@ impl DefWithBody {
acc: &mut Vec<AnyDiagnostic>, acc: &mut Vec<AnyDiagnostic>,
style_lints: bool, style_lints: bool,
) { ) {
db.unwind_if_cancelled();
let krate = self.module(db).id.krate(); let krate = self.module(db).id.krate();
let (body, source_map) = db.body_with_source_map(self.into()); let (body, source_map) = db.body_with_source_map(self.into());
@ -1762,7 +1760,9 @@ impl DefWithBody {
need_mut = &mir::MutabilityReason::Not; need_mut = &mir::MutabilityReason::Not;
} }
let local = Local { parent: self.into(), binding_id }; let local = Local { parent: self.into(), binding_id };
match (need_mut, local.is_mut(db)) { let is_mut = body[binding_id].mode == BindingAnnotation::Mutable;
match (need_mut, is_mut) {
(mir::MutabilityReason::Unused, _) => { (mir::MutabilityReason::Unused, _) => {
let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with('_')); let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with('_'));
if !should_ignore { if !should_ignore {

View file

@ -317,7 +317,8 @@ fn main() {
#[test] #[test]
fn mismatched_types_issue_15883() { fn mismatched_types_issue_15883() {
// Check we don't panic. // Check we don't panic.
check_diagnostics_no_bails( cov_mark::check!(validate_match_bailed_out);
check_diagnostics(
r#" r#"
//- minicore: option //- minicore: option
fn main() { fn main() {

View file

@ -320,13 +320,11 @@ pub fn diagnostics(
let module = sema.file_to_module_def(file_id); let module = sema.file_to_module_def(file_id);
let ctx = DiagnosticsContext { config, sema, resolve }; let ctx = DiagnosticsContext { config, sema, resolve };
if module.is_none() {
handlers::unlinked_file::unlinked_file(&ctx, &mut res, file_id);
}
let mut diags = Vec::new(); let mut diags = Vec::new();
if let Some(m) = module { match module {
m.diagnostics(db, &mut diags, config.style_lints); Some(m) => m.diagnostics(db, &mut diags, config.style_lints),
None => handlers::unlinked_file::unlinked_file(&ctx, &mut res, file_id),
} }
for diag in diags { for diag in diags {
@ -409,6 +407,11 @@ pub fn diagnostics(
res.push(d) res.push(d)
} }
res.retain(|d| {
!(ctx.config.disabled.contains(d.code.as_str())
|| ctx.config.disable_experimental && d.experimental)
});
let mut diagnostics_of_range = res let mut diagnostics_of_range = res
.iter_mut() .iter_mut()
.filter_map(|it| { .filter_map(|it| {
@ -421,9 +424,14 @@ pub fn diagnostics(
}) })
.collect::<FxHashMap<_, _>>(); .collect::<FxHashMap<_, _>>();
if diagnostics_of_range.is_empty() {
return res;
}
let mut rustc_stack: FxHashMap<String, Vec<Severity>> = FxHashMap::default(); let mut rustc_stack: FxHashMap<String, Vec<Severity>> = FxHashMap::default();
let mut clippy_stack: FxHashMap<String, Vec<Severity>> = FxHashMap::default(); let mut clippy_stack: FxHashMap<String, Vec<Severity>> = FxHashMap::default();
// FIXME: This becomes quite expensive for big files
handle_lint_attributes( handle_lint_attributes(
&ctx.sema, &ctx.sema,
parse.syntax(), parse.syntax(),
@ -432,11 +440,7 @@ pub fn diagnostics(
&mut diagnostics_of_range, &mut diagnostics_of_range,
); );
res.retain(|d| { res.retain(|d| d.severity != Severity::Allow);
d.severity != Severity::Allow
&& !ctx.config.disabled.contains(d.code.as_str())
&& !(ctx.config.disable_experimental && d.experimental)
});
res res
} }
@ -476,6 +480,7 @@ fn handle_lint_attributes(
clippy_stack: &mut FxHashMap<String, Vec<Severity>>, clippy_stack: &mut FxHashMap<String, Vec<Severity>>,
diagnostics_of_range: &mut FxHashMap<InFile<SyntaxNode>, &mut Diagnostic>, diagnostics_of_range: &mut FxHashMap<InFile<SyntaxNode>, &mut Diagnostic>,
) { ) {
let _g = tracing::span!(tracing::Level::INFO, "handle_lint_attributes").entered();
let file_id = sema.hir_file_for(root); let file_id = sema.hir_file_for(root);
let preorder = root.preorder(); let preorder = root.preorder();
for ev in preorder { for ev in preorder {
@ -486,24 +491,24 @@ fn handle_lint_attributes(
stack.push(severity); stack.push(severity);
}); });
} }
if let Some(x) = if let Some(it) =
diagnostics_of_range.get_mut(&InFile { file_id, value: node.clone() }) diagnostics_of_range.get_mut(&InFile { file_id, value: node.clone() })
{ {
const EMPTY_LINTS: &[&str] = &[]; const EMPTY_LINTS: &[&str] = &[];
let (names, stack) = match x.code { let (names, stack) = match it.code {
DiagnosticCode::RustcLint(name) => ( DiagnosticCode::RustcLint(name) => (
RUSTC_LINT_GROUPS_DICT.get(name).map_or(EMPTY_LINTS, |x| &**x), RUSTC_LINT_GROUPS_DICT.get(name).map_or(EMPTY_LINTS, |it| &**it),
&mut *rustc_stack, &mut *rustc_stack,
), ),
DiagnosticCode::Clippy(name) => ( DiagnosticCode::Clippy(name) => (
CLIPPY_LINT_GROUPS_DICT.get(name).map_or(EMPTY_LINTS, |x| &**x), CLIPPY_LINT_GROUPS_DICT.get(name).map_or(EMPTY_LINTS, |it| &**it),
&mut *clippy_stack, &mut *clippy_stack,
), ),
_ => continue, _ => continue,
}; };
for &name in names { for &name in names {
if let Some(s) = stack.get(name).and_then(|x| x.last()) { if let Some(s) = stack.get(name).and_then(|it| it.last()) {
x.severity = *s; it.severity = *s;
} }
} }
} }
@ -571,8 +576,8 @@ fn parse_lint_attribute(
if let Some(lint) = lint.as_single_name_ref() { if let Some(lint) = lint.as_single_name_ref() {
job(rustc_stack.entry(lint.to_string()).or_default(), severity); job(rustc_stack.entry(lint.to_string()).or_default(), severity);
} }
if let Some(tool) = lint.qualifier().and_then(|x| x.as_single_name_ref()) { if let Some(tool) = lint.qualifier().and_then(|it| it.as_single_name_ref()) {
if let Some(name_ref) = &lint.segment().and_then(|x| x.name_ref()) { if let Some(name_ref) = &lint.segment().and_then(|it| it.name_ref()) {
if tool.to_string() == "clippy" { if tool.to_string() == "clippy" {
job(clippy_stack.entry(name_ref.to_string()).or_default(), severity); job(clippy_stack.entry(name_ref.to_string()).or_default(), severity);
} }

View file

@ -40,7 +40,7 @@ fn integrated_highlighting_benchmark() {
}; };
let load_cargo_config = LoadCargoConfig { let load_cargo_config = LoadCargoConfig {
load_out_dirs_from_check: true, load_out_dirs_from_check: true,
with_proc_macro_server: ProcMacroServerChoice::None, with_proc_macro_server: ProcMacroServerChoice::Sysroot,
prefill_caches: false, prefill_caches: false,
}; };
@ -100,7 +100,7 @@ fn integrated_completion_benchmark() {
}; };
let load_cargo_config = LoadCargoConfig { let load_cargo_config = LoadCargoConfig {
load_out_dirs_from_check: true, load_out_dirs_from_check: true,
with_proc_macro_server: ProcMacroServerChoice::None, with_proc_macro_server: ProcMacroServerChoice::Sysroot,
prefill_caches: true, prefill_caches: true,
}; };
@ -262,7 +262,7 @@ fn integrated_diagnostics_benchmark() {
}; };
let load_cargo_config = LoadCargoConfig { let load_cargo_config = LoadCargoConfig {
load_out_dirs_from_check: true, load_out_dirs_from_check: true,
with_proc_macro_server: ProcMacroServerChoice::None, with_proc_macro_server: ProcMacroServerChoice::Sysroot,
prefill_caches: true, prefill_caches: true,
}; };