Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
0957ede5
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,发现更多精彩内容 >>
未验证
提交
0957ede5
编写于
7月 01, 2018
作者:
S
Santiago Pastorino
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Make causal tracking lazy
上级
24f91e87
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
225 addition
and
319 deletion
+225
-319
src/librustc/mir/mod.rs
src/librustc/mir/mod.rs
+29
-0
src/librustc_mir/borrow_check/nll/constraint_generation.rs
src/librustc_mir/borrow_check/nll/constraint_generation.rs
+13
-13
src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs
src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs
+100
-74
src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+53
-68
src/librustc_mir/borrow_check/nll/region_infer/error_reporting.rs
...ustc_mir/borrow_check/nll/region_infer/error_reporting.rs
+6
-9
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+3
-15
src/librustc_mir/borrow_check/nll/region_infer/values.rs
src/librustc_mir/borrow_check/nll/region_infer/values.rs
+3
-81
src/librustc_mir/borrow_check/nll/type_check/liveness.rs
src/librustc_mir/borrow_check/nll/type_check/liveness.rs
+3
-7
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
+1
-3
src/test/ui/generator/borrowing.nll.stderr
src/test/ui/generator/borrowing.nll.stderr
+2
-7
src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr
...st/ui/generator/ref-escapes-but-not-over-yield.nll.stderr
+5
-13
src/test/ui/issue-47646.stderr
src/test/ui/issue-47646.stderr
+1
-7
src/test/ui/span/destructor-restrictions.nll.stderr
src/test/ui/span/destructor-restrictions.nll.stderr
+2
-7
src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr
...an/issue-23338-locals-die-before-temps-of-body.nll.stderr
+4
-15
未找到文件。
src/librustc/mir/mod.rs
浏览文件 @
0957ede5
...
...
@@ -1000,6 +1000,10 @@ pub fn successors_mut(&mut self) -> SuccessorsMut {
self
.kind
.successors_mut
()
}
pub
fn
unwind
(
&
self
)
->
Option
<&
Option
<
BasicBlock
>>
{
self
.kind
.unwind
()
}
pub
fn
unwind_mut
(
&
mut
self
)
->
Option
<&
mut
Option
<
BasicBlock
>>
{
self
.kind
.unwind_mut
()
}
...
...
@@ -1195,6 +1199,31 @@ pub fn successors_mut(&mut self) -> SuccessorsMut {
}
}
pub
fn
unwind
(
&
self
)
->
Option
<&
Option
<
BasicBlock
>>
{
match
*
self
{
TerminatorKind
::
Goto
{
..
}
|
TerminatorKind
::
Resume
|
TerminatorKind
::
Abort
|
TerminatorKind
::
Return
|
TerminatorKind
::
Unreachable
|
TerminatorKind
::
GeneratorDrop
|
TerminatorKind
::
Yield
{
..
}
|
TerminatorKind
::
SwitchInt
{
..
}
|
TerminatorKind
::
FalseEdges
{
..
}
=>
None
,
TerminatorKind
::
Call
{
cleanup
:
ref
unwind
,
..
}
|
TerminatorKind
::
Assert
{
cleanup
:
ref
unwind
,
..
}
|
TerminatorKind
::
DropAndReplace
{
ref
unwind
,
..
}
|
TerminatorKind
::
Drop
{
ref
unwind
,
..
}
|
TerminatorKind
::
FalseUnwind
{
ref
unwind
,
..
}
=>
Some
(
unwind
),
}
}
pub
fn
unwind_mut
(
&
mut
self
)
->
Option
<&
mut
Option
<
BasicBlock
>>
{
match
*
self
{
TerminatorKind
::
Goto
{
..
}
...
...
src/librustc_mir/borrow_check/nll/constraint_generation.rs
浏览文件 @
0957ede5
...
...
@@ -12,7 +12,7 @@
use
borrow_check
::
location
::
LocationTable
;
use
borrow_check
::
nll
::
ToRegionVid
;
use
borrow_check
::
nll
::
facts
::
AllFacts
;
use
borrow_check
::
nll
::
region_infer
::
{
Cause
,
RegionInferenceContext
}
;
use
borrow_check
::
nll
::
region_infer
::
RegionInferenceContext
;
use
borrow_check
::
nll
::
type_check
::
AtLocation
;
use
rustc
::
hir
;
use
rustc
::
infer
::
InferCtxt
;
...
...
@@ -33,7 +33,7 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
location_table
:
&
LocationTable
,
mir
:
&
Mir
<
'tcx
>
,
borrow_set
:
&
BorrowSet
<
'tcx
>
,
liveness_set_from_typeck
:
&
[(
ty
::
Region
<
'tcx
>
,
Location
,
Cause
)],
liveness_set_from_typeck
:
&
[(
ty
::
Region
<
'tcx
>
,
Location
)],
)
{
let
mut
cg
=
ConstraintGeneration
{
borrow_set
,
...
...
@@ -69,14 +69,14 @@ fn visit_basic_block_data(&mut self, bb: BasicBlock, data: &BasicBlockData<'tcx>
/// We sometimes have `substs` within an rvalue, or within a
/// call. Make them live at the location where they appear.
fn
visit_substs
(
&
mut
self
,
substs
:
&&
'tcx
Substs
<
'tcx
>
,
location
:
Location
)
{
self
.add_regular_live_constraint
(
*
substs
,
location
,
Cause
::
LiveOther
(
location
)
);
self
.add_regular_live_constraint
(
*
substs
,
location
);
self
.super_substs
(
substs
);
}
/// We sometimes have `region` within an rvalue, or within a
/// call. Make them live at the location where they appear.
fn
visit_region
(
&
mut
self
,
region
:
&
ty
::
Region
<
'tcx
>
,
location
:
Location
)
{
self
.add_regular_live_constraint
(
*
region
,
location
,
Cause
::
LiveOther
(
location
)
);
self
.add_regular_live_constraint
(
*
region
,
location
);
self
.super_region
(
region
);
}
...
...
@@ -94,7 +94,7 @@ fn visit_ty(&mut self, ty: &ty::Ty<'tcx>, ty_context: TyContext) {
);
}
TyContext
::
Location
(
location
)
=>
{
self
.add_regular_live_constraint
(
*
ty
,
location
,
Cause
::
LiveOther
(
location
)
);
self
.add_regular_live_constraint
(
*
ty
,
location
);
}
}
...
...
@@ -104,14 +104,14 @@ fn visit_ty(&mut self, ty: &ty::Ty<'tcx>, ty_context: TyContext) {
/// We sometimes have `generator_substs` within an rvalue, or within a
/// call. Make them live at the location where they appear.
fn
visit_generator_substs
(
&
mut
self
,
substs
:
&
GeneratorSubsts
<
'tcx
>
,
location
:
Location
)
{
self
.add_regular_live_constraint
(
*
substs
,
location
,
Cause
::
LiveOther
(
location
)
);
self
.add_regular_live_constraint
(
*
substs
,
location
);
self
.super_generator_substs
(
substs
);
}
/// We sometimes have `closure_substs` within an rvalue, or within a
/// call. Make them live at the location where they appear.
fn
visit_closure_substs
(
&
mut
self
,
substs
:
&
ClosureSubsts
<
'tcx
>
,
location
:
Location
)
{
self
.add_regular_live_constraint
(
*
substs
,
location
,
Cause
::
LiveOther
(
location
)
);
self
.add_regular_live_constraint
(
*
substs
,
location
);
self
.super_closure_substs
(
substs
);
}
...
...
@@ -233,7 +233,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
/// that we also have to respect.
fn
add_region_liveness_constraints_from_type_check
(
&
mut
self
,
liveness_set
:
&
[(
ty
::
Region
<
'tcx
>
,
Location
,
Cause
)],
liveness_set
:
&
[(
ty
::
Region
<
'tcx
>
,
Location
)],
)
{
debug!
(
"add_region_liveness_constraints_from_type_check(liveness_set={} items)"
,
...
...
@@ -247,16 +247,16 @@ fn add_region_liveness_constraints_from_type_check(
..
}
=
self
;
for
(
region
,
location
,
cause
)
in
liveness_set
{
for
(
region
,
location
)
in
liveness_set
{
debug!
(
"generate: {:#?} is live at {:#?}"
,
region
,
location
);
let
region_vid
=
regioncx
.to_region_vid
(
region
);
regioncx
.add_live_point
(
region_vid
,
*
location
,
&
cause
);
regioncx
.add_live_point
(
region_vid
,
*
location
);
}
if
let
Some
(
all_facts
)
=
all_facts
{
all_facts
.region_live_at
.extend
(
liveness_set
.into_iter
()
.flat_map
(|(
region
,
location
,
_
)|
{
.extend
(
liveness_set
.into_iter
()
.flat_map
(|(
region
,
location
)|
{
let
r
=
regioncx
.to_region_vid
(
region
);
let
p1
=
location_table
.start_index
(
*
location
);
let
p2
=
location_table
.mid_index
(
*
location
);
...
...
@@ -269,7 +269,7 @@ fn add_region_liveness_constraints_from_type_check(
/// `location` -- i.e., it may be used later. This means that all
/// regions appearing in the type `live_ty` must be live at
/// `location`.
fn
add_regular_live_constraint
<
T
>
(
&
mut
self
,
live_ty
:
T
,
location
:
Location
,
cause
:
Cause
)
fn
add_regular_live_constraint
<
T
>
(
&
mut
self
,
live_ty
:
T
,
location
:
Location
)
where
T
:
TypeFoldable
<
'tcx
>
,
{
...
...
@@ -282,7 +282,7 @@ fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location, cau
.tcx
.for_each_free_region
(
&
live_ty
,
|
live_region
|
{
let
vid
=
live_region
.to_region_vid
();
self
.regioncx
.add_live_point
(
vid
,
location
,
&
cause
);
self
.regioncx
.add_live_point
(
vid
,
location
);
});
}
...
...
src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs
浏览文件 @
0957ede5
...
...
@@ -8,50 +8,32 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
borrow_check
::
borrow_set
::
BorrowData
;
use
borrow_check
::
nll
::
region_infer
::
RegionInferenceContext
;
use
std
::
collections
::
VecDeque
;
use
std
::
rc
::
Rc
;
use
borrow_check
::
nll
::
region_infer
::{
Cause
,
RegionInferenceContext
};
use
borrow_check
::
nll
::
ToRegionVid
;
use
rustc
::
mir
::
visit
::{
MirVisitable
,
PlaceContext
,
Visitor
};
use
rustc
::
mir
::{
Local
,
Location
,
Mir
};
use
rustc
::
ty
::{
RegionVid
,
TyCtxt
};
use
rustc_data_structures
::
fx
::
FxHashSet
;
use
util
::
liveness
::{
self
,
DefUse
,
LivenessMode
};
crate
fn
regular_use
<
'gcx
,
'tcx
>
(
mir
:
&
'gcx
Mir
,
regioncx
:
&
'tcx
RegionInferenceContext
,
borrow
:
&
'tcx
BorrowData
,
crate
fn
find
<
'cx
,
'gcx
:
'tcx
,
'tcx
:
'cx
>
(
mir
:
&
'cx
Mir
<
'tcx
>
,
regioncx
:
&
'cx
Rc
<
RegionInferenceContext
<
'tcx
>>
,
tcx
:
TyCtxt
<
'cx
,
'gcx
,
'tcx
>
,
region_vid
:
RegionVid
,
start_point
:
Location
,
local
:
Local
,
)
->
Option
<
Location
>
{
)
->
Option
<
Cause
>
{
let
mut
uf
=
UseFinder
{
mir
,
regioncx
,
borrow
,
tcx
,
region_vid
,
start_point
,
local
,
liveness_mode
:
LivenessMode
{
include_regular_use
:
true
,
include_drops
:
false
,
},
};
uf
.find
()
}
crate
fn
drop_use
<
'gcx
,
'tcx
>
(
mir
:
&
'gcx
Mir
,
regioncx
:
&
'tcx
RegionInferenceContext
,
borrow
:
&
'tcx
BorrowData
,
start_point
:
Location
,
local
:
Local
,
)
->
Option
<
Location
>
{
let
mut
uf
=
UseFinder
{
mir
,
regioncx
,
borrow
,
start_point
,
local
,
liveness_mode
:
LivenessMode
{
include_regular_use
:
false
,
include_drops
:
true
,
},
};
...
...
@@ -59,23 +41,23 @@
uf
.find
()
}
struct
UseFinder
<
'gcx
,
'tcx
>
{
mir
:
&
'gcx
Mir
<
'gcx
>
,
regioncx
:
&
'tcx
RegionInferenceContext
<
'tcx
>
,
borrow
:
&
'tcx
BorrowData
<
'tcx
>
,
struct
UseFinder
<
'cx
,
'gcx
:
'tcx
,
'tcx
:
'cx
>
{
mir
:
&
'cx
Mir
<
'tcx
>
,
regioncx
:
&
'cx
Rc
<
RegionInferenceContext
<
'tcx
>>
,
tcx
:
TyCtxt
<
'cx
,
'gcx
,
'tcx
>
,
region_vid
:
RegionVid
,
start_point
:
Location
,
local
:
Local
,
liveness_mode
:
LivenessMode
,
}
impl
<
'
gcx
,
'tcx
>
UseFinder
<
'gcx
,
'tcx
>
{
fn
find
(
&
mut
self
)
->
Option
<
Location
>
{
let
mut
stack
=
vec!
[]
;
impl
<
'
cx
,
'gcx
,
'tcx
>
UseFinder
<
'cx
,
'gcx
,
'tcx
>
{
fn
find
(
&
mut
self
)
->
Option
<
Cause
>
{
let
mut
queue
=
VecDeque
::
new
()
;
let
mut
visited
=
FxHashSet
();
stack
.push
(
self
.start_point
);
while
let
Some
(
p
)
=
stack
.pop
()
{
if
!
self
.regioncx
.region_contains_point
(
self
.
borrow.region
,
p
)
{
queue
.push_back
(
self
.start_point
);
while
let
Some
(
p
)
=
queue
.pop_front
()
{
if
!
self
.regioncx
.region_contains_point
(
self
.
region_vid
,
p
)
{
continue
;
}
...
...
@@ -84,23 +66,36 @@ fn find(&mut self) -> Option<Location> {
}
let
block_data
=
&
self
.mir
[
p
.block
];
let
(
defined
,
used
)
=
self
.def_use
(
p
,
block_data
.visitable
(
p
.statement_index
));
if
used
{
return
Some
(
p
);
}
else
if
!
defined
{
if
p
.statement_index
<
block_data
.statements
.len
()
{
stack
.push
(
Location
{
statement_index
:
p
.statement_index
+
1
,
..
p
});
}
else
{
stack
.extend
(
block_data
.terminator
()
.successors
()
.map
(|
&
basic_block
|
{
Location
{
statement_index
:
0
,
block
:
basic_block
,
}
}));
match
self
.def_use
(
p
,
block_data
.visitable
(
p
.statement_index
))
{
Some
(
DefUseResult
::
Def
)
=>
{}
Some
(
DefUseResult
::
UseLive
{
local
})
=>
{
return
Some
(
Cause
::
LiveVar
(
local
,
p
));
}
Some
(
DefUseResult
::
UseDrop
{
local
})
=>
{
return
Some
(
Cause
::
DropVar
(
local
,
p
));
}
None
=>
{
if
p
.statement_index
<
block_data
.statements
.len
()
{
queue
.push_back
(
Location
{
statement_index
:
p
.statement_index
+
1
,
..
p
});
}
else
{
queue
.extend
(
block_data
.terminator
()
.successors
()
.filter
(|
&
bb
|
Some
(
&
Some
(
*
bb
))
!=
block_data
.terminator
()
.unwind
())
.map
(|
&
bb
|
Location
{
statement_index
:
0
,
block
:
bb
,
}),
);
}
}
}
}
...
...
@@ -108,34 +103,65 @@ fn find(&mut self) -> Option<Location> {
None
}
fn
def_use
(
&
self
,
location
:
Location
,
thing
:
&
dyn
MirVisitable
<
'tcx
>
)
->
(
bool
,
bool
)
{
fn
def_use
(
&
self
,
location
:
Location
,
thing
:
&
dyn
MirVisitable
<
'tcx
>
)
->
Option
<
DefUseResult
>
{
let
mut
visitor
=
DefUseVisitor
{
defined
:
false
,
used
:
false
,
local
:
self
.local
,
mir
:
self
.mir
,
tcx
:
self
.tcx
,
region_vid
:
self
.region_vid
,
liveness_mode
:
self
.liveness_mode
,
def_use_result
:
None
,
};
thing
.apply
(
location
,
&
mut
visitor
);
(
visitor
.defined
,
visitor
.used
)
visitor
.def_use_result
}
}
struct
DefUseVisitor
{
defined
:
bool
,
used
:
bool
,
local
:
Local
,
struct
DefUseVisitor
<
'cx
,
'gcx
:
'tcx
,
'tcx
:
'cx
>
{
mir
:
&
'cx
Mir
<
'tcx
>
,
tcx
:
TyCtxt
<
'cx
,
'gcx
,
'tcx
>
,
region_vid
:
RegionVid
,
liveness_mode
:
LivenessMode
,
def_use_result
:
Option
<
DefUseResult
>
,
}
enum
DefUseResult
{
Def
,
UseLive
{
local
:
Local
},
UseDrop
{
local
:
Local
},
}
impl
<
'
tcx
>
Visitor
<
'tcx
>
for
DefUseVisitor
{
impl
<
'
cx
,
'gcx
,
'tcx
>
Visitor
<
'tcx
>
for
DefUseVisitor
<
'cx
,
'gcx
,
'tcx
>
{
fn
visit_local
(
&
mut
self
,
&
local
:
&
Local
,
context
:
PlaceContext
<
'tcx
>
,
_
:
Location
)
{
if
local
==
self
.local
{
let
local_ty
=
self
.mir.local_decls
[
local
]
.ty
;
let
mut
found_it
=
false
;
self
.tcx
.for_each_free_region
(
&
local_ty
,
|
r
|
{
if
r
.to_region_vid
()
==
self
.region_vid
{
found_it
=
true
;
}
});
if
found_it
{
match
liveness
::
categorize
(
context
,
self
.liveness_mode
)
{
Some
(
DefUse
::
Def
)
=>
self
.defined
=
true
,
Some
(
DefUse
::
Use
)
=>
self
.used
=
true
,
None
=>
(),
Some
(
DefUse
::
Def
)
=>
{
self
.def_use_result
=
Some
(
DefUseResult
::
Def
);
}
Some
(
DefUse
::
Use
)
=>
{
self
.def_use_result
=
if
context
.is_drop
()
{
Some
(
DefUseResult
::
UseDrop
{
local
})
}
else
{
Some
(
DefUseResult
::
UseLive
{
local
})
};
}
None
=>
{
self
.def_use_result
=
None
;
}
}
}
}
...
...
src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
浏览文件 @
0957ede5
...
...
@@ -38,87 +38,72 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
kind_place
:
Option
<
(
WriteKind
,
&
Place
<
'tcx
>
)
>
,
err
:
&
mut
DiagnosticBuilder
<
'_
>
,
)
{
let
regioncx
=
&&
self
.nonlexical_regioncx
;
debug!
(
"explain_why_borrow_contains_point(context={:?}, borrow={:?}, kind_place={:?})"
,
context
,
borrow
,
kind_place
,
);
let
regioncx
=
&
self
.nonlexical_regioncx
;
let
mir
=
self
.mir
;
let
tcx
=
self
.tcx
;
let
borrow_region_vid
=
regioncx
.to_region_vid
(
borrow
.region
);
if
let
Some
(
cause
)
=
regioncx
.why_region_contains_point
(
borrow_region_vid
,
context
.loc
)
{
match
cause
{
Cause
::
LiveVar
(
local
,
location
)
=>
match
find_use
::
regular_use
(
mir
,
regioncx
,
borrow
,
location
,
local
,
)
{
Some
(
p
)
=>
{
err
.span_label
(
mir
.source_info
(
p
)
.span
,
format!
(
"borrow later used here"
));
}
None
=>
{
span_bug!
(
mir
.source_info
(
context
.loc
)
.span
,
"Cause should end in a LiveVar"
);
}
},
debug!
(
"explain_why_borrow_contains_point: borrow_region_vid={:?}"
,
borrow_region_vid
);
Cause
::
DropVar
(
local
,
location
)
=>
match
find_use
::
drop_use
(
mir
,
regioncx
,
borrow
,
location
,
local
,
)
{
Some
(
p
)
=>
match
&
mir
.local_decls
[
local
]
.name
{
Some
(
local_name
)
=>
{
err
.span_label
(
mir
.source_info
(
p
)
.span
,
format!
(
"borrow later used here, when `{}` is dropped"
,
local_name
),
);
let
region_sub
=
regioncx
.find_constraint
(
borrow_region_vid
,
context
.loc
);
if
let
Some
((
WriteKind
::
StorageDeadOrDrop
,
place
))
=
kind_place
{
if
let
Place
::
Local
(
borrowed_local
)
=
place
{
let
dropped_local_scope
=
mir
.local_decls
[
local
]
.visibility_scope
;
let
borrowed_local_scope
=
mir
.local_decls
[
*
borrowed_local
]
.visibility_scope
;
debug!
(
"explain_why_borrow_contains_point: region_sub={:?}"
,
region_sub
);
if
mir
.is_sub_scope
(
borrowed_local_scope
,
dropped_local_scope
)
{
err
.note
(
"values in a scope are dropped
\
in the opposite order they are defined"
,
);
}
}
}
}
None
=>
{
err
.span_label
(
mir
.local_decls
[
local
]
.source_info.span
,
"borrow may end up in a temporary, created here"
,
);
match
find_use
::
find
(
mir
,
regioncx
,
tcx
,
region_sub
,
context
.loc
)
{
Some
(
Cause
::
LiveVar
(
_
local
,
location
))
=>
{
err
.span_label
(
mir
.source_info
(
location
)
.span
,
format!
(
"borrow later used here"
),
);
}
err
.span_label
(
mir
.source_info
(
p
)
.span
,
"temporary later dropped here,
\
potentially using the reference"
,
);
}
},
Some
(
Cause
::
DropVar
(
local
,
location
))
=>
match
&
mir
.local_decls
[
local
]
.name
{
Some
(
local_name
)
=>
{
err
.span_label
(
mir
.source_info
(
location
)
.span
,
format!
(
"borrow later used here, when `{}` is dropped"
,
local_name
),
);
None
=>
{
span_bug!
(
mir
.source_info
(
context
.loc
)
.span
,
"Cause should end in a DropVar"
);
}
},
if
let
Some
((
WriteKind
::
StorageDeadOrDrop
,
place
))
=
kind_place
{
if
let
Place
::
Local
(
borrowed_local
)
=
place
{
let
dropped_local_scope
=
mir
.local_decls
[
local
]
.visibility_scope
;
let
borrowed_local_scope
=
mir
.local_decls
[
*
borrowed_local
]
.visibility_scope
;
Cause
::
UniversalRegion
(
region_vid
)
=>
{
if
let
Some
(
region
)
=
regioncx
.to_error_region
(
region_vid
)
{
self
.tcx
.note_and_explain_free_region
(
err
,
"borrowed value must be valid for "
,
region
,
"..."
,
);
if
mir
.is_sub_scope
(
borrowed_local_scope
,
dropped_local_scope
)
{
err
.note
(
"values in a scope are dropped
\
in the opposite order they are defined"
,
);
}
}
}
}
_
=>
{}
None
=>
{}
},
None
=>
{
if
let
Some
(
region
)
=
regioncx
.to_error_region
(
region_sub
)
{
self
.tcx
.note_and_explain_free_region
(
err
,
"borrowed value must be valid for "
,
region
,
"..."
,
);
}
}
}
}
...
...
src/librustc_mir/borrow_check/nll/region_infer/error_reporting.rs
浏览文件 @
0957ede5
...
...
@@ -9,7 +9,7 @@
// except according to those terms.
use
std
::
fmt
;
use
borrow_check
::
nll
::
region_infer
::{
C
ause
,
C
onstraintIndex
,
RegionInferenceContext
};
use
borrow_check
::
nll
::
region_infer
::{
ConstraintIndex
,
RegionInferenceContext
};
use
borrow_check
::
nll
::
region_infer
::
values
::
ToElementIndex
;
use
borrow_check
::
nll
::
type_check
::
Locations
;
use
rustc
::
hir
::
def_id
::
DefId
;
...
...
@@ -259,15 +259,12 @@ pub(super) fn report_error(
}
}
crate
fn
why_region_contains_point
(
&
self
,
fr1
:
RegionVid
,
elem
:
Location
)
->
Option
<
Cause
>
{
// Find some constraint `X: Y` where:
// - `fr1: X` transitively
// - and `Y` is live at `elem`
// Find some constraint `X: Y` where:
// - `fr1: X` transitively
// - and `Y` is live at `elem`
crate
fn
find_constraint
(
&
self
,
fr1
:
RegionVid
,
elem
:
Location
)
->
RegionVid
{
let
index
=
self
.blame_constraint
(
fr1
,
elem
);
let
region_sub
=
self
.constraints
[
index
]
.sub
;
// then return why `Y` was live at `elem`
self
.liveness_constraints
.cause
(
region_sub
,
elem
)
self
.constraints
[
index
]
.sub
}
/// Tries to finds a good span to blame for the fact that `fr1`
...
...
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
浏览文件 @
0957ede5
...
...
@@ -75,8 +75,6 @@ pub struct RegionInferenceContext<'tcx> {
universal_regions
:
UniversalRegions
<
'tcx
>
,
}
struct
TrackCauses
(
bool
);
struct
RegionDefinition
<
'tcx
>
{
/// Why we created this variable. Mostly these will be
/// `RegionVariableOrigin::NLL`, but some variables get created
...
...
@@ -105,13 +103,6 @@ pub(crate) enum Cause {
/// point inserted because Local was dropped at the given Location
DropVar
(
Local
,
Location
),
/// point inserted because the type was live at the given Location,
/// but not as part of some local variable
LiveOther
(
Location
),
/// part of the initial set of values for a universally quantified region
UniversalRegion
(
RegionVid
),
}
/// A "type test" corresponds to an outlives constraint between a type
...
...
@@ -283,7 +274,6 @@ fn init_universal_regions(&mut self) {
self
.liveness_constraints
.add_element
(
variable
,
point_index
,
&
Cause
::
UniversalRegion
(
variable
),
);
}
...
...
@@ -291,7 +281,6 @@ fn init_universal_regions(&mut self) {
self
.liveness_constraints
.add_element
(
variable
,
variable
,
&
Cause
::
UniversalRegion
(
variable
),
);
}
}
...
...
@@ -337,13 +326,12 @@ pub fn region_contains_point<R>(&self, r: R, p: Location) -> bool
///
/// Returns `true` if this constraint is new and `false` is the
/// constraint was already present.
pub
(
super
)
fn
add_live_point
(
&
mut
self
,
v
:
RegionVid
,
point
:
Location
,
cause
:
&
Cause
)
->
bool
{
pub
(
super
)
fn
add_live_point
(
&
mut
self
,
v
:
RegionVid
,
point
:
Location
)
->
bool
{
debug!
(
"add_live_point({:?}, {:?})"
,
v
,
point
);
assert
!
(
self
.inferred_values
.is_none
(),
"values already inferred"
);
debug!
(
"add_live_point: @{:?} Adding cause {:?}"
,
point
,
cause
);
let
element
=
self
.elements
.index
(
point
);
self
.liveness_constraints
.add_element
(
v
,
element
,
&
cause
)
self
.liveness_constraints
.add_element
(
v
,
element
)
}
/// Indicates that the region variable `sup` must outlive `sub` is live at the point `point`.
...
...
@@ -436,7 +424,7 @@ fn compute_region_values(&self, _mir: &Mir<'tcx>) -> RegionValues {
// The initial values for each region are derived from the liveness
// constraints we have accumulated.
let
mut
inferred_values
=
self
.liveness_constraints
.
duplicate
(
TrackCauses
(
false
)
);
let
mut
inferred_values
=
self
.liveness_constraints
.
clone
(
);
let
dependency_map
=
self
.dependency_map
.as_ref
()
.unwrap
();
...
...
src/librustc_mir/borrow_check/nll/region_infer/values.rs
浏览文件 @
0957ede5
...
...
@@ -8,18 +8,14 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
borrow_check
::
nll
::
region_infer
::
TrackCauses
;
use
rustc
::
mir
::{
BasicBlock
,
Location
,
Mir
};
use
rustc
::
ty
::
RegionVid
;
use
rustc_data_structures
::
bitvec
::
SparseBitMatrix
;
use
rustc_data_structures
::
fx
::
FxHashMap
;
use
rustc_data_structures
::
indexed_vec
::
Idx
;
use
rustc_data_structures
::
indexed_vec
::
IndexVec
;
use
std
::
fmt
::
Debug
;
use
std
::
rc
::
Rc
;
use
super
::
Cause
;
/// Maps between the various kinds of elements of a region value to
/// the internal indices that w use.
pub
(
super
)
struct
RegionValueElements
{
...
...
@@ -180,19 +176,12 @@ fn to_element_index(self, _elements: &RegionValueElements) -> RegionElementIndex
/// compact `SparseBitMatrix` representation, with one row per region
/// variable. The columns consist of either universal regions or
/// points in the CFG.
#[derive(Clone)]
pub
(
super
)
struct
RegionValues
{
elements
:
Rc
<
RegionValueElements
>
,
matrix
:
SparseBitMatrix
<
RegionVid
,
RegionElementIndex
>
,
/// If cause tracking is enabled, maps from a pair (r, e)
/// consisting of a region `r` that contains some element `e` to
/// the reason that the element is contained. There should be an
/// entry for every bit set to 1 in `SparseBitMatrix`.
causes
:
Option
<
CauseMap
>
,
}
type
CauseMap
=
FxHashMap
<
(
RegionVid
,
RegionElementIndex
),
Cause
>
;
impl
RegionValues
{
/// Creates a new set of "region values" that tracks causal information.
/// Each of the regions in num_region_variables will be initialized with an
...
...
@@ -209,25 +198,6 @@ pub(super) fn new(elements: &Rc<RegionValueElements>, num_region_variables: usiz
RegionVid
::
new
(
num_region_variables
),
RegionElementIndex
::
new
(
elements
.num_elements
()),
),
causes
:
Some
(
CauseMap
::
default
()),
}
}
/// Duplicates the region values. If track_causes is false, then the
/// resulting value will not track causal information (and any existing
/// causal information is dropped). Otherwise, the causal information is
/// preserved and maintained. Tracking the causal information makes region
/// propagation significantly slower, so we prefer not to do it until an
/// error is reported.
pub
(
super
)
fn
duplicate
(
&
self
,
track_causes
:
TrackCauses
)
->
Self
{
Self
{
elements
:
self
.elements
.clone
(),
matrix
:
self
.matrix
.clone
(),
causes
:
if
track_causes
.0
{
self
.causes
.clone
()
}
else
{
None
},
}
}
...
...
@@ -237,10 +207,10 @@ pub(super) fn add_element<E: ToElementIndex>(
&
mut
self
,
r
:
RegionVid
,
elem
:
E
,
cause
:
&
Cause
,
)
->
bool
{
let
i
=
self
.elements
.index
(
elem
);
self
.add_internal
(
r
,
i
,
|
_
|
cause
.clone
())
debug!
(
"add(r={:?}, elem={:?})"
,
r
,
elem
);
self
.matrix
.add
(
r
,
i
)
}
/// Add all elements in `r_from` to `r_to` (because e.g. `r_to:
...
...
@@ -249,40 +219,6 @@ pub(super) fn add_region(&mut self, r_to: RegionVid, r_from: RegionVid) -> bool
self
.matrix
.merge
(
r_from
,
r_to
)
}
/// Internal method to add an element to a region.
///
/// Takes a "lazy" cause -- this function will return the cause, but it will only
/// be invoked if cause tracking is enabled.
fn
add_internal
<
F
>
(
&
mut
self
,
r
:
RegionVid
,
i
:
RegionElementIndex
,
make_cause
:
F
)
->
bool
where
F
:
FnOnce
(
&
CauseMap
)
->
Cause
,
{
if
self
.matrix
.add
(
r
,
i
)
{
debug!
(
"add(r={:?}, i={:?})"
,
r
,
self
.elements
.to_element
(
i
));
if
let
Some
(
causes
)
=
&
mut
self
.causes
{
let
cause
=
make_cause
(
causes
);
causes
.insert
((
r
,
i
),
cause
);
}
true
}
else
{
if
let
Some
(
causes
)
=
&
mut
self
.causes
{
let
cause
=
make_cause
(
causes
);
let
old_cause
=
causes
.get_mut
(
&
(
r
,
i
))
.unwrap
();
// #49998: compare using root cause alone to avoid
// useless traffic from similar outlives chains.
if
cause
<
*
old_cause
{
*
old_cause
=
cause
;
return
true
;
}
}
false
}
}
/// True if the region `r` contains the given element.
pub
(
super
)
fn
contains
<
E
:
ToElementIndex
>
(
&
self
,
r
:
RegionVid
,
elem
:
E
)
->
bool
{
let
i
=
self
.elements
.index
(
elem
);
...
...
@@ -398,18 +334,4 @@ fn push_location_range(str: &mut String, location1: Location, location2: Locatio
));
}
}
/// Given a region `r` that contains the element `elem`, returns the `Cause`
/// that tells us *why* `elem` is found in that region.
///
/// Returns None if cause tracking is disabled or `elem` is not
/// actually found in `r`.
pub
(
super
)
fn
cause
<
T
:
ToElementIndex
>
(
&
self
,
r
:
RegionVid
,
elem
:
T
)
->
Option
<
Cause
>
{
let
index
=
self
.elements
.index
(
elem
);
if
let
Some
(
causes
)
=
&
self
.causes
{
causes
.get
(
&
(
r
,
index
))
.cloned
()
}
else
{
None
}
}
}
src/librustc_mir/borrow_check/nll/type_check/liveness.rs
浏览文件 @
0957ede5
...
...
@@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
borrow_check
::
nll
::
region_infer
::
Cause
;
use
borrow_check
::
nll
::
type_check
::
AtLocation
;
use
dataflow
::
move_paths
::{
HasMoveData
,
MoveData
};
use
dataflow
::
MaybeInitializedPlaces
;
...
...
@@ -88,8 +87,7 @@ fn add_liveness_constraints(&mut self, bb: BasicBlock) {
.simulate_block
(
self
.mir
,
bb
,
|
location
,
live_locals
|
{
for
live_local
in
live_locals
.iter
()
{
let
live_local_ty
=
self
.mir.local_decls
[
live_local
]
.ty
;
let
cause
=
Cause
::
LiveVar
(
live_local
,
location
);
Self
::
push_type_live_constraint
(
&
mut
self
.cx
,
live_local_ty
,
location
,
cause
);
Self
::
push_type_live_constraint
(
&
mut
self
.cx
,
live_local_ty
,
location
);
}
});
...
...
@@ -161,7 +159,6 @@ fn push_type_live_constraint<T>(
cx
:
&
mut
TypeChecker
<
'_
,
'gcx
,
'tcx
>
,
value
:
T
,
location
:
Location
,
cause
:
Cause
,
)
where
T
:
TypeFoldable
<
'tcx
>
,
{
...
...
@@ -173,7 +170,7 @@ fn push_type_live_constraint<T>(
cx
.tcx
()
.for_each_free_region
(
&
value
,
|
live_region
|
{
cx
.constraints
.liveness_set
.push
((
live_region
,
location
,
cause
.clone
()
));
.push
((
live_region
,
location
));
});
}
...
...
@@ -210,9 +207,8 @@ fn add_drop_live_constraint(
// All things in the `outlives` array may be touched by
// the destructor and must be live at this point.
let
cause
=
Cause
::
DropVar
(
dropped_local
,
location
);
for
&
kind
in
&
drop_data
.dropck_result.kinds
{
Self
::
push_type_live_constraint
(
&
mut
self
.cx
,
kind
,
location
,
cause
);
Self
::
push_type_live_constraint
(
&
mut
self
.cx
,
kind
,
location
);
}
}
...
...
src/librustc_mir/borrow_check/nll/type_check/mod.rs
浏览文件 @
0957ede5
...
...
@@ -14,7 +14,6 @@
use
borrow_check
::
location
::
LocationTable
;
use
borrow_check
::
nll
::
constraint_set
::
ConstraintSet
;
use
borrow_check
::
nll
::
facts
::
AllFacts
;
use
borrow_check
::
nll
::
region_infer
::
Cause
;
use
borrow_check
::
nll
::
region_infer
::{
ClosureRegionRequirementsExt
,
TypeTest
};
use
borrow_check
::
nll
::
universal_regions
::
UniversalRegions
;
use
dataflow
::
move_paths
::
MoveData
;
...
...
@@ -615,7 +614,7 @@ struct BorrowCheckContext<'a, 'tcx: 'a> {
/// not otherwise appear in the MIR -- in particular, the
/// late-bound regions that it instantiates at call-sites -- and
/// hence it must report on their liveness constraints.
crate
liveness_set
:
Vec
<
(
ty
::
Region
<
'tcx
>
,
Location
,
Cause
)
>
,
crate
liveness_set
:
Vec
<
(
ty
::
Region
<
'tcx
>
,
Location
)
>
,
crate
outlives_constraints
:
ConstraintSet
,
...
...
@@ -986,7 +985,6 @@ fn check_terminator(
self
.constraints.liveness_set
.push
((
late_bound_region
,
term_location
,
Cause
::
LiveOther
(
term_location
),
));
}
...
...
src/test/ui/generator/borrowing.nll.stderr
浏览文件 @
0957ede5
...
...
@@ -2,15 +2,10 @@ error[E0597]: `a` does not live long enough
--> $DIR/borrowing.rs:18:18
|
LL | unsafe { (|| yield &a).resume() }
| ^^^^^^^^^^^^^
| |
| borrowed value does not live long enough
| borrow may end up in a temporary, created here
| ^^^^^^^^^^^^^ borrowed value does not live long enough
LL | //~^ ERROR: `a` does not live long enough
LL | };
| -- temporary later dropped here, potentially using the reference
| |
| borrowed value only lives until here
| - borrowed value only lives until here
error[E0597]: `a` does not live long enough
--> $DIR/borrowing.rs:24:9
...
...
src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr
浏览文件 @
0957ede5
error[E0597]: `b` does not live long enough
--> $DIR/ref-escapes-but-not-over-yield.rs:24:13
|
LL | let mut b = move || {
| _________________-
LL | | yield();
LL | | let b = 5;
LL | | a = &b;
| | ^^ borrowed value does not live long enough
LL | | //~^ ERROR `b` does not live long enough
LL | | };
| | -
| | |
| | borrowed value only lives until here
| |_____temporary later dropped here, potentially using the reference
| borrow may end up in a temporary, created here
LL | a = &b;
| ^^ borrowed value does not live long enough
LL | //~^ ERROR `b` does not live long enough
LL | };
| - borrowed value only lives until here
error: aborting due to previous error
...
...
src/test/ui/issue-47646.stderr
浏览文件 @
0957ede5
...
...
@@ -3,15 +3,9 @@ error[E0502]: cannot borrow `heap` as immutable because it is also borrowed as m
|
LL | let borrow = heap.peek_mut();
| ---- mutable borrow occurs here
LL |
LL | match (borrow, ()) {
| ------------ borrow may end up in a temporary, created here
LL | (Some(_), ()) => {
...
LL | println!("{:?}", heap); //~ ERROR cannot borrow `heap` as immutable
| ^^^^ immutable borrow occurs here
...
LL | };
| - temporary later dropped here, potentially using the reference
error: aborting due to previous error
...
...
src/test/ui/span/destructor-restrictions.nll.stderr
浏览文件 @
0957ede5
...
...
@@ -2,14 +2,9 @@ error[E0597]: `*a` does not live long enough
--> $DIR/destructor-restrictions.rs:18:10
|
LL | *a.borrow() + 1
| ^---------
| |
| borrowed value does not live long enough
| borrow may end up in a temporary, created here
| ^ borrowed value does not live long enough
LL | }; //~^ ERROR `*a` does not live long enough
| -- temporary later dropped here, potentially using the reference
| |
| borrowed value only lives until here
| - borrowed value only lives until here
error: aborting due to previous error
...
...
src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr
浏览文件 @
0957ede5
...
...
@@ -2,28 +2,17 @@ error[E0597]: `y` does not live long enough
--> $DIR/issue-23338-locals-die-before-temps-of-body.rs:20:5
|
LL | y.borrow().clone()
| ^---------
| |
| borrowed value does not live long enough
| borrow may end up in a temporary, created here
| ^ borrowed value does not live long enough
LL | }
| -
| |
| borrowed value only lives until here
| temporary later dropped here, potentially using the reference
| - borrowed value only lives until here
error[E0597]: `y` does not live long enough
--> $DIR/issue-23338-locals-die-before-temps-of-body.rs:27:9
|
LL | y.borrow().clone()
| ^---------
| |
| borrowed value does not live long enough
| borrow may end up in a temporary, created here
| ^ borrowed value does not live long enough
LL | };
| -- temporary later dropped here, potentially using the reference
| |
| borrowed value only lives until here
| - borrowed value only lives until here
error: aborting due to 2 previous errors
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录