Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
15688eaf
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,发现更多精彩内容 >>
提交
15688eaf
编写于
3月 25, 2013
作者:
P
Patrick Walton
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
librustc: Require explicit lifetime binders
上级
3b2fcf9f
变更
4
显示空白变更内容
内联
并排
Showing
4 changed file
with
322 addition
and
63 deletion
+322
-63
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/astconv.rs
+43
-6
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/check/mod.rs
+21
-8
src/librustc/middle/typeck/collect.rs
src/librustc/middle/typeck/collect.rs
+74
-38
src/librustc/middle/typeck/rscope.rs
src/librustc/middle/typeck/rscope.rs
+184
-11
未找到文件。
src/librustc/middle/typeck/astconv.rs
浏览文件 @
15688eaf
...
...
@@ -58,13 +58,15 @@
use
middle
::
ty
::{
arg
,
field
,
substs
};
use
middle
::
ty
::{
ty_param_substs_and_ty
};
use
middle
::
ty
;
use
middle
::
typeck
::
rscope
::{
in_binding_rscope
};
use
middle
::
typeck
::
rscope
::{
in_binding_rscope
,
in_binding_rscope_ext
};
use
middle
::
typeck
::
rscope
::{
region_scope
,
type_rscope
,
RegionError
};
use
middle
::
typeck
::
rscope
::{
RegionParamNames
};
use
core
::
result
;
use
core
::
vec
;
use
syntax
::{
ast
,
ast_util
};
use
syntax
::
codemap
::
span
;
use
syntax
::
opt_vec
::
OptVec
;
use
syntax
::
print
::
pprust
::{
lifetime_to_str
,
path_to_str
};
use
syntax
::
parse
::
token
::
special_idents
;
use
util
::
common
::
indenter
;
...
...
@@ -348,9 +350,15 @@ fn check_path_args(tcx: ty::ctxt,
bf
.abi
,
&
bf
.decl
))
}
ast
::
ty_closure
(
ref
f
)
=>
{
let
fn_decl
=
ty_of_closure
(
self
,
rscope
,
f
.sigil
,
f
.purity
,
f
.onceness
,
f
.region
,
&
f
.decl
,
None
,
let
fn_decl
=
ty_of_closure
(
self
,
rscope
,
f
.sigil
,
f
.purity
,
f
.onceness
,
f
.region
,
&
f
.decl
,
None
,
&
f
.lifetimes
,
ast_ty
.span
);
ty
::
mk_closure
(
tcx
,
fn_decl
)
}
...
...
@@ -507,7 +515,7 @@ pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + Durable>(
abi
:
ast
::
Abi
,
decl
:
&
ast
::
fn_decl
)
->
ty
::
BareFnTy
{
debug!
(
"ty_of_
fn_decl
"
);
debug!
(
"ty_of_
bare_fn
"
);
// new region names that appear inside of the fn decl are bound to
// that function type
...
...
@@ -526,6 +534,33 @@ pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + Durable>(
}
}
pub
fn
ty_of_bare_fn_ext
<
AC
:
AstConv
,
RS
:
region_scope
+
Copy
+
Durable
>
(
self
:
&
AC
,
rscope
:
&
RS
,
purity
:
ast
::
purity
,
abi
:
ast
::
Abi
,
decl
:
&
ast
::
fn_decl
,
+
region_param_names
:
RegionParamNames
)
->
ty
::
BareFnTy
{
debug!
(
"ty_of_bare_fn_ext"
);
// new region names that appear inside of the fn decl are bound to
// that function type
let
rb
=
in_binding_rscope_ext
(
rscope
,
region_param_names
);
let
input_tys
=
decl
.inputs
.map
(|
a
|
ty_of_arg
(
self
,
&
rb
,
*
a
,
None
));
let
output_ty
=
match
decl
.output.node
{
ast
::
ty_infer
=>
self
.ty_infer
(
decl
.output.span
),
_
=>
ast_ty_to_ty
(
self
,
&
rb
,
decl
.output
)
};
ty
::
BareFnTy
{
purity
:
purity
,
abi
:
abi
,
sig
:
ty
::
FnSig
{
inputs
:
input_tys
,
output
:
output_ty
}
}
}
pub
fn
ty_of_closure
<
AC
:
AstConv
,
RS
:
region_scope
+
Copy
+
Durable
>
(
self
:
&
AC
,
rscope
:
&
RS
,
...
...
@@ -535,6 +570,7 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + Durable>(
opt_lifetime
:
Option
<@
ast
::
Lifetime
>
,
decl
:
&
ast
::
fn_decl
,
expected_tys
:
Option
<
ty
::
FnSig
>
,
lifetimes
:
&
OptVec
<
ast
::
Lifetime
>
,
span
:
span
)
->
ty
::
ClosureTy
{
debug!
(
"ty_of_fn_decl"
);
...
...
@@ -563,7 +599,8 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + Durable>(
// new region names that appear inside of the fn decl are bound to
// that function type
let
rb
=
in_binding_rscope
(
rscope
);
let
region_param_names
=
RegionParamNames
::
from_lifetimes
(
lifetimes
);
let
rb
=
in_binding_rscope_ext
(
rscope
,
region_param_names
);
let
input_tys
=
do
decl
.inputs.mapi
|
i
,
a
|
{
let
expected_arg_ty
=
do
expected_tys
.chain_ref
|
e
|
{
...
...
src/librustc/middle/typeck/check/mod.rs
浏览文件 @
15688eaf
...
...
@@ -100,7 +100,7 @@
use
middle
::
typeck
::
infer
::{
resolve_type
,
force_tvar
,
mk_eqty
};
use
middle
::
typeck
::
infer
;
use
middle
::
typeck
::
rscope
::{
binding_rscope
,
bound_self_region
};
use
middle
::
typeck
::
rscope
::{
RegionError
};
use
middle
::
typeck
::
rscope
::{
RegionError
,
RegionParameterization
};
use
middle
::
typeck
::
rscope
::{
in_binding_rscope
,
region_scope
,
type_rscope
};
use
middle
::
typeck
::
rscope
;
use
middle
::
typeck
::{
isr_alist
,
lookup_def_ccx
,
method_map_entry
};
...
...
@@ -126,10 +126,11 @@
use
syntax
::
ast_util
;
use
syntax
::
codemap
::{
span
,
spanned
,
respan
};
use
syntax
::
codemap
;
use
syntax
::
opt_vec
::
OptVec
;
use
syntax
::
opt_vec
;
use
syntax
::
parse
::
token
::
special_idents
;
use
syntax
::
print
::
pprust
;
use
syntax
::
visit
;
use
syntax
::
opt_vec
::
OptVec
;
use
syntax
;
pub
mod
_
match
;
...
...
@@ -570,10 +571,12 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
ast
::
item_fn
(
ref
decl
,
_
,
_
,
ref
body
)
=>
{
check_bare_fn
(
ccx
,
decl
,
body
,
it
.id
,
None
);
}
ast
::
item_impl
(
_
,
_
,
ty
,
ref
ms
)
=>
{
ast
::
item_impl
(
ref
generics
,
_
,
ty
,
ref
ms
)
=>
{
let
rp
=
ccx
.tcx.region_paramd_items
.find
(
&
it
.id
)
.map_consume
(|
x
|
*
x
);
debug!
(
"item_impl %s with id %d rp %?"
,
*
ccx
.tcx.sess
.str_of
(
it
.ident
),
it
.id
,
rp
);
let
rp
=
RegionParameterization
::
from_variance_and_generics
(
rp
,
generics
);
let
self_ty
=
ccx
.to_ty
(
&
rscope
::
type_rscope
(
rp
),
ty
);
for
ms
.each
|
m
|
{
check_method
(
ccx
,
*
m
,
self_ty
);
...
...
@@ -1069,9 +1072,13 @@ pub fn impl_self_ty(vcx: &VtableContext,
node
:
ast
::
item_impl
(
ref
ts
,
_
,
st
,
_
),
_
},
_
))
=>
{
let
region_parameterization
=
RegionParameterization
::
from_variance_and_generics
(
region_param
,
ts
);
(
ts
.ty_params
.len
(),
region_param
,
vcx
.ccx
.to_ty
(
&
rscope
::
type_rscope
(
region_param
),
st
))
vcx
.ccx
.to_ty
(
&
rscope
::
type_rscope
(
region_param
eterization
),
st
))
}
Some
(
&
ast_map
::
node_item
(
@
ast
::
item
{
node
:
ast
::
item_struct
(
_
,
ref
ts
),
...
...
@@ -1654,10 +1661,16 @@ fn check_expr_fn(fcx: @mut FnCtxt,
};
// construct the function type
let
mut
fn_ty
=
astconv
::
ty_of_closure
(
fcx
,
fcx
,
sigil
,
purity
,
expected_onceness
,
None
,
decl
,
expected_tys
,
expr
.span
);
let
mut
fn_ty
=
astconv
::
ty_of_closure
(
fcx
,
fcx
,
sigil
,
purity
,
expected_onceness
,
None
,
decl
,
expected_tys
,
&
opt_vec
::
Empty
,
expr
.span
);
let
mut
fty_sig
;
let
fty
=
if
error_happened
{
...
...
src/librustc/middle/typeck/collect.rs
浏览文件 @
15688eaf
...
...
@@ -166,12 +166,15 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
// Create a set of parameter types shared among all the variants.
for
variants
.each
|
variant
|
{
let
region_parameterization
=
RegionParameterization
::
from_variance_and_generics
(
rp
,
generics
);
// Nullary enum constructors get turned into constants; n-ary enum
// constructors get turned into functions.
let
result_ty
;
match
variant
.node.kind
{
ast
::
tuple_variant_kind
(
ref
args
)
if
args
.len
()
>
0
=>
{
let
rs
=
type_rscope
(
r
p
);
let
rs
=
type_rscope
(
r
egion_parameterization
);
let
input_tys
=
args
.map
(|
va
|
ccx
.to_ty
(
&
rs
,
va
.ty
));
result_ty
=
Some
(
ty
::
mk_ctor_fn
(
tcx
,
input_tys
,
enum_ty
));
}
...
...
@@ -301,7 +304,8 @@ fn make_static_method_ty(ccx: &CrateCtxt,
ccx
,
&
ty_m
,
region_paramd
,
def_id
def_id
,
generics
);
if
ty_m
.self_ty.node
==
ast
::
sty_static
{
make_static_method_ty
(
ccx
,
&
ty_m
,
region_paramd
,
...
...
@@ -319,13 +323,14 @@ pub fn ensure_supertraits(ccx: &CrateCtxt,
id
:
ast
::
node_id
,
sp
:
codemap
::
span
,
rp
:
Option
<
ty
::
region_variance
>
,
trait_refs
:
&
[
@
ast
::
trait_ref
])
{
trait_refs
:
&
[
@
ast
::
trait_ref
],
generics
:
&
ast
::
Generics
)
{
let
tcx
=
ccx
.tcx
;
if
tcx
.supertraits
.contains_key
(
&
local_def
(
id
))
{
return
;
}
let
mut
instantiated
=
~
[];
for
trait_refs
.each
|
trait_ref
|
{
let
(
did
,
tpt
)
=
instantiate_trait_ref
(
ccx
,
*
trait_ref
,
rp
);
let
(
did
,
tpt
)
=
instantiate_trait_ref
(
ccx
,
*
trait_ref
,
rp
,
generics
);
if
instantiated
.any
(|
other_trait
:
&
InstantiatedTraitRef
|
{
other_trait
.def_id
==
did
})
{
// This means a trait inherited from the same supertrait more
...
...
@@ -506,7 +511,7 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt,
impl_ms
:
&
[
ConvertedMethod
])
{
let
tcx
=
ccx
.tcx
;
let
(
did
,
tpt
)
=
instantiate_trait_ref
(
ccx
,
a_trait_ty
,
rp
);
let
(
did
,
tpt
)
=
instantiate_trait_ref
(
ccx
,
a_trait_ty
,
rp
,
generics
);
if
did
.crate
==
ast
::
local_crate
{
// NB: This is subtle. We need to do this on the type of the trait
...
...
@@ -553,8 +558,11 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt,
pub
fn
convert_field
(
ccx
:
&
CrateCtxt
,
rp
:
Option
<
ty
::
region_variance
>
,
bounds
:
@~
[
ty
::
param_bounds
],
v
:
@
ast
::
struct_field
)
{
let
tt
=
ccx
.to_ty
(
&
type_rscope
(
rp
),
v
.node.ty
);
v
:
@
ast
::
struct_field
,
generics
:
&
ast
::
Generics
)
{
let
region_parameterization
=
RegionParameterization
::
from_variance_and_generics
(
rp
,
generics
);
let
tt
=
ccx
.to_ty
(
&
type_rscope
(
region_parameterization
),
v
.node.ty
);
write_ty_to_tcx
(
ccx
.tcx
,
v
.node.id
,
tt
);
/* add the field to the tcache */
ccx
.tcx.tcache
.insert
(
local_def
(
v
.node.id
),
...
...
@@ -575,13 +583,14 @@ pub struct ConvertedMethod {
pub
fn
convert_methods
(
ccx
:
&
CrateCtxt
,
ms
:
&
[
@
ast
::
method
],
rp
:
Option
<
ty
::
region_variance
>
,
rcvr_bounds
:
@~
[
ty
::
param_bounds
])
rcvr_bounds
:
@~
[
ty
::
param_bounds
],
rcvr_generics
:
&
ast
::
Generics
)
->
~
[
ConvertedMethod
]
{
let
tcx
=
ccx
.tcx
;
do
vec
::
map
(
ms
)
|
m
|
{
let
bounds
=
ty_param_bounds
(
ccx
,
&
m
.generics
);
let
mty
=
ty_of_method
(
ccx
,
*
m
,
rp
);
let
mty
=
ty_of_method
(
ccx
,
*
m
,
rp
,
rcvr_generics
,
&
m
.generics
);
let
fty
=
ty
::
mk_bare_fn
(
tcx
,
copy
mty
.fty
);
tcx
.tcache
.insert
(
local_def
(
m
.id
),
...
...
@@ -633,7 +642,9 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
}
ast
::
item_impl
(
ref
generics
,
trait_ref
,
selfty
,
ref
ms
)
=>
{
let
i_bounds
=
ty_param_bounds
(
ccx
,
generics
);
let
selfty
=
ccx
.to_ty
(
&
type_rscope
(
rp
),
selfty
);
let
region_parameterization
=
RegionParameterization
::
from_variance_and_generics
(
rp
,
generics
);
let
selfty
=
ccx
.to_ty
(
&
type_rscope
(
region_parameterization
),
selfty
);
write_ty_to_tcx
(
tcx
,
it
.id
,
selfty
);
tcx
.tcache
.insert
(
local_def
(
it
.id
),
ty_param_bounds_and_ty
{
...
...
@@ -642,7 +653,7 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
ty
:
selfty
});
// XXX: Bad copy of `ms` below.
let
cms
=
convert_methods
(
ccx
,
*
ms
,
rp
,
i_bounds
);
let
cms
=
convert_methods
(
ccx
,
*
ms
,
rp
,
i_bounds
,
generics
);
for
trait_ref
.each
|
t
|
{
check_methods_against_trait
(
ccx
,
generics
,
rp
,
selfty
,
*
t
,
cms
);
}
...
...
@@ -653,12 +664,12 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
it
.id
,
ppaux
::
ty_to_str
(
tcx
,
tpt
.ty
));
write_ty_to_tcx
(
tcx
,
it
.id
,
tpt
.ty
);
ensure_trait_methods
(
ccx
,
it
.id
,
tpt
.ty
);
ensure_supertraits
(
ccx
,
it
.id
,
it
.span
,
rp
,
*
supertraits
);
ensure_supertraits
(
ccx
,
it
.id
,
it
.span
,
rp
,
*
supertraits
,
generics
);
let
(
_
,
provided_methods
)
=
split_trait_methods
(
*
trait_methods
);
let
(
bounds
,
_
)
=
mk_substs
(
ccx
,
generics
,
rp
);
let
_
=
convert_methods
(
ccx
,
provided_methods
,
rp
,
bounds
);
let
_
=
convert_methods
(
ccx
,
provided_methods
,
rp
,
bounds
,
generics
);
}
ast
::
item_struct
(
struct_def
,
ref
generics
)
=>
{
ensure_no_ty_param_bounds
(
ccx
,
it
.span
,
generics
,
"structure"
);
...
...
@@ -694,12 +705,17 @@ pub fn convert_struct(ccx: &CrateCtxt,
let
tcx
=
ccx
.tcx
;
for
struct_def
.dtor.each
|
dtor
|
{
let
region_parameterization
=
RegionParameterization
::
from_variance_and_generics
(
rp
,
generics
);
// Write the dtor type
let
t_dtor
=
ty
::
mk_bare_fn
(
tcx
,
astconv
::
ty_of_bare_fn
(
ccx
,
&
type_rscope
(
rp
),
ast
::
impure_fn
,
ast
::
RustAbi
,
ccx
,
&
type_rscope
(
region_parameterization
),
ast
::
impure_fn
,
ast
::
RustAbi
,
&
ast_util
::
dtor_dec
()));
write_ty_to_tcx
(
tcx
,
dtor
.node.id
,
t_dtor
);
tcx
.tcache
.insert
(
local_def
(
dtor
.node.id
),
...
...
@@ -711,7 +727,7 @@ pub fn convert_struct(ccx: &CrateCtxt,
// Write the type of each of the members
for
struct_def
.fields.each
|
f
|
{
convert_field
(
ccx
,
rp
,
tpt
.bounds
,
*
f
);
convert_field
(
ccx
,
rp
,
tpt
.bounds
,
*
f
,
generics
);
}
let
(
_
,
substs
)
=
mk_substs
(
ccx
,
generics
,
rp
);
let
selfty
=
ty
::
mk_struct
(
tcx
,
local_def
(
id
),
substs
);
...
...
@@ -754,17 +770,23 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: @ast::foreign_item) {
pub
fn
ty_of_method
(
ccx
:
&
CrateCtxt
,
m
:
@
ast
::
method
,
rp
:
Option
<
ty
::
region_variance
>
)
->
ty
::
method
{
let
rscope
=
MethodRscope
{
self_ty
:
m
.self_ty.node
,
region_parameterization
:
rp
};
rp
:
Option
<
ty
::
region_variance
>
,
rcvr_generics
:
&
ast
::
Generics
,
method_generics
:
&
ast
::
Generics
)
->
ty
::
method
{
let
rscope
=
MethodRscope
::
new
(
m
.self_ty.node
,
rp
,
rcvr_generics
,
method_generics
);
ty
::
method
{
ident
:
m
.ident
,
tps
:
ty_param_bounds
(
ccx
,
&
m
.generics
),
fty
:
astconv
::
ty_of_bare_fn
(
ccx
,
&
rscope
,
m
.purity
,
ast
::
RustAbi
,
&
m
.decl
),
fty
:
astconv
::
ty_of_bare_fn_ext
(
ccx
,
&
rscope
,
m
.purity
,
ast
::
RustAbi
,
&
m
.decl
,
rscope
.region_param_names
()),
self_ty
:
m
.self_ty.node
,
vis
:
m
.vis
,
def_id
:
local_def
(
m
.id
)
...
...
@@ -774,17 +796,19 @@ pub fn ty_of_method(ccx: &CrateCtxt,
pub
fn
ty_of_ty_method
(
self
:
&
CrateCtxt
,
m
:
&
ast
::
ty_method
,
rp
:
Option
<
ty
::
region_variance
>
,
id
:
ast
::
def_id
)
->
ty
::
method
{
let
rscope
=
MethodRscope
{
self_ty
:
m
.self_ty.node
,
region_parameterization
:
rp
};
id
:
ast
::
def_id
,
generics
:
&
ast
::
Generics
)
->
ty
::
method
{
let
rscope
=
MethodRscope
::
new
(
m
.self_ty.node
,
rp
,
generics
,
&
m
.generics
);
ty
::
method
{
ident
:
m
.ident
,
tps
:
ty_param_bounds
(
self
,
&
m
.generics
),
fty
:
astconv
::
ty_of_bare_fn
(
self
,
&
rscope
,
m
.purity
,
ast
::
RustAbi
,
&
m
.decl
),
fty
:
astconv
::
ty_of_bare_fn_ext
(
self
,
&
rscope
,
m
.purity
,
ast
::
RustAbi
,
&
m
.decl
,
rscope
.region_param_names
()),
// assume public, because this is only invoked on trait methods
self_ty
:
m
.self_ty.node
,
vis
:
ast
::
public
,
...
...
@@ -797,13 +821,17 @@ pub fn ty_of_ty_method(self: &CrateCtxt,
it's bound to a valid trait type. Returns the def_id for the defining
trait. Fails if the type is a type other than an trait type.
*/
pub
fn
instantiate_trait_ref
(
ccx
:
&
CrateCtxt
,
t
:
@
ast
::
trait_ref
,
rp
:
Option
<
ty
::
region_variance
>
)
pub
fn
instantiate_trait_ref
(
ccx
:
&
CrateCtxt
,
t
:
@
ast
::
trait_ref
,
rp
:
Option
<
ty
::
region_variance
>
,
generics
:
&
ast
::
Generics
)
->
(
ast
::
def_id
,
ty_param_substs_and_ty
)
{
let
sp
=
t
.path.span
,
err
=
~
"can only implement trait types"
,
sess
=
ccx
.tcx.sess
;
let
rp
=
RegionParameterization
::
from_variance_and_generics
(
rp
,
generics
);
let
rscope
=
type_rscope
(
rp
);
match
lookup_def_tcx
(
ccx
.tcx
,
t
.path.span
,
t
.ref_id
)
{
...
...
@@ -841,8 +869,13 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
}
ast
::
item_fn
(
ref
decl
,
purity
,
ref
generics
,
_
)
=>
{
let
bounds
=
ty_param_bounds
(
ccx
,
generics
);
let
tofd
=
astconv
::
ty_of_bare_fn
(
ccx
,
&
empty_rscope
,
purity
,
ast
::
RustAbi
,
decl
);
let
region_param_names
=
RegionParamNames
::
from_generics
(
generics
);
let
tofd
=
astconv
::
ty_of_bare_fn_ext
(
ccx
,
&
empty_rscope
,
purity
,
ast
::
RustAbi
,
decl
,
region_param_names
);
let
tpt
=
ty_param_bounds_and_ty
{
bounds
:
bounds
,
region_param
:
None
,
...
...
@@ -862,9 +895,11 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
}
let
rp
=
tcx
.region_paramd_items
.find
(
&
it
.id
)
.map_consume
(|
x
|
*
x
);
let
region_parameterization
=
RegionParameterization
::
from_variance_and_generics
(
rp
,
generics
);
let
tpt
=
{
let
ty
=
{
let
t0
=
ccx
.to_ty
(
&
type_rscope
(
r
p
),
t
);
let
t0
=
ccx
.to_ty
(
&
type_rscope
(
r
egion_parameterization
),
t
);
// Do not associate a def id with a named, parameterized type
// like "foo<X>". This is because otherwise ty_to_str will
// print the name as merely "foo", as it has no way to
...
...
@@ -1007,7 +1042,8 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
generics
:
&
ast
::
Generics
)
->
ty
::
ty_param_bounds_and_ty
{
let
bounds
=
ty_param_bounds
(
ccx
,
generics
);
let
rb
=
in_binding_rscope
(
&
empty_rscope
);
let
region_param_names
=
RegionParamNames
::
from_generics
(
generics
);
let
rb
=
in_binding_rscope_ext
(
&
empty_rscope
,
region_param_names
);
let
input_tys
=
decl
.inputs
.map
(|
a
|
ty_of_arg
(
ccx
,
&
rb
,
*
a
,
None
)
);
let
output_ty
=
ast_ty_to_ty
(
ccx
,
&
rb
,
decl
.output
);
...
...
src/librustc/middle/typeck/rscope.rs
浏览文件 @
15688eaf
...
...
@@ -16,6 +16,9 @@
use
core
::
result
;
use
syntax
::
ast
;
use
syntax
::
codemap
::
span
;
use
syntax
::
opt_vec
::
OptVec
;
use
syntax
::
opt_vec
;
use
syntax
::
parse
::
token
::
special_idents
;
pub
struct
RegionError
{
msg
:
~
str
,
...
...
@@ -47,10 +50,130 @@ fn named_region(&self, _span: span, _id: ast::ident)
}
}
pub
struct
RegionParamNames
(
OptVec
<
ast
::
ident
>
);
impl
RegionParamNames
{
fn
has_self
(
&
self
)
->
bool
{
self
.has_ident
(
special_idents
::
self_
)
}
fn
has_ident
(
&
self
,
ident
:
ast
::
ident
)
->
bool
{
for
self
.each
|
region_param_name
|
{
if
*
region_param_name
==
ident
{
return
true
;
}
}
false
}
pub
fn
add_generics
(
&
mut
self
,
generics
:
&
ast
::
Generics
)
{
match
generics
.lifetimes
{
opt_vec
::
Empty
=>
{}
opt_vec
::
Vec
(
ref
new_lifetimes
)
=>
{
match
**
self
{
opt_vec
::
Empty
=>
{
*
self
=
RegionParamNames
(
opt_vec
::
Vec
(
new_lifetimes
.map
(|
lt
|
lt
.ident
)));
}
opt_vec
::
Vec
(
ref
mut
existing_lifetimes
)
=>
{
for
new_lifetimes
.each
|
new_lifetime
|
{
existing_lifetimes
.push
(
new_lifetime
.ident
);
}
}
}
}
}
}
// Convenience function to produce the error for an unresolved name. The
// optional argument specifies a custom replacement.
pub
fn
undeclared_name
(
custom_replacement
:
Option
<
ty
::
Region
>
)
->
Result
<
ty
::
Region
,
RegionError
>
{
let
replacement
=
match
custom_replacement
{
None
=>
ty
::
re_bound
(
ty
::
br_self
),
Some
(
custom_replacement
)
=>
custom_replacement
};
Err
(
RegionError
{
msg
:
~
"this lifetime must be declared"
,
replacement
:
replacement
})
}
pub
fn
from_generics
(
generics
:
&
ast
::
Generics
)
->
RegionParamNames
{
match
generics
.lifetimes
{
opt_vec
::
Empty
=>
RegionParamNames
(
opt_vec
::
Empty
),
opt_vec
::
Vec
(
ref
lifetimes
)
=>
{
RegionParamNames
(
opt_vec
::
Vec
(
lifetimes
.map
(|
lt
|
lt
.ident
)))
}
}
}
pub
fn
from_lifetimes
(
lifetimes
:
&
opt_vec
::
OptVec
<
ast
::
Lifetime
>
)
->
RegionParamNames
{
match
*
lifetimes
{
opt_vec
::
Empty
=>
RegionParamNames
::
new
(),
opt_vec
::
Vec
(
ref
v
)
=>
{
RegionParamNames
(
opt_vec
::
Vec
(
v
.map
(|
lt
|
lt
.ident
)))
}
}
}
fn
new
()
->
RegionParamNames
{
RegionParamNames
(
opt_vec
::
Empty
)
}
}
struct
RegionParameterization
{
variance
:
ty
::
region_variance
,
region_param_names
:
RegionParamNames
,
}
impl
RegionParameterization
{
pub
fn
from_variance_and_generics
(
variance
:
Option
<
ty
::
region_variance
>
,
generics
:
&
ast
::
Generics
)
->
Option
<
RegionParameterization
>
{
match
variance
{
None
=>
None
,
Some
(
variance
)
=>
{
Some
(
RegionParameterization
{
variance
:
variance
,
region_param_names
:
RegionParamNames
::
from_generics
(
generics
),
})
}
}
}
}
pub
struct
MethodRscope
{
self_ty
:
ast
::
self_ty_
,
region_parameterization
:
Option
<
ty
::
region_variance
>
variance
:
Option
<
ty
::
region_variance
>
,
region_param_names
:
RegionParamNames
,
}
impl
MethodRscope
{
// `generics` here refers to the generics of the outer item (impl or
// trait).
pub
fn
new
(
self_ty
:
ast
::
self_ty_
,
variance
:
Option
<
ty
::
region_variance
>
,
rcvr_generics
:
&
ast
::
Generics
,
method_generics
:
&
ast
::
Generics
)
->
MethodRscope
{
let
mut
region_param_names
=
RegionParamNames
::
from_generics
(
rcvr_generics
);
region_param_names
.add_generics
(
method_generics
);
MethodRscope
{
self_ty
:
self_ty
,
variance
:
variance
,
region_param_names
:
region_param_names
}
}
pub
fn
region_param_names
(
&
self
)
->
RegionParamNames
{
copy
self
.region_param_names
}
}
impl
region_scope
for
MethodRscope
{
fn
anon_region
(
&
self
,
_
span
:
span
)
->
Result
<
ty
::
Region
,
RegionError
>
{
result
::
Err
(
RegionError
{
...
...
@@ -59,12 +182,26 @@ fn anon_region(&self, _span: span) -> Result<ty::Region, RegionError> {
})
}
fn
self_region
(
&
self
,
_
span
:
span
)
->
Result
<
ty
::
Region
,
RegionError
>
{
fail_unless!
(
self
.region_parameterization
.is_some
()
||
self
.self_ty
.is_borrowed
());
fail_unless!
(
self
.variance
.is_some
()
||
self
.self_ty
.is_borrowed
());
match
self
.variance
{
None
=>
{}
// must be borrowed self, so this is OK
Some
(
_
)
=>
{
if
!
self
.self_ty
.is_borrowed
()
&&
!
self
.region_param_names
.has_self
()
{
return
Err
(
RegionError
{
msg
:
~
"the `self` lifetime must be declared"
,
replacement
:
ty
::
re_bound
(
ty
::
br_self
)
})
}
}
}
result
::
Ok
(
ty
::
re_bound
(
ty
::
br_self
))
}
fn
named_region
(
&
self
,
span
:
span
,
id
:
ast
::
ident
)
->
Result
<
ty
::
Region
,
RegionError
>
{
if
!
self
.region_param_names
.has_ident
(
id
)
{
return
RegionParamNames
::
undeclared_name
(
None
);
}
do
empty_rscope
.named_region
(
span
,
id
)
.chain_err
|
_
e
|
{
result
::
Err
(
RegionError
{
msg
:
~
"lifetime is not in scope"
,
...
...
@@ -74,7 +211,7 @@ fn named_region(&self, span: span, id: ast::ident)
}
}
pub
struct
type_rscope
(
Option
<
ty
::
region_variance
>
);
pub
struct
type_rscope
(
Option
<
RegionParameterization
>
);
impl
type_rscope
{
priv
fn
replacement
(
&
self
)
->
ty
::
Region
{
...
...
@@ -93,17 +230,29 @@ fn anon_region(&self, _span: span) -> Result<ty::Region, RegionError> {
})
}
fn
self_region
(
&
self
,
_
span
:
span
)
->
Result
<
ty
::
Region
,
RegionError
>
{
match
**
self
{
None
=>
{
// if the self region is used, region parameterization should
// have inferred that this type is RP
fail_unless!
(
self
.is_some
());
fail
!
(
~
"region parameterization should have inferred that
\
this type is RP"
);
}
Some
(
ref
region_parameterization
)
=>
{
if
!
region_parameterization
.region_param_names
.has_self
()
{
return
Err
(
RegionError
{
msg
:
~
"the `self` lifetime must be declared"
,
replacement
:
ty
::
re_bound
(
ty
::
br_self
)
})
}
}
}
result
::
Ok
(
ty
::
re_bound
(
ty
::
br_self
))
}
fn
named_region
(
&
self
,
span
:
span
,
id
:
ast
::
ident
)
->
Result
<
ty
::
Region
,
RegionError
>
{
do
empty_rscope
.named_region
(
span
,
id
)
.chain_err
|
_
e
|
{
result
::
Err
(
RegionError
{
msg
:
~
"only 'self is allowed allowed as
\
part of a type declaration"
,
msg
:
~
"only 'self is allowed as part of a type declaration"
,
replacement
:
self
.replacement
()
})
}
...
...
@@ -121,14 +270,33 @@ pub fn bound_self_region(rp: Option<ty::region_variance>)
pub
struct
binding_rscope
{
base
:
@
region_scope
,
anon_bindings
:
@
mut
uint
,
region_param_names
:
RegionParamNames
,
}
pub
fn
in_binding_rscope
<
RS
:
region_scope
+
Copy
+
Durable
>
(
self
:
&
RS
)
->
binding_rscope
{
let
base
=
@
copy
*
self
;
let
base
=
base
as
@
region_scope
;
binding_rscope
{
base
:
base
,
anon_bindings
:
@
mut
0
}
binding_rscope
{
base
:
base
,
anon_bindings
:
@
mut
0
,
region_param_names
:
RegionParamNames
::
new
()
}
}
pub
fn
in_binding_rscope_ext
<
RS
:
region_scope
+
Copy
+
Durable
>
(
self
:
&
RS
,
+
region_param_names
:
RegionParamNames
)
->
binding_rscope
{
let
base
=
@
copy
*
self
;
let
base
=
base
as
@
region_scope
;
binding_rscope
{
base
:
base
,
anon_bindings
:
@
mut
0
,
region_param_names
:
region_param_names
,
}
}
impl
region_scope
for
binding_rscope
{
fn
anon_region
(
&
self
,
_
span
:
span
)
->
Result
<
ty
::
Region
,
RegionError
>
{
let
idx
=
*
self
.anon_bindings
;
...
...
@@ -143,7 +311,12 @@ fn named_region(&self,
id
:
ast
::
ident
)
->
Result
<
ty
::
Region
,
RegionError
>
{
do
self
.base
.named_region
(
span
,
id
)
.chain_err
|
_
e
|
{
result
::
Ok
(
ty
::
re_bound
(
ty
::
br_named
(
id
)))
let
result
=
ty
::
re_bound
(
ty
::
br_named
(
id
));
if
self
.region_param_names
.has_ident
(
id
)
{
result
::
Ok
(
result
)
}
else
{
RegionParamNames
::
undeclared_name
(
Some
(
result
))
}
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录