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::{
autoderef,
diagnostics::{expr::ExprValidator, unsafe_check::UnsafeValidator},
display::{HirDisplayError, HirFormatter},
method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs,
TraitEnvironment, Ty, TyDefId, TypeCtor,
@ -678,13 +677,7 @@ impl Function {
}
pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
let _p = profile("Function::diagnostics");
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);
hir_ty::diagnostics::validate_body(db, self.id.into(), sink)
}
}

View file

@ -6,12 +6,25 @@ pub mod unsafe_check;
use std::any::Any;
use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile};
use ra_prof::profile;
use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
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};
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)]
pub struct NoSuchField {
pub file: HirFileId,

View file

@ -2,7 +2,7 @@
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 ra_syntax::{ast, AstPtr};
use rustc_hash::FxHashSet;
@ -30,23 +30,23 @@ pub use hir_def::{
LocalFieldId, Lookup, VariantId,
};
pub struct ExprValidator<'a, 'b: 'a> {
func: FunctionId,
pub(super) struct ExprValidator<'a, 'b: 'a> {
owner: DefWithBodyId,
infer: Arc<InferenceResult>,
sink: &'a mut DiagnosticSink<'b>,
}
impl<'a, 'b> ExprValidator<'a, 'b> {
pub fn new(
func: FunctionId,
pub(super) fn new(
owner: DefWithBodyId,
infer: Arc<InferenceResult>,
sink: &'a mut DiagnosticSink<'b>,
) -> ExprValidator<'a, 'b> {
ExprValidator { func, infer, sink }
ExprValidator { owner, infer, sink }
}
pub fn validate_body(&mut self, db: &dyn HirDatabase) {
let body = db.body(self.func.into());
pub(super) fn validate_body(&mut self, db: &dyn HirDatabase) {
let body = db.body(self.owner.into());
for (id, expr) in body.exprs.iter() {
if let Some((variant_def, missed_fields, true)) =
@ -96,7 +96,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
missed_fields: Vec<LocalFieldId>,
) {
// 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) {
let root = source_ptr.file_syntax(db.upcast());
@ -125,7 +125,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
missed_fields: Vec<LocalFieldId>,
) {
// 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 Some(expr) = source_ptr.value.as_ref().left() {
@ -181,7 +181,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
let mut arg_count = args.len();
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 is_method_call {
param_count -= 1;
@ -208,7 +208,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
infer: Arc<InferenceResult>,
) {
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) {
Some(ty) => ty,
@ -289,7 +289,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
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) {
Some(it) => it,
_ => return,
@ -304,7 +304,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
};
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) {
self.sink

View file

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

View file

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

View file

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