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
+1 -8
View File
@@ -24,7 +24,6 @@
};
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 @@ pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
}
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)
}
}
+14 -1
View File
@@ -6,12 +6,25 @@
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,
+14 -14
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 @@
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 @@ fn create_record_literal_missing_fields_diagnostic(
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 @@ fn create_record_pattern_missing_fields_diagnostic(
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 @@ fn validate_call(&mut self, db: &dyn HirDatabase, call_id: ExprId, expr: &Expr)
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 @@ fn validate_match(
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 @@ fn validate_results_in_tail_expr(&mut self, body_id: ExprId, id: ExprId, db: &dy
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 @@ fn validate_results_in_tail_expr(&mut self, body_id: ExprId, id: ExprId, db: &dy
};
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
@@ -6,7 +6,7 @@
use hir_def::{
body::Body,
expr::{Expr, ExprId, UnaryOp},
DefWithBodyId, FunctionId,
DefWithBodyId,
};
use hir_expand::diagnostics::DiagnosticSink;
@@ -15,26 +15,29 @@
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)
+5 -5
View File
@@ -168,7 +168,7 @@ pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {
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 @@ fn bitor_assign(&mut self, other: Self) {
}
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 @@ impl InferenceDiagnostic {
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");
+2 -10
View File
@@ -13,10 +13,7 @@
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 @@ fn diag<F: FnMut(&dyn Diagnostic)>(&self, mut cb: F) {
}
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);
}
}
}