diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 9222009fec..42c9ca189f 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -25,11 +25,8 @@ use hir_expand::{ use hir_ty::{ autoderef, display::{HirDisplayError, HirFormatter}, - expr::ExprValidator, - method_resolution, - unsafe_validation::UnsafeValidator, - ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs, TraitEnvironment, Ty, - TyDefId, TypeCtor, + method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs, + TraitEnvironment, Ty, TyDefId, TypeCtor, }; use ra_db::{CrateId, Edition, FileId}; use ra_prof::profile; @@ -680,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) } } diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index f74b78b237..bfa543e5b6 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs @@ -18,7 +18,7 @@ use hir_def::{ }; use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; use hir_ty::{ - expr::{record_literal_missing_fields, record_pattern_missing_fields}, + diagnostics::expr::{record_literal_missing_fields, record_pattern_missing_fields}, InferenceResult, Substs, Ty, }; use ra_syntax::{ diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index 5b0dda634f..d9c2b1214f 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs @@ -1,14 +1,30 @@ //! FIXME: write short doc here +pub mod expr; +mod match_check; +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, diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/diagnostics/expr.rs similarity index 94% rename from crates/ra_hir_ty/src/expr.rs rename to crates/ra_hir_ty/src/diagnostics/expr.rs index d44562b227..239be779fa 100644 --- a/crates/ra_hir_ty/src/expr.rs +++ b/crates/ra_hir_ty/src/diagnostics/expr.rs @@ -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; @@ -10,9 +10,9 @@ use rustc_hash::FxHashSet; use crate::{ db::HirDatabase, diagnostics::{ + match_check::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness}, MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, MissingPatFields, }, - match_checking::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness}, utils::variant_data, ApplicationTy, InferenceResult, Ty, TypeCtor, }; @@ -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, sink: &'a mut DiagnosticSink<'b>, } impl<'a, 'b> ExprValidator<'a, 'b> { - pub fn new( - func: FunctionId, + pub(super) fn new( + owner: DefWithBodyId, infer: Arc, 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, ) { // 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, ) { // 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, ) { let (body, source_map): (Arc, Arc) = - 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 diff --git a/crates/ra_hir_ty/src/match_checking.rs b/crates/ra_hir_ty/src/diagnostics/match_check.rs similarity index 99% rename from crates/ra_hir_ty/src/match_checking.rs rename to crates/ra_hir_ty/src/diagnostics/match_check.rs index 5495ce284f..722c0e9eea 100644 --- a/crates/ra_hir_ty/src/match_checking.rs +++ b/crates/ra_hir_ty/src/diagnostics/match_check.rs @@ -218,15 +218,16 @@ //! ``` use std::sync::Arc; +use hir_def::{ + adt::VariantData, + body::Body, + expr::{Expr, Literal, Pat, PatId}, + AdtId, EnumVariantId, VariantId, +}; +use ra_arena::Idx; use smallvec::{smallvec, SmallVec}; -use crate::{ - db::HirDatabase, - expr::{Body, Expr, Literal, Pat, PatId}, - ApplicationTy, InferenceResult, Ty, TypeCtor, -}; -use hir_def::{adt::VariantData, AdtId, EnumVariantId, VariantId}; -use ra_arena::Idx; +use crate::{db::HirDatabase, ApplicationTy, InferenceResult, Ty, TypeCtor}; #[derive(Debug, Clone, Copy)] /// Either a pattern from the source code being analyzed, represented as diff --git a/crates/ra_hir_ty/src/unsafe_validation.rs b/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs similarity index 85% rename from crates/ra_hir_ty/src/unsafe_validation.rs rename to crates/ra_hir_ty/src/diagnostics/unsafe_check.rs index c512c4f8e9..b8ff95ee1e 100644 --- a/crates/ra_hir_ty/src/unsafe_validation.rs +++ b/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs @@ -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, sink: &'a mut DiagnosticSink<'b>, } impl<'a, 'b> UnsafeValidator<'a, 'b> { - pub fn new( - func: FunctionId, + pub(super) fn new( + owner: DefWithBodyId, infer: Arc, 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) diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 2ce4f65ccc..28f32a0a4d 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -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"); diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 2652d200f5..d54568e67a 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -12,15 +12,12 @@ pub mod traits; pub mod method_resolution; mod op; mod lower; -mod match_checking; pub(crate) mod infer; pub(crate) mod utils; pub mod display; pub mod db; pub mod diagnostics; -pub mod expr; -pub mod unsafe_validation; #[cfg(test)] mod tests; diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs index dc447955f7..daf2b909eb 100644 --- a/crates/ra_hir_ty/src/test_db.rs +++ b/crates/ra_hir_ty/src/test_db.rs @@ -13,10 +13,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; use stdx::format_to; use test_utils::extract_annotations; -use crate::{ - db::HirDatabase, diagnostics::Diagnostic, expr::ExprValidator, - unsafe_validation::UnsafeValidator, -}; +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); } } }