Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
2d71c5f1
R
Rust
项目概览
int
/
Rust
11 个月 前同步成功
通知
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,发现更多精彩内容 >>
提交
2d71c5f1
编写于
10月 13, 2017
作者:
M
Mikhail Modin
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add TerminatorKind::FalseEdges and use it in matches
上级
2379faa9
变更
21
隐藏空白更改
内联
并排
Showing
21 changed file
with
377 addition
and
48 deletion
+377
-48
src/librustc/ich/impls_mir.rs
src/librustc/ich/impls_mir.rs
+8
-1
src/librustc/mir/mod.rs
src/librustc/mir/mod.rs
+28
-4
src/librustc/mir/visit.rs
src/librustc/mir/visit.rs
+7
-0
src/librustc_mir/borrow_check.rs
src/librustc_mir/borrow_check.rs
+2
-1
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/matches/mod.rs
+83
-35
src/librustc_mir/build/matches/test.rs
src/librustc_mir/build/matches/test.rs
+4
-0
src/librustc_mir/dataflow/mod.rs
src/librustc_mir/dataflow/mod.rs
+6
-0
src/librustc_mir/dataflow/move_paths/builder.rs
src/librustc_mir/dataflow/move_paths/builder.rs
+1
-0
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/check_unsafety.rs
+2
-1
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/inline.rs
+6
-0
src/librustc_mir/transform/no_landing_pads.rs
src/librustc_mir/transform/no_landing_pads.rs
+2
-1
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/qualify_consts.rs
+2
-1
src/librustc_mir/transform/simplify_branches.rs
src/librustc_mir/transform/simplify_branches.rs
+3
-0
src/librustc_mir/transform/type_check.rs
src/librustc_mir/transform/type_check.rs
+8
-1
src/librustc_passes/mir_stats.rs
src/librustc_passes/mir_stats.rs
+1
-0
src/librustc_trans/mir/analyze.rs
src/librustc_trans/mir/analyze.rs
+2
-1
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/block.rs
+2
-1
src/librustc_trans_utils/collector.rs
src/librustc_trans_utils/collector.rs
+2
-1
src/test/compile-fail/borrowck/borrowck-drop-from-guard.rs
src/test/compile-fail/borrowck/borrowck-drop-from-guard.rs
+24
-0
src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs
.../compile-fail/borrowck/borrowck-match-already-borrowed.rs
+18
-0
src/test/mir-opt/match_false_edges.rs
src/test/mir-opt/match_false_edges.rs
+166
-0
未找到文件。
src/librustc/ich/impls_mir.rs
浏览文件 @
2d71c5f1
...
...
@@ -62,7 +62,8 @@ fn hash_stable<W: StableHasherResult>(&self,
mir
::
TerminatorKind
::
Drop
{
..
}
|
mir
::
TerminatorKind
::
DropAndReplace
{
..
}
|
mir
::
TerminatorKind
::
Yield
{
..
}
|
mir
::
TerminatorKind
::
Call
{
..
}
=>
false
,
mir
::
TerminatorKind
::
Call
{
..
}
|
mir
::
TerminatorKind
::
FalseEdges
{
..
}
=>
false
,
};
if
hash_spans_unconditionally
{
...
...
@@ -210,6 +211,12 @@ fn hash_stable<W: StableHasherResult>(&self,
target
.hash_stable
(
hcx
,
hasher
);
cleanup
.hash_stable
(
hcx
,
hasher
);
}
mir
::
TerminatorKind
::
FalseEdges
{
ref
real_target
,
ref
imaginary_targets
}
=>
{
real_target
.hash_stable
(
hcx
,
hasher
);
for
target
in
imaginary_targets
{
target
.hash_stable
(
hcx
,
hasher
);
}
}
}
}
}
...
...
src/librustc/mir/mod.rs
浏览文件 @
2d71c5f1
...
...
@@ -682,6 +682,11 @@ pub enum TerminatorKind<'tcx> {
/// Indicates the end of the dropping of a generator
GeneratorDrop
,
FalseEdges
{
real_target
:
BasicBlock
,
imaginary_targets
:
Vec
<
BasicBlock
>
},
}
impl
<
'tcx
>
Terminator
<
'tcx
>
{
...
...
@@ -731,6 +736,11 @@ pub fn successors(&self) -> Cow<[BasicBlock]> {
}
Assert
{
target
,
cleanup
:
Some
(
unwind
),
..
}
=>
vec!
[
target
,
unwind
]
.into_cow
(),
Assert
{
ref
target
,
..
}
=>
slice
::
ref_slice
(
target
)
.into_cow
(),
FalseEdges
{
ref
real_target
,
ref
imaginary_targets
}
=>
{
let
mut
s
=
vec!
[
*
real_target
];
s
.extend_from_slice
(
imaginary_targets
);
s
.into_cow
()
}
}
}
...
...
@@ -757,7 +767,12 @@ pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> {
vec!
[
target
]
}
Assert
{
ref
mut
target
,
cleanup
:
Some
(
ref
mut
unwind
),
..
}
=>
vec!
[
target
,
unwind
],
Assert
{
ref
mut
target
,
..
}
=>
vec!
[
target
]
Assert
{
ref
mut
target
,
..
}
=>
vec!
[
target
],
FalseEdges
{
ref
mut
real_target
,
ref
mut
imaginary_targets
}
=>
{
let
mut
s
=
vec!
[
real_target
];
s
.extend
(
imaginary_targets
.iter_mut
());
s
}
}
}
}
...
...
@@ -874,7 +889,8 @@ pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result {
}
write!
(
fmt
,
")"
)
}
},
FalseEdges
{
..
}
=>
write!
(
fmt
,
"falseEdges"
)
}
}
...
...
@@ -910,7 +926,12 @@ pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
}
Assert
{
cleanup
:
None
,
..
}
=>
vec!
[
""
.into
()],
Assert
{
..
}
=>
vec!
[
"success"
.into_cow
(),
"unwind"
.into_cow
()]
vec!
[
"success"
.into_cow
(),
"unwind"
.into_cow
()],
FalseEdges
{
ref
imaginary_targets
,
..
}
=>
{
let
mut
l
=
vec!
[
"real"
.into
()];
l
.resize
(
imaginary_targets
.len
()
+
1
,
"imaginary"
.into
());
l
}
}
}
}
...
...
@@ -1878,6 +1899,8 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
Resume
=>
Resume
,
Return
=>
Return
,
Unreachable
=>
Unreachable
,
FalseEdges
{
real_target
,
ref
imaginary_targets
}
=>
FalseEdges
{
real_target
,
imaginary_targets
:
imaginary_targets
.clone
()
}
};
Terminator
{
source_info
:
self
.source_info
,
...
...
@@ -1917,7 +1940,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
Resume
|
Return
|
GeneratorDrop
|
Unreachable
=>
false
Unreachable
|
FalseEdges
{
..
}
=>
false
}
}
}
...
...
src/librustc/mir/visit.rs
浏览文件 @
2d71c5f1
...
...
@@ -486,8 +486,15 @@ fn super_terminator_kind(&mut self,
self
.visit_operand
(
value
,
source_location
);
self
.visit_branch
(
block
,
resume
);
drop
.map
(|
t
|
self
.visit_branch
(
block
,
t
));
}
TerminatorKind
::
FalseEdges
{
real_target
,
ref
imaginary_targets
}
=>
{
self
.visit_branch
(
block
,
real_target
);
for
target
in
imaginary_targets
{
self
.visit_branch
(
block
,
*
target
);
}
}
}
}
...
...
src/librustc_mir/borrow_check.rs
浏览文件 @
2d71c5f1
...
...
@@ -364,7 +364,8 @@ fn visit_terminator_entry(&mut self,
TerminatorKind
::
Resume
|
TerminatorKind
::
Return
|
TerminatorKind
::
GeneratorDrop
|
TerminatorKind
::
Unreachable
=>
{
TerminatorKind
::
Unreachable
|
TerminatorKind
::
FalseEdges
{
..
}
=>
{
// no data used, thus irrelevant to borrowck
}
}
...
...
src/librustc_mir/build/matches/mod.rs
浏览文件 @
2d71c5f1
...
...
@@ -21,7 +21,7 @@
use
rustc
::
hir
;
use
hair
::
*
;
use
syntax
::
ast
::{
Name
,
NodeId
};
use
syntax_pos
::
{
DUMMY_SP
,
Span
}
;
use
syntax_pos
::
Span
;
// helper functions, broken out by category:
mod
simplify
;
...
...
@@ -54,11 +54,17 @@ pub fn match_expr(&mut self,
(
body
,
scope
.unwrap_or
(
self
.visibility_scope
))
})
.collect
();
// create binding start block for link them by false edges
let
candidate_count
=
arms
.iter
()
.fold
(
0
,
|
ac
,
c
|
ac
+
c
.patterns
.len
());
let
binding_start_blocks
:
Vec
<
_
>
=
(
0
..
candidate_count
+
1
)
.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
// *per arm*. These candidates are kept sorted such that the
// highest priority candidate comes first in the list.
// (i.e. same order as in source)
let
candidates
:
Vec
<
_
>
=
arms
.iter
()
.enumerate
()
...
...
@@ -66,17 +72,25 @@ pub fn match_expr(&mut self,
arm
.patterns
.iter
()
.map
(
move
|
pat
|
(
arm_index
,
pat
,
arm
.guard
.clone
()))
})
.map
(|(
arm_index
,
pattern
,
guard
)|
{
.zip
(
binding_start_blocks
.iter
()
.zip
(
binding_start_blocks
.iter
()
.skip
(
1
)))
.map
(|((
arm_index
,
pattern
,
guard
),
(
binding_start_block
,
next_candidate_binding_start_block
))|
{
Candidate
{
span
:
pattern
.span
,
match_pairs
:
vec!
[
MatchPair
::
new
(
discriminant_lvalue
.clone
(),
pattern
)],
bindings
:
vec!
[],
guard
,
arm_index
,
binding_start_block
:
*
binding_start_block
,
next_candidate_binding_start_block
:
*
next_candidate_binding_start_block
,
}
})
.collect
();
let
outer_source_info
=
self
.source_info
(
span
);
self
.cfg
.terminate
(
*
binding_start_blocks
.last
()
.unwrap
(),
outer_source_info
,
TerminatorKind
::
Unreachable
);
// this will generate code to test discriminant_lvalue and
// branch to the appropriate arm block
let
otherwise
=
self
.match_candidates
(
span
,
&
mut
arm_blocks
,
candidates
,
block
);
...
...
@@ -148,7 +162,11 @@ pub fn lvalue_into_pattern(&mut self,
match_pairs
:
vec!
[
MatchPair
::
new
(
initializer
.clone
(),
&
irrefutable_pat
)],
bindings
:
vec!
[],
guard
:
None
,
arm_index
:
0
,
// since we don't call `match_candidates`, this field is unused
// since we don't call `match_candidates`, next fields is unused
arm_index
:
0
,
binding_start_block
:
block
,
next_candidate_binding_start_block
:
block
};
// Simplify the candidate. Since the pattern is irrefutable, this should
...
...
@@ -278,6 +296,10 @@ pub struct Candidate<'pat, 'tcx:'pat> {
// ...and then we branch to arm with this index.
arm_index
:
usize
,
// ...and the blocks for add false edges between candidates
binding_start_block
:
BasicBlock
,
next_candidate_binding_start_block
:
BasicBlock
,
}
#[derive(Clone,
Debug)]
...
...
@@ -398,17 +420,43 @@ fn match_candidates<'pat>(&mut self,
candidates
.iter
()
.take_while
(|
c
|
c
.match_pairs
.is_empty
())
.count
();
debug!
(
"match_candidates: {:?} candidates fully matched"
,
fully_matched
);
let
mut
unmatched_candidates
=
candidates
.split_off
(
fully_matched
);
for
(
index
,
candidate
)
in
candidates
.into_iter
()
.enumerate
()
{
let
fully_matched_with_guard
=
candidates
.iter
()
.take_while
(|
c
|
c
.guard
.is_some
())
.count
();
let
unreachable_candidates
=
if
fully_matched_with_guard
+
1
<
candidates
.len
()
{
candidates
.split_off
(
fully_matched_with_guard
+
1
)
}
else
{
vec!
[]
};
for
candidate
in
candidates
{
// If so, apply any bindings, test the guard (if any), and
// branch to the arm.
let
is_last
=
index
==
fully_matched
-
1
;
if
let
Some
(
b
)
=
self
.bind_and_guard_matched_candidate
(
block
,
arm_blocks
,
candidate
,
is_last
)
{
if
let
Some
(
b
)
=
self
.bind_and_guard_matched_candidate
(
block
,
arm_blocks
,
candidate
)
{
block
=
b
;
}
else
{
// if None is returned, then any remaining candidates
// are unreachable (at least not through this path).
return
vec!
[];
// Link them with false edges.
debug!
(
"match_candidates: add false edges for unreachable {:?} and unmatched {:?}"
,
unreachable_candidates
,
unmatched_candidates
);
for
candidate
in
unreachable_candidates
{
let
source_info
=
self
.source_info
(
candidate
.span
);
let
target
=
self
.cfg
.start_new_block
();
if
let
Some
(
otherwise
)
=
self
.bind_and_guard_matched_candidate
(
target
,
arm_blocks
,
candidate
)
{
self
.cfg
.terminate
(
otherwise
,
source_info
,
TerminatorKind
::
Unreachable
);
}
}
if
unmatched_candidates
.is_empty
()
{
return
vec!
[]
}
else
{
let
target
=
self
.cfg
.start_new_block
();
return
self
.match_candidates
(
span
,
arm_blocks
,
unmatched_candidates
,
target
);
}
}
}
...
...
@@ -423,9 +471,7 @@ fn match_candidates<'pat>(&mut self,
self
.test_candidates
(
span
,
arm_blocks
,
&
unmatched_candidates
,
block
);
// If the target candidates were exhaustive, then we are done.
if
otherwise
.is_empty
()
{
return
vec!
[];
}
// But for borrowck continue build decision tree.
// If all candidates were sorted into `target_candidates` somewhere, then
// the initial set was inexhaustive.
...
...
@@ -666,17 +712,24 @@ fn test_candidates<'pat>(&mut self,
fn
bind_and_guard_matched_candidate
<
'pat
>
(
&
mut
self
,
mut
block
:
BasicBlock
,
arm_blocks
:
&
mut
ArmBlocks
,
candidate
:
Candidate
<
'pat
,
'tcx
>
,
is_last_arm
:
bool
)
candidate
:
Candidate
<
'pat
,
'tcx
>
)
->
Option
<
BasicBlock
>
{
debug!
(
"bind_and_guard_matched_candidate(block={:?}, candidate={:?})"
,
block
,
candidate
);
debug_assert!
(
candidate
.match_pairs
.is_empty
());
self
.bind_matched_candidate
(
block
,
candidate
.bindings
);
let
arm_block
=
arm_blocks
.blocks
[
candidate
.arm_index
];
let
candidate_source_info
=
self
.source_info
(
candidate
.span
);
self
.cfg
.terminate
(
block
,
candidate_source_info
,
TerminatorKind
::
FalseEdges
{
real_target
:
candidate
.binding_start_block
,
imaginary_targets
:
vec!
[
candidate
.next_candidate_binding_start_block
]});
block
=
candidate
.binding_start_block
;
self
.bind_matched_candidate
(
block
,
candidate
.bindings
);
if
let
Some
(
guard
)
=
candidate
.guard
{
// the block to branch to if the guard fails; if there is no
...
...
@@ -684,30 +737,25 @@ fn bind_and_guard_matched_candidate<'pat>(&mut self,
let
guard
=
self
.hir
.mirror
(
guard
);
let
source_info
=
self
.source_info
(
guard
.span
);
let
cond
=
unpack!
(
block
=
self
.as_local_operand
(
block
,
guard
));
let
otherwise
=
self
.cfg
.start_new_block
();
let
false_edge_block
=
self
.cfg
.start_new_block
();
self
.cfg
.terminate
(
block
,
source_info
,
TerminatorKind
::
if_
(
self
.hir
.tcx
(),
cond
,
arm_block
,
otherwise
));
Some
(
otherwise
)
}
else
if
!
is_last_arm
{
// Add always true guard in case of more than one arm
// it creates false edges and allow MIR borrowck detects errors
// FIXME(#45184) -- permit "false edges"
let
source_info
=
self
.source_info
(
candidate
.span
);
let
true_expr
=
Expr
{
temp_lifetime
:
None
,
ty
:
self
.hir
.tcx
()
.types.bool
,
span
:
DUMMY_SP
,
kind
:
ExprKind
::
Literal
{
literal
:
self
.hir
.true_literal
()},
};
let
cond
=
unpack!
(
block
=
self
.as_local_operand
(
block
,
true_expr
));
TerminatorKind
::
if_
(
self
.hir
.tcx
(),
cond
,
arm_block
,
false_edge_block
));
let
otherwise
=
self
.cfg
.start_new_block
();
self
.cfg
.terminate
(
block
,
source_info
,
TerminatorKind
::
if_
(
self
.hir
.tcx
(),
cond
,
arm_block
,
otherwise
));
self
.cfg
.terminate
(
false_edge_block
,
source_info
,
TerminatorKind
::
FalseEdges
{
real_target
:
otherwise
,
imaginary_targets
:
vec!
[
candidate
.next_candidate_binding_start_block
]
});
Some
(
otherwise
)
}
else
{
let
source_info
=
self
.source_info
(
candidate
.span
);
self
.cfg
.terminate
(
block
,
source_info
,
TerminatorKind
::
Goto
{
target
:
arm_block
});
self
.cfg
.terminate
(
block
,
candidate_source_info
,
TerminatorKind
::
FalseEdges
{
real_target
:
arm_block
,
imaginary_targets
:
vec!
[
candidate
.next_candidate_binding_start_block
]});
None
}
}
...
...
src/librustc_mir/build/matches/test.rs
浏览文件 @
2d71c5f1
...
...
@@ -598,6 +598,8 @@ fn candidate_without_match_pair<'pat>(&mut self,
bindings
:
candidate
.bindings
.clone
(),
guard
:
candidate
.guard
.clone
(),
arm_index
:
candidate
.arm_index
,
binding_start_block
:
candidate
.binding_start_block
,
next_candidate_binding_start_block
:
candidate
.next_candidate_binding_start_block
,
}
}
...
...
@@ -659,6 +661,8 @@ fn candidate_after_variant_switch<'pat>(&mut self,
bindings
:
candidate
.bindings
.clone
(),
guard
:
candidate
.guard
.clone
(),
arm_index
:
candidate
.arm_index
,
binding_start_block
:
candidate
.binding_start_block
,
next_candidate_binding_start_block
:
candidate
.next_candidate_binding_start_block
,
}
}
...
...
src/librustc_mir/dataflow/mod.rs
浏览文件 @
2d71c5f1
...
...
@@ -721,6 +721,12 @@ fn propagate_bits_into_graph_successors_of(
self
.propagate_bits_into_entry_set_for
(
in_out
,
changed
,
dest_bb
);
}
}
mir
::
TerminatorKind
::
FalseEdges
{
ref
real_target
,
ref
imaginary_targets
}
=>
{
self
.propagate_bits_into_entry_set_for
(
in_out
,
changed
,
real_target
);
for
target
in
imaginary_targets
{
self
.propagate_bits_into_entry_set_for
(
in_out
,
changed
,
target
);
}
}
}
}
...
...
src/librustc_mir/dataflow/move_paths/builder.rs
浏览文件 @
2d71c5f1
...
...
@@ -305,6 +305,7 @@ fn gather_terminator(&mut self, term: &Terminator<'tcx>) {
TerminatorKind
::
Goto
{
target
:
_
}
|
TerminatorKind
::
Resume
|
TerminatorKind
::
GeneratorDrop
|
TerminatorKind
::
FalseEdges
{
..
}
|
TerminatorKind
::
Unreachable
=>
{
}
TerminatorKind
::
Return
=>
{
...
...
src/librustc_mir/transform/check_unsafety.rs
浏览文件 @
2d71c5f1
...
...
@@ -73,7 +73,8 @@ fn visit_terminator(&mut self,
TerminatorKind
::
GeneratorDrop
|
TerminatorKind
::
Resume
|
TerminatorKind
::
Return
|
TerminatorKind
::
Unreachable
=>
{
TerminatorKind
::
Unreachable
|
TerminatorKind
::
FalseEdges
{
..
}
=>
{
// safe (at least as emitted during MIR construction)
}
...
...
src/librustc_mir/transform/inline.rs
浏览文件 @
2d71c5f1
...
...
@@ -720,6 +720,12 @@ fn visit_terminator_kind(&mut self, block: BasicBlock,
}
}
TerminatorKind
::
Unreachable
=>
{
}
TerminatorKind
::
FalseEdges
{
ref
mut
real_target
,
ref
mut
imaginary_targets
}
=>
{
*
real_target
=
self
.update_target
(
*
real_target
);
for
target
in
imaginary_targets
{
*
target
=
self
.update_target
(
*
target
);
}
}
}
}
...
...
src/librustc_mir/transform/no_landing_pads.rs
浏览文件 @
2d71c5f1
...
...
@@ -45,7 +45,8 @@ fn visit_terminator(&mut self,
TerminatorKind
::
Unreachable
|
TerminatorKind
::
GeneratorDrop
|
TerminatorKind
::
Yield
{
..
}
|
TerminatorKind
::
SwitchInt
{
..
}
=>
{
TerminatorKind
::
SwitchInt
{
..
}
|
TerminatorKind
::
FalseEdges
{
..
}
=>
{
/* nothing to do */
},
TerminatorKind
::
Call
{
cleanup
:
ref
mut
unwind
,
..
}
|
...
...
src/librustc_mir/transform/qualify_consts.rs
浏览文件 @
2d71c5f1
...
...
@@ -317,7 +317,8 @@ fn qualify_const(&mut self) -> (Qualif, Rc<IdxSetBuf<Local>>) {
TerminatorKind
::
Resume
|
TerminatorKind
::
GeneratorDrop
|
TerminatorKind
::
Yield
{
..
}
|
TerminatorKind
::
Unreachable
=>
None
,
TerminatorKind
::
Unreachable
|
TerminatorKind
::
FalseEdges
{
..
}
=>
None
,
TerminatorKind
::
Return
=>
{
// Check for unused values. This usually means
...
...
src/librustc_mir/transform/simplify_branches.rs
浏览文件 @
2d71c5f1
...
...
@@ -61,6 +61,9 @@ fn run_pass<'a, 'tcx>(&self,
}),
expected
,
..
}
if
cond
==
expected
=>
{
TerminatorKind
::
Goto
{
target
:
target
}
},
TerminatorKind
::
FalseEdges
{
real_target
,
..
}
=>
{
TerminatorKind
::
Goto
{
target
:
real_target
}
},
_
=>
continue
};
}
...
...
src/librustc_mir/transform/type_check.rs
浏览文件 @
2d71c5f1
...
...
@@ -441,7 +441,8 @@ fn check_terminator(&mut self,
TerminatorKind
::
Return
|
TerminatorKind
::
GeneratorDrop
|
TerminatorKind
::
Unreachable
|
TerminatorKind
::
Drop
{
..
}
=>
{
TerminatorKind
::
Drop
{
..
}
|
TerminatorKind
::
FalseEdges
{
..
}
=>
{
// no checks needed for these
}
...
...
@@ -685,6 +686,12 @@ fn check_iscleanup(&mut self, mir: &Mir<'tcx>, block: &BasicBlockData<'tcx>)
self
.assert_iscleanup
(
mir
,
block
,
cleanup
,
true
);
}
}
TerminatorKind
::
FalseEdges
{
real_target
,
ref
imaginary_targets
}
=>
{
self
.assert_iscleanup
(
mir
,
block
,
real_target
,
is_cleanup
);
for
target
in
imaginary_targets
{
self
.assert_iscleanup
(
mir
,
block
,
*
target
,
is_cleanup
);
}
}
}
}
...
...
src/librustc_passes/mir_stats.rs
浏览文件 @
2d71c5f1
...
...
@@ -121,6 +121,7 @@ fn visit_terminator_kind(&mut self,
TerminatorKind
::
Assert
{
..
}
=>
"TerminatorKind::Assert"
,
TerminatorKind
::
GeneratorDrop
=>
"TerminatorKind::GeneratorDrop"
,
TerminatorKind
::
Yield
{
..
}
=>
"TerminatorKind::Yield"
,
TerminatorKind
::
FalseEdges
{
..
}
=>
"TerminatorKind::FalseEdges"
,
},
kind
);
self
.super_terminator_kind
(
block
,
kind
,
location
);
}
...
...
src/librustc_trans/mir/analyze.rs
浏览文件 @
2d71c5f1
...
...
@@ -228,7 +228,8 @@ fn discover_masters<'tcx>(result: &mut IndexVec<mir::BasicBlock, CleanupKind>,
TerminatorKind
::
GeneratorDrop
|
TerminatorKind
::
Unreachable
|
TerminatorKind
::
SwitchInt
{
..
}
|
TerminatorKind
::
Yield
{
..
}
=>
{
TerminatorKind
::
Yield
{
..
}
|
TerminatorKind
::
FalseEdges
{
..
}
=>
{
/* nothing to do */
}
TerminatorKind
::
Call
{
cleanup
:
unwind
,
..
}
|
...
...
src/librustc_trans/mir/block.rs
浏览文件 @
2d71c5f1
...
...
@@ -583,7 +583,8 @@ fn trans_terminator(&mut self,
cleanup
);
}
mir
::
TerminatorKind
::
GeneratorDrop
|
mir
::
TerminatorKind
::
Yield
{
..
}
=>
bug!
(
"generator ops in trans"
),
mir
::
TerminatorKind
::
Yield
{
..
}
|
mir
::
TerminatorKind
::
FalseEdges
{
..
}
=>
bug!
(
"generator ops in trans"
),
}
}
...
...
src/librustc_trans_utils/collector.rs
浏览文件 @
2d71c5f1
...
...
@@ -623,7 +623,8 @@ fn visit_terminator_kind(&mut self,
mir
::
TerminatorKind
::
Unreachable
|
mir
::
TerminatorKind
::
Assert
{
..
}
=>
{}
mir
::
TerminatorKind
::
GeneratorDrop
|
mir
::
TerminatorKind
::
Yield
{
..
}
=>
bug!
(),
mir
::
TerminatorKind
::
Yield
{
..
}
|
mir
::
TerminatorKind
::
FalseEdges
{
..
}
=>
bug!
(),
}
self
.super_terminator_kind
(
block
,
kind
,
location
);
...
...
src/test/compile-fail/borrowck/borrowck-drop-from-guard.rs
0 → 100644
浏览文件 @
2d71c5f1
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//compile-flags: -Z emit-end-regions -Z borrowck-mir
fn
foo
(
_
:
String
)
{}
fn
main
()
{
let
my_str
=
"hello"
.to_owned
();
match
Some
(
42
)
{
Some
(
_
)
if
{
drop
(
my_str
);
false
}
=>
{}
Some
(
_
)
=>
{}
None
=>
{
foo
(
my_str
);
}
//~ ERROR (Mir) [E0381]
}
}
src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs
浏览文件 @
2d71c5f1
...
...
@@ -11,6 +11,24 @@
// revisions: ast mir
//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
enum
Foo
{
A
(
i32
),
B
}
fn
match_enum
()
{
let
mut
foo
=
Foo
::
B
;
let
p
=
&
mut
foo
;
let
_
=
match
foo
{
Foo
::
B
=>
1
,
//[mir]~ ERROR (Mir) [E0503]
_
=>
2
,
Foo
::
A
(
x
)
=>
x
//[ast]~ ERROR [E0503]
//[mir]~^ ERROR (Ast) [E0503]
//[mir]~| ERROR (Mir) [E0503]
};
}
fn
main
()
{
let
mut
x
=
1
;
let
_
x
=
&
mut
x
;
...
...
src/test/mir-opt/match_false_edges.rs
0 → 100644
浏览文件 @
2d71c5f1
// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: -Z emit-end-regions -Z borrowck-mir
fn
guard
()
->
bool
{
false
}
fn
guard2
(
_
:
i32
)
->
bool
{
true
}
fn
full_tested_match
()
{
let
_
=
match
Some
(
42
)
{
Some
(
_
)
if
guard
()
=>
1
,
Some
(
_
)
=>
2
,
None
=>
3
};
}
fn
main
()
{
let
_
=
match
Some
(
1
)
{
Some
(
_
w
)
if
guard
()
=>
1
,
_
x
=>
2
,
Some
(
y
)
if
guard2
(
y
)
=>
3
,
_
z
=>
4
,
};
}
// END RUST SOURCE
//
// START rustc.node17.NLL.before.mir
// bb0: {
// ...
// _2 = std::option::Option<i32>::Some(const 42i32,);
// _3 = discriminant(_2);
// switchInt(_3) -> [0isize: bb8, otherwise: bb9];
// }
// bb1: { // arm1
// _1 = const 1i32;
// goto -> bb13;
// }
// bb2: { // arm2
// _1 = const 2i32;
// goto -> bb13;
// }
// bb3: { // arm3
// _1 = const 3i32;
// goto -> bb13;
// }
// bb4: { // binding1
// ...
// _4 = const guard() -> bb10;
// }
// bb5: { // binding2
// falseEdges -> [real: bb2, imaginary: bb6];
// }
// bb6: { // binding3
// falseEdges -> [real: bb3, imaginary: bb7];
// }
// bb7: {
// unreachable;
// }
// bb8: {
// falseEdges -> [real: bb6, imaginary: bb7]; // from before_binding3 to unreachable
// }
// bb9: {
// falseEdges -> [real: bb4, imaginary: bb5]; // from before_binding1 to binding2
// }
// bb10: {
// switchInt(_4) -> [0u8: bb11, otherwise: bb1]; // end of guard
// }
// bb11: {
// falseEdges -> [real: bb12, imaginary: bb5]; // after_guard to binding2
// }
// bb12: {
// falseEdges -> [real: bb5, imaginary: bb6]; // from before_binding2 to binding3
// }
// bb13: {
// ...
// return;
// }
//
//
// END rustc.node17.NLL.before.mir
//
// START rustc.node36.NLL.before.mir
// bb0: {
// ...
// _2 = std::option::Option<i32>::Some(const 1i32,);
// _7 = discriminant(_2);
// switchInt(_7) -> [1isize: bb10, otherwise: bb13];
// }
// bb1: { // arm1
// _1 = const 1i32;
// goto -> bb17;
// }
// bb2: { // arm2
// _1 = const 2i32;
// goto -> bb17;
// }
// bb3: { // arm3
// _1 = const 3i32;
// goto -> bb17;
// }
// bb4: { // arm4
// _1 = const 4i32;
// goto -> bb17;
// }
// bb5: { // binding1: Some(w) if guard() =>
// ...
// _8 = const guard() -> bb11;
// }
// bb6: { // binding2: x =>
// ...
// _4 = _2;
// falseEdges -> [real: bb2, imaginary: bb7]; // after binding2 to binding3
// }
// bb7: { // binding3: Some(y) if guard2(y) =>
// ...
// _10 = const guard2(_11) -> bb14;
// }
// bb8: { // binding4: z_ =>
// ...
// _6 = _2;
// falseEdges -> [real: bb4, imaginary: bb9]; // after binding3 to unreachable
// }
// bb9: {
// unreachable;
// }
// bb10: {
// falseEdges -> [real: bb5, imaginary: bb6]; // from before_binding1 to binding2
// }
// bb11: {
// switchInt(_8) -> [0u8: bb12, otherwise: bb1]; // end of gurard
// }
// bb12: {
// falseEdges -> [real: bb13, imaginary: bb6]; // after guard to binding2
// }
// bb13: {
// falseEdges -> [real: bb6, imaginary: bb7]; // from before_binding2 to binding3
// }
// bb14: {
// ...
// switchInt(_10) -> [0u8: bb15, otherwise: bb3]; // end of guard2
// }
// bb15: {
// falseEdges -> [real: bb16, imaginary: bb8]; // after guard2 to binding4
// }
// bb16: {
// falseEdges -> [real: bb8, imaginary: bb9]; // from befor binding3 to binding4
// }
// bb17: {
// ...
// return;
// }
// END rustc.node36.NLL.before.mir
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录