From f8009666beaedb34197da9c87cc54d8ca65203b8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 12 Jun 2021 17:17:23 +0300 Subject: internal: move inference diagnostics to hir --- crates/hir/src/diagnostics.rs | 54 +++++++++++++++++++++++++++++++++++++++++-- crates/hir/src/lib.rs | 22 ++++++++++++++++-- 2 files changed, 72 insertions(+), 4 deletions(-) (limited to 'crates/hir') diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 2cdbd172a..2edb53765 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs @@ -14,8 +14,7 @@ use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange}; pub use hir_ty::{ diagnostics::{ IncorrectCase, MismatchedArgCount, MissingFields, MissingMatchArms, - MissingOkOrSomeInTailExpr, NoSuchField, RemoveThisSemicolon, - ReplaceFilterMapNextWithFindMap, + MissingOkOrSomeInTailExpr, RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap, }, diagnostics_sink::{Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder}, }; @@ -251,3 +250,54 @@ impl Diagnostic for UnimplementedBuiltinMacro { self } } + +// Diagnostic: no-such-field +// +// This diagnostic is triggered if created structure does not have field provided in record. +#[derive(Debug)] +pub struct NoSuchField { + pub file: HirFileId, + pub field: AstPtr, +} + +impl Diagnostic for NoSuchField { + fn code(&self) -> DiagnosticCode { + DiagnosticCode("no-such-field") + } + + fn message(&self) -> String { + "no such field".to_string() + } + + fn display_source(&self) -> InFile { + InFile::new(self.file, self.field.clone().into()) + } + + fn as_any(&self) -> &(dyn Any + Send + 'static) { + self + } +} + +// Diagnostic: break-outside-of-loop +// +// This diagnostic is triggered if the `break` keyword is used outside of a loop. +#[derive(Debug)] +pub struct BreakOutsideOfLoop { + pub file: HirFileId, + pub expr: AstPtr, +} + +impl Diagnostic for BreakOutsideOfLoop { + fn code(&self) -> DiagnosticCode { + DiagnosticCode("break-outside-of-loop") + } + fn message(&self) -> String { + "break outside of loop".to_string() + } + fn display_source(&self) -> InFile { + InFile { file_id: self.file, value: self.expr.clone().into() } + } + fn as_any(&self) -> &(dyn Any + Send + 'static) { + self + } +} diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 0bb3767c1..bce626b03 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -36,8 +36,9 @@ use std::{iter, sync::Arc}; use arrayvec::ArrayVec; use base_db::{CrateDisplayName, CrateId, Edition, FileId}; use diagnostics::{ - InactiveCode, MacroError, UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, - UnresolvedMacroCall, UnresolvedModule, UnresolvedProcMacro, + BreakOutsideOfLoop, InactiveCode, MacroError, NoSuchField, UnimplementedBuiltinMacro, + UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, UnresolvedModule, + UnresolvedProcMacro, }; use either::Either; use hir_def::{ @@ -1042,6 +1043,23 @@ impl Function { } } + let infer = db.infer(self.id.into()); + let (_, source_map) = db.body_with_source_map(self.id.into()); + for d in &infer.diagnostics { + match d { + hir_ty::InferenceDiagnostic::NoSuchField { expr } => { + let field = source_map.field_syntax(*expr); + sink.push(NoSuchField { file: field.file_id, field: field.value }) + } + hir_ty::InferenceDiagnostic::BreakOutsideOfLoop { expr } => { + let ptr = source_map + .expr_syntax(*expr) + .expect("break outside of loop in synthetic syntax"); + sink.push(BreakOutsideOfLoop { file: ptr.file_id, expr: ptr.value }) + } + } + } + hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); hir_ty::diagnostics::validate_body(db, self.id.into(), sink); } -- cgit v1.2.3 From 0413d51317a2470c94f82d93e66a3d009fce41a3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 12 Jun 2021 17:39:46 +0300 Subject: internal: move missing unsafe diagnostic to hir --- crates/hir/src/diagnostics.rs | 24 ++++++++++++++++++++++++ crates/hir/src/lib.rs | 20 ++++++++++++++++---- 2 files changed, 40 insertions(+), 4 deletions(-) (limited to 'crates/hir') diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 2edb53765..e888fc23b 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs @@ -301,3 +301,27 @@ impl Diagnostic for BreakOutsideOfLoop { self } } + +// Diagnostic: missing-unsafe +// +// This diagnostic is triggered if an operation marked as `unsafe` is used outside of an `unsafe` function or block. +#[derive(Debug)] +pub struct MissingUnsafe { + pub file: HirFileId, + pub expr: AstPtr, +} + +impl Diagnostic for MissingUnsafe { + fn code(&self) -> DiagnosticCode { + DiagnosticCode("missing-unsafe") + } + fn message(&self) -> String { + format!("This operation is unsafe and requires an unsafe function or block") + } + fn display_source(&self) -> InFile { + InFile { file_id: self.file, value: self.expr.clone().into() } + } + fn as_any(&self) -> &(dyn Any + Send + 'static) { + self + } +} diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index bce626b03..a21a9da21 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -36,14 +36,14 @@ use std::{iter, sync::Arc}; use arrayvec::ArrayVec; use base_db::{CrateDisplayName, CrateId, Edition, FileId}; use diagnostics::{ - BreakOutsideOfLoop, InactiveCode, MacroError, NoSuchField, UnimplementedBuiltinMacro, - UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, UnresolvedModule, - UnresolvedProcMacro, + BreakOutsideOfLoop, InactiveCode, MacroError, MissingUnsafe, NoSuchField, + UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, + UnresolvedModule, UnresolvedProcMacro, }; use either::Either; use hir_def::{ adt::{ReprKind, VariantData}, - body::BodyDiagnostic, + body::{BodyDiagnostic, SyntheticSyntax}, expr::{BindingAnnotation, LabelId, Pat, PatId}, item_tree::ItemTreeNode, lang_item::LangItemTarget, @@ -1060,6 +1060,18 @@ impl Function { } } + for expr in hir_ty::diagnostics::missing_unsafe(db, self.id.into()) { + match source_map.as_ref().expr_syntax(expr) { + Ok(in_file) => { + sink.push(MissingUnsafe { file: in_file.file_id, expr: in_file.value }) + } + Err(SyntheticSyntax) => { + // FIXME: The `expr` was desugared, report or assert that + // this dosen't happen. + } + } + } + hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); hir_ty::diagnostics::validate_body(db, self.id.into(), sink); } -- cgit v1.2.3