Skip to content

Commit 5efcfe5

Browse files
committed
Auto merge of #14244 - Veykril:metrics, r=lnicola
internal: Report type metrics for patterns ``` ❯ cargo run --release -p rust-analyzer -q analysis-stats --memory-usage . Database loaded: 2.09s, 218mb (metadata 275.07ms, 21mb; build 1.29s, 504kb) crates: 44, mods: 916, decls: 19582, fns: 14631 Item Collection: 14.33s, 472mb exprs: 420422, ??ty: 68 (0%), ?ty: 141 (0%), !ty: 1 pats: 82968, ??ty: 11 (0%), ?ty: 10 (0%), !ty: 178 Inference: 47.84s, 745mb Total: 62.16s, 1217mb ``` We currently have 178 mismatches on r-a itself
2 parents 4b330f5 + 800ab65 commit 5efcfe5

File tree

1 file changed

+179
-8
lines changed

1 file changed

+179
-8
lines changed

crates/rust-analyzer/src/cli/analysis_stats.rs

Lines changed: 179 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use hir::{
1212
};
1313
use hir_def::{
1414
body::{BodySourceMap, SyntheticSyntax},
15-
expr::ExprId,
15+
expr::{ExprId, PatId},
1616
FunctionId,
1717
};
1818
use hir_ty::{Interner, TyExt, TypeFlags};
@@ -222,7 +222,11 @@ impl flags::AnalysisStats {
222222
let mut num_exprs = 0;
223223
let mut num_exprs_unknown = 0;
224224
let mut num_exprs_partially_unknown = 0;
225-
let mut num_type_mismatches = 0;
225+
let mut num_expr_type_mismatches = 0;
226+
let mut num_pats = 0;
227+
let mut num_pats_unknown = 0;
228+
let mut num_pats_partially_unknown = 0;
229+
let mut num_pat_type_mismatches = 0;
226230
let analysis = host.analysis();
227231
for f in funcs.iter().copied() {
228232
let name = f.name(db);
@@ -255,6 +259,8 @@ impl flags::AnalysisStats {
255259
let f_id = FunctionId::from(f);
256260
let (body, sm) = db.body_with_source_map(f_id.into());
257261
let inference_result = db.infer(f_id.into());
262+
263+
// region:expressions
258264
let (previous_exprs, previous_unknown, previous_partially_unknown) =
259265
(num_exprs, num_exprs_unknown, num_exprs_partially_unknown);
260266
for (expr_id, _) in body.exprs.iter() {
@@ -307,12 +313,12 @@ impl flags::AnalysisStats {
307313
if unknown_or_partial && self.output == Some(OutputFormat::Csv) {
308314
println!(
309315
r#"{},type,"{}""#,
310-
location_csv(db, &analysis, vfs, &sm, expr_id),
316+
location_csv_expr(db, &analysis, vfs, &sm, expr_id),
311317
ty.display(db)
312318
);
313319
}
314320
if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) {
315-
num_type_mismatches += 1;
321+
num_expr_type_mismatches += 1;
316322
if verbosity.is_verbose() {
317323
if let Some((path, start, end)) =
318324
expr_syntax_range(db, &analysis, vfs, &sm, expr_id)
@@ -339,7 +345,7 @@ impl flags::AnalysisStats {
339345
if self.output == Some(OutputFormat::Csv) {
340346
println!(
341347
r#"{},mismatch,"{}","{}""#,
342-
location_csv(db, &analysis, vfs, &sm, expr_id),
348+
location_csv_expr(db, &analysis, vfs, &sm, expr_id),
343349
mismatch.expected.display(db),
344350
mismatch.actual.display(db)
345351
);
@@ -355,6 +361,109 @@ impl flags::AnalysisStats {
355361
num_exprs_partially_unknown - previous_partially_unknown
356362
));
357363
}
364+
// endregion:expressions
365+
366+
// region:patterns
367+
let (previous_pats, previous_unknown, previous_partially_unknown) =
368+
(num_pats, num_pats_unknown, num_pats_partially_unknown);
369+
for (pat_id, _) in body.pats.iter() {
370+
let ty = &inference_result[pat_id];
371+
num_pats += 1;
372+
let unknown_or_partial = if ty.is_unknown() {
373+
num_pats_unknown += 1;
374+
if verbosity.is_spammy() {
375+
if let Some((path, start, end)) =
376+
pat_syntax_range(db, &analysis, vfs, &sm, pat_id)
377+
{
378+
bar.println(format!(
379+
"{} {}:{}-{}:{}: Unknown type",
380+
path,
381+
start.line + 1,
382+
start.col,
383+
end.line + 1,
384+
end.col,
385+
));
386+
} else {
387+
bar.println(format!("{name}: Unknown type",));
388+
}
389+
}
390+
true
391+
} else {
392+
let is_partially_unknown =
393+
ty.data(Interner).flags.contains(TypeFlags::HAS_ERROR);
394+
if is_partially_unknown {
395+
num_pats_partially_unknown += 1;
396+
}
397+
is_partially_unknown
398+
};
399+
if self.only.is_some() && verbosity.is_spammy() {
400+
// in super-verbose mode for just one function, we print every single pattern
401+
if let Some((_, start, end)) = pat_syntax_range(db, &analysis, vfs, &sm, pat_id)
402+
{
403+
bar.println(format!(
404+
"{}:{}-{}:{}: {}",
405+
start.line + 1,
406+
start.col,
407+
end.line + 1,
408+
end.col,
409+
ty.display(db)
410+
));
411+
} else {
412+
bar.println(format!("unknown location: {}", ty.display(db)));
413+
}
414+
}
415+
if unknown_or_partial && self.output == Some(OutputFormat::Csv) {
416+
println!(
417+
r#"{},type,"{}""#,
418+
location_csv_pat(db, &analysis, vfs, &sm, pat_id),
419+
ty.display(db)
420+
);
421+
}
422+
if let Some(mismatch) = inference_result.type_mismatch_for_pat(pat_id) {
423+
num_pat_type_mismatches += 1;
424+
if verbosity.is_verbose() {
425+
if let Some((path, start, end)) =
426+
pat_syntax_range(db, &analysis, vfs, &sm, pat_id)
427+
{
428+
bar.println(format!(
429+
"{} {}:{}-{}:{}: Expected {}, got {}",
430+
path,
431+
start.line + 1,
432+
start.col,
433+
end.line + 1,
434+
end.col,
435+
mismatch.expected.display(db),
436+
mismatch.actual.display(db)
437+
));
438+
} else {
439+
bar.println(format!(
440+
"{}: Expected {}, got {}",
441+
name,
442+
mismatch.expected.display(db),
443+
mismatch.actual.display(db)
444+
));
445+
}
446+
}
447+
if self.output == Some(OutputFormat::Csv) {
448+
println!(
449+
r#"{},mismatch,"{}","{}""#,
450+
location_csv_pat(db, &analysis, vfs, &sm, pat_id),
451+
mismatch.expected.display(db),
452+
mismatch.actual.display(db)
453+
);
454+
}
455+
}
456+
}
457+
if verbosity.is_spammy() {
458+
bar.println(format!(
459+
"In {}: {} pats, {} unknown, {} partial",
460+
full_name,
461+
num_pats - previous_pats,
462+
num_pats_unknown - previous_unknown,
463+
num_pats_partially_unknown - previous_partially_unknown
464+
));
465+
}
466+
// endregion:patterns
358467
bar.inc(1);
359468
}
360469

@@ -366,10 +475,21 @@ impl flags::AnalysisStats {
366475
percentage(num_exprs_unknown, num_exprs),
367476
num_exprs_partially_unknown,
368477
percentage(num_exprs_partially_unknown, num_exprs),
369-
num_type_mismatches
478+
num_expr_type_mismatches
479+
);
480+
eprintln!(
481+
" pats: {}, ??ty: {} ({}%), ?ty: {} ({}%), !ty: {}",
482+
num_pats,
483+
num_pats_unknown,
484+
percentage(num_pats_unknown, num_pats),
485+
num_pats_partially_unknown,
486+
percentage(num_pats_partially_unknown, num_pats),
487+
num_pat_type_mismatches
370488
);
371489
report_metric("unknown type", num_exprs_unknown, "#");
372-
report_metric("type mismatches", num_type_mismatches, "#");
490+
report_metric("type mismatches", num_expr_type_mismatches, "#");
491+
report_metric("pattern unknown type", num_pats_unknown, "#");
492+
report_metric("pattern type mismatches", num_pat_type_mismatches, "#");
373493

374494
eprintln!("{:<20} {}", "Inference:", inference_sw.elapsed());
375495
}
@@ -379,7 +499,7 @@ impl flags::AnalysisStats {
379499
}
380500
}
381501

382-
fn location_csv(
502+
fn location_csv_expr(
383503
db: &RootDatabase,
384504
analysis: &Analysis,
385505
vfs: &Vfs,
@@ -401,6 +521,30 @@ fn location_csv(
401521
format!("{path},{}:{},{}:{}", start.line + 1, start.col, end.line + 1, end.col)
402522
}
403523

524+
fn location_csv_pat(
525+
db: &RootDatabase,
526+
analysis: &Analysis,
527+
vfs: &Vfs,
528+
sm: &BodySourceMap,
529+
pat_id: PatId,
530+
) -> String {
531+
let src = match sm.pat_syntax(pat_id) {
532+
Ok(s) => s,
533+
Err(SyntheticSyntax) => return "synthetic,,".to_string(),
534+
};
535+
let root = db.parse_or_expand(src.file_id).unwrap();
536+
let node = src.map(|e| {
537+
e.either(|it| it.to_node(&root).syntax().clone(), |it| it.to_node(&root).syntax().clone())
538+
});
539+
let original_range = node.as_ref().original_file_range(db);
540+
let path = vfs.file_path(original_range.file_id);
541+
let line_index = analysis.file_line_index(original_range.file_id).unwrap();
542+
let text_range = original_range.range;
543+
let (start, end) =
544+
(line_index.line_col(text_range.start()), line_index.line_col(text_range.end()));
545+
format!("{path},{}:{},{}:{}", start.line + 1, start.col, end.line + 1, end.col)
546+
}
547+
404548
fn expr_syntax_range(
405549
db: &RootDatabase,
406550
analysis: &Analysis,
@@ -423,6 +567,33 @@ fn expr_syntax_range(
423567
None
424568
}
425569
}
570+
fn pat_syntax_range(
571+
db: &RootDatabase,
572+
analysis: &Analysis,
573+
vfs: &Vfs,
574+
sm: &BodySourceMap,
575+
pat_id: PatId,
576+
) -> Option<(VfsPath, LineCol, LineCol)> {
577+
let src = sm.pat_syntax(pat_id);
578+
if let Ok(src) = src {
579+
let root = db.parse_or_expand(src.file_id).unwrap();
580+
let node = src.map(|e| {
581+
e.either(
582+
|it| it.to_node(&root).syntax().clone(),
583+
|it| it.to_node(&root).syntax().clone(),
584+
)
585+
});
586+
let original_range = node.as_ref().original_file_range(db);
587+
let path = vfs.file_path(original_range.file_id);
588+
let line_index = analysis.file_line_index(original_range.file_id).unwrap();
589+
let text_range = original_range.range;
590+
let (start, end) =
591+
(line_index.line_col(text_range.start()), line_index.line_col(text_range.end()));
592+
Some((path, start, end))
593+
} else {
594+
None
595+
}
596+
}
426597

427598
fn shuffle<T>(rng: &mut Rand32, slice: &mut [T]) {
428599
for i in 0..slice.len() {

0 commit comments

Comments
 (0)