diff options
Diffstat (limited to 'crates/ra_hir_ty/src/expr.rs')
-rw-r--r-- | crates/ra_hir_ty/src/expr.rs | 70 |
1 files changed, 61 insertions, 9 deletions
diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs index 795f1762c..7532e2dc7 100644 --- a/crates/ra_hir_ty/src/expr.rs +++ b/crates/ra_hir_ty/src/expr.rs | |||
@@ -2,14 +2,19 @@ | |||
2 | 2 | ||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_def::{path::path, resolver::HasResolver, AdtId, DefWithBodyId, FunctionId}; | 5 | use hir_def::{ |
6 | path::path, resolver::HasResolver, src::HasSource, AdtId, DefWithBodyId, FunctionId, Lookup, | ||
7 | }; | ||
6 | use hir_expand::diagnostics::DiagnosticSink; | 8 | use hir_expand::diagnostics::DiagnosticSink; |
7 | use ra_syntax::{ast, AstPtr}; | 9 | use ra_syntax::{ast, AstPtr}; |
8 | use rustc_hash::FxHashSet; | 10 | use rustc_hash::FxHashSet; |
9 | 11 | ||
10 | use crate::{ | 12 | use crate::{ |
11 | db::HirDatabase, | 13 | db::HirDatabase, |
12 | diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr, MissingPatFields}, | 14 | diagnostics::{ |
15 | MissingFields, MissingMatchArms, MissingOkInTailExpr, MissingPatFields, MissingUnsafe, | ||
16 | UnnecessaryUnsafe, | ||
17 | }, | ||
13 | utils::variant_data, | 18 | utils::variant_data, |
14 | ApplicationTy, InferenceResult, Ty, TypeCtor, | 19 | ApplicationTy, InferenceResult, Ty, TypeCtor, |
15 | _match::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness}, | 20 | _match::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness}, |
@@ -321,16 +326,63 @@ pub fn unsafe_expressions( | |||
321 | let mut unsafe_expr_ids = vec![]; | 326 | let mut unsafe_expr_ids = vec![]; |
322 | let body = db.body(def); | 327 | let body = db.body(def); |
323 | for (id, expr) in body.exprs.iter() { | 328 | for (id, expr) in body.exprs.iter() { |
324 | if let Expr::Call { callee, .. } = expr { | 329 | match expr { |
325 | if infer | 330 | Expr::Call { callee, .. } => { |
326 | .method_resolution(*callee) | 331 | if infer |
327 | .map(|func| db.function_data(func).is_unsafe) | 332 | .method_resolution(*callee) |
328 | .unwrap_or(false) | 333 | .map(|func| db.function_data(func).is_unsafe) |
329 | { | 334 | .unwrap_or(false) |
330 | unsafe_expr_ids.push(id); | 335 | { |
336 | unsafe_expr_ids.push(id); | ||
337 | } | ||
338 | } | ||
339 | Expr::UnaryOp { expr, op: UnaryOp::Deref } => { | ||
340 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }) = &infer[*expr] { | ||
341 | unsafe_expr_ids.push(id); | ||
342 | } | ||
331 | } | 343 | } |
344 | _ => {} | ||
332 | } | 345 | } |
333 | } | 346 | } |
334 | 347 | ||
335 | unsafe_expr_ids | 348 | unsafe_expr_ids |
336 | } | 349 | } |
350 | |||
351 | pub struct UnsafeValidator<'a, 'b: 'a> { | ||
352 | func: FunctionId, | ||
353 | infer: Arc<InferenceResult>, | ||
354 | sink: &'a mut DiagnosticSink<'b>, | ||
355 | } | ||
356 | |||
357 | impl<'a, 'b> UnsafeValidator<'a, 'b> { | ||
358 | pub fn new( | ||
359 | func: FunctionId, | ||
360 | infer: Arc<InferenceResult>, | ||
361 | sink: &'a mut DiagnosticSink<'b>, | ||
362 | ) -> UnsafeValidator<'a, 'b> { | ||
363 | UnsafeValidator { func, infer, sink } | ||
364 | } | ||
365 | |||
366 | pub fn validate_body(&mut self, db: &dyn HirDatabase) { | ||
367 | let def = self.func.into(); | ||
368 | let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def); | ||
369 | let func_data = db.function_data(self.func); | ||
370 | let unnecessary = func_data.is_unsafe && unsafe_expressions.len() == 0; | ||
371 | let missing = !func_data.is_unsafe && unsafe_expressions.len() > 0; | ||
372 | if !(unnecessary || missing) { | ||
373 | return; | ||
374 | } | ||
375 | |||
376 | let loc = self.func.lookup(db.upcast()); | ||
377 | let in_file = loc.source(db.upcast()); | ||
378 | |||
379 | let file = in_file.file_id; | ||
380 | let fn_def = AstPtr::new(&in_file.value); | ||
381 | |||
382 | if unnecessary { | ||
383 | self.sink.push(UnnecessaryUnsafe { file, fn_def }) | ||
384 | } else { | ||
385 | self.sink.push(MissingUnsafe { file, fn_def }) | ||
386 | } | ||
387 | } | ||
388 | } | ||