Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
0b4791e6
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,发现更多精彩内容 >>
提交
0b4791e6
编写于
9月 21, 2018
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
make NLL handle `IfEq` bounds by using SCC normalization
上级
0f5dae03
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
630 addition
and
9 deletion
+630
-9
src/librustc_data_structures/indexed_vec.rs
src/librustc_data_structures/indexed_vec.rs
+7
-0
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+113
-9
src/test/ui/nll/ty-outlives/issue-53789-1.rs
src/test/ui/nll/ty-outlives/issue-53789-1.rs
+91
-0
src/test/ui/nll/ty-outlives/issue-53789-2.rs
src/test/ui/nll/ty-outlives/issue-53789-2.rs
+251
-0
src/test/ui/nll/ty-outlives/projection-body.rs
src/test/ui/nll/ty-outlives/projection-body.rs
+25
-0
src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.rs
...ll/ty-outlives/projection-where-clause-env-wrong-bound.rs
+36
-0
src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.rs
...ty-outlives/projection-where-clause-env-wrong-lifetime.rs
+24
-0
src/test/ui/nll/ty-outlives/projection-where-clause-env.rs
src/test/ui/nll/ty-outlives/projection-where-clause-env.rs
+30
-0
src/test/ui/nll/ty-outlives/projection-where-clause-none.rs
src/test/ui/nll/ty-outlives/projection-where-clause-none.rs
+26
-0
src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs
src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs
+27
-0
未找到文件。
src/librustc_data_structures/indexed_vec.rs
浏览文件 @
0b4791e6
...
...
@@ -535,6 +535,13 @@ pub fn len(&self) -> usize {
self
.raw
.len
()
}
/// Gives the next index that will be assigned when `push` is
/// called.
#[inline]
pub
fn
next_index
(
&
self
)
->
I
{
I
::
new
(
self
.len
())
}
#[inline]
pub
fn
is_empty
(
&
self
)
->
bool
{
self
.raw
.is_empty
()
...
...
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
浏览文件 @
0b4791e6
...
...
@@ -69,6 +69,15 @@ pub struct RegionInferenceContext<'tcx> {
/// visible from this index.
scc_universes
:
IndexVec
<
ConstraintSccIndex
,
ty
::
UniverseIndex
>
,
/// Contains a "representative" from each SCC. This will be the
/// minimal RegionVid belonging to that universe. It is used as a
/// kind of hacky way to manage checking outlives relationships,
/// since we can 'canonicalize' each region to the representative
/// of its SCC and be sure that -- if they have the same repr --
/// they *must* be equal (though not having the same repr does not
/// mean they are unequal).
scc_representatives
:
IndexVec
<
ConstraintSccIndex
,
ty
::
RegionVid
>
,
/// The final inferred values of the region variables; we compute
/// one value per SCC. To get the value for any given *region*,
/// you first find which scc it is a part of.
...
...
@@ -208,6 +217,8 @@ pub(crate) fn new(
let
scc_universes
=
Self
::
compute_scc_universes
(
&
constraint_sccs
,
&
definitions
);
let
scc_representatives
=
Self
::
compute_scc_representatives
(
&
constraint_sccs
,
&
definitions
);
let
mut
result
=
Self
{
definitions
,
liveness_constraints
,
...
...
@@ -215,6 +226,7 @@ pub(crate) fn new(
constraint_graph
,
constraint_sccs
,
scc_universes
,
scc_representatives
,
scc_values
,
type_tests
,
universal_regions
,
...
...
@@ -251,6 +263,27 @@ fn compute_scc_universes(
scc_universes
}
/// For each SCC, we compute a unique `RegionVid` (in fact, the
/// minimal one that belongs to the SCC). See
/// `scc_representatives` field of `RegionInferenceContext` for
/// more details.
fn
compute_scc_representatives
(
constraints_scc
:
&
Sccs
<
RegionVid
,
ConstraintSccIndex
>
,
definitions
:
&
IndexVec
<
RegionVid
,
RegionDefinition
<
'tcx
>>
,
)
->
IndexVec
<
ConstraintSccIndex
,
ty
::
RegionVid
>
{
let
num_sccs
=
constraints_scc
.num_sccs
();
let
next_region_vid
=
definitions
.next_index
();
let
mut
scc_representatives
=
IndexVec
::
from_elem_n
(
next_region_vid
,
num_sccs
);
for
region_vid
in
definitions
.indices
()
{
let
scc
=
constraints_scc
.scc
(
region_vid
);
let
prev_min
=
scc_representatives
[
scc
];
scc_representatives
[
scc
]
=
region_vid
.min
(
prev_min
);
}
scc_representatives
}
/// Initializes the region variables for each universally
/// quantified region (lifetime parameter). The first N variables
/// always correspond to the regions appearing in the function
...
...
@@ -545,7 +578,14 @@ fn check_type_tests<'gcx>(
for
type_test
in
&
self
.type_tests
{
debug!
(
"check_type_test: {:?}"
,
type_test
);
if
self
.eval_verify_bound
(
mir
,
type_test
.lower_bound
,
&
type_test
.verify_bound
)
{
let
generic_ty
=
type_test
.generic_kind
.to_ty
(
tcx
);
if
self
.eval_verify_bound
(
tcx
,
mir
,
generic_ty
,
type_test
.lower_bound
,
&
type_test
.verify_bound
,
)
{
continue
;
}
...
...
@@ -679,7 +719,7 @@ fn try_promote_type_test<'gcx>(
// where `ur` is a local bound -- we are sometimes in a
// position to prove things that our caller cannot. See
// #53570 for an example.
if
self
.eval_verify_bound
(
mir
,
ur
,
&
type_test
.verify_bound
)
{
if
self
.eval_verify_bound
(
tcx
,
mir
,
generic_ty
,
ur
,
&
type_test
.verify_bound
)
{
continue
;
}
...
...
@@ -853,7 +893,9 @@ fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
/// `point`, and returns true or false.
fn
eval_verify_bound
(
&
self
,
tcx
:
TyCtxt
<
'_
,
'_
,
'tcx
>
,
mir
:
&
Mir
<
'tcx
>
,
generic_ty
:
Ty
<
'tcx
>
,
lower_bound
:
RegionVid
,
verify_bound
:
&
VerifyBound
<
'tcx
>
,
)
->
bool
{
...
...
@@ -863,23 +905,85 @@ fn eval_verify_bound(
);
match
verify_bound
{
VerifyBound
::
IfEq
(
..
)
=>
false
,
// FIXME
VerifyBound
::
IfEq
(
test_ty
,
verify_bound1
)
=>
{
self
.eval_if_eq
(
tcx
,
mir
,
generic_ty
,
lower_bound
,
test_ty
,
verify_bound1
)
}
VerifyBound
::
OutlivedBy
(
r
)
=>
{
let
r_vid
=
self
.to_region_vid
(
r
);
self
.eval_outlives
(
mir
,
r_vid
,
lower_bound
)
}
VerifyBound
::
AnyBound
(
verify_bounds
)
=>
verify_bounds
.iter
(
)
.any
(|
verify_bound
|
self
.eval_verify_bound
(
mir
,
lower_bound
,
verify_bound
)
),
VerifyBound
::
AnyBound
(
verify_bounds
)
=>
verify_bounds
.iter
()
.any
(|
verify_bound
|
{
self
.eval_verify_bound
(
tcx
,
mir
,
generic_ty
,
lower_bound
,
verify_bound
)
}
),
VerifyBound
::
AllBounds
(
verify_bounds
)
=>
verify_bounds
.iter
(
)
.all
(|
verify_bound
|
self
.eval_verify_bound
(
mir
,
lower_bound
,
verify_bound
)
),
VerifyBound
::
AllBounds
(
verify_bounds
)
=>
verify_bounds
.iter
()
.all
(|
verify_bound
|
{
self
.eval_verify_bound
(
tcx
,
mir
,
generic_ty
,
lower_bound
,
verify_bound
)
}
),
}
}
fn
eval_if_eq
(
&
self
,
tcx
:
TyCtxt
<
'_
,
'_
,
'tcx
>
,
mir
:
&
Mir
<
'tcx
>
,
generic_ty
:
Ty
<
'tcx
>
,
lower_bound
:
RegionVid
,
test_ty
:
Ty
<
'tcx
>
,
verify_bound
:
&
VerifyBound
<
'tcx
>
,
)
->
bool
{
let
generic_ty_normalized
=
self
.normalize_to_scc_representatives
(
tcx
,
generic_ty
);
let
test_ty_normalized
=
self
.normalize_to_scc_representatives
(
tcx
,
test_ty
);
if
generic_ty_normalized
==
test_ty_normalized
{
self
.eval_verify_bound
(
tcx
,
mir
,
generic_ty
,
lower_bound
,
verify_bound
)
}
else
{
false
}
}
/// This is a conservative normalization procedure. It takes every
/// free region in `value` and replaces it with the
/// "representative" of its SCC (see `scc_representatives` field).
/// We are guaranteed that if two values normalize to the same
/// thing, then they are equal; this is a conservative check in
/// that they could still be equal even if they normalize to
/// different results. (For example, there might be two regions
/// with the same value that are not in the same SCC).
///
/// NB. This is not an ideal approach and I would like to revisit
/// it. However, it works pretty well in practice. In particular,
/// this is needed to deal with projection outlives bounds like
///
/// <T as Foo<'0>>::Item: '1
///
/// In particular, this routine winds up being important when
/// there are bounds like `where <T as Foo<'a>>::Item: 'b` in the
/// environment. In this case, if we can show that `'0 == 'a`,
/// and that `'b: '1`, then we know that the clause is
/// satisfied. In such cases, particularly due to limitations of
/// the trait solver =), we usually wind up with a where-clause like
/// `T: Foo<'a>` in scope, which thus forces `'0 == 'a` to be added as
/// a constraint, and thus ensures that they are in the same SCC.
///
/// So why can't we do a more correct routine? Well, we could
/// *almost* use the `relate_tys` code, but the way it is
/// currently setup it creates inference variables to deal with
/// higher-ranked things and so forth, and right now the inference
/// context is not permitted to make more inference variables. So
/// we use this kind of hacky solution.
fn
normalize_to_scc_representatives
<
T
>
(
&
self
,
tcx
:
TyCtxt
<
'_
,
'_
,
'tcx
>
,
value
:
T
)
->
T
where
T
:
TypeFoldable
<
'tcx
>
,
{
tcx
.fold_regions
(
&
value
,
&
mut
false
,
|
r
,
_
db
|
{
let
vid
=
self
.to_region_vid
(
r
);
let
scc
=
self
.constraint_sccs
.scc
(
vid
);
let
repr
=
self
.scc_representatives
[
scc
];
tcx
.mk_region
(
ty
::
ReVar
(
repr
))
})
}
// Evaluate whether `sup_region: sub_region @ point`.
fn
eval_outlives
(
&
self
,
...
...
src/test/ui/nll/ty-outlives/issue-53789-1.rs
0 → 100644
浏览文件 @
0b4791e6
// Regression test for #53789.
//
// compile-pass
#![feature(nll)]
#![allow(unused_variables)]
use
std
::
collections
::
BTreeMap
;
trait
ValueTree
{
type
Value
;
}
trait
Strategy
{
type
Value
:
ValueTree
;
}
type
StrategyFor
<
A
>
=
StrategyType
<
'static
,
A
>
;
type
StrategyType
<
'a
,
A
>
=
<
A
as
Arbitrary
<
'a
>>
::
Strategy
;
impl
<
K
:
ValueTree
,
V
:
ValueTree
>
Strategy
for
(
K
,
V
)
{
type
Value
=
TupleValueTree
<
(
K
,
V
)
>
;
}
impl
<
K
:
ValueTree
,
V
:
ValueTree
>
ValueTree
for
TupleValueTree
<
(
K
,
V
)
>
{
type
Value
=
BTreeMapValueTree
<
K
,
V
>
;
}
struct
TupleValueTree
<
T
>
{
tree
:
T
,
}
struct
BTreeMapStrategy
<
K
,
V
>
(
std
::
marker
::
PhantomData
<
(
K
,
V
)
>
)
where
K
:
Strategy
,
V
:
Strategy
;
struct
BTreeMapValueTree
<
K
,
V
>
(
std
::
marker
::
PhantomData
<
(
K
,
V
)
>
)
where
K
:
ValueTree
,
V
:
ValueTree
;
impl
<
K
,
V
>
Strategy
for
BTreeMapStrategy
<
K
,
V
>
where
K
:
Strategy
,
V
:
Strategy
,
{
type
Value
=
BTreeMapValueTree
<
K
::
Value
,
V
::
Value
>
;
}
impl
<
K
,
V
>
ValueTree
for
BTreeMapValueTree
<
K
,
V
>
where
K
:
ValueTree
,
V
:
ValueTree
,
{
type
Value
=
BTreeMap
<
K
::
Value
,
V
::
Value
>
;
}
trait
Arbitrary
<
'a
>
:
Sized
{
fn
arbitrary_with
(
args
:
Self
::
Parameters
)
->
Self
::
Strategy
;
type
Parameters
;
type
Strategy
:
Strategy
<
Value
=
Self
::
ValueTree
>
;
type
ValueTree
:
ValueTree
<
Value
=
Self
>
;
}
impl
<
'a
,
A
,
B
>
Arbitrary
<
'a
>
for
BTreeMap
<
A
,
B
>
where
A
:
Arbitrary
<
'static
>
,
B
:
Arbitrary
<
'static
>
,
StrategyFor
<
A
>
:
'static
,
StrategyFor
<
B
>
:
'static
,
{
type
ValueTree
=
<
Self
::
Strategy
as
Strategy
>
::
Value
;
type
Parameters
=
(
A
::
Parameters
,
B
::
Parameters
);
type
Strategy
=
BTreeMapStrategy
<
A
::
Strategy
,
B
::
Strategy
>
;
fn
arbitrary_with
(
args
:
Self
::
Parameters
)
->
BTreeMapStrategy
<
A
::
Strategy
,
B
::
Strategy
>
{
let
(
a
,
b
)
=
args
;
btree_map
(
any_with
::
<
A
>
(
a
),
any_with
::
<
B
>
(
b
))
}
}
fn
btree_map
<
K
:
Strategy
+
'static
,
V
:
Strategy
>
(
key
:
K
,
value
:
V
)
->
BTreeMapStrategy
<
K
,
V
>
{
unimplemented!
()
}
fn
any_with
<
'a
,
A
:
Arbitrary
<
'a
>>
(
args
:
A
::
Parameters
)
->
StrategyType
<
'a
,
A
>
{
unimplemented!
()
}
fn
main
()
{
}
src/test/ui/nll/ty-outlives/issue-53789-2.rs
0 → 100644
浏览文件 @
0b4791e6
// Regression test for #53789.
//
// compile-pass
#![feature(nll)]
#![allow(unused_variables)]
use
std
::
collections
::
BTreeMap
;
use
std
::
ops
::
Range
;
use
std
::
cmp
::
Ord
;
macro_rules!
valuetree
{
()
=>
{
type
ValueTree
=
<
Self
::
Strategy
as
$crate
::
Strategy
>
::
Value
;
};
}
macro_rules!
product_unpack
{
(
$factor
:
pat
)
=>
{
(
$factor
,)
};
(
$
(
$factor
:
pat
),
*
)
=>
{
(
$
(
$factor
),
*
)
};
(
$
(
$factor
:
pat
),
*
,)
=>
{
(
$
(
$factor
),
*
)
};
}
macro_rules!
product_type
{
(
$factor
:
ty
)
=>
{
(
$factor
,)
};
(
$
(
$factor
:
ty
),
*
)
=>
{
(
$
(
$factor
,
)
*
)
};
(
$
(
$factor
:
ty
),
*
,)
=>
{
(
$
(
$factor
,
)
*
)
};
}
macro_rules!
default
{
(
$type
:
ty
,
$val
:
expr
)
=>
{
impl
Default
for
$type
{
fn
default
()
->
Self
{
$val
.into
()
}
}
};
}
// Pervasive internal sugar
macro_rules!
mapfn
{
(
$
(
#[
$
meta:meta]
)
*
[
$
(
$vis:tt
)
*
]
fn
$name:ident
[
$
(
$gen:tt
)
*
](
$parm:ident
:
$input:ty
)
->
$output:ty
{
$
(
$body:tt
)
*
})
=>
{
$
(
#[
$
meta]
)
*
#[derive(Clone,
Copy)]
$
(
$vis
)
*
struct
$name
;
impl
$
(
$gen
)
*
statics
::
MapFn
<
$input
>
for
$name
{
type
Output
=
$output
;
}
}
}
macro_rules!
opaque_strategy_wrapper
{
(
$
(
#[
$
smeta:meta]
)
*
pub
struct
$stratname:ident
[
$
(
$sgen:tt
)
*
][
$
(
$swhere:tt
)
*
]
(
$innerstrat:ty
)
->
$stratvtty:ty
;
$
(
#[
$
vmeta:meta]
)
*
pub
struct
$vtname:ident
[
$
(
$vgen:tt
)
*
][
$
(
$vwhere:tt
)
*
]
(
$innervt:ty
)
->
$actualty:ty
;
)
=>
{
$
(
#[
$
smeta]
)
*
struct
$stratname
$
(
$sgen
)
*
(
std
::
marker
::
PhantomData
<
(
K
,
V
)
>
)
$
(
$swhere
)
*
;
$
(
#[
$
vmeta]
)
*
struct
$vtname
$
(
$vgen
)
*
(
$innervt
)
$
(
$vwhere
)
*
;
impl
$
(
$sgen
)
*
Strategy
for
$stratname
$
(
$sgen
)
*
$
(
$swhere
)
*
{
type
Value
=
$stratvtty
;
}
impl
$
(
$vgen
)
*
ValueTree
for
$vtname
$
(
$vgen
)
*
$
(
$vwhere
)
*
{
type
Value
=
$actualty
;
}
}
}
trait
ValueTree
{
type
Value
;
}
trait
Strategy
{
type
Value
:
ValueTree
;
}
#[derive(Clone)]
struct
VecStrategy
<
T
:
Strategy
>
{
element
:
T
,
size
:
Range
<
usize
>
,
}
fn
vec
<
T
:
Strategy
>
(
element
:
T
,
size
:
Range
<
usize
>
)
->
VecStrategy
<
T
>
{
VecStrategy
{
element
:
element
,
size
:
size
,
}
}
type
ValueFor
<
S
>
=
<<
S
as
Strategy
>
::
Value
as
ValueTree
>
::
Value
;
trait
Arbitrary
<
'a
>
:
Sized
{
fn
arbitrary_with
(
args
:
Self
::
Parameters
)
->
Self
::
Strategy
;
type
Parameters
:
Default
;
type
Strategy
:
Strategy
<
Value
=
Self
::
ValueTree
>
;
type
ValueTree
:
ValueTree
<
Value
=
Self
>
;
}
type
StrategyFor
<
A
>
=
StrategyType
<
'static
,
A
>
;
type
StrategyType
<
'a
,
A
>
=
<
A
as
Arbitrary
<
'a
>>
::
Strategy
;
//#[derive(Clone, PartialEq, Eq, Hash, Debug, From, Into)]
struct
SizeBounds
(
Range
<
usize
>
);
default!
(
SizeBounds
,
0
..
100
);
impl
From
<
Range
<
usize
>>
for
SizeBounds
{
fn
from
(
high
:
Range
<
usize
>
)
->
Self
{
unimplemented!
()
}
}
impl
From
<
SizeBounds
>
for
Range
<
usize
>
{
fn
from
(
high
:
SizeBounds
)
->
Self
{
unimplemented!
()
}
}
fn
any_with
<
'a
,
A
:
Arbitrary
<
'a
>>
(
args
:
A
::
Parameters
)
->
StrategyType
<
'a
,
A
>
{
unimplemented!
()
}
impl
<
K
:
ValueTree
,
V
:
ValueTree
>
Strategy
for
(
K
,
V
)
where
<
K
as
ValueTree
>
::
Value
:
Ord
{
type
Value
=
TupleValueTree
<
(
K
,
V
)
>
;
}
impl
<
K
:
ValueTree
,
V
:
ValueTree
>
ValueTree
for
TupleValueTree
<
(
K
,
V
)
>
where
<
K
as
ValueTree
>
::
Value
:
Ord
{
type
Value
=
BTreeMapValueTree
<
K
,
V
>
;
}
#[derive(Clone)]
struct
VecValueTree
<
T
:
ValueTree
>
{
elements
:
Vec
<
T
>
,
}
#[derive(Clone,
Copy)]
struct
TupleValueTree
<
T
>
{
tree
:
T
,
}
opaque_strategy_wrapper!
{
#[derive(Clone)]
pub
struct
BTreeMapStrategy
[
<
K
,
V
>
]
[
where
K
:
Strategy
,
V
:
Strategy
,
ValueFor
<
K
>
:
Ord
](
statics
::
Filter
<
statics
::
Map
<
VecStrategy
<
(
K
,
V
)
>
,
VecToBTreeMap
>
,
MinSize
>
)
->
BTreeMapValueTree
<
K
::
Value
,
V
::
Value
>
;
#[derive(Clone)]
pub
struct
BTreeMapValueTree
[
<
K
,
V
>
]
[
where
K
:
ValueTree
,
V
:
ValueTree
,
K
::
Value
:
Ord
](
statics
::
Filter
<
statics
::
Map
<
VecValueTree
<
TupleValueTree
<
(
K
,
V
)
>>
,
VecToBTreeMap
>
,
MinSize
>
)
->
BTreeMap
<
K
::
Value
,
V
::
Value
>
;
}
type
RangedParams2
<
A
,
B
>
=
product_type!
[
SizeBounds
,
A
,
B
];
impl
<
'a
,
A
,
B
>
Arbitrary
<
'a
>
for
BTreeMap
<
A
,
B
>
where
A
:
Arbitrary
<
'static
>
+
Ord
,
B
:
Arbitrary
<
'static
>
,
StrategyFor
<
A
>
:
'static
,
StrategyFor
<
B
>
:
'static
,
{
valuetree!
();
type
Parameters
=
RangedParams2
<
A
::
Parameters
,
B
::
Parameters
>
;
type
Strategy
=
BTreeMapStrategy
<
A
::
Strategy
,
B
::
Strategy
>
;
fn
arbitrary_with
(
args
:
Self
::
Parameters
)
->
Self
::
Strategy
{
let
product_unpack!
[
range
,
a
,
b
]
=
args
;
btree_map
(
any_with
::
<
A
>
(
a
),
any_with
::
<
B
>
(
b
),
range
.into
())
}
}
#[derive(Clone,
Copy)]
struct
MinSize
(
usize
);
mapfn!
{
[]
fn
VecToBTreeMap
[
<
K
:
Ord
,
V
>
]
(
vec
:
Vec
<
(
K
,
V
)
>
)
->
BTreeMap
<
K
,
V
>
{
vec
.into_iter
()
.collect
()
}
}
fn
btree_map
<
K
:
Strategy
+
'static
,
V
:
Strategy
+
'static
>
(
key
:
K
,
value
:
V
,
size
:
Range
<
usize
>
)
->
BTreeMapStrategy
<
K
,
V
>
where
ValueFor
<
K
>
:
Ord
{
unimplemented!
()
}
mod
statics
{
pub
(
super
)
trait
MapFn
<
T
>
{
type
Output
;
}
#[derive(Clone)]
pub
struct
Filter
<
S
,
F
>
{
source
:
S
,
fun
:
F
,
}
impl
<
S
,
F
>
Filter
<
S
,
F
>
{
pub
fn
new
(
source
:
S
,
whence
:
String
,
filter
:
F
)
->
Self
{
unimplemented!
()
}
}
#[derive(Clone)]
pub
struct
Map
<
S
,
F
>
{
source
:
S
,
fun
:
F
,
}
impl
<
S
,
F
>
Map
<
S
,
F
>
{
pub
fn
new
(
source
:
S
,
fun
:
F
)
->
Self
{
unimplemented!
()
}
}
}
fn
main
()
{
}
src/test/ui/nll/ty-outlives/projection-body.rs
0 → 100644
浏览文件 @
0b4791e6
// Test that when we infer the lifetime to a subset of the fn body, it
// works out.
trait
MyTrait
<
'a
>
{
type
Output
;
}
fn
foo1
<
T
>
()
where
for
<
'x
>
T
:
MyTrait
<
'x
>
,
{
// Here the region `'c` in `<T as MyTrait<'c>>::Output` will be
// inferred to a subset of the fn body.
let
x
=
bar
::
<
T
::
Output
>
();
drop
(
x
);
}
fn
bar
<
'a
,
T
>
()
->
&
'a
()
where
T
:
'a
,
{
&
()
}
fn
main
()
{}
src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.rs
0 → 100644
浏览文件 @
0b4791e6
#![feature(nll)]
// Test that we are able to establish that `<T as
// MyTrait<'a>>::Output` outlives `'b` here. We need to prove however
// that `<T as MyTrait<'a>>::Output` outlives `'a`, so we also have to
// prove that `'b: 'a`.
trait
MyTrait
<
'a
>
{
type
Output
;
}
fn
foo1
<
'a
,
'b
,
T
>
()
->
&
'a
()
where
T
:
MyTrait
<
'a
>
,
<
T
as
MyTrait
<
'a
>>
::
Output
:
'b
,
{
bar
::
<
T
::
Output
>
()
//~ ERROR may not live long enough
}
fn
foo2
<
'a
,
'b
,
T
>
()
->
&
'a
()
where
T
:
MyTrait
<
'a
>
,
<
T
as
MyTrait
<
'a
>>
::
Output
:
'b
,
'b
:
'a
,
{
bar
::
<
T
::
Output
>
()
// OK
}
fn
bar
<
'a
,
T
>
()
->
&
'a
()
where
T
:
'a
,
{
&
()
}
fn
main
()
{}
src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.rs
0 → 100644
浏览文件 @
0b4791e6
// Test that if we need to prove that `<T as MyTrait<'a>>::Output:
// 'a`, but we only know that `<T as MyTrait<'b>>::Output: 'a`, that
// doesn't suffice.
trait
MyTrait
<
'a
>
{
type
Output
;
}
fn
foo1
<
'a
,
'b
,
T
>
()
->
&
'a
()
where
for
<
'x
>
T
:
MyTrait
<
'x
>
,
<
T
as
MyTrait
<
'b
>>
::
Output
:
'a
,
{
bar
::
<<
T
as
MyTrait
<
'a
>>
::
Output
>
()
//~ ERROR the associated type `<T as MyTrait<'a>>::Output` may not live long enough
}
fn
bar
<
'a
,
T
>
()
->
&
'a
()
where
T
:
'a
,
{
&
()
}
fn
main
()
{}
src/test/ui/nll/ty-outlives/projection-where-clause-env.rs
0 → 100644
浏览文件 @
0b4791e6
#![feature(nll)]
// Test that when we have a `<T as MyTrait<'a>>::Output: 'a`
// relationship in the environment we take advantage of it. In this
// case, that means we **don't** have to prove that `T: 'a`.
//
// Regression test for #53121.
//
// compile-pass
trait
MyTrait
<
'a
>
{
type
Output
;
}
fn
foo
<
'a
,
T
>
()
->
&
'a
()
where
T
:
MyTrait
<
'a
>
,
<
T
as
MyTrait
<
'a
>>
::
Output
:
'a
,
{
bar
::
<
T
::
Output
>
()
}
fn
bar
<
'a
,
T
>
()
->
&
'a
()
where
T
:
'a
,
{
&
()
}
fn
main
()
{}
src/test/ui/nll/ty-outlives/projection-where-clause-none.rs
0 → 100644
浏览文件 @
0b4791e6
#![feature(nll)]
// Test that we are NOT able to establish that `<T as
// MyTrait<'a>>::Output: 'a` outlives `'a` here -- we have only one
// recourse, which is to prove that `T: 'a` and `'a: 'a`, but we don't
// know that `T: 'a`.
trait
MyTrait
<
'a
>
{
type
Output
;
}
fn
foo
<
'a
,
T
>
()
->
&
'a
()
where
T
:
MyTrait
<
'a
>
,
{
bar
::
<
T
::
Output
>
()
//~ ERROR the parameter type `T` may not live long enough
}
fn
bar
<
'a
,
T
>
()
->
&
'a
()
where
T
:
'a
,
{
&
()
}
fn
main
()
{}
src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs
0 → 100644
浏览文件 @
0b4791e6
#![feature(nll)]
// Test that we are able to establish that `<T as
// MyTrait<'a>>::Output: 'a` outlives `'a` (because the trait says
// so).
//
// compile-pass
trait
MyTrait
<
'a
>
{
type
Output
:
'a
;
}
fn
foo
<
'a
,
T
>
()
->
&
'a
()
where
T
:
MyTrait
<
'a
>
,
{
bar
::
<
T
::
Output
>
()
}
fn
bar
<
'a
,
T
>
()
->
&
'a
()
where
T
:
'a
,
{
&
()
}
fn
main
()
{}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录