Unnamed repository; edit this file 'description' to name the repository.
| -rw-r--r-- | crates/hir-ty/src/infer.rs | 4 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer/expr.rs | 2 | ||||
| -rw-r--r-- | crates/hir/src/diagnostics.rs | 10 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/union_expr_must_have_exactly_one_field.rs | 42 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/lib.rs | 2 |
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) } |