aboutsummaryrefslogtreecommitdiff
path: root/crates/hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir')
-rw-r--r--crates/hir/src/diagnostics.rs78
-rw-r--r--crates/hir/src/lib.rs36
2 files changed, 109 insertions, 5 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 2cdbd172a..e888fc23b 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -14,8 +14,7 @@ use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange};
14pub use hir_ty::{ 14pub use hir_ty::{
15 diagnostics::{ 15 diagnostics::{
16 IncorrectCase, MismatchedArgCount, MissingFields, MissingMatchArms, 16 IncorrectCase, MismatchedArgCount, MissingFields, MissingMatchArms,
17 MissingOkOrSomeInTailExpr, NoSuchField, RemoveThisSemicolon, 17 MissingOkOrSomeInTailExpr, RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap,
18 ReplaceFilterMapNextWithFindMap,
19 }, 18 },
20 diagnostics_sink::{Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder}, 19 diagnostics_sink::{Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder},
21}; 20};
@@ -251,3 +250,78 @@ impl Diagnostic for UnimplementedBuiltinMacro {
251 self 250 self
252 } 251 }
253} 252}
253
254// Diagnostic: no-such-field
255//
256// This diagnostic is triggered if created structure does not have field provided in record.
257#[derive(Debug)]
258pub struct NoSuchField {
259 pub file: HirFileId,
260 pub field: AstPtr<ast::RecordExprField>,
261}
262
263impl Diagnostic for NoSuchField {
264 fn code(&self) -> DiagnosticCode {
265 DiagnosticCode("no-such-field")
266 }
267
268 fn message(&self) -> String {
269 "no such field".to_string()
270 }
271
272 fn display_source(&self) -> InFile<SyntaxNodePtr> {
273 InFile::new(self.file, self.field.clone().into())
274 }
275
276 fn as_any(&self) -> &(dyn Any + Send + 'static) {
277 self
278 }
279}
280
281// Diagnostic: break-outside-of-loop
282//
283// This diagnostic is triggered if the `break` keyword is used outside of a loop.
284#[derive(Debug)]
285pub struct BreakOutsideOfLoop {
286 pub file: HirFileId,
287 pub expr: AstPtr<ast::Expr>,
288}
289
290impl Diagnostic for BreakOutsideOfLoop {
291 fn code(&self) -> DiagnosticCode {
292 DiagnosticCode("break-outside-of-loop")
293 }
294 fn message(&self) -> String {
295 "break outside of loop".to_string()
296 }
297 fn display_source(&self) -> InFile<SyntaxNodePtr> {
298 InFile { file_id: self.file, value: self.expr.clone().into() }
299 }
300 fn as_any(&self) -> &(dyn Any + Send + 'static) {
301 self
302 }
303}
304
305// Diagnostic: missing-unsafe
306//
307// This diagnostic is triggered if an operation marked as `unsafe` is used outside of an `unsafe` function or block.
308#[derive(Debug)]
309pub struct MissingUnsafe {
310 pub file: HirFileId,
311 pub expr: AstPtr<ast::Expr>,
312}
313
314impl Diagnostic for MissingUnsafe {
315 fn code(&self) -> DiagnosticCode {
316 DiagnosticCode("missing-unsafe")
317 }
318 fn message(&self) -> String {
319 format!("This operation is unsafe and requires an unsafe function or block")
320 }
321 fn display_source(&self) -> InFile<SyntaxNodePtr> {
322 InFile { file_id: self.file, value: self.expr.clone().into() }
323 }
324 fn as_any(&self) -> &(dyn Any + Send + 'static) {
325 self
326 }
327}
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 0bb3767c1..a21a9da21 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -36,13 +36,14 @@ use std::{iter, sync::Arc};
36use arrayvec::ArrayVec; 36use arrayvec::ArrayVec;
37use base_db::{CrateDisplayName, CrateId, Edition, FileId}; 37use base_db::{CrateDisplayName, CrateId, Edition, FileId};
38use diagnostics::{ 38use diagnostics::{
39 InactiveCode, MacroError, UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, 39 BreakOutsideOfLoop, InactiveCode, MacroError, MissingUnsafe, NoSuchField,
40 UnresolvedMacroCall, UnresolvedModule, UnresolvedProcMacro, 40 UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall,
41 UnresolvedModule, UnresolvedProcMacro,
41}; 42};
42use either::Either; 43use either::Either;
43use hir_def::{ 44use hir_def::{
44 adt::{ReprKind, VariantData}, 45 adt::{ReprKind, VariantData},
45 body::BodyDiagnostic, 46 body::{BodyDiagnostic, SyntheticSyntax},
46 expr::{BindingAnnotation, LabelId, Pat, PatId}, 47 expr::{BindingAnnotation, LabelId, Pat, PatId},
47 item_tree::ItemTreeNode, 48 item_tree::ItemTreeNode,
48 lang_item::LangItemTarget, 49 lang_item::LangItemTarget,
@@ -1042,6 +1043,35 @@ impl Function {
1042 } 1043 }
1043 } 1044 }
1044 1045
1046 let infer = db.infer(self.id.into());
1047 let (_, source_map) = db.body_with_source_map(self.id.into());
1048 for d in &infer.diagnostics {
1049 match d {
1050 hir_ty::InferenceDiagnostic::NoSuchField { expr } => {
1051 let field = source_map.field_syntax(*expr);
1052 sink.push(NoSuchField { file: field.file_id, field: field.value })
1053 }
1054 hir_ty::InferenceDiagnostic::BreakOutsideOfLoop { expr } => {
1055 let ptr = source_map
1056 .expr_syntax(*expr)
1057 .expect("break outside of loop in synthetic syntax");
1058 sink.push(BreakOutsideOfLoop { file: ptr.file_id, expr: ptr.value })
1059 }
1060 }
1061 }
1062
1063 for expr in hir_ty::diagnostics::missing_unsafe(db, self.id.into()) {
1064 match source_map.as_ref().expr_syntax(expr) {
1065 Ok(in_file) => {
1066 sink.push(MissingUnsafe { file: in_file.file_id, expr: in_file.value })
1067 }
1068 Err(SyntheticSyntax) => {
1069 // FIXME: The `expr` was desugared, report or assert that
1070 // this dosen't happen.
1071 }
1072 }
1073 }
1074
1045 hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); 1075 hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink);
1046 hir_ty::diagnostics::validate_body(db, self.id.into(), sink); 1076 hir_ty::diagnostics::validate_body(db, self.id.into(), sink);
1047 } 1077 }