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.rs170
1 files changed, 145 insertions, 25 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index a044f24587..f3188c9aad 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -15,12 +15,12 @@ use hir_def::{
};
use hir_expand::{HirFileId, InFile, mod_path::ModPath, name::Name};
use hir_ty::{
- CastError, InferenceDiagnostic, InferenceTyDiagnosticSource, ParamEnvAndCrate,
+ CastError, ExplicitDropMethodUseKind, InferenceDiagnostic, InferenceTyDiagnosticSource,
PathGenericsSource, PathLoweringDiagnostic, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
db::HirDatabase,
diagnostics::{BodyValidationDiagnostic, UnsafetyReason},
display::{DisplayTarget, HirDisplay},
- next_solver::DbInterner,
+ next_solver::{DbInterner, EarlyBinder},
solver_errors::SolverDiagnosticKind,
};
use stdx::{impl_from, never};
@@ -31,7 +31,7 @@ use syntax::{
};
use triomphe::Arc;
-use crate::{AssocItem, Field, Function, GenericDef, Local, Trait, Type, Variant};
+use crate::{AssocItem, Field, Function, GenericDef, Local, Trait, Type, TypeOwnerId, Variant};
pub use hir_def::VariantId;
pub use hir_ty::{
@@ -100,11 +100,17 @@ macro_rules! diagnostics {
}
diagnostics![AnyDiagnostic<'db> ->
+ ArrayPatternWithoutFixedLength,
AwaitOutsideOfAsync,
BreakOutsideOfLoop,
+ CannotBeDereferenced<'db>,
+ CannotImplicitlyDerefTraitObject<'db>,
+ CannotIndexInto<'db>,
CastToUnsized<'db>,
ExpectedArrayOrSlicePat<'db>,
ExpectedFunction<'db>,
+ ExplicitDropMethodUse,
+ FruInDestructuringAssignment,
FunctionalRecordUpdateOnNonStruct,
GenericDefaultRefersToSelf,
InactiveCode,
@@ -115,19 +121,23 @@ diagnostics![AnyDiagnostic<'db> ->
InvalidCast<'db>,
InvalidDeriveTarget,
InvalidLhsOfAssignment,
+ InvalidRangePatType,
MacroDefError,
MacroError,
MacroExpansionParseError,
MalformedDerive,
+ MethodCallIllegalSizedBound,
MismatchedArgCount,
MismatchedTupleStructPatArgCount,
MissingFields,
MissingMatchArms,
MissingUnsafe,
MovedOutOfRef<'db>,
+ MutableRefBinding,
NeedMut,
NonExhaustiveLet,
NonExhaustiveRecordExpr,
+ NonExhaustiveRecordPat,
NoSuchField,
MismatchedArrayPatLen,
DuplicateField,
@@ -298,18 +308,56 @@ pub struct MismatchedArrayPatLen {
}
#[derive(Debug)]
+pub struct ArrayPatternWithoutFixedLength {
+ pub pat: InFile<ExprOrPatPtr>,
+}
+
+#[derive(Debug)]
pub struct ExpectedArrayOrSlicePat<'db> {
pub pat: InFile<ExprOrPatPtr>,
pub found: Type<'db>,
}
#[derive(Debug)]
+pub struct InvalidRangePatType {
+ pub pat: InFile<ExprOrPatPtr>,
+}
+
+#[derive(Debug)]
pub struct ExpectedFunction<'db> {
pub call: InFile<ExprOrPatPtr>,
pub found: Type<'db>,
}
#[derive(Debug)]
+pub struct CannotBeDereferenced<'db> {
+ pub expr: InFile<ExprOrPatPtr>,
+ pub found: Type<'db>,
+}
+
+#[derive(Debug)]
+pub struct CannotImplicitlyDerefTraitObject<'db> {
+ pub pat: InFile<ExprOrPatPtr>,
+ pub found: Type<'db>,
+}
+
+#[derive(Debug)]
+pub struct CannotIndexInto<'db> {
+ pub expr: InFile<ExprOrPatPtr>,
+ pub found: Type<'db>,
+}
+
+#[derive(Debug)]
+pub struct ExplicitDropMethodUse {
+ pub expr_or_path: Either<InFile<AstPtr<ast::MethodCallExpr>>, InFile<AstPtr<ast::Path>>>,
+}
+
+#[derive(Debug)]
+pub struct FruInDestructuringAssignment {
+ pub node: InFile<AstPtr<ast::Expr>>,
+}
+
+#[derive(Debug)]
pub struct FunctionalRecordUpdateOnNonStruct {
pub base_expr: InFile<ExprOrPatPtr>,
}
@@ -401,6 +449,12 @@ pub struct NonExhaustiveRecordExpr {
}
#[derive(Debug)]
+pub struct NonExhaustiveRecordPat {
+ pub pat: InFile<ExprOrPatPtr>,
+ pub variant: Variant,
+}
+
+#[derive(Debug)]
pub struct TypeMismatch<'db> {
pub expr_or_pat: InFile<ExprOrPatPtr>,
pub expected: Type<'db>,
@@ -583,6 +637,11 @@ pub struct InvalidLhsOfAssignment {
}
#[derive(Debug)]
+pub struct MethodCallIllegalSizedBound {
+ pub call_expr: InFile<ExprOrPatPtr>,
+}
+
+#[derive(Debug)]
pub struct PatternArgInExternFn {
pub node: InFile<AstPtr<ast::Pat>>,
}
@@ -594,6 +653,11 @@ pub struct UnimplementedTrait<'db> {
pub root_trait_predicate: Option<crate::TraitPredicate<'db>>,
}
+#[derive(Debug)]
+pub struct MutableRefBinding {
+ pub pat: InFile<ExprOrPatPtr>,
+}
+
impl<'db> AnyDiagnostic<'db> {
pub(crate) fn body_validation_diagnostic(
db: &'db dyn HirDatabase,
@@ -733,7 +797,7 @@ impl<'db> AnyDiagnostic<'db> {
d: &'db InferenceDiagnostic,
source_map: &hir_def::expr_store::BodySourceMap,
sig_map: &hir_def::expr_store::ExpressionStoreSourceMap,
- env: ParamEnvAndCrate<'db>,
+ type_owner: TypeOwnerId,
) -> Option<AnyDiagnostic<'db>> {
let expr_syntax = |expr| {
source_map
@@ -757,6 +821,7 @@ impl<'db> AnyDiagnostic<'db> {
ExprOrPatId::ExprId(expr) => expr_syntax(expr),
ExprOrPatId::PatId(pat) => pat_syntax(pat),
};
+ let new_ty = |ty| Type { owner: type_owner, ty: EarlyBinder::bind(ty) };
let span_syntax = |span| match span {
hir_ty::Span::ExprId(idx) => expr_syntax(idx).map(|it| it.upcast()),
hir_ty::Span::PatId(idx) => pat_syntax(idx).map(|it| it.upcast()),
@@ -784,9 +849,21 @@ impl<'db> AnyDiagnostic<'db> {
let pat = pat_syntax(pat)?.map(Into::into);
MismatchedArrayPatLen { pat, expected, found, has_rest }.into()
}
+ &InferenceDiagnostic::ArrayPatternWithoutFixedLength { pat } => {
+ let pat = pat_syntax(pat)?.map(Into::into);
+ ArrayPatternWithoutFixedLength { pat }.into()
+ }
InferenceDiagnostic::ExpectedArrayOrSlicePat { pat, found } => {
let pat = pat_syntax(*pat)?.map(Into::into);
- ExpectedArrayOrSlicePat { pat, found: Type::new(db, def, found.as_ref()) }.into()
+ ExpectedArrayOrSlicePat {
+ pat,
+ found: Type { owner: type_owner, ty: EarlyBinder::bind(found.as_ref()) },
+ }
+ .into()
+ }
+ &InferenceDiagnostic::InvalidRangePatType { pat } => {
+ let pat = pat_syntax(pat)?.map(Into::into);
+ InvalidRangePatType { pat }.into()
}
&InferenceDiagnostic::DuplicateField { field: expr, variant } => {
let expr_or_pat = match expr {
@@ -812,8 +889,7 @@ impl<'db> AnyDiagnostic<'db> {
}
InferenceDiagnostic::ExpectedFunction { call_expr, found } => {
let call_expr = expr_syntax(*call_expr)?;
- ExpectedFunction { call: call_expr, found: Type::new(db, def, found.as_ref()) }
- .into()
+ ExpectedFunction { call: call_expr, found: new_ty(found.as_ref()) }.into()
}
InferenceDiagnostic::UnresolvedField {
expr,
@@ -825,7 +901,7 @@ impl<'db> AnyDiagnostic<'db> {
UnresolvedField {
expr,
name: name.clone(),
- receiver: Type::new(db, def, receiver.as_ref()),
+ receiver: new_ty(receiver.as_ref()),
method_with_same_name_exists: *method_with_same_name_exists,
}
.into()
@@ -841,10 +917,10 @@ impl<'db> AnyDiagnostic<'db> {
UnresolvedMethodCall {
expr,
name: name.clone(),
- receiver: Type::new(db, def, receiver.as_ref()),
+ receiver: new_ty(receiver.as_ref()),
field_with_same_name: field_with_same_name
.as_ref()
- .map(|ty| Type::new(db, def, ty.as_ref())),
+ .map(|ty| new_ty(ty.as_ref())),
assoc_func_with_same_name: assoc_func_with_same_name.map(Into::into),
}
.into()
@@ -872,12 +948,16 @@ impl<'db> AnyDiagnostic<'db> {
&InferenceDiagnostic::NonExhaustiveRecordExpr { expr } => {
NonExhaustiveRecordExpr { expr: expr_syntax(expr)? }.into()
}
+ &InferenceDiagnostic::NonExhaustiveRecordPat { pat, variant } => {
+ let pat = pat_syntax(pat)?.map(Into::into);
+ NonExhaustiveRecordPat { pat, variant: variant.into() }.into()
+ }
&InferenceDiagnostic::FunctionalRecordUpdateOnNonStruct { base_expr } => {
FunctionalRecordUpdateOnNonStruct { base_expr: expr_syntax(base_expr)? }.into()
}
InferenceDiagnostic::TypedHole { expr, expected } => {
let expr = expr_syntax(*expr)?;
- TypedHole { expr, expected: Type::new(db, def, expected.as_ref()) }.into()
+ TypedHole { expr, expected: new_ty(expected.as_ref()) }.into()
}
&InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => {
let InFile { file_id, value } = pat_syntax(pat)?;
@@ -888,14 +968,26 @@ impl<'db> AnyDiagnostic<'db> {
}
InferenceDiagnostic::CastToUnsized { expr, cast_ty } => {
let expr = expr_syntax(*expr)?;
- CastToUnsized { expr, cast_ty: Type::new(db, def, cast_ty.as_ref()) }.into()
+ CastToUnsized { expr, cast_ty: new_ty(cast_ty.as_ref()) }.into()
}
InferenceDiagnostic::InvalidCast { expr, error, expr_ty, cast_ty } => {
let expr = expr_syntax(*expr)?;
- let expr_ty = Type::new(db, def, expr_ty.as_ref());
- let cast_ty = Type::new(db, def, cast_ty.as_ref());
+ let expr_ty = new_ty(expr_ty.as_ref());
+ let cast_ty = new_ty(cast_ty.as_ref());
InvalidCast { expr, error: *error, expr_ty, cast_ty }.into()
}
+ InferenceDiagnostic::CannotBeDereferenced { expr, found } => {
+ let expr = expr_syntax(*expr)?;
+ CannotBeDereferenced { expr, found: new_ty(found.as_ref()) }.into()
+ }
+ InferenceDiagnostic::CannotImplicitlyDerefTraitObject { pat, found } => {
+ let pat = pat_syntax(*pat)?.map(Into::into);
+ CannotImplicitlyDerefTraitObject { pat, found: new_ty(found.as_ref()) }.into()
+ }
+ InferenceDiagnostic::CannotIndexInto { expr, found } => {
+ let expr = expr_syntax(*expr)?;
+ CannotIndexInto { expr, found: new_ty(found.as_ref()) }.into()
+ }
InferenceDiagnostic::TyDiagnostic { source, diag } => {
let source_map = match source {
InferenceTyDiagnosticSource::Body => source_map,
@@ -963,13 +1055,13 @@ impl<'db> AnyDiagnostic<'db> {
let lhs = expr_syntax(lhs)?;
InvalidLhsOfAssignment { lhs }.into()
}
+ &InferenceDiagnostic::MethodCallIllegalSizedBound { call_expr } => {
+ MethodCallIllegalSizedBound { call_expr: expr_syntax(call_expr)? }.into()
+ }
&InferenceDiagnostic::TypeMustBeKnown { at_point, ref top_term } => {
let at_point = span_syntax(at_point)?;
let top_term = top_term.as_ref().map(|top_term| match top_term.as_ref().kind() {
- rustc_type_ir::GenericArgKind::Type(ty) => Either::Left(Type {
- ty,
- env: crate::body_param_env_from_has_crate(db, def),
- }),
+ rustc_type_ir::GenericArgKind::Type(ty) => Either::Left(new_ty(ty)),
// FIXME: Printing the const to string is definitely not the correct thing to do here.
rustc_type_ir::GenericArgKind::Const(konst) => Either::Right(
konst.display(db, DisplayTarget::from_crate(db, def.krate(db))).to_string(),
@@ -988,14 +1080,37 @@ impl<'db> AnyDiagnostic<'db> {
let expr_or_pat = expr_or_pat_syntax(*node)?;
TypeMismatch {
expr_or_pat,
- expected: Type { env, ty: expected.as_ref() },
- actual: Type { env, ty: found.as_ref() },
+ expected: Type { owner: type_owner, ty: EarlyBinder::bind(expected.as_ref()) },
+ actual: Type { owner: type_owner, ty: EarlyBinder::bind(found.as_ref()) },
}
.into()
}
InferenceDiagnostic::SolverDiagnostic(d) => {
let span = span_syntax(d.span)?;
- Self::solver_diagnostic(db, &d.kind, span, env)?
+ Self::solver_diagnostic(db, &d.kind, span, type_owner)?
+ }
+ InferenceDiagnostic::ExplicitDropMethodUse { kind } => {
+ let expr_or_path = match kind {
+ ExplicitDropMethodUseKind::MethodCall(expr) => {
+ let expr = expr_syntax(*expr)?;
+ let expr = expr.with_value(expr.value.cast::<ast::MethodCallExpr>()?);
+ Either::Left(expr)
+ }
+ ExplicitDropMethodUseKind::Path(path_expr_id) => {
+ let syntax = expr_or_pat_syntax(*path_expr_id)?;
+ let file_id = syntax.file_id;
+ let syntax =
+ syntax.with_value(syntax.value.cast::<ast::PathExpr>()?).to_node(db);
+ let path = syntax.path()?;
+ let path = InFile::new(file_id, AstPtr::new(&path));
+ Either::Right(path)
+ }
+ };
+ ExplicitDropMethodUse { expr_or_path }.into()
+ }
+ InferenceDiagnostic::MutableRefBinding { pat } => {
+ let pat = pat_syntax(*pat)?.map(Into::into);
+ MutableRefBinding { pat }.into()
}
})
}
@@ -1004,16 +1119,21 @@ impl<'db> AnyDiagnostic<'db> {
db: &'db dyn HirDatabase,
d: &'db SolverDiagnosticKind,
span: SpanSyntax,
- env: ParamEnvAndCrate<'db>,
+ type_owner: TypeOwnerId,
) -> Option<AnyDiagnostic<'db>> {
let interner = DbInterner::new_no_crate(db);
Some(match d {
SolverDiagnosticKind::TraitUnimplemented { trait_predicate, root_trait_predicate } => {
- let trait_predicate =
- crate::TraitPredicate { inner: trait_predicate.get(interner), env };
+ let trait_predicate = crate::TraitPredicate {
+ inner: trait_predicate.get(interner),
+ owner: type_owner,
+ };
let root_trait_predicate =
root_trait_predicate.as_ref().map(|root_trait_predicate| {
- crate::TraitPredicate { inner: root_trait_predicate.get(interner), env }
+ crate::TraitPredicate {
+ inner: root_trait_predicate.get(interner),
+ owner: type_owner,
+ }
});
UnimplementedTrait { span, trait_predicate, root_trait_predicate }.into()
}