Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
5175bc18
R
Rust
项目概览
int
/
Rust
12 个月 前同步成功
通知
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,发现更多精彩内容 >>
提交
5175bc18
编写于
6月 08, 2017
作者:
E
Eduard-Mihai Burtescu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rustc_typeck: do not mutate tables directly during upvar inference.
上级
8b1b05bc
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
107 addition
and
219 deletion
+107
-219
src/librustc/infer/mod.rs
src/librustc/infer/mod.rs
+0
-4
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/expr_use_visitor.rs
+4
-18
src/librustc/middle/mem_categorization.rs
src/librustc/middle/mem_categorization.rs
+10
-59
src/librustc/ty/context.rs
src/librustc/ty/context.rs
+2
-2
src/librustc_mir/build/mod.rs
src/librustc_mir/build/mod.rs
+4
-3
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/expr.rs
+2
-8
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/regionck.rs
+3
-4
src/librustc_typeck/check/upvar.rs
src/librustc_typeck/check/upvar.rs
+82
-121
未找到文件。
src/librustc/infer/mod.rs
浏览文件 @
5175bc18
...
...
@@ -1521,10 +1521,6 @@ pub fn type_moves_by_default(&self,
!
traits
::
type_known_to_meet_bound
(
self
,
param_env
,
ty
,
copy_def_id
,
span
)
}
pub
fn
upvar_capture
(
&
self
,
upvar_id
:
ty
::
UpvarId
)
->
Option
<
ty
::
UpvarCapture
<
'tcx
>>
{
self
.tables
.borrow
()
.upvar_capture_map
.get
(
&
upvar_id
)
.cloned
()
}
pub
fn
closure_kind
(
&
self
,
def_id
:
DefId
)
->
Option
<
ty
::
ClosureKind
>
...
...
src/librustc/middle/expr_use_visitor.rs
浏览文件 @
5175bc18
...
...
@@ -270,23 +270,9 @@ pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
infcx
:
&
'a
InferCtxt
<
'a
,
'gcx
,
'tcx
>
,
param_env
:
ty
::
ParamEnv
<
'tcx
>
)
->
Self
{
ExprUseVisitor
::
with_options
(
delegate
,
infcx
,
param_env
,
region_maps
,
mc
::
MemCategorizationOptions
::
default
())
}
pub
fn
with_options
(
delegate
:
&
'a
mut
(
Delegate
<
'tcx
>+
'a
),
infcx
:
&
'a
InferCtxt
<
'a
,
'gcx
,
'tcx
>
,
param_env
:
ty
::
ParamEnv
<
'tcx
>
,
region_maps
:
&
'a
RegionMaps
,
options
:
mc
::
MemCategorizationOptions
)
->
Self
{
ExprUseVisitor
{
mc
:
mc
::
MemCategorizationContext
::
with_options
(
infcx
,
region_maps
,
option
s
),
mc
:
mc
::
MemCategorizationContext
::
new
(
infcx
,
region_map
s
),
delegate
,
param_env
,
}
...
...
@@ -678,8 +664,8 @@ fn contains_field_named(field: &ty::FieldDef,
// consumed or borrowed as part of the automatic adjustment
// process.
fn
walk_adjustment
(
&
mut
self
,
expr
:
&
hir
::
Expr
)
{
//NOTE(@jroesch): mixed RefCell borrow causes crash
let
adjustments
=
self
.mc.infcx.tables
.borrow
()
.expr_adjustments
(
expr
)
.to_vec
(
);
let
tables
=
self
.mc.infcx.tables
.borrow
();
let
adjustments
=
tables
.expr_adjustments
(
expr
);
let
mut
cmt
=
return_if_err!
(
self
.mc
.cat_expr_unadjusted
(
expr
));
for
adjustment
in
adjustments
{
debug!
(
"walk_adjustment expr={:?} adj={:?}"
,
expr
,
adjustment
);
...
...
@@ -896,7 +882,7 @@ fn walk_captures(&mut self, closure_expr: &hir::Expr, fn_decl_span: Span) {
let
id_var
=
self
.tcx
()
.hir
.as_local_node_id
(
def_id
)
.unwrap
();
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
id_var
,
closure_expr_id
:
closure_expr
.id
};
let
upvar_capture
=
self
.mc.infcx
.
upvar_capture
(
upvar_id
)
.unwrap
(
);
let
upvar_capture
=
self
.mc.infcx.
tables
.borrow
()
.upvar_capture
(
upvar_id
);
let
cmt_var
=
return_if_err!
(
self
.cat_captured_var
(
closure_expr
.id
,
fn_decl_span
,
freevar
.def
));
...
...
src/librustc/middle/mem_categorization.rs
浏览文件 @
5175bc18
...
...
@@ -283,18 +283,6 @@ fn span(&self) -> Span { self.span }
pub
struct
MemCategorizationContext
<
'a
,
'gcx
:
'a
+
'tcx
,
'tcx
:
'a
>
{
pub
infcx
:
&
'a
InferCtxt
<
'a
,
'gcx
,
'tcx
>
,
pub
region_maps
:
&
'a
RegionMaps
,
options
:
MemCategorizationOptions
,
}
#[derive(Copy,
Clone,
Default)]
pub
struct
MemCategorizationOptions
{
// If true, then when analyzing a closure upvar, if the closure
// has a missing kind, we treat it like a Fn closure. When false,
// we ICE if the closure has a missing kind. Should be false
// except during closure kind inference. It is used by the
// mem-categorization code to be able to have stricter assertions
// (which are always true except during upvar inference).
pub
during_closure_kind_inference
:
bool
,
}
pub
type
McResult
<
T
>
=
Result
<
T
,
()
>
;
...
...
@@ -400,20 +388,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
pub
fn
new
(
infcx
:
&
'a
InferCtxt
<
'a
,
'gcx
,
'tcx
>
,
region_maps
:
&
'a
RegionMaps
)
->
MemCategorizationContext
<
'a
,
'gcx
,
'tcx
>
{
MemCategorizationContext
::
with_options
(
infcx
,
region_maps
,
MemCategorizationOptions
::
default
())
}
pub
fn
with_options
(
infcx
:
&
'a
InferCtxt
<
'a
,
'gcx
,
'tcx
>
,
region_maps
:
&
'a
RegionMaps
,
options
:
MemCategorizationOptions
)
->
MemCategorizationContext
<
'a
,
'gcx
,
'tcx
>
{
MemCategorizationContext
{
infcx
:
infcx
,
region_maps
:
region_maps
,
options
:
options
,
}
MemCategorizationContext
{
infcx
,
region_maps
}
}
fn
tcx
(
&
self
)
->
TyCtxt
<
'a
,
'gcx
,
'tcx
>
{
...
...
@@ -620,38 +595,14 @@ pub fn cat_def(&self,
Def
::
Upvar
(
def_id
,
_
,
fn_node_id
)
=>
{
let
var_id
=
self
.tcx
()
.hir
.as_local_node_id
(
def_id
)
.unwrap
();
let
ty
=
self
.node_ty
(
fn_node_id
)
?
;
match
ty
.sty
{
ty
::
TyClosure
(
closure_id
,
_
)
=>
{
match
self
.infcx
.closure_kind
(
closure_id
)
{
Some
(
kind
)
=>
{
self
.cat_upvar
(
id
,
span
,
var_id
,
fn_node_id
,
kind
)
}
None
=>
{
if
!
self
.options.during_closure_kind_inference
{
span_bug!
(
span
,
"No closure kind for {:?}"
,
closure_id
);
}
// during closure kind inference, we
// don't know the closure kind yet, but
// it's ok because we detect that we are
// accessing an upvar and handle that
// case specially anyhow. Use Fn
// arbitrarily.
self
.cat_upvar
(
id
,
span
,
var_id
,
fn_node_id
,
ty
::
ClosureKind
::
Fn
)
}
}
}
_
=>
{
span_bug!
(
span
,
"Upvar of non-closure {} - {:?}"
,
fn_node_id
,
ty
);
}
let
closure_id
=
self
.tcx
()
.hir
.local_def_id
(
fn_node_id
);
match
self
.infcx
.closure_kind
(
closure_id
)
{
Some
(
kind
)
=>
{
self
.cat_upvar
(
id
,
span
,
var_id
,
fn_node_id
,
kind
)
}
None
=>
{
span_bug!
(
span
,
"No closure kind for {:?}"
,
closure_id
);
}
}
}
...
...
@@ -743,7 +694,7 @@ fn cat_upvar(&self,
// for that.
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
var_id
,
closure_expr_id
:
fn_node_id
};
let
upvar_capture
=
self
.infcx
.
upvar_capture
(
upvar_id
)
.unwrap
(
);
let
upvar_capture
=
self
.infcx.
tables
.borrow
()
.upvar_capture
(
upvar_id
);
let
cmt_result
=
match
upvar_capture
{
ty
::
UpvarCapture
::
ByValue
=>
{
cmt_result
...
...
src/librustc/ty/context.rs
浏览文件 @
5175bc18
...
...
@@ -376,8 +376,8 @@ pub fn is_method_call(&self, expr: &hir::Expr) -> bool {
}
}
pub
fn
upvar_capture
(
&
self
,
upvar_id
:
ty
::
UpvarId
)
->
Option
<
ty
::
UpvarCapture
<
'tcx
>
>
{
Some
(
self
.upvar_capture_map
.get
(
&
upvar_id
)
.unwrap
()
.clone
())
pub
fn
upvar_capture
(
&
self
,
upvar_id
:
ty
::
UpvarId
)
->
ty
::
UpvarCapture
<
'tcx
>
{
self
.upvar_capture_map
[
&
upvar_id
]
}
}
...
...
src/librustc_mir/build/mod.rs
浏览文件 @
5175bc18
...
...
@@ -365,13 +365,14 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
let
upvar_decls
:
Vec
<
_
>
=
tcx
.with_freevars
(
fn_id
,
|
freevars
|
{
freevars
.iter
()
.map
(|
fv
|
{
let
var_id
=
tcx
.hir
.as_local_node_id
(
fv
.def
.def_id
())
.unwrap
();
let
by_ref
=
hir
.tables
()
.upvar_capture
(
ty
::
UpvarId
{
let
capture
=
hir
.tables
()
.upvar_capture
(
ty
::
UpvarId
{
var_id
:
var_id
,
closure_expr_id
:
fn_id
})
.map_or
(
false
,
|
capture
|
match
capture
{
});
let
by_ref
=
match
capture
{
ty
::
UpvarCapture
::
ByValue
=>
false
,
ty
::
UpvarCapture
::
ByRef
(
..
)
=>
true
}
)
;
};
let
mut
decl
=
UpvarDecl
{
debug_name
:
keywords
::
Invalid
.name
(),
by_ref
:
by_ref
...
...
src/librustc_mir/hair/cx/expr.rs
浏览文件 @
5175bc18
...
...
@@ -758,13 +758,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
var_id
:
id_var
,
closure_expr_id
:
closure_expr_id
,
};
let
upvar_capture
=
match
cx
.tables
()
.upvar_capture
(
upvar_id
)
{
Some
(
c
)
=>
c
,
None
=>
{
span_bug!
(
expr
.span
,
"no upvar_capture for {:?}"
,
upvar_id
);
}
};
match
upvar_capture
{
match
cx
.tables
()
.upvar_capture
(
upvar_id
)
{
ty
::
UpvarCapture
::
ByValue
=>
field_kind
,
ty
::
UpvarCapture
::
ByRef
(
borrow
)
=>
{
ExprKind
::
Deref
{
...
...
@@ -878,7 +872,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
var_id
:
id_var
,
closure_expr_id
:
closure_expr
.id
,
};
let
upvar_capture
=
cx
.tables
()
.upvar_capture
(
upvar_id
)
.unwrap
()
;
let
upvar_capture
=
cx
.tables
()
.upvar_capture
(
upvar_id
);
let
temp_lifetime
=
cx
.region_maps
.temporary_scope
(
closure_expr
.id
);
let
var_ty
=
cx
.tables
()
.node_id_to_type
(
id_var
);
let
captured_var
=
Expr
{
...
...
src/librustc_typeck/check/regionck.rs
浏览文件 @
5175bc18
...
...
@@ -834,8 +834,8 @@ fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult<mc::cmt<'t
mc
.cat_expr_unadjusted
(
expr
)
?
};
//NOTE(@jroesch): mixed RefCell borrow causes crash
let
adjustments
=
self
.tables
.borrow
()
.expr_adjustments
(
&
expr
)
.to_vec
(
);
let
tables
=
self
.tables
.borrow
();
let
adjustments
=
tables
.expr_adjustments
(
&
expr
);
if
adjustments
.is_empty
()
{
return
Ok
(
cmt
);
}
...
...
@@ -1215,8 +1215,7 @@ fn link_reborrowed_region(&self,
// Detect by-ref upvar `x`:
let
cause
=
match
note
{
mc
::
NoteUpvarRef
(
ref
upvar_id
)
=>
{
let
upvar_capture_map
=
&
self
.tables
.borrow_mut
()
.upvar_capture_map
;
match
upvar_capture_map
.get
(
upvar_id
)
{
match
self
.tables
.borrow
()
.upvar_capture_map
.get
(
upvar_id
)
{
Some
(
&
ty
::
UpvarCapture
::
ByRef
(
ref
upvar_borrow
))
=>
{
// The mutability of the upvar may have been modified
// by the above adjustment, so update our local variable.
...
...
src/librustc_typeck/check/upvar.rs
浏览文件 @
5175bc18
...
...
@@ -53,31 +53,22 @@
use
rustc
::
hir
::
intravisit
::{
self
,
Visitor
,
NestedVisitorMap
};
use
rustc
::
util
::
nodemap
::
NodeMap
;
///////////////////////////////////////////////////////////////////////////
// PUBLIC ENTRY POINTS
use
std
::
collections
::
hash_map
::
Entry
;
impl
<
'a
,
'gcx
,
'tcx
>
FnCtxt
<
'a
,
'gcx
,
'tcx
>
{
pub
fn
closure_analyze
(
&
self
,
body
:
&
'gcx
hir
::
Body
)
{
let
mut
seed
=
SeedBorrowKind
::
new
(
self
);
seed
.visit_body
(
body
);
let
mut
adjust
=
AdjustBorrowKind
::
new
(
self
,
seed
.temp_closure_kinds
);
adjust
.visit_body
(
body
);
InferBorrowKindVisitor
{
fcx
:
self
}
.visit_body
(
body
);
// it's our job to process these.
assert
!
(
self
.deferred_call_resolutions
.borrow
()
.is_empty
());
}
}
///////////////////////////////////////////////////////////////////////////
// SEED BORROW KIND
struct
SeedBorrowKind
<
'a
,
'gcx
:
'a
+
'tcx
,
'tcx
:
'a
>
{
struct
InferBorrowKindVisitor
<
'a
,
'gcx
:
'a
+
'tcx
,
'tcx
:
'a
>
{
fcx
:
&
'a
FnCtxt
<
'a
,
'gcx
,
'tcx
>
,
temp_closure_kinds
:
NodeMap
<
(
ty
::
ClosureKind
,
Option
<
(
Span
,
ast
::
Name
)
>
)
>
,
}
impl
<
'a
,
'gcx
,
'tcx
>
Visitor
<
'gcx
>
for
SeedBorrowKind
<
'a
,
'gcx
,
'tcx
>
{
impl
<
'a
,
'gcx
,
'tcx
>
Visitor
<
'gcx
>
for
InferBorrowKindVisitor
<
'a
,
'gcx
,
'tcx
>
{
fn
nested_visit_map
<
'this
>
(
&
'this
mut
self
)
->
NestedVisitorMap
<
'this
,
'gcx
>
{
NestedVisitorMap
::
None
}
...
...
@@ -87,7 +78,7 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
hir
::
ExprClosure
(
cc
,
_
,
body_id
,
_
)
=>
{
let
body
=
self
.fcx.tcx.hir
.body
(
body_id
);
self
.visit_body
(
body
);
self
.
check_closure
(
expr
,
cc
);
self
.
fcx
.analyze_closure
(
expr
.id
,
expr
.span
,
body
,
cc
);
}
_
=>
{
}
...
...
@@ -97,26 +88,33 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
}
}
impl
<
'a
,
'gcx
,
'tcx
>
SeedBorrowKind
<
'a
,
'gcx
,
'tcx
>
{
fn
new
(
fcx
:
&
'a
FnCtxt
<
'a
,
'gcx
,
'tcx
>
)
->
SeedBorrowKind
<
'a
,
'gcx
,
'tcx
>
{
SeedBorrowKind
{
fcx
:
fcx
,
temp_closure_kinds
:
NodeMap
()
}
}
impl
<
'a
,
'gcx
,
'tcx
>
FnCtxt
<
'a
,
'gcx
,
'tcx
>
{
fn
analyze_closure
(
&
self
,
id
:
ast
::
NodeId
,
span
:
Span
,
body
:
&
hir
::
Body
,
capture_clause
:
hir
::
CaptureClause
)
{
/*!
* Analysis starting point.
*/
fn
check_closure
(
&
mut
self
,
expr
:
&
hir
::
Expr
,
capture_clause
:
hir
::
CaptureClause
)
{
if
!
self
.fcx.tables
.borrow
()
.closure_kinds
.contains_key
(
&
expr
.id
)
{
self
.temp_closure_kinds
.insert
(
expr
.id
,
(
ty
::
ClosureKind
::
Fn
,
None
));
debug!
(
"check_closure: adding closure {:?} as Fn"
,
expr
.id
);
}
debug!
(
"analyze_closure(id={:?}, body.id={:?})"
,
id
,
body
.id
());
self
.fcx.tcx
.with_freevars
(
expr
.id
,
|
freevars
|
{
let
infer_kind
=
match
self
.tables
.borrow_mut
()
.closure_kinds
.entry
(
id
)
{
Entry
::
Occupied
(
_
)
=>
false
,
Entry
::
Vacant
(
entry
)
=>
{
debug!
(
"check_closure: adding closure {:?} as Fn"
,
id
);
entry
.insert
((
ty
::
ClosureKind
::
Fn
,
None
));
true
}
};
self
.tcx
.with_freevars
(
id
,
|
freevars
|
{
for
freevar
in
freevars
{
let
def_id
=
freevar
.def
.def_id
();
let
var_node_id
=
self
.
fcx.
tcx.hir
.as_local_node_id
(
def_id
)
.unwrap
();
let
var_node_id
=
self
.tcx.hir
.as_local_node_id
(
def_id
)
.unwrap
();
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
var_node_id
,
closure_expr_id
:
expr
.
id
};
closure_expr_id
:
id
};
debug!
(
"seed upvar_id {:?}"
,
upvar_id
);
let
capture_kind
=
match
capture_clause
{
...
...
@@ -124,58 +122,37 @@ fn check_closure(&mut self,
ty
::
UpvarCapture
::
ByValue
}
hir
::
CaptureByRef
=>
{
let
origin
=
UpvarRegion
(
upvar_id
,
expr
.
span
);
let
freevar_region
=
self
.
fcx
.
next_region_var
(
origin
);
let
origin
=
UpvarRegion
(
upvar_id
,
span
);
let
freevar_region
=
self
.next_region_var
(
origin
);
let
upvar_borrow
=
ty
::
UpvarBorrow
{
kind
:
ty
::
ImmBorrow
,
region
:
freevar_region
};
ty
::
UpvarCapture
::
ByRef
(
upvar_borrow
)
}
};
self
.
fcx.
tables
.borrow_mut
()
.upvar_capture_map
.insert
(
upvar_id
,
capture_kind
);
self
.tables
.borrow_mut
()
.upvar_capture_map
.insert
(
upvar_id
,
capture_kind
);
}
});
}
}
///////////////////////////////////////////////////////////////////////////
// ADJUST BORROW KIND
struct
AdjustBorrowKind
<
'a
,
'gcx
:
'a
+
'tcx
,
'tcx
:
'a
>
{
fcx
:
&
'a
FnCtxt
<
'a
,
'gcx
,
'tcx
>
,
temp_closure_kinds
:
NodeMap
<
(
ty
::
ClosureKind
,
Option
<
(
Span
,
ast
::
Name
)
>
)
>
,
}
impl
<
'a
,
'gcx
,
'tcx
>
AdjustBorrowKind
<
'a
,
'gcx
,
'tcx
>
{
fn
new
(
fcx
:
&
'a
FnCtxt
<
'a
,
'gcx
,
'tcx
>
,
temp_closure_kinds
:
NodeMap
<
(
ty
::
ClosureKind
,
Option
<
(
Span
,
ast
::
Name
)
>
)
>
)
->
AdjustBorrowKind
<
'a
,
'gcx
,
'tcx
>
{
AdjustBorrowKind
{
fcx
:
fcx
,
temp_closure_kinds
:
temp_closure_kinds
}
}
fn
analyze_closure
(
&
mut
self
,
id
:
ast
::
NodeId
,
span
:
Span
,
body
:
&
hir
::
Body
)
{
/*!
* Analysis starting point.
*/
debug!
(
"analyze_closure(id={:?}, body.id={:?})"
,
id
,
body
.id
());
{
let
body_owner_def_id
=
self
.fcx.tcx.hir
.body_owner_def_id
(
body
.id
());
let
region_maps
=
&
self
.fcx.tcx
.region_maps
(
body_owner_def_id
);
let
param_env
=
self
.fcx.param_env
;
let
mut
euv
=
euv
::
ExprUseVisitor
::
with_options
(
self
,
self
.fcx
,
param_env
,
region_maps
,
mc
::
MemCategorizationOptions
{
during_closure_kind_inference
:
true
});
euv
.consume_body
(
body
);
let
body_owner_def_id
=
self
.tcx.hir
.body_owner_def_id
(
body
.id
());
let
region_maps
=
&
self
.tcx
.region_maps
(
body_owner_def_id
);
let
mut
delegate
=
InferBorrowKind
{
fcx
:
self
,
adjust_closure_kinds
:
NodeMap
(),
adjust_upvar_captures
:
ty
::
UpvarCaptureMap
::
default
(),
};
euv
::
ExprUseVisitor
::
new
(
&
mut
delegate
,
region_maps
,
self
,
self
.param_env
)
.consume_body
(
body
);
// Write the adjusted values back into the main tables.
if
infer_kind
{
if
let
Some
(
kind
)
=
delegate
.adjust_closure_kinds
.remove
(
&
id
)
{
self
.tables
.borrow_mut
()
.closure_kinds
.insert
(
id
,
kind
);
}
}
self
.tables
.borrow_mut
()
.upvar_capture_map
.extend
(
delegate
.adjust_upvar_captures
);
}
// Now that we've analyzed the closure, we know how each
...
...
@@ -191,7 +168,7 @@ fn analyze_closure(&mut self,
// inference algorithm will reject it).
// Extract the type variables UV0...UVn.
let
(
def_id
,
closure_substs
)
=
match
self
.
fcx
.
node_ty
(
id
)
.sty
{
let
(
def_id
,
closure_substs
)
=
match
self
.node_ty
(
id
)
.sty
{
ty
::
TyClosure
(
def_id
,
substs
)
=>
(
def_id
,
substs
),
ref
t
=>
{
span_bug!
(
...
...
@@ -206,44 +183,41 @@ fn analyze_closure(&mut self,
debug!
(
"analyze_closure: id={:?} closure_substs={:?} final_upvar_tys={:?}"
,
id
,
closure_substs
,
final_upvar_tys
);
for
(
upvar_ty
,
final_upvar_ty
)
in
closure_substs
.upvar_tys
(
def_id
,
self
.
fcx.
tcx
)
.zip
(
final_upvar_tys
)
closure_substs
.upvar_tys
(
def_id
,
self
.tcx
)
.zip
(
final_upvar_tys
)
{
self
.
fcx
.
demand_eqtype
(
span
,
final_upvar_ty
,
upvar_ty
);
self
.demand_eqtype
(
span
,
final_upvar_ty
,
upvar_ty
);
}
// If we are also inferred the closure kind here, update the
// main table and process any deferred resolutions.
if
let
Some
(
&
(
kind
,
context
))
=
self
.temp_closure_kinds
.get
(
&
id
)
{
self
.fcx.tables
.borrow_mut
()
.closure_kinds
.insert
(
id
,
(
kind
,
context
));
let
closure_def_id
=
self
.fcx.tcx.hir
.local_def_id
(
id
);
debug!
(
"closure_kind({:?}) = {:?}"
,
closure_def_id
,
kind
);
// If we are also inferred the closure kind here,
// process any deferred resolutions.
if
infer_kind
{
let
closure_def_id
=
self
.tcx.hir
.local_def_id
(
id
);
let
deferred_call_resolutions
=
self
.
fcx
.
remove_deferred_call_resolutions
(
closure_def_id
);
self
.remove_deferred_call_resolutions
(
closure_def_id
);
for
deferred_call_resolution
in
deferred_call_resolutions
{
deferred_call_resolution
.resolve
(
self
.fcx
);
deferred_call_resolution
.resolve
(
self
);
}
}
}
// Returns a list of `ClosureUpvar`s for each upvar.
fn
final_upvar_tys
(
&
mut
self
,
closure_id
:
ast
::
NodeId
)
->
Vec
<
Ty
<
'tcx
>>
{
fn
final_upvar_tys
(
&
self
,
closure_id
:
ast
::
NodeId
)
->
Vec
<
Ty
<
'tcx
>>
{
// Presently an unboxed closure type cannot "escape" out of a
// function, so we will only encounter ones that originated in the
// local crate or were inlined into it along with some function.
// This may change if abstract return types of some sort are
// implemented.
let
tcx
=
self
.
fcx.
tcx
;
let
tcx
=
self
.tcx
;
tcx
.with_freevars
(
closure_id
,
|
freevars
|
{
freevars
.iter
()
.map
(|
freevar
|
{
let
def_id
=
freevar
.def
.def_id
();
let
var_id
=
tcx
.hir
.as_local_node_id
(
def_id
)
.unwrap
();
let
freevar_ty
=
self
.
fcx
.
node_ty
(
var_id
);
let
freevar_ty
=
self
.node_ty
(
var_id
);
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
var_id
,
closure_expr_id
:
closure_id
};
let
capture
=
self
.
fcx
.upvar_capture
(
upvar_id
)
.unwrap
(
);
let
capture
=
self
.
tables
.borrow
()
.upvar_capture
(
upvar_id
);
debug!
(
"var_id={:?} freevar_ty={:?} capture={:?}"
,
var_id
,
freevar_ty
,
capture
);
...
...
@@ -260,7 +234,15 @@ fn final_upvar_tys(&mut self, closure_id: ast::NodeId) -> Vec<Ty<'tcx>> {
})
.collect
()
})
}
}
struct
InferBorrowKind
<
'a
,
'gcx
:
'a
+
'tcx
,
'tcx
:
'a
>
{
fcx
:
&
'a
FnCtxt
<
'a
,
'gcx
,
'tcx
>
,
adjust_closure_kinds
:
NodeMap
<
(
ty
::
ClosureKind
,
Option
<
(
Span
,
ast
::
Name
)
>
)
>
,
adjust_upvar_captures
:
ty
::
UpvarCaptureMap
<
'tcx
>
,
}
impl
<
'a
,
'gcx
,
'tcx
>
InferBorrowKind
<
'a
,
'gcx
,
'tcx
>
{
fn
adjust_upvar_borrow_kind_for_consume
(
&
mut
self
,
cmt
:
mc
::
cmt
<
'tcx
>
,
mode
:
euv
::
ConsumeMode
)
...
...
@@ -297,9 +279,7 @@ fn adjust_upvar_borrow_kind_for_consume(&mut self,
guarantor
.span
,
tcx
.hir
.name
(
upvar_id
.var_id
));
let
upvar_capture_map
=
&
mut
self
.fcx.tables
.borrow_mut
()
.upvar_capture_map
;
upvar_capture_map
.insert
(
upvar_id
,
ty
::
UpvarCapture
::
ByValue
);
self
.adjust_upvar_captures
.insert
(
upvar_id
,
ty
::
UpvarCapture
::
ByValue
);
}
mc
::
NoteClosureEnv
(
upvar_id
)
=>
{
// we get just a closureenv ref if this is a
...
...
@@ -410,11 +390,7 @@ fn try_adjust_upvar_deref(&mut self,
// upvar, then we need to modify the
// borrow_kind of the upvar to make sure it
// is inferred to mutable if necessary
{
let
upvar_capture_map
=
&
mut
self
.fcx.tables
.borrow_mut
()
.upvar_capture_map
;
let
ub
=
upvar_capture_map
.get_mut
(
&
upvar_id
)
.unwrap
();
self
.adjust_upvar_borrow_kind
(
upvar_id
,
ub
,
borrow_kind
);
}
self
.adjust_upvar_borrow_kind
(
upvar_id
,
borrow_kind
);
// also need to be in an FnMut closure since this is not an ImmBorrow
self
.adjust_closure_kind
(
upvar_id
.closure_expr_id
,
...
...
@@ -448,22 +424,25 @@ fn try_adjust_upvar_deref(&mut self,
/// some particular use.
fn
adjust_upvar_borrow_kind
(
&
mut
self
,
upvar_id
:
ty
::
UpvarId
,
upvar_capture
:
&
mut
ty
::
UpvarCapture
,
kind
:
ty
::
BorrowKind
)
{
let
upvar_capture
=
self
.adjust_upvar_captures
.get
(
&
upvar_id
)
.cloned
()
.unwrap_or_else
(||
self
.fcx.tables
.borrow
()
.upvar_capture
(
upvar_id
));
debug!
(
"adjust_upvar_borrow_kind(upvar_id={:?}, upvar_capture={:?}, kind={:?})"
,
upvar_id
,
upvar_capture
,
kind
);
match
*
upvar_capture
{
match
upvar_capture
{
ty
::
UpvarCapture
::
ByValue
=>
{
// Upvar is already by-value, the strongest criteria.
}
ty
::
UpvarCapture
::
ByRef
(
ref
mut
upvar_borrow
)
=>
{
ty
::
UpvarCapture
::
ByRef
(
mut
upvar_borrow
)
=>
{
match
(
upvar_borrow
.kind
,
kind
)
{
// Take RHS:
(
ty
::
ImmBorrow
,
ty
::
UniqueImmBorrow
)
|
(
ty
::
ImmBorrow
,
ty
::
MutBorrow
)
|
(
ty
::
UniqueImmBorrow
,
ty
::
MutBorrow
)
=>
{
upvar_borrow
.kind
=
kind
;
self
.adjust_upvar_captures
.insert
(
upvar_id
,
ty
::
UpvarCapture
::
ByRef
(
upvar_borrow
));
}
// Take LHS:
(
ty
::
ImmBorrow
,
ty
::
ImmBorrow
)
|
...
...
@@ -484,7 +463,9 @@ fn adjust_closure_kind(&mut self,
debug!
(
"adjust_closure_kind(closure_id={}, new_kind={:?}, upvar_span={:?}, var_name={})"
,
closure_id
,
new_kind
,
upvar_span
,
var_name
);
if
let
Some
(
&
(
existing_kind
,
_
))
=
self
.temp_closure_kinds
.get
(
&
closure_id
)
{
let
closure_kind
=
self
.adjust_closure_kinds
.get
(
&
closure_id
)
.cloned
()
.or_else
(||
self
.fcx.tables
.borrow
()
.closure_kinds
.get
(
&
closure_id
)
.cloned
());
if
let
Some
((
existing_kind
,
_
))
=
closure_kind
{
debug!
(
"adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}"
,
closure_id
,
existing_kind
,
new_kind
);
...
...
@@ -500,7 +481,7 @@ fn adjust_closure_kind(&mut self,
(
ty
::
ClosureKind
::
Fn
,
ty
::
ClosureKind
::
FnOnce
)
|
(
ty
::
ClosureKind
::
FnMut
,
ty
::
ClosureKind
::
FnOnce
)
=>
{
// new kind is stronger than the old kind
self
.
temp
_closure_kinds
.insert
(
self
.
adjust
_closure_kinds
.insert
(
closure_id
,
(
new_kind
,
Some
((
upvar_span
,
var_name
)))
);
...
...
@@ -510,27 +491,7 @@ fn adjust_closure_kind(&mut self,
}
}
impl
<
'a
,
'gcx
,
'tcx
>
Visitor
<
'gcx
>
for
AdjustBorrowKind
<
'a
,
'gcx
,
'tcx
>
{
fn
nested_visit_map
<
'this
>
(
&
'this
mut
self
)
->
NestedVisitorMap
<
'this
,
'gcx
>
{
NestedVisitorMap
::
None
}
fn
visit_fn
(
&
mut
self
,
fn_kind
:
intravisit
::
FnKind
<
'gcx
>
,
decl
:
&
'gcx
hir
::
FnDecl
,
body
:
hir
::
BodyId
,
span
:
Span
,
id
:
ast
::
NodeId
)
{
intravisit
::
walk_fn
(
self
,
fn_kind
,
decl
,
body
,
span
,
id
);
let
body
=
self
.fcx.tcx.hir
.body
(
body
);
self
.visit_body
(
body
);
self
.analyze_closure
(
id
,
span
,
body
);
}
}
impl
<
'a
,
'gcx
,
'tcx
>
euv
::
Delegate
<
'tcx
>
for
AdjustBorrowKind
<
'a
,
'gcx
,
'tcx
>
{
impl
<
'a
,
'gcx
,
'tcx
>
euv
::
Delegate
<
'tcx
>
for
InferBorrowKind
<
'a
,
'gcx
,
'tcx
>
{
fn
consume
(
&
mut
self
,
_
consume_id
:
ast
::
NodeId
,
_
consume_span
:
Span
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录