Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
7512284a
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,发现更多精彩内容 >>
提交
7512284a
编写于
5月 15, 2012
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
further modularization of typeck, add comments
上级
8cc596ce
变更
9
展开全部
隐藏空白更改
内联
并排
Showing
9 changed file
with
3486 addition
and
3398 deletion
+3486
-3398
src/rustc/middle/typeck.rs
src/rustc/middle/typeck.rs
+62
-3111
src/rustc/middle/typeck/astconv.rs
src/rustc/middle/typeck/astconv.rs
+48
-256
src/rustc/middle/typeck/check.rs
src/rustc/middle/typeck/check.rs
+2977
-0
src/rustc/middle/typeck/collect.rs
src/rustc/middle/typeck/collect.rs
+390
-31
src/rustc/middle/typeck/demand.rs
src/rustc/middle/typeck/demand.rs
+2
-0
src/rustc/middle/typeck/regionck.rs
src/rustc/middle/typeck/regionck.rs
+1
-0
src/rustc/middle/typeck/vtable.rs
src/rustc/middle/typeck/vtable.rs
+2
-0
src/rustc/middle/typeck/writeback.rs
src/rustc/middle/typeck/writeback.rs
+3
-0
src/rustc/rustc.rc
src/rustc/rustc.rc
+1
-0
未找到文件。
src/rustc/middle/typeck.rs
浏览文件 @
7512284a
此差异已折叠。
点击以展开。
src/rustc/middle/typeck/astconv.rs
浏览文件 @
7512284a
#[doc
=
"
Conversion from AST representation of types to the ty.rs representation.
The main routine here is `ast_ty_to_ty()`: each use is parameterized
by an instance of `ast_conv` and a `region_scope`.
The `ast_conv` interface is the conversion context. It has two
implementations, one for the crate context and one for the function
context. The main purpose is to provide the `get_item_ty()` hook
which looks up the type of an item by its def-id. This can be done in
two ways: in the initial phase, when a crate context is provided, this
will potentially trigger a call to `ty_of_item()`. Later, when a
function context is used, this will simply be a lookup.
Conversion from AST representation of types to the ty.rs
representation. The main routine here is `ast_ty_to_ty()`: each use
is parameterized by an instance of `ast_conv` and a `region_scope`.
The parameterization of `ast_ty_to_ty()` is because it behaves
somewhat differently during the collect and check phases, particularly
with respect to looking up the types of top-level items. In the
collect phase, the crate context is used as the `ast_conv` instance;
in this phase, the `get_item_ty()` function triggers a recursive call
to `ty_of_item()` (note that `ast_ty_to_ty()` will detect recursive
types and report an error). In the check phase, when the @fn_ctxt is
used as the `ast_conv`, `get_item_ty()` just looks up the item type in
`tcx.tcache`.
The `region_scope` interface controls how region references are
handled. It has two methods which are used to resolve anonymous
...
...
@@ -21,8 +22,30 @@
region, or `type_rscope`, which permits the self region if the type in
question is parameterized by a region.
Unlike the `ast_conv` iface, the region scope can change as we descend
the type. This is to accommodate the fact that (a) fn types are binding
scopes and (b) the default region may change. To understand case (a),
consider something like:
type foo = { x: &a.int, y: fn(&a.int) }
The type of `x` is an error because there is no region `a` in scope.
In the type of `y`, however, region `a` is considered a bound region
as it does not already appear in scope.
Case (b) says that if you have a type:
type foo/& = ...;
type bar = fn(&foo, &a.foo)
The fully expanded version of type bar is:
type bar = fn(&foo/&, &a.foo/&a)
Note that the self region for the `foo` defaulted to `&` in the first
case but `&a` in the second. Basically, defaults that appear inside
an rptr (`&r.T`) use the region `r` that appears in the rptr.
"
]
;
import
check
::
fn_ctxt
;
iface
ast_conv
{
fn
tcx
()
->
ty
::
ctxt
;
fn
ccx
()
->
@
crate_ctxt
;
...
...
@@ -32,48 +55,6 @@
fn
ty_infer
(
span
:
span
)
->
ty
::
t
;
}
impl
of
ast_conv
for
@
crate_ctxt
{
fn
tcx
()
->
ty
::
ctxt
{
self
.tcx
}
fn
ccx
()
->
@
crate_ctxt
{
self
}
fn
get_item_ty
(
id
:
ast
::
def_id
)
->
ty
::
ty_param_bounds_and_ty
{
if
id
.crate
!=
ast
::
local_crate
{
csearch
::
get_type
(
self
.tcx
,
id
)
}
else
{
alt
self
.tcx.items
.find
(
id
.node
)
{
some
(
ast_map
::
node_item
(
item
,
_
))
{
ty_of_item
(
self
,
item
)
}
some
(
ast_map
::
node_native_item
(
native_item
,
_
,
_
))
{
ty_of_native_item
(
self
,
native_item
)
}
x
{
self
.tcx.sess
.bug
(
#
fmt
[
"unexpected sort of item
\
in get_item_ty(): %?"
,
x
]);
}
}
}
}
fn
ty_infer
(
span
:
span
)
->
ty
::
t
{
self
.tcx.sess
.span_bug
(
span
,
"found `ty_infer` in unexpected place"
);
}
}
impl
of
ast_conv
for
@
fn_ctxt
{
fn
tcx
()
->
ty
::
ctxt
{
self
.ccx.tcx
}
fn
ccx
()
->
@
crate_ctxt
{
self
.ccx
}
fn
get_item_ty
(
id
:
ast
::
def_id
)
->
ty
::
ty_param_bounds_and_ty
{
ty
::
lookup_item_type
(
self
.tcx
(),
id
)
}
fn
ty_infer
(
_
span
:
span
)
->
ty
::
t
{
self
.next_ty_var
()
}
}
iface
region_scope
{
fn
anon_region
()
->
result
<
ty
::
region
,
str
>
;
fn
named_region
(
id
:
str
)
->
result
<
ty
::
region
,
str
>
;
...
...
@@ -112,23 +93,6 @@ fn named_region(id: str) -> result<ty::region, str> {
}
}
impl
of
region_scope
for
@
fn_ctxt
{
fn
anon_region
()
->
result
<
ty
::
region
,
str
>
{
result
::
ok
(
self
.next_region_var
())
}
fn
named_region
(
id
:
str
)
->
result
<
ty
::
region
,
str
>
{
empty_rscope
.named_region
(
id
)
.chain_err
{
|
_
e
|
alt
self
.in_scope_regions
.find
(
ty
::
br_named
(
id
))
{
some
(
r
)
{
result
::
ok
(
r
)
}
none
if
id
==
"blk"
{
self
.block_region
()
}
none
{
result
::
err
(
#
fmt
[
"named region `%s` not in scope here"
,
id
])
}
}
}
}
}
enum
anon_rscope
=
{
anon
:
ty
::
region
,
base
:
region_scope
};
fn
in_anon_rscope
<
RS
:
region_scope
copy
>
(
self
:
RS
,
r
:
ty
::
region
)
->
@
anon_rscope
{
...
...
@@ -159,6 +123,19 @@ fn named_region(id: str) -> result<ty::region, str> {
}
}
fn
get_region_reporting_err
(
tcx
:
ty
::
ctxt
,
span
:
span
,
res
:
result
<
ty
::
region
,
str
>
)
->
ty
::
region
{
alt
res
{
result
::
ok
(
r
)
{
r
}
result
::
err
(
e
)
{
tcx
.sess
.span_err
(
span
,
e
);
ty
::
re_static
}
}
}
fn
ast_region_to_region
<
AC
:
ast_conv
,
RS
:
region_scope
>
(
self
:
AC
,
rscope
:
RS
,
span
:
span
,
a_r
:
@
ast
::
region
)
->
ty
::
region
{
...
...
@@ -233,36 +210,6 @@ fn ast_path_to_ty<AC: ast_conv, RS: region_scope copy>(
ret
{
substs
:
substs
,
ty
:
ty
};
}
/*
Instantiates the path for the given iface reference, assuming that
it's bound to a valid iface type. Returns the def_id for the defining
iface. Fails if the type is a type other than an iface type.
*/
fn
instantiate_iface_ref
(
ccx
:
@
crate_ctxt
,
t
:
@
ast
::
iface_ref
,
rp
:
ast
::
region_param
)
->
(
ast
::
def_id
,
ty_param_substs_and_ty
)
{
let
sp
=
t
.path.span
,
err
=
"can only implement interface types"
,
sess
=
ccx
.tcx.sess
;
let
rscope
=
type_rscope
(
rp
);
alt
lookup_def_tcx
(
ccx
.tcx
,
t
.path.span
,
t
.id
)
{
ast
::
def_ty
(
t_id
)
{
let
tpt
=
ast_path_to_ty
(
ccx
,
rscope
,
t_id
,
t
.path
,
t
.id
);
alt
ty
::
get
(
tpt
.ty
)
.struct
{
ty
::
ty_iface
(
*
)
{
(
t_id
,
tpt
)
}
_
{
sess
.span_fatal
(
sp
,
err
);
}
}
}
_
{
sess
.span_fatal
(
sp
,
err
);
}
}
}
const
NO_REGIONS
:
uint
=
1u
;
const
NO_TPS
:
uint
=
2u
;
...
...
@@ -474,103 +421,6 @@ fn check_path_args(tcx: ty::ctxt,
ret
typ
;
}
fn
ty_of_item
(
ccx
:
@
crate_ctxt
,
it
:
@
ast
::
item
)
->
ty
::
ty_param_bounds_and_ty
{
let
def_id
=
local_def
(
it
.id
);
let
tcx
=
ccx
.tcx
;
alt
tcx
.tcache
.find
(
def_id
)
{
some
(
tpt
)
{
ret
tpt
;
}
_
{}
}
alt
it
.node
{
ast
::
item_const
(
t
,
_
)
{
let
typ
=
ccx
.to_ty
(
empty_rscope
,
t
);
let
tpt
=
no_params
(
typ
);
tcx
.tcache
.insert
(
local_def
(
it
.id
),
tpt
);
ret
tpt
;
}
ast
::
item_fn
(
decl
,
tps
,
_
)
{
let
bounds
=
ty_param_bounds
(
ccx
,
tps
);
let
tofd
=
ty_of_fn_decl
(
ccx
,
empty_rscope
,
ast
::
proto_bare
,
decl
,
none
);
let
tpt
=
{
bounds
:
bounds
,
rp
:
ast
::
rp_none
,
// functions do not have a self
ty
:
ty
::
mk_fn
(
ccx
.tcx
,
tofd
)};
ccx
.tcx.tcache
.insert
(
local_def
(
it
.id
),
tpt
);
ret
tpt
;
}
ast
::
item_ty
(
t
,
tps
,
rp
)
{
alt
tcx
.tcache
.find
(
local_def
(
it
.id
))
{
some
(
tpt
)
{
ret
tpt
;
}
none
{
}
}
let
tpt
=
{
let
ty
=
{
let
t0
=
ccx
.to_ty
(
type_rscope
(
rp
),
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
// reconstruct the value of X.
if
!
vec
::
is_empty
(
tps
)
{
t0
}
else
{
ty
::
mk_with_id
(
tcx
,
t0
,
def_id
)
}
};
{
bounds
:
ty_param_bounds
(
ccx
,
tps
),
rp
:
rp
,
ty
:
ty
}
};
check_bounds_are_used
(
ccx
,
t
.span
,
tps
,
rp
,
tpt
.ty
);
tcx
.tcache
.insert
(
local_def
(
it
.id
),
tpt
);
ret
tpt
;
}
ast
::
item_res
(
decl
,
tps
,
_
,
_
,
_
,
rp
)
{
let
{
bounds
,
substs
}
=
mk_substs
(
ccx
,
tps
,
rp
);
let
t_arg
=
ty_of_arg
(
ccx
,
type_rscope
(
rp
),
decl
.inputs
[
0
],
none
);
let
t
=
ty
::
mk_res
(
tcx
,
local_def
(
it
.id
),
t_arg
.ty
,
substs
);
let
t_res
=
{
bounds
:
bounds
,
rp
:
rp
,
ty
:
t
};
tcx
.tcache
.insert
(
local_def
(
it
.id
),
t_res
);
ret
t_res
;
}
ast
::
item_enum
(
_
,
tps
,
rp
)
{
// Create a new generic polytype.
let
{
bounds
,
substs
}
=
mk_substs
(
ccx
,
tps
,
rp
);
let
t
=
ty
::
mk_enum
(
tcx
,
local_def
(
it
.id
),
substs
);
let
tpt
=
{
bounds
:
bounds
,
rp
:
rp
,
ty
:
t
};
tcx
.tcache
.insert
(
local_def
(
it
.id
),
tpt
);
ret
tpt
;
}
ast
::
item_iface
(
tps
,
rp
,
ms
)
{
let
{
bounds
,
substs
}
=
mk_substs
(
ccx
,
tps
,
rp
);
let
t
=
ty
::
mk_iface
(
tcx
,
local_def
(
it
.id
),
substs
);
let
tpt
=
{
bounds
:
bounds
,
rp
:
rp
,
ty
:
t
};
tcx
.tcache
.insert
(
local_def
(
it
.id
),
tpt
);
ret
tpt
;
}
ast
::
item_class
(
tps
,
_
,
_
,
_
,
_
,
rp
)
{
let
{
bounds
,
substs
}
=
mk_substs
(
ccx
,
tps
,
rp
);
let
t
=
ty
::
mk_class
(
tcx
,
local_def
(
it
.id
),
substs
);
let
tpt
=
{
bounds
:
bounds
,
rp
:
rp
,
ty
:
t
};
tcx
.tcache
.insert
(
local_def
(
it
.id
),
tpt
);
ret
tpt
;
}
ast
::
item_impl
(
*
)
|
ast
::
item_mod
(
_
)
|
ast
::
item_native_mod
(
_
)
{
fail
;
}
}
}
fn
ty_of_native_item
(
ccx
:
@
crate_ctxt
,
it
:
@
ast
::
native_item
)
->
ty
::
ty_param_bounds_and_ty
{
alt
it
.node
{
ast
::
native_item_fn
(
fn_decl
,
params
)
{
ret
ty_of_native_fn_decl
(
ccx
,
fn_decl
,
params
,
local_def
(
it
.id
));
}
}
}
fn
ty_of_arg
<
AC
:
ast_conv
,
RS
:
region_scope
copy
>
(
self
:
AC
,
rscope
:
RS
,
a
:
ast
::
arg
,
expected_ty
:
option
<
ty
::
arg
>
)
->
ty
::
arg
{
...
...
@@ -651,61 +501,3 @@ fn ty_of_fn_decl<AC: ast_conv, RS: region_scope copy>(
}
fn
ty_param_bounds
(
ccx
:
@
crate_ctxt
,
params
:
[
ast
::
ty_param
])
->
@
[
ty
::
param_bounds
]
{
fn
compute_bounds
(
ccx
:
@
crate_ctxt
,
param
:
ast
::
ty_param
)
->
ty
::
param_bounds
{
@
vec
::
flat_map
(
*
param
.bounds
)
{
|
b
|
alt
b
{
ast
::
bound_send
{
[
ty
::
bound_send
]
}
ast
::
bound_copy
{
[
ty
::
bound_copy
]
}
ast
::
bound_iface
(
t
)
{
let
ity
=
ast_ty_to_ty
(
ccx
,
empty_rscope
,
t
);
alt
ty
::
get
(
ity
)
.struct
{
ty
::
ty_iface
(
*
)
{
[
ty
::
bound_iface
(
ity
)]
}
_
{
ccx
.tcx.sess
.span_err
(
t
.span
,
"type parameter bounds must be
\
interface types"
);
[]
}
}
}
}
}
}
@
params
.map
{
|
param
|
alt
ccx
.tcx.ty_param_bounds
.find
(
param
.id
)
{
some
(
bs
)
{
bs
}
none
{
let
bounds
=
compute_bounds
(
ccx
,
param
);
ccx
.tcx.ty_param_bounds
.insert
(
param
.id
,
bounds
);
bounds
}
}
}
}
fn
ty_of_native_fn_decl
(
ccx
:
@
crate_ctxt
,
decl
:
ast
::
fn_decl
,
ty_params
:
[
ast
::
ty_param
],
def_id
:
ast
::
def_id
)
->
ty
::
ty_param_bounds_and_ty
{
let
bounds
=
ty_param_bounds
(
ccx
,
ty_params
);
let
rb
=
in_binding_rscope
(
empty_rscope
);
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
);
let
t_fn
=
ty
::
mk_fn
(
ccx
.tcx
,
{
proto
:
ast
::
proto_bare
,
inputs
:
input_tys
,
output
:
output_ty
,
ret_style
:
ast
::
return_val
,
constraints
:
[]});
let
tpt
=
{
bounds
:
bounds
,
rp
:
ast
::
rp_none
,
ty
:
t_fn
};
ccx
.tcx.tcache
.insert
(
def_id
,
tpt
);
ret
tpt
;
}
src/rustc/middle/typeck/check.rs
0 → 100644
浏览文件 @
7512284a
此差异已折叠。
点击以展开。
src/rustc/middle/typeck/collect.rs
浏览文件 @
7512284a
import
astconv
::{
type_rscope
,
instantiate_iface_ref
,
ty_of_item
,
empty_rscope
,
ty_of_native_item
,
ast_conv
};
// Item collection - a pair of bootstrap passes:
//
// (1) Collect the IDs of all type items (typedefs) and store them in a table.
//
// (2) Translate the AST fragments that describe types to determine a type for
// each item. When we encounter a named type, we consult the table built
// in pass 1 to find its item, and recursively translate it.
//
// We then annotate the AST with the resulting types and return the annotated
// AST, along with a table mapping item IDs to their types.
/*
# Collect phase
The collect phase of type check has the job of visiting all items,
determining their type, and writing that type into the `tcx.tcache`
table. Despite its name, this table does not really operate as a
*cache*, at least not for the types of items defined within the
current crate: we assume that after the collect phase, the types of
all local items will be present in the table.
Unlike most of the types that are present in Rust, the types computed
for each item are in fact polytypes. In "layman's terms", this means
that they are generic types that may have type parameters (more
mathematically phrased, they are universally quantified over a set of
type parameters). Polytypes are represented by an instance of
`ty::ty_param_bounds_and_ty`. This combines the core type along with
a list of the bounds for each parameter. Type parameters themselves
are represented as `ty_param()` instances.
*/
import
astconv
::{
type_rscope
,
empty_rscope
,
in_binding_rscope
,
ast_conv
,
ty_of_fn_decl
,
ty_of_arg
,
region_scope
,
ast_ty_to_ty
};
fn
collect_item_types
(
ccx
:
@
crate_ctxt
,
crate
:
@
ast
::
crate
)
{
visit
::
visit_crate
(
*
crate
,
(),
visit
::
mk_simple_visitor
(
@
{
visit_item
:
bind
convert
(
ccx
,
_
),
visit_native_item
:
bind
convert_native
(
ccx
,
_
)
with
*
visit
::
default_simple_visitor
()
}));
}
impl
methods
for
@
crate_ctxt
{
fn
to_ty
<
RS
:
region_scope
copy
>
(
rs
:
RS
,
ast_ty
:
@
ast
::
ty
)
->
ty
::
t
{
ast_ty_to_ty
(
self
,
rs
,
ast_ty
)
}
}
impl
of
ast_conv
for
@
crate_ctxt
{
fn
tcx
()
->
ty
::
ctxt
{
self
.tcx
}
fn
ccx
()
->
@
crate_ctxt
{
self
}
fn
get_item_ty
(
id
:
ast
::
def_id
)
->
ty
::
ty_param_bounds_and_ty
{
if
id
.crate
!=
ast
::
local_crate
{
csearch
::
get_type
(
self
.tcx
,
id
)
}
else
{
alt
self
.tcx.items
.find
(
id
.node
)
{
some
(
ast_map
::
node_item
(
item
,
_
))
{
ty_of_item
(
self
,
item
)
}
some
(
ast_map
::
node_native_item
(
native_item
,
_
,
_
))
{
ty_of_native_item
(
self
,
native_item
)
}
x
{
self
.tcx.sess
.bug
(
#
fmt
[
"unexpected sort of item
\
in get_item_ty(): %?"
,
x
]);
}
}
}
}
fn
ty_infer
(
span
:
span
)
->
ty
::
t
{
self
.tcx.sess
.span_bug
(
span
,
"found `ty_infer` in unexpected place"
);
}
}
fn
get_enum_variant_types
(
ccx
:
@
crate_ctxt
,
enum_ty
:
ty
::
t
,
variants
:
[
ast
::
variant
],
...
...
@@ -36,7 +91,7 @@ fn get_enum_variant_types(ccx: @crate_ctxt,
ret_style
:
ast
::
return_val
,
constraints
:
[]})
};
let
tpt
=
{
bounds
:
astconv
::
ty_param_bounds
(
ccx
,
ty_params
),
let
tpt
=
{
bounds
:
ty_param_bounds
(
ccx
,
ty_params
),
rp
:
rp
,
ty
:
result_ty
};
tcx
.tcache
.insert
(
local_def
(
variant
.node.id
),
tpt
);
...
...
@@ -68,6 +123,51 @@ fn store_methods<T>(ccx: @crate_ctxt, id: ast::node_id,
}
}
fn
compare_impl_method
(
tcx
:
ty
::
ctxt
,
sp
:
span
,
impl_m
:
ty
::
method
,
impl_tps
:
uint
,
if_m
:
ty
::
method
,
substs
:
ty
::
substs
,
self_ty
:
ty
::
t
)
->
ty
::
t
{
if
impl_m
.tps
!=
if_m
.tps
{
tcx
.sess
.span_err
(
sp
,
"method `"
+
if_m
.ident
+
"` has an incompatible set of type parameters"
);
ty
::
mk_fn
(
tcx
,
impl_m
.fty
)
}
else
if
vec
::
len
(
impl_m
.fty.inputs
)
!=
vec
::
len
(
if_m
.fty.inputs
)
{
tcx
.sess
.span_err
(
sp
,
#
fmt
[
"method `%s` has %u parameters
\
but the iface has %u"
,
if_m
.ident
,
vec
::
len
(
impl_m
.fty.inputs
),
vec
::
len
(
if_m
.fty.inputs
)]);
ty
::
mk_fn
(
tcx
,
impl_m
.fty
)
}
else
{
let
auto_modes
=
vec
::
map2
(
impl_m
.fty.inputs
,
if_m
.fty.inputs
,
{|
i
,
f
|
alt
ty
::
get
(
f
.ty
)
.struct
{
ty
::
ty_param
(
*
)
|
ty
::
ty_self
if
alt
i
.mode
{
ast
::
infer
(
_
)
{
true
}
_
{
false
}
}
{
{
mode
:
ast
::
expl
(
ast
::
by_ref
)
with
i
}
}
_
{
i
}
}
});
let
impl_fty
=
ty
::
mk_fn
(
tcx
,
{
inputs
:
auto_modes
with
impl_m
.fty
});
// Add dummy substs for the parameters of the impl method
let
substs
=
{
self_r
:
substs
.self_r
,
self_ty
:
some
(
self_ty
),
tps
:
substs
.tps
+
vec
::
from_fn
(
vec
::
len
(
*
if_m
.tps
),
{|
i
|
ty
::
mk_param
(
tcx
,
i
+
impl_tps
,
{
crate
:
0
,
node
:
0
})
})
};
let
mut
if_fty
=
ty
::
mk_fn
(
tcx
,
if_m
.fty
);
if_fty
=
ty
::
subst
(
tcx
,
substs
,
if_fty
);
require_same_types
(
tcx
,
sp
,
impl_fty
,
if_fty
,
{||
"method `"
+
if_m
.ident
+
"` has an incompatible type"
});
ret
impl_fty
;
}
}
fn
check_methods_against_iface
(
ccx
:
@
crate_ctxt
,
tps
:
[
ast
::
ty_param
],
rp
:
ast
::
region_param
,
...
...
@@ -76,7 +176,7 @@ fn check_methods_against_iface(ccx: @crate_ctxt,
ms
:
[
@
ast
::
method
])
{
let
tcx
=
ccx
.tcx
;
let
i_bounds
=
astconv
::
ty_param_bounds
(
ccx
,
tps
);
let
i_bounds
=
ty_param_bounds
(
ccx
,
tps
);
let
my_methods
=
convert_methods
(
ccx
,
ms
,
rp
,
i_bounds
,
selfty
);
let
(
did
,
tpt
)
=
instantiate_iface_ref
(
ccx
,
a_ifacety
,
rp
);
if
did
.crate
==
ast
::
local_crate
{
...
...
@@ -138,7 +238,7 @@ fn convert_methods(ccx: @crate_ctxt,
let
tcx
=
ccx
.tcx
;
vec
::
map
(
ms
)
{
|
m
|
write_ty_to_tcx
(
tcx
,
m
.self_id
,
self_ty
);
let
bounds
=
astconv
::
ty_param_bounds
(
ccx
,
m
.tps
);
let
bounds
=
ty_param_bounds
(
ccx
,
m
.tps
);
let
mty
=
ty_of_method
(
ccx
,
m
,
rp
);
let
fty
=
ty
::
mk_fn
(
tcx
,
mty
.fty
);
tcx
.tcache
.insert
(
...
...
@@ -169,7 +269,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
ty_params
,
rp
);
}
ast
::
item_impl
(
tps
,
rp
,
ifce
,
selfty
,
ms
)
{
let
i_bounds
=
astconv
::
ty_param_bounds
(
ccx
,
tps
);
let
i_bounds
=
ty_param_bounds
(
ccx
,
tps
);
let
selfty
=
ccx
.to_ty
(
type_rscope
(
rp
),
selfty
);
write_ty_to_tcx
(
tcx
,
it
.id
,
selfty
);
tcx
.tcache
.insert
(
local_def
(
it
.id
),
...
...
@@ -194,7 +294,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
ast
::
item_res
(
decl
,
tps
,
_
,
dtor_id
,
ctor_id
,
rp
)
{
let
{
bounds
,
substs
}
=
mk_substs
(
ccx
,
tps
,
rp
);
let
def_id
=
local_def
(
it
.id
);
let
t_arg
=
astconv
::
ty_of_arg
(
ccx
,
type_rscope
(
rp
),
let
t_arg
=
ty_of_arg
(
ccx
,
type_rscope
(
rp
),
decl
.inputs
[
0
],
none
);
let
t_res
=
ty
::
mk_res
(
tcx
,
def_id
,
t_arg
.ty
,
substs
);
...
...
@@ -237,7 +337,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
let
t_ctor
=
ty
::
mk_fn
(
tcx
,
astconv
::
ty_of_fn_decl
(
ccx
,
ty_of_fn_decl
(
ccx
,
empty_rscope
,
ast
::
proto_any
,
ctor
.node.dec
,
...
...
@@ -253,7 +353,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
tcx
,
// not sure about empty_rscope
// FIXME
astconv
::
ty_of_fn_decl
(
ccx
,
ty_of_fn_decl
(
ccx
,
empty_rscope
,
ast
::
proto_any
,
ast_util
::
dtor_dec
(),
...
...
@@ -317,20 +417,13 @@ fn convert_native(ccx: @crate_ctxt, i: @ast::native_item) {
}
}
}
fn
collect_item_types
(
ccx
:
@
crate_ctxt
,
crate
:
@
ast
::
crate
)
{
visit
::
visit_crate
(
*
crate
,
(),
visit
::
mk_simple_visitor
(
@
{
visit_item
:
bind
convert
(
ccx
,
_
),
visit_native_item
:
bind
convert_native
(
ccx
,
_
)
with
*
visit
::
default_simple_visitor
()
}));
}
fn
ty_of_method
(
ccx
:
@
crate_ctxt
,
m
:
@
ast
::
method
,
rp
:
ast
::
region_param
)
->
ty
::
method
{
{
ident
:
m
.ident
,
tps
:
astconv
::
ty_param_bounds
(
ccx
,
m
.tps
),
fty
:
astconv
::
ty_of_fn_decl
(
ccx
,
type_rscope
(
rp
),
ast
::
proto_bare
,
tps
:
ty_param_bounds
(
ccx
,
m
.tps
),
fty
:
ty_of_fn_decl
(
ccx
,
type_rscope
(
rp
),
ast
::
proto_bare
,
m
.decl
,
none
),
purity
:
m
.decl.purity
,
vis
:
m
.vis
}
...
...
@@ -340,9 +433,275 @@ fn ty_of_ty_method(self: @crate_ctxt,
m
:
ast
::
ty_method
,
rp
:
ast
::
region_param
)
->
ty
::
method
{
{
ident
:
m
.ident
,
tps
:
astconv
::
ty_param_bounds
(
self
,
m
.tps
),
fty
:
astconv
::
ty_of_fn_decl
(
self
,
type_rscope
(
rp
),
ast
::
proto_bare
,
tps
:
ty_param_bounds
(
self
,
m
.tps
),
fty
:
ty_of_fn_decl
(
self
,
type_rscope
(
rp
),
ast
::
proto_bare
,
m
.decl
,
none
),
// assume public, because this is only invoked on iface methods
purity
:
m
.decl.purity
,
vis
:
ast
::
public
}
}
fn
check_intrinsic_type
(
ccx
:
@
crate_ctxt
,
it
:
@
ast
::
native_item
)
{
fn
param
(
ccx
:
@
crate_ctxt
,
n
:
uint
)
->
ty
::
t
{
ty
::
mk_param
(
ccx
.tcx
,
n
,
local_def
(
0
))
}
fn
arg
(
m
:
ast
::
rmode
,
ty
:
ty
::
t
)
->
ty
::
arg
{
{
mode
:
ast
::
expl
(
m
),
ty
:
ty
}
}
let
tcx
=
ccx
.tcx
;
let
(
n_tps
,
inputs
,
output
)
=
alt
it
.ident
{
"size_of"
|
"pref_align_of"
|
"min_align_of"
{
(
1u
,
[],
ty
::
mk_uint
(
ccx
.tcx
))
}
"get_tydesc"
{
(
1u
,
[],
ty
::
mk_nil_ptr
(
tcx
))
}
"init"
{
(
1u
,
[],
param
(
ccx
,
0u
))
}
"forget"
{
(
1u
,
[
arg
(
ast
::
by_move
,
param
(
ccx
,
0u
))],
ty
::
mk_nil
(
tcx
))
}
"reinterpret_cast"
{
(
2u
,
[
arg
(
ast
::
by_ref
,
param
(
ccx
,
0u
))],
param
(
ccx
,
1u
))
}
"addr_of"
{
(
1u
,
[
arg
(
ast
::
by_ref
,
param
(
ccx
,
0u
))],
ty
::
mk_imm_ptr
(
tcx
,
param
(
ccx
,
0u
)))
}
"needs_drop"
{
(
1u
,
[],
ty
::
mk_bool
(
tcx
))
}
"visit_ty"
{
(
2u
,
[
arg
(
ast
::
by_ref
,
param
(
ccx
,
1u
))],
ty
::
mk_nil
(
tcx
))
}
"visit_val"
{
(
2u
,
[
arg
(
ast
::
by_ref
,
param
(
ccx
,
0u
)),
arg
(
ast
::
by_ref
,
param
(
ccx
,
1u
))],
ty
::
mk_nil
(
tcx
))
}
"visit_val_pair"
{
(
2u
,
[
arg
(
ast
::
by_ref
,
param
(
ccx
,
0u
)),
arg
(
ast
::
by_ref
,
param
(
ccx
,
0u
)),
arg
(
ast
::
by_ref
,
param
(
ccx
,
1u
))],
ty
::
mk_nil
(
tcx
))
}
other
{
tcx
.sess
.span_err
(
it
.span
,
"unrecognized intrinsic function: `"
+
other
+
"`"
);
ret
;
}
};
let
fty
=
ty
::
mk_fn
(
tcx
,
{
proto
:
ast
::
proto_bare
,
inputs
:
inputs
,
output
:
output
,
ret_style
:
ast
::
return_val
,
constraints
:
[]});
let
i_ty
=
ty_of_native_item
(
ccx
,
it
);
let
i_n_tps
=
(
*
i_ty
.bounds
)
.len
();
if
i_n_tps
!=
n_tps
{
tcx
.sess
.span_err
(
it
.span
,
#
fmt
(
"intrinsic has wrong number
\
of type parameters. found %u,
\
expected %u"
,
i_n_tps
,
n_tps
));
}
else
{
require_same_types
(
tcx
,
it
.span
,
i_ty
.ty
,
fty
,
{||
#
fmt
[
"intrinsic has wrong type.
\
expected %s"
,
ty_to_str
(
ccx
.tcx
,
fty
)]});
}
}
/*
Instantiates the path for the given iface reference, assuming that
it's bound to a valid iface type. Returns the def_id for the defining
iface. Fails if the type is a type other than an iface type.
*/
fn
instantiate_iface_ref
(
ccx
:
@
crate_ctxt
,
t
:
@
ast
::
iface_ref
,
rp
:
ast
::
region_param
)
->
(
ast
::
def_id
,
ty_param_substs_and_ty
)
{
let
sp
=
t
.path.span
,
err
=
"can only implement interface types"
,
sess
=
ccx
.tcx.sess
;
let
rscope
=
type_rscope
(
rp
);
alt
lookup_def_tcx
(
ccx
.tcx
,
t
.path.span
,
t
.id
)
{
ast
::
def_ty
(
t_id
)
{
let
tpt
=
astconv
::
ast_path_to_ty
(
ccx
,
rscope
,
t_id
,
t
.path
,
t
.id
);
alt
ty
::
get
(
tpt
.ty
)
.struct
{
ty
::
ty_iface
(
*
)
{
(
t_id
,
tpt
)
}
_
{
sess
.span_fatal
(
sp
,
err
);
}
}
}
_
{
sess
.span_fatal
(
sp
,
err
);
}
}
}
fn
ty_of_item
(
ccx
:
@
crate_ctxt
,
it
:
@
ast
::
item
)
->
ty
::
ty_param_bounds_and_ty
{
let
def_id
=
local_def
(
it
.id
);
let
tcx
=
ccx
.tcx
;
alt
tcx
.tcache
.find
(
def_id
)
{
some
(
tpt
)
{
ret
tpt
;
}
_
{}
}
alt
it
.node
{
ast
::
item_const
(
t
,
_
)
{
let
typ
=
ccx
.to_ty
(
empty_rscope
,
t
);
let
tpt
=
no_params
(
typ
);
tcx
.tcache
.insert
(
local_def
(
it
.id
),
tpt
);
ret
tpt
;
}
ast
::
item_fn
(
decl
,
tps
,
_
)
{
let
bounds
=
ty_param_bounds
(
ccx
,
tps
);
let
tofd
=
ty_of_fn_decl
(
ccx
,
empty_rscope
,
ast
::
proto_bare
,
decl
,
none
);
let
tpt
=
{
bounds
:
bounds
,
rp
:
ast
::
rp_none
,
// functions do not have a self
ty
:
ty
::
mk_fn
(
ccx
.tcx
,
tofd
)};
ccx
.tcx.tcache
.insert
(
local_def
(
it
.id
),
tpt
);
ret
tpt
;
}
ast
::
item_ty
(
t
,
tps
,
rp
)
{
alt
tcx
.tcache
.find
(
local_def
(
it
.id
))
{
some
(
tpt
)
{
ret
tpt
;
}
none
{
}
}
let
tpt
=
{
let
ty
=
{
let
t0
=
ccx
.to_ty
(
type_rscope
(
rp
),
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
// reconstruct the value of X.
if
!
vec
::
is_empty
(
tps
)
{
t0
}
else
{
ty
::
mk_with_id
(
tcx
,
t0
,
def_id
)
}
};
{
bounds
:
ty_param_bounds
(
ccx
,
tps
),
rp
:
rp
,
ty
:
ty
}
};
tcx
.tcache
.insert
(
local_def
(
it
.id
),
tpt
);
ret
tpt
;
}
ast
::
item_res
(
decl
,
tps
,
_
,
_
,
_
,
rp
)
{
let
{
bounds
,
substs
}
=
mk_substs
(
ccx
,
tps
,
rp
);
let
t_arg
=
ty_of_arg
(
ccx
,
type_rscope
(
rp
),
decl
.inputs
[
0
],
none
);
let
t
=
ty
::
mk_res
(
tcx
,
local_def
(
it
.id
),
t_arg
.ty
,
substs
);
let
t_res
=
{
bounds
:
bounds
,
rp
:
rp
,
ty
:
t
};
tcx
.tcache
.insert
(
local_def
(
it
.id
),
t_res
);
ret
t_res
;
}
ast
::
item_enum
(
_
,
tps
,
rp
)
{
// Create a new generic polytype.
let
{
bounds
,
substs
}
=
mk_substs
(
ccx
,
tps
,
rp
);
let
t
=
ty
::
mk_enum
(
tcx
,
local_def
(
it
.id
),
substs
);
let
tpt
=
{
bounds
:
bounds
,
rp
:
rp
,
ty
:
t
};
tcx
.tcache
.insert
(
local_def
(
it
.id
),
tpt
);
ret
tpt
;
}
ast
::
item_iface
(
tps
,
rp
,
ms
)
{
let
{
bounds
,
substs
}
=
mk_substs
(
ccx
,
tps
,
rp
);
let
t
=
ty
::
mk_iface
(
tcx
,
local_def
(
it
.id
),
substs
);
let
tpt
=
{
bounds
:
bounds
,
rp
:
rp
,
ty
:
t
};
tcx
.tcache
.insert
(
local_def
(
it
.id
),
tpt
);
ret
tpt
;
}
ast
::
item_class
(
tps
,
_
,
_
,
_
,
_
,
rp
)
{
let
{
bounds
,
substs
}
=
mk_substs
(
ccx
,
tps
,
rp
);
let
t
=
ty
::
mk_class
(
tcx
,
local_def
(
it
.id
),
substs
);
let
tpt
=
{
bounds
:
bounds
,
rp
:
rp
,
ty
:
t
};
tcx
.tcache
.insert
(
local_def
(
it
.id
),
tpt
);
ret
tpt
;
}
ast
::
item_impl
(
*
)
|
ast
::
item_mod
(
_
)
|
ast
::
item_native_mod
(
_
)
{
fail
;
}
}
}
fn
ty_of_native_item
(
ccx
:
@
crate_ctxt
,
it
:
@
ast
::
native_item
)
->
ty
::
ty_param_bounds_and_ty
{
alt
it
.node
{
ast
::
native_item_fn
(
fn_decl
,
params
)
{
ret
ty_of_native_fn_decl
(
ccx
,
fn_decl
,
params
,
local_def
(
it
.id
));
}
}
}
fn
ty_param_bounds
(
ccx
:
@
crate_ctxt
,
params
:
[
ast
::
ty_param
])
->
@
[
ty
::
param_bounds
]
{
fn
compute_bounds
(
ccx
:
@
crate_ctxt
,
param
:
ast
::
ty_param
)
->
ty
::
param_bounds
{
@
vec
::
flat_map
(
*
param
.bounds
)
{
|
b
|
alt
b
{
ast
::
bound_send
{
[
ty
::
bound_send
]
}
ast
::
bound_copy
{
[
ty
::
bound_copy
]
}
ast
::
bound_iface
(
t
)
{
let
ity
=
ast_ty_to_ty
(
ccx
,
empty_rscope
,
t
);
alt
ty
::
get
(
ity
)
.struct
{
ty
::
ty_iface
(
*
)
{
[
ty
::
bound_iface
(
ity
)]
}
_
{
ccx
.tcx.sess
.span_err
(
t
.span
,
"type parameter bounds must be
\
interface types"
);
[]
}
}
}
}
}
}
@
params
.map
{
|
param
|
alt
ccx
.tcx.ty_param_bounds
.find
(
param
.id
)
{
some
(
bs
)
{
bs
}
none
{
let
bounds
=
compute_bounds
(
ccx
,
param
);
ccx
.tcx.ty_param_bounds
.insert
(
param
.id
,
bounds
);
bounds
}
}
}
}
fn
ty_of_native_fn_decl
(
ccx
:
@
crate_ctxt
,
decl
:
ast
::
fn_decl
,
ty_params
:
[
ast
::
ty_param
],
def_id
:
ast
::
def_id
)
->
ty
::
ty_param_bounds_and_ty
{
let
bounds
=
ty_param_bounds
(
ccx
,
ty_params
);
let
rb
=
in_binding_rscope
(
empty_rscope
);
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
);
let
t_fn
=
ty
::
mk_fn
(
ccx
.tcx
,
{
proto
:
ast
::
proto_bare
,
inputs
:
input_tys
,
output
:
output_ty
,
ret_style
:
ast
::
return_val
,
constraints
:
[]});
let
tpt
=
{
bounds
:
bounds
,
rp
:
ast
::
rp_none
,
ty
:
t_fn
};
ccx
.tcx.tcache
.insert
(
def_id
,
tpt
);
ret
tpt
;
}
fn
mk_ty_params
(
ccx
:
@
crate_ctxt
,
atps
:
[
ast
::
ty_param
])
->
{
bounds
:
@
[
ty
::
param_bounds
],
params
:
[
ty
::
t
]}
{
let
mut
i
=
0u
;
let
bounds
=
ty_param_bounds
(
ccx
,
atps
);
{
bounds
:
bounds
,
params
:
vec
::
map
(
atps
,
{|
atp
|
let
t
=
ty
::
mk_param
(
ccx
.tcx
,
i
,
local_def
(
atp
.id
));
i
+=
1u
;
t
})}
}
fn
mk_substs
(
ccx
:
@
crate_ctxt
,
atps
:
[
ast
::
ty_param
],
rp
:
ast
::
region_param
)
->
{
bounds
:
@
[
ty
::
param_bounds
],
substs
:
ty
::
substs
}
{
let
{
bounds
,
params
}
=
mk_ty_params
(
ccx
,
atps
);
let
self_r
=
alt
rp
{
ast
::
rp_self
{
some
(
ty
::
re_bound
(
ty
::
br_self
))
}
ast
::
rp_none
{
none
}
};
{
bounds
:
bounds
,
substs
:
{
self_r
:
self_r
,
self_ty
:
none
,
tps
:
params
}}
}
src/rustc/middle/typeck/demand.rs
浏览文件 @
7512284a
import
check
::{
fn_ctxt
,
methods
};
// Requires that the two types unify, and prints an error message if they
// don't.
fn
suptype
(
fcx
:
@
fn_ctxt
,
sp
:
span
,
...
...
src/rustc/middle/typeck/regionck.rs
浏览文件 @
7512284a
...
...
@@ -15,6 +15,7 @@
import
util
::
ppaux
;
import
syntax
::
print
::
pprust
;
import
check
::{
fn_ctxt
,
methods
};
type
rcx
=
@
{
fcx
:
@
fn_ctxt
,
mut
errors_reported
:
uint
};
type
rvt
=
visit
::
vt
<
rcx
>
;
...
...
src/rustc/middle/typeck/vtable.rs
浏览文件 @
7512284a
import
check
::{
fn_ctxt
,
impl_self_ty
,
methods
};
fn
has_iface_bounds
(
tps
:
[
ty
::
param_bounds
])
->
bool
{
vec
::
any
(
tps
,
{|
bs
|
vec
::
any
(
*
bs
,
{|
b
|
...
...
src/rustc/middle/typeck/writeback.rs
浏览文件 @
7512284a
// Type resolution: the phase that finds all the types in the AST with
// unresolved type variables and replaces "ty_var" types with their
// substitutions.
import
check
::{
fn_ctxt
,
lookup_local
,
methods
};
export
resolve_type_vars_in_fn
;
export
resolve_type_vars_in_expr
;
...
...
src/rustc/rustc.rc
浏览文件 @
7512284a
...
...
@@ -52,6 +52,7 @@ mod middle {
mod
ast_map
;
mod
resolve
;
mod
typeck
{
mod
check
;
mod
regionck
;
mod
demand
;
mod
infer
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录