Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/diagnostics.rs')
| -rw-r--r-- | crates/hir/src/diagnostics.rs | 79 |
1 files changed, 70 insertions, 9 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 8297acde85..612c6adb20 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs @@ -3,21 +3,35 @@ //! //! This probably isn't the best way to do this -- ideally, diagnostics should //! be expressed in terms of hir types themselves. -pub use hir_ty::diagnostics::{CaseType, IncorrectCase}; -use hir_ty::{ - db::HirDatabase, diagnostics::BodyValidationDiagnostic, CastError, InferenceDiagnostic, -}; - use cfg::{CfgExpr, CfgOptions}; use either::Either; -pub use hir_def::VariantId; -use hir_def::{body::SyntheticSyntax, hir::ExprOrPatId, path::ModPath, AssocItemId, DefWithBodyId}; +use hir_def::{ + hir::ExprOrPatId, + path::{hir_segment_to_ast_segment, ModPath}, + type_ref::TypesSourceMap, + AssocItemId, DefWithBodyId, SyntheticSyntax, +}; use hir_expand::{name::Name, HirFileId, InFile}; -use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange}; +use hir_ty::{ + db::HirDatabase, + diagnostics::{BodyValidationDiagnostic, UnsafetyReason}, + CastError, InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringDiagnostic, + TyLoweringDiagnosticKind, +}; +use syntax::{ + ast::{self, HasGenericArgs}, + AstPtr, SyntaxError, SyntaxNodePtr, TextRange, +}; use triomphe::Arc; use crate::{AssocItem, Field, Local, Trait, Type}; +pub use hir_def::VariantId; +pub use hir_ty::{ + diagnostics::{CaseType, IncorrectCase}, + GenericArgsProhibitedReason, +}; + macro_rules! diagnostics { ($($diag:ident,)*) => { #[derive(Debug)] @@ -96,6 +110,7 @@ diagnostics![ UnresolvedIdent, UnusedMut, UnusedVariable, + GenericArgsProhibited, ]; #[derive(Debug)] @@ -258,9 +273,10 @@ pub struct PrivateField { #[derive(Debug)] pub struct MissingUnsafe { - pub expr: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>, + pub node: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>, /// If true, the diagnostics is an `unsafe_op_in_unsafe_fn` lint instead of a hard error. pub only_lint: bool, + pub reason: UnsafetyReason, } #[derive(Debug)] @@ -385,6 +401,12 @@ pub struct InvalidCast { pub cast_ty: Type, } +#[derive(Debug)] +pub struct GenericArgsProhibited { + pub args: InFile<AstPtr<Either<ast::GenericArgList, ast::ParenthesizedArgList>>>, + pub reason: GenericArgsProhibitedReason, +} + impl AnyDiagnostic { pub(crate) fn body_validation_diagnostic( db: &dyn HirDatabase, @@ -524,6 +546,7 @@ impl AnyDiagnostic { db: &dyn HirDatabase, def: DefWithBodyId, d: &InferenceDiagnostic, + outer_types_source_map: &TypesSourceMap, source_map: &hir_def::body::BodySourceMap, ) -> Option<AnyDiagnostic> { let expr_syntax = |expr| { @@ -637,6 +660,44 @@ impl AnyDiagnostic { let cast_ty = Type::new(db, def, cast_ty.clone()); InvalidCast { expr, error: *error, expr_ty, cast_ty }.into() } + InferenceDiagnostic::TyDiagnostic { source, diag } => { + let source_map = match source { + InferenceTyDiagnosticSource::Body => &source_map.types, + InferenceTyDiagnosticSource::Signature => outer_types_source_map, + }; + Self::ty_diagnostic(diag, source_map, db)? + } + }) + } + + pub(crate) fn ty_diagnostic( + diag: &TyLoweringDiagnostic, + source_map: &TypesSourceMap, + db: &dyn HirDatabase, + ) -> Option<AnyDiagnostic> { + let source = match diag.source { + Either::Left(type_ref_id) => { + let Ok(source) = source_map.type_syntax(type_ref_id) else { + stdx::never!("error on synthetic type syntax"); + return None; + }; + source + } + Either::Right(source) => source, + }; + let syntax = || source.value.to_node(&db.parse_or_expand(source.file_id)); + Some(match diag.kind { + TyLoweringDiagnosticKind::GenericArgsProhibited { segment, reason } => { + let ast::Type::PathType(syntax) = syntax() else { return None }; + let segment = hir_segment_to_ast_segment(&syntax.path()?, segment)?; + let args = if let Some(generics) = segment.generic_arg_list() { + AstPtr::new(&generics).wrap_left() + } else { + AstPtr::new(&segment.parenthesized_arg_list()?).wrap_right() + }; + let args = source.with_value(args); + GenericArgsProhibited { args, reason }.into() + } }) } } |