Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
26dc48d6
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,发现更多精彩内容 >>
提交
26dc48d6
编写于
5月 15, 2012
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
break apart typeck a little (more to come)
上级
adb61e3e
变更
6
展开全部
隐藏空白更改
内联
并排
Showing
6 changed file
with
1531 addition
and
1500 deletion
+1531
-1500
src/rustc/middle/typeck.rs
src/rustc/middle/typeck.rs
+16
-1499
src/rustc/middle/typeck/astconv.rs
src/rustc/middle/typeck/astconv.rs
+711
-0
src/rustc/middle/typeck/collect.rs
src/rustc/middle/typeck/collect.rs
+343
-0
src/rustc/middle/typeck/vtable.rs
src/rustc/middle/typeck/vtable.rs
+271
-0
src/rustc/middle/typeck/writeback.rs
src/rustc/middle/typeck/writeback.rs
+184
-0
src/rustc/rustc.rc
src/rustc/rustc.rc
+6
-1
未找到文件。
src/rustc/middle/typeck.rs
浏览文件 @
26dc48d6
此差异已折叠。
点击以展开。
src/rustc/middle/typeck/astconv.rs
0 → 100644
浏览文件 @
26dc48d6
此差异已折叠。
点击以展开。
src/rustc/middle/typeck/collect.rs
0 → 100644
浏览文件 @
26dc48d6
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.
fn
get_enum_variant_types
(
ccx
:
@
crate_ctxt
,
enum_ty
:
ty
::
t
,
variants
:
[
ast
::
variant
],
ty_params
:
[
ast
::
ty_param
],
rp
:
ast
::
region_param
)
{
let
tcx
=
ccx
.tcx
;
// Create a set of parameter types shared among all the variants.
for
variants
.each
{|
variant
|
// Nullary enum constructors get turned into constants; n-ary enum
// constructors get turned into functions.
let
result_ty
=
if
vec
::
len
(
variant
.node.args
)
==
0u
{
enum_ty
}
else
{
let
rs
=
type_rscope
(
rp
);
let
args
=
variant
.node.args.map
{
|
va
|
let
arg_ty
=
ccx
.to_ty
(
rs
,
va
.ty
);
{
mode
:
ast
::
expl
(
ast
::
by_copy
),
ty
:
arg_ty
}
};
ty
::
mk_fn
(
tcx
,
{
proto
:
ast
::
proto_box
,
inputs
:
args
,
output
:
enum_ty
,
ret_style
:
ast
::
return_val
,
constraints
:
[]})
};
let
tpt
=
{
bounds
:
astconv
::
ty_param_bounds
(
ccx
,
ty_params
),
rp
:
rp
,
ty
:
result_ty
};
tcx
.tcache
.insert
(
local_def
(
variant
.node.id
),
tpt
);
write_ty_to_tcx
(
tcx
,
variant
.node.id
,
result_ty
);
}
}
fn
ensure_iface_methods
(
ccx
:
@
crate_ctxt
,
id
:
ast
::
node_id
)
{
fn
store_methods
<
T
>
(
ccx
:
@
crate_ctxt
,
id
:
ast
::
node_id
,
stuff
:
[
T
],
f
:
fn
@
(
T
)
->
ty
::
method
)
{
ty
::
store_iface_methods
(
ccx
.tcx
,
id
,
@
vec
::
map
(
stuff
,
f
));
}
let
tcx
=
ccx
.tcx
;
alt
check
tcx
.items
.get
(
id
)
{
ast_map
::
node_item
(
@
{
node
:
ast
::
item_iface
(
_
,
rp
,
ms
),
_
},
_
)
{
store_methods
::
<
ast
::
ty_method
>
(
ccx
,
id
,
ms
)
{|
m
|
ty_of_ty_method
(
ccx
,
m
,
rp
)
};
}
ast_map
::
node_item
(
@
{
node
:
ast
::
item_class
(
_
,
_
,
its
,
_
,
_
,
rp
),
_
},
_
)
{
let
(
_
,
ms
)
=
split_class_items
(
its
);
// All methods need to be stored, since lookup_method
// relies on the same method cache for self-calls
store_methods
::
<@
ast
::
method
>
(
ccx
,
id
,
ms
)
{|
m
|
ty_of_method
(
ccx
,
m
,
rp
)
};
}
}
}
fn
check_methods_against_iface
(
ccx
:
@
crate_ctxt
,
tps
:
[
ast
::
ty_param
],
rp
:
ast
::
region_param
,
selfty
:
ty
::
t
,
a_ifacety
:
@
ast
::
iface_ref
,
ms
:
[
@
ast
::
method
])
{
let
tcx
=
ccx
.tcx
;
let
i_bounds
=
astconv
::
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
{
ensure_iface_methods
(
ccx
,
did
.node
);
}
for
vec
::
each
(
*
ty
::
iface_methods
(
tcx
,
did
))
{|
if_m
|
alt
vec
::
find
(
my_methods
,
{|
m
|
if_m
.ident
==
m
.mty.ident
})
{
some
({
mty
:
m
,
id
,
span
})
{
if
m
.purity
!=
if_m
.purity
{
ccx
.tcx.sess
.span_err
(
span
,
#
fmt
[
"method `%s`'s purity
\
not match the iface method's
\
purity"
,
m
.ident
]);
}
let
mt
=
compare_impl_method
(
ccx
.tcx
,
span
,
m
,
vec
::
len
(
tps
),
if_m
,
tpt
.substs
,
selfty
);
let
old
=
tcx
.tcache
.get
(
local_def
(
id
));
if
old
.ty
!=
mt
{
tcx
.tcache
.insert
(
local_def
(
id
),
{
bounds
:
old
.bounds
,
rp
:
old
.rp
,
ty
:
mt
});
write_ty_to_tcx
(
tcx
,
id
,
mt
);
}
}
none
{
tcx
.sess
.span_err
(
a_ifacety
.path.span
,
#
fmt
[
"missing method `%s`"
,
if_m
.ident
]);
}
}
// alt
}
// |if_m|
}
// fn
fn
convert_class_item
(
ccx
:
@
crate_ctxt
,
rp
:
ast
::
region_param
,
v
:
ast_util
::
ivar
)
{
/* we want to do something here, b/c within the
scope of the class, it's ok to refer to fields &
methods unqualified */
/* they have these types *within the scope* of the
class. outside the class, it's done with expr_field */
let
tt
=
ccx
.to_ty
(
type_rscope
(
rp
),
v
.ty
);
write_ty_to_tcx
(
ccx
.tcx
,
v
.id
,
tt
);
}
fn
convert_methods
(
ccx
:
@
crate_ctxt
,
ms
:
[
@
ast
::
method
],
rp
:
ast
::
region_param
,
i_bounds
:
@
[
ty
::
param_bounds
],
self_ty
:
ty
::
t
)
->
[{
mty
:
ty
::
method
,
id
:
ast
::
node_id
,
span
:
span
}]
{
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
mty
=
ty_of_method
(
ccx
,
m
,
rp
);
let
fty
=
ty
::
mk_fn
(
tcx
,
mty
.fty
);
tcx
.tcache
.insert
(
local_def
(
m
.id
),
// n.b. This code is kind of sketchy (concat'ing i_bounds
// with bounds), but removing *i_bounds breaks other stuff
{
bounds
:
@
(
*
i_bounds
+
*
bounds
),
rp
:
rp
,
ty
:
fty
});
write_ty_to_tcx
(
tcx
,
m
.id
,
fty
);
{
mty
:
mty
,
id
:
m
.id
,
span
:
m
.span
}
}
}
fn
convert
(
ccx
:
@
crate_ctxt
,
it
:
@
ast
::
item
)
{
let
tcx
=
ccx
.tcx
;
alt
it
.node
{
// These don't define types.
ast
::
item_mod
(
_
)
{}
ast
::
item_native_mod
(
m
)
{
if
syntax
::
attr
::
native_abi
(
it
.attrs
)
==
either
::
right
(
ast
::
native_abi_rust_intrinsic
)
{
for
m
.items.each
{
|
item
|
check_intrinsic_type
(
ccx
,
item
);
}
}
}
ast
::
item_enum
(
variants
,
ty_params
,
rp
)
{
let
tpt
=
ty_of_item
(
ccx
,
it
);
write_ty_to_tcx
(
tcx
,
it
.id
,
tpt
.ty
);
get_enum_variant_types
(
ccx
,
tpt
.ty
,
variants
,
ty_params
,
rp
);
}
ast
::
item_impl
(
tps
,
rp
,
ifce
,
selfty
,
ms
)
{
let
i_bounds
=
astconv
::
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
),
{
bounds
:
i_bounds
,
rp
:
rp
,
ty
:
selfty
});
alt
ifce
{
some
(
t
)
{
check_methods_against_iface
(
ccx
,
tps
,
rp
,
selfty
,
t
,
ms
);
}
_
{
// Still have to do this to write method types
// into the table
convert_methods
(
ccx
,
ms
,
rp
,
i_bounds
,
selfty
);
}
}
}
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
),
decl
.inputs
[
0
],
none
);
let
t_res
=
ty
::
mk_res
(
tcx
,
def_id
,
t_arg
.ty
,
substs
);
let
t_ctor
=
ty
::
mk_fn
(
tcx
,
{
proto
:
ast
::
proto_box
,
inputs
:
[{
mode
:
ast
::
expl
(
ast
::
by_copy
),
ty
:
t_arg
.ty
}],
output
:
t_res
,
ret_style
:
ast
::
return_val
,
constraints
:
[]
});
let
t_dtor
=
ty
::
mk_fn
(
tcx
,
{
proto
:
ast
::
proto_box
,
inputs
:
[
t_arg
],
output
:
ty
::
mk_nil
(
tcx
),
ret_style
:
ast
::
return_val
,
constraints
:
[]
});
write_ty_to_tcx
(
tcx
,
it
.id
,
t_res
);
write_ty_to_tcx
(
tcx
,
ctor_id
,
t_ctor
);
tcx
.tcache
.insert
(
local_def
(
ctor_id
),
{
bounds
:
bounds
,
rp
:
rp
,
ty
:
t_ctor
});
tcx
.tcache
.insert
(
def_id
,
{
bounds
:
bounds
,
rp
:
rp
,
ty
:
t_res
});
write_ty_to_tcx
(
tcx
,
dtor_id
,
t_dtor
);
}
ast
::
item_iface
(
*
)
{
let
tpt
=
ty_of_item
(
ccx
,
it
);
#
debug
[
"item_iface(it.id=%d, tpt.ty=%s)"
,
it
.id
,
ty_to_str
(
tcx
,
tpt
.ty
)];
write_ty_to_tcx
(
tcx
,
it
.id
,
tpt
.ty
);
ensure_iface_methods
(
ccx
,
it
.id
);
}
ast
::
item_class
(
tps
,
ifaces
,
members
,
ctor
,
m_dtor
,
rp
)
{
// Write the class type
let
tpt
=
ty_of_item
(
ccx
,
it
);
write_ty_to_tcx
(
tcx
,
it
.id
,
tpt
.ty
);
// Write the ctor type
let
t_ctor
=
ty
::
mk_fn
(
tcx
,
astconv
::
ty_of_fn_decl
(
ccx
,
empty_rscope
,
ast
::
proto_any
,
ctor
.node.dec
,
none
));
write_ty_to_tcx
(
tcx
,
ctor
.node.id
,
t_ctor
);
tcx
.tcache
.insert
(
local_def
(
ctor
.node.id
),
{
bounds
:
tpt
.bounds
,
rp
:
ast
::
rp_none
,
ty
:
t_ctor
});
option
::
iter
(
m_dtor
)
{|
dtor
|
// Write the dtor type
let
t_dtor
=
ty
::
mk_fn
(
tcx
,
// not sure about empty_rscope
// FIXME
astconv
::
ty_of_fn_decl
(
ccx
,
empty_rscope
,
ast
::
proto_any
,
ast_util
::
dtor_dec
(),
none
));
write_ty_to_tcx
(
tcx
,
dtor
.node.id
,
t_dtor
);
tcx
.tcache
.insert
(
local_def
(
dtor
.node.id
),
{
bounds
:
tpt
.bounds
,
rp
:
ast
::
rp_none
,
ty
:
t_dtor
});
};
ensure_iface_methods
(
ccx
,
it
.id
);
/* FIXME: check for proper public/privateness */
// Write the type of each of the members
let
(
fields
,
methods
)
=
split_class_items
(
members
);
for
fields
.each
{|
f
|
convert_class_item
(
ccx
,
rp
,
f
);
}
// The selfty is just the class type
let
{
bounds
:
_
,
substs
}
=
mk_substs
(
ccx
,
tps
,
rp
);
let
selfty
=
ty
::
mk_class
(
tcx
,
local_def
(
it
.id
),
substs
);
// Need to convert all methods so we can check internal
// references to private methods
// NDM to TJC---I think we ought to be using bounds here, not @[].
// But doing so causes errors later on.
convert_methods
(
ccx
,
methods
,
rp
,
@
[],
selfty
);
/*
Finally, check that the class really implements the ifaces
that it claims to implement.
*/
for
ifaces
.each
{
|
ifce
|
check_methods_against_iface
(
ccx
,
tps
,
rp
,
selfty
,
ifce
,
methods
);
let
t
=
ty
::
node_id_to_type
(
tcx
,
ifce
.id
);
// FIXME: This assumes classes only implement
// non-parameterized ifaces. add a test case for
// a class implementing a parameterized iface.
// -- tjc (#1726)
tcx
.tcache
.insert
(
local_def
(
ifce
.id
),
no_params
(
t
));
}
}
_
{
// This call populates the type cache with the converted type
// of the item in passing. All we have to do here is to write
// it into the node type table.
let
tpt
=
ty_of_item
(
ccx
,
it
);
write_ty_to_tcx
(
tcx
,
it
.id
,
tpt
.ty
);
}
}
}
fn
convert_native
(
ccx
:
@
crate_ctxt
,
i
:
@
ast
::
native_item
)
{
// As above, this call populates the type table with the converted
// type of the native item. We simply write it into the node type
// table.
let
tpt
=
ty_of_native_item
(
ccx
,
i
);
alt
i
.node
{
ast
::
native_item_fn
(
_
,
_
)
{
write_ty_to_tcx
(
ccx
.tcx
,
i
.id
,
tpt
.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
()
}));
}
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
,
m
.decl
,
none
),
purity
:
m
.decl.purity
,
vis
:
m
.vis
}
}
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
,
m
.decl
,
none
),
// assume public, because this is only invoked on iface methods
purity
:
m
.decl.purity
,
vis
:
ast
::
public
}
}
src/rustc/middle/typeck/vtable.rs
0 → 100644
浏览文件 @
26dc48d6
fn
has_iface_bounds
(
tps
:
[
ty
::
param_bounds
])
->
bool
{
vec
::
any
(
tps
,
{|
bs
|
vec
::
any
(
*
bs
,
{|
b
|
alt
b
{
ty
::
bound_iface
(
_
)
{
true
}
_
{
false
}
}
})
})
}
fn
lookup_vtables
(
fcx
:
@
fn_ctxt
,
isc
:
resolve
::
iscopes
,
sp
:
span
,
bounds
:
@
[
ty
::
param_bounds
],
substs
:
ty
::
substs
,
allow_unsafe
:
bool
)
->
vtable_res
{
let
tcx
=
fcx
.ccx.tcx
;
let
mut
result
=
[],
i
=
0u
;
for
substs
.tps.each
{|
ty
|
for
vec
::
each
(
*
bounds
[
i
])
{|
bound
|
alt
bound
{
ty
::
bound_iface
(
i_ty
)
{
let
i_ty
=
ty
::
subst
(
tcx
,
substs
,
i_ty
);
result
+=
[
lookup_vtable
(
fcx
,
isc
,
sp
,
ty
,
i_ty
,
allow_unsafe
)];
}
_
{}
}
}
i
+=
1u
;
}
@
result
}
fn
fixup_substs
(
fcx
:
@
fn_ctxt
,
sp
:
span
,
id
:
ast
::
def_id
,
substs
:
ty
::
substs
)
->
ty
::
substs
{
let
tcx
=
fcx
.ccx.tcx
;
// use a dummy type just to package up the substs that need fixing up
let
t
=
ty
::
mk_iface
(
tcx
,
id
,
substs
);
let
t_f
=
fixup_ty
(
fcx
,
sp
,
t
);
alt
check
ty
::
get
(
t_f
)
.struct
{
ty
::
ty_iface
(
_
,
substs_f
)
{
substs_f
}
}
}
fn
relate_iface_tys
(
fcx
:
@
fn_ctxt
,
sp
:
span
,
exp_iface_ty
:
ty
::
t
,
act_iface_ty
:
ty
::
t
)
{
demand
::
suptype
(
fcx
,
sp
,
exp_iface_ty
,
act_iface_ty
)
}
/*
Look up the vtable to use when treating an item of type <t>
as if it has type <iface_ty>
*/
fn
lookup_vtable
(
fcx
:
@
fn_ctxt
,
isc
:
resolve
::
iscopes
,
sp
:
span
,
ty
:
ty
::
t
,
iface_ty
:
ty
::
t
,
allow_unsafe
:
bool
)
->
vtable_origin
{
#
debug
[
"lookup_vtable(ty=%s, iface_ty=%s)"
,
fcx
.ty_to_str
(
ty
),
fcx
.ty_to_str
(
iface_ty
)];
let
_
i
=
indenter
();
let
tcx
=
fcx
.ccx.tcx
;
let
(
iface_id
,
iface_substs
)
=
alt
check
ty
::
get
(
iface_ty
)
.struct
{
ty
::
ty_iface
(
did
,
substs
)
{
(
did
,
substs
)
}
};
let
ty
=
fixup_ty
(
fcx
,
sp
,
ty
);
alt
ty
::
get
(
ty
)
.struct
{
ty
::
ty_param
(
n
,
did
)
{
let
mut
n_bound
=
0u
;
for
vec
::
each
(
*
tcx
.ty_param_bounds
.get
(
did
.node
))
{
|
bound
|
alt
bound
{
ty
::
bound_send
|
ty
::
bound_copy
{
/* ignore */
}
ty
::
bound_iface
(
ity
)
{
alt
check
ty
::
get
(
ity
)
.struct
{
ty
::
ty_iface
(
idid
,
substs
)
{
if
iface_id
==
idid
{
relate_iface_tys
(
fcx
,
sp
,
iface_ty
,
ity
);
ret
vtable_param
(
n
,
n_bound
);
}
}
}
n_bound
+=
1u
;
}
}
}
}
ty
::
ty_iface
(
did
,
substs
)
if
iface_id
==
did
{
relate_iface_tys
(
fcx
,
sp
,
iface_ty
,
ty
);
if
!
allow_unsafe
{
for
vec
::
each
(
*
ty
::
iface_methods
(
tcx
,
did
))
{|
m
|
if
ty
::
type_has_self
(
ty
::
mk_fn
(
tcx
,
m
.fty
))
{
tcx
.sess
.span_err
(
sp
,
"a boxed iface with self types may not be
\
passed as a bounded type"
);
}
else
if
(
*
m
.tps
)
.len
()
>
0u
{
tcx
.sess
.span_err
(
sp
,
"a boxed iface with generic methods may not
\
be passed as a bounded type"
);
}
}
}
ret
vtable_iface
(
did
,
substs
.tps
);
}
_
{
let
mut
found
=
[];
for
list
::
each
(
isc
)
{|
impls
|
/* For each impl in scope... */
for
vec
::
each
(
*
impls
)
{|
im
|
// im = one specific impl
// find the iface that im implements (if any)
let
of_ty
=
alt
ty
::
impl_iface
(
tcx
,
im
.did
)
{
some
(
of_ty
)
{
of_ty
}
_
{
cont
;
}
};
// it must have the same id as the expected one
alt
ty
::
get
(
of_ty
)
.struct
{
ty
::
ty_iface
(
id
,
_
)
if
id
!=
iface_id
{
cont
;
}
_
{
/* ok */
}
}
// check whether the type unifies with the type
// that the impl is for, and continue if not
let
{
substs
:
substs
,
ty
:
for_ty
}
=
impl_self_ty
(
fcx
,
im
.did
);
let
im_bs
=
ty
::
lookup_item_type
(
tcx
,
im
.did
)
.bounds
;
alt
fcx
.mk_subty
(
ty
,
for_ty
)
{
result
::
err
(
_
)
{
cont
;
}
result
::
ok
(())
{
}
}
// check that desired iface type unifies
let
of_ty
=
ty
::
subst
(
tcx
,
substs
,
of_ty
);
relate_iface_tys
(
fcx
,
sp
,
iface_ty
,
of_ty
);
// recursively process the bounds
let
iface_tps
=
iface_substs
.tps
;
let
substs_f
=
fixup_substs
(
fcx
,
sp
,
iface_id
,
substs
);
connect_iface_tps
(
fcx
,
sp
,
substs_f
.tps
,
iface_tps
,
im
.did
);
let
subres
=
lookup_vtables
(
fcx
,
isc
,
sp
,
im_bs
,
substs_f
,
false
);
found
+=
[
vtable_static
(
im
.did
,
substs_f
.tps
,
subres
)];
}
alt
found
.len
()
{
0u
{
/* fallthrough */
}
1u
{
ret
found
[
0
];
}
_
{
fcx
.ccx.tcx.sess
.span_err
(
sp
,
"multiple applicable methods in scope"
);
ret
found
[
0
];
}
}
}
}
}
tcx
.sess
.span_fatal
(
sp
,
"failed to find an implementation of interface "
+
ty_to_str
(
tcx
,
iface_ty
)
+
" for "
+
ty_to_str
(
tcx
,
ty
));
}
fn
fixup_ty
(
fcx
:
@
fn_ctxt
,
sp
:
span
,
ty
:
ty
::
t
)
->
ty
::
t
{
let
tcx
=
fcx
.ccx.tcx
;
alt
infer
::
resolve_deep
(
fcx
.infcx
,
ty
,
true
)
{
result
::
ok
(
new_type
)
{
new_type
}
result
::
err
(
e
)
{
tcx
.sess
.span_fatal
(
sp
,
#
fmt
[
"cannot determine a type
\
for this bounded type parameter: %s"
,
infer
::
fixup_err_to_str
(
e
)])
}
}
}
fn
connect_iface_tps
(
fcx
:
@
fn_ctxt
,
sp
:
span
,
impl_tys
:
[
ty
::
t
],
iface_tys
:
[
ty
::
t
],
impl_did
:
ast
::
def_id
)
{
let
tcx
=
fcx
.ccx.tcx
;
let
ity
=
option
::
get
(
ty
::
impl_iface
(
tcx
,
impl_did
));
let
iface_ty
=
ty
::
subst_tps
(
tcx
,
impl_tys
,
ity
);
alt
check
ty
::
get
(
iface_ty
)
.struct
{
ty
::
ty_iface
(
_
,
substs
)
{
vec
::
iter2
(
substs
.tps
,
iface_tys
,
{|
a
,
b
|
demand
::
suptype
(
fcx
,
sp
,
a
,
b
);});
}
}
}
fn
resolve_expr
(
ex
:
@
ast
::
expr
,
&&
fcx
:
@
fn_ctxt
,
v
:
visit
::
vt
<@
fn_ctxt
>
)
{
let
cx
=
fcx
.ccx
;
alt
ex
.node
{
ast
::
expr_path
(
*
)
{
alt
fcx
.opt_node_ty_substs
(
ex
.id
)
{
some
(
substs
)
{
let
did
=
ast_util
::
def_id_of_def
(
cx
.tcx.def_map
.get
(
ex
.id
));
let
item_ty
=
ty
::
lookup_item_type
(
cx
.tcx
,
did
);
if
has_iface_bounds
(
*
item_ty
.bounds
)
{
let
impls
=
cx
.impl_map
.get
(
ex
.id
);
cx
.vtable_map
.insert
(
ex
.id
,
lookup_vtables
(
fcx
,
impls
,
ex
.span
,
item_ty
.bounds
,
substs
,
false
));
}
}
_
{}
}
}
// Must resolve bounds on methods with bounded params
ast
::
expr_field
(
*
)
|
ast
::
expr_binary
(
*
)
|
ast
::
expr_unary
(
*
)
|
ast
::
expr_assign_op
(
*
)
|
ast
::
expr_index
(
*
)
{
alt
cx
.method_map
.find
(
ex
.id
)
{
some
(
method_static
(
did
))
{
let
bounds
=
ty
::
lookup_item_type
(
cx
.tcx
,
did
)
.bounds
;
if
has_iface_bounds
(
*
bounds
)
{
let
callee_id
=
alt
ex
.node
{
ast
::
expr_field
(
_
,
_
,
_
)
{
ex
.id
}
_
{
ast_util
::
op_expr_callee_id
(
ex
)
}
};
let
substs
=
fcx
.node_ty_substs
(
callee_id
);
let
iscs
=
cx
.impl_map
.get
(
ex
.id
);
cx
.vtable_map
.insert
(
callee_id
,
lookup_vtables
(
fcx
,
iscs
,
ex
.span
,
bounds
,
substs
,
false
));
}
}
_
{}
}
}
ast
::
expr_cast
(
src
,
_
)
{
let
target_ty
=
fcx
.expr_ty
(
ex
);
alt
ty
::
get
(
target_ty
)
.struct
{
ty
::
ty_iface
(
*
)
{
/* Casting to an interface type.
Look up all impls for the cast expr...
*/
let
impls
=
cx
.impl_map
.get
(
ex
.id
);
/*
Look up vtables for the type we're casting to,
passing in the source and target type
*/
let
vtable
=
lookup_vtable
(
fcx
,
impls
,
ex
.span
,
fcx
.expr_ty
(
src
),
target_ty
,
true
);
/*
Map this expression to that vtable (that is: "ex has
vtable <vtable>")
*/
cx
.vtable_map
.insert
(
ex
.id
,
@
[
vtable
]);
}
_
{}
}
}
_
{}
}
visit
::
visit_expr
(
ex
,
fcx
,
v
);
}
// Detect points where an interface-bounded type parameter is
// instantiated, resolve the impls for the parameters.
fn
resolve_in_block
(
fcx
:
@
fn_ctxt
,
bl
:
ast
::
blk
)
{
visit
::
visit_block
(
bl
,
fcx
,
visit
::
mk_vt
(
@
{
visit_expr
:
resolve_expr
,
visit_item
:
fn
@
(
_
i
:
@
ast
::
item
,
&&
_
e
:
@
fn_ctxt
,
_
v
:
visit
::
vt
<@
fn_ctxt
>
)
{}
with
*
visit
::
default_visitor
()
}));
}
src/rustc/middle/typeck/writeback.rs
0 → 100644
浏览文件 @
26dc48d6
// Type resolution: the phase that finds all the types in the AST with
// unresolved type variables and replaces "ty_var" types with their
// substitutions.
export
resolve_type_vars_in_fn
;
export
resolve_type_vars_in_expr
;
fn
resolve_type_vars_in_type
(
fcx
:
@
fn_ctxt
,
sp
:
span
,
typ
:
ty
::
t
)
->
option
<
ty
::
t
>
{
if
!
ty
::
type_needs_infer
(
typ
)
{
ret
some
(
typ
);
}
alt
infer
::
resolve_deep
(
fcx
.infcx
,
typ
,
true
)
{
result
::
ok
(
new_type
)
{
ret
some
(
new_type
);
}
result
::
err
(
e
)
{
if
!
fcx
.ccx.tcx.sess
.has_errors
()
{
fcx
.ccx.tcx.sess
.span_err
(
sp
,
#
fmt
[
"cannot determine a type
\
for this expression: %s"
,
infer
::
fixup_err_to_str
(
e
)])
}
ret
none
;
}
}
}
fn
resolve_type_vars_for_node
(
wbcx
:
wb_ctxt
,
sp
:
span
,
id
:
ast
::
node_id
)
->
option
<
ty
::
t
>
{
let
fcx
=
wbcx
.fcx
,
tcx
=
fcx
.ccx.tcx
;
let
n_ty
=
fcx
.node_ty
(
id
);
alt
resolve_type_vars_in_type
(
fcx
,
sp
,
n_ty
)
{
none
{
wbcx
.success
=
false
;
ret
none
;
}
some
(
t
)
{
#
debug
[
"resolve_type_vars_for_node(id=%d, n_ty=%s, t=%s)"
,
id
,
ty_to_str
(
tcx
,
n_ty
),
ty_to_str
(
tcx
,
t
)];
write_ty_to_tcx
(
tcx
,
id
,
t
);
alt
fcx
.opt_node_ty_substs
(
id
)
{
some
(
substs
)
{
let
mut
new_tps
=
[];
for
substs
.tps.each
{|
subst
|
alt
resolve_type_vars_in_type
(
fcx
,
sp
,
subst
)
{
some
(
t
)
{
new_tps
+=
[
t
];
}
none
{
wbcx
.success
=
false
;
ret
none
;
}
}
}
write_substs_to_tcx
(
tcx
,
id
,
new_tps
);
}
none
{}
}
ret
some
(
t
);
}
}
}
fn
maybe_resolve_type_vars_for_node
(
wbcx
:
wb_ctxt
,
sp
:
span
,
id
:
ast
::
node_id
)
->
option
<
ty
::
t
>
{
if
wbcx
.fcx.node_types
.contains_key
(
id
as
uint
)
{
resolve_type_vars_for_node
(
wbcx
,
sp
,
id
)
}
else
{
none
}
}
type
wb_ctxt
=
// As soon as we hit an error we have to stop resolving
// the entire function
{
fcx
:
@
fn_ctxt
,
mut
success
:
bool
};
type
wb_vt
=
visit
::
vt
<
wb_ctxt
>
;
fn
visit_stmt
(
s
:
@
ast
::
stmt
,
wbcx
:
wb_ctxt
,
v
:
wb_vt
)
{
if
!
wbcx
.success
{
ret
;
}
resolve_type_vars_for_node
(
wbcx
,
s
.span
,
ty
::
stmt_node_id
(
s
));
visit
::
visit_stmt
(
s
,
wbcx
,
v
);
}
fn
visit_expr
(
e
:
@
ast
::
expr
,
wbcx
:
wb_ctxt
,
v
:
wb_vt
)
{
if
!
wbcx
.success
{
ret
;
}
resolve_type_vars_for_node
(
wbcx
,
e
.span
,
e
.id
);
alt
e
.node
{
ast
::
expr_fn
(
_
,
decl
,
_
,
_
)
|
ast
::
expr_fn_block
(
decl
,
_
,
_
)
{
vec
::
iter
(
decl
.inputs
)
{|
input
|
let
r_ty
=
resolve_type_vars_for_node
(
wbcx
,
e
.span
,
input
.id
);
// Just in case we never constrained the mode to anything,
// constrain it to the default for the type in question.
alt
(
r_ty
,
input
.mode
)
{
(
some
(
t
),
ast
::
infer
(
_
))
{
let
tcx
=
wbcx
.fcx.ccx.tcx
;
let
m_def
=
ty
::
default_arg_mode_for_ty
(
t
);
ty
::
set_default_mode
(
tcx
,
input
.mode
,
m_def
);
}
_
{}
}
}
}
ast
::
expr_new
(
_
,
alloc_id
,
_
)
{
resolve_type_vars_for_node
(
wbcx
,
e
.span
,
alloc_id
);
}
ast
::
expr_binary
(
_
,
_
,
_
)
|
ast
::
expr_unary
(
_
,
_
)
|
ast
::
expr_assign_op
(
_
,
_
,
_
)
|
ast
::
expr_index
(
_
,
_
)
{
maybe_resolve_type_vars_for_node
(
wbcx
,
e
.span
,
ast_util
::
op_expr_callee_id
(
e
));
}
_
{
}
}
visit
::
visit_expr
(
e
,
wbcx
,
v
);
}
fn
visit_block
(
b
:
ast
::
blk
,
wbcx
:
wb_ctxt
,
v
:
wb_vt
)
{
if
!
wbcx
.success
{
ret
;
}
resolve_type_vars_for_node
(
wbcx
,
b
.span
,
b
.node.id
);
visit
::
visit_block
(
b
,
wbcx
,
v
);
}
fn
visit_pat
(
p
:
@
ast
::
pat
,
wbcx
:
wb_ctxt
,
v
:
wb_vt
)
{
if
!
wbcx
.success
{
ret
;
}
resolve_type_vars_for_node
(
wbcx
,
p
.span
,
p
.id
);
#
debug
[
"Type for pattern binding %s (id %d) resolved to %s"
,
pat_to_str
(
p
),
p
.id
,
wbcx
.fcx
.ty_to_str
(
ty
::
node_id_to_type
(
wbcx
.fcx.ccx.tcx
,
p
.id
))];
visit
::
visit_pat
(
p
,
wbcx
,
v
);
}
fn
visit_local
(
l
:
@
ast
::
local
,
wbcx
:
wb_ctxt
,
v
:
wb_vt
)
{
if
!
wbcx
.success
{
ret
;
}
let
var_id
=
lookup_local
(
wbcx
.fcx
,
l
.span
,
l
.node.id
);
alt
infer
::
resolve_deep_var
(
wbcx
.fcx.infcx
,
var_id
,
true
)
{
result
::
ok
(
lty
)
{
#
debug
[
"Type for local %s (id %d) resolved to %s"
,
pat_to_str
(
l
.node.pat
),
l
.node.id
,
wbcx
.fcx
.ty_to_str
(
lty
)];
write_ty_to_tcx
(
wbcx
.fcx.ccx.tcx
,
l
.node.id
,
lty
);
}
result
::
err
(
e
)
{
wbcx
.fcx.ccx.tcx.sess
.span_err
(
l
.span
,
#
fmt
[
"cannot determine a type
\
for this local variable: %s"
,
infer
::
fixup_err_to_str
(
e
)]);
wbcx
.success
=
false
;
}
}
visit
::
visit_local
(
l
,
wbcx
,
v
);
}
fn
visit_item
(
_
item
:
@
ast
::
item
,
_
wbcx
:
wb_ctxt
,
_
v
:
wb_vt
)
{
// Ignore items
}
fn
resolve_type_vars_in_expr
(
fcx
:
@
fn_ctxt
,
e
:
@
ast
::
expr
)
->
bool
{
let
wbcx
=
{
fcx
:
fcx
,
mut
success
:
true
};
let
visit
=
visit
::
mk_vt
(
@
{
visit_item
:
visit_item
,
visit_stmt
:
visit_stmt
,
visit_expr
:
visit_expr
,
visit_block
:
visit_block
,
visit_pat
:
visit_pat
,
visit_local
:
visit_local
with
*
visit
::
default_visitor
()});
visit
.visit_expr
(
e
,
wbcx
,
visit
);
ret
wbcx
.success
;
}
fn
resolve_type_vars_in_fn
(
fcx
:
@
fn_ctxt
,
decl
:
ast
::
fn_decl
,
blk
:
ast
::
blk
)
->
bool
{
let
wbcx
=
{
fcx
:
fcx
,
mut
success
:
true
};
let
visit
=
visit
::
mk_vt
(
@
{
visit_item
:
visit_item
,
visit_stmt
:
visit_stmt
,
visit_expr
:
visit_expr
,
visit_block
:
visit_block
,
visit_pat
:
visit_pat
,
visit_local
:
visit_local
with
*
visit
::
default_visitor
()});
visit
.visit_block
(
blk
,
wbcx
,
visit
);
for
decl
.inputs.each
{|
arg
|
resolve_type_vars_for_node
(
wbcx
,
arg
.ty.span
,
arg
.id
);
}
ret
wbcx
.success
;
}
src/rustc/rustc.rc
浏览文件 @
26dc48d6
...
...
@@ -52,7 +52,12 @@ mod middle {
mod
infer
;
mod
ast_map
;
mod
resolve
;
mod
typeck
;
mod
typeck
{
mod
astconv
;
mod
collect
;
mod
vtable
;
mod
writeback
;
}
mod
check_loop
;
mod
check_alt
;
mod
check_const
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录