Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
ec48b4eb
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,发现更多精彩内容 >>
提交
ec48b4eb
编写于
6月 07, 2019
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
preliminary integration of "pick constraints" into nll solver
上级
3b5a7276
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
231 addition
and
127 deletion
+231
-127
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/error_reporting/mod.rs
+2
-2
src/librustc/infer/opaque_types/mod.rs
src/librustc/infer/opaque_types/mod.rs
+6
-5
src/librustc_mir/borrow_check/nll/pick_constraints.rs
src/librustc_mir/borrow_check/nll/pick_constraints.rs
+8
-0
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+213
-120
src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
..._mir/borrow_check/nll/type_check/constraint_conversion.rs
+2
-0
未找到文件。
src/librustc/infer/error_reporting/mod.rs
浏览文件 @
ec48b4eb
...
...
@@ -385,13 +385,13 @@ pub fn report_region_errors(
option_regions
:
_
,
}
=>
{
let
hidden_ty
=
self
.resolve_vars_if_possible
(
&
hidden_ty
);
opaque_types
::
report_unexpected_hidden_region
(
opaque_types
::
unexpected_hidden_region_diagnostic
(
self
.tcx
,
Some
(
region_scope_tree
),
opaque_type_def_id
,
hidden_ty
,
pick_region
,
);
)
.emit
()
;
}
}
}
...
...
src/librustc/infer/opaque_types/mod.rs
浏览文件 @
ec48b4eb
...
...
@@ -9,6 +9,7 @@
use
crate
::
ty
::
subst
::{
InternalSubsts
,
Kind
,
SubstsRef
,
UnpackedKind
};
use
crate
::
ty
::{
self
,
GenericParamDefKind
,
Ty
,
TyCtxt
};
use
crate
::
util
::
nodemap
::
DefIdMap
;
use
errors
::
DiagnosticBuilder
;
use
rustc_data_structures
::
fx
::
FxHashMap
;
use
std
::
rc
::
Rc
;
...
...
@@ -499,13 +500,13 @@ pub fn infer_opaque_definition_from_instantiation(
}
}
pub
fn
report_unexpected_hidden_region
(
pub
fn
unexpected_hidden_region_diagnostic
(
tcx
:
TyCtxt
<
'tcx
>
,
region_scope_tree
:
Option
<&
region
::
ScopeTree
>
,
opaque_type_def_id
:
DefId
,
hidden_ty
:
Ty
<
'tcx
>
,
hidden_region
:
ty
::
Region
<
'tcx
>
,
)
{
)
->
DiagnosticBuilder
<
'tcx
>
{
let
span
=
tcx
.def_span
(
opaque_type_def_id
);
let
mut
err
=
struct_span_err!
(
tcx
.sess
,
...
...
@@ -573,7 +574,7 @@ pub fn report_unexpected_hidden_region(
}
}
err
.emit
();
err
}
// Visitor that requires that (almost) all regions in the type visited outlive
...
...
@@ -724,13 +725,13 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
None
=>
{
if
!
self
.map_missing_regions_to_empty
&&
!
self
.tainted_by_errors
{
if
let
Some
(
hidden_ty
)
=
self
.hidden_ty
.take
()
{
report_unexpected_hidden_region
(
unexpected_hidden_region_diagnostic
(
self
.tcx
,
None
,
self
.opaque_type_def_id
,
hidden_ty
,
r
,
);
)
.emit
()
;
}
}
self
.tcx.lifetimes.re_empty
...
...
src/librustc_mir/borrow_check/nll/pick_constraints.rs
浏览文件 @
ec48b4eb
...
...
@@ -71,10 +71,12 @@ impl<'tcx> PickConstraintSet<'tcx, ty::RegionVid> {
p_c
:
&
PickConstraint
<
'tcx
>
,
mut
to_region_vid
:
impl
FnMut
(
ty
::
Region
<
'tcx
>
)
->
ty
::
RegionVid
,
)
{
debug!
(
"push_constraint(p_c={:?})"
,
p_c
);
let
pick_region_vid
:
ty
::
RegionVid
=
to_region_vid
(
p_c
.pick_region
);
let
next_constraint
=
self
.first_constraints
.get
(
&
pick_region_vid
)
.cloned
();
let
start_index
=
self
.option_regions
.len
();
let
end_index
=
start_index
+
p_c
.option_regions
.len
();
debug!
(
"push_constraint: pick_region_vid={:?}"
,
pick_region_vid
);
let
constraint_index
=
self
.constraints
.push
(
NllPickConstraint
{
next_constraint
,
pick_region_vid
,
...
...
@@ -136,6 +138,12 @@ impl<'tcx, R> PickConstraintSet<'tcx, R>
where
R
:
Copy
+
Hash
+
Eq
,
{
crate
fn
all_indices
(
&
self
,
)
->
impl
Iterator
<
Item
=
NllPickConstraintIndex
>
{
self
.constraints
.indices
()
}
/// Iterate down the constraint indices associated with a given
/// peek-region. You can then use `option_regions` and other
/// methods to access data.
...
...
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
浏览文件 @
ec48b4eb
use
super
::
universal_regions
::
UniversalRegions
;
use
crate
::
borrow_check
::
nll
::
constraints
::
graph
::
NormalConstraintGraph
;
use
crate
::
borrow_check
::
nll
::
constraints
::{
ConstraintSccIndex
,
OutlivesConstraintSet
,
OutlivesConstraint
};
use
crate
::
borrow_check
::
nll
::
constraints
::{
ConstraintSccIndex
,
OutlivesConstraint
,
OutlivesConstraintSet
,
};
use
crate
::
borrow_check
::
nll
::
pick_constraints
::
PickConstraintSet
;
use
crate
::
borrow_check
::
nll
::
region_infer
::
values
::{
PlaceholderIndices
,
RegionElement
,
ToElementIndex
PlaceholderIndices
,
RegionElement
,
ToElementIndex
,
};
use
crate
::
borrow_check
::
Upvar
;
use
crate
::
borrow_check
::
nll
::
type_check
::
free_region_relations
::
UniversalRegionRelations
;
use
crate
::
borrow_check
::
nll
::
type_check
::
Locations
;
use
crate
::
borrow_check
::
Upvar
;
use
rustc
::
hir
::
def_id
::
DefId
;
use
rustc
::
infer
::
canonical
::
QueryOutlivesConstraint
;
use
rustc
::
infer
::
opaque_types
;
use
rustc
::
infer
::
region_constraints
::{
GenericKind
,
VarInfos
,
VerifyBound
};
use
rustc
::
infer
::{
InferCtxt
,
NLLRegionVariableOrigin
,
RegionVariableOrigin
};
use
rustc
::
mir
::{
ClosureOutlivesRequirement
,
ClosureOutlivesSubject
,
ClosureRegionRequirements
,
ConstraintCategory
,
Local
,
Location
,
Body
,
Body
,
ClosureOutlivesRequirement
,
ClosureOutlivesSubject
,
ClosureRegionRequirements
,
ConstraintCategory
,
Local
,
Location
,
};
use
rustc
::
ty
::{
self
,
subst
::
SubstsRef
,
RegionVid
,
Ty
,
TyCtxt
,
TypeFoldable
};
use
rustc
::
util
::
common
::{
self
,
ErrorReported
};
...
...
@@ -61,6 +64,9 @@ pub struct RegionInferenceContext<'tcx> {
/// compute the values of each region.
constraint_sccs
:
Rc
<
Sccs
<
RegionVid
,
ConstraintSccIndex
>>
,
/// The "pick R0 from [R1..Rn]" constraints, indexed by SCC.
pick_constraints
:
Rc
<
PickConstraintSet
<
'tcx
,
ConstraintSccIndex
>>
,
/// Map closure bounds to a `Span` that should be used for error reporting.
closure_bounds_mapping
:
FxHashMap
<
Location
,
FxHashMap
<
(
RegionVid
,
RegionVid
),
(
ConstraintCategory
,
Span
)
>>
,
...
...
@@ -188,7 +194,7 @@ pub(crate) fn new(
universal_region_relations
:
Rc
<
UniversalRegionRelations
<
'tcx
>>
,
_
body
:
&
Body
<
'tcx
>
,
outlives_constraints
:
OutlivesConstraintSet
,
pick_constraints
:
PickConstraintSet
<
'tcx
,
RegionVid
>
,
pick_constraints
_in
:
PickConstraintSet
<
'tcx
,
RegionVid
>
,
closure_bounds_mapping
:
FxHashMap
<
Location
,
FxHashMap
<
(
RegionVid
,
RegionVid
),
(
ConstraintCategory
,
Span
)
>
,
...
...
@@ -220,9 +226,7 @@ pub(crate) fn new(
let
scc_representatives
=
Self
::
compute_scc_representatives
(
&
constraint_sccs
,
&
definitions
);
let
_
pick_constraints_scc
=
pick_constraints
.into_mapped
(
// TODO
|
r
|
constraint_sccs
.scc
(
r
),
);
let
pick_constraints
=
Rc
::
new
(
pick_constraints_in
.into_mapped
(|
r
|
constraint_sccs
.scc
(
r
)));
let
mut
result
=
Self
{
definitions
,
...
...
@@ -230,6 +234,7 @@ pub(crate) fn new(
constraints
,
constraint_graph
,
constraint_sccs
,
pick_constraints
,
closure_bounds_mapping
,
scc_universes
,
scc_representatives
,
...
...
@@ -347,9 +352,7 @@ fn init_free_and_bound_regions(&mut self) {
debug!
(
"init_free_and_bound_regions: placeholder {:?} is
\
not compatible with universe {:?} of its SCC {:?}"
,
placeholder
,
scc_universe
,
scc
,
placeholder
,
scc_universe
,
scc
,
);
self
.add_incompatible_universe
(
scc
);
}
...
...
@@ -434,11 +437,8 @@ fn solve_inner(
// to store those. Otherwise, we'll pass in `None` to the
// functions below, which will trigger them to report errors
// eagerly.
let
mut
outlives_requirements
=
if
infcx
.tcx
.is_closure
(
mir_def_id
)
{
Some
(
vec!
[])
}
else
{
None
};
let
mut
outlives_requirements
=
if
infcx
.tcx
.is_closure
(
mir_def_id
)
{
Some
(
vec!
[])
}
else
{
None
};
self
.check_type_tests
(
infcx
,
...
...
@@ -457,16 +457,15 @@ fn solve_inner(
errors_buffer
,
);
self
.check_pick_constraints
(
infcx
,
mir_def_id
,
errors_buffer
);
let
outlives_requirements
=
outlives_requirements
.unwrap_or
(
vec!
[]);
if
outlives_requirements
.is_empty
()
{
None
}
else
{
let
num_external_vids
=
self
.universal_regions
.num_global_and_external_regions
();
Some
(
ClosureRegionRequirements
{
num_external_vids
,
outlives_requirements
,
})
Some
(
ClosureRegionRequirements
{
num_external_vids
,
outlives_requirements
})
}
}
...
...
@@ -496,6 +495,8 @@ fn propagate_constraints(&mut self, _body: &Body<'tcx>) {
}
}
/// Computes the value of the SCC `scc_a` if it has not already
/// been computed. The `visited` parameter is a bitset
#[inline]
fn
propagate_constraint_sccs_if_new
(
&
mut
self
,
...
...
@@ -507,6 +508,10 @@ fn propagate_constraint_sccs_if_new(
}
}
/// Computes the value of the SCC `scc_a`, which has not yet been
/// computed. This works by first computing all successors of the
/// SCC (if they haven't been computed already) and then unioning
/// together their elements.
fn
propagate_constraint_sccs_new
(
&
mut
self
,
scc_a
:
ConstraintSccIndex
,
...
...
@@ -516,10 +521,7 @@ fn propagate_constraint_sccs_new(
// Walk each SCC `B` such that `A: B`...
for
&
scc_b
in
constraint_sccs
.successors
(
scc_a
)
{
debug!
(
"propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}"
,
scc_a
,
scc_b
);
debug!
(
"propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}"
,
scc_a
,
scc_b
);
// ...compute the value of `B`...
self
.propagate_constraint_sccs_if_new
(
scc_b
,
visited
);
...
...
@@ -537,6 +539,12 @@ fn propagate_constraint_sccs_new(
}
}
// Now take pick constraints into account
let
pick_constraints
=
self
.pick_constraints
.clone
();
for
p_c_i
in
pick_constraints
.indices
(
scc_a
)
{
self
.apply_pick_constraint
(
scc_a
,
pick_constraints
.option_regions
(
p_c_i
));
}
debug!
(
"propagate_constraint_sccs: scc_a = {:?} has value {:?}"
,
scc_a
,
...
...
@@ -544,6 +552,114 @@ fn propagate_constraint_sccs_new(
);
}
/// Invoked for each `pick R0 from [R1..Rn]` constraint.
///
/// `scc` is the SCC containing R0, and `option_regions` are the
/// `R1..Rn` regions -- they are always known to be universal
/// regions (and if that's not true, we just don't attempt to
/// enforce the constraint).
///
/// The current value of `scc` at the time the method is invoked
/// is considered a *lower bound*. If possible, we will modify
/// the constraint to set it equal to one of the option regions.
/// If we make any changes, returns true, else false.
fn
apply_pick_constraint
(
&
mut
self
,
scc
:
ConstraintSccIndex
,
option_regions
:
&
[
ty
::
RegionVid
],
)
->
bool
{
debug!
(
"apply_pick_constraint(scc={:?}, option_regions={:#?})"
,
scc
,
option_regions
,);
if
let
Some
(
uh_oh
)
=
option_regions
.iter
()
.find
(|
&&
r
|
!
self
.universal_regions
.is_universal_region
(
r
))
{
debug!
(
"apply_pick_constraint: option region `{:?}` is not a universal region"
,
uh_oh
);
return
false
;
}
// Create a mutable vector of the options. We'll try to winnow
// them down.
let
mut
option_regions
:
Vec
<
ty
::
RegionVid
>
=
option_regions
.to_vec
();
// The 'pick-region' in a pick-constraint is part of the
// hidden type, which must be in the root universe. Therefore,
// it cannot have any placeholders in its value.
assert
!
(
self
.scc_universes
[
scc
]
==
ty
::
UniverseIndex
::
ROOT
);
debug_assert!
(
self
.scc_values
.placeholders_contained_in
(
scc
)
.next
()
.is_none
(),
"scc {:?} in a pick-constraint has placeholder value: {:?}"
,
scc
,
self
.scc_values
.region_value_str
(
scc
),
);
// The existing value for `scc` is a lower-bound. This will
// consist of some set {P} + {LB} of points {P} and
// lower-bound free regions {LB}. As each option region O is a
// free region, it will outlive the points. But we can only
// consider the option O if O: LB.
option_regions
.retain
(|
&
o_r
|
{
self
.scc_values
.universal_regions_outlived_by
(
scc
)
.all
(|
lb
|
self
.universal_region_relations
.outlives
(
o_r
,
lb
))
});
// Now find all the *upper bounds* -- that is, each UB is a free
// region that must outlive pick region R0 (`UB: R0`). Therefore,
// we need only keep an option O if `UB: O`.
//
// TODO -- need to implement the reverse graph construction for this
//
// let mut upper_bounds = ...;
// option_regions.retain(|&o_r| {
// upper_bounds
// .all(|ub| self.universal_region_relations.outlives(
// ub,
// o_r,
// })
// });
// If we ruled everything out, we're done.
if
option_regions
.is_empty
()
{
return
false
;
}
// Otherwise, we need to find the minimum option, if any, and take that.
debug!
(
"apply_pick_constraint: option_regions remaining are {:#?}"
,
option_regions
);
let
min
=
|
r1
:
ty
::
RegionVid
,
r2
:
ty
::
RegionVid
|
->
Option
<
ty
::
RegionVid
>
{
let
r1_outlives_r2
=
self
.universal_region_relations
.outlives
(
r1
,
r2
);
let
r2_outlives_r1
=
self
.universal_region_relations
.outlives
(
r2
,
r1
);
if
r1_outlives_r2
&&
r2_outlives_r1
{
Some
(
r1
.min
(
r2
))
}
else
if
r1_outlives_r2
{
Some
(
r2
)
}
else
if
r2_outlives_r1
{
Some
(
r1
)
}
else
{
None
}
};
let
mut
best_option
=
option_regions
[
0
];
for
&
other_option
in
&
option_regions
[
1
..
]
{
debug!
(
"apply_pick_constraint: best_option={:?} other_option={:?}"
,
best_option
,
other_option
,
);
match
min
(
best_option
,
other_option
)
{
Some
(
m
)
=>
best_option
=
m
,
None
=>
{
debug!
(
"apply_pick_constraint: {:?} and {:?} are incomparable --> no best choice"
,
best_option
,
other_option
,
);
return
false
;
}
}
}
debug!
(
"apply_pick_constraint: best_choice={:?}"
,
best_option
);
self
.scc_values
.add_element
(
scc
,
best_option
)
}
/// Returns `true` if all the elements in the value of `scc_b` are nameable
/// in `scc_a`. Used during constraint propagation, and only once
/// the value of `scc_b` has been computed.
...
...
@@ -560,9 +676,7 @@ fn universe_compatible(&self, scc_b: ConstraintSccIndex, scc_a: ConstraintSccInd
// Otherwise, we have to iterate over the universe elements in
// B's value, and check whether all of them are nameable
// from universe_a
self
.scc_values
.placeholders_contained_in
(
scc_b
)
.all
(|
p
|
universe_a
.can_name
(
p
.universe
))
self
.scc_values
.placeholders_contained_in
(
scc_b
)
.all
(|
p
|
universe_a
.can_name
(
p
.universe
))
}
/// Extend `scc` so that it can outlive some placeholder region
...
...
@@ -737,12 +851,7 @@ fn try_promote_type_test(
)
->
bool
{
let
tcx
=
infcx
.tcx
;
let
TypeTest
{
generic_kind
,
lower_bound
,
locations
,
verify_bound
:
_
,
}
=
type_test
;
let
TypeTest
{
generic_kind
,
lower_bound
,
locations
,
verify_bound
:
_
}
=
type_test
;
let
generic_ty
=
generic_kind
.to_ty
(
tcx
);
let
subject
=
match
self
.try_promote_type_test_subject
(
infcx
,
generic_ty
)
{
...
...
@@ -892,11 +1001,7 @@ fn try_promote_type_test_subject(
/// except that it converts further takes the non-local upper
/// bound of `'y`, so that the final result is non-local.
fn
non_local_universal_upper_bound
(
&
self
,
r
:
RegionVid
)
->
RegionVid
{
debug!
(
"non_local_universal_upper_bound(r={:?}={})"
,
r
,
self
.region_value_str
(
r
)
);
debug!
(
"non_local_universal_upper_bound(r={:?}={})"
,
r
,
self
.region_value_str
(
r
));
let
lub
=
self
.universal_upper_bound
(
r
);
...
...
@@ -904,10 +1009,7 @@ fn non_local_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
// creator.
let
non_local_lub
=
self
.universal_region_relations
.non_local_upper_bound
(
lub
);
debug!
(
"non_local_universal_upper_bound: non_local_lub={:?}"
,
non_local_lub
);
debug!
(
"non_local_universal_upper_bound: non_local_lub={:?}"
,
non_local_lub
);
non_local_lub
}
...
...
@@ -927,11 +1029,7 @@ fn non_local_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
/// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding
/// a result `'y`.
fn
universal_upper_bound
(
&
self
,
r
:
RegionVid
)
->
RegionVid
{
debug!
(
"universal_upper_bound(r={:?}={})"
,
r
,
self
.region_value_str
(
r
)
);
debug!
(
"universal_upper_bound(r={:?}={})"
,
r
,
self
.region_value_str
(
r
));
// Find the smallest universal region that contains all other
// universal regions within `region`.
...
...
@@ -956,10 +1054,7 @@ fn eval_verify_bound(
lower_bound
:
RegionVid
,
verify_bound
:
&
VerifyBound
<
'tcx
>
,
)
->
bool
{
debug!
(
"eval_verify_bound(lower_bound={:?}, verify_bound={:?})"
,
lower_bound
,
verify_bound
);
debug!
(
"eval_verify_bound(lower_bound={:?}, verify_bound={:?})"
,
lower_bound
,
verify_bound
);
match
verify_bound
{
VerifyBound
::
IfEq
(
test_ty
,
verify_bound1
)
=>
{
...
...
@@ -968,7 +1063,7 @@ fn eval_verify_bound(
VerifyBound
::
OutlivedBy
(
r
)
=>
{
let
r_vid
=
self
.to_region_vid
(
r
);
self
.eval_outlives
(
body
,
r_vid
,
lower_bound
)
self
.eval_outlives
(
r_vid
,
lower_bound
)
}
VerifyBound
::
AnyBound
(
verify_bounds
)
=>
verify_bounds
.iter
()
.any
(|
verify_bound
|
{
...
...
@@ -1041,23 +1136,17 @@ fn normalize_to_scc_representatives<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
})
}
// Evaluate whether `sup_region
: sub_region @ point
`.
fn
eval_
outlives
(
&
self
,
_
body
:
&
Body
<
'tcx
>
,
sup_region
:
RegionVid
,
sub_region
:
RegionVid
,
)
->
bool
{
// Evaluate whether `sup_region
== sub_region
`.
fn
eval_
equal
(
&
self
,
r1
:
RegionVid
,
r2
:
RegionVid
)
->
bool
{
self
.eval_outlives
(
r1
,
r2
)
&&
self
.eval_outlives
(
r2
,
r1
)
}
// Evaluate whether `sup_region: sub_region`.
fn
eval_outlives
(
&
self
,
sup_region
:
RegionVid
,
sub_region
:
RegionVid
)
->
bool
{
debug!
(
"eval_outlives({:?}: {:?})"
,
sup_region
,
sub_region
);
debug!
(
"eval_outlives: sup_region's value = {:?}"
,
self
.region_value_str
(
sup_region
),
);
debug!
(
"eval_outlives: sub_region's value = {:?}"
,
self
.region_value_str
(
sub_region
),
);
debug!
(
"eval_outlives: sup_region's value = {:?}"
,
self
.region_value_str
(
sup_region
),);
debug!
(
"eval_outlives: sub_region's value = {:?}"
,
self
.region_value_str
(
sub_region
),);
let
sub_region_scc
=
self
.constraint_sccs
.scc
(
sub_region
);
let
sup_region_scc
=
self
.constraint_sccs
.scc
(
sup_region
);
...
...
@@ -1068,9 +1157,8 @@ fn eval_outlives(
// now). Therefore, the sup-region outlives the sub-region if,
// for each universal region R1 in the sub-region, there
// exists some region R2 in the sup-region that outlives R1.
let
universal_outlives
=
self
.scc_values
.universal_regions_outlived_by
(
sub_region_scc
)
.all
(|
r1
|
{
let
universal_outlives
=
self
.scc_values
.universal_regions_outlived_by
(
sub_region_scc
)
.all
(|
r1
|
{
self
.scc_values
.universal_regions_outlived_by
(
sup_region_scc
)
.any
(|
r2
|
self
.universal_region_relations
.outlives
(
r2
,
r1
))
...
...
@@ -1088,8 +1176,7 @@ fn eval_outlives(
return
true
;
}
self
.scc_values
.contains_points
(
sup_region_scc
,
sub_region_scc
)
self
.scc_values
.contains_points
(
sup_region_scc
,
sub_region_scc
)
}
/// Once regions have been propagated, this method is used to see
...
...
@@ -1171,12 +1258,7 @@ fn check_universal_region(
// Because this free region must be in the ROOT universe, we
// know it cannot contain any bound universes.
assert
!
(
self
.scc_universes
[
longer_fr_scc
]
==
ty
::
UniverseIndex
::
ROOT
);
debug_assert!
(
self
.scc_values
.placeholders_contained_in
(
longer_fr_scc
)
.next
()
.is_none
()
);
debug_assert!
(
self
.scc_values
.placeholders_contained_in
(
longer_fr_scc
)
.next
()
.is_none
());
// Only check all of the relations for the main representative of each
// SCC, otherwise just check that we outlive said representative. This
...
...
@@ -1230,9 +1312,7 @@ fn check_universal_region_relation(
errors_buffer
:
&
mut
Vec
<
Diagnostic
>
,
)
->
Option
<
ErrorReported
>
{
// If it is known that `fr: o`, carry on.
if
self
.universal_region_relations
.outlives
(
longer_fr
,
shorter_fr
)
{
if
self
.universal_region_relations
.outlives
(
longer_fr
,
shorter_fr
)
{
return
None
;
}
...
...
@@ -1246,9 +1326,7 @@ fn check_universal_region_relation(
// We'll call it `fr-` -- it's ever so slightly smaller than
// `longer_fr`.
if
let
Some
(
fr_minus
)
=
self
.universal_region_relations
.non_local_lower_bound
(
longer_fr
)
if
let
Some
(
fr_minus
)
=
self
.universal_region_relations
.non_local_lower_bound
(
longer_fr
)
{
debug!
(
"check_universal_region: fr_minus={:?}"
,
fr_minus
);
...
...
@@ -1258,12 +1336,9 @@ fn check_universal_region_relation(
// Grow `shorter_fr` until we find some non-local regions. (We
// always will.) We'll call them `shorter_fr+` -- they're ever
// so slightly larger than `shorter_fr`.
let
shorter_fr_plus
=
self
.universal_region_relations
.non_local_upper_bounds
(
&
shorter_fr
);
debug!
(
"check_universal_region: shorter_fr_plus={:?}"
,
shorter_fr_plus
);
let
shorter_fr_plus
=
self
.universal_region_relations
.non_local_upper_bounds
(
&
shorter_fr
);
debug!
(
"check_universal_region: shorter_fr_plus={:?}"
,
shorter_fr_plus
);
for
&&
fr
in
&
shorter_fr_plus
{
// Push the constraint `fr-: shorter_fr+`
propagated_outlives_requirements
.push
(
ClosureOutlivesRequirement
{
...
...
@@ -1295,28 +1370,20 @@ fn check_bound_universal_region(
longer_fr
:
RegionVid
,
placeholder
:
ty
::
PlaceholderRegion
,
)
{
debug!
(
"check_bound_universal_region(fr={:?}, placeholder={:?})"
,
longer_fr
,
placeholder
,
);
debug!
(
"check_bound_universal_region(fr={:?}, placeholder={:?})"
,
longer_fr
,
placeholder
,);
let
longer_fr_scc
=
self
.constraint_sccs
.scc
(
longer_fr
);
debug!
(
"check_bound_universal_region: longer_fr_scc={:?}"
,
longer_fr_scc
,
);
debug!
(
"check_bound_universal_region: longer_fr_scc={:?}"
,
longer_fr_scc
,);
// If we have some bound universal region `'a`, then the only
// elements it can contain is itself -- we don't know anything
// else about it!
let
error_element
=
match
{
self
.scc_values
.elements_contained_in
(
longer_fr_scc
)
.find
(|
element
|
match
element
{
RegionElement
::
Location
(
_
)
=>
true
,
RegionElement
::
RootUniversalRegion
(
_
)
=>
true
,
RegionElement
::
PlaceholderRegion
(
placeholder1
)
=>
placeholder
!=
*
placeholder1
,
})
self
.scc_values
.elements_contained_in
(
longer_fr_scc
)
.find
(|
element
|
match
element
{
RegionElement
::
Location
(
_
)
=>
true
,
RegionElement
::
RootUniversalRegion
(
_
)
=>
true
,
RegionElement
::
PlaceholderRegion
(
placeholder1
)
=>
placeholder
!=
*
placeholder1
,
})
}
{
Some
(
v
)
=>
v
,
None
=>
return
,
...
...
@@ -1327,7 +1394,8 @@ fn check_bound_universal_region(
let
error_region
=
match
error_element
{
RegionElement
::
Location
(
l
)
=>
self
.find_sub_region_live_at
(
longer_fr
,
l
),
RegionElement
::
RootUniversalRegion
(
r
)
=>
r
,
RegionElement
::
PlaceholderRegion
(
error_placeholder
)
=>
self
.definitions
RegionElement
::
PlaceholderRegion
(
error_placeholder
)
=>
self
.definitions
.iter_enumerated
()
.filter_map
(|(
r
,
definition
)|
match
definition
.origin
{
NLLRegionVariableOrigin
::
Placeholder
(
p
)
if
p
==
error_placeholder
=>
Some
(
r
),
...
...
@@ -1345,12 +1413,44 @@ fn check_bound_universal_region(
// the AST-based checker uses a more conservative check,
// so to even see this error, one must pass in a special
// flag.
let
mut
diag
=
infcx
.tcx
.sess
.struct_span_err
(
span
,
"higher-ranked subtype error"
);
let
mut
diag
=
infcx
.tcx.sess
.struct_span_err
(
span
,
"higher-ranked subtype error"
);
diag
.emit
();
}
fn
check_pick_constraints
(
&
self
,
infcx
:
&
InferCtxt
<
'_
,
'tcx
>
,
mir_def_id
:
DefId
,
errors_buffer
:
&
mut
Vec
<
Diagnostic
>
,
// TODO
)
{
let
pick_constraints
=
self
.pick_constraints
.clone
();
for
p_c_i
in
pick_constraints
.all_indices
()
{
debug!
(
"check_pick_constraint(p_c_i={:?})"
,
p_c_i
);
let
p_c
=
&
pick_constraints
[
p_c_i
];
let
pick_region_vid
=
p_c
.pick_region_vid
;
debug!
(
"check_pick_constraint: pick_region_vid={:?} with value {}"
,
pick_region_vid
,
self
.region_value_str
(
pick_region_vid
));
let
option_regions
=
pick_constraints
.option_regions
(
p_c_i
);
debug!
(
"check_pick_constraint: option_regions={:?}"
,
option_regions
);
// did the pick-region wind up equal to any of the option regions?
if
let
Some
(
o
)
=
option_regions
.iter
()
.find
(|
&&
o_r
|
self
.eval_equal
(
o_r
,
p_c
.pick_region_vid
))
{
debug!
(
"check_pick_constraint: evaluated as equal to {:?}"
,
o
);
continue
;
}
// if not, report an error
let
region_scope_tree
=
&
infcx
.tcx
.region_scope_tree
(
mir_def_id
);
let
pick_region
=
infcx
.tcx
.mk_region
(
ty
::
ReVar
(
pick_region_vid
));
// XXX
opaque_types
::
unexpected_hidden_region_diagnostic
(
infcx
.tcx
,
Some
(
region_scope_tree
),
p_c
.opaque_type_def_id
,
p_c
.hidden_ty
,
pick_region
,
)
.buffer
(
errors_buffer
);
}
}
}
impl
<
'tcx
>
RegionDefinition
<
'tcx
>
{
...
...
@@ -1364,11 +1464,7 @@ fn new(universe: ty::UniverseIndex, rv_origin: RegionVariableOrigin) -> Self {
_
=>
NLLRegionVariableOrigin
::
Existential
,
};
Self
{
origin
,
universe
,
external_name
:
None
,
}
Self
{
origin
,
universe
,
external_name
:
None
}
}
}
...
...
@@ -1471,10 +1567,7 @@ fn subst_closure_mapping<T>(
if
let
ty
::
ReClosureBound
(
vid
)
=
r
{
closure_mapping
[
*
vid
]
}
else
{
bug!
(
"subst_closure_mapping: encountered non-closure bound free region {:?}"
,
r
)
bug!
(
"subst_closure_mapping: encountered non-closure bound free region {:?}"
,
r
)
}
})
}
...
...
src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
浏览文件 @
ec48b4eb
...
...
@@ -51,6 +51,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
}
pub
(
super
)
fn
convert_all
(
&
mut
self
,
query_constraints
:
&
QueryRegionConstraints
<
'tcx
>
)
{
debug!
(
"convert_all(query_constraints={:#?})"
,
query_constraints
);
let
QueryRegionConstraints
{
outlives
,
pick_constraints
}
=
query_constraints
;
// Annoying: to invoke `self.to_region_vid`, we need access to
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录