Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
2f29cdeb
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,发现更多精彩内容 >>
提交
2f29cdeb
编写于
1月 24, 2015
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Remove the capture mode map and just store the capture mode for individual variables.
Also add test. Fixes #16749.
上级
e0f5980e
变更
19
隐藏空白更改
内联
并排
Showing
19 changed file
with
418 addition
and
439 deletion
+418
-439
src/librustc/metadata/common.rs
src/librustc/metadata/common.rs
+1
-1
src/librustc/middle/astencode.rs
src/librustc/middle/astencode.rs
+25
-41
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/expr_use_visitor.rs
+21
-42
src/librustc/middle/mem_categorization.rs
src/librustc/middle/mem_categorization.rs
+115
-120
src/librustc/middle/ty.rs
src/librustc/middle/ty.rs
+57
-103
src/librustc/util/ppaux.rs
src/librustc/util/ppaux.rs
+9
-0
src/librustc_driver/driver.rs
src/librustc_driver/driver.rs
+0
-2
src/librustc_driver/test.rs
src/librustc_driver/test.rs
+1
-2
src/librustc_resolve/lib.rs
src/librustc_resolve/lib.rs
+2
-7
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/base.rs
+6
-6
src/librustc_trans/trans/closure.rs
src/librustc_trans/trans/closure.rs
+20
-19
src/librustc_trans/trans/common.rs
src/librustc_trans/trans/common.rs
+2
-7
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/mod.rs
+4
-8
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/regionck.rs
+28
-33
src/librustc_typeck/check/upvar.rs
src/librustc_typeck/check/upvar.rs
+43
-32
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/check/writeback.rs
+13
-9
src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs
src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs
+4
-2
src/test/compile-fail/unboxed-closure-illegal-move.rs
src/test/compile-fail/unboxed-closure-illegal-move.rs
+5
-5
src/test/compile-fail/unboxed-closures-mutate-upvar.rs
src/test/compile-fail/unboxed-closures-mutate-upvar.rs
+62
-0
未找到文件。
src/librustc/metadata/common.rs
浏览文件 @
2f29cdeb
...
...
@@ -140,7 +140,7 @@ pub enum astencode_tag { // Reserves 0x40 -- 0x5f
tag_table_moves_map
=
0x52
,
tag_table_capture_map
=
0x53
,
tag_table_closures
=
0x54
,
tag_table_upvar_
borrow
_map
=
0x55
,
tag_table_upvar_
capture
_map
=
0x55
,
tag_table_capture_modes
=
0x56
,
tag_table_object_cast_map
=
0x57
,
}
...
...
src/librustc/middle/astencode.rs
浏览文件 @
2f29cdeb
...
...
@@ -518,10 +518,6 @@ fn encode_freevar_entry(rbml_w: &mut Encoder, fv: &ty::Freevar) {
(
*
fv
)
.encode
(
rbml_w
)
.unwrap
();
}
fn
encode_capture_mode
(
rbml_w
:
&
mut
Encoder
,
cm
:
ast
::
CaptureClause
)
{
cm
.encode
(
rbml_w
)
.unwrap
();
}
trait
rbml_decoder_helper
{
fn
read_freevar_entry
(
&
mut
self
,
dcx
:
&
DecodeContext
)
->
ty
::
Freevar
;
...
...
@@ -559,6 +555,15 @@ fn tr(&self, dcx: &DecodeContext) -> ty::UpvarBorrow {
}
}
impl
tr
for
ty
::
UpvarCapture
{
fn
tr
(
&
self
,
dcx
:
&
DecodeContext
)
->
ty
::
UpvarCapture
{
match
*
self
{
ty
::
UpvarCapture
::
ByValue
=>
ty
::
UpvarCapture
::
ByValue
,
ty
::
UpvarCapture
::
ByRef
(
ref
data
)
=>
ty
::
UpvarCapture
::
ByRef
(
data
.tr
(
dcx
)),
}
}
}
// ______________________________________________________________________
// Encoding and decoding of MethodCallee
...
...
@@ -1210,34 +1215,20 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
});
for
freevar
in
fv
.iter
()
{
match
tcx
.capture_mode
(
id
)
{
ast
::
CaptureByRef
=>
{
rbml_w
.tag
(
c
::
tag_table_upvar_borrow_map
,
|
rbml_w
|
{
rbml_w
.id
(
id
);
rbml_w
.tag
(
c
::
tag_table_val
,
|
rbml_w
|
{
let
var_id
=
freevar
.def
.def_id
()
.node
;
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
var_id
,
closure_expr_id
:
id
};
let
upvar_borrow
=
tcx
.upvar_borrow_map
.borrow
()[
upvar_id
]
.clone
();
var_id
.encode
(
rbml_w
);
upvar_borrow
.encode
(
rbml_w
);
})
})
}
_
=>
{}
}
}
}
for
&
cm
in
tcx
.capture_modes
.borrow
()
.get
(
&
id
)
.iter
()
{
rbml_w
.tag
(
c
::
tag_table_capture_modes
,
|
rbml_w
|
{
rbml_w
.id
(
id
);
rbml_w
.tag
(
c
::
tag_table_val
,
|
rbml_w
|
{
encode_capture_mode
(
rbml_w
,
*
cm
);
rbml_w
.tag
(
c
::
tag_table_upvar_capture_map
,
|
rbml_w
|
{
rbml_w
.id
(
id
);
rbml_w
.tag
(
c
::
tag_table_val
,
|
rbml_w
|
{
let
var_id
=
freevar
.def
.def_id
()
.node
;
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
var_id
,
closure_expr_id
:
id
};
let
upvar_capture
=
tcx
.upvar_capture_map
.borrow
()[
upvar_id
]
.clone
();
var_id
.encode
(
rbml_w
);
upvar_capture
.encode
(
rbml_w
);
})
})
}
)
}
}
let
lid
=
ast
::
DefId
{
krate
:
ast
::
LOCAL_CRATE
,
node
:
id
};
...
...
@@ -1911,21 +1902,14 @@ fn decode_side_tables(dcx: &DecodeContext,
})
.unwrap
()
.into_iter
()
.collect
();
dcx
.tcx.freevars
.borrow_mut
()
.insert
(
id
,
fv_info
);
}
c
::
tag_table_upvar_
borrow
_map
=>
{
c
::
tag_table_upvar_
capture
_map
=>
{
let
var_id
:
ast
::
NodeId
=
Decodable
::
decode
(
val_dsr
)
.unwrap
();
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
dcx
.tr_id
(
var_id
),
closure_expr_id
:
id
};
let
ub
:
ty
::
UpvarBorrow
=
Decodable
::
decode
(
val_dsr
)
.unwrap
();
dcx
.tcx.upvar_borrow_map
.borrow_mut
()
.insert
(
upvar_id
,
ub
.tr
(
dcx
));
}
c
::
tag_table_capture_modes
=>
{
let
capture_mode
=
val_dsr
.read_capture_mode
();
dcx
.tcx
.capture_modes
.borrow_mut
()
.insert
(
id
,
capture_mode
);
let
ub
:
ty
::
UpvarCapture
=
Decodable
::
decode
(
val_dsr
)
.unwrap
();
dcx
.tcx.upvar_capture_map
.borrow_mut
()
.insert
(
upvar_id
,
ub
.tr
(
dcx
));
}
c
::
tag_table_tcache
=>
{
let
type_scheme
=
val_dsr
.read_type_scheme
(
dcx
);
...
...
src/librustc/middle/expr_use_visitor.rs
浏览文件 @
2f29cdeb
...
...
@@ -1208,53 +1208,32 @@ fn walk_captures(&mut self, closure_expr: &ast::Expr) {
debug!
(
"walk_captures({})"
,
closure_expr
.repr
(
self
.tcx
()));
ty
::
with_freevars
(
self
.tcx
(),
closure_expr
.id
,
|
freevars
|
{
match
self
.tcx
()
.capture_mode
(
closure_expr
.id
)
{
ast
::
CaptureByRef
=>
{
self
.walk_by_ref_captures
(
closure_expr
,
freevars
);
}
ast
::
CaptureByValue
=>
{
self
.walk_by_value_captures
(
closure_expr
,
freevars
);
for
freevar
in
freevars
.iter
()
{
let
id_var
=
freevar
.def
.def_id
()
.node
;
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
id_var
,
closure_expr_id
:
closure_expr
.id
};
let
upvar_capture
=
self
.typer
.upvar_capture
(
upvar_id
)
.unwrap
();
let
cmt_var
=
return_if_err!
(
self
.cat_captured_var
(
closure_expr
.id
,
closure_expr
.span
,
freevar
.def
));
match
upvar_capture
{
ty
::
UpvarCapture
::
ByValue
=>
{
let
mode
=
copy_or_move
(
self
.typer
,
&
cmt_var
,
CaptureMove
);
self
.delegate
.consume
(
closure_expr
.id
,
freevar
.span
,
cmt_var
,
mode
);
}
ty
::
UpvarCapture
::
ByRef
(
upvar_borrow
)
=>
{
self
.delegate
.borrow
(
closure_expr
.id
,
closure_expr
.span
,
cmt_var
,
upvar_borrow
.region
,
upvar_borrow
.kind
,
ClosureCapture
(
freevar
.span
));
}
}
}
});
}
fn
walk_by_ref_captures
(
&
mut
self
,
closure_expr
:
&
ast
::
Expr
,
freevars
:
&
[
ty
::
Freevar
])
{
for
freevar
in
freevars
.iter
()
{
let
id_var
=
freevar
.def
.def_id
()
.node
;
let
cmt_var
=
return_if_err!
(
self
.cat_captured_var
(
closure_expr
.id
,
closure_expr
.span
,
freevar
.def
));
// Lookup the kind of borrow the callee requires, as
// inferred by regionbk
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
id_var
,
closure_expr_id
:
closure_expr
.id
};
let
upvar_borrow
=
self
.typer
.upvar_borrow
(
upvar_id
)
.unwrap
();
self
.delegate
.borrow
(
closure_expr
.id
,
closure_expr
.span
,
cmt_var
,
upvar_borrow
.region
,
upvar_borrow
.kind
,
ClosureCapture
(
freevar
.span
));
}
}
fn
walk_by_value_captures
(
&
mut
self
,
closure_expr
:
&
ast
::
Expr
,
freevars
:
&
[
ty
::
Freevar
])
{
for
freevar
in
freevars
.iter
()
{
let
cmt_var
=
return_if_err!
(
self
.cat_captured_var
(
closure_expr
.id
,
closure_expr
.span
,
freevar
.def
));
let
mode
=
copy_or_move
(
self
.typer
,
&
cmt_var
,
CaptureMove
);
self
.delegate
.consume
(
closure_expr
.id
,
freevar
.span
,
cmt_var
,
mode
);
}
}
fn
cat_captured_var
(
&
mut
self
,
closure_id
:
ast
::
NodeId
,
closure_span
:
Span
,
...
...
src/librustc/middle/mem_categorization.rs
浏览文件 @
2f29cdeb
...
...
@@ -277,9 +277,7 @@ fn node_method_origin(&self, method_call: ty::MethodCall)
fn
adjustments
<
'a
>
(
&
'a
self
)
->
&
'a
RefCell
<
NodeMap
<
ty
::
AutoAdjustment
<
'tcx
>>>
;
fn
is_method_call
(
&
self
,
id
:
ast
::
NodeId
)
->
bool
;
fn
temporary_scope
(
&
self
,
rvalue_id
:
ast
::
NodeId
)
->
Option
<
region
::
CodeExtent
>
;
fn
upvar_borrow
(
&
self
,
upvar_id
:
ty
::
UpvarId
)
->
Option
<
ty
::
UpvarBorrow
>
;
fn
capture_mode
(
&
self
,
closure_expr_id
:
ast
::
NodeId
)
->
ast
::
CaptureClause
;
fn
upvar_capture
(
&
self
,
upvar_id
:
ty
::
UpvarId
)
->
Option
<
ty
::
UpvarCapture
>
;
}
impl
MutabilityCategory
{
...
...
@@ -595,8 +593,7 @@ pub fn cat_def(&self,
match
ty
.sty
{
ty
::
ty_closure
(
closure_id
,
_
,
_
)
=>
{
let
kind
=
self
.typer
.closure_kind
(
closure_id
);
let
mode
=
self
.typer
.capture_mode
(
fn_node_id
);
self
.cat_upvar
(
id
,
span
,
var_id
,
fn_node_id
,
kind
,
mode
)
self
.cat_upvar
(
id
,
span
,
var_id
,
fn_node_id
,
kind
)
}
_
=>
{
self
.tcx
()
.sess
.span_bug
(
...
...
@@ -628,10 +625,13 @@ fn cat_upvar(&self,
span
:
Span
,
var_id
:
ast
::
NodeId
,
fn_node_id
:
ast
::
NodeId
,
kind
:
ty
::
ClosureKind
,
mode
:
ast
::
CaptureClause
)
->
McResult
<
cmt
<
'tcx
>>
{
// An upvar can have up to 3 components. The base is a
kind
:
ty
::
ClosureKind
)
->
McResult
<
cmt
<
'tcx
>>
{
// An upvar can have up to 3 components. We translate first to a
// `cat_upvar`, which is itself a fiction -- it represents the reference to the
// field from the environment.
//
// `cat_upvar`. Next, we add a deref through the implicit
// environment pointer with an anonymous free region 'env and
// appropriate borrow kind for closure kinds that take self by
...
...
@@ -650,135 +650,130 @@ fn cat_upvar(&self,
// Fn | copied -> &'env | upvar -> &'env -> &'up bk
// FnMut | copied -> &'env mut | upvar -> &'env mut -> &'up bk
// FnOnce | copied | upvar -> &'up bk
let
var_ty
=
try!
(
self
.node_ty
(
var_id
));
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
var_id
,
closure_expr_id
:
fn_node_id
};
let
var_ty
=
try!
(
self
.node_ty
(
var_id
));
// Mutability of original variable itself
let
var_mutbl
=
MutabilityCategory
::
from_local
(
self
.tcx
(),
var_id
);
// Construct information about env pointer dereference, if any
let
mutbl
=
match
kind
{
ty
::
FnOnceClosureKind
=>
None
,
// None, env is by-value
ty
::
FnMutClosureKind
=>
match
mode
{
// Depends on capture type
ast
::
CaptureByValue
=>
Some
(
var_mutbl
),
// Mutable if the original var is
ast
::
CaptureByRef
=>
Some
(
McDeclared
)
// Mutable regardless
},
ty
::
FnClosureKind
=>
Some
(
McImmutable
)
// Never mutable
// Construct the upvar. This represents access to the field
// from the environment (perhaps we should eventually desugar
// this field further, but it will do for now).
let
cmt_result
=
cmt_
{
id
:
id
,
span
:
span
,
cat
:
cat_upvar
(
Upvar
{
id
:
upvar_id
,
kind
:
kind
}),
mutbl
:
var_mutbl
,
ty
:
var_ty
,
note
:
NoteNone
};
let
env_info
=
mutbl
.map
(|
env_mutbl
|
{
// Look up the node ID of the closure body so we can construct
// a free region within it
let
fn_body_id
=
{
let
fn_expr
=
match
self
.tcx
()
.map
.find
(
fn_node_id
)
{
Some
(
ast_map
::
NodeExpr
(
e
))
=>
e
,
_
=>
unreachable!
()
};
match
fn_expr
.node
{
ast
::
ExprClosure
(
_
,
_
,
_
,
ref
body
)
=>
body
.id
,
_
=>
unreachable!
()
}
};
// Region of environment pointer
let
env_region
=
ty
::
ReFree
(
ty
::
FreeRegion
{
scope
:
region
::
CodeExtent
::
from_node_id
(
fn_body_id
),
bound_region
:
ty
::
BrEnv
});
let
env_ptr
=
BorrowedPtr
(
if
env_mutbl
.is_mutable
()
{
ty
::
MutBorrow
}
else
{
ty
::
ImmBorrow
},
env_region
);
(
env_mutbl
,
env_ptr
)
});
// If this is a `FnMut` or `Fn` closure, then the above is
// conceptually a `&mut` or `&` reference, so we have to add a
// deref.
let
cmt_result
=
match
kind
{
ty
::
FnOnceClosureKind
=>
{
cmt_result
}
ty
::
FnMutClosureKind
=>
{
self
.env_deref
(
id
,
span
,
upvar_id
,
var_mutbl
,
ty
::
MutBorrow
,
cmt_result
)
}
ty
::
FnClosureKind
=>
{
self
.env_deref
(
id
,
span
,
upvar_id
,
var_mutbl
,
ty
::
ImmBorrow
,
cmt_result
)
}
};
// First, switch by capture mode
Ok
(
match
mode
{
ast
::
CaptureByValue
=>
{
let
mut
base
=
cmt_
{
// If this is a by-ref capture, then the upvar we loaded is
// actually a reference, so we have to add an implicit deref
// for that.
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
var_id
,
closure_expr_id
:
fn_node_id
};
let
upvar_capture
=
self
.typer
.upvar_capture
(
upvar_id
)
.unwrap
();
let
cmt_result
=
match
upvar_capture
{
ty
::
UpvarCapture
::
ByValue
=>
{
cmt_result
}
ty
::
UpvarCapture
::
ByRef
(
upvar_borrow
)
=>
{
let
ptr
=
BorrowedPtr
(
upvar_borrow
.kind
,
upvar_borrow
.region
);
cmt_
{
id
:
id
,
span
:
span
,
cat
:
cat_upvar
(
Upvar
{
id
:
upvar_id
,
kind
:
kind
}),
mutbl
:
var_mutbl
,
cat
:
cat_deref
(
Rc
::
new
(
cmt_result
),
0
,
ptr
),
mutbl
:
MutabilityCategory
::
from_borrow_kind
(
upvar_borrow
.kind
),
ty
:
var_ty
,
note
:
NoteNone
};
match
env_info
{
Some
((
env_mutbl
,
env_ptr
))
=>
{
// We need to add the env deref. This means
// that the above is actually immutable and
// has a ref type. However, nothing should
// actually look at the type, so we can get
// away with stuffing a `ty_err` in there
// instead of bothering to construct a proper
// one.
base
.mutbl
=
McImmutable
;
base
.ty
=
self
.tcx
()
.types.err
;
Rc
::
new
(
cmt_
{
id
:
id
,
span
:
span
,
cat
:
cat_deref
(
Rc
::
new
(
base
),
0
,
env_ptr
),
mutbl
:
env_mutbl
,
ty
:
var_ty
,
note
:
NoteClosureEnv
(
upvar_id
)
})
}
None
=>
Rc
::
new
(
base
)
note
:
NoteUpvarRef
(
upvar_id
)
}
},
ast
::
CaptureByRef
=>
{
// The type here is actually a ref (or ref of a ref),
// but we can again get away with not constructing one
// properly since it will never be used.
let
mut
base
=
cmt_
{
id
:
id
,
span
:
span
,
cat
:
cat_upvar
(
Upvar
{
id
:
upvar_id
,
kind
:
kind
}),
mutbl
:
McImmutable
,
ty
:
self
.tcx
()
.types.err
,
note
:
NoteNone
};
}
};
match
env_info
{
Some
((
env_mutbl
,
env_ptr
))
=>
{
base
=
cmt_
{
id
:
id
,
span
:
span
,
cat
:
cat_deref
(
Rc
::
new
(
base
),
0
,
env_ptr
),
mutbl
:
env_mutbl
,
ty
:
self
.tcx
()
.types.err
,
note
:
NoteClosureEnv
(
upvar_id
)
};
}
None
=>
{}
}
Ok
(
Rc
::
new
(
cmt_result
))
}
// Look up upvar borrow so we can get its region
let
upvar_borrow
=
self
.typer
.upvar_borrow
(
upvar_id
)
.unwrap
();
let
ptr
=
BorrowedPtr
(
upvar_borrow
.kind
,
upvar_borrow
.region
);
fn
env_deref
(
&
self
,
id
:
ast
::
NodeId
,
span
:
Span
,
upvar_id
:
ty
::
UpvarId
,
upvar_mutbl
:
MutabilityCategory
,
env_borrow_kind
:
ty
::
BorrowKind
,
cmt_result
:
cmt_
<
'tcx
>
)
->
cmt_
<
'tcx
>
{
// Look up the node ID of the closure body so we can construct
// a free region within it
let
fn_body_id
=
{
let
fn_expr
=
match
self
.tcx
()
.map
.find
(
upvar_id
.closure_expr_id
)
{
Some
(
ast_map
::
NodeExpr
(
e
))
=>
e
,
_
=>
unreachable!
()
};
Rc
::
new
(
cmt_
{
id
:
id
,
span
:
span
,
cat
:
cat_deref
(
Rc
::
new
(
base
),
0
,
ptr
),
mutbl
:
MutabilityCategory
::
from_borrow_kind
(
upvar_borrow
.kind
),
ty
:
var_ty
,
note
:
NoteUpvarRef
(
upvar_id
)
})
match
fn_expr
.node
{
ast
::
ExprClosure
(
_
,
_
,
_
,
ref
body
)
=>
body
.id
,
_
=>
unreachable!
()
}
})
};
// Region of environment pointer
let
env_region
=
ty
::
ReFree
(
ty
::
FreeRegion
{
scope
:
region
::
CodeExtent
::
from_node_id
(
fn_body_id
),
bound_region
:
ty
::
BrEnv
});
let
env_ptr
=
BorrowedPtr
(
env_borrow_kind
,
env_region
);
let
var_ty
=
cmt_result
.ty
;
// We need to add the env deref. This means
// that the above is actually immutable and
// has a ref type. However, nothing should
// actually look at the type, so we can get
// away with stuffing a `ty_err` in there
// instead of bothering to construct a proper
// one.
let
cmt_result
=
cmt_
{
mutbl
:
McImmutable
,
ty
:
self
.tcx
()
.types.err
,
..
cmt_result
};
let
mut
deref_mutbl
=
MutabilityCategory
::
from_borrow_kind
(
env_borrow_kind
);
// Issue #18335. If variable is declared as immutable, override the
// mutability from the environment and substitute an `&T` anyway.
match
upvar_mutbl
{
McImmutable
=>
{
deref_mutbl
=
McImmutable
;
}
McDeclared
|
McInherited
=>
{
}
}
cmt_
{
id
:
id
,
span
:
span
,
cat
:
cat_deref
(
Rc
::
new
(
cmt_result
),
0
,
env_ptr
),
mutbl
:
deref_mutbl
,
ty
:
var_ty
,
note
:
NoteClosureEnv
(
upvar_id
)
}
}
pub
fn
cat_rvalue_node
(
&
self
,
...
...
src/librustc/middle/ty.rs
浏览文件 @
2f29cdeb
...
...
@@ -777,7 +777,7 @@ pub struct ctxt<'tcx> {
pub
populated_external_traits
:
RefCell
<
DefIdSet
>
,
/// Borrows
pub
upvar_
borrow_map
:
RefCell
<
UpvarBorrow
Map
>
,
pub
upvar_
capture_map
:
RefCell
<
UpvarCapture
Map
>
,
/// These two caches are used by const_eval when decoding external statics
/// and variants that are found.
...
...
@@ -803,9 +803,6 @@ pub struct ctxt<'tcx> {
/// Maps any item's def-id to its stability index.
pub
stability
:
RefCell
<
stability
::
Index
>
,
/// Maps closures to their capture clauses.
pub
capture_modes
:
RefCell
<
CaptureModeMap
>
,
/// Maps def IDs to true if and only if they're associated types.
pub
associated_types
:
RefCell
<
DefIdMap
<
bool
>>
,
...
...
@@ -1247,60 +1244,31 @@ pub enum BorrowKind {
MutBorrow
}
/// Information describing the borrowing of an upvar. This is computed
/// during `typeck`, specifically by `regionck`. The general idea is
/// that the compiler analyses treat closures like:
///
/// let closure: &'e fn() = || {
/// x = 1; // upvar x is assigned to
/// use(y); // upvar y is read
/// foo(&z); // upvar z is borrowed immutably
/// };
///
/// as if they were "desugared" to something loosely like:
///
/// struct Vars<'x,'y,'z> { x: &'x mut int,
/// y: &'y const int,
/// z: &'z int }
/// let closure: &'e fn() = {
/// fn f(env: &Vars) {
/// *env.x = 1;
/// use(*env.y);
/// foo(env.z);
/// }
/// let env: &'e mut Vars<'x,'y,'z> = &mut Vars { x: &'x mut x,
/// y: &'y const y,
/// z: &'z z };
/// (env, f)
/// };
///
/// This is basically what happens at runtime. The closure is basically
/// an existentially quantified version of the `(env, f)` pair.
///
/// This data structure indicates the region and mutability of a single
/// one of the `x...z` borrows.
///
/// It may not be obvious why each borrowed variable gets its own
/// lifetime (in the desugared version of the example, these are indicated
/// by the lifetime parameters `'x`, `'y`, and `'z` in the `Vars` definition).
/// Each such lifetime must encompass the lifetime `'e` of the closure itself,
/// but need not be identical to it. The reason that this makes sense:
///
/// - Callers are only permitted to invoke the closure, and hence to
/// use the pointers, within the lifetime `'e`, so clearly `'e` must
/// be a sublifetime of `'x...'z`.
/// - The closure creator knows which upvars were borrowed by the closure
/// and thus `x...z` will be reserved for `'x...'z` respectively.
/// - Through mutation, the borrowed upvars can actually escape
/// the closure, so sometimes it is necessary for them to be larger
/// than the closure lifetime itself.
/// Information describing the capture of an upvar. This is computed
/// during `typeck`, specifically by `regionck`.
#[derive(PartialEq,
Clone,
RustcEncodable,
RustcDecodable,
Debug,
Copy)]
pub
enum
UpvarCapture
{
/// Upvar is captured by value. This is always true when the
/// closure is labeled `move`, but can also be true in other cases
/// depending on inference.
ByValue
,
/// Upvar is captured by reference.
ByRef
(
UpvarBorrow
),
}
#[derive(PartialEq,
Clone,
RustcEncodable,
RustcDecodable,
Debug,
Copy)]
pub
struct
UpvarBorrow
{
/// The kind of borrow: by-ref upvars have access to shared
/// immutable borrows, which are not part of the normal language
/// syntax.
pub
kind
:
BorrowKind
,
/// Region of the resulting reference.
pub
region
:
ty
::
Region
,
}
pub
type
Upvar
BorrowMap
=
FnvHashMap
<
UpvarId
,
UpvarBorrow
>
;
pub
type
Upvar
CaptureMap
=
FnvHashMap
<
UpvarId
,
UpvarCapture
>
;
impl
Region
{
pub
fn
is_bound
(
&
self
)
->
bool
{
...
...
@@ -1320,7 +1288,7 @@ pub fn escapes_depth(&self, depth: u32) -> bool {
}
#[derive(Clone,
PartialEq,
PartialOrd,
Eq,
Ord,
Hash,
RustcEncodable,
RustcDecodable,
Debug,
Copy)]
RustcEncodable,
RustcDecodable,
Debug,
Copy)]
/// A "free" region `fr` can be interpreted as "some region
/// at least as big as the scope `fr.scope`".
pub
struct
FreeRegion
{
...
...
@@ -1329,7 +1297,7 @@ pub struct FreeRegion {
}
#[derive(Clone,
PartialEq,
PartialOrd,
Eq,
Ord,
Hash,
RustcEncodable,
RustcDecodable,
Debug,
Copy)]
RustcEncodable,
RustcDecodable,
Debug,
Copy)]
pub
enum
BoundRegion
{
/// An anonymous region parameter for a given fn (&T)
BrAnon
(
u32
),
...
...
@@ -2359,7 +2327,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
named_region_map
:
resolve_lifetime
::
NamedRegionMap
,
map
:
ast_map
::
Map
<
'tcx
>
,
freevars
:
RefCell
<
FreevarMap
>
,
capture_modes
:
RefCell
<
CaptureModeMap
>
,
region_maps
:
middle
::
region
::
RegionMaps
,
lang_items
:
middle
::
lang_items
::
LanguageItems
,
stability
:
stability
::
Index
)
->
ctxt
<
'tcx
>
...
...
@@ -2413,7 +2380,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
used_mut_nodes
:
RefCell
::
new
(
NodeSet
()),
populated_external_types
:
RefCell
::
new
(
DefIdSet
()),
populated_external_traits
:
RefCell
::
new
(
DefIdSet
()),
upvar_
borrow
_map
:
RefCell
::
new
(
FnvHashMap
()),
upvar_
capture
_map
:
RefCell
::
new
(
FnvHashMap
()),
extern_const_statics
:
RefCell
::
new
(
DefIdMap
()),
extern_const_variants
:
RefCell
::
new
(
DefIdMap
()),
method_map
:
RefCell
::
new
(
FnvHashMap
()),
...
...
@@ -2422,7 +2389,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
node_lint_levels
:
RefCell
::
new
(
FnvHashMap
()),
transmute_restrictions
:
RefCell
::
new
(
Vec
::
new
()),
stability
:
RefCell
::
new
(
stability
),
capture_modes
:
capture_modes
,
associated_types
:
RefCell
::
new
(
DefIdMap
()),
selection_cache
:
traits
::
SelectionCache
::
new
(),
repr_hint_cache
:
RefCell
::
new
(
DefIdMap
()),
...
...
@@ -5646,7 +5612,6 @@ pub fn closure_upvars<'tcx>(typer: &mc::Typer<'tcx>,
// implemented.
assert
!
(
closure_id
.krate
==
ast
::
LOCAL_CRATE
);
let
tcx
=
typer
.tcx
();
let
capture_mode
=
tcx
.capture_modes
.borrow
()[
closure_id
.node
]
.clone
();
match
tcx
.freevars
.borrow
()
.get
(
&
closure_id
.node
)
{
None
=>
Some
(
vec!
[]),
Some
(
ref
freevars
)
=>
{
...
...
@@ -5659,43 +5624,38 @@ pub fn closure_upvars<'tcx>(typer: &mc::Typer<'tcx>,
};
let
freevar_ty
=
freevar_ty
.subst
(
tcx
,
substs
);
match
capture_mode
{
ast
::
CaptureByValue
=>
{
Some
(
ClosureUpvar
{
def
:
freevar
.def
,
span
:
freevar
.span
,
ty
:
freevar_ty
})
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
freevar_def_id
.node
,
closure_expr_id
:
closure_id
.node
};
let
captured_freevar_ty
=
match
typer
.upvar_capture
(
upvar_id
)
{
Some
(
UpvarCapture
::
ByValue
)
=>
{
freevar_ty
}
ast
::
CaptureByRef
=>
{
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
freevar_def_id
.node
,
closure_expr_id
:
closure_id
.node
};
Some
(
UpvarCapture
::
ByRef
(
borrow
))
=>
{
mk_rptr
(
tcx
,
tcx
.mk_region
(
borrow
.region
),
ty
::
mt
{
ty
:
freevar_ty
,
mutbl
:
borrow
.kind
.to_mutbl_lossy
(),
})
}
// FIXME
let
freevar_ref_ty
=
match
typer
.upvar_borrow
(
upvar_id
)
{
Some
(
borrow
)
=>
{
mk_rptr
(
tcx
,
tcx
.mk_region
(
borrow
.region
),
ty
::
mt
{
ty
:
freevar_ty
,
mutbl
:
borrow
.kind
.to_mutbl_lossy
(),
})
}
None
=>
{
// FIXME(#16640) we should really return None here;
// but that requires better inference integration,
// for now gin up something.
freevar_ty
}
};
Some
(
ClosureUpvar
{
def
:
freevar
.def
,
span
:
freevar
.span
,
ty
:
freevar_ref_ty
,
})
None
=>
{
// FIXME(#16640) we should really return None here;
// but that requires better inference integration,
// for now gin up something.
freevar_ty
}
}
};
Some
(
ClosureUpvar
{
def
:
freevar
.def
,
span
:
freevar
.span
,
ty
:
captured_freevar_ty
,
})
})
.collect
()
}
...
...
@@ -6449,14 +6409,13 @@ pub fn to_user_str(&self) -> &'static str {
}
impl
<
'tcx
>
ctxt
<
'tcx
>
{
pub
fn
capture_mode
(
&
self
,
closure_expr_id
:
ast
::
NodeId
)
->
ast
::
CaptureClause
{
self
.capture_modes
.borrow
()[
closure_expr_id
]
.clone
()
}
pub
fn
is_method_call
(
&
self
,
expr_id
:
ast
::
NodeId
)
->
bool
{
self
.method_map
.borrow
()
.contains_key
(
&
MethodCall
::
expr
(
expr_id
))
}
pub
fn
upvar_capture
(
&
self
,
upvar_id
:
ty
::
UpvarId
)
->
Option
<
ty
::
UpvarCapture
>
{
Some
(
self
.upvar_capture_map
.borrow
()[
upvar_id
]
.clone
())
}
}
impl
<
'a
,
'tcx
>
mc
::
Typer
<
'tcx
>
for
ParameterEnvironment
<
'a
,
'tcx
>
{
...
...
@@ -6494,13 +6453,8 @@ fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent>
self
.tcx.region_maps
.temporary_scope
(
rvalue_id
)
}
fn
upvar_borrow
(
&
self
,
upvar_id
:
ty
::
UpvarId
)
->
Option
<
ty
::
UpvarBorrow
>
{
Some
(
self
.tcx.upvar_borrow_map
.borrow
()[
upvar_id
]
.clone
())
}
fn
capture_mode
(
&
self
,
closure_expr_id
:
ast
::
NodeId
)
->
ast
::
CaptureClause
{
self
.tcx
.capture_mode
(
closure_expr_id
)
fn
upvar_capture
(
&
self
,
upvar_id
:
ty
::
UpvarId
)
->
Option
<
ty
::
UpvarCapture
>
{
self
.tcx
.upvar_capture
(
upvar_id
)
}
fn
type_moves_by_default
(
&
self
,
span
:
Span
,
ty
:
Ty
<
'tcx
>
)
->
bool
{
...
...
src/librustc/util/ppaux.rs
浏览文件 @
2f29cdeb
...
...
@@ -1292,6 +1292,15 @@ fn repr(&self, tcx: &ctxt) -> String {
}
}
impl
<
'tcx
>
Repr
<
'tcx
>
for
ty
::
UpvarCapture
{
fn
repr
(
&
self
,
tcx
:
&
ctxt
)
->
String
{
match
*
self
{
ty
::
UpvarCapture
::
ByValue
=>
format!
(
"ByValue"
),
ty
::
UpvarCapture
::
ByRef
(
ref
data
)
=>
format!
(
"ByRef({})"
,
data
.repr
(
tcx
)),
}
}
}
impl
<
'tcx
>
Repr
<
'tcx
>
for
ty
::
IntVid
{
fn
repr
(
&
self
,
_
tcx
:
&
ctxt
)
->
String
{
format!
(
"{:?}"
,
self
)
...
...
src/librustc_driver/driver.rs
浏览文件 @
2f29cdeb
...
...
@@ -560,7 +560,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
let
resolve
::
CrateMap
{
def_map
,
freevars
,
capture_mode_map
,
export_map
,
trait_map
,
external_exports
,
...
...
@@ -606,7 +605,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
named_region_map
,
ast_map
,
freevars
,
capture_mode_map
,
region_map
,
lang_items
,
stability_index
);
...
...
src/librustc_driver/test.rs
浏览文件 @
2f29cdeb
...
...
@@ -121,7 +121,7 @@ fn test_env<F>(source_string: &str,
// run just enough stuff to build a tcx:
let
lang_items
=
lang_items
::
collect_language_items
(
krate
,
&
sess
);
let
resolve
::
CrateMap
{
def_map
,
freevars
,
capture_mode_map
,
..
}
=
let
resolve
::
CrateMap
{
def_map
,
freevars
,
..
}
=
resolve
::
resolve_crate
(
&
sess
,
&
ast_map
,
&
lang_items
,
krate
,
resolve
::
MakeGlobMap
::
No
);
let
named_region_map
=
resolve_lifetime
::
krate
(
&
sess
,
krate
,
&
def_map
);
let
region_map
=
region
::
resolve_crate
(
&
sess
,
krate
);
...
...
@@ -132,7 +132,6 @@ fn test_env<F>(source_string: &str,
named_region_map
,
ast_map
,
freevars
,
capture_mode_map
,
region_map
,
lang_items
,
stability_index
);
...
...
src/librustc_resolve/lib.rs
浏览文件 @
2f29cdeb
...
...
@@ -62,7 +62,7 @@
use
rustc
::
middle
::
pat_util
::
pat_bindings
;
use
rustc
::
middle
::
privacy
::
*
;
use
rustc
::
middle
::
subst
::{
ParamSpace
,
FnSpace
,
TypeSpace
};
use
rustc
::
middle
::
ty
::{
CaptureModeMap
,
Freevar
,
FreevarMap
,
TraitMap
,
GlobMap
};
use
rustc
::
middle
::
ty
::{
Freevar
,
FreevarMap
,
TraitMap
,
GlobMap
};
use
rustc
::
util
::
nodemap
::{
NodeMap
,
NodeSet
,
DefIdSet
,
FnvHashMap
};
use
rustc
::
util
::
lev_distance
::
lev_distance
;
...
...
@@ -900,7 +900,6 @@ struct Resolver<'a, 'tcx:'a> {
def_map
:
DefMap
,
freevars
:
RefCell
<
FreevarMap
>
,
freevars_seen
:
RefCell
<
NodeMap
<
NodeSet
>>
,
capture_mode_map
:
CaptureModeMap
,
export_map
:
ExportMap
,
trait_map
:
TraitMap
,
external_exports
:
ExternalExports
,
...
...
@@ -974,7 +973,6 @@ fn new(session: &'a Session,
def_map
:
RefCell
::
new
(
NodeMap
()),
freevars
:
RefCell
::
new
(
NodeMap
()),
freevars_seen
:
RefCell
::
new
(
NodeMap
()),
capture_mode_map
:
NodeMap
(),
export_map
:
NodeMap
(),
trait_map
:
NodeMap
(),
used_imports
:
HashSet
::
new
(),
...
...
@@ -4523,8 +4521,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
visit
::
walk_expr
(
self
,
expr
);
}
ExprClosure
(
capture_clause
,
_
,
ref
fn_decl
,
ref
block
)
=>
{
self
.capture_mode_map
.insert
(
expr
.id
,
capture_clause
);
ExprClosure
(
_
,
_
,
ref
fn_decl
,
ref
block
)
=>
{
self
.resolve_function
(
ClosureRibKind
(
expr
.id
),
Some
(
&**
fn_decl
),
NoTypeParameters
,
&**
block
);
...
...
@@ -4835,7 +4832,6 @@ fn dump_module(&mut self, module_: Rc<Module>) {
pub
struct
CrateMap
{
pub
def_map
:
DefMap
,
pub
freevars
:
RefCell
<
FreevarMap
>
,
pub
capture_mode_map
:
RefCell
<
CaptureModeMap
>
,
pub
export_map
:
ExportMap
,
pub
trait_map
:
TraitMap
,
pub
external_exports
:
ExternalExports
,
...
...
@@ -4875,7 +4871,6 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
CrateMap
{
def_map
:
resolver
.def_map
,
freevars
:
resolver
.freevars
,
capture_mode_map
:
RefCell
::
new
(
resolver
.capture_mode_map
),
export_map
:
resolver
.export_map
,
trait_map
:
resolver
.trait_map
,
external_exports
:
resolver
.external_exports
,
...
...
src/librustc_trans/trans/base.rs
浏览文件 @
2f29cdeb
...
...
@@ -1789,7 +1789,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
fcx
=
new_fn_ctxt
(
ccx
,
llfndecl
,
fn_ast_id
,
closure_env
.kind
!=
closure
::
NotClosure
,
closure_env
.kind
!=
closure
::
ClosureKind
::
NotClosure
,
output_type
,
param_substs
,
Some
(
body
.span
),
...
...
@@ -1809,12 +1809,12 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
.map
(|
arg
|
node_id_type
(
bcx
,
arg
.id
))
.collect
::
<
Vec
<
_
>>
();
let
monomorphized_arg_types
=
match
closure_env
.kind
{
closure
::
NotClosure
=>
{
closure
::
ClosureKind
::
NotClosure
=>
{
monomorphized_arg_types
}
// Tuple up closure argument types for the "rust-call" ABI.
closure
::
Closure
(
..
)
=>
{
closure
::
Closure
Kind
::
Closure
=>
{
vec!
[
ty
::
mk_tup
(
ccx
.tcx
(),
monomorphized_arg_types
)]
}
};
...
...
@@ -1836,13 +1836,13 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
};
bcx
=
match
closure_env
.kind
{
closure
::
NotClosure
=>
{
closure
::
ClosureKind
::
NotClosure
=>
{
copy_args_to_allocas
(
bcx
,
arg_scope
,
&
decl
.inputs
[],
arg_datums
)
}
closure
::
Closure
(
..
)
=>
{
closure
::
Closure
Kind
::
Closure
=>
{
copy_closure_args_to_allocas
(
bcx
,
arg_scope
,
...
...
@@ -1932,7 +1932,7 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
attrs
,
output_type
,
abi
,
closure
::
ClosureEnv
::
new
(
&
[],
closure
::
NotClosure
));
closure
::
ClosureEnv
::
new
(
&
[],
closure
::
ClosureKind
::
NotClosure
));
}
pub
fn
trans_enum_variant
<
'a
,
'tcx
>
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
...
...
src/librustc_trans/trans/closure.rs
浏览文件 @
2f29cdeb
...
...
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub
use
self
::
ClosureKind
::
*
;
use
back
::
link
::
mangle_internal_name_by_path_and_seq
;
use
middle
::
mem_categorization
::
Typer
;
use
trans
::
adt
;
...
...
@@ -33,9 +31,9 @@
fn
load_closure_environment
<
'blk
,
'tcx
>
(
bcx
:
Block
<
'blk
,
'tcx
>
,
arg_scope_id
:
ScopeId
,
freevar_mode
:
ast
::
CaptureClause
,
freevars
:
&
[
ty
::
Freevar
])
->
Block
<
'blk
,
'tcx
>
{
->
Block
<
'blk
,
'tcx
>
{
let
_
icx
=
push_ctxt
(
"closure::load_closure_environment"
);
// Special case for small by-value selfs.
...
...
@@ -65,18 +63,21 @@ fn load_closure_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
};
for
(
i
,
freevar
)
in
freevars
.iter
()
.enumerate
()
{
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
freevar
.def
.local_node_id
(),
closure_expr_id
:
closure_id
.node
};
let
upvar_capture
=
bcx
.tcx
()
.upvar_capture
(
upvar_id
)
.unwrap
();
let
mut
upvar_ptr
=
GEPi
(
bcx
,
llenv
,
&
[
0
,
i
]);
let
captured_by_ref
=
match
freevar_mode
{
ast
::
CaptureByRef
=>
{
let
captured_by_ref
=
match
upvar_capture
{
ty
::
UpvarCapture
::
ByValue
=>
false
,
ty
::
UpvarCapture
::
ByRef
(
..
)
=>
{
upvar_ptr
=
Load
(
bcx
,
upvar_ptr
);
true
}
ast
::
CaptureByValue
=>
false
};
let
def_id
=
freevar
.def
.def_id
();
bcx
.fcx.llupvars
.borrow_mut
()
.insert
(
def_id
.node
,
upvar_ptr
);
if
kind
==
ty
::
FnOnceClosureKind
&&
freevar_mode
==
ast
::
CaptureByValue
{
if
kind
==
ty
::
FnOnceClosureKind
&&
!
captured_by_ref
{
bcx
.fcx
.schedule_drop_mem
(
arg_scope_id
,
upvar_ptr
,
node_id_type
(
bcx
,
def_id
.node
))
...
...
@@ -99,8 +100,7 @@ fn load_closure_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
#[derive(PartialEq)]
pub
enum
ClosureKind
<
'tcx
>
{
NotClosure
,
// See load_closure_environment.
Closure
(
ast
::
CaptureClause
)
Closure
,
}
pub
struct
ClosureEnv
<
'a
,
'tcx
>
{
...
...
@@ -125,9 +125,9 @@ pub fn load<'blk>(self, bcx: Block<'blk, 'tcx>, arg_scope: ScopeId)
}
match
self
.kind
{
NotClosure
=>
bcx
,
Closure
(
freevar_mode
)
=>
{
load_closure_environment
(
bcx
,
arg_scope
,
freevar_mode
,
self
.freevars
)
ClosureKind
::
NotClosure
=>
bcx
,
Closure
Kind
::
Closure
=>
{
load_closure_environment
(
bcx
,
arg_scope
,
self
.freevars
)
}
}
}
...
...
@@ -212,7 +212,6 @@ pub fn trans_closure_expr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
let
freevars
:
Vec
<
ty
::
Freevar
>
=
ty
::
with_freevars
(
bcx
.tcx
(),
id
,
|
fv
|
fv
.iter
()
.map
(|
&
fv
|
fv
)
.collect
());
let
freevar_mode
=
bcx
.tcx
()
.capture_mode
(
id
);
let
sig
=
ty
::
erase_late_bound_regions
(
bcx
.tcx
(),
&
function_type
.sig
);
...
...
@@ -225,8 +224,7 @@ pub fn trans_closure_expr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
&
[],
sig
.output
,
function_type
.abi
,
ClosureEnv
::
new
(
&
freevars
[],
Closure
(
freevar_mode
)));
ClosureEnv
::
new
(
&
freevars
[],
ClosureKind
::
Closure
));
// Don't hoist this to the top of the function. It's perfectly legitimate
// to have a zero-size closure (in which case dest will be `Ignore`) and
...
...
@@ -249,11 +247,14 @@ pub fn trans_closure_expr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
dest_addr
,
0
,
i
);
match
freevar_mode
{
ast
::
CaptureByValue
=>
{
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
freevar
.def
.local_node_id
(),
closure_expr_id
:
id
};
let
upvar_capture
=
bcx
.tcx
()
.upvar_capture
(
upvar_id
)
.unwrap
();
match
upvar_capture
{
ty
::
UpvarCapture
::
ByValue
=>
{
bcx
=
datum
.store_to
(
bcx
,
upvar_slot_dest
);
}
ast
::
CaptureByRef
=>
{
ty
::
UpvarCapture
::
ByRef
(
..
)
=>
{
Store
(
bcx
,
datum
.to_llref
(),
upvar_slot_dest
);
}
}
...
...
src/librustc_trans/trans/common.rs
浏览文件 @
2f29cdeb
...
...
@@ -679,13 +679,8 @@ fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent>
self
.tcx
()
.region_maps
.temporary_scope
(
rvalue_id
)
}
fn
upvar_borrow
(
&
self
,
upvar_id
:
ty
::
UpvarId
)
->
Option
<
ty
::
UpvarBorrow
>
{
Some
(
self
.tcx
()
.upvar_borrow_map
.borrow
()[
upvar_id
]
.clone
())
}
fn
capture_mode
(
&
self
,
closure_expr_id
:
ast
::
NodeId
)
->
ast
::
CaptureClause
{
self
.tcx
()
.capture_modes
.borrow
()[
closure_expr_id
]
.clone
()
fn
upvar_capture
(
&
self
,
upvar_id
:
ty
::
UpvarId
)
->
Option
<
ty
::
UpvarCapture
>
{
Some
(
self
.tcx
()
.upvar_capture_map
.borrow
()[
upvar_id
]
.clone
())
}
fn
type_moves_by_default
(
&
self
,
span
:
Span
,
ty
:
Ty
<
'tcx
>
)
->
bool
{
...
...
src/librustc_typeck/check/mod.rs
浏览文件 @
2f29cdeb
...
...
@@ -160,7 +160,7 @@ pub struct Inherited<'a, 'tcx: 'a> {
item_substs
:
RefCell
<
NodeMap
<
ty
::
ItemSubsts
<
'tcx
>>>
,
adjustments
:
RefCell
<
NodeMap
<
ty
::
AutoAdjustment
<
'tcx
>>>
,
method_map
:
MethodMap
<
'tcx
>
,
upvar_
borrow_map
:
RefCell
<
ty
::
UpvarBorrow
Map
>
,
upvar_
capture_map
:
RefCell
<
ty
::
UpvarCapture
Map
>
,
closures
:
RefCell
<
DefIdMap
<
ty
::
Closure
<
'tcx
>>>
,
object_cast_map
:
ObjectCastMap
<
'tcx
>
,
...
...
@@ -330,12 +330,8 @@ fn is_method_call(&self, id: ast::NodeId) -> bool {
fn
temporary_scope
(
&
self
,
rvalue_id
:
ast
::
NodeId
)
->
Option
<
CodeExtent
>
{
self
.param_env
()
.temporary_scope
(
rvalue_id
)
}
fn
upvar_borrow
(
&
self
,
upvar_id
:
ty
::
UpvarId
)
->
Option
<
ty
::
UpvarBorrow
>
{
self
.inh.upvar_borrow_map
.borrow
()
.get
(
&
upvar_id
)
.cloned
()
}
fn
capture_mode
(
&
self
,
closure_expr_id
:
ast
::
NodeId
)
->
ast
::
CaptureClause
{
self
.ccx.tcx
.capture_mode
(
closure_expr_id
)
fn
upvar_capture
(
&
self
,
upvar_id
:
ty
::
UpvarId
)
->
Option
<
ty
::
UpvarCapture
>
{
self
.inh.upvar_capture_map
.borrow
()
.get
(
&
upvar_id
)
.cloned
()
}
}
...
...
@@ -378,7 +374,7 @@ fn new(tcx: &'a ty::ctxt<'tcx>,
adjustments
:
RefCell
::
new
(
NodeMap
()),
method_map
:
RefCell
::
new
(
FnvHashMap
()),
object_cast_map
:
RefCell
::
new
(
NodeMap
()),
upvar_
borrow
_map
:
RefCell
::
new
(
FnvHashMap
()),
upvar_
capture
_map
:
RefCell
::
new
(
FnvHashMap
()),
closures
:
RefCell
::
new
(
DefIdMap
()),
fn_sig_map
:
RefCell
::
new
(
NodeMap
()),
fulfillment_cx
:
RefCell
::
new
(
traits
::
FulfillmentContext
::
new
()),
...
...
src/librustc_typeck/check/regionck.rs
浏览文件 @
2f29cdeb
...
...
@@ -742,16 +742,9 @@ fn check_expr_fn_block(rcx: &mut Rcx,
match
function_type
.sty
{
ty
::
ty_closure
(
_
,
region
,
_
)
=>
{
if
tcx
.capture_modes
.borrow
()[
expr
.id
]
.clone
()
==
ast
::
CaptureByRef
{
ty
::
with_freevars
(
tcx
,
expr
.id
,
|
freevars
|
{
if
!
freevars
.is_empty
()
{
// Variables being referenced must be constrained and registered
// in the upvar borrow map
constrain_free_variables_in_by_ref_closure
(
rcx
,
*
region
,
expr
,
freevars
);
}
})
}
ty
::
with_freevars
(
tcx
,
expr
.id
,
|
freevars
|
{
constrain_captured_variables
(
rcx
,
*
region
,
expr
,
freevars
);
})
}
_
=>
{
}
}
...
...
@@ -799,14 +792,14 @@ fn ensure_free_variable_types_outlive_closure_bound(
let
raw_var_ty
=
rcx
.resolve_node_type
(
var_node_id
);
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
var_node_id
,
closure_expr_id
:
expr
.id
};
let
var_ty
=
match
rcx
.fcx.inh.upvar_
borrow_map
.borrow
()
.get
(
&
upvar_id
)
{
Some
(
upvar_borrow
)
=>
{
let
var_ty
=
match
rcx
.fcx.inh.upvar_
capture_map
.borrow
()[
upvar_id
]
{
ty
::
UpvarCapture
::
ByRef
(
ref
upvar_borrow
)
=>
{
ty
::
mk_rptr
(
rcx
.tcx
(),
rcx
.tcx
()
.mk_region
(
upvar_borrow
.region
),
ty
::
mt
{
mutbl
:
upvar_borrow
.kind
.to_mutbl_lossy
(),
ty
:
raw_var_ty
})
}
None
=>
raw_var_ty
ty
::
UpvarCapture
::
ByValue
=>
raw_var_ty
,
};
// Check that the type meets the criteria of the existential bounds:
...
...
@@ -824,17 +817,17 @@ fn ensure_free_variable_types_outlive_closure_bound(
/// Make sure that all free variables referenced inside the closure outlive the closure's
/// lifetime bound. Also, create an entry in the upvar_borrows map with a region.
fn
constrain_
free_variables_in_by_ref_closure
(
fn
constrain_
captured_variables
(
rcx
:
&
mut
Rcx
,
region_bound
:
ty
::
Region
,
expr
:
&
ast
::
Expr
,
freevars
:
&
[
ty
::
Freevar
])
{
let
tcx
=
rcx
.fcx.ccx.tcx
;
debug!
(
"constrain_
free
_variables({}, {})"
,
debug!
(
"constrain_
captured
_variables({}, {})"
,
region_bound
.repr
(
tcx
),
expr
.repr
(
tcx
));
for
freevar
in
freevars
.iter
()
{
debug!
(
"
freevar def is
{:?}"
,
freevar
.def
);
debug!
(
"
constrain_captured_variables: freevar.def=
{:?}"
,
freevar
.def
);
// Identify the variable being closed over and its node-id.
let
def
=
freevar
.def
;
...
...
@@ -846,16 +839,20 @@ fn constrain_free_variables_in_by_ref_closure(
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
var_node_id
,
closure_expr_id
:
expr
.id
};
let
upvar_borrow
=
rcx
.fcx.inh.upvar_borrow_map
.borrow
()[
upvar_id
];
rcx
.fcx
.mk_subr
(
infer
::
FreeVariable
(
freevar
.span
,
var_node_id
),
region_bound
,
upvar_borrow
.region
);
// Guarantee that the closure does not outlive the variable itself.
let
enclosing_region
=
region_of_def
(
rcx
.fcx
,
def
);
debug!
(
"enclosing_region = {}"
,
enclosing_region
.repr
(
tcx
));
rcx
.fcx
.mk_subr
(
infer
::
FreeVariable
(
freevar
.span
,
var_node_id
),
region_bound
,
enclosing_region
);
match
rcx
.fcx.inh.upvar_capture_map
.borrow
()[
upvar_id
]
{
ty
::
UpvarCapture
::
ByValue
=>
{
}
ty
::
UpvarCapture
::
ByRef
(
upvar_borrow
)
=>
{
rcx
.fcx
.mk_subr
(
infer
::
FreeVariable
(
freevar
.span
,
var_node_id
),
region_bound
,
upvar_borrow
.region
);
// Guarantee that the closure does not outlive the variable itself.
let
enclosing_region
=
region_of_def
(
rcx
.fcx
,
def
);
debug!
(
"constrain_captured_variables: enclosing_region = {}"
,
enclosing_region
.repr
(
tcx
));
rcx
.fcx
.mk_subr
(
infer
::
FreeVariable
(
freevar
.span
,
var_node_id
),
region_bound
,
enclosing_region
);
}
}
}
}
}
...
...
@@ -1333,22 +1330,20 @@ fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
// Detect by-ref upvar `x`:
let
cause
=
match
note
{
mc
::
NoteUpvarRef
(
ref
upvar_id
)
=>
{
let
mut
upvar_borrow_map
=
rcx
.fcx.inh.upvar_borrow_map
.borrow_mut
();
match
upvar_borrow_map
.get_mut
(
upvar_id
)
{
Some
(
upvar_borrow
)
=>
{
let
upvar_capture_map
=
rcx
.fcx.inh.upvar_capture_map
.borrow_mut
();
match
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.
ref_kind
=
upvar_borrow
.kind
;
infer
::
ReborrowUpvar
(
span
,
*
upvar_id
)
}
None
=>
{
_
=>
{
rcx
.tcx
()
.sess
.span_bug
(
span
,
&
format!
(
"Illegal upvar id: {}"
,
upvar_id
.repr
(
rcx
.tcx
()))[]);
upvar_id
.repr
(
rcx
.tcx
()))[]);
}
}
}
...
...
src/librustc_typeck/check/upvar.rs
浏览文件 @
2f29cdeb
...
...
@@ -121,25 +121,29 @@ fn check_closure(&mut self,
capture_clause
:
ast
::
CaptureClause
,
_
body
:
&
ast
::
Block
)
{
match
capture_clause
{
ast
::
CaptureByValue
=>
{}
_
=>
{
ty
::
with_freevars
(
self
.tcx
(),
expr
.id
,
|
freevars
|
{
for
freevar
in
freevars
.iter
()
{
let
var_node_id
=
freevar
.def
.local_node_id
();
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
var_node_id
,
closure_expr_id
:
expr
.id
};
debug!
(
"seed upvar_id {:?}"
,
upvar_id
);
ty
::
with_freevars
(
self
.tcx
(),
expr
.id
,
|
freevars
|
{
for
freevar
in
freevars
.iter
()
{
let
var_node_id
=
freevar
.def
.local_node_id
();
let
upvar_id
=
ty
::
UpvarId
{
var_id
:
var_node_id
,
closure_expr_id
:
expr
.id
};
debug!
(
"seed upvar_id {:?}"
,
upvar_id
);
let
capture_kind
=
match
capture_clause
{
ast
::
CaptureByValue
=>
{
ty
::
UpvarCapture
::
ByValue
}
ast
::
CaptureByRef
=>
{
let
origin
=
UpvarRegion
(
upvar_id
,
expr
.span
);
let
freevar_region
=
self
.infcx
()
.next_region_var
(
origin
);
let
upvar_borrow
=
ty
::
UpvarBorrow
{
kind
:
ty
::
ImmBorrow
,
region
:
freevar_region
};
self
.fcx.inh.upvar_borrow_map
.borrow_mut
()
.insert
(
upvar_id
,
upvar_borrow
);
ty
::
UpvarCapture
::
ByRef
(
upvar_borrow
)
}
});
};
self
.fcx.inh.upvar_capture_map
.borrow_mut
()
.insert
(
upvar_id
,
capture_kind
);
}
}
}
);
}
}
...
...
@@ -150,7 +154,7 @@ struct AdjustBorrowKind<'a,'tcx:'a> {
fcx
:
&
'a
FnCtxt
<
'a
,
'tcx
>
}
impl
<
'a
,
'tcx
>
AdjustBorrowKind
<
'a
,
'tcx
>
{
impl
<
'a
,
'tcx
>
AdjustBorrowKind
<
'a
,
'tcx
>
{
fn
new
(
fcx
:
&
'a
FnCtxt
<
'a
,
'tcx
>
)
->
AdjustBorrowKind
<
'a
,
'tcx
>
{
AdjustBorrowKind
{
fcx
:
fcx
}
}
...
...
@@ -195,8 +199,8 @@ fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: mc::cmt<'tcx>) {
// upvar, then we need to modify the
// borrow_kind of the upvar to make sure it
// is inferred to mutable if necessary
let
mut
upvar_
borrow_map
=
self
.fcx.inh.upvar_borrow
_map
.borrow_mut
();
let
ub
=
&
mut
upvar_
borrow
_map
[
upvar_id
];
let
mut
upvar_
capture_map
=
self
.fcx.inh.upvar_capture
_map
.borrow_mut
();
let
ub
=
&
mut
upvar_
capture
_map
[
upvar_id
];
self
.adjust_upvar_borrow_kind
(
upvar_id
,
ub
,
ty
::
MutBorrow
);
}
else
{
// assignment to deref of an `&mut`
...
...
@@ -237,7 +241,7 @@ fn adjust_upvar_borrow_kind_for_unique(&self, cmt: mc::cmt<'tcx>) {
// upvar, then we need to modify the
// borrow_kind of the upvar to make sure it
// is inferred to unique if necessary
let
mut
ub
=
self
.fcx.inh.upvar_
borrow
_map
.borrow_mut
();
let
mut
ub
=
self
.fcx.inh.upvar_
capture
_map
.borrow_mut
();
let
ub
=
&
mut
ub
[
upvar_id
];
self
.adjust_upvar_borrow_kind
(
upvar_id
,
ub
,
ty
::
UniqueImmBorrow
);
}
else
{
...
...
@@ -262,23 +266,30 @@ fn adjust_upvar_borrow_kind_for_unique(&self, cmt: mc::cmt<'tcx>) {
/// some particular use.
fn
adjust_upvar_borrow_kind
(
&
self
,
upvar_id
:
ty
::
UpvarId
,
upvar_
borrow
:
&
mut
ty
::
UpvarBorrow
,
upvar_
capture
:
&
mut
ty
::
UpvarCapture
,
kind
:
ty
::
BorrowKind
)
{
debug!
(
"adjust_upvar_borrow_kind: id={:?} kind=({:?} -> {:?})"
,
upvar_id
,
upvar_borrow
.kind
,
kind
);
match
(
upvar_borrow
.kind
,
kind
)
{
// Take RHS:
(
ty
::
ImmBorrow
,
ty
::
UniqueImmBorrow
)
|
(
ty
::
ImmBorrow
,
ty
::
MutBorrow
)
|
(
ty
::
UniqueImmBorrow
,
ty
::
MutBorrow
)
=>
{
upvar_borrow
.kind
=
kind
;
debug!
(
"adjust_upvar_borrow_kind(upvar_id={:?}, upvar_capture={:?}, kind={:?})"
,
upvar_id
,
upvar_capture
,
kind
);
match
*
upvar_capture
{
ty
::
UpvarCapture
::
ByValue
=>
{
// Upvar is already by-value, the strongest criteria.
}
// Take LHS:
(
ty
::
ImmBorrow
,
ty
::
ImmBorrow
)
|
(
ty
::
UniqueImmBorrow
,
ty
::
ImmBorrow
)
|
(
ty
::
UniqueImmBorrow
,
ty
::
UniqueImmBorrow
)
|
(
ty
::
MutBorrow
,
_
)
=>
{
ty
::
UpvarCapture
::
ByRef
(
ref
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
;
}
// Take LHS:
(
ty
::
ImmBorrow
,
ty
::
ImmBorrow
)
|
(
ty
::
UniqueImmBorrow
,
ty
::
ImmBorrow
)
|
(
ty
::
UniqueImmBorrow
,
ty
::
UniqueImmBorrow
)
|
(
ty
::
MutBorrow
,
_
)
=>
{
}
}
}
}
}
...
...
src/librustc_typeck/check/writeback.rs
浏览文件 @
2f29cdeb
...
...
@@ -182,16 +182,20 @@ fn visit_upvar_borrow_map(&self) {
return
;
}
for
(
upvar_id
,
upvar_borrow
)
in
self
.fcx.inh.upvar_borrow_map
.borrow
()
.iter
()
{
let
r
=
upvar_borrow
.region
;
let
r
=
self
.resolve
(
&
r
,
ResolvingUpvar
(
*
upvar_id
));
let
new_upvar_borrow
=
ty
::
UpvarBorrow
{
kind
:
upvar_borrow
.kind
,
region
:
r
};
debug!
(
"Upvar borrow for {} resolved to {}"
,
for
(
upvar_id
,
upvar_capture
)
in
self
.fcx.inh.upvar_capture_map
.borrow
()
.iter
()
{
let
new_upvar_capture
=
match
*
upvar_capture
{
ty
::
UpvarCapture
::
ByValue
=>
ty
::
UpvarCapture
::
ByValue
,
ty
::
UpvarCapture
::
ByRef
(
ref
upvar_borrow
)
=>
{
let
r
=
upvar_borrow
.region
;
let
r
=
self
.resolve
(
&
r
,
ResolvingUpvar
(
*
upvar_id
));
ty
::
UpvarCapture
::
ByRef
(
ty
::
UpvarBorrow
{
kind
:
upvar_borrow
.kind
,
region
:
r
})
}
};
debug!
(
"Upvar capture for {} resolved to {}"
,
upvar_id
.repr
(
self
.tcx
()),
new_upvar_borrow
.repr
(
self
.tcx
()));
self
.fcx
.tcx
()
.upvar_borrow_map
.borrow_mut
()
.insert
(
*
upvar_id
,
new_upvar_borrow
);
new_upvar_capture
.repr
(
self
.tcx
()));
self
.fcx
.tcx
()
.upvar_capture_map
.borrow_mut
()
.insert
(
*
upvar_id
,
new_upvar_capture
);
}
}
...
...
src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs
浏览文件 @
2f29cdeb
...
...
@@ -58,8 +58,10 @@ fn test6() {
fn
test7
()
{
fn
foo
<
F
>
(
_
:
F
)
where
F
:
FnMut
(
Box
<
FnMut
(
isize
)
>
,
isize
)
{}
let
mut
f
=
|
&
mut
:
g
:
Box
<
FnMut
(
isize
)
>
,
b
:
isize
|
{};
f
(
box
|
a
|
{
//~ ERROR: cannot borrow `f` as immutable because it is also borrowed as mutable
foo
(
f
);
//~ ERROR: cannot move out of captured outer variable
f
(
box
|
a
|
{
foo
(
f
);
//~^ ERROR cannot move `f` into closure because it is borrowed
//~| ERROR cannot move out of captured outer variable in an `FnMut` closure
},
3
);
}
...
...
src/test/compile-fail/unboxed-closure-illegal-move.rs
浏览文件 @
2f29cdeb
...
...
@@ -19,24 +19,24 @@ fn main() {
// By-ref cases
{
let
x
=
box
0u
s
;
let
f
=
|
&
:|
drop
(
x
);
//~ cannot move
let
f
=
|
&
:|
drop
(
x
);
//~
ERROR
cannot move
}
{
let
x
=
box
0u
s
;
let
f
=
|
&
mut
:|
drop
(
x
);
//~ cannot move
let
f
=
|
&
mut
:|
drop
(
x
);
//~
ERROR
cannot move
}
{
let
x
=
box
0u
s
;
let
f
=
|:|
drop
(
x
);
//
~ cannot mov
e
let
f
=
|:|
drop
(
x
);
//
OK -- FnOnc
e
}
// By-value cases
{
let
x
=
box
0u
s
;
let
f
=
move
|
&
:|
drop
(
x
);
//~ cannot move
let
f
=
move
|
&
:|
drop
(
x
);
//~
ERROR
cannot move
}
{
let
x
=
box
0u
s
;
let
f
=
move
|
&
mut
:|
drop
(
x
);
//~ cannot move
let
f
=
move
|
&
mut
:|
drop
(
x
);
//~
ERROR
cannot move
}
{
let
x
=
box
0u
s
;
...
...
src/test/compile-fail/unboxed-closures-mutate-upvar.rs
0 → 100644
浏览文件 @
2f29cdeb
// Copyright 2015 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.
// Test that we cannot mutate an outer variable that is not declared
// as `mut` through a closure. Also test that we CAN mutate a moved copy,
// unless this is a `Fn` closure. Issue #16749.
use
std
::
mem
;
fn
a
()
{
let
n
=
0u8
;
let
mut
f
=
|
&
mut
:|
{
//~ ERROR closure cannot assign
n
+=
1
;
};
}
fn
b
()
{
let
mut
n
=
0u8
;
let
mut
f
=
|
&
mut
:|
{
n
+=
1
;
// OK
};
}
fn
c
()
{
let
n
=
0u8
;
let
mut
f
=
move
|
&
mut
:|
{
// If we just did a straight-forward desugaring, this would
// compile, but we do something a bit more subtle, and hence
// we get an error.
n
+=
1
;
//~ ERROR cannot assign
};
}
fn
d
()
{
let
mut
n
=
0u8
;
let
mut
f
=
move
|
&
mut
:|
{
n
+=
1
;
// OK
};
}
fn
e
()
{
let
n
=
0u8
;
let
mut
f
=
move
|
&
:|
{
n
+=
1
;
//~ ERROR cannot assign
};
}
fn
f
()
{
let
mut
n
=
0u8
;
let
mut
f
=
move
|
&
:|
{
n
+=
1
;
//~ ERROR cannot assign
};
}
fn
main
()
{
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录