Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
173315e3
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,发现更多精彩内容 >>
提交
173315e3
编写于
5月 04, 2018
作者:
F
Felix S. Klock II
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rust-lang/rust#27282: emit `ReadForMatch` on each match arm.
Also, turn on ReadForMatch emission by default (when using NLL).
上级
24abe6f3
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
107 addition
and
4 deletion
+107
-4
src/librustc/session/config.rs
src/librustc/session/config.rs
+4
-0
src/librustc/ty/context.rs
src/librustc/ty/context.rs
+13
-0
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/matches/mod.rs
+90
-4
未找到文件。
src/librustc/session/config.rs
浏览文件 @
173315e3
...
...
@@ -1298,10 +1298,14 @@ fn parse_cross_lang_lto(slot: &mut CrossLangLto, v: Option<&str>) -> bool {
"dump facts from NLL analysis into side files"
),
disable_nll_user_type_assert
:
bool
=
(
false
,
parse_bool
,
[
UNTRACKED
],
"disable user provided type assertion in NLL"
),
nll_dont_emit_read_for_match
:
bool
=
(
false
,
parse_bool
,
[
UNTRACKED
],
"in match codegen, do not include ReadForMatch statements (used by mir-borrowck)"
),
polonius
:
bool
=
(
false
,
parse_bool
,
[
UNTRACKED
],
"enable polonius-based borrow-checker"
),
codegen_time_graph
:
bool
=
(
false
,
parse_bool
,
[
UNTRACKED
],
"generate a graphical HTML report of time spent in codegen and LLVM"
),
trans_time_graph
:
bool
=
(
false
,
parse_bool
,
[
UNTRACKED
],
"generate a graphical HTML report of time spent in trans and LLVM"
),
thinlto
:
Option
<
bool
>
=
(
None
,
parse_opt_bool
,
[
TRACKED
],
"enable ThinLTO when possible"
),
inline_in_all_cgus
:
Option
<
bool
>
=
(
None
,
parse_opt_bool
,
[
TRACKED
],
...
...
src/librustc/ty/context.rs
浏览文件 @
173315e3
...
...
@@ -1356,6 +1356,19 @@ pub fn use_mir_borrowck(self) -> bool {
self
.borrowck_mode
()
.use_mir
()
}
/// If true, make MIR codegen for `match` emit a temp that holds a
/// borrow of the input to the match expression.
pub
fn
generate_borrow_of_any_match_input
(
&
self
)
->
bool
{
self
.emit_read_for_match
()
}
/// If true, make MIR codegen for `match` emit ReadForMatch
/// statements (which simulate the maximal effect of executing the
/// patterns in a match arm).
pub
fn
emit_read_for_match
(
&
self
)
->
bool
{
self
.use_mir_borrowck
()
&&
!
self
.sess.opts.debugging_opts.nll_dont_emit_read_for_match
}
/// If true, pattern variables for use in guards on match arms
/// will be bound as references to the data, and occurrences of
/// those variables in the guard expression will implicitly
...
...
src/librustc_mir/build/matches/mod.rs
浏览文件 @
173315e3
...
...
@@ -30,6 +30,16 @@
mod
test
;
mod
util
;
/// Injects a borrow of `place`. The region is unknown at this point; we rely on NLL
/// inference to find an appropriate one. Therefore you can only call this when NLL
/// is turned on.
fn
inject_borrow
<
'a
,
'gcx
,
'tcx
>
(
tcx
:
ty
::
TyCtxt
<
'a
,
'gcx
,
'tcx
>
,
place
:
Place
<
'tcx
>
)
->
Rvalue
<
'tcx
>
{
assert
!
(
tcx
.use_mir_borrowck
());
Rvalue
::
Ref
(
tcx
.types.re_empty
,
BorrowKind
::
Shared
,
place
)
}
/// ArmHasGuard is isomorphic to a boolean flag. It indicates whether
/// a match arm has a guard expression attached to it.
#[derive(Copy,
Clone,
Debug)]
...
...
@@ -43,6 +53,7 @@ pub fn match_expr(&mut self,
discriminant
:
ExprRef
<
'tcx
>
,
arms
:
Vec
<
Arm
<
'tcx
>>
)
->
BlockAnd
<
()
>
{
let
tcx
=
self
.hir
.tcx
();
let
discriminant_place
=
unpack!
(
block
=
self
.as_place
(
block
,
discriminant
));
// Matching on a `discriminant_place` with an uninhabited type doesn't
...
...
@@ -55,16 +66,34 @@ pub fn match_expr(&mut self,
// HACK(eddyb) Work around the above issue by adding a dummy inspection
// of `discriminant_place`, specifically by applying `Rvalue::Discriminant`
// (which will work regardless of type) and storing the result in a temp.
//
// FIXME: would just the borrow into `borrowed_input_temp`
// also achieve the desired effect here? TBD.
let
dummy_source_info
=
self
.source_info
(
span
);
let
dummy_access
=
Rvalue
::
Discriminant
(
discriminant_place
.clone
());
let
dummy_ty
=
dummy_access
.ty
(
&
self
.local_decls
,
self
.hir
.tcx
()
);
let
dummy_ty
=
dummy_access
.ty
(
&
self
.local_decls
,
tcx
);
let
dummy_temp
=
self
.temp
(
dummy_ty
,
dummy_source_info
.span
);
self
.cfg
.push_assign
(
block
,
dummy_source_info
,
&
dummy_temp
,
dummy_access
);
let
source_info
=
self
.source_info
(
span
);
let
borrowed_input_temp
=
if
tcx
.generate_borrow_of_any_match_input
()
{
let
borrowed_input
=
inject_borrow
(
tcx
,
discriminant_place
.clone
());
let
borrowed_input_ty
=
borrowed_input
.ty
(
&
self
.local_decls
,
tcx
);
let
borrowed_input_temp
=
self
.temp
(
borrowed_input_ty
,
span
);
self
.cfg
.push_assign
(
block
,
source_info
,
&
borrowed_input_temp
,
borrowed_input
);
Some
(
borrowed_input_temp
)
}
else
{
None
};
let
mut
arm_blocks
=
ArmBlocks
{
blocks
:
arms
.iter
()
.map
(|
_
|
self
.cfg
.start_new_block
())
.collect
(),
.map
(|
_
|
{
let
arm_block
=
self
.cfg
.start_new_block
();
arm_block
})
.collect
(),
};
// Get the arm bodies and their scopes, while declaring bindings.
...
...
@@ -81,7 +110,9 @@ pub fn match_expr(&mut self,
// create binding start block for link them by false edges
let
candidate_count
=
arms
.iter
()
.fold
(
0
,
|
ac
,
c
|
ac
+
c
.patterns
.len
());
let
pre_binding_blocks
:
Vec
<
_
>
=
(
0
..
candidate_count
+
1
)
.map
(|
_
|
self
.cfg
.start_new_block
())
.collect
();
.map
(|
_
|
self
.cfg
.start_new_block
())
.collect
();
// assemble a list of candidates: there is one candidate per
// pattern, which means there may be more than one candidate
...
...
@@ -99,6 +130,61 @@ pub fn match_expr(&mut self,
.zip
(
pre_binding_blocks
.iter
()
.zip
(
pre_binding_blocks
.iter
()
.skip
(
1
)))
.map
(|((
arm_index
,
pattern
,
guard
),
(
pre_binding_block
,
next_candidate_pre_binding_block
))|
{
if
let
(
true
,
Some
(
borrow_temp
))
=
(
tcx
.emit_read_for_match
(),
borrowed_input_temp
.clone
())
{
// inject a fake read of the borrowed input at
// the start of each arm's pattern testing
// code.
//
// This should ensure that you cannot change
// the variant for an enum while you are in
// the midst of matching on it.
//
// FIXME: I originally had put this at the
// start of each elem of arm_blocks (see
// ArmBlocks construction above). But this was
// broken; for example, when you had a trivial
// match like `match "foo".to_string() { _s =>
// {} }`, it would inject a ReadForMatch
// *after* the move of the input into `_s`,
// and that then does not pass the borrow
// check.
//
// * So: I need to fine tune exactly *where*
// the ReadForMatch belongs. Should it come
// at the beginning of each pattern match,
// or the end? And, should there be one
// ReadForMatch per arm, or one per
// candidate (aka pattern)?
self
.cfg
.push
(
*
pre_binding_block
,
Statement
{
source_info
,
kind
:
StatementKind
::
ReadForMatch
(
borrow_temp
.clone
()),
});
}
// One might ask: why not build up the match pair such that it
// matches via `borrowed_input_temp.deref()` instead of
// using the `discriminant_place` directly, as it is doing here?
//
// The basic answer is that if you do that, then you end up with
// accceses to a shared borrow of the input and that conflicts with
// any arms that look like e.g.
//
// match Some(&4) {
// ref mut foo => {
// ... /* mutate `foo` in arm body */ ...
// }
// }
//
// (Perhaps we could further revise the MIR
// construction here so that it only does a
// shared borrow at the outset and delays doing
// the mutable borrow until after the pattern is
// matched *and* the guard (if any) for the arm
// has been run.)
Candidate
{
span
:
pattern
.span
,
match_pairs
:
vec!
[
MatchPair
::
new
(
discriminant_place
.clone
(),
pattern
)],
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录