Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22202 from WeiTheShinobi/diag_E0784
feat: add diagnostic for E0784
Chayim Refael Friedman 2 weeks ago
parent 8dcb776 · parent 0de2447 · commit e3847c8
-rw-r--r--crates/hir-ty/src/infer.rs4
-rw-r--r--crates/hir-ty/src/infer/expr.rs2
-rw-r--r--crates/hir/src/diagnostics.rs10
-rw-r--r--crates/ide-diagnostics/src/handlers/union_expr_must_have_exactly_one_field.rs42
-rw-r--r--crates/ide-diagnostics/src/lib.rs2
5 files changed, 59 insertions, 1 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 333219c5af..09c1325c41 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -455,6 +455,10 @@ pub enum InferenceDiagnostic {
at_point: Span,
top_term: Option<StoredGenericArg>,
},
+ UnionExprMustHaveExactlyOneField {
+ #[type_visitable(ignore)]
+ expr: ExprId,
+ },
}
/// A mismatch between an expected and an inferred type.
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 782c6be7c3..c59c919c51 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -1093,7 +1093,7 @@ impl<'db> InferenceContext<'_, 'db> {
// Make sure the programmer specified correct number of fields.
if matches!(adt_id, AdtId::UnionId(_)) && hir_fields.len() != 1 {
- // FIXME: Emit an error: unions must specify exactly one field.
+ self.push_diagnostic(InferenceDiagnostic::UnionExprMustHaveExactlyOneField { expr });
}
match base_expr {
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 095b527cb0..082c29c174 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -112,6 +112,7 @@ diagnostics![AnyDiagnostic<'db> ->
MissingLifetime,
ElidedLifetimesInPath,
TypeMustBeKnown<'db>,
+ UnionExprMustHaveExactlyOneField,
];
#[derive(Debug)]
@@ -489,6 +490,11 @@ pub struct GenericDefaultRefersToSelf {
}
#[derive(Debug)]
+pub struct UnionExprMustHaveExactlyOneField {
+ pub expr: InFile<ExprOrPatPtr>,
+}
+
+#[derive(Debug)]
pub struct InvalidLhsOfAssignment {
pub lhs: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
}
@@ -853,6 +859,10 @@ impl<'db> AnyDiagnostic<'db> {
});
TypeMustBeKnown { at_point, top_term }.into()
}
+ &InferenceDiagnostic::UnionExprMustHaveExactlyOneField { expr } => {
+ let expr = expr_syntax(expr)?;
+ UnionExprMustHaveExactlyOneField { expr }.into()
+ }
})
}
diff --git a/crates/ide-diagnostics/src/handlers/union_expr_must_have_exactly_one_field.rs b/crates/ide-diagnostics/src/handlers/union_expr_must_have_exactly_one_field.rs
new file mode 100644
index 0000000000..7f1b2da482
--- /dev/null
+++ b/crates/ide-diagnostics/src/handlers/union_expr_must_have_exactly_one_field.rs
@@ -0,0 +1,42 @@
+use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
+
+// Diagnostic: union-expr-must-have-exactly-one-field
+//
+// A union expression does not have exactly one field.
+pub(crate) fn union_expr_must_have_exactly_one_field(
+ ctx: &DiagnosticsContext<'_, '_>,
+ d: &hir::UnionExprMustHaveExactlyOneField,
+) -> Diagnostic {
+ Diagnostic::new_with_syntax_node_ptr(
+ ctx,
+ DiagnosticCode::RustcHardError("E0784"),
+ "union expressions should have exactly one field",
+ d.expr.map(|it| it.into()),
+ )
+ .stable()
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::check_diagnostics;
+
+ #[test]
+ fn union_expr_must_have_exactly_one_field() {
+ check_diagnostics(
+ r#"
+union Bird {
+ pigeon: u8,
+ turtledove: u16,
+}
+
+fn main() {
+ let bird = Bird { pigeon: 0 };
+ let bird = Bird {};
+ // ^^^^^^^ error: union expressions should have exactly one field
+ let bird = Bird { pigeon: 0, turtledove: 1 };
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: union expressions should have exactly one field
+}
+"#,
+ );
+ }
+}
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index 335e4b047c..618edc5c61 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -72,6 +72,7 @@ mod handlers {
pub(crate) mod typed_hole;
pub(crate) mod undeclared_label;
pub(crate) mod unimplemented_builtin_macro;
+ pub(crate) mod union_expr_must_have_exactly_one_field;
pub(crate) mod unreachable_label;
pub(crate) mod unresolved_assoc_item;
pub(crate) mod unresolved_extern_crate;
@@ -489,6 +490,7 @@ pub fn semantic_diagnostics(
AnyDiagnostic::InvalidLhsOfAssignment(d) => handlers::invalid_lhs_of_assignment::invalid_lhs_of_assignment(&ctx, &d),
AnyDiagnostic::TypeMustBeKnown(d) => handlers::type_must_be_known::type_must_be_known(&ctx, &d),
AnyDiagnostic::PatternArgInExternFn(d) => handlers::pattern_arg_in_extern_fn::pattern_arg_in_extern_fn(&ctx, &d),
+ AnyDiagnostic::UnionExprMustHaveExactlyOneField(d) => handlers::union_expr_must_have_exactly_one_field::union_expr_must_have_exactly_one_field(&ctx, &d),
};
res.push(d)
}