use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
// Diagnostic: non-exhaustive-record-pat
//
// This diagnostic is triggered if a record pattern destructures a `#[non_exhaustive]`
// struct or enum variant from another crate without `..`.
pub(crate) fn non_exhaustive_record_pat(
ctx: &DiagnosticsContext<'_, '_>,
d: &hir::NonExhaustiveRecordPat,
) -> Diagnostic {
let item = match d.variant {
hir::Variant::Struct(_) => "struct",
hir::Variant::Union(_) => "union",
hir::Variant::EnumVariant(_) => "variant",
};
Diagnostic::new_with_syntax_node_ptr(
ctx,
DiagnosticCode::RustcHardError("E0638"),
format!("`..` required with {item} marked as non-exhaustive"),
d.pat.map(Into::into),
)
.stable()
}
#[cfg(test)]
mod tests {
use crate::tests::check_diagnostics;
#[test]
fn reports_external_non_exhaustive_struct_pattern_without_rest() {
check_diagnostics(
r#"
//- /lib.rs crate:lib
#[non_exhaustive]
pub struct S {
pub field: u32,
}
fn local_ok(s: S) {
let S { field } = s;
let _ = field;
}
//- /main.rs crate:main deps:lib
fn main(s: lib::S) {
let lib::S { field } = s;
//^^^^^^^^^^^^^^^^ error: `..` required with struct marked as non-exhaustive
let _ = field;
}
"#,
);
}
#[test]
fn reports_external_non_exhaustive_variant_pattern_without_rest() {
check_diagnostics(
r#"
//- /lib.rs crate:lib
pub enum E {
#[non_exhaustive]
V { field: u32 },
}
fn local_ok(e: E) {
let E::V { field } = e;
let _ = field;
}
//- /main.rs crate:main deps:lib
fn main(e: lib::E) {
let lib::E::V { field } = e;
//^^^^^^^^^^^^^^^^^^^ error: `..` required with variant marked as non-exhaustive
let _ = field;
}
"#,
);
}
}