Skip to content

Commit

Permalink
Rollup merge of #89423 - DevinR528:reachable-fields, r=Nadrieril
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Manishearth authored Oct 5, 2021
2 parents 27b84a9 + b06409e commit 87f782e
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 14 deletions.
27 changes: 16 additions & 11 deletions compiler/rustc_typeck/src/check/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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>,
Expand All @@ -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()
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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());
}

Expand All @@ -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() {
Expand All @@ -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 {
Expand All @@ -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) {
Expand Down Expand Up @@ -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)],
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
6 changes: 5 additions & 1 deletion src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down

0 comments on commit 87f782e

Please sign in to comment.