Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-ty/src/infer.rs5
-rw-r--r--crates/hir-ty/src/infer/expr.rs9
-rw-r--r--crates/hir-ty/src/infer/unify.rs1
-rw-r--r--crates/hir/src/diagnostics.rs11
-rw-r--r--crates/ide-diagnostics/src/handlers/cannot_index_into.rs77
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_unsafe.rs7
-rw-r--r--crates/ide-diagnostics/src/handlers/mutability_errors.rs2
-rw-r--r--crates/ide-diagnostics/src/lib.rs2
8 files changed, 109 insertions, 5 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 86a4f613b3..db437788c0 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -401,6 +401,11 @@ pub enum InferenceDiagnostic {
expr: ExprId,
found: StoredTy,
},
+ CannotIndexInto {
+ #[type_visitable(ignore)]
+ expr: ExprId,
+ found: StoredTy,
+ },
TypedHole {
#[type_visitable(ignore)]
expr: ExprId,
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 3cff0ea896..8df6d9bee4 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -729,8 +729,13 @@ impl<'db> InferenceContext<'_, 'db> {
self.table.select_obligations_where_possible();
trait_element_ty
}
- // FIXME: Report an error.
- None => self.types.types.error,
+ None => {
+ self.push_diagnostic(InferenceDiagnostic::CannotIndexInto {
+ expr: tgt_expr,
+ found: base_t.store(),
+ });
+ self.types.types.error
+ }
}
}
Expr::Tuple { exprs, .. } => {
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index 6500eb213c..393b404cde 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -578,6 +578,7 @@ pub(super) mod resolve_completely {
self.resolve_completely(diagnostic);
if let InferenceDiagnostic::CannotBeDereferenced { found: ty, .. }
+ | InferenceDiagnostic::CannotIndexInto { found: ty, .. }
| InferenceDiagnostic::ExpectedFunction { found: ty, .. }
| InferenceDiagnostic::ExpectedArrayOrSlicePat { found: ty, .. }
| InferenceDiagnostic::UnresolvedField { receiver: ty, .. }
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index a399df8276..6b07834231 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -104,6 +104,7 @@ diagnostics![AnyDiagnostic<'db> ->
AwaitOutsideOfAsync,
BreakOutsideOfLoop,
CannotBeDereferenced<'db>,
+ CannotIndexInto<'db>,
CastToUnsized<'db>,
ExpectedArrayOrSlicePat<'db>,
ExpectedFunction<'db>,
@@ -328,6 +329,12 @@ pub struct CannotBeDereferenced<'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>>>,
}
@@ -947,6 +954,10 @@ impl<'db> AnyDiagnostic<'db> {
let expr = expr_syntax(*expr)?;
CannotBeDereferenced { expr, found: Type::new(db, def, found.as_ref()) }.into()
}
+ InferenceDiagnostic::CannotIndexInto { expr, found } => {
+ let expr = expr_syntax(*expr)?;
+ CannotIndexInto { expr, found: Type::new(db, def, found.as_ref()) }.into()
+ }
InferenceDiagnostic::TyDiagnostic { source, diag } => {
let source_map = match source {
InferenceTyDiagnosticSource::Body => source_map,
diff --git a/crates/ide-diagnostics/src/handlers/cannot_index_into.rs b/crates/ide-diagnostics/src/handlers/cannot_index_into.rs
new file mode 100644
index 0000000000..1e42313b4a
--- /dev/null
+++ b/crates/ide-diagnostics/src/handlers/cannot_index_into.rs
@@ -0,0 +1,77 @@
+use hir::HirDisplay;
+
+use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
+
+// Diagnostic: cannot-index-into
+//
+// This diagnostic is triggered if indexing is used on a type that cannot be
+// indexed.
+pub(crate) fn cannot_index_into(
+ ctx: &DiagnosticsContext<'_, '_>,
+ d: &hir::CannotIndexInto<'_>,
+) -> Diagnostic {
+ Diagnostic::new_with_syntax_node_ptr(
+ ctx,
+ DiagnosticCode::RustcHardError("E0608"),
+ format!(
+ "cannot index into a value of type `{}`",
+ d.found.display(ctx.sema.db, ctx.display_target)
+ ),
+ d.expr.map(Into::into),
+ )
+ .stable()
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::check_diagnostics;
+
+ #[test]
+ fn cannot_index_into() {
+ check_diagnostics(
+ r#"
+//- minicore: index
+fn f() {
+ let x = 1i32;
+ let _ = x[0];
+ //^^^^ error: cannot index into a value of type `i32`
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn allows_array_indexing() {
+ check_diagnostics(
+ r#"
+//- minicore: index, slice
+fn f() {
+ let x = [1i32, 2];
+ let _ = x[0];
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn allows_overloaded_indexing() {
+ check_diagnostics(
+ r#"
+//- minicore: index
+struct Bag(i32);
+
+impl core::ops::Index<usize> for Bag {
+ type Output = i32;
+
+ fn index(&self, _: usize) -> &Self::Output {
+ &self.0
+ }
+}
+
+fn f(x: Bag) {
+ let _ = x[0];
+}
+"#,
+ );
+ }
+}
diff --git a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
index b4ddb239c8..d279e9b4e8 100644
--- a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
@@ -425,17 +425,20 @@ fn main() {
fn raw_deref_on_union_field() {
check_diagnostics(
r#"
+//- minicore: index, slice
+#![allow(unused_variables)]
+
fn main() {
union U {
a: u8
}
- let x = U { a: 3 };
+ let mut x = U { a: 3 };
let a = &raw mut x.a;
union U1 {
- a: u8
+ a: usize
}
let x = U1 { a: 3 };
diff --git a/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
index 31becd1d74..49aa6d7bd9 100644
--- a/crates/ide-diagnostics/src/handlers/mutability_errors.rs
+++ b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
@@ -1313,7 +1313,7 @@ fn main() {
fn regression_20662() {
check_diagnostics(
r#"
-//- minicore: index
+//- minicore: index, slice
pub trait A: core::ops::IndexMut<usize> {
type T: A;
}
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index c8972316f9..11ee669af0 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -33,6 +33,7 @@ mod handlers {
pub(crate) mod bad_rtn;
pub(crate) mod break_outside_of_loop;
pub(crate) mod cannot_be_dereferenced;
+ pub(crate) mod cannot_index_into;
pub(crate) mod duplicate_field;
pub(crate) mod elided_lifetimes_in_path;
pub(crate) mod expected_array_or_slice_pat;
@@ -433,6 +434,7 @@ pub fn semantic_diagnostics(
let d = match diag {
AnyDiagnostic::AwaitOutsideOfAsync(d) => handlers::await_outside_of_async::await_outside_of_async(&ctx, &d),
AnyDiagnostic::CannotBeDereferenced(d) => handlers::cannot_be_dereferenced::cannot_be_dereferenced(&ctx, &d),
+ AnyDiagnostic::CannotIndexInto(d) => handlers::cannot_index_into::cannot_index_into(&ctx, &d),
AnyDiagnostic::CastToUnsized(d) => handlers::invalid_cast::cast_to_unsized(&ctx, &d),
AnyDiagnostic::ExpectedArrayOrSlicePat(d) => handlers::expected_array_or_slice_pat::expected_array_or_slice_pat(&ctx, &d),
AnyDiagnostic::ExpectedFunction(d) => handlers::expected_function::expected_function(&ctx, &d),