Skip to content

Commit 7512284

Browse files
committed
further modularization of typeck, add comments
1 parent 8cc596c commit 7512284

File tree

9 files changed

+3486
-3398
lines changed

9 files changed

+3486
-3398
lines changed

src/rustc/middle/typeck.rs

Lines changed: 62 additions & 3111 deletions
Large diffs are not rendered by default.

src/rustc/middle/typeck/astconv.rs

Lines changed: 48 additions & 256 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
#[doc = "
22
3-
Conversion from AST representation of types to the ty.rs representation.
4-
5-
The main routine here is `ast_ty_to_ty()`: each use is parameterized
6-
by an instance of `ast_conv` and a `region_scope`.
7-
8-
The `ast_conv` interface is the conversion context. It has two
9-
implementations, one for the crate context and one for the function
10-
context. The main purpose is to provide the `get_item_ty()` hook
11-
which looks up the type of an item by its def-id. This can be done in
12-
two ways: in the initial phase, when a crate context is provided, this
13-
will potentially trigger a call to `ty_of_item()`. Later, when a
14-
function context is used, this will simply be a lookup.
3+
Conversion from AST representation of types to the ty.rs
4+
representation. The main routine here is `ast_ty_to_ty()`: each use
5+
is parameterized by an instance of `ast_conv` and a `region_scope`.
6+
7+
The parameterization of `ast_ty_to_ty()` is because it behaves
8+
somewhat differently during the collect and check phases, particularly
9+
with respect to looking up the types of top-level items. In the
10+
collect phase, the crate context is used as the `ast_conv` instance;
11+
in this phase, the `get_item_ty()` function triggers a recursive call
12+
to `ty_of_item()` (note that `ast_ty_to_ty()` will detect recursive
13+
types and report an error). In the check phase, when the @fn_ctxt is
14+
used as the `ast_conv`, `get_item_ty()` just looks up the item type in
15+
`tcx.tcache`.
1516
1617
The `region_scope` interface controls how region references are
1718
handled. It has two methods which are used to resolve anonymous
@@ -21,8 +22,30 @@ commonly you want either `empty_rscope`, which permits only the static
2122
region, or `type_rscope`, which permits the self region if the type in
2223
question is parameterized by a region.
2324
25+
Unlike the `ast_conv` iface, the region scope can change as we descend
26+
the type. This is to accommodate the fact that (a) fn types are binding
27+
scopes and (b) the default region may change. To understand case (a),
28+
consider something like:
29+
30+
type foo = { x: &a.int, y: fn(&a.int) }
31+
32+
The type of `x` is an error because there is no region `a` in scope.
33+
In the type of `y`, however, region `a` is considered a bound region
34+
as it does not already appear in scope.
35+
36+
Case (b) says that if you have a type:
37+
type foo/& = ...;
38+
type bar = fn(&foo, &a.foo)
39+
The fully expanded version of type bar is:
40+
type bar = fn(&foo/&, &a.foo/&a)
41+
Note that the self region for the `foo` defaulted to `&` in the first
42+
case but `&a` in the second. Basically, defaults that appear inside
43+
an rptr (`&r.T`) use the region `r` that appears in the rptr.
44+
2445
"];
2546

47+
import check::fn_ctxt;
48+
2649
iface ast_conv {
2750
fn tcx() -> ty::ctxt;
2851
fn ccx() -> @crate_ctxt;
@@ -32,48 +55,6 @@ iface ast_conv {
3255
fn ty_infer(span: span) -> ty::t;
3356
}
3457

35-
impl of ast_conv for @crate_ctxt {
36-
fn tcx() -> ty::ctxt { self.tcx }
37-
fn ccx() -> @crate_ctxt { self }
38-
39-
fn get_item_ty(id: ast::def_id) -> ty::ty_param_bounds_and_ty {
40-
if id.crate != ast::local_crate {
41-
csearch::get_type(self.tcx, id)
42-
} else {
43-
alt self.tcx.items.find(id.node) {
44-
some(ast_map::node_item(item, _)) {
45-
ty_of_item(self, item)
46-
}
47-
some(ast_map::node_native_item(native_item, _, _)) {
48-
ty_of_native_item(self, native_item)
49-
}
50-
x {
51-
self.tcx.sess.bug(#fmt["unexpected sort of item \
52-
in get_item_ty(): %?", x]);
53-
}
54-
}
55-
}
56-
}
57-
58-
fn ty_infer(span: span) -> ty::t {
59-
self.tcx.sess.span_bug(span,
60-
"found `ty_infer` in unexpected place");
61-
}
62-
}
63-
64-
impl of ast_conv for @fn_ctxt {
65-
fn tcx() -> ty::ctxt { self.ccx.tcx }
66-
fn ccx() -> @crate_ctxt { self.ccx }
67-
68-
fn get_item_ty(id: ast::def_id) -> ty::ty_param_bounds_and_ty {
69-
ty::lookup_item_type(self.tcx(), id)
70-
}
71-
72-
fn ty_infer(_span: span) -> ty::t {
73-
self.next_ty_var()
74-
}
75-
}
76-
7758
iface region_scope {
7859
fn anon_region() -> result<ty::region, str>;
7960
fn named_region(id: str) -> result<ty::region, str>;
@@ -112,23 +93,6 @@ impl of region_scope for type_rscope {
11293
}
11394
}
11495

115-
impl of region_scope for @fn_ctxt {
116-
fn anon_region() -> result<ty::region, str> {
117-
result::ok(self.next_region_var())
118-
}
119-
fn named_region(id: str) -> result<ty::region, str> {
120-
empty_rscope.named_region(id).chain_err { |_e|
121-
alt self.in_scope_regions.find(ty::br_named(id)) {
122-
some(r) { result::ok(r) }
123-
none if id == "blk" { self.block_region() }
124-
none {
125-
result::err(#fmt["named region `%s` not in scope here", id])
126-
}
127-
}
128-
}
129-
}
130-
}
131-
13296
enum anon_rscope = {anon: ty::region, base: region_scope};
13397
fn in_anon_rscope<RS: region_scope copy>(self: RS, r: ty::region)
13498
-> @anon_rscope {
@@ -159,6 +123,19 @@ impl of region_scope for @binding_rscope {
159123
}
160124
}
161125

126+
fn get_region_reporting_err(tcx: ty::ctxt,
127+
span: span,
128+
res: result<ty::region, str>) -> ty::region {
129+
130+
alt res {
131+
result::ok(r) { r }
132+
result::err(e) {
133+
tcx.sess.span_err(span, e);
134+
ty::re_static
135+
}
136+
}
137+
}
138+
162139
fn ast_region_to_region<AC: ast_conv, RS: region_scope>(
163140
self: AC, rscope: RS, span: span, a_r: @ast::region) -> ty::region {
164141

@@ -233,36 +210,6 @@ fn ast_path_to_ty<AC: ast_conv, RS: region_scope copy>(
233210
ret {substs: substs, ty: ty};
234211
}
235212

236-
/*
237-
Instantiates the path for the given iface reference, assuming that
238-
it's bound to a valid iface type. Returns the def_id for the defining
239-
iface. Fails if the type is a type other than an iface type.
240-
*/
241-
fn instantiate_iface_ref(ccx: @crate_ctxt, t: @ast::iface_ref,
242-
rp: ast::region_param)
243-
-> (ast::def_id, ty_param_substs_and_ty) {
244-
245-
let sp = t.path.span, err = "can only implement interface types",
246-
sess = ccx.tcx.sess;
247-
248-
let rscope = type_rscope(rp);
249-
250-
alt lookup_def_tcx(ccx.tcx, t.path.span, t.id) {
251-
ast::def_ty(t_id) {
252-
let tpt = ast_path_to_ty(ccx, rscope, t_id, t.path, t.id);
253-
alt ty::get(tpt.ty).struct {
254-
ty::ty_iface(*) {
255-
(t_id, tpt)
256-
}
257-
_ { sess.span_fatal(sp, err); }
258-
}
259-
}
260-
_ {
261-
sess.span_fatal(sp, err);
262-
}
263-
}
264-
}
265-
266213
const NO_REGIONS: uint = 1u;
267214
const NO_TPS: uint = 2u;
268215

@@ -474,103 +421,6 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy>(
474421
ret typ;
475422
}
476423

477-
fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
478-
-> ty::ty_param_bounds_and_ty {
479-
480-
let def_id = local_def(it.id);
481-
let tcx = ccx.tcx;
482-
alt tcx.tcache.find(def_id) {
483-
some(tpt) { ret tpt; }
484-
_ {}
485-
}
486-
alt it.node {
487-
ast::item_const(t, _) {
488-
let typ = ccx.to_ty(empty_rscope, t);
489-
let tpt = no_params(typ);
490-
tcx.tcache.insert(local_def(it.id), tpt);
491-
ret tpt;
492-
}
493-
ast::item_fn(decl, tps, _) {
494-
let bounds = ty_param_bounds(ccx, tps);
495-
let tofd = ty_of_fn_decl(ccx, empty_rscope, ast::proto_bare,
496-
decl, none);
497-
let tpt = {bounds: bounds,
498-
rp: ast::rp_none, // functions do not have a self
499-
ty: ty::mk_fn(ccx.tcx, tofd)};
500-
ccx.tcx.tcache.insert(local_def(it.id), tpt);
501-
ret tpt;
502-
}
503-
ast::item_ty(t, tps, rp) {
504-
alt tcx.tcache.find(local_def(it.id)) {
505-
some(tpt) { ret tpt; }
506-
none { }
507-
}
508-
509-
let tpt = {
510-
let ty = {
511-
let t0 = ccx.to_ty(type_rscope(rp), t);
512-
// Do not associate a def id with a named, parameterized type
513-
// like "foo<X>". This is because otherwise ty_to_str will
514-
// print the name as merely "foo", as it has no way to
515-
// reconstruct the value of X.
516-
if !vec::is_empty(tps) { t0 } else {
517-
ty::mk_with_id(tcx, t0, def_id)
518-
}
519-
};
520-
{bounds: ty_param_bounds(ccx, tps), rp: rp, ty: ty}
521-
};
522-
523-
check_bounds_are_used(ccx, t.span, tps, rp, tpt.ty);
524-
525-
tcx.tcache.insert(local_def(it.id), tpt);
526-
ret tpt;
527-
}
528-
ast::item_res(decl, tps, _, _, _, rp) {
529-
let {bounds, substs} = mk_substs(ccx, tps, rp);
530-
let t_arg = ty_of_arg(ccx, type_rscope(rp),
531-
decl.inputs[0], none);
532-
let t = ty::mk_res(tcx, local_def(it.id), t_arg.ty, substs);
533-
let t_res = {bounds: bounds, rp: rp, ty: t};
534-
tcx.tcache.insert(local_def(it.id), t_res);
535-
ret t_res;
536-
}
537-
ast::item_enum(_, tps, rp) {
538-
// Create a new generic polytype.
539-
let {bounds, substs} = mk_substs(ccx, tps, rp);
540-
let t = ty::mk_enum(tcx, local_def(it.id), substs);
541-
let tpt = {bounds: bounds, rp: rp, ty: t};
542-
tcx.tcache.insert(local_def(it.id), tpt);
543-
ret tpt;
544-
}
545-
ast::item_iface(tps, rp, ms) {
546-
let {bounds, substs} = mk_substs(ccx, tps, rp);
547-
let t = ty::mk_iface(tcx, local_def(it.id), substs);
548-
let tpt = {bounds: bounds, rp: rp, ty: t};
549-
tcx.tcache.insert(local_def(it.id), tpt);
550-
ret tpt;
551-
}
552-
ast::item_class(tps, _, _, _, _, rp) {
553-
let {bounds,substs} = mk_substs(ccx, tps, rp);
554-
let t = ty::mk_class(tcx, local_def(it.id), substs);
555-
let tpt = {bounds: bounds, rp: rp, ty: t};
556-
tcx.tcache.insert(local_def(it.id), tpt);
557-
ret tpt;
558-
}
559-
ast::item_impl(*) | ast::item_mod(_) |
560-
ast::item_native_mod(_) { fail; }
561-
}
562-
}
563-
564-
fn ty_of_native_item(ccx: @crate_ctxt, it: @ast::native_item)
565-
-> ty::ty_param_bounds_and_ty {
566-
alt it.node {
567-
ast::native_item_fn(fn_decl, params) {
568-
ret ty_of_native_fn_decl(ccx, fn_decl, params,
569-
local_def(it.id));
570-
}
571-
}
572-
}
573-
574424
fn ty_of_arg<AC: ast_conv, RS: region_scope copy>(
575425
self: AC, rscope: RS, a: ast::arg,
576426
expected_ty: option<ty::arg>) -> ty::arg {
@@ -651,61 +501,3 @@ fn ty_of_fn_decl<AC: ast_conv, RS: region_scope copy>(
651501
}
652502

653503

654-
fn ty_param_bounds(ccx: @crate_ctxt,
655-
params: [ast::ty_param]) -> @[ty::param_bounds] {
656-
657-
fn compute_bounds(ccx: @crate_ctxt,
658-
param: ast::ty_param) -> ty::param_bounds {
659-
@vec::flat_map(*param.bounds) { |b|
660-
alt b {
661-
ast::bound_send { [ty::bound_send] }
662-
ast::bound_copy { [ty::bound_copy] }
663-
ast::bound_iface(t) {
664-
let ity = ast_ty_to_ty(ccx, empty_rscope, t);
665-
alt ty::get(ity).struct {
666-
ty::ty_iface(*) {
667-
[ty::bound_iface(ity)]
668-
}
669-
_ {
670-
ccx.tcx.sess.span_err(
671-
t.span, "type parameter bounds must be \
672-
interface types");
673-
[]
674-
}
675-
}
676-
}
677-
}
678-
}
679-
}
680-
681-
@params.map { |param|
682-
alt ccx.tcx.ty_param_bounds.find(param.id) {
683-
some(bs) { bs }
684-
none {
685-
let bounds = compute_bounds(ccx, param);
686-
ccx.tcx.ty_param_bounds.insert(param.id, bounds);
687-
bounds
688-
}
689-
}
690-
}
691-
}
692-
693-
fn ty_of_native_fn_decl(ccx: @crate_ctxt,
694-
decl: ast::fn_decl,
695-
ty_params: [ast::ty_param],
696-
def_id: ast::def_id) -> ty::ty_param_bounds_and_ty {
697-
698-
let bounds = ty_param_bounds(ccx, ty_params);
699-
let rb = in_binding_rscope(empty_rscope);
700-
let input_tys = decl.inputs.map { |a| ty_of_arg(ccx, rb, a, none) };
701-
let output_ty = ast_ty_to_ty(ccx, rb, decl.output);
702-
703-
let t_fn = ty::mk_fn(ccx.tcx, {proto: ast::proto_bare,
704-
inputs: input_tys,
705-
output: output_ty,
706-
ret_style: ast::return_val,
707-
constraints: []});
708-
let tpt = {bounds: bounds, rp: ast::rp_none, ty: t_fn};
709-
ccx.tcx.tcache.insert(def_id, tpt);
710-
ret tpt;
711-
}

0 commit comments

Comments
 (0)