Skip to content

Commit 5387cb4

Browse files
committed
Add diagnostic for RecordPat, TupleStructPat
1 parent 3c921e1 commit 5387cb4

6 files changed

Lines changed: 96 additions & 57 deletions

File tree

crates/hir-ty/src/infer.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,9 +352,9 @@ pub enum InferenceDiagnostic {
352352
#[type_visitable(ignore)]
353353
id: ExprOrPatId,
354354
},
355-
UnresolvedRecordExpr {
355+
UnresolvedVariant {
356356
#[type_visitable(ignore)]
357-
expr: ExprId,
357+
id: ExprOrPatId,
358358
},
359359
// FIXME: This should be emitted in body lowering
360360
BreakOutsideOfLoop {
@@ -2278,6 +2278,8 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
22782278
let interner = DbInterner::conjure();
22792279
let (resolution, unresolved) = if value_ns {
22802280
let Some(res) = path_ctx.resolve_path_in_value_ns(HygieneId::ROOT) else {
2281+
drop(ctx);
2282+
self.push_diagnostic(InferenceDiagnostic::UnresolvedVariant { id: node });
22812283
return (self.types.types.error, None);
22822284
};
22832285
match res {
@@ -2313,7 +2315,11 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
23132315
} else {
23142316
match path_ctx.resolve_path_in_type_ns() {
23152317
Some((it, idx)) => (it, idx),
2316-
None => return (self.types.types.error, None),
2318+
None => {
2319+
drop(ctx);
2320+
self.push_diagnostic(InferenceDiagnostic::UnresolvedVariant { id: node });
2321+
return (self.types.types.error, None);
2322+
}
23172323
}
23182324
};
23192325
return match resolution {

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,6 @@ 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-
self.push_diagnostic(InferenceDiagnostic::UnresolvedRecordExpr { expr });
968967
for field in fields {
969968
self.infer_expr_no_expect(field.expr, ExprIsRead::Yes);
970969
}

crates/hir/src/diagnostics.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ diagnostics![AnyDiagnostic<'db> ->
160160
UnresolvedMethodCall<'db>,
161161
UnresolvedModule,
162162
UnresolvedIdent,
163-
UnresolvedRecordExpr,
163+
UnresolvedVariant,
164164
UnusedMut,
165165
UnusedVariable,
166166
GenericArgsProhibited,
@@ -364,8 +364,8 @@ pub struct UnresolvedIdent {
364364
}
365365

366366
#[derive(Debug)]
367-
pub struct UnresolvedRecordExpr {
368-
pub expr: InFile<ExprOrPatPtr>,
367+
pub struct UnresolvedVariant {
368+
pub node: InFile<ExprOrPatPtr>,
369369
}
370370

371371
#[derive(Debug)]
@@ -907,9 +907,9 @@ impl<'db> AnyDiagnostic<'db> {
907907
};
908908
UnresolvedIdent { node }.into()
909909
}
910-
&InferenceDiagnostic::UnresolvedRecordExpr { expr } => {
911-
let expr = expr_syntax(expr)?;
912-
UnresolvedRecordExpr { expr }.into()
910+
&InferenceDiagnostic::UnresolvedVariant { id } => {
911+
let node = expr_or_pat_syntax(id)?;
912+
UnresolvedVariant { node }.into()
913913
}
914914
&InferenceDiagnostic::BreakOutsideOfLoop { expr, is_break, bad_value_break } => {
915915
let expr = expr_syntax(expr)?;

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

Lines changed: 0 additions & 45 deletions
This file was deleted.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
use either::Either;
2+
use syntax::{AstNode, ast};
3+
4+
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, adjusted_display_range};
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_variant(
10+
ctx: &DiagnosticsContext<'_, '_>,
11+
d: &hir::UnresolvedVariant,
12+
) -> Diagnostic {
13+
Diagnostic::new(
14+
DiagnosticCode::RustcHardError("E0422"),
15+
"cannot find struct, variant or union type in this scope".to_owned(),
16+
adjusted_display_range(ctx, d.node, &|node| match node {
17+
Either::Left(ast::Expr::RecordExpr(it)) => it.path().map(|p| p.syntax().text_range()),
18+
Either::Right(ast::Pat::RecordPat(it)) => it.path().map(|p| p.syntax().text_range()),
19+
Either::Right(ast::Pat::TupleStructPat(it)) => {
20+
it.path().map(|p| p.syntax().text_range())
21+
}
22+
_ => None,
23+
}),
24+
)
25+
.stable()
26+
}
27+
28+
#[cfg(test)]
29+
mod tests {
30+
use crate::tests::check_diagnostics;
31+
32+
#[test]
33+
fn unresolved_record_expr() {
34+
check_diagnostics(
35+
r#"
36+
fn main() {
37+
let _ = DoesNotExist { x: 1, y: 2 };
38+
// ^^^^^^^^^^^^ error: cannot find struct, variant or union type in this scope
39+
}
40+
"#,
41+
);
42+
}
43+
44+
#[test]
45+
fn unresolved_record_pat() {
46+
check_diagnostics(
47+
r#"
48+
fn main() {
49+
struct Exist { x: i32, y: i32 }
50+
let a = Exist { x: 1, y: 2 };
51+
match a {
52+
Exist { .. } => {}
53+
DoesNotExist { .. } => {}
54+
// ^^^^^^^^^^^^ error: cannot find struct, variant or union type in this scope
55+
_ => {}
56+
}
57+
}
58+
"#,
59+
);
60+
}
61+
62+
#[test]
63+
fn unresolved_tuple_struct_pat() {
64+
check_diagnostics(
65+
r#"
66+
fn main() {
67+
struct Tuple(i32, i32);
68+
let t = Tuple(1, 2);
69+
match t {
70+
Tuple( .. ) => {}
71+
DoesNotExist( .. ) => {}
72+
// ^^^^^^^^^^^^ error: cannot find struct, variant or union type in this scope
73+
_ => {}
74+
}
75+
}
76+
"#,
77+
);
78+
}
79+
}

crates/ide-diagnostics/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +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;
95+
pub(crate) mod unresolved_variant;
9696
pub(crate) mod unused_must_use;
9797
pub(crate) mod unused_variables;
9898

@@ -502,7 +502,7 @@ pub fn semantic_diagnostics(
502502
AnyDiagnostic::UnresolvedMacroCall(d) => handlers::unresolved_macro_call::unresolved_macro_call(&ctx, &d),
503503
AnyDiagnostic::UnresolvedMethodCall(d) => handlers::unresolved_method::unresolved_method(&ctx, &d),
504504
AnyDiagnostic::UnresolvedModule(d) => handlers::unresolved_module::unresolved_module(&ctx, &d),
505-
AnyDiagnostic::UnresolvedRecordExpr(d) => handlers::unresolved_record_expr::unresolved_record_expr(&ctx, &d),
505+
AnyDiagnostic::UnresolvedVariant(d) => handlers::unresolved_variant::unresolved_variant(&ctx, &d),
506506
AnyDiagnostic::UnusedMustUse(d) => handlers::unused_must_use::unused_must_use(&ctx, &d),
507507
AnyDiagnostic::UnusedMut(d) => match handlers::mutability_errors::unused_mut(&ctx, &d) {
508508
Some(it) => it,

0 commit comments

Comments
 (0)