Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
8e1de177
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,发现更多精彩内容 >>
提交
8e1de177
编写于
10月 28, 2013
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Create a new pass to resolve named lifetimes; rscope is not only
used to indicate when anonymous regions (i.e., &T) are permitted
上级
a594a999
变更
10
显示空白变更内容
内联
并排
Showing
10 changed file
with
644 addition
and
404 deletion
+644
-404
src/librustc/driver/driver.rs
src/librustc/driver/driver.rs
+5
-2
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/resolve_lifetime.rs
+321
-0
src/librustc/middle/ty.rs
src/librustc/middle/ty.rs
+5
-0
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/astconv.rs
+88
-101
src/librustc/middle/typeck/rscope.rs
src/librustc/middle/typeck/rscope.rs
+33
-286
src/libsyntax/ast.rs
src/libsyntax/ast.rs
+14
-0
src/libsyntax/visit.rs
src/libsyntax/visit.rs
+88
-15
src/test/compile-fail/regions-name-duplicated.rs
src/test/compile-fail/regions-name-duplicated.rs
+15
-0
src/test/compile-fail/regions-name-static.rs
src/test/compile-fail/regions-name-static.rs
+15
-0
src/test/compile-fail/regions-name-undeclared.rs
src/test/compile-fail/regions-name-undeclared.rs
+60
-0
未找到文件。
src/librustc/driver/driver.rs
浏览文件 @
8e1de177
...
...
@@ -239,6 +239,9 @@ pub fn phase_3_run_analysis_passes(sess: Session,
time
(
time_passes
,
"resolution"
,
(),
|
_
|
middle
::
resolve
::
resolve_crate
(
sess
,
lang_items
,
crate
));
let
named_region_map
=
time
(
time_passes
,
"lifetime resolution"
,
(),
|
_
|
middle
::
resolve_lifetime
::
crate
(
sess
,
crate
));
time
(
time_passes
,
"looking for entry point"
,
(),
|
_
|
middle
::
entry
::
find_entry_point
(
sess
,
crate
,
ast_map
));
...
...
@@ -251,8 +254,8 @@ pub fn phase_3_run_analysis_passes(sess: Session,
let
rp_set
=
time
(
time_passes
,
"region parameterization inference"
,
(),
|
_
|
middle
::
region
::
determine_rp_in_crate
(
sess
,
ast_map
,
def_map
,
crate
));
let
ty_cx
=
ty
::
mk_ctxt
(
sess
,
def_map
,
ast_map
,
freevars
,
region_map
,
rp_set
,
lang_items
);
let
ty_cx
=
ty
::
mk_ctxt
(
sess
,
def_map
,
named_region_map
,
ast_map
,
freevars
,
region_map
,
lang_items
);
// passes are timed inside typeck
let
(
method_map
,
vtable_map
)
=
typeck
::
check_crate
(
...
...
src/librustc/middle/resolve_lifetime.rs
0 → 100644
浏览文件 @
8e1de177
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*!
* Name resolution for lifetimes.
*
* Name resolution for lifetimes follows MUCH simpler rules than the
* full resolve. For example, lifetime names are never exported or
* used between functions, and they operate in a purely top-down
* way. Therefore we break lifetime name resolution into a separate pass.
*/
use
driver
::
session
;
use
std
::
hashmap
::
HashMap
;
use
syntax
::
ast
;
use
syntax
::
codemap
::
Span
;
use
syntax
::
opt_vec
::
OptVec
;
use
syntax
::
parse
::
token
::
special_idents
;
use
syntax
::
print
::
pprust
::{
lifetime_to_str
};
use
syntax
::
visit
;
use
syntax
::
visit
::
Visitor
;
// maps the id of each lifetime reference to the lifetime decl
// that it corresponds to
pub
type
NamedRegionMap
=
HashMap
<
ast
::
NodeId
,
ast
::
DefRegion
>
;
struct
LifetimeContext
{
sess
:
session
::
Session
,
named_region_map
:
@
mut
NamedRegionMap
,
}
enum
ScopeChain
<
'self
>
{
ItemScope
(
&
'self
OptVec
<
ast
::
Lifetime
>
),
FnScope
(
ast
::
NodeId
,
&
'self
OptVec
<
ast
::
Lifetime
>
,
&
'self
ScopeChain
<
'self
>
),
BlockScope
(
ast
::
NodeId
,
&
'self
ScopeChain
<
'self
>
),
RootScope
}
pub
fn
crate
(
sess
:
session
::
Session
,
crate
:
&
ast
::
Crate
)
->
@
mut
NamedRegionMap
{
let
mut
ctxt
=
LifetimeContext
{
sess
:
sess
,
named_region_map
:
@
mut
HashMap
::
new
()
};
visit
::
walk_crate
(
&
mut
ctxt
,
crate
,
&
RootScope
);
sess
.abort_if_errors
();
ctxt
.named_region_map
}
impl
<
'self
>
Visitor
<&
'self
ScopeChain
<
'self
>>
for
LifetimeContext
{
fn
visit_item
(
&
mut
self
,
item
:
@
ast
::
item
,
_
:
&
'self
ScopeChain
<
'self
>
)
{
let
scope
=
match
item
.node
{
ast
::
item_fn
(
*
)
|
// fn lifetimes get added in visit_fn below
ast
::
item_mod
(
*
)
|
ast
::
item_mac
(
*
)
|
ast
::
item_foreign_mod
(
*
)
|
ast
::
item_static
(
*
)
=>
{
RootScope
}
ast
::
item_ty
(
_
,
ref
generics
)
|
ast
::
item_enum
(
_
,
ref
generics
)
|
ast
::
item_struct
(
_
,
ref
generics
)
|
ast
::
item_impl
(
ref
generics
,
_
,
_
,
_
)
|
ast
::
item_trait
(
ref
generics
,
_
,
_
)
=>
{
self
.check_lifetime_names
(
&
generics
.lifetimes
);
ItemScope
(
&
generics
.lifetimes
)
}
};
debug!
(
"entering scope {:?}"
,
scope
);
visit
::
walk_item
(
self
,
item
,
&
scope
);
debug!
(
"exiting scope {:?}"
,
scope
);
}
fn
visit_fn
(
&
mut
self
,
fk
:
&
visit
::
fn_kind
,
fd
:
&
ast
::
fn_decl
,
b
:
&
ast
::
Block
,
s
:
Span
,
n
:
ast
::
NodeId
,
scope
:
&
'self
ScopeChain
<
'self
>
)
{
match
*
fk
{
visit
::
fk_item_fn
(
_
,
generics
,
_
,
_
)
|
visit
::
fk_method
(
_
,
generics
,
_
)
=>
{
let
scope1
=
FnScope
(
n
,
&
generics
.lifetimes
,
scope
);
self
.check_lifetime_names
(
&
generics
.lifetimes
);
debug!
(
"pushing fn scope id={} due to item/method"
,
n
);
visit
::
walk_fn
(
self
,
fk
,
fd
,
b
,
s
,
n
,
&
scope1
);
debug!
(
"popping fn scope id={} due to item/method"
,
n
);
}
visit
::
fk_anon
(
*
)
|
visit
::
fk_fn_block
(
*
)
=>
{
visit
::
walk_fn
(
self
,
fk
,
fd
,
b
,
s
,
n
,
scope
);
}
}
}
fn
visit_ty
(
&
mut
self
,
ty
:
&
ast
::
Ty
,
scope
:
&
'self
ScopeChain
<
'self
>
)
{
match
ty
.node
{
ast
::
ty_closure
(
@
ast
::
TyClosure
{
lifetimes
:
ref
lifetimes
,
_
})
|
ast
::
ty_bare_fn
(
@
ast
::
TyBareFn
{
lifetimes
:
ref
lifetimes
,
_
})
=>
{
let
scope1
=
FnScope
(
ty
.id
,
lifetimes
,
scope
);
self
.check_lifetime_names
(
lifetimes
);
debug!
(
"pushing fn scope id={} due to type"
,
ty
.id
);
visit
::
walk_ty
(
self
,
ty
,
&
scope1
);
debug!
(
"popping fn scope id={} due to type"
,
ty
.id
);
}
_
=>
{
visit
::
walk_ty
(
self
,
ty
,
scope
);
}
}
}
fn
visit_ty_method
(
&
mut
self
,
m
:
&
ast
::
TypeMethod
,
scope
:
&
'self
ScopeChain
<
'self
>
)
{
let
scope1
=
FnScope
(
m
.id
,
&
m
.generics.lifetimes
,
scope
);
self
.check_lifetime_names
(
&
m
.generics.lifetimes
);
debug!
(
"pushing fn scope id={} due to ty_method"
,
m
.id
);
visit
::
walk_ty_method
(
self
,
m
,
&
scope1
);
debug!
(
"popping fn scope id={} due to ty_method"
,
m
.id
);
}
fn
visit_block
(
&
mut
self
,
b
:
&
ast
::
Block
,
scope
:
&
'self
ScopeChain
<
'self
>
)
{
let
scope1
=
BlockScope
(
b
.id
,
scope
);
debug!
(
"pushing block scope {}"
,
b
.id
);
visit
::
walk_block
(
self
,
b
,
&
scope1
);
debug!
(
"popping block scope {}"
,
b
.id
);
}
fn
visit_lifetime_ref
(
&
mut
self
,
lifetime_ref
:
&
ast
::
Lifetime
,
scope
:
&
'self
ScopeChain
<
'self
>
)
{
if
lifetime_ref
.ident
==
special_idents
::
statik
{
self
.insert_lifetime
(
lifetime_ref
,
ast
::
DefStaticRegion
);
return
;
}
self
.resolve_lifetime_ref
(
lifetime_ref
,
scope
);
}
}
impl
LifetimeContext
{
fn
resolve_lifetime_ref
(
&
self
,
lifetime_ref
:
&
ast
::
Lifetime
,
scope
:
&
ScopeChain
)
{
// Walk up the scope chain, tracking the number of fn scopes
// that we pass through, until we find a lifetime with the
// given name or we run out of scopes. If we encounter a code
// block, then the lifetime is not bound but free, so switch
// over to `resolve_free_lifetime_ref()` to complete the
// search.
let
mut
depth
=
0
;
let
mut
scope
=
scope
;
loop
{
match
*
scope
{
BlockScope
(
id
,
s
)
=>
{
return
self
.resolve_free_lifetime_ref
(
id
,
lifetime_ref
,
s
);
}
RootScope
=>
{
break
;
}
ItemScope
(
lifetimes
)
=>
{
match
search_lifetimes
(
lifetimes
,
lifetime_ref
)
{
Some
((
index
,
decl_id
))
=>
{
let
def
=
ast
::
DefTypeBoundRegion
(
index
,
decl_id
);
self
.insert_lifetime
(
lifetime_ref
,
def
);
return
;
}
None
=>
{
break
;
}
}
}
FnScope
(
id
,
lifetimes
,
s
)
=>
{
match
search_lifetimes
(
lifetimes
,
lifetime_ref
)
{
Some
((
_
index
,
decl_id
))
=>
{
let
def
=
ast
::
DefFnBoundRegion
(
id
,
depth
,
decl_id
);
self
.insert_lifetime
(
lifetime_ref
,
def
);
return
;
}
None
=>
{
depth
+=
1
;
scope
=
s
;
}
}
}
}
}
self
.unresolved_lifetime_ref
(
lifetime_ref
);
}
fn
resolve_free_lifetime_ref
(
&
self
,
scope_id
:
ast
::
NodeId
,
lifetime_ref
:
&
ast
::
Lifetime
,
scope
:
&
ScopeChain
)
{
// Walk up the scope chain, tracking the outermost free scope,
// until we encounter a scope that contains the named lifetime
// or we run out of scopes.
let
mut
scope_id
=
scope_id
;
let
mut
scope
=
scope
;
let
mut
search_result
=
None
;
loop
{
match
*
scope
{
BlockScope
(
id
,
s
)
=>
{
scope_id
=
id
;
scope
=
s
;
}
RootScope
=>
{
break
;
}
ItemScope
(
lifetimes
)
=>
{
search_result
=
search_lifetimes
(
lifetimes
,
lifetime_ref
);
break
;
}
FnScope
(
_
,
lifetimes
,
s
)
=>
{
search_result
=
search_lifetimes
(
lifetimes
,
lifetime_ref
);
if
search_result
.is_some
()
{
break
;
}
scope
=
s
;
}
}
}
match
search_result
{
Some
((
_
depth
,
decl_id
))
=>
{
let
def
=
ast
::
DefFreeRegion
(
scope_id
,
decl_id
);
self
.insert_lifetime
(
lifetime_ref
,
def
);
}
None
=>
{
self
.unresolved_lifetime_ref
(
lifetime_ref
);
}
}
}
fn
unresolved_lifetime_ref
(
&
self
,
lifetime_ref
:
&
ast
::
Lifetime
)
{
self
.sess
.span_err
(
lifetime_ref
.span
,
format!
(
"use of undeclared lifetime name `'{}`"
,
self
.sess
.str_of
(
lifetime_ref
.ident
)));
}
fn
check_lifetime_names
(
&
self
,
lifetimes
:
&
OptVec
<
ast
::
Lifetime
>
)
{
for
i
in
range
(
0
,
lifetimes
.len
())
{
let
lifetime_i
=
lifetimes
.get
(
i
);
let
special_idents
=
[
special_idents
::
statik
];
for
lifetime
in
lifetimes
.iter
()
{
if
special_idents
.iter
()
.any
(|
&
i
|
i
==
lifetime
.ident
)
{
self
.sess
.span_err
(
lifetime
.span
,
format!
(
"illegal lifetime parameter name: `{}`"
,
self
.sess
.str_of
(
lifetime
.ident
)));
}
}
for
j
in
range
(
i
+
1
,
lifetimes
.len
())
{
let
lifetime_j
=
lifetimes
.get
(
j
);
if
lifetime_i
.ident
==
lifetime_j
.ident
{
self
.sess
.span_err
(
lifetime_j
.span
,
format!
(
"lifetime name `'{}` declared twice in
\
the same scope"
,
self
.sess
.str_of
(
lifetime_j
.ident
)));
}
}
}
}
fn
insert_lifetime
(
&
self
,
lifetime_ref
:
&
ast
::
Lifetime
,
def
:
ast
::
DefRegion
)
{
if
lifetime_ref
.id
==
ast
::
DUMMY_NODE_ID
{
self
.sess
.span_bug
(
lifetime_ref
.span
,
"Lifetime reference not renumbered,
\
probably a bug in syntax::fold"
);
}
debug!
(
"lifetime_ref={} id={} resolved to {:?}"
,
lifetime_to_str
(
lifetime_ref
,
self
.sess
.intr
()),
lifetime_ref
.id
,
def
);
self
.named_region_map
.insert
(
lifetime_ref
.id
,
def
);
}
}
fn
search_lifetimes
(
lifetimes
:
&
OptVec
<
ast
::
Lifetime
>
,
lifetime_ref
:
&
ast
::
Lifetime
)
->
Option
<
(
uint
,
ast
::
NodeId
)
>
{
for
(
i
,
lifetime_decl
)
in
lifetimes
.iter
()
.enumerate
()
{
if
lifetime_decl
.ident
==
lifetime_ref
.ident
{
return
Some
((
i
,
lifetime_decl
.id
));
}
}
return
None
;
}
src/librustc/middle/ty.rs
浏览文件 @
8e1de177
...
...
@@ -17,6 +17,7 @@
use
middle
::
lang_items
::
OpaqueStructLangItem
;
use
middle
::
freevars
;
use
middle
::
resolve
;
use
middle
::
resolve_lifetime
;
use
middle
::
ty
;
use
middle
::
subst
::
Subst
;
use
middle
::
typeck
;
...
...
@@ -258,6 +259,8 @@ struct ctxt_ {
sess
:
session
::
Session
,
def_map
:
resolve
::
DefMap
,
named_region_map
:
@
mut
resolve_lifetime
::
NamedRegionMap
,
region_maps
:
@
mut
middle
::
region
::
RegionMaps
,
region_paramd_items
:
middle
::
region
::
region_paramd_items
,
...
...
@@ -919,6 +922,7 @@ pub fn new_ty_hash<V:'static>() -> @mut HashMap<t, V> {
pub
fn
mk_ctxt
(
s
:
session
::
Session
,
dm
:
resolve
::
DefMap
,
named_region_map
:
@
mut
resolve_lifetime
::
NamedRegionMap
,
amap
:
ast_map
::
map
,
freevars
:
freevars
::
freevar_map
,
region_maps
:
@
mut
middle
::
region
::
RegionMaps
,
...
...
@@ -926,6 +930,7 @@ pub fn mk_ctxt(s: session::Session,
lang_items
:
middle
::
lang_items
::
LanguageItems
)
->
ctxt
{
@
ctxt_
{
named_region_map
:
named_region_map
,
diag
:
s
.diagnostic
(),
interner
:
@
mut
HashMap
::
new
(),
next_id
:
@
mut
primitives
::
LAST_PRIMITIVE_ID
,
...
...
src/librustc/middle/typeck/astconv.rs
浏览文件 @
8e1de177
...
...
@@ -23,13 +23,10 @@
* In the check phase, when the @FnCtxt is used as the `AstConv`,
* `get_item_ty()` just looks up the item type in `tcx.tcache`.
*
* The `RegionScope` trait controls how region references are
* handled. It has two methods which are used to resolve anonymous
* region references (e.g., `&T`) and named region references (e.g.,
* `&a.T`). There are numerous region scopes that can be used, but most
* commonly you want either `EmptyRscope`, which permits only the static
* region, or `TypeRscope`, which permits the self region if the type in
* question is parameterized by a region.
* The `RegionScope` trait controls what happens when the user does
* not specify a region in some location where a region is required
* (e.g., if the user writes `&Foo` as a type rather than `&'a Foo`).
* See the `rscope` module for more details.
*
* Unlike the `AstConv` trait, the region scope can change as we descend
* the type. This is to accommodate the fact that (a) fn types are binding
...
...
@@ -57,20 +54,17 @@
use
middle
::
ty
::{
substs
};
use
middle
::
ty
::{
ty_param_substs_and_ty
};
use
middle
::
ty
;
use
middle
::
typeck
::
rscope
::
in_binding_rscope
;
use
middle
::
typeck
::
rscope
::{
RegionScope
,
RegionError
};
use
middle
::
typeck
::
rscope
::
RegionParamNames
;
use
middle
::
typeck
::
rscope
;
use
middle
::
typeck
::
rscope
::{
RegionScope
};
use
middle
::
typeck
::
lookup_def_tcx
;
use
std
::
result
;
use
std
::
vec
;
use
syntax
::
abi
::
AbiSet
;
use
syntax
::{
ast
,
ast_util
};
use
syntax
::
codemap
::
Span
;
use
syntax
::
opt_vec
::
OptVec
;
use
syntax
::
opt_vec
;
use
syntax
::
print
::
pprust
::{
lifetime_to_str
,
path_to_str
};
use
syntax
::
parse
::
token
::
special_idents
;
use
util
::
common
::
indenter
;
pub
trait
AstConv
{
fn
tcx
(
&
self
)
->
ty
::
ctxt
;
...
...
@@ -81,55 +75,83 @@ pub trait AstConv {
fn
ty_infer
(
&
self
,
span
:
Span
)
->
ty
::
t
;
}
pub
fn
get_region_reporting_err
(
pub
fn
ast_region_to_region
(
tcx
:
ty
::
ctxt
,
span
:
Span
,
a_r
:
&
Option
<
ast
::
Lifetime
>
,
res
:
Result
<
ty
::
Region
,
RegionError
>
)
->
ty
::
Region
lifetime
:
&
ast
::
Lifetime
)
->
ty
::
Region
{
match
res
{
result
::
Ok
(
r
)
=>
r
,
result
::
Err
(
ref
e
)
=>
{
let
descr
=
match
a_r
{
&
None
=>
~
"anonymous lifetime"
,
&
Some
(
ref
a
)
=>
format!
(
"lifetime {}"
,
lifetime_to_str
(
a
,
tcx
.sess
.intr
()))
};
tcx
.sess
.span_err
(
span
,
format!
(
"Illegal {}: {}"
,
descr
,
e
.msg
));
e
.replacement
let
r
=
match
tcx
.named_region_map
.find
(
&
lifetime
.id
)
{
None
=>
{
// should have been recorded by the `resolve_lifetime` pass
tcx
.sess
.span_bug
(
lifetime
.span
,
"unresolved lifetime"
);
}
Some
(
&
ast
::
DefStaticRegion
)
=>
{
ty
::
re_static
}
Some
(
&
ast
::
DefFnBoundRegion
(
binder_id
,
_
,
id
))
=>
{
ty
::
re_fn_bound
(
binder_id
,
ty
::
br_named
(
ast_util
::
local_def
(
id
),
lifetime
.ident
))
}
Some
(
&
ast
::
DefTypeBoundRegion
(
index
,
id
))
=>
{
ty
::
re_type_bound
(
id
,
index
,
lifetime
.ident
)
}
Some
(
&
ast
::
DefFreeRegion
(
scope_id
,
id
))
=>
{
ty
::
re_free
(
ty
::
FreeRegion
{
scope_id
:
scope_id
,
bound_region
:
ty
::
br_named
(
ast_util
::
local_def
(
id
),
lifetime
.ident
)
})
}
};
debug!
(
"ast_region_to_region(lifetime={} id={}) yields {}"
,
lifetime_to_str
(
lifetime
,
tcx
.sess
.intr
()),
lifetime
.id
,
r
.repr
(
tcx
));
r
}
pub
fn
ast_region_to_region
<
AC
:
AstConv
,
RS
:
RegionScope
+
Clone
+
'static
>
(
pub
fn
opt_ast_region_to_region
<
AC
:
AstConv
,
RS
:
RegionScope
>
(
this
:
&
AC
,
rscope
:
&
RS
,
default_span
:
Span
,
opt_lifetime
:
&
Option
<
ast
::
Lifetime
>
)
->
ty
::
Region
{
let
(
span
,
res
)
=
match
opt_lifetime
{
&
None
=>
{
(
default_span
,
rscope
.anon_region
(
default_span
)
)
let
r
=
match
*
opt_lifetime
{
Some
(
ref
lifetime
)
=>
{
ast_region_to_region
(
this
.tcx
(),
lifetime
)
}
&
Some
(
ref
lifetime
)
if
lifetime
.ident
==
special_idents
::
statik
=>
{
(
lifetime
.span
,
Ok
(
ty
::
re_static
))
None
=>
{
match
rscope
.anon_regions
(
default_span
,
1
)
{
None
=>
{
debug!
(
"optional region in illegal location"
);
this
.tcx
()
.sess
.span_err
(
default_span
,
"missing lifetime specifier"
);
ty
::
re_static
}
Some
(
rs
)
=>
{
rs
[
0
]
}
&
Some
(
ref
lifetime
)
if
lifetime
.ident
==
special_idents
::
self_
=>
{
(
lifetime
.span
,
rscope
.self_region
(
lifetime
.span
))
}
&
Some
(
ref
lifetime
)
=>
{
(
lifetime
.span
,
rscope
.named_region
(
lifetime
.span
,
lifetime
.ident
))
}
};
get_region_reporting_err
(
this
.tcx
(),
span
,
opt_lifetime
,
res
)
debug!
(
"opt_ast_region_to_region(opt_lifetime={:?}) yields {}"
,
opt_lifetime
.as_ref
()
.map
(
|
e
|
lifetime_to_str
(
e
,
this
.tcx
()
.sess
.intr
())),
r
.repr
(
this
.tcx
()));
r
}
fn
ast_path_substs
<
AC
:
AstConv
,
RS
:
RegionScope
+
Clone
+
'static
>
(
fn
ast_path_substs
<
AC
:
AstConv
,
RS
:
RegionScope
>
(
this
:
&
AC
,
rscope
:
&
RS
,
def_id
:
ast
::
DefId
,
...
...
@@ -200,7 +222,7 @@ fn ast_path_substs<AC:AstConv,RS:RegionScope + Clone + 'static>(
}
pub
fn
ast_path_to_substs_and_ty
<
AC
:
AstConv
,
RS
:
RegionScope
+
Clone
+
'static
>
(
RS
:
RegionScope
>
(
this
:
&
AC
,
rscope
:
&
RS
,
did
:
ast
::
DefId
,
...
...
@@ -217,7 +239,7 @@ pub fn ast_path_to_substs_and_ty<AC:AstConv,
ty_param_substs_and_ty
{
substs
:
substs
,
ty
:
ty
}
}
pub
fn
ast_path_to_trait_ref
<
AC
:
AstConv
,
RS
:
RegionScope
+
Clone
+
'static
>
(
pub
fn
ast_path_to_trait_ref
<
AC
:
AstConv
,
RS
:
RegionScope
>
(
this
:
&
AC
,
rscope
:
&
RS
,
trait_def_id
:
ast
::
DefId
,
...
...
@@ -240,7 +262,7 @@ pub fn ast_path_to_trait_ref<AC:AstConv,RS:RegionScope + Clone + 'static>(
return
trait_ref
;
}
pub
fn
ast_path_to_ty
<
AC
:
AstConv
,
RS
:
RegionScope
+
Clone
+
'static
>
(
pub
fn
ast_path_to_ty
<
AC
:
AstConv
,
RS
:
RegionScope
>
(
this
:
&
AC
,
rscope
:
&
RS
,
did
:
ast
::
DefId
,
...
...
@@ -262,10 +284,10 @@ pub fn ast_path_to_ty<AC:AstConv,RS:RegionScope + Clone + 'static>(
// Parses the programmer's textual representation of a type into our
// internal notion of a type. `getter` is a function that returns the type
// corresponding to a definition ID:
pub
fn
ast_ty_to_ty
<
AC
:
AstConv
,
RS
:
RegionScope
+
Clone
+
'static
>
(
pub
fn
ast_ty_to_ty
<
AC
:
AstConv
,
RS
:
RegionScope
>
(
this
:
&
AC
,
rscope
:
&
RS
,
ast_ty
:
&
ast
::
Ty
)
->
ty
::
t
{
fn
ast_mt_to_mt
<
AC
:
AstConv
,
RS
:
RegionScope
+
Clone
+
'static
>
(
fn
ast_mt_to_mt
<
AC
:
AstConv
,
RS
:
RegionScope
>
(
this
:
&
AC
,
rscope
:
&
RS
,
mt
:
&
ast
::
mt
)
->
ty
::
mt
{
ty
::
mt
{
ty
:
ast_ty_to_ty
(
this
,
rscope
,
mt
.ty
),
mutbl
:
mt
.mutbl
}
...
...
@@ -274,7 +296,7 @@ fn ast_mt_to_mt<AC:AstConv, RS:RegionScope + Clone + 'static>(
// Handle @, ~, and & being able to mean estrs and evecs.
// If a_seq_ty is a str or a vec, make it an estr/evec.
// Also handle first-class trait types.
fn
mk_pointer
<
AC
:
AstConv
,
RS
:
RegionScope
+
Clone
+
'static
>
(
fn
mk_pointer
<
AC
:
AstConv
,
RS
:
RegionScope
>
(
this
:
&
AC
,
rscope
:
&
RS
,
a_seq_ty
:
&
ast
::
mt
,
...
...
@@ -387,7 +409,8 @@ fn check_path_args(tcx: ty::ctxt,
ty
::
mk_ptr
(
tcx
,
ast_mt_to_mt
(
this
,
rscope
,
mt
))
}
ast
::
ty_rptr
(
ref
region
,
ref
mt
)
=>
{
let
r
=
ast_region_to_region
(
this
,
rscope
,
ast_ty
.span
,
region
);
let
r
=
opt_ast_region_to_region
(
this
,
rscope
,
ast_ty
.span
,
region
);
debug!
(
"ty_rptr r={}"
,
r
.repr
(
this
.tcx
()));
mk_pointer
(
this
,
rscope
,
mt
,
ty
::
vstore_slice
(
r
),
|
tmt
|
ty
::
mk_rptr
(
tcx
,
r
,
tmt
))
}
...
...
@@ -551,7 +574,7 @@ fn check_path_args(tcx: ty::ctxt,
}
pub
fn
ty_of_arg
<
AC
:
AstConv
,
RS
:
RegionScope
+
Clone
+
'static
>
(
RS
:
RegionScope
>
(
this
:
&
AC
,
rscope
:
&
RS
,
a
:
&
ast
::
arg
,
...
...
@@ -564,42 +587,12 @@ pub fn ty_of_arg<AC:AstConv,
}
}
pub
fn
bound_lifetimes
<
AC
:
AstConv
>
(
this
:
&
AC
,
ast_lifetimes
:
&
OptVec
<
ast
::
Lifetime
>
)
->
OptVec
<
ast
::
Ident
>
{
/*!
*
* Converts a list of lifetimes into a list of bound identifier
* names. Does not permit special names like 'static or 'this to
* be bound. Note that this function is for use in closures,
* methods, and fn definitions. It is legal to bind 'this in a
* type. Eventually this distinction should go away and the same
* rules should apply everywhere ('this would not be a special name
* at that point).
*/
let
special_idents
=
[
special_idents
::
statik
,
special_idents
::
self_
];
let
mut
bound_lifetime_names
=
opt_vec
::
Empty
;
ast_lifetimes
.map_to_vec
(|
ast_lifetime
|
{
if
special_idents
.iter
()
.any
(|
&
i
|
i
==
ast_lifetime
.ident
)
{
this
.tcx
()
.sess
.span_err
(
ast_lifetime
.span
,
format!
(
"illegal lifetime parameter name: `{}`"
,
lifetime_to_str
(
ast_lifetime
,
this
.tcx
()
.sess
.intr
())));
}
else
{
bound_lifetime_names
.push
(
ast_lifetime
.ident
);
}
});
bound_lifetime_names
}
struct
SelfInfo
{
untransformed_self_ty
:
ty
::
t
,
explicit_self
:
ast
::
explicit_self
}
pub
fn
ty_of_method
<
AC
:
AstConv
,
RS
:
RegionScope
+
Clone
+
'static
>
(
pub
fn
ty_of_method
<
AC
:
AstConv
>
(
this
:
&
AC
,
rscope
:
&
RS
,
purity
:
ast
::
purity
,
...
...
@@ -643,10 +636,7 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:RegionScope + Clone + 'static>(
// new region names that appear inside of the fn decl are bound to
// that function type
let
bound_lifetime_names
=
bound_lifetimes
(
this
,
lifetimes
);
let
rb
=
in_binding_rscope
(
rscope
,
RegionParamNames
(
bound_lifetime_names
.clone
()));
let
rb
=
rscope
::
BindingRscope
::
new
(
id
);
let
opt_transformed_self_ty
=
do
opt_self_info
.map
|
self_info
|
{
transform_self_ty
(
this
,
&
rb
,
self_info
)
...
...
@@ -671,7 +661,7 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:RegionScope + Clone + 'static>(
}
});
fn
transform_self_ty
<
AC
:
AstConv
,
RS
:
RegionScope
+
Clone
+
'static
>
(
fn
transform_self_ty
<
AC
:
AstConv
,
RS
:
RegionScope
>
(
this
:
&
AC
,
rscope
:
&
RS
,
self_info
:
&
SelfInfo
)
->
Option
<
ty
::
t
>
...
...
@@ -683,7 +673,7 @@ fn transform_self_ty<AC:AstConv,RS:RegionScope + Clone + 'static>(
}
ast
::
sty_region
(
ref
lifetime
,
mutability
)
=>
{
let
region
=
ast_region_to_region
(
this
,
rscope
,
opt_
ast_region_to_region
(
this
,
rscope
,
self_info
.explicit_self.span
,
lifetime
);
Some
(
ty
::
mk_rptr
(
this
.tcx
(),
region
,
...
...
@@ -704,7 +694,7 @@ fn transform_self_ty<AC:AstConv,RS:RegionScope + Clone + 'static>(
}
}
pub
fn
ty_of_closure
<
AC
:
AstConv
,
RS
:
RegionScope
+
Clone
+
'static
>
(
pub
fn
ty_of_closure
<
AC
:
AstConv
,
RS
:
RegionScope
>
(
this
:
&
AC
,
rscope
:
&
RS
,
sigil
:
ast
::
Sigil
,
...
...
@@ -729,8 +719,8 @@ pub fn ty_of_closure<AC:AstConv,RS:RegionScope + Clone + 'static>(
// resolve the function bound region in the original region
// scope `rscope`, not the scope of the function parameters
let
bound_region
=
match
opt_lifetime
{
&
Some
(
_
)
=>
{
ast_region_to_region
(
this
,
rscope
,
span
,
opt_
lifetime
)
&
Some
(
ref
lifetime
)
=>
{
ast_region_to_region
(
this
.tcx
(),
lifetime
)
}
&
None
=>
{
match
sigil
{
...
...
@@ -741,7 +731,7 @@ pub fn ty_of_closure<AC:AstConv,RS:RegionScope + Clone + 'static>(
}
ast
::
BorrowedSigil
=>
{
// &fn() defaults as normal for an omitted lifetime:
ast_region_to_region
(
this
,
rscope
,
span
,
opt_lifetime
)
opt_
ast_region_to_region
(
this
,
rscope
,
span
,
opt_lifetime
)
}
}
}
...
...
@@ -749,10 +739,7 @@ pub fn ty_of_closure<AC:AstConv,RS:RegionScope + Clone + 'static>(
// new region names that appear inside of the fn decl are bound to
// that function type
let
bound_lifetime_names
=
bound_lifetimes
(
this
,
lifetimes
);
let
rb
=
in_binding_rscope
(
rscope
,
RegionParamNames
(
bound_lifetime_names
.clone
()));
let
rb
=
rscope
::
BindingRscope
::
new
(
id
);
let
input_tys
=
do
decl
.inputs
.iter
()
.enumerate
()
.map
|(
i
,
a
)|
{
let
expected_arg_ty
=
do
expected_sig
.as_ref
()
.and_then
|
e
|
{
...
...
src/librustc/middle/typeck/rscope.rs
浏览文件 @
8e1de177
...
...
@@ -11,312 +11,59 @@
use
middle
::
ty
;
use
std
::
result
;
use
std
::
vec
;
use
syntax
::
ast
;
use
syntax
::
codemap
::
Span
;
use
syntax
::
opt_vec
::
OptVec
;
use
syntax
::
opt_vec
;
use
syntax
::
parse
::
token
::
special_idents
;
#[deriving(ToStr)]
pub
struct
RegionError
{
msg
:
~
str
,
replacement
:
ty
::
Region
}
pub
trait
RegionScope
{
fn
anon_region
(
&
self
,
span
:
Span
)
->
Result
<
ty
::
Region
,
RegionError
>
;
fn
self_region
(
&
self
,
span
:
Span
)
->
Result
<
ty
::
Region
,
RegionError
>
;
fn
named_region
(
&
self
,
span
:
Span
,
id
:
ast
::
Ident
)
->
Result
<
ty
::
Region
,
RegionError
>
;
}
#[deriving(Clone)]
pub
struct
EmptyRscope
;
impl
RegionScope
for
EmptyRscope
{
fn
anon_region
(
&
self
,
_
span
:
Span
)
->
Result
<
ty
::
Region
,
RegionError
>
{
result
::
Err
(
RegionError
{
msg
:
~
"only 'static is allowed here"
,
replacement
:
ty
::
re_static
})
}
fn
self_region
(
&
self
,
_
span
:
Span
)
->
Result
<
ty
::
Region
,
RegionError
>
{
self
.anon_region
(
_
span
)
}
fn
named_region
(
&
self
,
_
span
:
Span
,
_
id
:
ast
::
Ident
)
->
Result
<
ty
::
Region
,
RegionError
>
{
self
.anon_region
(
_
span
)
}
}
#[deriving(Clone)]
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
region_param_name
in
self
.iter
()
{
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_lifetime
in
new_lifetimes
.iter
()
{
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
)
}
}
#[deriving(Clone)]
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
),
})
}
}
}
}
#[deriving(Clone)]
pub
struct
MethodRscope
{
explicit_self
:
ast
::
explicit_self_
,
variance
:
Option
<
ty
::
region_variance
>
,
region_param_names
:
RegionParamNames
,
fn
anon_regions
(
&
self
,
span
:
Span
,
count
:
uint
)
->
Option
<~
[
ty
::
Region
]
>
;
}
impl
MethodRscope
{
// `generics` here refers to the generics of the outer item (impl or
// trait).
pub
fn
new
(
explicit_self
:
ast
::
explicit_self_
,
variance
:
Option
<
ty
::
region_variance
>
,
rcvr_generics
:
&
ast
::
Generics
)
->
MethodRscope
{
let
region_param_names
=
RegionParamNames
::
from_generics
(
rcvr_generics
);
MethodRscope
{
explicit_self
:
explicit_self
,
variance
:
variance
,
region_param_names
:
region_param_names
}
}
pub
fn
region_param_names
(
&
self
)
->
RegionParamNames
{
self
.region_param_names
.clone
()
}
}
// A scope in which all regions must be explicitly named
pub
struct
ExplicitRscope
;
impl
RegionScope
for
MethodRscope
{
fn
anon_region
(
&
self
,
_
span
:
Span
)
->
Result
<
ty
::
Region
,
RegionError
>
{
result
::
Err
(
RegionError
{
msg
:
~
"anonymous lifetimes are not permitted here"
,
replacement
:
ty
::
re_bound
(
ty
::
br_self
)
})
}
fn
self_region
(
&
self
,
_
span
:
Span
)
->
Result
<
ty
::
Region
,
RegionError
>
{
assert
!
(
self
.variance
.is_some
());
match
self
.variance
{
None
=>
{}
// must be borrowed self, so this is OK
Some
(
_
)
=>
{
if
!
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
EmptyRscope
.named_region
(
span
,
id
)
.or_else
|
_
e
|
{
result
::
Err
(
RegionError
{
msg
:
~
"lifetime is not in scope"
,
replacement
:
ty
::
re_bound
(
ty
::
br_self
)
})
}
}
}
#[deriving(Clone)]
pub
struct
TypeRscope
(
Option
<
RegionParameterization
>
);
impl
TypeRscope
{
fn
replacement
(
&
self
)
->
ty
::
Region
{
if
self
.is_some
()
{
ty
::
re_bound
(
ty
::
br_self
)
}
else
{
ty
::
re_static
}
}
}
impl
RegionScope
for
TypeRscope
{
fn
anon_region
(
&
self
,
_
span
:
Span
)
->
Result
<
ty
::
Region
,
RegionError
>
{
result
::
Err
(
RegionError
{
msg
:
~
"anonymous lifetimes are not permitted here"
,
replacement
:
self
.replacement
()
})
}
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
!
(
"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
EmptyRscope
.named_region
(
span
,
id
)
.or_else
|
_
e
|
{
result
::
Err
(
RegionError
{
msg
:
~
"only 'self is allowed as part of a type declaration"
,
replacement
:
self
.replacement
()
})
}
}
}
pub
fn
bound_self_region
(
rp
:
Option
<
ty
::
region_variance
>
)
->
OptVec
<
ty
::
Region
>
{
match
rp
{
Some
(
_
)
=>
opt_vec
::
with
(
ty
::
re_bound
(
ty
::
br_self
)),
None
=>
opt_vec
::
Empty
impl
RegionScope
for
ExplicitRscope
{
fn
anon_regions
(
&
self
,
_
span
:
Span
,
_
count
:
uint
)
->
Option
<~
[
ty
::
Region
]
>
{
None
}
}
pub
struct
BindingRscope
{
base
:
@
RegionScope
,
anon_bindings
:
@
mut
uint
,
region_param_names
:
RegionParamNames
,
binder_id
:
ast
::
NodeId
,
anon_bindings
:
@
mut
uint
}
impl
Clone
for
BindingRscope
{
fn
clone
(
&
self
)
->
BindingRscope
{
impl
BindingRscope
{
pub
fn
new
(
binder_id
:
ast
::
NodeId
)
->
BindingRscope
{
BindingRscope
{
base
:
self
.base
,
anon_bindings
:
self
.anon_bindings
,
region_param_names
:
self
.region_param_names
.clone
(),
binder_id
:
binder_id
,
anon_bindings
:
@
mut
0
}
}
}
pub
fn
in_binding_rscope
<
RS
:
RegionScope
+
Clone
+
'static
>
(
this
:
&
RS
,
region_param_names
:
RegionParamNames
)
->
BindingRscope
{
let
base
=
@
(
*
this
)
.clone
();
let
base
=
base
as
@
RegionScope
;
BindingRscope
{
base
:
base
,
anon_bindings
:
@
mut
0
,
region_param_names
:
region_param_names
,
}
}
impl
RegionScope
for
BindingRscope
{
fn
anon_region
(
&
self
,
_
span
:
Span
)
->
Result
<
ty
::
Region
,
RegionError
>
{
fn
anon_regions
(
&
self
,
_
:
Span
,
count
:
uint
)
->
Option
<~
[
ty
::
Region
]
>
{
let
idx
=
*
self
.anon_bindings
;
*
self
.anon_bindings
+=
1
;
result
::
Ok
(
ty
::
re_bound
(
ty
::
br_anon
(
idx
)))
}
fn
self_region
(
&
self
,
span
:
Span
)
->
Result
<
ty
::
Region
,
RegionError
>
{
self
.base
.self_region
(
span
)
}
fn
named_region
(
&
self
,
span
:
Span
,
id
:
ast
::
Ident
)
->
Result
<
ty
::
Region
,
RegionError
>
{
do
self
.base
.named_region
(
span
,
id
)
.or_else
|
_
e
|
{
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
))
}
}
*
self
.anon_bindings
+=
count
;
Some
(
vec
::
from_fn
(
count
,
|
i
|
ty
::
re_fn_bound
(
self
.binder_id
,
ty
::
br_anon
(
idx
+
i
))))
}
}
pub
fn
bound_type_regions
(
defs
:
&
[
ty
::
RegionParameterDef
])
->
OptVec
<
ty
::
Region
>
{
assert
!
(
defs
.iter
()
.all
(|
def
|
def
.def_id.crate
==
ast
::
LOCAL_CRATE
));
defs
.iter
()
.enumerate
()
.map
(
|(
i
,
def
)|
ty
::
re_type_bound
(
def
.def_id.node
,
i
,
def
.ident
))
.collect
()
}
src/libsyntax/ast.rs
浏览文件 @
8e1de177
...
...
@@ -251,6 +251,20 @@ pub enum Def {
DefMethod
(
DefId
/* method */
,
Option
<
DefId
>
/* trait */
),
}
#[deriving(Clone,
Eq,
IterBytes,
Encodable,
Decodable,
ToStr)]
pub
enum
DefRegion
{
DefStaticRegion
,
DefTypeBoundRegion
(
/* index */
uint
,
/* lifetime decl */
NodeId
),
DefFnBoundRegion
(
/* binder_id */
NodeId
,
/* depth */
uint
,
/* lifetime decl */
NodeId
),
DefFreeRegion
(
/* block scope */
NodeId
,
/* lifetime decl */
NodeId
),
}
#[deriving(Clone,
Eq,
IterBytes,
Encodable,
Decodable,
ToStr)]
pub
struct
DefNamedRegion
{
node_id
:
NodeId
,
depth
:
uint
,
}
// The set of MetaItems that define the compilation environment of the crate,
// used to drive conditional compilation
pub
type
CrateConfig
=
~
[
@
MetaItem
];
...
...
src/libsyntax/visit.rs
浏览文件 @
8e1de177
...
...
@@ -90,7 +90,32 @@ fn visit_struct_def(&mut self, s:@struct_def, i:Ident, g:&Generics, n:NodeId, e:
walk_struct_def
(
self
,
s
,
i
,
g
,
n
,
e
)
}
fn
visit_struct_field
(
&
mut
self
,
s
:
@
struct_field
,
e
:
E
)
{
walk_struct_field
(
self
,
s
,
e
)
}
fn
visit_mac
(
&
mut
self
,
m
:
&
mac
,
e
:
E
)
{
walk_mac
(
self
,
m
,
e
);
}
fn
visit_opt_lifetime_ref
(
&
mut
self
,
_
span
:
Span
,
opt_lifetime
:
&
Option
<
Lifetime
>
,
env
:
E
)
{
/*!
* Visits an optional reference to a lifetime. The `span` is
* the span of some surrounding reference should opt_lifetime
* be None.
*/
match
*
opt_lifetime
{
Some
(
ref
l
)
=>
self
.visit_lifetime_ref
(
l
,
env
),
None
=>
()
}
}
fn
visit_lifetime_ref
(
&
mut
self
,
_
lifetime
:
&
Lifetime
,
_
e
:
E
)
{
/*! Visits a reference to a lifetime */
}
fn
visit_lifetime_decl
(
&
mut
self
,
_
lifetime
:
&
Lifetime
,
_
e
:
E
)
{
/*! Visits a declaration of a lifetime */
}
fn
visit_explicit_self
(
&
mut
self
,
es
:
&
explicit_self
,
e
:
E
)
{
walk_explicit_self
(
self
,
es
,
e
)
}
fn
visit_mac
(
&
mut
self
,
macro
:
&
mac
,
e
:
E
)
{
walk_mac
(
self
,
macro
,
e
)
}
}
pub
fn
walk_crate
<
E
:
Clone
,
V
:
Visitor
<
E
>>
(
visitor
:
&
mut
V
,
crate
:
&
Crate
,
env
:
E
)
{
...
...
@@ -119,6 +144,18 @@ pub fn walk_local<E:Clone, V:Visitor<E>>(visitor: &mut V, local: &Local, env: E)
}
}
fn
walk_explicit_self
<
E
:
Clone
,
V
:
Visitor
<
E
>>
(
visitor
:
&
mut
V
,
explicit_self
:
&
explicit_self
,
env
:
E
)
{
match
explicit_self
.node
{
sty_static
|
sty_value
(
_
)
|
sty_box
(
_
)
|
sty_uniq
(
_
)
=>
{
}
sty_region
(
ref
lifetime
,
_
)
=>
{
visitor
.visit_opt_lifetime_ref
(
explicit_self
.span
,
lifetime
,
env
)
}
}
}
fn
walk_trait_ref
<
E
:
Clone
,
V
:
Visitor
<
E
>>
(
visitor
:
&
mut
V
,
trait_ref
:
&
ast
::
trait_ref
,
env
:
E
)
{
...
...
@@ -221,8 +258,11 @@ pub fn skip_ty<E, V:Visitor<E>>(_: &mut V, _: &Ty, _: E) {
pub
fn
walk_ty
<
E
:
Clone
,
V
:
Visitor
<
E
>>
(
visitor
:
&
mut
V
,
typ
:
&
Ty
,
env
:
E
)
{
match
typ
.node
{
ty_box
(
ref
mutable_type
)
|
ty_uniq
(
ref
mutable_type
)
|
ty_vec
(
ref
mutable_type
)
|
ty_ptr
(
ref
mutable_type
)
|
ty_rptr
(
_
,
ref
mutable_type
)
=>
{
ty_vec
(
ref
mutable_type
)
|
ty_ptr
(
ref
mutable_type
)
=>
{
visitor
.visit_ty
(
mutable_type
.ty
,
env
)
}
ty_rptr
(
ref
lifetime
,
ref
mutable_type
)
=>
{
visitor
.visit_opt_lifetime_ref
(
typ
.span
,
lifetime
,
env
.clone
());
visitor
.visit_ty
(
mutable_type
.ty
,
env
)
}
ty_tup
(
ref
tuple_element_types
)
=>
{
...
...
@@ -238,12 +278,20 @@ pub fn walk_ty<E:Clone, V:Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
for
bounds
in
function_declaration
.bounds
.iter
()
{
walk_ty_param_bounds
(
visitor
,
bounds
,
env
.clone
())
}
visitor
.visit_opt_lifetime_ref
(
typ
.span
,
&
function_declaration
.region
,
env
.clone
());
walk_lifetime_decls
(
visitor
,
&
function_declaration
.lifetimes
,
env
.clone
());
}
ty_bare_fn
(
ref
function_declaration
)
=>
{
for
argument
in
function_declaration
.decl.inputs
.iter
()
{
visitor
.visit_ty
(
&
argument
.ty
,
env
.clone
())
}
visitor
.visit_ty
(
&
function_declaration
.decl.output
,
env
.clone
())
visitor
.visit_ty
(
&
function_declaration
.decl.output
,
env
.clone
());
walk_lifetime_decls
(
visitor
,
&
function_declaration
.lifetimes
,
env
.clone
());
}
ty_path
(
ref
path
,
ref
bounds
,
_
)
=>
{
walk_path
(
visitor
,
path
,
env
.clone
());
...
...
@@ -262,10 +310,21 @@ pub fn walk_ty<E:Clone, V:Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
}
}
fn
walk_lifetime_decls
<
E
:
Clone
,
V
:
Visitor
<
E
>>
(
visitor
:
&
mut
V
,
lifetimes
:
&
OptVec
<
Lifetime
>
,
env
:
E
)
{
for
l
in
lifetimes
.iter
()
{
visitor
.visit_lifetime_decl
(
l
,
env
.clone
());
}
}
pub
fn
walk_path
<
E
:
Clone
,
V
:
Visitor
<
E
>>
(
visitor
:
&
mut
V
,
path
:
&
Path
,
env
:
E
)
{
for
segment
in
path
.segments
.iter
()
{
for
typ
in
segment
.types
.iter
()
{
visitor
.visit_ty
(
typ
,
env
.clone
())
visitor
.visit_ty
(
typ
,
env
.clone
());
}
for
lifetime
in
segment
.lifetimes
.iter
()
{
visitor
.visit_lifetime_ref
(
lifetime
,
env
.clone
());
}
}
}
...
...
@@ -354,6 +413,7 @@ pub fn walk_generics<E:Clone, V:Visitor<E>>(visitor: &mut V,
for
type_parameter
in
generics
.ty_params
.iter
()
{
walk_ty_param_bounds
(
visitor
,
&
type_parameter
.bounds
,
env
.clone
())
}
walk_lifetime_decls
(
visitor
,
&
generics
.lifetimes
,
env
);
}
pub
fn
walk_fn_decl
<
E
:
Clone
,
V
:
Visitor
<
E
>>
(
visitor
:
&
mut
V
,
...
...
@@ -385,18 +445,31 @@ pub fn walk_fn<E:Clone, V:Visitor<E>>(visitor: &mut V,
function_kind
:
&
fn_kind
,
function_declaration
:
&
fn_decl
,
function_body
:
&
Block
,
_
:
Span
,
_
span
:
Span
,
_
:
NodeId
,
env
:
E
)
{
walk_fn_decl
(
visitor
,
function_declaration
,
env
.clone
());
let
generics
=
generics_of_fn
(
function_kind
);
visitor
.visit_generics
(
&
generics
,
env
.clone
());
match
*
function_kind
{
fk_item_fn
(
_
,
generics
,
_
,
_
)
=>
{
visitor
.visit_generics
(
generics
,
env
.clone
());
}
fk_method
(
_
,
generics
,
method
)
=>
{
visitor
.visit_generics
(
generics
,
env
.clone
());
visitor
.visit_explicit_self
(
&
method
.explicit_self
,
env
.clone
());
}
fk_anon
(
*
)
|
fk_fn_block
(
*
)
=>
{
}
}
visitor
.visit_block
(
function_body
,
env
)
}
pub
fn
walk_ty_method
<
E
:
Clone
,
V
:
Visitor
<
E
>>
(
visitor
:
&
mut
V
,
method_type
:
&
TypeMethod
,
env
:
E
)
{
visitor
.visit_explicit_self
(
&
method_type
.explicit_self
,
env
.clone
());
for
argument_type
in
method_type
.decl.inputs
.iter
()
{
visitor
.visit_ty
(
&
argument_type
.ty
,
env
.clone
())
}
...
...
src/test/compile-fail/regions-name-duplicated.rs
0 → 100644
浏览文件 @
8e1de177
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct
Foo
<
'a
,
'a
>
{
//~ ERROR lifetime name `'a` declared twice
x
:
&
'a
int
}
fn
main
()
{}
src/test/compile-fail/regions-name-static.rs
0 → 100644
浏览文件 @
8e1de177
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct
Foo
<
'static
>
{
//~ ERROR illegal lifetime parameter name: `static`
x
:
&
'static
int
}
fn
main
()
{}
src/test/compile-fail/regions-name-undeclared.rs
0 → 100644
浏览文件 @
8e1de177
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Check that lifetime resolver enforces the lifetime name scoping
// rules correctly in various scenarios.
struct
Foo
<
'a
>
{
x
:
&
'a
int
}
impl
<
'a
>
Foo
<
'a
>
{
// &'a is inherited:
fn
m1
(
&
self
,
arg
:
&
'a
int
)
{
}
fn
m2
(
&
'a
self
)
{
}
fn
m3
(
&
self
,
arg
:
Foo
<
'a
>
)
{
}
// &'b is not:
fn
m4
(
&
self
,
arg
:
&
'b
int
)
{
}
//~ ERROR undeclared lifetime
fn
m5
(
&
'b
self
)
{
}
//~ ERROR undeclared lifetime
fn
m6
(
&
self
,
arg
:
Foo
<
'b
>
)
{
}
//~ ERROR undeclared lifetime
}
fn
bar
<
'a
>
(
x
:
&
'a
int
)
{
// &'a is visible to code:
let
y
:
&
'a
int
=
x
;
// &'a is not visible to *items*:
type
X
=
Option
<&
'a
int
>
;
//~ ERROR undeclared lifetime
enum
E
{
E1
(
&
'a
int
)
//~ ERROR undeclared lifetime
}
struct
S
{
f
:
&
'a
int
//~ ERROR undeclared lifetime
}
fn
f
(
a
:
&
'a
int
)
{
}
//~ ERROR undeclared lifetime
// &'a CAN be declared on functions and used then:
fn
g
<
'a
>
(
a
:
&
'a
int
)
{
}
// OK
fn
h
(
a
:
&
fn
<
'a
>
(
&
'a
int
))
{
}
// OK
}
// Test nesting of lifetimes in fn type declarations
fn
fn_types
(
a
:
&
'a
int
,
//~ ERROR undeclared lifetime
b
:
&
fn
<
'a
>
(
a
:
&
'a
int
,
b
:
&
'b
int
,
//~ ERROR undeclared lifetime
c
:
&
fn
<
'b
>
(
a
:
&
'a
int
,
b
:
&
'b
int
),
d
:
&
'b
int
),
//~ ERROR undeclared lifetime
c
:
&
'a
int
)
//~ ERROR undeclared lifetime
{
}
pub
fn
main
()
{}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录