aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model.rs9
-rw-r--r--crates/ra_hir_ty/src/diagnostics.rs15
-rw-r--r--crates/ra_hir_ty/src/diagnostics/expr.rs28
-rw-r--r--crates/ra_hir_ty/src/diagnostics/unsafe_check.rs23
-rw-r--r--crates/ra_hir_ty/src/infer.rs10
-rw-r--r--crates/ra_hir_ty/src/test_db.rs12
6 files changed, 49 insertions, 48 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index dbda25d1d..42c9ca189 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -24,7 +24,6 @@ use hir_expand::{
24}; 24};
25use hir_ty::{ 25use hir_ty::{
26 autoderef, 26 autoderef,
27 diagnostics::{expr::ExprValidator, unsafe_check::UnsafeValidator},
28 display::{HirDisplayError, HirFormatter}, 27 display::{HirDisplayError, HirFormatter},
29 method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs, 28 method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs,
30 TraitEnvironment, Ty, TyDefId, TypeCtor, 29 TraitEnvironment, Ty, TyDefId, TypeCtor,
@@ -678,13 +677,7 @@ impl Function {
678 } 677 }
679 678
680 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { 679 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
681 let _p = profile("Function::diagnostics"); 680 hir_ty::diagnostics::validate_body(db, self.id.into(), sink)
682 let infer = db.infer(self.id.into());
683 infer.add_diagnostics(db, self.id, sink);
684 let mut validator = ExprValidator::new(self.id, infer.clone(), sink);
685 validator.validate_body(db);
686 let mut validator = UnsafeValidator::new(self.id, infer, sink);
687 validator.validate_body(db);
688 } 681 }
689} 682}
690 683
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs
index 07c7729b3..d9c2b1214 100644
--- a/crates/ra_hir_ty/src/diagnostics.rs
+++ b/crates/ra_hir_ty/src/diagnostics.rs
@@ -6,12 +6,25 @@ pub mod unsafe_check;
6use std::any::Any; 6use std::any::Any;
7 7
8use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; 8use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile};
9use ra_prof::profile;
9use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; 10use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
10use stdx::format_to; 11use stdx::format_to;
11 12
12pub use hir_def::{diagnostics::UnresolvedModule, expr::MatchArm, path::Path}; 13pub use hir_def::{diagnostics::UnresolvedModule, expr::MatchArm, path::Path, DefWithBodyId};
13pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; 14pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
14 15
16use crate::db::HirDatabase;
17
18pub fn validate_body(db: &dyn HirDatabase, owner: DefWithBodyId, sink: &mut DiagnosticSink<'_>) {
19 let _p = profile("validate_body");
20 let infer = db.infer(owner);
21 infer.add_diagnostics(db, owner, sink);
22 let mut validator = expr::ExprValidator::new(owner, infer.clone(), sink);
23 validator.validate_body(db);
24 let mut validator = unsafe_check::UnsafeValidator::new(owner, infer, sink);
25 validator.validate_body(db);
26}
27
15#[derive(Debug)] 28#[derive(Debug)]
16pub struct NoSuchField { 29pub struct NoSuchField {
17 pub file: HirFileId, 30 pub file: HirFileId,
diff --git a/crates/ra_hir_ty/src/diagnostics/expr.rs b/crates/ra_hir_ty/src/diagnostics/expr.rs
index 51c97f801..239be779f 100644
--- a/crates/ra_hir_ty/src/diagnostics/expr.rs
+++ b/crates/ra_hir_ty/src/diagnostics/expr.rs
@@ -2,7 +2,7 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{path::path, resolver::HasResolver, AdtId, FunctionId}; 5use hir_def::{path::path, resolver::HasResolver, AdtId, DefWithBodyId};
6use hir_expand::diagnostics::DiagnosticSink; 6use hir_expand::diagnostics::DiagnosticSink;
7use ra_syntax::{ast, AstPtr}; 7use ra_syntax::{ast, AstPtr};
8use rustc_hash::FxHashSet; 8use rustc_hash::FxHashSet;
@@ -30,23 +30,23 @@ pub use hir_def::{
30 LocalFieldId, Lookup, VariantId, 30 LocalFieldId, Lookup, VariantId,
31}; 31};
32 32
33pub struct ExprValidator<'a, 'b: 'a> { 33pub(super) struct ExprValidator<'a, 'b: 'a> {
34 func: FunctionId, 34 owner: DefWithBodyId,
35 infer: Arc<InferenceResult>, 35 infer: Arc<InferenceResult>,
36 sink: &'a mut DiagnosticSink<'b>, 36 sink: &'a mut DiagnosticSink<'b>,
37} 37}
38 38
39impl<'a, 'b> ExprValidator<'a, 'b> { 39impl<'a, 'b> ExprValidator<'a, 'b> {
40 pub fn new( 40 pub(super) fn new(
41 func: FunctionId, 41 owner: DefWithBodyId,
42 infer: Arc<InferenceResult>, 42 infer: Arc<InferenceResult>,
43 sink: &'a mut DiagnosticSink<'b>, 43 sink: &'a mut DiagnosticSink<'b>,
44 ) -> ExprValidator<'a, 'b> { 44 ) -> ExprValidator<'a, 'b> {
45 ExprValidator { func, infer, sink } 45 ExprValidator { owner, infer, sink }
46 } 46 }
47 47
48 pub fn validate_body(&mut self, db: &dyn HirDatabase) { 48 pub(super) fn validate_body(&mut self, db: &dyn HirDatabase) {
49 let body = db.body(self.func.into()); 49 let body = db.body(self.owner.into());
50 50
51 for (id, expr) in body.exprs.iter() { 51 for (id, expr) in body.exprs.iter() {
52 if let Some((variant_def, missed_fields, true)) = 52 if let Some((variant_def, missed_fields, true)) =
@@ -96,7 +96,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
96 missed_fields: Vec<LocalFieldId>, 96 missed_fields: Vec<LocalFieldId>,
97 ) { 97 ) {
98 // XXX: only look at source_map if we do have missing fields 98 // XXX: only look at source_map if we do have missing fields
99 let (_, source_map) = db.body_with_source_map(self.func.into()); 99 let (_, source_map) = db.body_with_source_map(self.owner.into());
100 100
101 if let Ok(source_ptr) = source_map.expr_syntax(id) { 101 if let Ok(source_ptr) = source_map.expr_syntax(id) {
102 let root = source_ptr.file_syntax(db.upcast()); 102 let root = source_ptr.file_syntax(db.upcast());
@@ -125,7 +125,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
125 missed_fields: Vec<LocalFieldId>, 125 missed_fields: Vec<LocalFieldId>,
126 ) { 126 ) {
127 // XXX: only look at source_map if we do have missing fields 127 // XXX: only look at source_map if we do have missing fields
128 let (_, source_map) = db.body_with_source_map(self.func.into()); 128 let (_, source_map) = db.body_with_source_map(self.owner.into());
129 129
130 if let Ok(source_ptr) = source_map.pat_syntax(id) { 130 if let Ok(source_ptr) = source_map.pat_syntax(id) {
131 if let Some(expr) = source_ptr.value.as_ref().left() { 131 if let Some(expr) = source_ptr.value.as_ref().left() {
@@ -181,7 +181,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
181 let mut arg_count = args.len(); 181 let mut arg_count = args.len();
182 182
183 if arg_count != param_count { 183 if arg_count != param_count {
184 let (_, source_map) = db.body_with_source_map(self.func.into()); 184 let (_, source_map) = db.body_with_source_map(self.owner.into());
185 if let Ok(source_ptr) = source_map.expr_syntax(call_id) { 185 if let Ok(source_ptr) = source_map.expr_syntax(call_id) {
186 if is_method_call { 186 if is_method_call {
187 param_count -= 1; 187 param_count -= 1;
@@ -208,7 +208,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
208 infer: Arc<InferenceResult>, 208 infer: Arc<InferenceResult>,
209 ) { 209 ) {
210 let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) = 210 let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) =
211 db.body_with_source_map(self.func.into()); 211 db.body_with_source_map(self.owner.into());
212 212
213 let match_expr_ty = match infer.type_of_expr.get(match_expr) { 213 let match_expr_ty = match infer.type_of_expr.get(match_expr) {
214 Some(ty) => ty, 214 Some(ty) => ty,
@@ -289,7 +289,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
289 289
290 let core_result_path = path![core::result::Result]; 290 let core_result_path = path![core::result::Result];
291 291
292 let resolver = self.func.resolver(db.upcast()); 292 let resolver = self.owner.resolver(db.upcast());
293 let core_result_enum = match resolver.resolve_known_enum(db.upcast(), &core_result_path) { 293 let core_result_enum = match resolver.resolve_known_enum(db.upcast(), &core_result_path) {
294 Some(it) => it, 294 Some(it) => it,
295 _ => return, 295 _ => return,
@@ -304,7 +304,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
304 }; 304 };
305 305
306 if params.len() == 2 && params[0] == mismatch.actual { 306 if params.len() == 2 && params[0] == mismatch.actual {
307 let (_, source_map) = db.body_with_source_map(self.func.into()); 307 let (_, source_map) = db.body_with_source_map(self.owner.into());
308 308
309 if let Ok(source_ptr) = source_map.expr_syntax(id) { 309 if let Ok(source_ptr) = source_map.expr_syntax(id) {
310 self.sink 310 self.sink
diff --git a/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs b/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs
index c512c4f8e..b8ff95ee1 100644
--- a/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs
+++ b/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs
@@ -6,7 +6,7 @@ use std::sync::Arc;
6use hir_def::{ 6use hir_def::{
7 body::Body, 7 body::Body,
8 expr::{Expr, ExprId, UnaryOp}, 8 expr::{Expr, ExprId, UnaryOp},
9 DefWithBodyId, FunctionId, 9 DefWithBodyId,
10}; 10};
11use hir_expand::diagnostics::DiagnosticSink; 11use hir_expand::diagnostics::DiagnosticSink;
12 12
@@ -15,26 +15,29 @@ use crate::{
15 InferenceResult, Ty, TypeCtor, 15 InferenceResult, Ty, TypeCtor,
16}; 16};
17 17
18pub struct UnsafeValidator<'a, 'b: 'a> { 18pub(super) struct UnsafeValidator<'a, 'b: 'a> {
19 func: FunctionId, 19 owner: DefWithBodyId,
20 infer: Arc<InferenceResult>, 20 infer: Arc<InferenceResult>,
21 sink: &'a mut DiagnosticSink<'b>, 21 sink: &'a mut DiagnosticSink<'b>,
22} 22}
23 23
24impl<'a, 'b> UnsafeValidator<'a, 'b> { 24impl<'a, 'b> UnsafeValidator<'a, 'b> {
25 pub fn new( 25 pub(super) fn new(
26 func: FunctionId, 26 owner: DefWithBodyId,
27 infer: Arc<InferenceResult>, 27 infer: Arc<InferenceResult>,
28 sink: &'a mut DiagnosticSink<'b>, 28 sink: &'a mut DiagnosticSink<'b>,
29 ) -> UnsafeValidator<'a, 'b> { 29 ) -> UnsafeValidator<'a, 'b> {
30 UnsafeValidator { func, infer, sink } 30 UnsafeValidator { owner, infer, sink }
31 } 31 }
32 32
33 pub fn validate_body(&mut self, db: &dyn HirDatabase) { 33 pub(super) fn validate_body(&mut self, db: &dyn HirDatabase) {
34 let def = self.func.into(); 34 let def = self.owner.into();
35 let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def); 35 let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def);
36 let func_data = db.function_data(self.func); 36 let is_unsafe = match self.owner {
37 if func_data.is_unsafe 37 DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe,
38 DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false,
39 };
40 if is_unsafe
38 || unsafe_expressions 41 || unsafe_expressions
39 .iter() 42 .iter()
40 .filter(|unsafe_expr| !unsafe_expr.inside_unsafe_block) 43 .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 2ce4f65cc..28f32a0a4 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -168,7 +168,7 @@ impl InferenceResult {
168 pub fn add_diagnostics( 168 pub fn add_diagnostics(
169 &self, 169 &self,
170 db: &dyn HirDatabase, 170 db: &dyn HirDatabase,
171 owner: FunctionId, 171 owner: DefWithBodyId,
172 sink: &mut DiagnosticSink, 172 sink: &mut DiagnosticSink,
173 ) { 173 ) {
174 self.diagnostics.iter().for_each(|it| it.add_to(db, owner, sink)) 174 self.diagnostics.iter().for_each(|it| it.add_to(db, owner, sink))
@@ -760,7 +760,7 @@ impl std::ops::BitOrAssign for Diverges {
760} 760}
761 761
762mod diagnostics { 762mod diagnostics {
763 use hir_def::{expr::ExprId, FunctionId}; 763 use hir_def::{expr::ExprId, DefWithBodyId};
764 use hir_expand::diagnostics::DiagnosticSink; 764 use hir_expand::diagnostics::DiagnosticSink;
765 765
766 use crate::{ 766 use crate::{
@@ -778,17 +778,17 @@ mod diagnostics {
778 pub(super) fn add_to( 778 pub(super) fn add_to(
779 &self, 779 &self,
780 db: &dyn HirDatabase, 780 db: &dyn HirDatabase,
781 owner: FunctionId, 781 owner: DefWithBodyId,
782 sink: &mut DiagnosticSink, 782 sink: &mut DiagnosticSink,
783 ) { 783 ) {
784 match self { 784 match self {
785 InferenceDiagnostic::NoSuchField { expr, field } => { 785 InferenceDiagnostic::NoSuchField { expr, field } => {
786 let (_, source_map) = db.body_with_source_map(owner.into()); 786 let (_, source_map) = db.body_with_source_map(owner);
787 let field = source_map.field_syntax(*expr, *field); 787 let field = source_map.field_syntax(*expr, *field);
788 sink.push(NoSuchField { file: field.file_id, field: field.value }) 788 sink.push(NoSuchField { file: field.file_id, field: field.value })
789 } 789 }
790 InferenceDiagnostic::BreakOutsideOfLoop { expr } => { 790 InferenceDiagnostic::BreakOutsideOfLoop { expr } => {
791 let (_, source_map) = db.body_with_source_map(owner.into()); 791 let (_, source_map) = db.body_with_source_map(owner);
792 let ptr = source_map 792 let ptr = source_map
793 .expr_syntax(*expr) 793 .expr_syntax(*expr)
794 .expect("break outside of loop in synthetic syntax"); 794 .expect("break outside of loop in synthetic syntax");
diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs
index 519f43c4e..daf2b909e 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};
13use stdx::format_to; 13use stdx::format_to;
14use test_utils::extract_annotations; 14use test_utils::extract_annotations;
15 15
16use crate::{ 16use crate::diagnostics::{validate_body, Diagnostic};
17 db::HirDatabase,
18 diagnostics::{expr::ExprValidator, unsafe_check::UnsafeValidator, Diagnostic},
19};
20 17
21#[salsa::database( 18#[salsa::database(
22 ra_db::SourceDatabaseExtStorage, 19 ra_db::SourceDatabaseExtStorage,
@@ -118,13 +115,8 @@ impl TestDB {
118 } 115 }
119 116
120 for f in fns { 117 for f in fns {
121 let infer = self.infer(f.into());
122 let mut sink = DiagnosticSink::new(&mut cb); 118 let mut sink = DiagnosticSink::new(&mut cb);
123 infer.add_diagnostics(self, f, &mut sink); 119 validate_body(self, f.into(), &mut sink);
124 let mut validator = ExprValidator::new(f, infer.clone(), &mut sink);
125 validator.validate_body(self);
126 let mut validator = UnsafeValidator::new(f, infer, &mut sink);
127 validator.validate_body(self);
128 } 120 }
129 } 121 }
130 } 122 }