Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions crates/hir-ty/src/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,14 @@ pub enum InferenceDiagnostic {
#[type_visitable(ignore)]
variant: VariantId,
},
UnionPatMustHaveExactlyOneField {
#[type_visitable(ignore)]
pat: PatId,
},
UnionPatHasRest {
#[type_visitable(ignore)]
pat: PatId,
},
FunctionalRecordUpdateOnNonStruct {
#[type_visitable(ignore)]
base_expr: ExprId,
Expand Down
4 changes: 2 additions & 2 deletions crates/hir-ty/src/infer/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1241,10 +1241,10 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
// Report an error if an incorrect number of fields was specified.
if matches!(variant, VariantId::UnionId(_)) {
if fields.len() != 1 {
// FIXME: Emit an error, unions can't have more than one field.
self.push_diagnostic(InferenceDiagnostic::UnionPatMustHaveExactlyOneField { pat });
}
if has_rest_pat {
// FIXME: Emit an error, unions can't have a rest pat.
self.push_diagnostic(InferenceDiagnostic::UnionPatHasRest { pat });
}
} else if !unmentioned_fields.is_empty() && !has_rest_pat {
// FIXME: Emit an error.
Expand Down
20 changes: 20 additions & 0 deletions crates/hir/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ diagnostics![AnyDiagnostic<'db> ->
ElidedLifetimesInPath,
TypeMustBeKnown<'db>,
UnionExprMustHaveExactlyOneField,
UnionPatMustHaveExactlyOneField,
UnionPatHasRest,
UnimplementedTrait<'db>,
];

Expand Down Expand Up @@ -625,6 +627,16 @@ pub struct UnionExprMustHaveExactlyOneField {
pub expr: InFile<ExprOrPatPtr>,
}

#[derive(Debug)]
pub struct UnionPatMustHaveExactlyOneField {
pub pat: InFile<ExprOrPatPtr>,
}

#[derive(Debug)]
pub struct UnionPatHasRest {
pub pat: InFile<ExprOrPatPtr>,
}

#[derive(Debug)]
pub struct InvalidLhsOfAssignment {
pub lhs: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
Expand Down Expand Up @@ -942,6 +954,14 @@ impl<'db> AnyDiagnostic<'db> {
let pat = pat_syntax(pat)?.map(Into::into);
NonExhaustiveRecordPat { pat, variant: variant.into() }.into()
}
&InferenceDiagnostic::UnionPatMustHaveExactlyOneField { pat } => {
let pat = pat_syntax(pat)?.map(Into::into);
UnionPatMustHaveExactlyOneField { pat }.into()
}
&InferenceDiagnostic::UnionPatHasRest { pat } => {
let pat = pat_syntax(pat)?.map(Into::into);
UnionPatHasRest { pat }.into()
}
&InferenceDiagnostic::FunctionalRecordUpdateOnNonStruct { base_expr } => {
FunctionalRecordUpdateOnNonStruct { base_expr: expr_syntax(base_expr)? }.into()
}
Expand Down
41 changes: 41 additions & 0 deletions crates/ide-diagnostics/src/handlers/union_pat_has_rest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};

// Diagnostic: union-pat-has-rest
//
// A union pattern uses `..`.
pub(crate) fn union_pat_has_rest(
ctx: &DiagnosticsContext<'_, '_>,
d: &hir::UnionPatHasRest,
) -> Diagnostic {
Diagnostic::new_with_syntax_node_ptr(
ctx,
DiagnosticCode::RustcHardError("E0784"),
"union patterns cannot use `..`",
d.pat.map(Into::into),
)
.stable()
}

#[cfg(test)]
mod tests {
use crate::tests::check_diagnostics;

#[test]
fn union_pat_has_rest() {
check_diagnostics(
r#"
union Bird {
pigeon: u8,
turtledove: u16,
}

fn main(bird: Bird) {
unsafe {
let Bird { pigeon: 0, .. } = bird;
//^^^^^^^^^^^^^^^^^^^^^^ error: union patterns cannot use `..`
}
}
"#,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};

// Diagnostic: union-pat-must-have-exactly-one-field
//
// A union pattern does not have exactly one field.
pub(crate) fn union_pat_must_have_exactly_one_field(
ctx: &DiagnosticsContext<'_, '_>,
d: &hir::UnionPatMustHaveExactlyOneField,
) -> Diagnostic {
Diagnostic::new_with_syntax_node_ptr(
ctx,
DiagnosticCode::RustcHardError("E0784"),
"union patterns should have exactly one field",
d.pat.map(Into::into),
)
.stable()
}

#[cfg(test)]
mod tests {
use crate::tests::check_diagnostics;

#[test]
fn union_pat_must_have_exactly_one_field() {
check_diagnostics(
r#"
union Bird {
pigeon: u8,
turtledove: u16,
}

fn main(bird: Bird) {
unsafe {
let Bird {} = bird;
//^^^^^^^ error: union patterns should have exactly one field
let Bird { pigeon: 0, turtledove: 1 } = bird;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: union patterns should have exactly one field
}
}
"#,
);
}
}
8 changes: 8 additions & 0 deletions crates/ide-diagnostics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ mod handlers {
pub(crate) mod unimplemented_builtin_macro;
pub(crate) mod unimplemented_trait;
pub(crate) mod union_expr_must_have_exactly_one_field;
pub(crate) mod union_pat_has_rest;
pub(crate) mod union_pat_must_have_exactly_one_field;
pub(crate) mod unreachable_label;
pub(crate) mod unresolved_assoc_item;
pub(crate) mod unresolved_extern_crate;
Expand Down Expand Up @@ -544,6 +546,12 @@ pub fn semantic_diagnostics(
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),
AnyDiagnostic::UnionPatMustHaveExactlyOneField(d) => {
handlers::union_pat_must_have_exactly_one_field::union_pat_must_have_exactly_one_field(&ctx, &d)
}
AnyDiagnostic::UnionPatHasRest(d) => {
handlers::union_pat_has_rest::union_pat_has_rest(&ctx, &d)
}
AnyDiagnostic::UnimplementedTrait(d) => handlers::unimplemented_trait::unimplemented_trait(&ctx, &d),
AnyDiagnostic::FruInDestructuringAssignment(d) => handlers::fru_in_destructuring_assignment::fru_in_destructuring_assignment(&ctx, &d),
AnyDiagnostic::ExplicitDropMethodUse(d) => handlers::explicit_drop_method_use::explicit_drop_method_use(&ctx, &d),
Expand Down
Loading