Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
d3e9881e
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,发现更多精彩内容 >>
提交
d3e9881e
编写于
11月 11, 2017
作者:
S
Shotaro Yamada
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
MIR-borrowck: fix diagnostics for closures
上级
45caff88
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
301 addition
and
9 deletion
+301
-9
src/librustc/hir/mod.rs
src/librustc/hir/mod.rs
+1
-1
src/librustc/mir/mod.rs
src/librustc/mir/mod.rs
+2
-2
src/librustc_mir/borrow_check.rs
src/librustc_mir/borrow_check.rs
+90
-6
src/test/ui/borrowck/borrowck-closures-two-mut.rs
src/test/ui/borrowck/borrowck-closures-two-mut.rs
+62
-0
src/test/ui/borrowck/borrowck-closures-two-mut.stderr
src/test/ui/borrowck/borrowck-closures-two-mut.stderr
+146
-0
未找到文件。
src/librustc/hir/mod.rs
浏览文件 @
d3e9881e
...
...
@@ -1949,7 +1949,7 @@ pub fn descriptive_variant(&self) -> &str {
}
/// A free variable referred to in a function.
#[derive(Copy,
Clone,
RustcEncodable,
RustcDecodable)]
#[derive(
Debug,
Copy,
Clone,
RustcEncodable,
RustcDecodable)]
pub
struct
Freevar
{
/// The variable being accessed free.
pub
def
:
Def
,
...
...
src/librustc/mir/mod.rs
浏览文件 @
d3e9881e
...
...
@@ -267,10 +267,10 @@ pub fn source_info(&self, location: Location) -> &SourceInfo {
let
block
=
&
self
[
location
.block
];
let
stmts
=
&
block
.statements
;
let
idx
=
location
.statement_index
;
if
location
.statement_inde
x
<
stmts
.len
()
{
if
id
x
<
stmts
.len
()
{
&
stmts
[
idx
]
.source_info
}
else
{
assert
!
(
location
.statement_inde
x
==
stmts
.len
());
assert
!
(
id
x
==
stmts
.len
());
&
block
.terminator
()
.source_info
}
}
...
...
src/librustc_mir/borrow_check.rs
浏览文件 @
d3e9881e
...
...
@@ -1169,8 +1169,70 @@ fn report_use_while_mutably_borrowed(&mut self,
err
.emit
();
}
/// Finds the span of arguments of aclosure (within `maybe_closure_span`) and its usage of
/// the local assigned at `location`.
fn
find_closure_span
(
&
self
,
maybe_closure_span
:
Span
,
location
:
Location
,
)
->
Option
<
(
Span
,
Span
)
>
{
use
rustc
::
hir
::
ExprClosure
;
use
rustc
::
mir
::
AggregateKind
;
let
local
=
if
let
StatementKind
::
Assign
(
Lvalue
::
Local
(
local
),
_
)
=
self
.mir
[
location
.block
]
.statements
[
location
.statement_index
]
.kind
{
local
}
else
{
return
None
;
};
for
stmt
in
&
self
.mir
[
location
.block
]
.statements
[
location
.statement_index
+
1
..
]
{
if
maybe_closure_span
!=
stmt
.source_info.span
{
break
;
}
if
let
StatementKind
::
Assign
(
_
,
Rvalue
::
Aggregate
(
ref
kind
,
ref
lvs
))
=
stmt
.kind
{
if
let
AggregateKind
::
Closure
(
def_id
,
_
)
=
**
kind
{
debug!
(
"find_closure_span: found closure {:?}"
,
lvs
);
return
if
let
Some
(
node_id
)
=
self
.tcx.hir
.as_local_node_id
(
def_id
)
{
let
args_span
=
if
let
ExprClosure
(
_
,
_
,
_
,
span
,
_
)
=
self
.tcx.hir
.expect_expr
(
node_id
)
.node
{
span
}
else
{
return
None
;
};
self
.tcx
.with_freevars
(
node_id
,
|
freevars
|
{
for
(
v
,
lv
)
in
freevars
.iter
()
.zip
(
lvs
)
{
if
let
Operand
::
Consume
(
Lvalue
::
Local
(
l
))
=
*
lv
{
if
local
==
l
{
debug!
(
"find_closure_span: found captured local {:?}"
,
l
);
return
Some
(
v
.span
);
}
}
}
None
})
.map
(|
var_span
|
(
args_span
,
var_span
))
}
else
{
None
};
}
}
}
None
}
fn
report_conflicting_borrow
(
&
mut
self
,
_
context
:
Context
,
context
:
Context
,
common_prefix
:
&
Lvalue
,
(
lvalue
,
span
):
(
&
Lvalue
,
Span
),
gen_borrow_kind
:
BorrowKind
,
...
...
@@ -1183,38 +1245,60 @@ fn report_conflicting_borrow(&mut self,
let
issued_span
=
self
.retrieve_borrow_span
(
issued_borrow
);
let
new_closure_span
=
self
.find_closure_span
(
span
,
context
.loc
);
let
span
=
new_closure_span
.map
(|(
args
,
_
)|
args
)
.unwrap_or
(
span
);
let
old_closure_span
=
self
.find_closure_span
(
issued_span
,
issued_borrow
.location
);
let
issued_span
=
old_closure_span
.map
(|(
args
,
_
)|
args
)
.unwrap_or
(
issued_span
);
let
desc_lvalue
=
self
.describe_lvalue
(
lvalue
);
// FIXME: supply non-"" `opt_via` when appropriate
let
mut
err
=
match
(
gen_borrow_kind
,
"immutable"
,
"mutable"
,
issued_borrow
.kind
,
"immutable"
,
"mutable"
)
{
(
BorrowKind
::
Shared
,
lft
,
_
,
BorrowKind
::
Mut
,
_
,
rgt
)
|
(
BorrowKind
::
Mut
,
_
,
lft
,
BorrowKind
::
Shared
,
rgt
,
_
)
=>
self
.tcx
.cannot_reborrow_already_borrowed
(
span
,
&
self
.describe_lvalue
(
lvalue
)
,
""
,
lft
,
issued_span
,
span
,
&
desc_lvalue
,
""
,
lft
,
issued_span
,
"it"
,
rgt
,
""
,
end_issued_loan_span
,
Origin
::
Mir
),
(
BorrowKind
::
Mut
,
_
,
_
,
BorrowKind
::
Mut
,
_
,
_
)
=>
self
.tcx
.cannot_mutably_borrow_multiply
(
span
,
&
self
.describe_lvalue
(
lvalue
)
,
""
,
issued_span
,
span
,
&
desc_lvalue
,
""
,
issued_span
,
""
,
end_issued_loan_span
,
Origin
::
Mir
),
(
BorrowKind
::
Unique
,
_
,
_
,
BorrowKind
::
Unique
,
_
,
_
)
=>
self
.tcx
.cannot_uniquely_borrow_by_two_closures
(
span
,
&
self
.describe_lvalue
(
lvalue
)
,
issued_span
,
span
,
&
desc_lvalue
,
issued_span
,
end_issued_loan_span
,
Origin
::
Mir
),
(
BorrowKind
::
Unique
,
_
,
_
,
_
,
_
,
_
)
=>
self
.tcx
.cannot_uniquely_borrow_by_one_closure
(
span
,
&
self
.describe_lvalue
(
lvalue
)
,
""
,
span
,
&
desc_lvalue
,
""
,
issued_span
,
"it"
,
""
,
end_issued_loan_span
,
Origin
::
Mir
),
(
_
,
_
,
_
,
BorrowKind
::
Unique
,
_
,
_
)
=>
self
.tcx
.cannot_reborrow_already_uniquely_borrowed
(
span
,
&
self
.describe_lvalue
(
lvalue
)
,
"it"
,
""
,
span
,
&
desc_lvalue
,
"it"
,
""
,
issued_span
,
""
,
end_issued_loan_span
,
Origin
::
Mir
),
(
BorrowKind
::
Shared
,
_
,
_
,
BorrowKind
::
Shared
,
_
,
_
)
=>
unreachable!
(),
};
if
let
Some
((
_
,
var_span
))
=
old_closure_span
{
err
.span_label
(
var_span
,
format!
(
"previous borrow occurs due to use of `{}` in closure"
,
desc_lvalue
),
);
}
if
let
Some
((
_
,
var_span
))
=
new_closure_span
{
err
.span_label
(
var_span
,
format!
(
"borrow occurs due to use of `{}` in closure"
,
desc_lvalue
),
);
}
err
.emit
();
}
...
...
src/test/ui/borrowck/borrowck-closures-two-mut.rs
0 → 100644
浏览文件 @
d3e9881e
// Copyright 2014 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.
// Tests that two closures cannot simultaneously have mutable
// access to the variable, whether that mutable access be used
// for direct assignment or for taking mutable ref. Issue #6801.
// compile-flags: -Z emit-end-regions -Z borrowck-mir
#![feature(box_syntax)]
fn
to_fn_mut
<
F
:
FnMut
()
>
(
f
:
F
)
->
F
{
f
}
fn
a
()
{
let
mut
x
=
3
;
let
c1
=
to_fn_mut
(||
x
=
4
);
let
c2
=
to_fn_mut
(||
x
=
5
);
//~ ERROR cannot borrow `x` as mutable more than once
}
fn
set
(
x
:
&
mut
isize
)
{
*
x
=
4
;
}
fn
b
()
{
let
mut
x
=
3
;
let
c1
=
to_fn_mut
(||
set
(
&
mut
x
));
let
c2
=
to_fn_mut
(||
set
(
&
mut
x
));
//~ ERROR cannot borrow `x` as mutable more than once
}
fn
c
()
{
let
mut
x
=
3
;
let
c1
=
to_fn_mut
(||
x
=
5
);
let
c2
=
to_fn_mut
(||
set
(
&
mut
x
));
//~ ERROR cannot borrow `x` as mutable more than once
}
fn
d
()
{
let
mut
x
=
3
;
let
c1
=
to_fn_mut
(||
x
=
5
);
let
c2
=
to_fn_mut
(||
{
let
_
y
=
to_fn_mut
(||
set
(
&
mut
x
));
});
// (nested closure)
//~^ ERROR cannot borrow `x` as mutable more than once
}
fn
g
()
{
struct
Foo
{
f
:
Box
<
isize
>
}
let
mut
x
:
Box
<
_
>
=
box
Foo
{
f
:
box
3
};
let
c1
=
to_fn_mut
(||
set
(
&
mut
*
x
.f
));
let
c2
=
to_fn_mut
(||
set
(
&
mut
*
x
.f
));
//~^ ERROR cannot borrow `x` as mutable more than once
}
fn
main
()
{
}
src/test/ui/borrowck/borrowck-closures-two-mut.stderr
0 → 100644
浏览文件 @
d3e9881e
error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
--> $DIR/borrowck-closures-two-mut.rs:24:24
|
23 | let c1 = to_fn_mut(|| x = 4);
| -- - previous borrow occurs due to use of `x` in closure
| |
| first mutable borrow occurs here
24 | let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
| ^^ - borrow occurs due to use of `x` in closure
| |
| second mutable borrow occurs here
25 | }
| - first borrow ends here
error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
--> $DIR/borrowck-closures-two-mut.rs:34:24
|
33 | let c1 = to_fn_mut(|| set(&mut x));
| -- - previous borrow occurs due to use of `x` in closure
| |
| first mutable borrow occurs here
34 | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
| ^^ - borrow occurs due to use of `x` in closure
| |
| second mutable borrow occurs here
35 | }
| - first borrow ends here
error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
--> $DIR/borrowck-closures-two-mut.rs:40:24
|
39 | let c1 = to_fn_mut(|| x = 5);
| -- - previous borrow occurs due to use of `x` in closure
| |
| first mutable borrow occurs here
40 | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
| ^^ - borrow occurs due to use of `x` in closure
| |
| second mutable borrow occurs here
41 | }
| - first borrow ends here
error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
--> $DIR/borrowck-closures-two-mut.rs:46:24
|
45 | let c1 = to_fn_mut(|| x = 5);
| -- - previous borrow occurs due to use of `x` in closure
| |
| first mutable borrow occurs here
46 | let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
| ^^ - borrow occurs due to use of `x` in closure
| |
| second mutable borrow occurs here
47 | //~^ ERROR cannot borrow `x` as mutable more than once
48 | }
| - first borrow ends here
error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
--> $DIR/borrowck-closures-two-mut.rs:57:24
|
56 | let c1 = to_fn_mut(|| set(&mut *x.f));
| -- - previous borrow occurs due to use of `x` in closure
| |
| first mutable borrow occurs here
57 | let c2 = to_fn_mut(|| set(&mut *x.f));
| ^^ - borrow occurs due to use of `x` in closure
| |
| second mutable borrow occurs here
58 | //~^ ERROR cannot borrow `x` as mutable more than once
59 | }
| - first borrow ends here
error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
--> $DIR/borrowck-closures-two-mut.rs:24:24
|
23 | let c1 = to_fn_mut(|| x = 4);
| -- - previous borrow occurs due to use of `x` in closure
| |
| first mutable borrow occurs here
24 | let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
| ^^ - borrow occurs due to use of `x` in closure
| |
| second mutable borrow occurs here
25 | }
| - first borrow ends here
error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
--> $DIR/borrowck-closures-two-mut.rs:34:24
|
33 | let c1 = to_fn_mut(|| set(&mut x));
| -- - previous borrow occurs due to use of `x` in closure
| |
| first mutable borrow occurs here
34 | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
| ^^ - borrow occurs due to use of `x` in closure
| |
| second mutable borrow occurs here
35 | }
| - first borrow ends here
error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
--> $DIR/borrowck-closures-two-mut.rs:40:24
|
39 | let c1 = to_fn_mut(|| x = 5);
| -- - previous borrow occurs due to use of `x` in closure
| |
| first mutable borrow occurs here
40 | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
| ^^ - borrow occurs due to use of `x` in closure
| |
| second mutable borrow occurs here
41 | }
| - first borrow ends here
error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
--> $DIR/borrowck-closures-two-mut.rs:46:24
|
45 | let c1 = to_fn_mut(|| x = 5);
| -- - previous borrow occurs due to use of `x` in closure
| |
| first mutable borrow occurs here
46 | let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
| ^^ - borrow occurs due to use of `x` in closure
| |
| second mutable borrow occurs here
47 | //~^ ERROR cannot borrow `x` as mutable more than once
48 | }
| - first borrow ends here
error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
--> $DIR/borrowck-closures-two-mut.rs:57:24
|
56 | let c1 = to_fn_mut(|| set(&mut *x.f));
| -- - previous borrow occurs due to use of `x` in closure
| |
| first mutable borrow occurs here
57 | let c2 = to_fn_mut(|| set(&mut *x.f));
| ^^ - borrow occurs due to use of `x` in closure
| |
| second mutable borrow occurs here
58 | //~^ ERROR cannot borrow `x` as mutable more than once
59 | }
| - first borrow ends here
error: aborting due to 10 previous errors
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录