Skip to content

Commit b12aab5

Browse files
Nadrierilmark-i-m
authored andcommitted
Inline StructFields into Fields
1 parent f95cbac commit b12aab5

File tree

1 file changed

+70
-115
lines changed

1 file changed

+70
-115
lines changed

src/librustc_mir_build/hair/pattern/_match.rs

+70-115
Original file line numberDiff line numberDiff line change
@@ -950,13 +950,6 @@ impl<'tcx> Constructor<'tcx> {
950950
}
951951
}
952952

953-
/// The fields of a struct, a tuple, or an enum variant. This hides away fields whose
954-
/// uninhabitedness should not be visible to the user.
955-
#[derive(Debug, Clone)]
956-
struct StructFields<'p, 'tcx> {
957-
fields: SmallVec<[StructField<'p, 'tcx>; 2]>,
958-
}
959-
960953
#[derive(Debug, Copy, Clone)]
961954
enum StructField<'p, 'tcx> {
962955
Kept(&'p Pat<'tcx>),
@@ -984,97 +977,6 @@ impl<'p, 'tcx> StructField<'p, 'tcx> {
984977
}
985978
}
986979

987-
impl<'p, 'tcx> StructFields<'p, 'tcx> {
988-
/// Creates a new list of wildcard fields for a given constructor. `constructor`
989-
/// must be `Variant` or `Single`.
990-
fn wildcards(
991-
cx: &MatchCheckCtxt<'p, 'tcx>,
992-
constructor: &Constructor<'tcx>,
993-
ty: Ty<'tcx>,
994-
) -> Self {
995-
let fields = match ty.kind {
996-
ty::Tuple(ref fs) => fs
997-
.into_iter()
998-
.map(|t| t.expect_ty())
999-
.map(|ty| StructField::wildcard_from_ty(cx, ty))
1000-
.collect(),
1001-
ty::Ref(_, rty, _) => smallvec![StructField::wildcard_from_ty(cx, rty)],
1002-
ty::Adt(adt, substs) => {
1003-
if adt.is_box() {
1004-
// Use T as the sub pattern type of Box<T>.
1005-
smallvec![StructField::wildcard_from_ty(cx, substs.type_at(0))]
1006-
} else {
1007-
let variant = &adt.variants[constructor.variant_index_for_adt(cx, adt)];
1008-
// Whether we must not match the fields of this variant exhaustively.
1009-
let is_non_exhaustive =
1010-
variant.is_field_list_non_exhaustive() && !adt.did.is_local();
1011-
variant
1012-
.fields
1013-
.iter()
1014-
.map(|field| {
1015-
let field_ty = field.ty(cx.tcx, substs);
1016-
let is_visible =
1017-
adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
1018-
let is_uninhabited = cx.is_uninhabited(field_ty);
1019-
1020-
// In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide
1021-
// uninhabited fields in order not to reveal the uninhabitedness of the whole variant.
1022-
if is_uninhabited && (!is_visible || is_non_exhaustive) {
1023-
StructField::Hidden(field_ty)
1024-
} else {
1025-
StructField::wildcard_from_ty(cx, field_ty)
1026-
}
1027-
})
1028-
.collect()
1029-
}
1030-
}
1031-
_ => smallvec![],
1032-
};
1033-
StructFields { fields }
1034-
}
1035-
1036-
/// Number of (filtered) patterns contained.
1037-
fn arity(&self) -> usize {
1038-
self.fields.iter().filter(|p| p.kept().is_some()).count()
1039-
}
1040-
1041-
/// Overrides some of the fields with the provided patterns in the order provided.
1042-
fn replace_fields(&self, pats: impl IntoIterator<Item = &'p Pat<'tcx>>) -> Self {
1043-
// There should be `arity()` patterns in there.
1044-
let mut pats_iter = pats.into_iter();
1045-
let mut fields = self.clone();
1046-
for f in &mut fields.fields {
1047-
if let StructField::Kept(p) = f {
1048-
// We take one input pattern for each `Kept` field, in order.
1049-
let pat = pats_iter.next().unwrap();
1050-
*p = pat;
1051-
}
1052-
}
1053-
fields
1054-
}
1055-
1056-
/// Overrides some of the fields with the provided patterns.
1057-
fn replace_fields_indexed(&self, pats: impl IntoIterator<Item = &'p FieldPat<'tcx>>) -> Self {
1058-
let mut res = self.clone();
1059-
for pat in pats {
1060-
if let StructField::Kept(p) = &mut res.fields[pat.field.index()] {
1061-
*p = &pat.pattern
1062-
}
1063-
}
1064-
res
1065-
}
1066-
1067-
/// Iterate over the exhaustive list of patterns.
1068-
fn iter_all_patterns<'a>(&'a self) -> impl Iterator<Item = Pat<'tcx>> + Captures<'a> {
1069-
self.fields.iter().map(|p| p.to_pattern())
1070-
}
1071-
1072-
/// Returns the filtered list of patterns, to be stored in the matrix.
1073-
fn filtered_patterns(&self) -> SmallVec<[&'p Pat<'tcx>; 2]> {
1074-
self.fields.iter().filter_map(|p| p.kept()).collect()
1075-
}
1076-
}
1077-
1078980
/// A value can be decomposed into a constructor applied to some fields. This struct represents
1079981
/// those fields, generalized to allow patterns in each field. See also `Constructor`.
1080982
///
@@ -1085,11 +987,11 @@ impl<'p, 'tcx> StructFields<'p, 'tcx> {
1085987
/// full fields.
1086988
#[derive(Debug, Clone)]
1087989
enum Fields<'p, 'tcx> {
1088-
/// Fields of a struct, with special handling of uninhabited types.
1089-
Struct(StructFields<'p, 'tcx>),
990+
/// Fields of a struct/tuple/variant, with special handling of uninhabited types.
991+
Struct(SmallVec<[StructField<'p, 'tcx>; 2]>),
1090992
/// Non-struct list of patterns
1091993
Other(SmallVec<[&'p Pat<'tcx>; 2]>),
1092-
/// Optimization for slices
994+
/// Optimization for slices of wildcards
1093995
WildcardSlice { arity: usize, wild: &'p Pat<'tcx> },
1094996
}
1095997

@@ -1113,7 +1015,44 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11131015
debug!("Fields::wildcards({:#?}, {:?})", constructor, ty);
11141016

11151017
match constructor {
1116-
Single | Variant(_) => Fields::Struct(StructFields::wildcards(cx, constructor, ty)),
1018+
Single | Variant(_) => Fields::Struct(match ty.kind {
1019+
ty::Tuple(ref fs) => fs
1020+
.into_iter()
1021+
.map(|t| t.expect_ty())
1022+
.map(|ty| StructField::wildcard_from_ty(cx, ty))
1023+
.collect(),
1024+
ty::Ref(_, rty, _) => smallvec![StructField::wildcard_from_ty(cx, rty)],
1025+
ty::Adt(adt, substs) => {
1026+
if adt.is_box() {
1027+
// Use T as the sub pattern type of Box<T>.
1028+
smallvec![StructField::wildcard_from_ty(cx, substs.type_at(0))]
1029+
} else {
1030+
let variant = &adt.variants[constructor.variant_index_for_adt(cx, adt)];
1031+
// Whether we must not match the fields of this variant exhaustively.
1032+
let is_non_exhaustive =
1033+
variant.is_field_list_non_exhaustive() && !adt.did.is_local();
1034+
variant
1035+
.fields
1036+
.iter()
1037+
.map(|field| {
1038+
let field_ty = field.ty(cx.tcx, substs);
1039+
let is_visible = adt.is_enum()
1040+
|| field.vis.is_accessible_from(cx.module, cx.tcx);
1041+
let is_uninhabited = cx.is_uninhabited(field_ty);
1042+
1043+
// In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide
1044+
// uninhabited fields in order not to reveal the uninhabitedness of the whole variant.
1045+
if is_uninhabited && (!is_visible || is_non_exhaustive) {
1046+
StructField::Hidden(field_ty)
1047+
} else {
1048+
StructField::wildcard_from_ty(cx, field_ty)
1049+
}
1050+
})
1051+
.collect()
1052+
}
1053+
}
1054+
_ => smallvec![],
1055+
}),
11171056
Slice(slice) => match ty.kind {
11181057
ty::Slice(ty) | ty::Array(ty, _) => {
11191058
let wild = &*cx.pattern_arena.alloc(Pat::wildcard_from_ty(ty));
@@ -1128,7 +1067,18 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11281067

11291068
/// Overrides some of the fields with the provided patterns. Panics if `self` is not `Struct`.
11301069
fn replace_fields_indexed(&self, pats: impl IntoIterator<Item = &'p FieldPat<'tcx>>) -> Self {
1131-
Fields::Struct(self.as_structfields().unwrap().replace_fields_indexed(pats))
1070+
match self {
1071+
Fields::Struct(fields) => {
1072+
let mut fields = fields.clone();
1073+
for pat in pats {
1074+
if let StructField::Kept(p) = &mut fields[pat.field.index()] {
1075+
*p = &pat.pattern
1076+
}
1077+
}
1078+
Fields::Struct(fields)
1079+
}
1080+
_ => bug!("`replace_fields_indexed` called on the wrong kind of `Fields`"),
1081+
}
11321082
}
11331083

11341084
/// Replaces contained fields with the given filtered list of patterns, e.g. taken from the
@@ -1138,33 +1088,38 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11381088
cx: &MatchCheckCtxt<'p, 'tcx>,
11391089
pats: impl IntoIterator<Item = Pat<'tcx>>,
11401090
) -> Self {
1091+
// There should be `arity()` patterns in there.
11411092
let pats: &[_] = cx.pattern_arena.alloc_from_iter(pats);
1093+
let mut pats = pats.iter();
1094+
11421095
match self {
1143-
Fields::Struct(sf) => Fields::Struct(sf.replace_fields(pats)),
1144-
_ => Fields::Other(pats.iter().collect()),
1096+
Fields::Struct(fields) => {
1097+
let mut fields = fields.clone();
1098+
for f in &mut fields {
1099+
if let StructField::Kept(p) = f {
1100+
// We take one input pattern for each `Kept` field, in order.
1101+
*p = pats.next().unwrap();
1102+
}
1103+
}
1104+
Fields::Struct(fields)
1105+
}
1106+
_ => Fields::Other(pats.collect()),
11451107
}
11461108
}
11471109

11481110
/// Number of (filtered) patterns contained.
11491111
fn arity(&self) -> usize {
11501112
match self {
1151-
Fields::Struct(sf) => sf.arity(),
1113+
Fields::Struct(fields) => fields.iter().filter(|p| p.kept().is_some()).count(),
11521114
Fields::Other(pats) => pats.len(),
11531115
&Fields::WildcardSlice { arity, .. } => arity,
11541116
}
11551117
}
11561118

1157-
fn as_structfields(&self) -> Option<&StructFields<'p, 'tcx>> {
1158-
match self {
1159-
Fields::Struct(sf) => Some(sf),
1160-
_ => None,
1161-
}
1162-
}
1163-
11641119
/// Returns the exhaustive list of patterns.
11651120
fn all_patterns(&self) -> SmallVec<[Pat<'tcx>; 2]> {
11661121
match self {
1167-
Fields::Struct(sf) => sf.iter_all_patterns().collect(),
1122+
Fields::Struct(fields) => fields.iter().map(|p| p.to_pattern()).collect(),
11681123
Fields::Other(pats) => pats.iter().copied().cloned().collect(),
11691124
&Fields::WildcardSlice { arity, wild } => (0..arity).map(|_| wild).cloned().collect(),
11701125
}
@@ -1173,7 +1128,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11731128
/// Returns the filtered list of patterns, to be stored in the matrix.
11741129
fn filtered_patterns(self) -> SmallVec<[&'p Pat<'tcx>; 2]> {
11751130
match self {
1176-
Fields::Struct(sf) => sf.filtered_patterns(),
1131+
Fields::Struct(fields) => fields.into_iter().filter_map(|p| p.kept()).collect(),
11771132
Fields::Other(pats) => pats,
11781133
Fields::WildcardSlice { arity, wild } => (0..arity).map(|_| wild).collect(),
11791134
}

0 commit comments

Comments
 (0)