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:
Manish Goregaokar 2021-10-04 23:56:20 -07:00 committed by GitHub
commit 87f782ede6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 14 deletions

View file

@ -181,8 +181,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// 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)],

View file

@ -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,
}

View file

@ -10,7 +10,7 @@ use enums::{
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) {

View file

@ -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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^