Skip to content

Commit 0505d4a

Browse files
Merge pull request #22404 from WaterWhisperer/diag-E0608
feat: add diagnostic for E0608
2 parents cdfe408 + f798d0b commit 0505d4a

8 files changed

Lines changed: 109 additions & 5 deletions

File tree

crates/hir-ty/src/infer.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,11 @@ pub enum InferenceDiagnostic {
401401
expr: ExprId,
402402
found: StoredTy,
403403
},
404+
CannotIndexInto {
405+
#[type_visitable(ignore)]
406+
expr: ExprId,
407+
found: StoredTy,
408+
},
404409
TypedHole {
405410
#[type_visitable(ignore)]
406411
expr: ExprId,

crates/hir-ty/src/infer/expr.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -729,8 +729,13 @@ impl<'db> InferenceContext<'_, 'db> {
729729
self.table.select_obligations_where_possible();
730730
trait_element_ty
731731
}
732-
// FIXME: Report an error.
733-
None => self.types.types.error,
732+
None => {
733+
self.push_diagnostic(InferenceDiagnostic::CannotIndexInto {
734+
expr: tgt_expr,
735+
found: base_t.store(),
736+
});
737+
self.types.types.error
738+
}
734739
}
735740
}
736741
Expr::Tuple { exprs, .. } => {

crates/hir-ty/src/infer/unify.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,7 @@ pub(super) mod resolve_completely {
578578
self.resolve_completely(diagnostic);
579579

580580
if let InferenceDiagnostic::CannotBeDereferenced { found: ty, .. }
581+
| InferenceDiagnostic::CannotIndexInto { found: ty, .. }
581582
| InferenceDiagnostic::ExpectedFunction { found: ty, .. }
582583
| InferenceDiagnostic::ExpectedArrayOrSlicePat { found: ty, .. }
583584
| InferenceDiagnostic::UnresolvedField { receiver: ty, .. }

crates/hir/src/diagnostics.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ diagnostics![AnyDiagnostic<'db> ->
104104
AwaitOutsideOfAsync,
105105
BreakOutsideOfLoop,
106106
CannotBeDereferenced<'db>,
107+
CannotIndexInto<'db>,
107108
CastToUnsized<'db>,
108109
ExpectedArrayOrSlicePat<'db>,
109110
ExpectedFunction<'db>,
@@ -327,6 +328,12 @@ pub struct CannotBeDereferenced<'db> {
327328
pub found: Type<'db>,
328329
}
329330

331+
#[derive(Debug)]
332+
pub struct CannotIndexInto<'db> {
333+
pub expr: InFile<ExprOrPatPtr>,
334+
pub found: Type<'db>,
335+
}
336+
330337
#[derive(Debug)]
331338
pub struct ExplicitDropMethodUse {
332339
pub expr_or_path: Either<InFile<AstPtr<ast::MethodCallExpr>>, InFile<AstPtr<ast::Path>>>,
@@ -947,6 +954,10 @@ impl<'db> AnyDiagnostic<'db> {
947954
let expr = expr_syntax(*expr)?;
948955
CannotBeDereferenced { expr, found: Type::new(db, def, found.as_ref()) }.into()
949956
}
957+
InferenceDiagnostic::CannotIndexInto { expr, found } => {
958+
let expr = expr_syntax(*expr)?;
959+
CannotIndexInto { expr, found: Type::new(db, def, found.as_ref()) }.into()
960+
}
950961
InferenceDiagnostic::TyDiagnostic { source, diag } => {
951962
let source_map = match source {
952963
InferenceTyDiagnosticSource::Body => source_map,
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use hir::HirDisplay;
2+
3+
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
4+
5+
// Diagnostic: cannot-index-into
6+
//
7+
// This diagnostic is triggered if indexing is used on a type that cannot be
8+
// indexed.
9+
pub(crate) fn cannot_index_into(
10+
ctx: &DiagnosticsContext<'_, '_>,
11+
d: &hir::CannotIndexInto<'_>,
12+
) -> Diagnostic {
13+
Diagnostic::new_with_syntax_node_ptr(
14+
ctx,
15+
DiagnosticCode::RustcHardError("E0608"),
16+
format!(
17+
"cannot index into a value of type `{}`",
18+
d.found.display(ctx.sema.db, ctx.display_target)
19+
),
20+
d.expr.map(Into::into),
21+
)
22+
.stable()
23+
}
24+
25+
#[cfg(test)]
26+
mod tests {
27+
use crate::tests::check_diagnostics;
28+
29+
#[test]
30+
fn cannot_index_into() {
31+
check_diagnostics(
32+
r#"
33+
//- minicore: index
34+
fn f() {
35+
let x = 1i32;
36+
let _ = x[0];
37+
//^^^^ error: cannot index into a value of type `i32`
38+
}
39+
"#,
40+
);
41+
}
42+
43+
#[test]
44+
fn allows_array_indexing() {
45+
check_diagnostics(
46+
r#"
47+
//- minicore: index, slice
48+
fn f() {
49+
let x = [1i32, 2];
50+
let _ = x[0];
51+
}
52+
"#,
53+
);
54+
}
55+
56+
#[test]
57+
fn allows_overloaded_indexing() {
58+
check_diagnostics(
59+
r#"
60+
//- minicore: index
61+
struct Bag(i32);
62+
63+
impl core::ops::Index<usize> for Bag {
64+
type Output = i32;
65+
66+
fn index(&self, _: usize) -> &Self::Output {
67+
&self.0
68+
}
69+
}
70+
71+
fn f(x: Bag) {
72+
let _ = x[0];
73+
}
74+
"#,
75+
);
76+
}
77+
}

crates/ide-diagnostics/src/handlers/missing_unsafe.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,17 +425,20 @@ fn main() {
425425
fn raw_deref_on_union_field() {
426426
check_diagnostics(
427427
r#"
428+
//- minicore: index, slice
429+
#![allow(unused_variables)]
430+
428431
fn main() {
429432
430433
union U {
431434
a: u8
432435
}
433-
let x = U { a: 3 };
436+
let mut x = U { a: 3 };
434437
435438
let a = &raw mut x.a;
436439
437440
union U1 {
438-
a: u8
441+
a: usize
439442
}
440443
let x = U1 { a: 3 };
441444

crates/ide-diagnostics/src/handlers/mutability_errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1313,7 +1313,7 @@ fn main() {
13131313
fn regression_20662() {
13141314
check_diagnostics(
13151315
r#"
1316-
//- minicore: index
1316+
//- minicore: index, slice
13171317
pub trait A: core::ops::IndexMut<usize> {
13181318
type T: A;
13191319
}

crates/ide-diagnostics/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ mod handlers {
3333
pub(crate) mod bad_rtn;
3434
pub(crate) mod break_outside_of_loop;
3535
pub(crate) mod cannot_be_dereferenced;
36+
pub(crate) mod cannot_index_into;
3637
pub(crate) mod duplicate_field;
3738
pub(crate) mod elided_lifetimes_in_path;
3839
pub(crate) mod expected_array_or_slice_pat;
@@ -433,6 +434,7 @@ pub fn semantic_diagnostics(
433434
let d = match diag {
434435
AnyDiagnostic::AwaitOutsideOfAsync(d) => handlers::await_outside_of_async::await_outside_of_async(&ctx, &d),
435436
AnyDiagnostic::CannotBeDereferenced(d) => handlers::cannot_be_dereferenced::cannot_be_dereferenced(&ctx, &d),
437+
AnyDiagnostic::CannotIndexInto(d) => handlers::cannot_index_into::cannot_index_into(&ctx, &d),
436438
AnyDiagnostic::CastToUnsized(d) => handlers::invalid_cast::cast_to_unsized(&ctx, &d),
437439
AnyDiagnostic::ExpectedArrayOrSlicePat(d) => handlers::expected_array_or_slice_pat::expected_array_or_slice_pat(&ctx, &d),
438440
AnyDiagnostic::ExpectedFunction(d) => handlers::expected_function::expected_function(&ctx, &d),

0 commit comments

Comments
 (0)