Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
2c6b0e5c
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,发现更多精彩内容 >>
未验证
提交
2c6b0e5c
编写于
8月 07, 2018
作者:
D
David Wood
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Label definition of captured variables in errors.
上级
51b0552b
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
95 addition
and
63 deletion
+95
-63
src/librustc/mir/tcx.rs
src/librustc/mir/tcx.rs
+22
-5
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/mod.rs
+1
-1
src/librustc_mir/borrow_check/move_errors.rs
src/librustc_mir/borrow_check/move_errors.rs
+51
-23
src/librustc_mir/borrow_check/mutability_errors.rs
src/librustc_mir/borrow_check/mutability_errors.rs
+3
-27
src/librustc_mir/dataflow/move_paths/builder.rs
src/librustc_mir/dataflow/move_paths/builder.rs
+9
-6
src/librustc_mir/dataflow/move_paths/mod.rs
src/librustc_mir/dataflow/move_paths/mod.rs
+1
-1
src/test/ui/borrowck/borrowck-in-static.nll.stderr
src/test/ui/borrowck/borrowck-in-static.nll.stderr
+2
-0
src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.nll.stderr
...-closures-move-upvar-from-non-once-ref-closure.nll.stderr
+3
-0
src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
...st/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
+3
-0
未找到文件。
src/librustc/mir/tcx.rs
浏览文件 @
2c6b0e5c
...
...
@@ -127,14 +127,14 @@ pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> P
/// of a closure type.
pub
fn
is_upvar_field_projection
<
'cx
,
'gcx
>
(
&
self
,
mir
:
&
'cx
Mir
<
'tcx
>
,
tcx
:
&
TyCtxt
<
'cx
,
'gcx
,
'tcx
>
)
->
Option
<
Field
>
{
let
place
=
if
let
Place
::
Projection
(
ref
proj
)
=
self
{
let
(
place
,
by_ref
)
=
if
let
Place
::
Projection
(
ref
proj
)
=
self
{
if
let
ProjectionElem
::
Deref
=
proj
.elem
{
&
proj
.base
(
&
proj
.base
,
true
)
}
else
{
self
(
self
,
false
)
}
}
else
{
self
(
self
,
false
)
};
match
place
{
...
...
@@ -142,7 +142,9 @@ pub fn is_upvar_field_projection<'cx, 'gcx>(&self, mir: &'cx Mir<'tcx>,
ProjectionElem
::
Field
(
field
,
_
ty
)
=>
{
let
base_ty
=
proj
.base
.ty
(
mir
,
*
tcx
)
.to_ty
(
*
tcx
);
if
base_ty
.is_closure
()
||
base_ty
.is_generator
()
{
if
(
base_ty
.is_closure
()
||
base_ty
.is_generator
())
&&
(
!
by_ref
||
mir
.upvar_decls
[
field
.index
()]
.by_ref
)
{
Some
(
field
)
}
else
{
None
...
...
@@ -153,6 +155,21 @@ pub fn is_upvar_field_projection<'cx, 'gcx>(&self, mir: &'cx Mir<'tcx>,
_
=>
None
,
}
}
/// Strip the deref projections from a `Place`. For example, given `(*(*((*_1).0: &&T)))`, this
/// will return `((*_1).0)`. Once stripped of any deref projections, places can then be
/// checked as upvar field projections using `is_upvar_field_projection`.
pub
fn
strip_deref_projections
(
&
self
)
->
&
Place
<
'tcx
>
{
let
mut
current
=
self
;
while
let
Place
::
Projection
(
ref
proj
)
=
current
{
if
let
ProjectionElem
::
Deref
=
proj
.elem
{
current
=
&
proj
.base
;
}
else
{
break
;
}
}
current
}
}
pub
enum
RvalueInitializationState
{
...
...
src/librustc_mir/borrow_check/mod.rs
浏览文件 @
2c6b0e5c
...
...
@@ -151,7 +151,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
let
location_table
=
&
LocationTable
::
new
(
mir
);
let
mut
errors_buffer
=
Vec
::
new
();
let
(
move_data
,
move_errors
):
(
MoveData
<
'tcx
>
,
Option
<
Vec
<
MoveError
<
'tcx
>
>>
)
=
let
(
move_data
,
move_errors
):
(
MoveData
<
'tcx
>
,
Option
<
Vec
<
(
Place
<
'tcx
>
,
MoveError
<
'tcx
>
)
>>
)
=
match
MoveData
::
gather_moves
(
mir
,
tcx
)
{
Ok
(
move_data
)
=>
(
move_data
,
None
),
Err
((
move_data
,
move_errors
))
=>
(
move_data
,
Some
(
move_errors
)),
...
...
src/librustc_mir/borrow_check/move_errors.rs
浏览文件 @
2c6b0e5c
...
...
@@ -11,8 +11,8 @@
use
rustc
::
hir
;
use
rustc
::
mir
::
*
;
use
rustc
::
ty
;
use
rustc_data_structures
::
indexed_vec
::
Idx
;
use
rustc_errors
::
DiagnosticBuilder
;
use
rustc_data_structures
::
indexed_vec
::
Idx
;
use
syntax_pos
::
Span
;
use
borrow_check
::
MirBorrowckCtxt
;
...
...
@@ -38,6 +38,7 @@ enum GroupedMoveError<'tcx> {
// Match place can't be moved from
// e.g. match x[0] { s => (), } where x: &[String]
MovesFromMatchPlace
{
original_path
:
Place
<
'tcx
>
,
span
:
Span
,
move_from
:
Place
<
'tcx
>
,
kind
:
IllegalMoveOriginKind
<
'tcx
>
,
...
...
@@ -46,6 +47,7 @@ enum GroupedMoveError<'tcx> {
// Part of a pattern can't be moved from,
// e.g. match &String::new() { &x => (), }
MovesFromPattern
{
original_path
:
Place
<
'tcx
>
,
span
:
Span
,
move_from
:
MovePathIndex
,
kind
:
IllegalMoveOriginKind
<
'tcx
>
,
...
...
@@ -53,23 +55,27 @@ enum GroupedMoveError<'tcx> {
},
// Everything that isn't from pattern matching.
OtherIllegalMove
{
original_path
:
Place
<
'tcx
>
,
span
:
Span
,
kind
:
IllegalMoveOriginKind
<
'tcx
>
,
},
}
impl
<
'a
,
'gcx
,
'tcx
>
MirBorrowckCtxt
<
'a
,
'gcx
,
'tcx
>
{
pub
(
crate
)
fn
report_move_errors
(
&
mut
self
,
move_errors
:
Vec
<
MoveError
<
'tcx
>
>
)
{
pub
(
crate
)
fn
report_move_errors
(
&
mut
self
,
move_errors
:
Vec
<
(
Place
<
'tcx
>
,
MoveError
<
'tcx
>
)
>
)
{
let
grouped_errors
=
self
.group_move_errors
(
move_errors
);
for
error
in
grouped_errors
{
self
.report
(
error
);
}
}
fn
group_move_errors
(
&
self
,
errors
:
Vec
<
MoveError
<
'tcx
>>
)
->
Vec
<
GroupedMoveError
<
'tcx
>>
{
fn
group_move_errors
(
&
self
,
errors
:
Vec
<
(
Place
<
'tcx
>
,
MoveError
<
'tcx
>
)
>
)
->
Vec
<
GroupedMoveError
<
'tcx
>>
{
let
mut
grouped_errors
=
Vec
::
new
();
for
error
in
errors
{
self
.append_to_grouped_errors
(
&
mut
grouped_errors
,
error
);
for
(
original_path
,
error
)
in
errors
{
self
.append_to_grouped_errors
(
&
mut
grouped_errors
,
original_path
,
error
);
}
grouped_errors
}
...
...
@@ -77,6 +83,7 @@ fn group_move_errors(&self, errors: Vec<MoveError<'tcx>>) -> Vec<GroupedMoveErro
fn
append_to_grouped_errors
(
&
self
,
grouped_errors
:
&
mut
Vec
<
GroupedMoveError
<
'tcx
>>
,
original_path
:
Place
<
'tcx
>
,
error
:
MoveError
<
'tcx
>
,
)
{
match
error
{
...
...
@@ -116,6 +123,7 @@ fn append_to_grouped_errors(
self
.append_binding_error
(
grouped_errors
,
kind
,
original_path
,
move_from
,
*
local
,
opt_match_place
,
...
...
@@ -127,6 +135,7 @@ fn append_to_grouped_errors(
}
grouped_errors
.push
(
GroupedMoveError
::
OtherIllegalMove
{
span
:
stmt_source_info
.span
,
original_path
,
kind
,
});
}
...
...
@@ -137,6 +146,7 @@ fn append_binding_error(
&
self
,
grouped_errors
:
&
mut
Vec
<
GroupedMoveError
<
'tcx
>>
,
kind
:
IllegalMoveOriginKind
<
'tcx
>
,
original_path
:
Place
<
'tcx
>
,
move_from
:
&
Place
<
'tcx
>
,
bind_to
:
Local
,
match_place
:
&
Option
<
Place
<
'tcx
>>
,
...
...
@@ -176,6 +186,7 @@ fn append_binding_error(
grouped_errors
.push
(
GroupedMoveError
::
MovesFromMatchPlace
{
span
,
move_from
:
match_place
.clone
(),
original_path
,
kind
,
binds_to
,
});
...
...
@@ -206,6 +217,7 @@ fn append_binding_error(
grouped_errors
.push
(
GroupedMoveError
::
MovesFromPattern
{
span
:
match_span
,
move_from
:
mpi
,
original_path
,
kind
,
binds_to
:
vec!
[
bind_to
],
});
...
...
@@ -215,13 +227,23 @@ fn append_binding_error(
fn
report
(
&
mut
self
,
error
:
GroupedMoveError
<
'tcx
>
)
{
let
(
mut
err
,
err_span
)
=
{
let
(
span
,
kind
):
(
Span
,
&
IllegalMoveOriginKind
)
=
match
error
{
GroupedMoveError
::
MovesFromMatchPlace
{
span
,
ref
kind
,
..
}
|
GroupedMoveError
::
MovesFromPattern
{
span
,
ref
kind
,
..
}
|
GroupedMoveError
::
OtherIllegalMove
{
span
,
ref
kind
}
=>
(
span
,
kind
),
};
let
(
span
,
original_path
,
kind
):
(
Span
,
&
Place
<
'tcx
>
,
&
IllegalMoveOriginKind
)
=
match
error
{
GroupedMoveError
::
MovesFromMatchPlace
{
span
,
ref
original_path
,
ref
kind
,
..
}
|
GroupedMoveError
::
MovesFromPattern
{
span
,
ref
original_path
,
ref
kind
,
..
}
|
GroupedMoveError
::
OtherIllegalMove
{
span
,
ref
original_path
,
ref
kind
}
=>
{
(
span
,
original_path
,
kind
)
},
};
let
origin
=
Origin
::
Mir
;
debug!
(
"report: span={:?}, kind={:?}"
,
span
,
kind
);
debug!
(
"report: original_path={:?} span={:?}, kind={:?}
\
original_path.is_upvar_field_projection={:?}"
,
original_path
,
span
,
kind
,
original_path
.is_upvar_field_projection
(
self
.mir
,
&
self
.tcx
));
(
match
kind
{
IllegalMoveOriginKind
::
Static
=>
{
...
...
@@ -237,17 +259,11 @@ fn report(&mut self, error: GroupedMoveError<'tcx>) {
.tcx
.cannot_move_out_of_interior_noncopy
(
span
,
ty
,
None
,
origin
),
ty
::
TyClosure
(
def_id
,
closure_substs
)
if
!
self
.mir.upvar_decls
.is_empty
()
&&
{
match
place
{
Place
::
Projection
(
ref
proj
)
=>
{
proj
.base
==
Place
::
Local
(
Local
::
new
(
1
))
}
Place
::
Promoted
(
_
)
|
Place
::
Local
(
_
)
|
Place
::
Static
(
_
)
=>
unreachable!
(),
}
}
=>
{
if
!
self
.mir.upvar_decls
.is_empty
()
&&
original_path
.strip_deref_projections
()
.is_upvar_field_projection
(
self
.mir
,
&
self
.tcx
)
.is_some
()
=>
{
let
closure_kind_ty
=
closure_substs
.closure_kind_ty
(
def_id
,
self
.tcx
);
let
closure_kind
=
closure_kind_ty
.to_opt_closure_kind
();
...
...
@@ -267,7 +283,19 @@ fn report(&mut self, error: GroupedMoveError<'tcx>) {
place_description={:?}"
,
closure_kind_ty
,
closure_kind
,
place_description
);
self
.tcx
.cannot_move_out_of
(
span
,
place_description
,
origin
)
let
mut
diag
=
self
.tcx
.cannot_move_out_of
(
span
,
place_description
,
origin
);
if
let
Some
(
field
)
=
original_path
.is_upvar_field_projection
(
self
.mir
,
&
self
.tcx
)
{
let
upvar_decl
=
&
self
.mir.upvar_decls
[
field
.index
()];
let
upvar_hir_id
=
upvar_decl
.var_hir_id
.assert_crate_local
();
let
upvar_node_id
=
self
.tcx.hir
.hir_to_node_id
(
upvar_hir_id
);
let
upvar_span
=
self
.tcx.hir
.span
(
upvar_node_id
);
diag
.span_label
(
upvar_span
,
"captured outer variable"
);
}
diag
}
_
=>
self
.tcx
...
...
src/librustc_mir/borrow_check/mutability_errors.rs
浏览文件 @
2c6b0e5c
...
...
@@ -71,7 +71,7 @@ pub(super) fn report_mutability_error(
));
item_msg
=
format!
(
"`{}`"
,
access_place_desc
.unwrap
());
if
self
.is_upvar
(
access_place
)
{
if
access_place
.is_upvar_field_projection
(
self
.mir
,
&
self
.tcx
)
.is_some
(
)
{
reason
=
", as it is not declared as mutable"
.to_string
();
}
else
{
let
name
=
self
.mir.upvar_decls
[
upvar_index
.index
()]
.debug_name
;
...
...
@@ -90,7 +90,8 @@ pub(super) fn report_mutability_error(
the_place_err
.ty
(
self
.mir
,
self
.tcx
)
.to_ty
(
self
.tcx
)
));
reason
=
if
self
.is_upvar
(
access_place
)
{
reason
=
if
access_place
.is_upvar_field_projection
(
self
.mir
,
&
self
.tcx
)
.is_some
()
{
", as it is a captured variable in a `Fn` closure"
.to_string
()
}
else
{
", as `Fn` closures cannot mutate their captured variables"
.to_string
()
...
...
@@ -394,31 +395,6 @@ pub(super) fn report_mutability_error(
err
.buffer
(
&
mut
self
.errors_buffer
);
}
// Does this place refer to what the user sees as an upvar
fn
is_upvar
(
&
self
,
place
:
&
Place
<
'tcx
>
)
->
bool
{
match
*
place
{
Place
::
Projection
(
box
Projection
{
ref
base
,
elem
:
ProjectionElem
::
Field
(
_
,
_
),
})
=>
{
let
base_ty
=
base
.ty
(
self
.mir
,
self
.tcx
)
.to_ty
(
self
.tcx
);
is_closure_or_generator
(
base_ty
)
}
Place
::
Projection
(
box
Projection
{
base
:
Place
::
Projection
(
box
Projection
{
ref
base
,
elem
:
ProjectionElem
::
Field
(
upvar_index
,
_
),
}),
elem
:
ProjectionElem
::
Deref
,
})
=>
{
let
base_ty
=
base
.ty
(
self
.mir
,
self
.tcx
)
.to_ty
(
self
.tcx
);
is_closure_or_generator
(
base_ty
)
&&
self
.mir.upvar_decls
[
upvar_index
.index
()]
.by_ref
}
_
=>
false
,
}
}
}
fn
suggest_ampmut_self
<
'cx
,
'gcx
,
'tcx
>
(
...
...
src/librustc_mir/dataflow/move_paths/builder.rs
浏览文件 @
2c6b0e5c
...
...
@@ -27,7 +27,7 @@ struct MoveDataBuilder<'a, 'gcx: 'tcx, 'tcx: 'a> {
mir
:
&
'a
Mir
<
'tcx
>
,
tcx
:
TyCtxt
<
'a
,
'gcx
,
'tcx
>
,
data
:
MoveData
<
'tcx
>
,
errors
:
Vec
<
MoveError
<
'tcx
>
>
,
errors
:
Vec
<
(
Place
<
'tcx
>
,
MoveError
<
'tcx
>
)
>
,
}
impl
<
'a
,
'gcx
,
'tcx
>
MoveDataBuilder
<
'a
,
'gcx
,
'tcx
>
{
...
...
@@ -186,7 +186,9 @@ fn move_path_for_projection(&mut self,
}
impl
<
'a
,
'gcx
,
'tcx
>
MoveDataBuilder
<
'a
,
'gcx
,
'tcx
>
{
fn
finalize
(
self
)
->
Result
<
MoveData
<
'tcx
>
,
(
MoveData
<
'tcx
>
,
Vec
<
MoveError
<
'tcx
>>
)
>
{
fn
finalize
(
self
)
->
Result
<
MoveData
<
'tcx
>
,
(
MoveData
<
'tcx
>
,
Vec
<
(
Place
<
'tcx
>
,
MoveError
<
'tcx
>
)
>
)
>
{
debug!
(
"{}"
,
{
debug!
(
"moves for {:?}:"
,
self
.mir.span
);
for
(
j
,
mo
)
in
self
.data.moves
.iter_enumerated
()
{
...
...
@@ -207,9 +209,10 @@ fn finalize(self) -> Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<MoveError<'tcx>
}
}
pub
(
super
)
fn
gather_moves
<
'a
,
'gcx
,
'tcx
>
(
mir
:
&
Mir
<
'tcx
>
,
tcx
:
TyCtxt
<
'a
,
'gcx
,
'tcx
>
)
->
Result
<
MoveData
<
'tcx
>
,
(
MoveData
<
'tcx
>
,
Vec
<
MoveError
<
'tcx
>>
)
>
{
pub
(
super
)
fn
gather_moves
<
'a
,
'gcx
,
'tcx
>
(
mir
:
&
Mir
<
'tcx
>
,
tcx
:
TyCtxt
<
'a
,
'gcx
,
'tcx
>
)
->
Result
<
MoveData
<
'tcx
>
,
(
MoveData
<
'tcx
>
,
Vec
<
(
Place
<
'tcx
>
,
MoveError
<
'tcx
>
)
>
)
>
{
let
mut
builder
=
MoveDataBuilder
::
new
(
mir
,
tcx
);
builder
.gather_args
();
...
...
@@ -407,7 +410,7 @@ fn gather_move(&mut self, place: &Place<'tcx>) {
let
path
=
match
self
.move_path_for
(
place
)
{
Ok
(
path
)
|
Err
(
MoveError
::
UnionMove
{
path
})
=>
path
,
Err
(
error
@
MoveError
::
IllegalMove
{
..
})
=>
{
self
.builder.errors
.push
(
error
);
self
.builder.errors
.push
(
(
place
.clone
(),
error
)
);
return
;
}
};
...
...
src/librustc_mir/dataflow/move_paths/mod.rs
浏览文件 @
2c6b0e5c
...
...
@@ -313,7 +313,7 @@ fn cannot_move_out_of(location: Location, kind: IllegalMoveOriginKind<'tcx>) ->
impl
<
'a
,
'gcx
,
'tcx
>
MoveData
<
'tcx
>
{
pub
fn
gather_moves
(
mir
:
&
Mir
<
'tcx
>
,
tcx
:
TyCtxt
<
'a
,
'gcx
,
'tcx
>
)
->
Result
<
Self
,
(
Self
,
Vec
<
MoveError
<
'tcx
>
>
)
>
{
->
Result
<
Self
,
(
Self
,
Vec
<
(
Place
<
'tcx
>
,
MoveError
<
'tcx
>
)
>
)
>
{
builder
::
gather_moves
(
mir
,
tcx
)
}
}
src/test/ui/borrowck/borrowck-in-static.nll.stderr
浏览文件 @
2c6b0e5c
error[E0507]: cannot move out of captured variable in an `Fn` closure
--> $DIR/borrowck-in-static.rs:15:17
|
LL | let x = Box::new(0);
| - captured outer variable
LL | Box::new(|| x) //~ ERROR cannot move out of captured outer variable
| ^ cannot move out of captured variable in an `Fn` closure
...
...
src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.nll.stderr
浏览文件 @
2c6b0e5c
error[E0507]: cannot move out of captured variable in an `Fn` closure
--> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:21:9
|
LL | let y = vec![format!("World")];
| - captured outer variable
LL | call(|| {
LL | y.into_iter();
| ^ cannot move out of captured variable in an `Fn` closure
...
...
src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
浏览文件 @
2c6b0e5c
...
...
@@ -31,6 +31,9 @@ LL | f.f.call_mut(())
error[E0507]: cannot move out of captured variable in an `FnMut` closure
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13
|
LL | let mut f = move |g: Box<FnMut(isize)>, b: isize| {
| ----- captured outer variable
...
LL | foo(f);
| ^ cannot move out of captured variable in an `FnMut` closure
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录