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_ty/src/diagnostics.rs | 185 --------------------------------------- crates/hir_ty/src/infer.rs | 62 ++----------- crates/hir_ty/src/lib.rs | 2 +- 3 files changed, 10 insertions(+), 239 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs index 283894704..28d6ca567 100644 --- a/crates/hir_ty/src/diagnostics.rs +++ b/crates/hir_ty/src/diagnostics.rs @@ -33,40 +33,12 @@ pub fn validate_module_item( pub fn validate_body(db: &dyn HirDatabase, owner: DefWithBodyId, sink: &mut DiagnosticSink<'_>) { let _p = profile::span("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); } -// 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: missing-structure-fields // // This diagnostic is triggered if record lacks some fields that exist in the corresponding structure. @@ -247,30 +219,6 @@ impl Diagnostic for RemoveThisSemicolon { } } -// 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 - } -} - // Diagnostic: missing-unsafe // // This diagnostic is triggered if an operation marked as `unsafe` is used outside of an `unsafe` function or block. @@ -530,129 +478,6 @@ mod tests { assert_eq!(annotations, actual); } - #[test] - fn no_such_field_diagnostics() { - check_diagnostics( - r#" -struct S { foo: i32, bar: () } -impl S { - fn new() -> S { - S { - //^ Missing structure fields: - //| - bar - foo: 92, - baz: 62, - //^^^^^^^ no such field - } - } -} -"#, - ); - } - #[test] - fn no_such_field_with_feature_flag_diagnostics() { - check_diagnostics( - r#" -//- /lib.rs crate:foo cfg:feature=foo -struct MyStruct { - my_val: usize, - #[cfg(feature = "foo")] - bar: bool, -} - -impl MyStruct { - #[cfg(feature = "foo")] - pub(crate) fn new(my_val: usize, bar: bool) -> Self { - Self { my_val, bar } - } - #[cfg(not(feature = "foo"))] - pub(crate) fn new(my_val: usize, _bar: bool) -> Self { - Self { my_val } - } -} -"#, - ); - } - - #[test] - fn no_such_field_enum_with_feature_flag_diagnostics() { - check_diagnostics( - r#" -//- /lib.rs crate:foo cfg:feature=foo -enum Foo { - #[cfg(not(feature = "foo"))] - Buz, - #[cfg(feature = "foo")] - Bar, - Baz -} - -fn test_fn(f: Foo) { - match f { - Foo::Bar => {}, - Foo::Baz => {}, - } -} -"#, - ); - } - - #[test] - fn no_such_field_with_feature_flag_diagnostics_on_struct_lit() { - check_diagnostics( - r#" -//- /lib.rs crate:foo cfg:feature=foo -struct S { - #[cfg(feature = "foo")] - foo: u32, - #[cfg(not(feature = "foo"))] - bar: u32, -} - -impl S { - #[cfg(feature = "foo")] - fn new(foo: u32) -> Self { - Self { foo } - } - #[cfg(not(feature = "foo"))] - fn new(bar: u32) -> Self { - Self { bar } - } - fn new2(bar: u32) -> Self { - #[cfg(feature = "foo")] - { Self { foo: bar } } - #[cfg(not(feature = "foo"))] - { Self { bar } } - } - fn new2(val: u32) -> Self { - Self { - #[cfg(feature = "foo")] - foo: val, - #[cfg(not(feature = "foo"))] - bar: val, - } - } -} -"#, - ); - } - - #[test] - fn no_such_field_with_type_macro() { - check_diagnostics( - r#" -macro_rules! Type { () => { u32 }; } -struct Foo { bar: Type![] } - -impl Foo { - fn new() -> Self { - Foo { bar: 0 } - } -} -"#, - ); - } - #[test] fn missing_record_pat_field_diagnostic() { check_diagnostics( @@ -734,16 +559,6 @@ pub struct Claims { ); } - #[test] - fn break_outside_of_loop() { - check_diagnostics( - r#" -fn foo() { break; } - //^^^^^ break outside of loop -"#, - ); - } - #[test] fn missing_semicolon() { check_diagnostics( diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 0e9f777da..7b57593e4 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -35,11 +35,9 @@ use stdx::impl_from; use syntax::SmolStr; use super::{DomainGoal, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty}; -use crate::diagnostics_sink::DiagnosticSink; use crate::{ - db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic, - lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Goal, Interner, Substitution, - TyBuilder, TyExt, TyKind, + db::HirDatabase, fold_tys, lower::ImplTraitLoweringMode, + to_assoc_type_id, AliasEq, AliasTy, Goal, Interner, Substitution, TyBuilder, TyExt, TyKind, }; // This lint has a false positive here. See the link below for details. @@ -111,6 +109,12 @@ pub(crate) struct InferOk { pub(crate) struct TypeError; pub(crate) type InferResult = Result; +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum InferenceDiagnostic { + NoSuchField { expr: ExprId }, + BreakOutsideOfLoop { expr: ExprId }, +} + /// A mismatch between an expected and an inferred type. #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct TypeMismatch { @@ -140,7 +144,7 @@ pub struct InferenceResult { variant_resolutions: FxHashMap, /// For each associated item record what it resolves to assoc_resolutions: FxHashMap, - diagnostics: Vec, + pub diagnostics: Vec, pub type_of_expr: ArenaMap, /// For each pattern record the type it resolves to. /// @@ -191,14 +195,6 @@ impl InferenceResult { _ => None, }) } - pub fn add_diagnostics( - &self, - db: &dyn HirDatabase, - owner: DefWithBodyId, - sink: &mut DiagnosticSink, - ) { - self.diagnostics.iter().for_each(|it| it.add_to(db, owner, sink)) - } } impl Index for InferenceResult { @@ -804,43 +800,3 @@ impl std::ops::BitOrAssign for Diverges { *self = *self | other; } } - -mod diagnostics { - use hir_def::{expr::ExprId, DefWithBodyId}; - - use crate::{ - db::HirDatabase, - diagnostics::{BreakOutsideOfLoop, NoSuchField}, - diagnostics_sink::DiagnosticSink, - }; - - #[derive(Debug, PartialEq, Eq, Clone)] - pub(super) enum InferenceDiagnostic { - NoSuchField { expr: ExprId }, - BreakOutsideOfLoop { expr: ExprId }, - } - - impl InferenceDiagnostic { - pub(super) fn add_to( - &self, - db: &dyn HirDatabase, - owner: DefWithBodyId, - sink: &mut DiagnosticSink, - ) { - match self { - InferenceDiagnostic::NoSuchField { expr } => { - let (_, source_map) = db.body_with_source_map(owner); - let field = source_map.field_syntax(*expr); - sink.push(NoSuchField { file: field.file_id, field: field.value }) - } - InferenceDiagnostic::BreakOutsideOfLoop { expr } => { - let (_, source_map) = db.body_with_source_map(owner); - 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 }) - } - } - } - } -} diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 50e0d6333..0c6b19653 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -50,7 +50,7 @@ use crate::{db::HirDatabase, utils::generics}; pub use autoderef::autoderef; pub use builder::TyBuilder; pub use chalk_ext::*; -pub use infer::{could_unify, InferenceResult}; +pub use infer::{could_unify, InferenceDiagnostic, InferenceResult}; pub use interner::Interner; pub use lower::{ associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, -- cgit v1.2.3