Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
a8577be6
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,发现更多精彩内容 >>
提交
a8577be6
编写于
9月 13, 2014
作者:
P
P1start
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Output a note when lifetimes cannot be elided from functions
上级
60e73173
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
103 addition
and
22 deletion
+103
-22
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/astconv.rs
+69
-14
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/check/mod.rs
+1
-1
src/librustc/middle/typeck/rscope.rs
src/librustc/middle/typeck/rscope.rs
+28
-5
src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs
...ifetime-elision-return-type-requires-explicit-lifetime.rs
+5
-2
未找到文件。
src/librustc/middle/typeck/astconv.rs
浏览文件 @
a8577be6
...
...
@@ -59,7 +59,7 @@
use
middle
::
ty
;
use
middle
::
typeck
::
lookup_def_tcx
;
use
middle
::
typeck
::
infer
;
use
middle
::
typeck
::
rscope
::{
Explicit
Rscope
,
RegionScope
,
SpecificRscope
};
use
middle
::
typeck
::
rscope
::{
Unelidable
Rscope
,
RegionScope
,
SpecificRscope
};
use
middle
::
typeck
::
rscope
;
use
middle
::
typeck
::
TypeAndSubsts
;
use
middle
::
typeck
;
...
...
@@ -67,10 +67,11 @@
use
std
::
collections
::
HashMap
;
use
std
::
rc
::
Rc
;
use
s
yntax
::
abi
;
use
syntax
::{
ast
,
ast_util
};
use
s
td
::
iter
::
AdditiveIterator
;
use
syntax
::{
a
bi
,
a
st
,
ast_util
};
use
syntax
::
codemap
::
Span
;
use
syntax
::
parse
::
token
;
use
syntax
::
print
::
pprust
;
pub
trait
AstConv
<
'tcx
>
{
fn
tcx
<
'a
>
(
&
'a
self
)
->
&
'a
ty
::
ctxt
<
'tcx
>
;
...
...
@@ -147,10 +148,49 @@ pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
None
=>
{
match
rscope
.anon_regions
(
default_span
,
1
)
{
Err
(
()
)
=>
{
Err
(
v
)
=>
{
debug!
(
"optional region in illegal location"
);
span_err!
(
this
.tcx
()
.sess
,
default_span
,
E0106
,
"missing lifetime specifier"
);
match
v
{
Some
(
v
)
=>
{
let
mut
m
=
String
::
new
();
let
len
=
v
.len
();
for
(
i
,
(
name
,
n
))
in
v
.move_iter
()
.enumerate
()
{
m
.push_str
(
if
n
==
1
{
format!
(
"`{}`"
,
name
)
}
else
{
format!
(
"one of `{}`'s {} elided lifetimes"
,
name
,
n
)
}
.as_slice
());
if
len
==
2
&&
i
==
0
{
m
.push_str
(
" or "
);
}
else
if
i
==
len
-
2
{
m
.push_str
(
", or "
);
}
else
if
i
!=
len
-
1
{
m
.push_str
(
", "
);
}
}
if
len
==
1
{
span_note!
(
this
.tcx
()
.sess
,
default_span
,
"this function's return type contains a borrowed value, but
\
the signature does not say which {} it is borrowed from"
,
m
);
}
else
if
len
==
0
{
span_note!
(
this
.tcx
()
.sess
,
default_span
,
"this function's return type contains a borrowed value, but
\
there is no value for it to be borrowed from"
);
span_note!
(
this
.tcx
()
.sess
,
default_span
,
"consider giving it a 'static lifetime"
);
}
else
{
span_note!
(
this
.tcx
()
.sess
,
default_span
,
"this function's return type contains a borrowed value, but
\
the signature does not say whether it is borrowed from {}"
,
m
);
}
}
None
=>
{},
}
ty
::
ReStatic
}
...
...
@@ -217,7 +257,7 @@ fn ast_path_substs<'tcx,AC,RS>(
match
anon_regions
{
Ok
(
v
)
=>
v
.into_iter
()
.collect
(),
Err
(
()
)
=>
Vec
::
from_fn
(
expected_num_region_params
,
Err
(
_
)
=>
Vec
::
from_fn
(
expected_num_region_params
,
|
_
|
ty
::
ReStatic
)
// hokey
}
};
...
...
@@ -1153,15 +1193,20 @@ fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>(
};
// HACK(eddyb) replace the fake self type in the AST with the actual type.
let
input_
ty
s
=
if
self_ty
.is_some
()
{
let
input_
param
s
=
if
self_ty
.is_some
()
{
decl
.inputs
.slice_from
(
1
)
}
else
{
decl
.inputs
.as_slice
()
};
let
input_tys
=
input_tys
.iter
()
.map
(|
a
|
ty_of_arg
(
this
,
&
rb
,
a
,
None
));
let
self_and_input_tys
:
Vec
<
_
>
=
let
input_tys
=
input_params
.iter
()
.map
(|
a
|
ty_of_arg
(
this
,
&
rb
,
a
,
None
));
let
input_pats
:
Vec
<
String
>
=
input_params
.iter
()
.map
(|
a
|
pprust
::
pat_to_string
(
&*
a
.pat
))
.collect
();
let
self_and_input_tys
:
Vec
<
ty
::
t
>
=
self_ty
.into_iter
()
.chain
(
input_tys
)
.collect
();
let
mut
lifetimes_for_params
:
Vec
<
(
String
,
Vec
<
ty
::
Region
>
)
>
=
Vec
::
new
();
// Second, if there was exactly one lifetime (either a substitution or a
// reference) in the arguments, then any anonymous regions in the output
// have that lifetime.
...
...
@@ -1172,15 +1217,25 @@ fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>(
drop
(
self_and_input_tys_iter
.next
())
}
let
mut
accumulator
=
Vec
::
new
();
for
input_type
in
self_and_input_tys_iter
{
ty
::
accumulate_lifetimes_in_type
(
&
mut
accumulator
,
*
input_type
)
for
(
input_type
,
input_pat
)
in
self_and_input_tys_iter
.zip
(
input_pats
.into_iter
())
{
let
mut
accumulator
=
Vec
::
new
();
ty
::
accumulate_lifetimes_in_type
(
&
mut
accumulator
,
*
input_type
);
lifetimes_for_params
.push
((
input_pat
,
accumulator
));
}
if
accumulator
.len
()
==
1
{
implied_output_region
=
Some
(
*
accumulator
.get
(
0
));
if
lifetimes_for_params
.iter
()
.map
(|
&
(
_
,
ref
x
)|
x
.len
())
.sum
()
==
1
{
implied_output_region
=
Some
(
lifetimes_for_params
.iter
()
.filter_map
(|
&
(
_
,
ref
x
)|
if
x
.len
()
==
1
{
Some
(
x
[
0
])
}
else
{
None
})
.next
()
.unwrap
());
}
}
let
param_lifetimes
:
Vec
<
(
String
,
uint
)
>
=
lifetimes_for_params
.into_iter
()
.map
(|(
n
,
v
)|
(
n
,
v
.len
()))
.collect
();
let
output_ty
=
match
decl
.output.node
{
ast
::
TyInfer
=>
this
.ty_infer
(
decl
.output.span
),
_
=>
{
...
...
@@ -1193,7 +1248,7 @@ fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>(
// All regions must be explicitly specified in the output
// if the lifetime elision rules do not apply. This saves
// the user from potentially-confusing errors.
let
rb
=
ExplicitRscope
;
let
rb
=
UnelidableRscope
::
new
(
param_lifetimes
)
;
ast_ty_to_ty
(
this
,
&
rb
,
&*
decl
.output
)
}
}
...
...
src/librustc/middle/typeck/check/mod.rs
浏览文件 @
a8577be6
...
...
@@ -1601,7 +1601,7 @@ fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
}
fn
anon_regions
(
&
self
,
span
:
Span
,
count
:
uint
)
->
Result
<
Vec
<
ty
::
Region
>
,
()
>
{
->
Result
<
Vec
<
ty
::
Region
>
,
Option
<
Vec
<
(
String
,
uint
)
>>
>
{
Ok
(
Vec
::
from_fn
(
count
,
|
_
|
{
self
.next_region_var
(
infer
::
MiscVariable
(
span
))
}))
...
...
src/librustc/middle/typeck/rscope.rs
浏览文件 @
a8577be6
...
...
@@ -29,7 +29,7 @@ pub trait RegionScope {
fn
anon_regions
(
&
self
,
span
:
Span
,
count
:
uint
)
->
Result
<
Vec
<
ty
::
Region
>
,
()
>
;
->
Result
<
Vec
<
ty
::
Region
>
,
Option
<
Vec
<
(
String
,
uint
)
>>
>
;
fn
default_region_bound
(
&
self
,
span
:
Span
)
->
Option
<
ty
::
Region
>
;
}
...
...
@@ -46,8 +46,31 @@ fn default_region_bound(&self, _span: Span) -> Option<ty::Region> {
fn
anon_regions
(
&
self
,
_
span
:
Span
,
_
count
:
uint
)
->
Result
<
Vec
<
ty
::
Region
>
,
()
>
{
Err
(())
->
Result
<
Vec
<
ty
::
Region
>
,
Option
<
Vec
<
(
String
,
uint
)
>>>
{
Err
(
None
)
}
}
// Same as `ExplicitRscope`, but provides some extra information for diagnostics
pub
struct
UnelidableRscope
(
Vec
<
(
String
,
uint
)
>
);
impl
UnelidableRscope
{
pub
fn
new
(
v
:
Vec
<
(
String
,
uint
)
>
)
->
UnelidableRscope
{
UnelidableRscope
(
v
)
}
}
impl
RegionScope
for
UnelidableRscope
{
fn
default_region_bound
(
&
self
,
_
span
:
Span
)
->
Option
<
ty
::
Region
>
{
None
}
fn
anon_regions
(
&
self
,
_
span
:
Span
,
_
count
:
uint
)
->
Result
<
Vec
<
ty
::
Region
>
,
Option
<
Vec
<
(
String
,
uint
)
>>>
{
let
UnelidableRscope
(
ref
v
)
=
*
self
;
Err
(
Some
(
v
.clone
()))
}
}
...
...
@@ -72,7 +95,7 @@ fn default_region_bound(&self, _span: Span) -> Option<ty::Region> {
fn
anon_regions
(
&
self
,
_
span
:
Span
,
count
:
uint
)
->
Result
<
Vec
<
ty
::
Region
>
,
()
>
->
Result
<
Vec
<
ty
::
Region
>
,
Option
<
Vec
<
(
String
,
uint
)
>>
>
{
Ok
(
Vec
::
from_elem
(
count
,
self
.default
))
}
...
...
@@ -109,7 +132,7 @@ fn default_region_bound(&self, _span: Span) -> Option<ty::Region>
fn
anon_regions
(
&
self
,
_
:
Span
,
count
:
uint
)
->
Result
<
Vec
<
ty
::
Region
>
,
()
>
->
Result
<
Vec
<
ty
::
Region
>
,
Option
<
Vec
<
(
String
,
uint
)
>>
>
{
Ok
(
Vec
::
from_fn
(
count
,
|
_
|
self
.next_region
()))
}
...
...
src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs
浏览文件 @
a8577be6
...
...
@@ -10,11 +10,13 @@
// Lifetime annotation needed because we have no arguments.
fn
f
()
->
&
int
{
//~ ERROR missing lifetime specifier
//~^ NOTE there is no value for it to be borrowed from
fail
!
()
}
// Lifetime annotation needed because we have two by-reference parameters.
fn
g
(
_
:
&
int
,
_
:
&
int
)
->
&
int
{
//~ ERROR missing lifetime specifier
fn
g
(
_
x
:
&
int
,
_
y
:
&
int
)
->
&
int
{
//~ ERROR missing lifetime specifier
//~^ NOTE the signature does not say whether it is borrowed from `_x` or `_y`
fail
!
()
}
...
...
@@ -24,7 +26,8 @@ struct Foo<'a> {
// Lifetime annotation needed because we have two lifetimes: one as a parameter
// and one on the reference.
fn
h
(
_
:
&
Foo
)
->
&
int
{
//~ ERROR missing lifetime specifier
fn
h
(
_
x
:
&
Foo
)
->
&
int
{
//~ ERROR missing lifetime specifier
//~^ NOTE the signature does not say which one of `_x`'s 2 elided lifetimes it is borrowed from
fail
!
()
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录