Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
5804637a
R
Rust
项目概览
int
/
Rust
11 个月 前同步成功
通知
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,发现更多精彩内容 >>
提交
5804637a
编写于
12月 04, 2017
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
permit `ClosureOutlivesRequirement` to constrain regions or types
上级
c7cfa236
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
96 addition
and
38 deletion
+96
-38
src/librustc/ich/impls_mir.rs
src/librustc/ich/impls_mir.rs
+18
-3
src/librustc/mir/mod.rs
src/librustc/mir/mod.rs
+25
-8
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/mod.rs
+1
-1
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/mod.rs
+2
-2
src/librustc_mir/borrow_check/nll/mod.rs
src/librustc_mir/borrow_check/nll/mod.rs
+8
-3
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+42
-21
未找到文件。
src/librustc/ich/impls_mir.rs
浏览文件 @
5804637a
...
...
@@ -536,14 +536,29 @@ fn hash_stable<W: StableHasherResult>(&self,
impl_stable_hash_for!
(
struct
mir
::
Location
{
block
,
statement_index
});
impl_stable_hash_for!
(
struct
mir
::
ClosureRegionRequirements
{
impl_stable_hash_for!
(
struct
mir
::
ClosureRegionRequirements
<
'tcx
>
{
num_external_vids
,
outlives_requirements
});
impl_stable_hash_for!
(
struct
mir
::
ClosureOutlivesRequirement
{
free_region
,
impl_stable_hash_for!
(
struct
mir
::
ClosureOutlivesRequirement
<
'tcx
>
{
subject
,
outlived_free_region
,
blame_span
});
impl
<
'gcx
>
HashStable
<
StableHashingContext
<
'gcx
>>
for
mir
::
ClosureOutlivesSubject
<
'gcx
>
{
fn
hash_stable
<
W
:
StableHasherResult
>
(
&
self
,
hcx
:
&
mut
StableHashingContext
<
'gcx
>
,
hasher
:
&
mut
StableHasher
<
W
>
)
{
mem
::
discriminant
(
self
)
.hash_stable
(
hcx
,
hasher
);
match
*
self
{
mir
::
ClosureOutlivesSubject
::
Ty
(
ref
ty
)
=>
{
ty
.hash_stable
(
hcx
,
hasher
);
}
mir
::
ClosureOutlivesSubject
::
Region
(
ref
region
)
=>
{
region
.hash_stable
(
hcx
,
hasher
);
}
}
}
}
src/librustc/mir/mod.rs
浏览文件 @
5804637a
...
...
@@ -1832,7 +1832,7 @@ pub struct GeneratorLayout<'tcx> {
/// can be extracted from its type and constrained to have the given
/// outlives relationship.
#[derive(Clone,
Debug,
RustcEncodable,
RustcDecodable)]
pub
struct
ClosureRegionRequirements
{
pub
struct
ClosureRegionRequirements
<
'gcx
>
{
/// The number of external regions defined on the closure. In our
/// example above, it would be 3 -- one for `'static`, then `'1`
/// and `'2`. This is just used for a sanity check later on, to
...
...
@@ -1842,15 +1842,15 @@ pub struct ClosureRegionRequirements {
/// Requirements between the various free regions defined in
/// indices.
pub
outlives_requirements
:
Vec
<
ClosureOutlivesRequirement
>
,
pub
outlives_requirements
:
Vec
<
ClosureOutlivesRequirement
<
'gcx
>
>
,
}
/// Indicates an outlives constraint between
two free-regions declared
/// on the closure.
#[derive(Copy,
Clone,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
RustcEncodable,
RustcDecodable)]
pub
struct
ClosureOutlivesRequirement
{
// This region ...
pub
free_region
:
ty
::
RegionVid
,
/// Indicates an outlives constraint between
a type or between two
///
free-regions declared
on the closure.
#[derive(Copy,
Clone,
Debug,
RustcEncodable,
RustcDecodable)]
pub
struct
ClosureOutlivesRequirement
<
'tcx
>
{
// This region
or type
...
pub
subject
:
ClosureOutlivesSubject
<
'tcx
>
,
// .. must outlive this one.
pub
outlived_free_region
:
ty
::
RegionVid
,
...
...
@@ -1859,6 +1859,23 @@ pub struct ClosureOutlivesRequirement {
pub
blame_span
:
Span
,
}
/// The subject of a ClosureOutlivesRequirement -- that is, the thing
/// that must outlive some region.
#[derive(Copy,
Clone,
Debug,
RustcEncodable,
RustcDecodable)]
pub
enum
ClosureOutlivesSubject
<
'tcx
>
{
/// Subject is a type, typically a type parameter, but could also
/// be a projection. Indicates a requirement like `T: 'a` being
/// passed to the caller, where the type here is `T`.
///
/// The type here is guaranteed not to contain any free regions at
/// present.
Ty
(
Ty
<
'tcx
>
),
/// Subject is a free region from the closure. Indicates a requirement
/// like `'a: 'b` being passed to the caller; the region here is `'a`.
Region
(
ty
::
RegionVid
),
}
/*
* TypeFoldable implementations for MIR types
*/
...
...
src/librustc/ty/maps/mod.rs
浏览文件 @
5804637a
...
...
@@ -193,7 +193,7 @@
/// Borrow checks the function body. If this is a closure, returns
/// additional requirements that the closure's creator must verify.
[]
fn
mir_borrowck
:
MirBorrowCheck
(
DefId
)
->
Option
<
mir
::
ClosureRegionRequirements
>
,
[]
fn
mir_borrowck
:
MirBorrowCheck
(
DefId
)
->
Option
<
mir
::
ClosureRegionRequirements
<
'tcx
>
>
,
/// Gets a complete map from all types to their inherent impls.
/// Not meant to be used directly outside of coherence.
...
...
src/librustc_mir/borrow_check/mod.rs
浏览文件 @
5804637a
...
...
@@ -65,7 +65,7 @@ pub fn provide(providers: &mut Providers) {
fn
mir_borrowck
<
'a
,
'tcx
>
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
def_id
:
DefId
,
)
->
Option
<
ClosureRegionRequirements
>
{
)
->
Option
<
ClosureRegionRequirements
<
'tcx
>
>
{
let
input_mir
=
tcx
.mir_validated
(
def_id
);
debug!
(
"run query mir_borrowck: {}"
,
tcx
.item_path_str
(
def_id
));
...
...
@@ -89,7 +89,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
infcx
:
&
InferCtxt
<
'a
,
'gcx
,
'tcx
>
,
input_mir
:
&
Mir
<
'gcx
>
,
def_id
:
DefId
,
)
->
Option
<
ClosureRegionRequirements
>
{
)
->
Option
<
ClosureRegionRequirements
<
'gcx
>
>
{
let
tcx
=
infcx
.tcx
;
let
attributes
=
tcx
.get_attrs
(
def_id
);
let
param_env
=
tcx
.param_env
(
def_id
);
...
...
src/librustc_mir/borrow_check/nll/mod.rs
浏览文件 @
5804637a
...
...
@@ -9,11 +9,12 @@
// except according to those terms.
use
rustc
::
hir
::
def_id
::
DefId
;
use
rustc
::
mir
::{
ClosureRegionRequirements
,
Mir
};
use
rustc
::
mir
::{
ClosureRegionRequirements
,
ClosureOutlivesSubject
,
Mir
};
use
rustc
::
infer
::
InferCtxt
;
use
rustc
::
ty
::{
self
,
RegionKind
,
RegionVid
};
use
rustc
::
util
::
nodemap
::
FxHashMap
;
use
std
::
collections
::
BTreeSet
;
use
std
::
fmt
::
Debug
;
use
std
::
io
;
use
transform
::
MirSource
;
use
util
::
liveness
::{
LivenessResults
,
LocalSet
};
...
...
@@ -73,7 +74,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
move_data
:
&
MoveData
<
'tcx
>
,
)
->
(
RegionInferenceContext
<
'tcx
>
,
Option
<
ClosureRegionRequirements
>
,
Option
<
ClosureRegionRequirements
<
'gcx
>
>
,
)
{
// Run the MIR type-checker.
let
mir_node_id
=
infcx
.tcx.hir
.as_local_node_id
(
def_id
)
.unwrap
();
...
...
@@ -263,9 +264,13 @@ fn for_each_region_constraint(
with_msg
:
&
mut
FnMut
(
&
str
)
->
io
::
Result
<
()
>
,
)
->
io
::
Result
<
()
>
{
for
req
in
&
closure_region_requirements
.outlives_requirements
{
let
subject
:
&
Debug
=
match
&
req
.subject
{
ClosureOutlivesSubject
::
Region
(
subject
)
=>
subject
,
ClosureOutlivesSubject
::
Ty
(
ty
)
=>
ty
,
};
with_msg
(
&
format!
(
"where {:?}: {:?}"
,
req
.free_region
,
subject
,
req
.outlived_free_region
,
))
?
;
}
...
...
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
浏览文件 @
5804637a
...
...
@@ -15,7 +15,8 @@
use
rustc
::
infer
::
RegionVariableOrigin
;
use
rustc
::
infer
::
SubregionOrigin
;
use
rustc
::
infer
::
region_constraints
::{
GenericKind
,
VarOrigins
};
use
rustc
::
mir
::{
ClosureOutlivesRequirement
,
ClosureRegionRequirements
,
Location
,
Mir
};
use
rustc
::
mir
::{
ClosureOutlivesRequirement
,
ClosureOutlivesSubject
,
ClosureRegionRequirements
,
Location
,
Mir
};
use
rustc
::
ty
::{
self
,
RegionVid
};
use
rustc_data_structures
::
indexed_vec
::
IndexVec
;
use
std
::
fmt
;
...
...
@@ -339,12 +340,12 @@ pub(super) fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
/// Perform region inference and report errors if we see any
/// unsatisfiable constraints. If this is a closure, returns the
/// region requirements to propagate to our creator, if any.
pub
(
super
)
fn
solve
(
pub
(
super
)
fn
solve
<
'gcx
>
(
&
mut
self
,
infcx
:
&
InferCtxt
<
'_
,
'
_
,
'tcx
>
,
infcx
:
&
InferCtxt
<
'_
,
'
gcx
,
'tcx
>
,
mir
:
&
Mir
<
'tcx
>
,
mir_def_id
:
DefId
,
)
->
Option
<
ClosureRegionRequirements
>
{
)
->
Option
<
ClosureRegionRequirements
<
'gcx
>
>
{
assert
!
(
self
.inferred_values
.is_none
(),
"values already inferred"
);
self
.propagate_constraints
(
mir
);
...
...
@@ -559,10 +560,10 @@ fn eval_outlives(
/// If `propagated_outlives_requirements` is `Some`, then we will
/// push unsatisfied obligations into there. Otherwise, we'll
/// report them as errors.
fn
check_universal_regions
(
fn
check_universal_regions
<
'gcx
>
(
&
self
,
infcx
:
&
InferCtxt
<
'_
,
'
_
,
'tcx
>
,
mut
propagated_outlives_requirements
:
Option
<&
mut
Vec
<
ClosureOutlivesRequirement
>>
,
infcx
:
&
InferCtxt
<
'_
,
'
gcx
,
'tcx
>
,
mut
propagated_outlives_requirements
:
Option
<&
mut
Vec
<
ClosureOutlivesRequirement
<
'gcx
>
>>
,
)
{
// The universal regions are always found in a prefix of the
// full list.
...
...
@@ -583,9 +584,17 @@ fn check_universal_regions(
propagated_outlives_requirements
.extend
(
outlives_requirements
.drain
(
..
));
}
else
{
for
outlives_requirement
in
outlives_requirements
.drain
(
..
)
{
let
fr
=
match
outlives_requirement
.subject
{
ClosureOutlivesSubject
::
Region
(
fr
)
=>
fr
,
_
=>
span_bug!
(
outlives_requirement
.blame_span
,
"check_universal_region() produced requirement w/ non-region subject"
),
};
self
.report_error
(
infcx
,
outlives_requirement
.free_region
,
fr
,
outlives_requirement
.outlived_free_region
,
outlives_requirement
.blame_span
,
);
...
...
@@ -602,11 +611,11 @@ fn check_universal_regions(
///
/// Things that are to be propagated are accumulated into the
/// `outlives_requirements` vector.
fn
check_universal_region
(
fn
check_universal_region
<
'gcx
>
(
&
self
,
infcx
:
&
InferCtxt
<
'_
,
'
_
,
'tcx
>
,
infcx
:
&
InferCtxt
<
'_
,
'
gcx
,
'tcx
>
,
longer_fr
:
RegionVid
,
propagated_outlives_requirements
:
&
mut
Vec
<
ClosureOutlivesRequirement
>
,
propagated_outlives_requirements
:
&
mut
Vec
<
ClosureOutlivesRequirement
<
'gcx
>
>
,
)
{
let
inferred_values
=
self
.inferred_values
.as_ref
()
.unwrap
();
...
...
@@ -645,7 +654,7 @@ fn check_universal_region(
// Push the constraint `fr-: shorter_fr+`
propagated_outlives_requirements
.push
(
ClosureOutlivesRequirement
{
free_region
:
fr_minus
,
subject
:
ClosureOutlivesSubject
::
Region
(
fr_minus
)
,
outlived_free_region
:
shorter_fr_plus
,
blame_span
:
blame_span
,
});
...
...
@@ -773,7 +782,7 @@ fn apply_requirements<'tcx>(
);
}
impl
ClosureRegionRequirementsExt
for
ClosureRegionRequirements
{
impl
<
'gcx
>
ClosureRegionRequirementsExt
for
ClosureRegionRequirements
<
'gcx
>
{
/// Given an instance T of the closure type, this method
/// instantiates the "extra" requirements that we computed for the
/// closure into the inference context. This has the effect of
...
...
@@ -815,17 +824,29 @@ fn apply_requirements<'tcx>(
// Create the predicates.
for
outlives_requirement
in
&
self
.outlives_requirements
{
let
region
=
closure_mapping
[
outlives_requirement
.free_region
];
let
outlived_region
=
closure_mapping
[
outlives_requirement
.outlived_free_region
];
debug!
(
"apply_requirements: region={:?} outlived_region={:?} outlives_requirements={:?}"
,
region
,
outlived_region
,
outlives_requirement
);
// FIXME, this origin is not entirely suitable.
let
origin
=
SubregionOrigin
::
CallRcvr
(
outlives_requirement
.blame_span
);
infcx
.sub_regions
(
origin
,
outlived_region
,
region
);
match
outlives_requirement
.subject
{
ClosureOutlivesSubject
::
Region
(
region
)
=>
{
let
region
=
closure_mapping
[
region
];
debug!
(
"apply_requirements: region={:?}
\
outlived_region={:?}
\
outlives_requirements={:?}"
,
region
,
outlived_region
,
outlives_requirement
);
infcx
.sub_regions
(
origin
,
outlived_region
,
region
);
}
ClosureOutlivesSubject
::
Ty
(
_
ty
)
=>
{
bug!
(
"TODO not yet implemented -- closure outlives subject of a type"
);
}
}
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录