Skip to content

Commit 3c921e1

Browse files
committed
feat: add diagnostic for E0422
1 parent 8f29923 commit 3c921e1

6 files changed

Lines changed: 64 additions & 2 deletions

File tree

crates/hir-ty/src/infer.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,10 @@ pub enum InferenceDiagnostic {
352352
#[type_visitable(ignore)]
353353
id: ExprOrPatId,
354354
},
355+
UnresolvedRecordExpr {
356+
#[type_visitable(ignore)]
357+
expr: ExprId,
358+
},
355359
// FIXME: This should be emitted in body lowering
356360
BreakOutsideOfLoop {
357361
#[type_visitable(ignore)]

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,7 @@ impl<'db> InferenceContext<'_, 'db> {
964964
) -> Ty<'db> {
965965
// Find the relevant variant
966966
let (adt_ty, Some(variant)) = self.resolve_variant(expr.into(), path, false) else {
967-
// FIXME: Emit an error.
967+
self.push_diagnostic(InferenceDiagnostic::UnresolvedRecordExpr { expr });
968968
for field in fields {
969969
self.infer_expr_no_expect(field.expr, ExprIsRead::Yes);
970970
}

crates/hir/src/diagnostics.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ diagnostics![AnyDiagnostic<'db> ->
160160
UnresolvedMethodCall<'db>,
161161
UnresolvedModule,
162162
UnresolvedIdent,
163+
UnresolvedRecordExpr,
163164
UnusedMut,
164165
UnusedVariable,
165166
GenericArgsProhibited,
@@ -362,6 +363,11 @@ pub struct UnresolvedIdent {
362363
pub node: InFile<(ExprOrPatPtr, Option<TextRange>)>,
363364
}
364365

366+
#[derive(Debug)]
367+
pub struct UnresolvedRecordExpr {
368+
pub expr: InFile<ExprOrPatPtr>,
369+
}
370+
365371
#[derive(Debug)]
366372
pub struct PrivateField {
367373
pub expr: InFile<ExprOrPatPtr>,
@@ -901,6 +907,10 @@ impl<'db> AnyDiagnostic<'db> {
901907
};
902908
UnresolvedIdent { node }.into()
903909
}
910+
&InferenceDiagnostic::UnresolvedRecordExpr { expr } => {
911+
let expr = expr_syntax(expr)?;
912+
UnresolvedRecordExpr { expr }.into()
913+
}
904914
&InferenceDiagnostic::BreakOutsideOfLoop { expr, is_break, bad_value_break } => {
905915
let expr = expr_syntax(expr)?;
906916
BreakOutsideOfLoop { expr, is_break, bad_value_break }.into()

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ fn f() {
7171
fn abc() {}
7272
abc(#[cfg(a)] 0);
7373
//^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
74-
let x = Struct {
74+
struct Struct {}
75+
let _x = Struct {
7576
#[cfg(a)] f: 0,
7677
//^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
7778
};
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use either::Either;
2+
use syntax::{AstNode, ast::Expr};
3+
4+
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
5+
6+
// Diagnostic: unresolved-record-expr
7+
//
8+
// This diagnostic is triggered if the struct, variant, or union type referred to by a record expression does not exist in the current scope.
9+
pub(crate) fn unresolved_record_expr(
10+
ctx: &DiagnosticsContext<'_, '_>,
11+
d: &hir::UnresolvedRecordExpr,
12+
) -> Diagnostic {
13+
Diagnostic::new(
14+
DiagnosticCode::RustcHardError("E0422"),
15+
"cannot find struct, variant or union type in this scope".to_owned(),
16+
crate::adjusted_display_range(ctx, d.expr, &|expr| match expr {
17+
Either::Left(Expr::RecordExpr(it)) => it.path().map(|p| p.syntax().text_range()),
18+
_ => None,
19+
}),
20+
)
21+
.stable()
22+
}
23+
24+
#[cfg(test)]
25+
mod tests {
26+
use crate::tests::check_diagnostics;
27+
28+
#[test]
29+
fn unresolved_record_expr() {
30+
check_diagnostics(
31+
r#"
32+
struct Exist {
33+
x: i32,
34+
y: i32,
35+
}
36+
37+
fn main() {
38+
let _ = Exist { x: 1, y: 2 };
39+
let _ = DoesNotExist { x: 1, y: 2 };
40+
// ^^^^^^^^^^^^ error: cannot find struct, variant or union type in this scope
41+
}
42+
"#,
43+
);
44+
}
45+
}

crates/ide-diagnostics/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ mod handlers {
9292
pub(crate) mod unresolved_macro_call;
9393
pub(crate) mod unresolved_method;
9494
pub(crate) mod unresolved_module;
95+
pub(crate) mod unresolved_record_expr;
9596
pub(crate) mod unused_must_use;
9697
pub(crate) mod unused_variables;
9798

@@ -501,6 +502,7 @@ pub fn semantic_diagnostics(
501502
AnyDiagnostic::UnresolvedMacroCall(d) => handlers::unresolved_macro_call::unresolved_macro_call(&ctx, &d),
502503
AnyDiagnostic::UnresolvedMethodCall(d) => handlers::unresolved_method::unresolved_method(&ctx, &d),
503504
AnyDiagnostic::UnresolvedModule(d) => handlers::unresolved_module::unresolved_module(&ctx, &d),
505+
AnyDiagnostic::UnresolvedRecordExpr(d) => handlers::unresolved_record_expr::unresolved_record_expr(&ctx, &d),
504506
AnyDiagnostic::UnusedMustUse(d) => handlers::unused_must_use::unused_must_use(&ctx, &d),
505507
AnyDiagnostic::UnusedMut(d) => match handlers::mutability_errors::unused_mut(&ctx, &d) {
506508
Some(it) => it,

0 commit comments

Comments
 (0)