Skip to content

Commit 63f74f3

Browse files
committedJul 28, 2011
Remove vestiges of "layers", insert skeletal do-nothing "kind" pass plus cached calculation of kind for each type.
1 parent 04611a3 commit 63f74f3

File tree

6 files changed

+265
-19
lines changed

6 files changed

+265
-19
lines changed
 

‎src/comp/driver/rustc.rs

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import front::attr;
1111
import middle::trans;
1212
import middle::resolve;
1313
import middle::freevars;
14+
import middle::kind;
1415
import middle::ty;
1516
import middle::typeck;
1617
import middle::tstate::ck;
@@ -147,6 +148,8 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
147148
}
148149
time(time_passes, "alias checking",
149150
bind middle::alias::check_crate(ty_cx, crate));
151+
time[()](time_passes, "kind checking",
152+
bind kind::check_crate(ty_cx, crate));
150153
let llmod =
151154
time[llvm::llvm::ModuleRef](time_passes, "translation",
152155
bind trans::trans_crate(sess, crate,

‎src/comp/middle/kind.rs

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* Kinds are types of type.
3+
*
4+
* Every type has a kind. Every type parameter has a set of kind-capabilities
5+
* saying which kind of type may be passed as the parameter.
6+
*
7+
* The kinds are based on two capabilities: copy and send. These may each be
8+
* present or absent, though only three of the four combinations can actually
9+
* occur:
10+
*
11+
*
12+
*
13+
* COPY + SEND = "Unique": no shared substructures or pins, only
14+
* interiors and ~ boxes.
15+
*
16+
* COPY + NOSEND = "Shared": structures containing @, fixed to the local
17+
* task heap/pool.
18+
*
19+
* NOCOPY + NOSEND = "Pinned": structures containing resources or
20+
* by-alias closures as interior or
21+
* uniquely-boxed members.
22+
*
23+
* NOCOPY + SEND = -- : no types are like this.
24+
*
25+
*
26+
* Since this forms a lattice, we denote the capabilites in terms of a
27+
* worst-case requirement. That is, if your function needs to copy-and-send
28+
* your T, you write fn<~T>(...). If you need to copy but not send, you write
29+
* fn<@T>(...). And if you need neither -- can work with any sort of pinned
30+
* data at all -- then you write fn<T>(...).
31+
*
32+
*
33+
* Most types are unique or shared. Other possible name combinations for these
34+
* two: (tree, graph; pruned, pooled; message, local; owned, common) are
35+
* plausible but nothing stands out as completely pithy-and-obvious.
36+
*
37+
* Resources cannot be copied or sent; they're pinned. They can't be copied
38+
* because it would interfere with destruction (multiple destruction?) They
39+
* cannot be sent because we don't want to oblige the communication system to
40+
* run destructors in some weird limbo context of messages-in-transit. It
41+
* should always be ok to just free messages it's dropping.
42+
*
43+
* Note that obj~ and fn~ -- those that capture a unique environment -- can be
44+
* sent, so satisfy ~T. So can plain obj and fn.
45+
*
46+
*
47+
* Further notes on copying and moving; sending is accomplished by calling a
48+
* move-in operator on something constrained to a unique type ~T.
49+
*
50+
*
51+
* COPYING:
52+
* --------
53+
*
54+
* A copy is made any time you pass-by-value or execute the = operator in a
55+
* non-init expression.
56+
*
57+
* ~ copies deep
58+
* @ copies shallow
59+
* pinned values (pinned resources, alias-closures) can't be copied
60+
* all other interiors copy shallow
61+
*
62+
* MOVING:
63+
* -------
64+
*
65+
* A move is made any time you pass-by-move (that is, with 'move' mode) or
66+
* execute the <- operator.
67+
*
68+
* Anything you can copy, you can move. Move is (semantically) just
69+
* shallow-copy + deinit. Note that: ~ moves shallow even though it copies
70+
* deep. Move is the operator that lets ~ copy shallow: by pairing it with a
71+
* deinit.
72+
*
73+
*/
74+
75+
76+
import syntax::ast;
77+
import syntax::walk;
78+
79+
import ast::kind;
80+
import ast::kind_unique;
81+
import ast::kind_shared;
82+
import ast::kind_pinned;
83+
84+
fn kind_lteq(a: kind, b: kind) -> bool {
85+
alt a {
86+
kind_pinned. { true }
87+
kind_shared. { b != kind_pinned }
88+
kind_unique. { b == kind_unique }
89+
}
90+
}
91+
92+
fn lower_kind(a: kind, b: kind) -> kind {
93+
if kind_lteq(a, b) { a } else { b }
94+
}
95+
96+
fn kind_to_str(k: kind) -> str {
97+
alt k {
98+
ast::kind_pinned. { "pinned" }
99+
ast::kind_unique. { "unique" }
100+
ast::kind_shared. { "shared" }
101+
}
102+
}
103+
104+
fn check_expr(tcx: &ty::ctxt, e: &@ast::expr) {
105+
let t = ty::expr_ty(tcx, e);
106+
let k = ty::type_kind(tcx, t);
107+
log #fmt("%s type: %s", kind_to_str(k),
108+
util::ppaux::ty_to_str(tcx, t));
109+
}
110+
111+
fn check_crate(tcx: &ty::ctxt, crate: &@ast::crate) {
112+
let visit =
113+
{visit_expr_pre: bind check_expr(tcx, _)
114+
with walk::default_visitor()};
115+
walk::walk_crate(visit, *crate);
116+
tcx.sess.abort_if_errors();
117+
}
118+
119+
//
120+
// Local Variables:
121+
// mode: rust
122+
// fill-column: 78;
123+
// indent-tabs-mode: nil
124+
// c-basic-offset: 4
125+
// buffer-file-coding-system: utf-8-unix
126+
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
127+
// End:
128+
//

‎src/comp/middle/ty.rs

+128-2
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ export ty_fn_args;
152152
export type_constr;
153153
export type_contains_params;
154154
export type_contains_vars;
155+
export type_kind;
155156
export type_err;
156157
export type_err_to_str;
157158
export type_has_dynamic_size;
@@ -216,6 +217,7 @@ type ctxt =
216217
rcache: creader_cache,
217218
short_names_cache: hashmap[t, str],
218219
has_pointer_cache: hashmap[t, bool],
220+
kind_cache: hashmap[t, ast::kind],
219221
owns_heap_mem_cache: hashmap[t, bool],
220222
ast_ty_to_ty_cache: hashmap[@ast::ty, option::t[t]]};
221223

@@ -409,6 +411,7 @@ fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
409411
rcache: mk_rcache(),
410412
short_names_cache: map::mk_hashmap(ty::hash_ty, ty::eq_ty),
411413
has_pointer_cache: map::mk_hashmap(ty::hash_ty, ty::eq_ty),
414+
kind_cache: map::mk_hashmap(ty::hash_ty, ty::eq_ty),
412415
owns_heap_mem_cache: map::mk_hashmap(ty::hash_ty, ty::eq_ty),
413416
ast_ty_to_ty_cache: map::mk_hashmap(ast::hash_ty, ast::eq_ty)};
414417
populate_type_store(cx);
@@ -981,7 +984,10 @@ fn type_has_pointers(cx: &ctxt, ty: &t) -> bool {
981984
ty_native(_) {/* no-op */ }
982985
ty_rec(flds) {
983986
for f: field in flds {
984-
if type_has_pointers(cx, f.mt.ty) { result = true; }
987+
if type_has_pointers(cx, f.mt.ty) {
988+
result = true;
989+
break;
990+
}
985991
}
986992
}
987993
ty_tag(did, tps) {
@@ -990,8 +996,12 @@ fn type_has_pointers(cx: &ctxt, ty: &t) -> bool {
990996
for aty: t in variant.args {
991997
// Perform any type parameter substitutions.
992998
let arg_ty = substitute_type_params(cx, tps, aty);
993-
if type_has_pointers(cx, arg_ty) { result = true; }
999+
if type_has_pointers(cx, arg_ty) {
1000+
result = true;
1001+
break;
1002+
}
9941003
}
1004+
if result { break; }
9951005
}
9961006
}
9971007
ty_res(did, inner, tps) {
@@ -1005,6 +1015,122 @@ fn type_has_pointers(cx: &ctxt, ty: &t) -> bool {
10051015
ret result;
10061016
}
10071017

1018+
fn type_kind(cx: &ctxt, ty: &t) -> ast::kind {
1019+
alt cx.kind_cache.find(ty) {
1020+
some(result) { ret result; }
1021+
none. {/* fall through */ }
1022+
}
1023+
1024+
let result = ast::kind_unique;
1025+
1026+
// Insert a default in case we loop back on self recursively.
1027+
cx.kind_cache.insert(ty, result);
1028+
1029+
alt struct(cx, ty) {
1030+
1031+
// Scalar types are unique-kind, no substructure.
1032+
ty_nil. | ty_bot. | ty_bool. | ty_int. | ty_uint. | ty_float.
1033+
| ty_machine(_) | ty_char. | ty_native(_) {
1034+
// no-op
1035+
}
1036+
1037+
// A handful of other built-in are unique too.
1038+
ty_type. | ty_istr. | ty_native_fn(_, _, _) {
1039+
// no-op
1040+
}
1041+
1042+
// Those things with refcounts-to-interior are just shared.
1043+
ty_str. | ty_task. {
1044+
result = kind_shared;
1045+
}
1046+
1047+
// FIXME: obj is broken for now, since we aren't asserting
1048+
// anything about its fields.
1049+
ty_obj(_) { result = kind_shared; }
1050+
1051+
// FIXME: the environment capture mode is not fully encoded
1052+
// here yet, leading to weirdness around closure.
1053+
ty_fn(proto, _, _, _, _) {
1054+
result = alt proto {
1055+
ast::proto_block. { ast::kind_pinned }
1056+
ast::proto_closure. { ast::kind_shared }
1057+
_ { ast::kind_unique }
1058+
}
1059+
}
1060+
1061+
// Those with refcounts-to-inner are the lower of their
1062+
// inner and shared.
1063+
ty_box(mt) | ty_vec(mt) {
1064+
result = kind::lower_kind(ast::kind_shared,
1065+
type_kind(cx, mt.ty));
1066+
1067+
}
1068+
1069+
// FIXME: remove ports. Ports currently contribute 'shared'
1070+
ty_port(t) {
1071+
result = kind::lower_kind(ast::kind_shared,
1072+
type_kind(cx, t));
1073+
}
1074+
1075+
// FIXME: remove chans. Chans currently contribute only
1076+
// their inner.
1077+
ty_chan(t) {
1078+
result = type_kind(cx, t);
1079+
}
1080+
1081+
// Pointers and unique boxes / vecs lower to whatever they point to.
1082+
ty_ptr(tm) | ty_ivec(tm) {
1083+
result = type_kind(cx, tm.ty);
1084+
}
1085+
1086+
// Records lower to the lowest of their members.
1087+
ty_rec(flds) {
1088+
for f: field in flds {
1089+
result = kind::lower_kind(result, type_kind(cx, f.mt.ty));
1090+
if result == ast::kind_pinned { break; }
1091+
}
1092+
}
1093+
1094+
// Tags lower to the lowest of their variants.
1095+
ty_tag(did, tps) {
1096+
let variants = tag_variants(cx, did);
1097+
for variant: variant_info in variants {
1098+
for aty: t in variant.args {
1099+
// Perform any type parameter substitutions.
1100+
let arg_ty = substitute_type_params(cx, tps, aty);
1101+
result = kind::lower_kind(result, type_kind(cx, arg_ty));
1102+
if result == ast::kind_pinned { break; }
1103+
}
1104+
if result == ast::kind_pinned { break; }
1105+
}
1106+
}
1107+
1108+
// Resources are always pinned.
1109+
ty_res(did, inner, tps) {
1110+
result = ast::kind_pinned;
1111+
}
1112+
1113+
ty_var(_) { fail; }
1114+
1115+
ty_param(_) {
1116+
// FIXME: this should contribute the kind-bound of the typaram,
1117+
// when those exist.
1118+
}
1119+
1120+
ty_constr(t, _) {
1121+
result = type_kind(cx, t);
1122+
}
1123+
1124+
_ {
1125+
cx.sess.bug("missed case: " + ty_to_str(cx, ty));
1126+
}
1127+
1128+
}
1129+
1130+
cx.kind_cache.insert(ty, result);
1131+
ret result;
1132+
}
1133+
10081134

10091135
// FIXME: should we just return true for native types in
10101136
// type_is_scalar?

‎src/comp/rustc.rc

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ mod middle {
2727
mod typeck;
2828
mod check_alt;
2929
mod alias;
30+
mod kind;
3031
mod freevars;
3132

3233
mod tstate {

‎src/comp/syntax/ast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ fn pat_id_map(pat: &@pat) -> pat_id_map {
157157

158158
tag mutability { mut; imm; maybe_mut; }
159159

160-
tag layer { layer_value; layer_state; layer_gc; }
160+
tag kind { kind_pinned; kind_shared; kind_unique; }
161161

162162
tag _auth { auth_unsafe; }
163163

0 commit comments

Comments
 (0)