Rollup merge of #89423 - DevinR528:reachable-fields, r=Nadrieril
Fix ICE caused by non_exaustive_omitted_patterns struct lint fixes #89382 Add check that a list of `Pat`s is non empty to prevent ICE in `FnCtxt::lint_non_exhaustive_omitted_patterns`. Is related to #89374 and #89105
This commit is contained in:
commit
87f782ede6
@ -181,8 +181,8 @@ fn check_pat(
|
||||
self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, def_bm, ti)
|
||||
}
|
||||
PatKind::Path(_) => self.check_pat_path(pat, path_res.unwrap(), expected, ti),
|
||||
PatKind::Struct(ref qpath, fields, etc) => {
|
||||
self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, ti)
|
||||
PatKind::Struct(ref qpath, fields, has_rest_pat) => {
|
||||
self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, def_bm, ti)
|
||||
}
|
||||
PatKind::Or(pats) => {
|
||||
let parent_pat = Some(pat);
|
||||
@ -712,7 +712,7 @@ fn check_pat_struct(
|
||||
pat: &'tcx Pat<'tcx>,
|
||||
qpath: &hir::QPath<'_>,
|
||||
fields: &'tcx [hir::PatField<'tcx>],
|
||||
etc: bool,
|
||||
has_rest_pat: bool,
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: BindingMode,
|
||||
ti: TopInfo<'tcx>,
|
||||
@ -734,7 +734,7 @@ fn check_pat_struct(
|
||||
self.demand_eqtype_pat(pat.span, expected, pat_ty, ti);
|
||||
|
||||
// Type-check subpatterns.
|
||||
if self.check_struct_pat_fields(pat_ty, pat, variant, fields, etc, def_bm, ti) {
|
||||
if self.check_struct_pat_fields(pat_ty, &pat, variant, fields, has_rest_pat, def_bm, ti) {
|
||||
pat_ty
|
||||
} else {
|
||||
self.tcx.ty_error()
|
||||
@ -1216,7 +1216,7 @@ fn check_struct_pat_fields(
|
||||
pat: &'tcx Pat<'tcx>,
|
||||
variant: &'tcx ty::VariantDef,
|
||||
fields: &'tcx [hir::PatField<'tcx>],
|
||||
etc: bool,
|
||||
has_rest_pat: bool,
|
||||
def_bm: BindingMode,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> bool {
|
||||
@ -1290,7 +1290,7 @@ fn check_struct_pat_fields(
|
||||
|
||||
// Require `..` if struct has non_exhaustive attribute.
|
||||
let non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did.is_local();
|
||||
if non_exhaustive && !etc {
|
||||
if non_exhaustive && !has_rest_pat {
|
||||
self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty());
|
||||
}
|
||||
|
||||
@ -1302,7 +1302,7 @@ fn check_struct_pat_fields(
|
||||
.struct_span_err(pat.span, "union patterns should have exactly one field")
|
||||
.emit();
|
||||
}
|
||||
if etc {
|
||||
if has_rest_pat {
|
||||
tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit();
|
||||
}
|
||||
} else if !unmentioned_fields.is_empty() {
|
||||
@ -1313,9 +1313,8 @@ fn check_struct_pat_fields(
|
||||
field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx)
|
||||
})
|
||||
.collect();
|
||||
if non_exhaustive {
|
||||
self.non_exhaustive_reachable_pattern(pat, &accessible_unmentioned_fields, adt_ty)
|
||||
} else if !etc {
|
||||
|
||||
if !has_rest_pat {
|
||||
if accessible_unmentioned_fields.is_empty() {
|
||||
unmentioned_err = Some(self.error_no_accessible_fields(pat, fields));
|
||||
} else {
|
||||
@ -1326,6 +1325,12 @@ fn check_struct_pat_fields(
|
||||
fields,
|
||||
));
|
||||
}
|
||||
} else if non_exhaustive && !accessible_unmentioned_fields.is_empty() {
|
||||
self.lint_non_exhaustive_omitted_patterns(
|
||||
pat,
|
||||
&accessible_unmentioned_fields,
|
||||
adt_ty,
|
||||
)
|
||||
}
|
||||
}
|
||||
match (inexistent_fields_err, unmentioned_err) {
|
||||
@ -1653,7 +1658,7 @@ fn error_no_accessible_fields(
|
||||
/// is not exhaustive enough.
|
||||
///
|
||||
/// Nb: the partner lint for enums lives in `compiler/rustc_mir_build/src/thir/pattern/usefulness.rs`.
|
||||
fn non_exhaustive_reachable_pattern(
|
||||
fn lint_non_exhaustive_omitted_patterns(
|
||||
&self,
|
||||
pat: &Pat<'_>,
|
||||
unmentioned_fields: &[(&ty::FieldDef, Ident)],
|
||||
|
@ -31,3 +31,11 @@ pub struct NestedStruct {
|
||||
pub foo: u16,
|
||||
pub bar: NormalStruct,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[non_exhaustive]
|
||||
pub struct MixedVisFields {
|
||||
pub a: u16,
|
||||
pub b: bool,
|
||||
pub(crate) foo: bool,
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
EmptyNonExhaustiveEnum, NestedNonExhaustive, NonExhaustiveEnum, NonExhaustiveSingleVariant,
|
||||
VariantNonExhaustive,
|
||||
};
|
||||
use structs::{FunctionalRecord, NestedStruct, NormalStruct};
|
||||
use structs::{FunctionalRecord, MixedVisFields, NestedStruct, NormalStruct};
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Default)]
|
||||
@ -141,6 +141,10 @@ fn main() {
|
||||
//~^ some fields are not explicitly listed
|
||||
//~^^ some fields are not explicitly listed
|
||||
|
||||
// Ok: this tests https://github.com/rust-lang/rust/issues/89382
|
||||
#[warn(non_exhaustive_omitted_patterns)]
|
||||
let MixedVisFields { a, b, .. } = MixedVisFields::default();
|
||||
|
||||
// Ok: because this only has 1 variant
|
||||
#[deny(non_exhaustive_omitted_patterns)]
|
||||
match NonExhaustiveSingleVariant::A(true) {
|
||||
|
@ -129,13 +129,13 @@ LL | #[deny(non_exhaustive_omitted_patterns)]
|
||||
= note: the matched value is of type `ErrorKind` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||
|
||||
error: some variants are not matched explicitly
|
||||
--> $DIR/reachable-patterns.rs:153:9
|
||||
--> $DIR/reachable-patterns.rs:157:9
|
||||
|
|
||||
LL | _ => {}
|
||||
| ^ pattern `A(_)` not covered
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/reachable-patterns.rs:151:12
|
||||
--> $DIR/reachable-patterns.rs:155:12
|
||||
|
|
||||
LL | #[deny(non_exhaustive_omitted_patterns)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
Loading…
Reference in New Issue
Block a user