Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
ba1849da
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,发现更多精彩内容 >>
提交
ba1849da
编写于
1月 13, 2017
作者:
E
Eduard-Mihai Burtescu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rustc: move most of lifetime elision to resolve_lifetimes.
上级
bbc34142
变更
13
展开全部
隐藏空白更改
内联
并排
Showing
13 changed file
with
703 addition
and
602 deletion
+703
-602
src/librustc/diagnostics.rs
src/librustc/diagnostics.rs
+63
-0
src/librustc/hir/lowering.rs
src/librustc/hir/lowering.rs
+2
-1
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/resolve_lifetime.rs
+492
-10
src/librustc_typeck/astconv.rs
src/librustc_typeck/astconv.rs
+55
-282
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/mod.rs
+15
-11
src/librustc_typeck/collect.rs
src/librustc_typeck/collect.rs
+29
-53
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/diagnostics.rs
+3
-69
src/librustc_typeck/rscope.rs
src/librustc_typeck/rscope.rs
+0
-168
src/test/compile-fail/E0106.rs
src/test/compile-fail/E0106.rs
+12
-0
src/test/compile-fail/E0107.rs
src/test/compile-fail/E0107.rs
+0
-3
src/test/compile-fail/associated-types-project-from-hrtb-in-struct.rs
...pile-fail/associated-types-project-from-hrtb-in-struct.rs
+5
-4
src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs
...ifetime-elision-return-type-requires-explicit-lifetime.rs
+24
-0
src/test/compile-fail/rfc1623.rs
src/test/compile-fail/rfc1623.rs
+3
-1
未找到文件。
src/librustc/diagnostics.rs
浏览文件 @
ba1849da
...
...
@@ -327,6 +327,69 @@ struct ListNode {
This works because `Box` is a pointer, so its size is well-known.
"##
,
E0106
:
r##"
This error indicates that a lifetime is missing from a type. If it is an error
inside a function signature, the problem may be with failing to adhere to the
lifetime elision rules (see below).
Here are some simple examples of where you'll run into this error:
```compile_fail,E0106
struct Foo { x: &bool } // error
struct Foo<'a> { x: &'a bool } // correct
enum Bar { A(u8), B(&bool), } // error
enum Bar<'a> { A(u8), B(&'a bool), } // correct
type MyStr = &str; // error
type MyStr<'a> = &'a str; // correct
```
Lifetime elision is a special, limited kind of inference for lifetimes in
function signatures which allows you to leave out lifetimes in certain cases.
For more background on lifetime elision see [the book][book-le].
The lifetime elision rules require that any function signature with an elided
output lifetime must either have
- exactly one input lifetime
- or, multiple input lifetimes, but the function must also be a method with a
`&self` or `&mut self` receiver
In the first case, the output lifetime is inferred to be the same as the unique
input lifetime. In the second case, the lifetime is instead inferred to be the
same as the lifetime on `&self` or `&mut self`.
Here are some examples of elision errors:
```compile_fail,E0106
// error, no input lifetimes
fn foo() -> &str { }
// error, `x` and `y` have distinct lifetimes inferred
fn bar(x: &str, y: &str) -> &str { }
// error, `y`'s lifetime is inferred to be distinct from `x`'s
fn baz<'a>(x: &'a str, y: &str) -> &str { }
```
Here's an example that is currently an error, but may work in a future version
of Rust:
```compile_fail,E0106
struct Foo<'a>(&'a str);
trait Quux { }
impl Quux for Foo { }
```
Lifetime elision in implementation headers was part of the lifetime elision
RFC. It is, however, [currently unimplemented][iss15872].
[book-le]: https://doc.rust-lang.org/nightly/book/lifetimes.html#lifetime-elision
[iss15872]: https://github.com/rust-lang/rust/issues/15872
"##
,
E0109
:
r##"
You tried to give a type parameter to a type which doesn't need it. Erroneous
code example:
...
...
src/librustc/hir/lowering.rs
浏览文件 @
ba1849da
...
...
@@ -314,9 +314,10 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
TyKind
::
Slice
(
ref
ty
)
=>
hir
::
TySlice
(
self
.lower_ty
(
ty
)),
TyKind
::
Ptr
(
ref
mt
)
=>
hir
::
TyPtr
(
self
.lower_mt
(
mt
)),
TyKind
::
Rptr
(
ref
region
,
ref
mt
)
=>
{
let
span
=
Span
{
hi
:
t
.span.lo
,
..
t
.span
};
let
lifetime
=
match
*
region
{
Some
(
ref
lt
)
=>
self
.lower_lifetime
(
lt
),
None
=>
self
.elided_lifetime
(
t
.
span
)
None
=>
self
.elided_lifetime
(
span
)
};
hir
::
TyRptr
(
lifetime
,
self
.lower_mt
(
mt
))
}
...
...
src/librustc/middle/resolve_lifetime.rs
浏览文件 @
ba1849da
此差异已折叠。
点击以展开。
src/librustc_typeck/astconv.rs
浏览文件 @
ba1849da
此差异已折叠。
点击以展开。
src/librustc_typeck/check/mod.rs
浏览文件 @
ba1849da
...
...
@@ -97,7 +97,7 @@
use
rustc
::
ty
::
fold
::{
BottomUpFolder
,
TypeFoldable
};
use
rustc
::
ty
::
util
::{
Representability
,
IntTypeExt
};
use
require_c_abi_if_variadic
;
use
rscope
::
{
ElisionFailureInfo
,
RegionScope
}
;
use
rscope
::
RegionScope
;
use
session
::{
Session
,
CompileResult
};
use
CrateCtxt
;
use
TypeAndSubsts
;
...
...
@@ -1410,6 +1410,15 @@ fn get_type_parameter_bounds(&self,
Ok
(
r
)
}
fn
re_infer
(
&
self
,
span
:
Span
,
def
:
Option
<&
ty
::
RegionParameterDef
>
)
->
&
'tcx
ty
::
Region
{
let
v
=
match
def
{
Some
(
def
)
=>
infer
::
EarlyBoundRegion
(
span
,
def
.name
),
None
=>
infer
::
MiscVariable
(
span
)
};
self
.next_region_var
(
v
)
}
fn
ty_infer
(
&
self
,
span
:
Span
)
->
Ty
<
'tcx
>
{
self
.next_ty_var
(
TypeVariableOrigin
::
TypeInference
(
span
))
}
...
...
@@ -1465,15 +1474,6 @@ fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
// be some expression).
*
self
.next_region_var
(
infer
::
MiscVariable
(
span
))
}
fn
anon_region
(
&
self
,
span
:
Span
,
def
:
Option
<&
ty
::
RegionParameterDef
>
)
->
Result
<
ty
::
Region
,
Option
<
Vec
<
ElisionFailureInfo
>>>
{
let
v
=
match
def
{
Some
(
def
)
=>
infer
::
EarlyBoundRegion
(
span
,
def
.name
),
None
=>
infer
::
MiscVariable
(
span
)
};
Ok
(
*
self
.next_region_var
(
v
))
}
}
/// Controls whether the arguments are tupled. This is used for the call
...
...
@@ -4408,7 +4408,11 @@ pub fn instantiate_value_path(&self,
None
=>
&
[]
};
AstConv
::
opt_ast_region_to_region
(
self
,
self
,
span
,
lifetimes
.get
(
i
),
Some
(
def
))
if
let
Some
(
lifetime
)
=
lifetimes
.get
(
i
)
{
AstConv
::
ast_region_to_region
(
self
,
lifetime
,
Some
(
def
))
}
else
{
self
.re_infer
(
span
,
Some
(
def
))
}
},
|
def
,
substs
|
{
let
mut
i
=
def
.index
as
usize
;
...
...
src/librustc_typeck/collect.rs
浏览文件 @
ba1849da
...
...
@@ -437,6 +437,11 @@ fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
None
}
fn
re_infer
(
&
self
,
span
:
Span
,
_
def
:
Option
<&
ty
::
RegionParameterDef
>
)
->
&
'tcx
ty
::
Region
{
span_bug!
(
span
,
"unelided lifetime in signature"
);
}
fn
ty_infer
(
&
self
,
span
:
Span
)
->
Ty
<
'tcx
>
{
struct_span_err!
(
self
.tcx
()
.sess
,
...
...
@@ -639,8 +644,6 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
container
:
AssociatedItemContainer
,
id
:
ast
::
NodeId
,
sig
:
&
hir
::
MethodSig
,
untransformed_rcvr_ty
:
Ty
<
'tcx
>
,
body
:
Option
<
hir
::
BodyId
>
,
rcvr_ty_predicates
:
&
ty
::
GenericPredicates
<
'tcx
>
,)
{
let
def_id
=
ccx
.tcx.hir
.local_def_id
(
id
);
let
ty_generics
=
generics_of_def_id
(
ccx
,
def_id
);
...
...
@@ -652,14 +655,8 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
ImplContainer
(
_
)
=>
Some
(
AnonTypeScope
::
new
(
def_id
)),
TraitContainer
(
_
)
=>
None
};
let
assoc_item
=
ccx
.tcx
.associated_item
(
def_id
);
let
self_value_ty
=
if
assoc_item
.method_has_self_argument
{
Some
(
untransformed_rcvr_ty
)
}
else
{
None
};
let
fty
=
AstConv
::
ty_of_method
(
&
ccx
.icx
(
&
(
rcvr_ty_predicates
,
&
sig
.generics
)),
sig
,
self_value_ty
,
body
,
anon_scope
);
let
fty
=
AstConv
::
ty_of_fn
(
&
ccx
.icx
(
&
(
rcvr_ty_predicates
,
&
sig
.generics
)),
sig
.unsafety
,
sig
.abi
,
&
sig
.decl
,
anon_scope
);
let
substs
=
mk_item_substs
(
&
ccx
.icx
(
&
(
rcvr_ty_predicates
,
&
sig
.generics
)),
ccx
.tcx.hir
.span
(
id
),
def_id
);
...
...
@@ -876,14 +873,9 @@ fn convert_trait_item(ccx: &CrateCtxt, trait_item: &hir::TraitItem) {
convert_associated_type
(
ccx
,
TraitContainer
(
trait_def_id
),
trait_item
.id
,
typ
);
}
hir
::
TraitItemKind
::
Method
(
ref
sig
,
ref
method
)
=>
{
let
body
=
match
*
method
{
hir
::
TraitMethod
::
Required
(
_
)
=>
None
,
hir
::
TraitMethod
::
Provided
(
body
)
=>
Some
(
body
)
};
hir
::
TraitItemKind
::
Method
(
ref
sig
,
_
)
=>
{
convert_method
(
ccx
,
TraitContainer
(
trait_def_id
),
trait_item
.id
,
sig
,
tcx
.mk_self_type
(),
body
,
&
trait_predicates
);
trait_item
.id
,
sig
,
&
trait_predicates
);
}
}
}
...
...
@@ -896,7 +888,6 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) {
let
impl_def_id
=
tcx
.hir
.get_parent_did
(
impl_item
.id
);
let
impl_predicates
=
tcx
.item_predicates
(
impl_def_id
);
let
impl_trait_ref
=
tcx
.impl_trait_ref
(
impl_def_id
);
let
impl_self_ty
=
tcx
.item_type
(
impl_def_id
);
match
impl_item
.node
{
hir
::
ImplItemKind
::
Const
(
ref
ty
,
_
)
=>
{
...
...
@@ -923,10 +914,8 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) {
convert_associated_type
(
ccx
,
ImplContainer
(
impl_def_id
),
impl_item
.id
,
Some
(
typ
));
}
hir
::
ImplItemKind
::
Method
(
ref
sig
,
body
)
=>
{
convert_method
(
ccx
,
ImplContainer
(
impl_def_id
),
impl_item
.id
,
sig
,
impl_self_ty
,
Some
(
body
),
&
impl_predicates
);
hir
::
ImplItemKind
::
Method
(
ref
sig
,
_
)
=>
{
convert_method
(
ccx
,
ImplContainer
(
impl_def_id
),
impl_item
.id
,
sig
,
&
impl_predicates
);
}
}
}
...
...
@@ -1472,7 +1461,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
index
:
own_start
+
i
as
u32
,
def_id
:
tcx
.hir
.local_def_id
(
l
.lifetime.id
),
bounds
:
l
.bounds
.iter
()
.map
(|
l
|
{
AstConv
::
ast_region_to_region
(
&
ccx
.icx
(
&
()),
l
)
AstConv
::
ast_region_to_region
(
&
ccx
.icx
(
&
()),
l
,
None
)
})
.collect
(),
pure_wrt_drop
:
l
.pure_wrt_drop
,
}
...
...
@@ -1545,11 +1534,11 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
NodeItem
(
item
)
=>
{
match
item
.node
{
ItemStatic
(
ref
t
,
..
)
|
ItemConst
(
ref
t
,
_
)
=>
{
ccx
.icx
(
&
())
.to_ty
(
&
StaticRscope
::
new
(
&
ccx
.tcx
)
,
&
t
)
ccx
.icx
(
&
())
.to_ty
(
&
ExplicitRscope
,
&
t
)
}
ItemFn
(
ref
decl
,
unsafety
,
_
,
abi
,
ref
generics
,
body
)
=>
{
let
tofd
=
AstConv
::
ty_of_
bare_
fn
(
&
ccx
.icx
(
generics
),
unsafety
,
abi
,
&
decl
,
body
,
Some
(
AnonTypeScope
::
new
(
def_id
)));
ItemFn
(
ref
decl
,
unsafety
,
_
,
abi
,
ref
generics
,
_
)
=>
{
let
tofd
=
AstConv
::
ty_of_fn
(
&
ccx
.icx
(
generics
),
unsafety
,
abi
,
&
decl
,
Some
(
AnonTypeScope
::
new
(
def_id
)));
let
substs
=
mk_item_substs
(
&
ccx
.icx
(
generics
),
item
.span
,
def_id
);
ccx
.tcx
.mk_fn_def
(
def_id
,
substs
,
tofd
)
}
...
...
@@ -1765,7 +1754,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
name
:
param
.lifetime.name
}));
for
bound
in
&
param
.bounds
{
let
bound_region
=
AstConv
::
ast_region_to_region
(
&
ccx
.icx
(
&
()),
bound
);
let
bound_region
=
AstConv
::
ast_region_to_region
(
&
ccx
.icx
(
&
()),
bound
,
None
);
let
outlives
=
ty
::
Binder
(
ty
::
OutlivesPredicate
(
region
,
bound_region
));
predicates
.push
(
outlives
.to_predicate
());
}
...
...
@@ -1816,7 +1805,9 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
}
&
hir
::
TyParamBound
::
RegionTyParamBound
(
ref
lifetime
)
=>
{
let
region
=
AstConv
::
ast_region_to_region
(
&
ccx
.icx
(
&
()),
lifetime
);
let
region
=
AstConv
::
ast_region_to_region
(
&
ccx
.icx
(
&
()),
lifetime
,
None
);
let
pred
=
ty
::
Binder
(
ty
::
OutlivesPredicate
(
ty
,
region
));
predicates
.push
(
ty
::
Predicate
::
TypeOutlives
(
pred
))
}
...
...
@@ -1825,9 +1816,9 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
}
&
hir
::
WherePredicate
::
RegionPredicate
(
ref
region_pred
)
=>
{
let
r1
=
AstConv
::
ast_region_to_region
(
&
ccx
.icx
(
&
()),
&
region_pred
.lifetime
);
let
r1
=
AstConv
::
ast_region_to_region
(
&
ccx
.icx
(
&
()),
&
region_pred
.lifetime
,
None
);
for
bound
in
&
region_pred
.bounds
{
let
r2
=
AstConv
::
ast_region_to_region
(
&
ccx
.icx
(
&
()),
bound
);
let
r2
=
AstConv
::
ast_region_to_region
(
&
ccx
.icx
(
&
()),
bound
,
None
);
let
pred
=
ty
::
Binder
(
ty
::
OutlivesPredicate
(
r1
,
r2
));
predicates
.push
(
ty
::
Predicate
::
RegionOutlives
(
pred
))
}
...
...
@@ -1935,7 +1926,7 @@ fn from_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
hir
::
TraitTyParamBound
(
..
)
=>
None
,
hir
::
RegionTyParamBound
(
ref
lifetime
)
=>
Some
(
AstConv
::
ast_region_to_region
(
&
ccx
.icx
(
&
()),
lifetime
)),
Some
(
AstConv
::
ast_region_to_region
(
&
ccx
.icx
(
&
()),
lifetime
,
None
)),
}
})
.collect
()
...
...
@@ -1997,7 +1988,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
})
.collect
();
let
region_bounds
=
region_bounds
.into_iter
()
.map
(|
r
|
{
astconv
.ast_region_to_region
(
r
)
astconv
.ast_region_to_region
(
r
,
None
)
})
.collect
();
trait_bounds
.sort_by
(|
a
,
b
|
a
.def_id
()
.cmp
(
&
b
.def_id
()));
...
...
@@ -2039,7 +2030,7 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
.collect
()
}
hir
::
RegionTyParamBound
(
ref
lifetime
)
=>
{
let
region
=
astconv
.ast_region_to_region
(
lifetime
);
let
region
=
astconv
.ast_region_to_region
(
lifetime
,
None
);
let
pred
=
ty
::
Binder
(
ty
::
OutlivesPredicate
(
param_ty
,
region
));
vec!
[
ty
::
Predicate
::
TypeOutlives
(
pred
)]
}
...
...
@@ -2057,18 +2048,7 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
abi
:
abi
::
Abi
)
->
Ty
<
'tcx
>
{
let
rb
=
BindingRscope
::
new
();
let
input_tys
=
decl
.inputs
.iter
()
.map
(|
a
|
AstConv
::
ty_of_arg
(
&
ccx
.icx
(
ast_generics
),
&
rb
,
a
,
None
))
.collect
::
<
Vec
<
_
>>
();
let
output
=
match
decl
.output
{
hir
::
Return
(
ref
ty
)
=>
AstConv
::
ast_ty_to_ty
(
&
ccx
.icx
(
ast_generics
),
&
rb
,
&
ty
),
hir
::
DefaultReturn
(
..
)
=>
ccx
.tcx
.mk_nil
(),
};
let
fty
=
AstConv
::
ty_of_fn
(
&
ccx
.icx
(
ast_generics
),
hir
::
Unsafety
::
Unsafe
,
abi
,
decl
,
None
);
// feature gate SIMD types in FFI, since I (huonw) am not sure the
// ABIs are handled at all correctly.
...
...
@@ -2084,21 +2064,17 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
.emit
();
}
};
for
(
input
,
ty
)
in
decl
.inputs
.iter
()
.zip
(
&
input_tys
)
{
for
(
input
,
ty
)
in
decl
.inputs
.iter
()
.zip
(
*
fty
.sig
.inputs
()
.skip_binder
()
)
{
check
(
&
input
,
ty
)
}
if
let
hir
::
Return
(
ref
ty
)
=
decl
.output
{
check
(
&
ty
,
output
)
check
(
&
ty
,
*
fty
.sig
.output
()
.skip_binder
()
)
}
}
let
id
=
ccx
.tcx.hir
.as_local_node_id
(
def_id
)
.unwrap
();
let
substs
=
mk_item_substs
(
&
ccx
.icx
(
ast_generics
),
ccx
.tcx.hir
.span
(
id
),
def_id
);
ccx
.tcx
.mk_fn_def
(
def_id
,
substs
,
ccx
.tcx
.mk_bare_fn
(
ty
::
BareFnTy
{
abi
:
abi
,
unsafety
:
hir
::
Unsafety
::
Unsafe
,
sig
:
ty
::
Binder
(
ccx
.tcx
.mk_fn_sig
(
input_tys
.into_iter
(),
output
,
decl
.variadic
)),
}))
ccx
.tcx
.mk_fn_def
(
def_id
,
substs
,
fty
)
}
pub
fn
mk_item_substs
<
'gcx
:
'tcx
,
'tcx
>
(
astconv
:
&
AstConv
<
'gcx
,
'tcx
>
,
...
...
src/librustc_typeck/diagnostics.rs
浏览文件 @
ba1849da
...
...
@@ -1412,85 +1412,19 @@ fn main() {
```
"##
,
E0106
:
r##"
This error indicates that a lifetime is missing from a type. If it is an error
inside a function signature, the problem may be with failing to adhere to the
lifetime elision rules (see below).
Here are some simple examples of where you'll run into this error:
```compile_fail,E0106
struct Foo { x: &bool } // error
struct Foo<'a> { x: &'a bool } // correct
enum Bar { A(u8), B(&bool), } // error
enum Bar<'a> { A(u8), B(&'a bool), } // correct
type MyStr = &str; // error
type MyStr<'a> = &'a str; // correct
```
Lifetime elision is a special, limited kind of inference for lifetimes in
function signatures which allows you to leave out lifetimes in certain cases.
For more background on lifetime elision see [the book][book-le].
The lifetime elision rules require that any function signature with an elided
output lifetime must either have
- exactly one input lifetime
- or, multiple input lifetimes, but the function must also be a method with a
`&self` or `&mut self` receiver
In the first case, the output lifetime is inferred to be the same as the unique
input lifetime. In the second case, the lifetime is instead inferred to be the
same as the lifetime on `&self` or `&mut self`.
Here are some examples of elision errors:
```compile_fail,E0106
// error, no input lifetimes
fn foo() -> &str { }
// error, `x` and `y` have distinct lifetimes inferred
fn bar(x: &str, y: &str) -> &str { }
// error, `y`'s lifetime is inferred to be distinct from `x`'s
fn baz<'a>(x: &'a str, y: &str) -> &str { }
```
[book-le]: https://doc.rust-lang.org/nightly/book/lifetimes.html#lifetime-elision
"##
,
E0107
:
r##"
This error means that an incorrect number of lifetime parameters were provided
for a type (like a struct or enum) or trait.
Some basic examples include:
for a type (like a struct or enum) or trait:
```compile_fail,E0107
struct Foo<'a
>(&'a
str);
struct Foo<'a
, 'b>(&'a str, &'b
str);
enum Bar { A, B, C }
struct Baz<'a> {
foo: Foo
, // error: expected 1, found 0
foo: Foo
<'a>, // error: expected 2, found 1
bar: Bar<'a>, // error: expected 0, found 1
}
```
Here's an example that is currently an error, but may work in a future version
of Rust:
```compile_fail,E0107
struct Foo<'a>(&'a str);
trait Quux { }
impl Quux for Foo { } // error: expected 1, found 0
```
Lifetime elision in implementation headers was part of the lifetime elision
RFC. It is, however, [currently unimplemented][iss15872].
[iss15872]: https://github.com/rust-lang/rust/issues/15872
"##
,
E0116
:
r##"
...
...
src/librustc_typeck/rscope.rs
浏览文件 @
ba1849da
...
...
@@ -8,28 +8,14 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
rustc
::
hir
;
use
rustc
::
hir
::
def_id
::
DefId
;
use
rustc
::
ty
;
use
rustc
::
ty
::
subst
::
Substs
;
use
astconv
::
AstConv
;
use
std
::
cell
::
Cell
;
use
syntax_pos
::
Span
;
#[derive(Clone)]
pub
struct
ElisionFailureInfo
{
/// Where we can find the argument pattern.
pub
parent
:
Option
<
hir
::
BodyId
>
,
/// The index of the argument in the original definition.
pub
index
:
usize
,
pub
lifetime_count
:
usize
,
pub
have_bound_regions
:
bool
}
pub
type
ElidedLifetime
=
Result
<
ty
::
Region
,
Option
<
Vec
<
ElisionFailureInfo
>>>
;
/// Defines strategies for handling regions that are omitted. For
/// example, if one writes the type `&Foo`, then the lifetime of
/// this reference has been omitted. When converting this
...
...
@@ -41,9 +27,6 @@ pub struct ElisionFailureInfo {
/// can return `Err(())` to indicate that this is not a scope in which
/// regions can legally be omitted.
pub
trait
RegionScope
{
fn
anon_region
(
&
self
,
span
:
Span
,
def
:
Option
<&
ty
::
RegionParameterDef
>
)
->
Result
<
ty
::
Region
,
Option
<
Vec
<
ElisionFailureInfo
>>>
;
/// If an object omits any explicit lifetime bound, and none can
/// be derived from the object traits, what should we use? If
/// `None` is returned, an explicit annotation is required.
...
...
@@ -115,11 +98,6 @@ fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
self
.base_scope
.object_lifetime_default
(
span
)
}
fn
anon_region
(
&
self
,
span
:
Span
,
def
:
Option
<&
ty
::
RegionParameterDef
>
)
->
Result
<
ty
::
Region
,
Option
<
Vec
<
ElisionFailureInfo
>>>
{
self
.base_scope
.anon_region
(
span
,
def
)
}
fn
base_object_lifetime_default
(
&
self
,
span
:
Span
)
->
ty
::
Region
{
self
.base_scope
.base_object_lifetime_default
(
span
)
}
...
...
@@ -135,105 +113,6 @@ fn anon_type_scope(&self) -> Option<AnonTypeScope> {
pub
struct
ExplicitRscope
;
impl
RegionScope
for
ExplicitRscope
{
fn
anon_region
(
&
self
,
_
span
:
Span
,
_
:
Option
<&
ty
::
RegionParameterDef
>
)
->
Result
<
ty
::
Region
,
Option
<
Vec
<
ElisionFailureInfo
>>>
{
Err
(
None
)
}
fn
object_lifetime_default
(
&
self
,
span
:
Span
)
->
Option
<
ty
::
Region
>
{
Some
(
self
.base_object_lifetime_default
(
span
))
}
fn
base_object_lifetime_default
(
&
self
,
_
span
:
Span
)
->
ty
::
Region
{
ty
::
ReStatic
}
}
// Same as `ExplicitRscope`, but provides some extra information for diagnostics
pub
struct
UnelidableRscope
(
Option
<
Vec
<
ElisionFailureInfo
>>
);
impl
UnelidableRscope
{
pub
fn
new
(
v
:
Option
<
Vec
<
ElisionFailureInfo
>>
)
->
UnelidableRscope
{
UnelidableRscope
(
v
)
}
}
impl
RegionScope
for
UnelidableRscope
{
fn
anon_region
(
&
self
,
_
span
:
Span
,
_
:
Option
<&
ty
::
RegionParameterDef
>
)
->
Result
<
ty
::
Region
,
Option
<
Vec
<
ElisionFailureInfo
>>>
{
Err
(
self
.0
.clone
())
}
fn
object_lifetime_default
(
&
self
,
span
:
Span
)
->
Option
<
ty
::
Region
>
{
Some
(
self
.base_object_lifetime_default
(
span
))
}
fn
base_object_lifetime_default
(
&
self
,
_
span
:
Span
)
->
ty
::
Region
{
ty
::
ReStatic
}
}
// A scope in which omitted anonymous region defaults to
// `default`. This is used after the `->` in function signatures. The
// latter use may go away. Note that object-lifetime defaults work a
// bit differently, as specified in RFC #599.
pub
struct
ElidableRscope
{
default
:
ty
::
Region
,
}
impl
ElidableRscope
{
pub
fn
new
(
r
:
ty
::
Region
)
->
ElidableRscope
{
ElidableRscope
{
default
:
r
}
}
}
impl
RegionScope
for
ElidableRscope
{
fn
object_lifetime_default
(
&
self
,
span
:
Span
)
->
Option
<
ty
::
Region
>
{
// Per RFC #599, object-lifetimes default to 'static unless
// overridden by context, and this takes precedence over
// lifetime elision.
Some
(
self
.base_object_lifetime_default
(
span
))
}
fn
base_object_lifetime_default
(
&
self
,
_
span
:
Span
)
->
ty
::
Region
{
ty
::
ReStatic
}
fn
anon_region
(
&
self
,
_
span
:
Span
,
_
:
Option
<&
ty
::
RegionParameterDef
>
)
->
Result
<
ty
::
Region
,
Option
<
Vec
<
ElisionFailureInfo
>>>
{
Ok
(
self
.default
)
}
}
/// A scope that behaves as an ElidabeRscope with a `'static` default region
/// that should also warn if the `static_in_const` feature is unset.
#[derive(Copy,
Clone)]
pub
struct
StaticRscope
<
'a
,
'gcx
:
'a
+
'tcx
,
'tcx
:
'a
>
{
tcx
:
&
'a
ty
::
TyCtxt
<
'a
,
'gcx
,
'tcx
>
,
}
impl
<
'a
,
'gcx
:
'a
+
'tcx
,
'tcx
:
'a
>
StaticRscope
<
'a
,
'gcx
,
'tcx
>
{
/// create a new StaticRscope from a reference to the `TyCtxt`
pub
fn
new
(
tcx
:
&
'a
ty
::
TyCtxt
<
'a
,
'gcx
,
'tcx
>
)
->
Self
{
StaticRscope
{
tcx
:
tcx
}
}
}
impl
<
'a
,
'gcx
:
'a
+
'tcx
,
'tcx
:
'a
>
RegionScope
for
StaticRscope
<
'a
,
'gcx
,
'tcx
>
{
fn
anon_region
(
&
self
,
span
:
Span
,
_
:
Option
<&
ty
::
RegionParameterDef
>
)
->
Result
<
ty
::
Region
,
Option
<
Vec
<
ElisionFailureInfo
>>>
{
if
!
self
.tcx.sess.features
.borrow
()
.static_in_const
{
self
.tcx
.sess
.struct_span_err
(
span
,
"this needs a `'static` lifetime or the
\
`static_in_const` feature, see #35897"
)
.emit
();
}
Ok
(
ty
::
ReStatic
)
}
fn
object_lifetime_default
(
&
self
,
span
:
Span
)
->
Option
<
ty
::
Region
>
{
Some
(
self
.base_object_lifetime_default
(
span
))
}
...
...
@@ -243,41 +122,6 @@ fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
}
}
/// A scope in which we generate anonymous, late-bound regions for
/// omitted regions. This occurs in function signatures.
pub
struct
BindingRscope
{
anon_bindings
:
Cell
<
u32
>
,
}
impl
BindingRscope
{
pub
fn
new
()
->
BindingRscope
{
BindingRscope
{
anon_bindings
:
Cell
::
new
(
0
),
}
}
}
impl
RegionScope
for
BindingRscope
{
fn
object_lifetime_default
(
&
self
,
span
:
Span
)
->
Option
<
ty
::
Region
>
{
// Per RFC #599, object-lifetimes default to 'static unless
// overridden by context, and this takes precedence over the
// binding defaults in a fn signature.
Some
(
self
.base_object_lifetime_default
(
span
))
}
fn
base_object_lifetime_default
(
&
self
,
_
span
:
Span
)
->
ty
::
Region
{
ty
::
ReStatic
}
fn
anon_region
(
&
self
,
_
:
Span
,
_
:
Option
<&
ty
::
RegionParameterDef
>
)
->
Result
<
ty
::
Region
,
Option
<
Vec
<
ElisionFailureInfo
>>>
{
let
idx
=
self
.anon_bindings
.get
();
self
.anon_bindings
.set
(
idx
+
1
);
Ok
(
ty
::
ReLateBound
(
ty
::
DebruijnIndex
::
new
(
1
),
ty
::
BrAnon
(
idx
)))
}
}
/// A scope which overrides the default object lifetime but has no other effect.
pub
struct
ObjectLifetimeDefaultRscope
<
'r
>
{
base_scope
:
&
'r
(
RegionScope
+
'r
),
...
...
@@ -315,12 +159,6 @@ fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
self
.base_scope
.base_object_lifetime_default
(
span
)
}
fn
anon_region
(
&
self
,
span
:
Span
,
def
:
Option
<&
ty
::
RegionParameterDef
>
)
->
Result
<
ty
::
Region
,
Option
<
Vec
<
ElisionFailureInfo
>>>
{
self
.base_scope
.anon_region
(
span
,
def
)
}
fn
anon_type_scope
(
&
self
)
->
Option
<
AnonTypeScope
>
{
self
.base_scope
.anon_type_scope
()
}
...
...
@@ -348,12 +186,6 @@ fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
ty
::
fold
::
shift_region
(
self
.base_scope
.base_object_lifetime_default
(
span
),
1
)
}
fn
anon_region
(
&
self
,
span
:
Span
,
def
:
Option
<&
ty
::
RegionParameterDef
>
)
->
Result
<
ty
::
Region
,
Option
<
Vec
<
ElisionFailureInfo
>>>
{
self
.base_scope
.anon_region
(
span
,
def
)
.map
(|
r
|
ty
::
fold
::
shift_region
(
r
,
1
))
}
fn
anon_type_scope
(
&
self
)
->
Option
<
AnonTypeScope
>
{
self
.base_scope
.anon_type_scope
()
}
...
...
src/test/compile-fail/E0106.rs
浏览文件 @
ba1849da
...
...
@@ -23,5 +23,17 @@ enum Bar {
//~^ ERROR E0106
//~| NOTE expected lifetime parameter
struct
Baz
<
'a
>
(
&
'a
str
);
struct
Buzz
<
'a
,
'b
>
(
&
'a
str
,
&
'b
str
);
struct
Quux
{
baz
:
Baz
,
//~^ ERROR E0106
//~| expected lifetime parameter
buzz
:
Buzz
,
//~^ ERROR E0106
//~| expected 2 lifetime parameters
}
fn
main
()
{
}
src/test/compile-fail/E0107.rs
浏览文件 @
ba1849da
...
...
@@ -18,9 +18,6 @@ enum Bar {
}
struct
Baz
<
'a
,
'b
,
'c
>
{
foo
:
Foo
,
//~^ ERROR E0107
//~| expected 1 lifetime parameter
buzz
:
Buzz
<
'a
>
,
//~^ ERROR E0107
//~| expected 2 lifetime parameters
...
...
src/test/compile-fail/associated-types-project-from-hrtb-in-struct.rs
浏览文件 @
ba1849da
...
...
@@ -22,10 +22,11 @@ struct SomeStruct<I : for<'x> Foo<&'x isize>> {
//~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context
}
struct
AnotherStruct
<
I
:
for
<
'x
>
Foo
<&
'x
isize
>>
{
field
:
<
I
as
Foo
<&
isize
>>
::
A
//~^ ERROR missing lifetime specifier
}
// FIXME(eddyb) This one doesn't even compile because of the unsupported syntax.
// struct AnotherStruct<I : for<'x> Foo<&'x isize>> {
// field: <I as for<'y> Foo<&'y isize>>::A
// }
struct
YetAnotherStruct
<
'a
,
I
:
for
<
'x
>
Foo
<&
'x
isize
>>
{
field
:
<
I
as
Foo
<&
'a
isize
>>
::
A
...
...
src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs
浏览文件 @
ba1849da
...
...
@@ -38,4 +38,28 @@ fn i(_x: isize) -> &isize { //~ ERROR missing lifetime specifier
panic!
()
}
// Cases which used to work but now don't.
type
StaticStr
=
&
'static
str
;
// hides 'static
trait
WithLifetime
<
'a
>
{
type
Output
;
// can hide 'a
}
// This worked because the type of the first argument contains
// 'static, although StaticStr doesn't even have parameters.
fn
j
(
_
x
:
StaticStr
)
->
&
isize
{
//~ ERROR missing lifetime specifier
//~^ HELP this function's return type contains a borrowed value
//~| HELP consider giving it an explicit bounded or 'static lifetime
panic!
()
}
// This worked because the compiler resolved the argument type
// to <T as WithLifetime<'a>>::Output which has the hidden 'a.
fn
k
<
'a
,
T
:
WithLifetime
<
'a
>>
(
_
x
:
T
::
Output
)
->
&
isize
{
//~^ ERROR missing lifetime specifier
//~| HELP this function's return type contains a borrowed value
//~| HELP consider giving it an explicit bounded or 'static lifetime
panic!
()
}
fn
main
()
{}
src/test/compile-fail/rfc1623.rs
浏览文件 @
ba1849da
...
...
@@ -15,8 +15,10 @@ fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 {
}
// the boundaries of elision
static
NON_ELIDABLE_FN
:
&
fn
(
&
u8
,
&
u8
)
->
&
u8
=
&
(
non_elidable
as
fn
(
&
u8
,
&
u8
)
->
&
u8
);
static
NON_ELIDABLE_FN
:
&
fn
(
&
u8
,
&
u8
)
->
&
u8
=
//~^ ERROR missing lifetime specifier [E0106]
&
(
non_elidable
as
fn
(
&
u8
,
&
u8
)
->
&
u8
);
//~^ ERROR missing lifetime specifier [E0106]
struct
SomeStruct
<
'x
,
'y
,
'z
:
'x
>
{
foo
:
&
'x
Foo
<
'z
>
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录