Cleanup hir diagnostics API

This commit is contained in:
Aleksey Kladov 2020-07-14 10:28:55 +02:00
parent 1fdbf81181
commit 19450534cf
6 changed files with 49 additions and 48 deletions

View File

@ -24,7 +24,6 @@ use hir_expand::{
}; };
use hir_ty::{ use hir_ty::{
autoderef, autoderef,
diagnostics::{expr::ExprValidator, unsafe_check::UnsafeValidator},
display::{HirDisplayError, HirFormatter}, display::{HirDisplayError, HirFormatter},
method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs, method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs,
TraitEnvironment, Ty, TyDefId, TypeCtor, TraitEnvironment, Ty, TyDefId, TypeCtor,
@ -678,13 +677,7 @@ impl Function {
} }
pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
let _p = profile("Function::diagnostics"); hir_ty::diagnostics::validate_body(db, self.id.into(), sink)
let infer = db.infer(self.id.into());
infer.add_diagnostics(db, self.id, sink);
let mut validator = ExprValidator::new(self.id, infer.clone(), sink);
validator.validate_body(db);
let mut validator = UnsafeValidator::new(self.id, infer, sink);
validator.validate_body(db);
} }
} }

View File

@ -6,12 +6,25 @@ pub mod unsafe_check;
use std::any::Any; use std::any::Any;
use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile};
use ra_prof::profile;
use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
use stdx::format_to; use stdx::format_to;
pub use hir_def::{diagnostics::UnresolvedModule, expr::MatchArm, path::Path}; pub use hir_def::{diagnostics::UnresolvedModule, expr::MatchArm, path::Path, DefWithBodyId};
pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
use crate::db::HirDatabase;
pub fn validate_body(db: &dyn HirDatabase, owner: DefWithBodyId, sink: &mut DiagnosticSink<'_>) {
let _p = profile("validate_body");
let infer = db.infer(owner);
infer.add_diagnostics(db, owner, sink);
let mut validator = expr::ExprValidator::new(owner, infer.clone(), sink);
validator.validate_body(db);
let mut validator = unsafe_check::UnsafeValidator::new(owner, infer, sink);
validator.validate_body(db);
}
#[derive(Debug)] #[derive(Debug)]
pub struct NoSuchField { pub struct NoSuchField {
pub file: HirFileId, pub file: HirFileId,

View File

@ -2,7 +2,7 @@
use std::sync::Arc; use std::sync::Arc;
use hir_def::{path::path, resolver::HasResolver, AdtId, FunctionId}; use hir_def::{path::path, resolver::HasResolver, AdtId, DefWithBodyId};
use hir_expand::diagnostics::DiagnosticSink; use hir_expand::diagnostics::DiagnosticSink;
use ra_syntax::{ast, AstPtr}; use ra_syntax::{ast, AstPtr};
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
@ -30,23 +30,23 @@ pub use hir_def::{
LocalFieldId, Lookup, VariantId, LocalFieldId, Lookup, VariantId,
}; };
pub struct ExprValidator<'a, 'b: 'a> { pub(super) struct ExprValidator<'a, 'b: 'a> {
func: FunctionId, owner: DefWithBodyId,
infer: Arc<InferenceResult>, infer: Arc<InferenceResult>,
sink: &'a mut DiagnosticSink<'b>, sink: &'a mut DiagnosticSink<'b>,
} }
impl<'a, 'b> ExprValidator<'a, 'b> { impl<'a, 'b> ExprValidator<'a, 'b> {
pub fn new( pub(super) fn new(
func: FunctionId, owner: DefWithBodyId,
infer: Arc<InferenceResult>, infer: Arc<InferenceResult>,
sink: &'a mut DiagnosticSink<'b>, sink: &'a mut DiagnosticSink<'b>,
) -> ExprValidator<'a, 'b> { ) -> ExprValidator<'a, 'b> {
ExprValidator { func, infer, sink } ExprValidator { owner, infer, sink }
} }
pub fn validate_body(&mut self, db: &dyn HirDatabase) { pub(super) fn validate_body(&mut self, db: &dyn HirDatabase) {
let body = db.body(self.func.into()); let body = db.body(self.owner.into());
for (id, expr) in body.exprs.iter() { for (id, expr) in body.exprs.iter() {
if let Some((variant_def, missed_fields, true)) = if let Some((variant_def, missed_fields, true)) =
@ -96,7 +96,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
missed_fields: Vec<LocalFieldId>, missed_fields: Vec<LocalFieldId>,
) { ) {
// XXX: only look at source_map if we do have missing fields // XXX: only look at source_map if we do have missing fields
let (_, source_map) = db.body_with_source_map(self.func.into()); let (_, source_map) = db.body_with_source_map(self.owner.into());
if let Ok(source_ptr) = source_map.expr_syntax(id) { if let Ok(source_ptr) = source_map.expr_syntax(id) {
let root = source_ptr.file_syntax(db.upcast()); let root = source_ptr.file_syntax(db.upcast());
@ -125,7 +125,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
missed_fields: Vec<LocalFieldId>, missed_fields: Vec<LocalFieldId>,
) { ) {
// XXX: only look at source_map if we do have missing fields // XXX: only look at source_map if we do have missing fields
let (_, source_map) = db.body_with_source_map(self.func.into()); let (_, source_map) = db.body_with_source_map(self.owner.into());
if let Ok(source_ptr) = source_map.pat_syntax(id) { if let Ok(source_ptr) = source_map.pat_syntax(id) {
if let Some(expr) = source_ptr.value.as_ref().left() { if let Some(expr) = source_ptr.value.as_ref().left() {
@ -181,7 +181,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
let mut arg_count = args.len(); let mut arg_count = args.len();
if arg_count != param_count { if arg_count != param_count {
let (_, source_map) = db.body_with_source_map(self.func.into()); let (_, source_map) = db.body_with_source_map(self.owner.into());
if let Ok(source_ptr) = source_map.expr_syntax(call_id) { if let Ok(source_ptr) = source_map.expr_syntax(call_id) {
if is_method_call { if is_method_call {
param_count -= 1; param_count -= 1;
@ -208,7 +208,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
infer: Arc<InferenceResult>, infer: Arc<InferenceResult>,
) { ) {
let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) = let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) =
db.body_with_source_map(self.func.into()); db.body_with_source_map(self.owner.into());
let match_expr_ty = match infer.type_of_expr.get(match_expr) { let match_expr_ty = match infer.type_of_expr.get(match_expr) {
Some(ty) => ty, Some(ty) => ty,
@ -289,7 +289,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
let core_result_path = path![core::result::Result]; let core_result_path = path![core::result::Result];
let resolver = self.func.resolver(db.upcast()); let resolver = self.owner.resolver(db.upcast());
let core_result_enum = match resolver.resolve_known_enum(db.upcast(), &core_result_path) { let core_result_enum = match resolver.resolve_known_enum(db.upcast(), &core_result_path) {
Some(it) => it, Some(it) => it,
_ => return, _ => return,
@ -304,7 +304,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
}; };
if params.len() == 2 && params[0] == mismatch.actual { if params.len() == 2 && params[0] == mismatch.actual {
let (_, source_map) = db.body_with_source_map(self.func.into()); let (_, source_map) = db.body_with_source_map(self.owner.into());
if let Ok(source_ptr) = source_map.expr_syntax(id) { if let Ok(source_ptr) = source_map.expr_syntax(id) {
self.sink self.sink

View File

@ -6,7 +6,7 @@ use std::sync::Arc;
use hir_def::{ use hir_def::{
body::Body, body::Body,
expr::{Expr, ExprId, UnaryOp}, expr::{Expr, ExprId, UnaryOp},
DefWithBodyId, FunctionId, DefWithBodyId,
}; };
use hir_expand::diagnostics::DiagnosticSink; use hir_expand::diagnostics::DiagnosticSink;
@ -15,26 +15,29 @@ use crate::{
InferenceResult, Ty, TypeCtor, InferenceResult, Ty, TypeCtor,
}; };
pub struct UnsafeValidator<'a, 'b: 'a> { pub(super) struct UnsafeValidator<'a, 'b: 'a> {
func: FunctionId, owner: DefWithBodyId,
infer: Arc<InferenceResult>, infer: Arc<InferenceResult>,
sink: &'a mut DiagnosticSink<'b>, sink: &'a mut DiagnosticSink<'b>,
} }
impl<'a, 'b> UnsafeValidator<'a, 'b> { impl<'a, 'b> UnsafeValidator<'a, 'b> {
pub fn new( pub(super) fn new(
func: FunctionId, owner: DefWithBodyId,
infer: Arc<InferenceResult>, infer: Arc<InferenceResult>,
sink: &'a mut DiagnosticSink<'b>, sink: &'a mut DiagnosticSink<'b>,
) -> UnsafeValidator<'a, 'b> { ) -> UnsafeValidator<'a, 'b> {
UnsafeValidator { func, infer, sink } UnsafeValidator { owner, infer, sink }
} }
pub fn validate_body(&mut self, db: &dyn HirDatabase) { pub(super) fn validate_body(&mut self, db: &dyn HirDatabase) {
let def = self.func.into(); let def = self.owner.into();
let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def); let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def);
let func_data = db.function_data(self.func); let is_unsafe = match self.owner {
if func_data.is_unsafe DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe,
DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false,
};
if is_unsafe
|| unsafe_expressions || unsafe_expressions
.iter() .iter()
.filter(|unsafe_expr| !unsafe_expr.inside_unsafe_block) .filter(|unsafe_expr| !unsafe_expr.inside_unsafe_block)

View File

@ -168,7 +168,7 @@ impl InferenceResult {
pub fn add_diagnostics( pub fn add_diagnostics(
&self, &self,
db: &dyn HirDatabase, db: &dyn HirDatabase,
owner: FunctionId, owner: DefWithBodyId,
sink: &mut DiagnosticSink, sink: &mut DiagnosticSink,
) { ) {
self.diagnostics.iter().for_each(|it| it.add_to(db, owner, sink)) self.diagnostics.iter().for_each(|it| it.add_to(db, owner, sink))
@ -760,7 +760,7 @@ impl std::ops::BitOrAssign for Diverges {
} }
mod diagnostics { mod diagnostics {
use hir_def::{expr::ExprId, FunctionId}; use hir_def::{expr::ExprId, DefWithBodyId};
use hir_expand::diagnostics::DiagnosticSink; use hir_expand::diagnostics::DiagnosticSink;
use crate::{ use crate::{
@ -778,17 +778,17 @@ mod diagnostics {
pub(super) fn add_to( pub(super) fn add_to(
&self, &self,
db: &dyn HirDatabase, db: &dyn HirDatabase,
owner: FunctionId, owner: DefWithBodyId,
sink: &mut DiagnosticSink, sink: &mut DiagnosticSink,
) { ) {
match self { match self {
InferenceDiagnostic::NoSuchField { expr, field } => { InferenceDiagnostic::NoSuchField { expr, field } => {
let (_, source_map) = db.body_with_source_map(owner.into()); let (_, source_map) = db.body_with_source_map(owner);
let field = source_map.field_syntax(*expr, *field); let field = source_map.field_syntax(*expr, *field);
sink.push(NoSuchField { file: field.file_id, field: field.value }) sink.push(NoSuchField { file: field.file_id, field: field.value })
} }
InferenceDiagnostic::BreakOutsideOfLoop { expr } => { InferenceDiagnostic::BreakOutsideOfLoop { expr } => {
let (_, source_map) = db.body_with_source_map(owner.into()); let (_, source_map) = db.body_with_source_map(owner);
let ptr = source_map let ptr = source_map
.expr_syntax(*expr) .expr_syntax(*expr)
.expect("break outside of loop in synthetic syntax"); .expect("break outside of loop in synthetic syntax");

View File

@ -13,10 +13,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
use stdx::format_to; use stdx::format_to;
use test_utils::extract_annotations; use test_utils::extract_annotations;
use crate::{ use crate::diagnostics::{validate_body, Diagnostic};
db::HirDatabase,
diagnostics::{expr::ExprValidator, unsafe_check::UnsafeValidator, Diagnostic},
};
#[salsa::database( #[salsa::database(
ra_db::SourceDatabaseExtStorage, ra_db::SourceDatabaseExtStorage,
@ -118,13 +115,8 @@ impl TestDB {
} }
for f in fns { for f in fns {
let infer = self.infer(f.into());
let mut sink = DiagnosticSink::new(&mut cb); let mut sink = DiagnosticSink::new(&mut cb);
infer.add_diagnostics(self, f, &mut sink); validate_body(self, f.into(), &mut sink);
let mut validator = ExprValidator::new(f, infer.clone(), &mut sink);
validator.validate_body(self);
let mut validator = UnsafeValidator::new(f, infer, &mut sink);
validator.validate_body(self);
} }
} }
} }