mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Report type metrics for patterns
This commit is contained in:
parent
7c092a13bf
commit
c12fac698f
@ -12,7 +12,7 @@ use hir::{
|
|||||||
};
|
};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
body::{BodySourceMap, SyntheticSyntax},
|
body::{BodySourceMap, SyntheticSyntax},
|
||||||
expr::ExprId,
|
expr::{ExprId, PatId},
|
||||||
FunctionId,
|
FunctionId,
|
||||||
};
|
};
|
||||||
use hir_ty::{Interner, TyExt, TypeFlags};
|
use hir_ty::{Interner, TyExt, TypeFlags};
|
||||||
@ -222,7 +222,11 @@ impl flags::AnalysisStats {
|
|||||||
let mut num_exprs = 0;
|
let mut num_exprs = 0;
|
||||||
let mut num_exprs_unknown = 0;
|
let mut num_exprs_unknown = 0;
|
||||||
let mut num_exprs_partially_unknown = 0;
|
let mut num_exprs_partially_unknown = 0;
|
||||||
let mut num_type_mismatches = 0;
|
let mut num_expr_type_mismatches = 0;
|
||||||
|
let mut num_pats = 0;
|
||||||
|
let mut num_pats_unknown = 0;
|
||||||
|
let mut num_pats_partially_unknown = 0;
|
||||||
|
let mut num_pat_type_mismatches = 0;
|
||||||
let analysis = host.analysis();
|
let analysis = host.analysis();
|
||||||
for f in funcs.iter().copied() {
|
for f in funcs.iter().copied() {
|
||||||
let name = f.name(db);
|
let name = f.name(db);
|
||||||
@ -255,6 +259,8 @@ impl flags::AnalysisStats {
|
|||||||
let f_id = FunctionId::from(f);
|
let f_id = FunctionId::from(f);
|
||||||
let (body, sm) = db.body_with_source_map(f_id.into());
|
let (body, sm) = db.body_with_source_map(f_id.into());
|
||||||
let inference_result = db.infer(f_id.into());
|
let inference_result = db.infer(f_id.into());
|
||||||
|
|
||||||
|
// region:expressions
|
||||||
let (previous_exprs, previous_unknown, previous_partially_unknown) =
|
let (previous_exprs, previous_unknown, previous_partially_unknown) =
|
||||||
(num_exprs, num_exprs_unknown, num_exprs_partially_unknown);
|
(num_exprs, num_exprs_unknown, num_exprs_partially_unknown);
|
||||||
for (expr_id, _) in body.exprs.iter() {
|
for (expr_id, _) in body.exprs.iter() {
|
||||||
@ -307,12 +313,12 @@ impl flags::AnalysisStats {
|
|||||||
if unknown_or_partial && self.output == Some(OutputFormat::Csv) {
|
if unknown_or_partial && self.output == Some(OutputFormat::Csv) {
|
||||||
println!(
|
println!(
|
||||||
r#"{},type,"{}""#,
|
r#"{},type,"{}""#,
|
||||||
location_csv(db, &analysis, vfs, &sm, expr_id),
|
location_csv_expr(db, &analysis, vfs, &sm, expr_id),
|
||||||
ty.display(db)
|
ty.display(db)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) {
|
if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) {
|
||||||
num_type_mismatches += 1;
|
num_expr_type_mismatches += 1;
|
||||||
if verbosity.is_verbose() {
|
if verbosity.is_verbose() {
|
||||||
if let Some((path, start, end)) =
|
if let Some((path, start, end)) =
|
||||||
expr_syntax_range(db, &analysis, vfs, &sm, expr_id)
|
expr_syntax_range(db, &analysis, vfs, &sm, expr_id)
|
||||||
@ -339,7 +345,7 @@ impl flags::AnalysisStats {
|
|||||||
if self.output == Some(OutputFormat::Csv) {
|
if self.output == Some(OutputFormat::Csv) {
|
||||||
println!(
|
println!(
|
||||||
r#"{},mismatch,"{}","{}""#,
|
r#"{},mismatch,"{}","{}""#,
|
||||||
location_csv(db, &analysis, vfs, &sm, expr_id),
|
location_csv_expr(db, &analysis, vfs, &sm, expr_id),
|
||||||
mismatch.expected.display(db),
|
mismatch.expected.display(db),
|
||||||
mismatch.actual.display(db)
|
mismatch.actual.display(db)
|
||||||
);
|
);
|
||||||
@ -355,6 +361,109 @@ impl flags::AnalysisStats {
|
|||||||
num_exprs_partially_unknown - previous_partially_unknown
|
num_exprs_partially_unknown - previous_partially_unknown
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
// endregion:expressions
|
||||||
|
|
||||||
|
// region:patterns
|
||||||
|
let (previous_pats, previous_unknown, previous_partially_unknown) =
|
||||||
|
(num_pats, num_pats_unknown, num_pats_partially_unknown);
|
||||||
|
for (pat_id, _) in body.pats.iter() {
|
||||||
|
let ty = &inference_result[pat_id];
|
||||||
|
num_pats += 1;
|
||||||
|
let unknown_or_partial = if ty.is_unknown() {
|
||||||
|
num_pats_unknown += 1;
|
||||||
|
if verbosity.is_spammy() {
|
||||||
|
if let Some((path, start, end)) =
|
||||||
|
pat_syntax_range(db, &analysis, vfs, &sm, pat_id)
|
||||||
|
{
|
||||||
|
bar.println(format!(
|
||||||
|
"{} {}:{}-{}:{}: Unknown type",
|
||||||
|
path,
|
||||||
|
start.line + 1,
|
||||||
|
start.col,
|
||||||
|
end.line + 1,
|
||||||
|
end.col,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
bar.println(format!("{name}: Unknown type",));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
let is_partially_unknown =
|
||||||
|
ty.data(Interner).flags.contains(TypeFlags::HAS_ERROR);
|
||||||
|
if is_partially_unknown {
|
||||||
|
num_pats_partially_unknown += 1;
|
||||||
|
}
|
||||||
|
is_partially_unknown
|
||||||
|
};
|
||||||
|
if self.only.is_some() && verbosity.is_spammy() {
|
||||||
|
// in super-verbose mode for just one function, we print every single pattern
|
||||||
|
if let Some((_, start, end)) = pat_syntax_range(db, &analysis, vfs, &sm, pat_id)
|
||||||
|
{
|
||||||
|
bar.println(format!(
|
||||||
|
"{}:{}-{}:{}: {}",
|
||||||
|
start.line + 1,
|
||||||
|
start.col,
|
||||||
|
end.line + 1,
|
||||||
|
end.col,
|
||||||
|
ty.display(db)
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
bar.println(format!("unknown location: {}", ty.display(db)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if unknown_or_partial && self.output == Some(OutputFormat::Csv) {
|
||||||
|
println!(
|
||||||
|
r#"{},type,"{}""#,
|
||||||
|
location_csv_pat(db, &analysis, vfs, &sm, pat_id),
|
||||||
|
ty.display(db)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if let Some(mismatch) = inference_result.type_mismatch_for_pat(pat_id) {
|
||||||
|
num_pat_type_mismatches += 1;
|
||||||
|
if verbosity.is_verbose() {
|
||||||
|
if let Some((path, start, end)) =
|
||||||
|
pat_syntax_range(db, &analysis, vfs, &sm, pat_id)
|
||||||
|
{
|
||||||
|
bar.println(format!(
|
||||||
|
"{} {}:{}-{}:{}: Expected {}, got {}",
|
||||||
|
path,
|
||||||
|
start.line + 1,
|
||||||
|
start.col,
|
||||||
|
end.line + 1,
|
||||||
|
end.col,
|
||||||
|
mismatch.expected.display(db),
|
||||||
|
mismatch.actual.display(db)
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
bar.println(format!(
|
||||||
|
"{}: Expected {}, got {}",
|
||||||
|
name,
|
||||||
|
mismatch.expected.display(db),
|
||||||
|
mismatch.actual.display(db)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.output == Some(OutputFormat::Csv) {
|
||||||
|
println!(
|
||||||
|
r#"{},mismatch,"{}","{}""#,
|
||||||
|
location_csv_pat(db, &analysis, vfs, &sm, pat_id),
|
||||||
|
mismatch.expected.display(db),
|
||||||
|
mismatch.actual.display(db)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if verbosity.is_spammy() {
|
||||||
|
bar.println(format!(
|
||||||
|
"In {}: {} pats, {} unknown, {} partial",
|
||||||
|
full_name,
|
||||||
|
num_pats - previous_pats,
|
||||||
|
num_pats_unknown - previous_unknown,
|
||||||
|
num_pats_partially_unknown - previous_partially_unknown
|
||||||
|
));
|
||||||
|
}
|
||||||
|
// endregion:patterns
|
||||||
bar.inc(1);
|
bar.inc(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,10 +475,19 @@ impl flags::AnalysisStats {
|
|||||||
percentage(num_exprs_unknown, num_exprs),
|
percentage(num_exprs_unknown, num_exprs),
|
||||||
num_exprs_partially_unknown,
|
num_exprs_partially_unknown,
|
||||||
percentage(num_exprs_partially_unknown, num_exprs),
|
percentage(num_exprs_partially_unknown, num_exprs),
|
||||||
num_type_mismatches
|
num_expr_type_mismatches
|
||||||
);
|
);
|
||||||
report_metric("unknown type", num_exprs_unknown, "#");
|
eprintln!(
|
||||||
report_metric("type mismatches", num_type_mismatches, "#");
|
" pats: {}, ??ty: {} ({}%), ?ty: {} ({}%), !ty: {}",
|
||||||
|
num_pats,
|
||||||
|
num_pats_unknown,
|
||||||
|
percentage(num_pats_unknown, num_pats),
|
||||||
|
num_pats_partially_unknown,
|
||||||
|
percentage(num_pats_partially_unknown, num_pats),
|
||||||
|
num_pat_type_mismatches
|
||||||
|
);
|
||||||
|
report_metric("unknown type", num_exprs_unknown + num_pats_unknown, "#");
|
||||||
|
report_metric("type mismatches", num_expr_type_mismatches + num_pat_type_mismatches, "#");
|
||||||
|
|
||||||
eprintln!("{:<20} {}", "Inference:", inference_sw.elapsed());
|
eprintln!("{:<20} {}", "Inference:", inference_sw.elapsed());
|
||||||
}
|
}
|
||||||
@ -379,7 +497,7 @@ impl flags::AnalysisStats {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn location_csv(
|
fn location_csv_expr(
|
||||||
db: &RootDatabase,
|
db: &RootDatabase,
|
||||||
analysis: &Analysis,
|
analysis: &Analysis,
|
||||||
vfs: &Vfs,
|
vfs: &Vfs,
|
||||||
@ -401,6 +519,30 @@ fn location_csv(
|
|||||||
format!("{path},{}:{},{}:{}", start.line + 1, start.col, end.line + 1, end.col)
|
format!("{path},{}:{},{}:{}", start.line + 1, start.col, end.line + 1, end.col)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn location_csv_pat(
|
||||||
|
db: &RootDatabase,
|
||||||
|
analysis: &Analysis,
|
||||||
|
vfs: &Vfs,
|
||||||
|
sm: &BodySourceMap,
|
||||||
|
pat_id: PatId,
|
||||||
|
) -> String {
|
||||||
|
let src = match sm.pat_syntax(pat_id) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(SyntheticSyntax) => return "synthetic,,".to_string(),
|
||||||
|
};
|
||||||
|
let root = db.parse_or_expand(src.file_id).unwrap();
|
||||||
|
let node = src.map(|e| {
|
||||||
|
e.either(|it| it.to_node(&root).syntax().clone(), |it| it.to_node(&root).syntax().clone())
|
||||||
|
});
|
||||||
|
let original_range = node.as_ref().original_file_range(db);
|
||||||
|
let path = vfs.file_path(original_range.file_id);
|
||||||
|
let line_index = analysis.file_line_index(original_range.file_id).unwrap();
|
||||||
|
let text_range = original_range.range;
|
||||||
|
let (start, end) =
|
||||||
|
(line_index.line_col(text_range.start()), line_index.line_col(text_range.end()));
|
||||||
|
format!("{path},{}:{},{}:{}", start.line + 1, start.col, end.line + 1, end.col)
|
||||||
|
}
|
||||||
|
|
||||||
fn expr_syntax_range(
|
fn expr_syntax_range(
|
||||||
db: &RootDatabase,
|
db: &RootDatabase,
|
||||||
analysis: &Analysis,
|
analysis: &Analysis,
|
||||||
@ -423,6 +565,33 @@ fn expr_syntax_range(
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn pat_syntax_range(
|
||||||
|
db: &RootDatabase,
|
||||||
|
analysis: &Analysis,
|
||||||
|
vfs: &Vfs,
|
||||||
|
sm: &BodySourceMap,
|
||||||
|
pat_id: PatId,
|
||||||
|
) -> Option<(VfsPath, LineCol, LineCol)> {
|
||||||
|
let src = sm.pat_syntax(pat_id);
|
||||||
|
if let Ok(src) = src {
|
||||||
|
let root = db.parse_or_expand(src.file_id).unwrap();
|
||||||
|
let node = src.map(|e| {
|
||||||
|
e.either(
|
||||||
|
|it| it.to_node(&root).syntax().clone(),
|
||||||
|
|it| it.to_node(&root).syntax().clone(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
let original_range = node.as_ref().original_file_range(db);
|
||||||
|
let path = vfs.file_path(original_range.file_id);
|
||||||
|
let line_index = analysis.file_line_index(original_range.file_id).unwrap();
|
||||||
|
let text_range = original_range.range;
|
||||||
|
let (start, end) =
|
||||||
|
(line_index.line_col(text_range.start()), line_index.line_col(text_range.end()));
|
||||||
|
Some((path, start, end))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn shuffle<T>(rng: &mut Rand32, slice: &mut [T]) {
|
fn shuffle<T>(rng: &mut Rand32, slice: &mut [T]) {
|
||||||
for i in 0..slice.len() {
|
for i in 0..slice.len() {
|
||||||
|
Loading…
Reference in New Issue
Block a user