Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
1c176d11
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
1c176d11
编写于
12月 19, 2020
作者:
N
Nadrieril
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Simplify field filtering
上级
53e03fb7
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
56 addition
and
64 deletion
+56
-64
compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+55
-63
compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+1
-1
未找到文件。
compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
浏览文件 @
1c176d11
...
...
@@ -1058,41 +1058,30 @@ pub(super) fn iter_missing<'a, 'p>(
}
/// Some fields need to be explicitly hidden away in certain cases; see the comment above the
/// `Fields` struct. This struct represents such a potentially-hidden field. When a field is hidden
/// we still keep its type around.
/// `Fields` struct. This struct represents such a potentially-hidden field.
#[derive(Debug,
Copy,
Clone)]
pub
(
super
)
enum
FilteredField
<
'p
,
'tcx
>
{
Kept
(
&
'p
Pat
<
'tcx
>
),
Hidden
(
Ty
<
'tcx
>
)
,
Hidden
,
}
impl
<
'p
,
'tcx
>
FilteredField
<
'p
,
'tcx
>
{
fn
kept
(
self
)
->
Option
<&
'p
Pat
<
'tcx
>>
{
match
self
{
FilteredField
::
Kept
(
p
)
=>
Some
(
p
),
FilteredField
::
Hidden
(
_
)
=>
None
,
}
}
fn
to_pattern
(
self
)
->
Pat
<
'tcx
>
{
match
self
{
FilteredField
::
Kept
(
p
)
=>
p
.clone
(),
FilteredField
::
Hidden
(
ty
)
=>
Pat
::
wildcard_from_ty
(
ty
),
FilteredField
::
Hidden
=>
None
,
}
}
}
/// A value can be decomposed into a constructor applied to some fields. This struct represents
/// those fields, generalized to allow patterns in each field. See also `Constructor`.
/// This is constructed from a constructor using [`Fields::wildcards()`].
///
/// If a private or `non_exhaustive` field is uninhabited, the code mustn't observe that it is
/// uninhabited. For that, we filter these fields out of the matrix. This is subtle because we
/// still need to have those fields back when going to/from a `Pat`. Most of this is handled
/// automatically in `Fields`, but when constructing or deconstructing `Fields` you need to be
/// careful. As a rule, when going to/from the matrix, use the filtered field list; when going
/// to/from `Pat`, use the full field list.
/// This filtering is uncommon in practice, because uninhabited fields are rarely used, so we avoid
/// it when possible to preserve performance.
/// uninhabited. For that, we filter these fields out of the matrix. This is handled automatically
/// in `Fields`. This filtering is uncommon in practice, because uninhabited fields are rare used,
/// so we avoid it when possible to preserve performance.
#[derive(Debug,
Clone)]
pub
(
super
)
enum
Fields
<
'p
,
'tcx
>
{
/// Lists of patterns that don't contain any filtered fields.
...
...
@@ -1101,21 +1090,19 @@ pub(super) enum Fields<'p, 'tcx> {
/// have not measured if it really made a difference.
Slice
(
&
'p
[
Pat
<
'tcx
>
]),
Vec
(
SmallVec
<
[
&
'p
Pat
<
'tcx
>
;
2
]
>
),
/// Patterns where some of the fields need to be hidden. `kept_count` caches the number of
/// non-hidden fields.
/// Patterns where some of the fields need to be hidden. For all intents and purposes we only
/// care about the non-hidden fields. We need to keep the real field index for those fields;
/// we're morally storing a `Vec<(usize, &Pat)>` but what we do is more convenient.
/// `len` counts the number of non-hidden fields
Filtered
{
fields
:
SmallVec
<
[
FilteredField
<
'p
,
'tcx
>
;
2
]
>
,
kept_count
:
usize
,
len
:
usize
,
},
}
impl
<
'p
,
'tcx
>
Fields
<
'p
,
'tcx
>
{
fn
empty
()
->
Self
{
Fields
::
Slice
(
&
[])
}
/// Construct a new `Fields` from the given pattern. Must not be used if the pattern is a field
/// of a struct/tuple/variant.
/// Internal use. Use `Fields::wildcards()` instead.
/// Must not be used if the pattern is a field of a struct/tuple/variant.
fn
from_single_pattern
(
pat
:
&
'p
Pat
<
'tcx
>
)
->
Self
{
Fields
::
Slice
(
std
::
slice
::
from_ref
(
pat
))
}
...
...
@@ -1160,7 +1147,7 @@ pub(super) fn wildcards(pcx: PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'t
if
has_no_hidden_fields
{
Fields
::
wildcards_from_tys
(
cx
,
field_tys
)
}
else
{
let
mut
kept_count
=
0
;
let
mut
len
=
0
;
let
fields
=
variant
.fields
.iter
()
...
...
@@ -1175,14 +1162,14 @@ pub(super) fn wildcards(pcx: PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'t
// order not to reveal the uninhabitedness of the whole
// variant.
if
is_uninhabited
&&
(
!
is_visible
||
is_non_exhaustive
)
{
FilteredField
::
Hidden
(
ty
)
FilteredField
::
Hidden
}
else
{
kept_count
+=
1
;
len
+=
1
;
FilteredField
::
Kept
(
wildcard_from_ty
(
ty
))
}
})
.collect
();
Fields
::
Filtered
{
fields
,
kept_count
}
Fields
::
Filtered
{
fields
,
len
}
}
}
}
...
...
@@ -1196,7 +1183,7 @@ pub(super) fn wildcards(pcx: PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'t
_
=>
bug!
(
"bad slice pattern {:?} {:?}"
,
constructor
,
ty
),
},
Str
(
..
)
|
FloatRange
(
..
)
|
IntRange
(
..
)
|
NonExhaustive
|
Opaque
|
Missing
|
Wildcard
=>
Fields
::
empty
(
),
|
Wildcard
=>
Fields
::
Slice
(
&
[]
),
};
debug!
(
"Fields::wildcards({:?}, {:?}) = {:#?}"
,
constructor
,
ty
,
ret
);
ret
...
...
@@ -1218,14 +1205,16 @@ pub(super) fn wildcards(pcx: PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'t
/// `self`: `[false]`
/// returns `Some(false)`
pub
(
super
)
fn
apply
(
self
,
pcx
:
PatCtxt
<
'_
,
'p
,
'tcx
>
,
ctor
:
&
Constructor
<
'tcx
>
)
->
Pat
<
'tcx
>
{
let
mut
subpatterns
=
self
.all_patterns
();
let
subpatterns_and_indices
=
self
.patterns_and_indices
();
let
mut
subpatterns
=
subpatterns_and_indices
.iter
()
.map
(|
&
(
_
,
p
)|
p
)
.cloned
();
let
pat
=
match
ctor
{
Single
|
Variant
(
_
)
=>
match
pcx
.ty
.kind
()
{
ty
::
Adt
(
..
)
|
ty
::
Tuple
(
..
)
=>
{
let
subpatterns
=
subpatterns
.enumerate
()
.map
(|(
i
,
p
)|
FieldPat
{
field
:
Field
::
new
(
i
),
pattern
:
p
})
// We want the real indices here.
let
subpatterns
=
subpatterns_and_indices
.iter
()
.map
(|
&
(
field
,
p
)|
FieldPat
{
field
,
pattern
:
p
.clone
()
})
.collect
();
if
let
ty
::
Adt
(
adt
,
substs
)
=
pcx
.ty
.kind
()
{
...
...
@@ -1290,39 +1279,42 @@ pub(super) fn apply(self, pcx: PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'tcx>)
Pat
{
ty
:
pcx
.ty
,
span
:
DUMMY_SP
,
kind
:
Box
::
new
(
pat
)
}
}
/// Returns the number of patterns from the viewpoint of match-checking, i.e. excluding hidden
/// fields. This is what we want in most cases in this file, the only exception being
/// conversion to/from `Pat`.
/// Returns the number of patterns. This is the same as the arity of the constructor used to
/// construct `self`.
pub
(
super
)
fn
len
(
&
self
)
->
usize
{
match
self
{
Fields
::
Slice
(
pats
)
=>
pats
.len
(),
Fields
::
Vec
(
pats
)
=>
pats
.len
(),
Fields
::
Filtered
{
kept_count
,
..
}
=>
*
kept_count
,
Fields
::
Filtered
{
len
,
..
}
=>
*
len
,
}
}
/// Returns the complete list of patterns, including hidden fields.
fn
all_patterns
(
self
)
->
impl
Iterator
<
Item
=
Pat
<
'tcx
>>
{
let
pats
:
SmallVec
<
[
_
;
2
]
>
=
match
self
{
Fields
::
Slice
(
pats
)
=>
pats
.iter
()
.cloned
()
.collect
(),
Fields
::
Vec
(
pats
)
=>
pats
.into_iter
()
.cloned
()
.collect
(),
/// Returns the list of patterns along with the corresponding field indices.
fn
patterns_and_indices
(
&
self
)
->
SmallVec
<
[(
Field
,
&
'p
Pat
<
'tcx
>
);
2
]
>
{
match
self
{
Fields
::
Slice
(
pats
)
=>
{
pats
.iter
()
.enumerate
()
.map
(|(
i
,
p
)|
(
Field
::
new
(
i
),
p
))
.collect
()
}
Fields
::
Vec
(
pats
)
=>
{
pats
.iter
()
.copied
()
.enumerate
()
.map
(|(
i
,
p
)|
(
Field
::
new
(
i
),
p
))
.collect
()
}
Fields
::
Filtered
{
fields
,
..
}
=>
{
// We don't skip any fields here.
fields
.into_iter
()
.map
(|
p
|
p
.to_pattern
())
.collect
()
// Indices must be relative to the full list of patterns
fields
.iter
()
.enumerate
()
.filter_map
(|(
i
,
p
)|
Some
((
Field
::
new
(
i
),
p
.kept
()
?
)))
.collect
()
}
};
pats
.into_iter
()
}
}
/// Returns the
filtered list of patterns, not including hidden field
s.
pub
(
super
)
fn
filtered
_patterns
(
self
)
->
SmallVec
<
[
&
'p
Pat
<
'tcx
>
;
2
]
>
{
/// Returns the
list of pattern
s.
pub
(
super
)
fn
into
_patterns
(
self
)
->
SmallVec
<
[
&
'p
Pat
<
'tcx
>
;
2
]
>
{
match
self
{
Fields
::
Slice
(
pats
)
=>
pats
.iter
()
.collect
(),
Fields
::
Vec
(
pats
)
=>
pats
,
Fields
::
Filtered
{
fields
,
..
}
=>
{
// We skip hidden fields here
fields
.into_iter
()
.filter_map
(|
p
|
p
.kept
())
.collect
()
}
Fields
::
Filtered
{
fields
,
..
}
=>
fields
.iter
()
.filter_map
(|
p
|
p
.kept
())
.collect
(),
}
}
...
...
@@ -1338,10 +1330,10 @@ fn replace_with_fieldpats(
}
/// Overrides some of the fields with the provided patterns. This is used when a pattern
/// defines some fields but not all, for example `Foo { field1: Some(_), .. }`: here we start
with a
///
`Fields` that is just one wildcard per field of the `Foo` struct, and override the entry
///
corresponding to `field1` with the pattern `Some(_)`. This is also used for slice patterns
/// for the same reason.
/// defines some fields but not all, for example `Foo { field1: Some(_), .. }`: here we start
///
with a `Fields` that is just one wildcard per field of the `Foo` struct, and override the
///
entry corresponding to `field1` with the pattern `Some(_)`. This is also used for slice
///
patterns
for the same reason.
fn
replace_fields_indexed
(
&
self
,
new_pats
:
impl
IntoIterator
<
Item
=
(
usize
,
&
'p
Pat
<
'tcx
>
)
>
,
...
...
@@ -1369,8 +1361,8 @@ fn replace_fields_indexed(
fields
}
/// Replaces contained fields with the given
filtered list of patterns, e.g. taken from the
///
matrix. There must be `len()` patterns
in `pats`.
/// Replaces contained fields with the given
list of patterns. There must be `len()` patterns
/// in `pats`.
pub
(
super
)
fn
replace_fields
(
&
self
,
cx
:
&
MatchCheckCtxt
<
'p
,
'tcx
>
,
...
...
@@ -1379,7 +1371,7 @@ pub(super) fn replace_fields(
let
pats
:
&
[
_
]
=
cx
.pattern_arena
.alloc_from_iter
(
pats
);
match
self
{
Fields
::
Filtered
{
fields
,
kept_count
}
=>
{
Fields
::
Filtered
{
fields
,
len
}
=>
{
let
mut
pats
=
pats
.iter
();
let
mut
fields
=
fields
.clone
();
for
f
in
&
mut
fields
{
...
...
@@ -1388,7 +1380,7 @@ pub(super) fn replace_fields(
*
p
=
pats
.next
()
.unwrap
();
}
}
Fields
::
Filtered
{
fields
,
kept_count
:
*
kept_count
}
Fields
::
Filtered
{
fields
,
len
:
*
len
}
}
_
=>
Fields
::
Slice
(
pats
),
}
...
...
compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
浏览文件 @
1c176d11
...
...
@@ -447,7 +447,7 @@ fn pop_head_constructor(&self, ctor_wild_subpatterns: &Fields<'p, 'tcx>) -> PatS
// We pop the head pattern and push the new fields extracted from the arguments of
// `self.head()`.
let
mut
new_fields
=
ctor_wild_subpatterns
.replace_with_pattern_arguments
(
self
.head
())
.
filtered
_patterns
();
ctor_wild_subpatterns
.replace_with_pattern_arguments
(
self
.head
())
.
into
_patterns
();
new_fields
.extend_from_slice
(
&
self
.pats
[
1
..
]);
PatStack
::
from_vec
(
new_fields
)
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录