mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-16 18:44:56 +00:00
Merge #1737
1737: Report type mismatches in analysis-stats r=matklad a=flodiebold
Only the number usually; each one individually when running with `-v`.
Getting the file/line locations for the exprs was really annoying and I had to make some stuff public (that I didn't remember why it would be `pub(crate)`); maybe I missed some easier way? It would be nice to have some general way for mapping locations 🤔
This reports 1768 mismatches on RA currently; from skimming, this seems to be mostly various kinds of coercions, though there were also some other things.
Co-authored-by: Florian Diebold <flodiebold@gmail.com>
This commit is contained in:
commit
f39f72db57
@ -1,7 +1,7 @@
|
||||
use std::{collections::HashSet, fmt::Write, path::Path, time::Instant};
|
||||
|
||||
use ra_db::SourceDatabase;
|
||||
use ra_hir::{Crate, HasSource, ImplItem, ModuleDef, Ty};
|
||||
use ra_hir::{Crate, HasBodySource, HasSource, HirDisplay, ImplItem, ModuleDef, Ty};
|
||||
use ra_syntax::AstNode;
|
||||
|
||||
use crate::Result;
|
||||
@ -66,6 +66,7 @@ pub fn run(verbose: bool, memory_usage: bool, path: &Path, only: Option<&str>) -
|
||||
let mut num_exprs = 0;
|
||||
let mut num_exprs_unknown = 0;
|
||||
let mut num_exprs_partially_unknown = 0;
|
||||
let mut num_type_mismatches = 0;
|
||||
for f in funcs {
|
||||
let name = f.name(db);
|
||||
let mut msg = format!("processing: {}", name);
|
||||
@ -100,6 +101,39 @@ pub fn run(verbose: bool, memory_usage: bool, path: &Path, only: Option<&str>) -
|
||||
num_exprs_partially_unknown += 1;
|
||||
}
|
||||
}
|
||||
if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) {
|
||||
num_type_mismatches += 1;
|
||||
if verbose {
|
||||
let src = f.expr_source(db, expr_id);
|
||||
if let Some(src) = src {
|
||||
// FIXME: it might be nice to have a function (on Analysis?) that goes from Source<T> -> (LineCol, LineCol) directly
|
||||
let original_file = src.file_id.original_file(db);
|
||||
let path = db.file_relative_path(original_file);
|
||||
let line_index = host.analysis().file_line_index(original_file).unwrap();
|
||||
let (start, end) = (
|
||||
line_index.line_col(src.ast.syntax().text_range().start()),
|
||||
line_index.line_col(src.ast.syntax().text_range().end()),
|
||||
);
|
||||
bar.println(format!(
|
||||
"{} {}:{}-{}:{}: Expected {}, got {}",
|
||||
path.display(),
|
||||
start.line + 1,
|
||||
start.col_utf16,
|
||||
end.line + 1,
|
||||
end.col_utf16,
|
||||
mismatch.expected.display(db),
|
||||
mismatch.actual.display(db)
|
||||
));
|
||||
} else {
|
||||
bar.println(format!(
|
||||
"{}: Expected {}, got {}",
|
||||
name,
|
||||
mismatch.expected.display(db),
|
||||
mismatch.actual.display(db)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bar.inc(1);
|
||||
}
|
||||
@ -115,6 +149,7 @@ pub fn run(verbose: bool, memory_usage: bool, path: &Path, only: Option<&str>) -
|
||||
num_exprs_partially_unknown,
|
||||
(num_exprs_partially_unknown * 100 / num_exprs)
|
||||
);
|
||||
println!("Type mismatches: {}", num_type_mismatches);
|
||||
println!("Inference: {:?}, {}", inference_time.elapsed(), ra_prof::memory_usage());
|
||||
println!("Total: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage());
|
||||
|
||||
|
@ -510,18 +510,6 @@ pub enum DefWithBody {
|
||||
impl_froms!(DefWithBody: Function, Const, Static);
|
||||
|
||||
impl DefWithBody {
|
||||
pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
|
||||
db.infer(self)
|
||||
}
|
||||
|
||||
pub fn body(self, db: &impl HirDatabase) -> Arc<Body> {
|
||||
db.body_hir(self)
|
||||
}
|
||||
|
||||
pub fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
|
||||
db.body_with_source_map(self).1
|
||||
}
|
||||
|
||||
/// Builds a resolver for code inside this item.
|
||||
pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
|
||||
match self {
|
||||
@ -532,6 +520,43 @@ impl DefWithBody {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HasBody: Copy {
|
||||
fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult>;
|
||||
fn body(self, db: &impl HirDatabase) -> Arc<Body>;
|
||||
fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap>;
|
||||
}
|
||||
|
||||
impl<T> HasBody for T
|
||||
where
|
||||
T: Into<DefWithBody> + Copy + HasSource,
|
||||
{
|
||||
fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
|
||||
db.infer(self.into())
|
||||
}
|
||||
|
||||
fn body(self, db: &impl HirDatabase) -> Arc<Body> {
|
||||
db.body_hir(self.into())
|
||||
}
|
||||
|
||||
fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
|
||||
db.body_with_source_map(self.into()).1
|
||||
}
|
||||
}
|
||||
|
||||
impl HasBody for DefWithBody {
|
||||
fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
|
||||
db.infer(self)
|
||||
}
|
||||
|
||||
fn body(self, db: &impl HirDatabase) -> Arc<Body> {
|
||||
db.body_hir(self)
|
||||
}
|
||||
|
||||
fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
|
||||
db.body_with_source_map(self).1
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Function {
|
||||
pub(crate) id: FunctionId,
|
||||
|
@ -1,9 +1,9 @@
|
||||
use ra_syntax::ast;
|
||||
use ra_syntax::ast::{self, AstNode};
|
||||
|
||||
use crate::{
|
||||
ids::AstItemDef, AstDatabase, Const, DefDatabase, Enum, EnumVariant, FieldSource, Function,
|
||||
HirFileId, MacroDef, Module, ModuleSource, Static, Struct, StructField, Trait, TypeAlias,
|
||||
Union,
|
||||
HasBody, HirDatabase, HirFileId, MacroDef, Module, ModuleSource, Static, Struct, StructField,
|
||||
Trait, TypeAlias, Union,
|
||||
};
|
||||
|
||||
pub struct Source<T> {
|
||||
@ -108,3 +108,27 @@ impl HasSource for MacroDef {
|
||||
Source { file_id: self.id.0.file_id(), ast: self.id.0.to_node(db) }
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HasBodySource: HasBody + HasSource
|
||||
where
|
||||
Self::Ast: AstNode,
|
||||
{
|
||||
fn expr_source(
|
||||
self,
|
||||
db: &impl HirDatabase,
|
||||
expr_id: crate::expr::ExprId,
|
||||
) -> Option<Source<ast::Expr>> {
|
||||
let source_map = self.body_source_map(db);
|
||||
let expr_syntax = source_map.expr_syntax(expr_id)?;
|
||||
let source = self.source(db);
|
||||
let node = expr_syntax.to_node(&source.ast.syntax());
|
||||
ast::Expr::cast(node).map(|ast| Source { file_id: source.file_id, ast })
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> HasBodySource for T
|
||||
where
|
||||
T: HasBody + HasSource,
|
||||
T::Ast: AstNode,
|
||||
{
|
||||
}
|
||||
|
@ -75,8 +75,8 @@ pub use self::{
|
||||
|
||||
pub use self::code_model::{
|
||||
docs::{DocDef, Docs, Documentation},
|
||||
src::{HasSource, Source},
|
||||
src::{HasBodySource, HasSource, Source},
|
||||
BuiltinType, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum,
|
||||
EnumVariant, FieldSource, FnData, Function, MacroDef, Module, ModuleDef, ModuleSource, Static,
|
||||
Struct, StructField, Trait, TypeAlias, Union,
|
||||
EnumVariant, FieldSource, FnData, Function, HasBody, MacroDef, Module, ModuleDef, ModuleSource,
|
||||
Static, Struct, StructField, Trait, TypeAlias, Union,
|
||||
};
|
||||
|
@ -27,9 +27,9 @@ use crate::{
|
||||
name,
|
||||
path::{PathKind, PathSegment},
|
||||
ty::method_resolution::implements_trait,
|
||||
AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HirDatabase, HirFileId,
|
||||
MacroDef, Module, ModuleDef, Name, Path, PerNs, Resolution, Resolver, Static, Struct, Trait,
|
||||
Ty,
|
||||
AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HasBody, HirDatabase,
|
||||
HirFileId, MacroDef, Module, ModuleDef, Name, Path, PerNs, Resolution, Resolver, Static,
|
||||
Struct, Trait, Ty,
|
||||
};
|
||||
|
||||
/// Locates the module by `FileId`. Picks topmost module in the file.
|
||||
|
@ -50,8 +50,8 @@ use crate::{
|
||||
},
|
||||
ty::infer::diagnostics::InferenceDiagnostic,
|
||||
type_ref::{Mutability, TypeRef},
|
||||
AdtDef, ConstData, DefWithBody, FnData, Function, HirDatabase, ImplItem, ModuleDef, Name, Path,
|
||||
StructField,
|
||||
AdtDef, ConstData, DefWithBody, FnData, Function, HasBody, HirDatabase, ImplItem, ModuleDef,
|
||||
Name, Path, StructField,
|
||||
};
|
||||
|
||||
mod unify;
|
||||
|
@ -15,9 +15,8 @@ impl SyntaxNodePtr {
|
||||
SyntaxNodePtr { range: node.text_range(), kind: node.kind() }
|
||||
}
|
||||
|
||||
pub fn to_node(self, root: &SyntaxNode) -> SyntaxNode {
|
||||
assert!(root.parent().is_none());
|
||||
successors(Some(root.clone()), |node| {
|
||||
pub fn to_node(self, parent: &SyntaxNode) -> SyntaxNode {
|
||||
successors(Some(parent.clone()), |node| {
|
||||
node.children().find(|it| self.range.is_subrange(&it.text_range()))
|
||||
})
|
||||
.find(|it| it.text_range() == self.range && it.kind() == self.kind)
|
||||
|
Loading…
Reference in New Issue
Block a user