Skip to content

Commit 8bd3683

Browse files
committed
---
yaml --- r: 14271 b: refs/heads/try c: 6c9d95a h: refs/heads/master i: 14269: 84f985e 14267: eaeb69a 14263: 2c5ad5e 14255: 5ee4033 14239: c87d1d9 14207: f09eb4b v: v3
1 parent b9de081 commit 8bd3683

File tree

8 files changed

+91
-62
lines changed

8 files changed

+91
-62
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
refs/heads/master: 61b1875c16de39c166b0f4d54bba19f9c6777d1a
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 4a81779abd786ff22d71434c6d9a5917ea4cdfff
5-
refs/heads/try: 9caca02dac6bb9318aaa2f9ac52868b8ccead3e0
5+
refs/heads/try: 6c9d95a9a0f82895559dc1dae6300ee14c304d7e
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105

branches/try/src/comp/metadata/csearch.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import driver::session;
99
export get_symbol;
1010
export get_type_param_count;
1111
export lookup_defs;
12+
export lookup_method_purity;
1213
export get_enum_variants;
1314
export get_impls_for_mod;
1415
export get_iface_methods;
@@ -35,6 +36,15 @@ fn lookup_defs(cstore: cstore::cstore, cnum: ast::crate_num,
3536
ret result;
3637
}
3738

39+
fn lookup_method_purity(cstore: cstore::cstore, did: ast::def_id)
40+
-> ast::purity {
41+
let cdata = cstore::get_crate_data(cstore, did.crate).data;
42+
alt decoder::lookup_def(did.crate, cdata, did) {
43+
ast::def_fn(_, p) { p }
44+
_ { fail; }
45+
}
46+
}
47+
3848
fn resolve_path(cstore: cstore::cstore, cnum: ast::crate_num,
3949
path: [ast::ident]) ->
4050
[(ast::crate_num, @[u8], ast::def_id)] {

branches/try/src/comp/metadata/decoder.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,12 @@ fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
337337
let fty = alt ty::get(ty).struct { ty::ty_fn(f) { f }
338338
_ { tcx.sess.bug("get_iface_methods: id has non-function type");
339339
} };
340-
result += [{ident: name, tps: bounds, fty: fty}];
340+
result += [{ident: name, tps: bounds, fty: fty,
341+
purity: alt item_family(mth) as char {
342+
'u' { ast::unsafe_fn }
343+
'f' { ast::impure_fn }
344+
'p' { ast::pure_fn }
345+
}}];
341346
}
342347
@result
343348
}

branches/try/src/comp/metadata/encoder.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,10 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
311311
ebml::end_tag(ebml_w);
312312
}
313313

314+
fn purity_fn_family(p: purity) -> char {
315+
alt p { unsafe_fn { 'u' } pure_fn { 'p' } impure_fn { 'f' } }
316+
}
317+
314318
fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
315319
&index: [entry<int>], path: ast_map::path) {
316320
let tcx = ecx.ccx.tcx;
@@ -327,12 +331,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
327331
item_fn(decl, tps, _) {
328332
ebml::start_tag(ebml_w, tag_items_data_item);
329333
encode_def_id(ebml_w, local_def(item.id));
330-
encode_family(ebml_w,
331-
alt decl.purity {
332-
unsafe_fn { 'u' }
333-
pure_fn { 'p' }
334-
impure_fn { 'f' }
335-
} as u8);
334+
encode_family(ebml_w, purity_fn_family(decl.purity) as u8);
336335
encode_type_param_bounds(ebml_w, ecx, tps);
337336
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
338337
encode_symbol(ecx, ebml_w, item.id);
@@ -431,10 +430,9 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
431430
index += [{val: m.id, pos: ebml_w.writer.tell()}];
432431
ebml::start_tag(ebml_w, tag_items_data_item);
433432
encode_def_id(ebml_w, local_def(m.id));
434-
encode_family(ebml_w, 'f' as u8);
433+
encode_family(ebml_w, purity_fn_family(m.decl.purity) as u8);
435434
encode_type_param_bounds(ebml_w, ecx, tps + m.tps);
436-
encode_type(ecx, ebml_w,
437-
node_id_to_type(tcx, m.id));
435+
encode_type(ecx, ebml_w, node_id_to_type(tcx, m.id));
438436
encode_name(ebml_w, m.ident);
439437
encode_symbol(ecx, ebml_w, m.id);
440438
encode_path(ebml_w, impl_path, ast_map::path_name(m.ident));
@@ -454,6 +452,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
454452
encode_name(ebml_w, mty.ident);
455453
encode_type_param_bounds(ebml_w, ecx, ms[i].tps);
456454
encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
455+
encode_family(ebml_w, purity_fn_family(mty.purity) as u8);
457456
ebml::end_tag(ebml_w);
458457
i += 1u;
459458
}

branches/try/src/comp/middle/trans/impl.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ fn trans_method_callee(bcx: @block_ctxt, callee_id: ast::node_id,
8888
}
8989
}
9090
}
91-
typeck::method_iface(off) {
92-
trans_iface_callee(bcx, callee_id, self, off)
91+
typeck::method_iface(iid, off) {
92+
trans_iface_callee(bcx, callee_id, self, iid, off)
9393
}
9494
}
9595
}
@@ -165,8 +165,8 @@ fn trans_monomorphized_callee(bcx: @block_ctxt, callee_id: ast::node_id,
165165
ast_util::local_def(mth.id),
166166
some((tys, sub_origins)));
167167
}
168-
typeck::dict_iface(_) {
169-
ret trans_iface_callee(bcx, callee_id, base, n_method);
168+
typeck::dict_iface(iid) {
169+
ret trans_iface_callee(bcx, callee_id, base, iid, n_method);
170170
}
171171
typeck::dict_param(n_param, n_bound) {
172172
fail "dict_param left in monomorphized function's dict substs";
@@ -186,7 +186,7 @@ fn trans_param_callee(bcx: @block_ctxt, callee_id: ast::node_id,
186186

187187
// Method callee where the dict comes from a boxed iface
188188
fn trans_iface_callee(bcx: @block_ctxt, callee_id: ast::node_id,
189-
base: @ast::expr, n_method: uint)
189+
base: @ast::expr, iface_id: ast::def_id, n_method: uint)
190190
-> lval_maybe_callee {
191191
let {bcx, val} = trans_temp_expr(bcx, base);
192192
let dict = Load(bcx, PointerCast(bcx, GEPi(bcx, val, [0, 0]),
@@ -195,10 +195,6 @@ fn trans_iface_callee(bcx: @block_ctxt, callee_id: ast::node_id,
195195
// FIXME[impl] I doubt this is alignment-safe
196196
let self = PointerCast(bcx, GEPi(bcx, box, [0, abi::box_field_body]),
197197
T_opaque_cbox_ptr(bcx_ccx(bcx)));
198-
let iface_id = alt ty::get(expr_ty(bcx, base)).struct {
199-
ty::ty_iface(did, _) { did }
200-
_ { fail "base has non-iface type in trans_iface_callee"; }
201-
};
202198
trans_vtable_callee(bcx, self, dict, callee_id, iface_id, n_method)
203199
}
204200

branches/try/src/comp/middle/ty.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,10 @@ type field = {ident: ast::ident, mt: mt};
140140

141141
type param_bounds = @[param_bound];
142142

143-
type method = {ident: ast::ident, tps: @[param_bounds], fty: fn_ty};
143+
type method = {ident: ast::ident,
144+
tps: @[param_bounds],
145+
fty: fn_ty,
146+
purity: ast::purity};
144147

145148
type constr_table = hashmap<ast::node_id, [constr]>;
146149

branches/try/src/comp/middle/typeck.rs

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ enum method_origin {
2525
method_static(ast::def_id),
2626
// iface id, method num, param num, bound num
2727
method_param(ast::def_id, uint, uint, uint),
28-
method_iface(uint),
28+
method_iface(ast::def_id, uint),
2929
}
3030
type method_map = hashmap<ast::node_id, method_origin>;
3131

@@ -556,12 +556,14 @@ fn ty_param_bounds(tcx: ty::ctxt, mode: mode, params: [ast::ty_param])
556556
}
557557
fn ty_of_method(tcx: ty::ctxt, mode: mode, m: @ast::method) -> ty::method {
558558
{ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps),
559-
fty: ty_of_fn_decl(tcx, mode, ast::proto_bare, m.decl)}
559+
fty: ty_of_fn_decl(tcx, mode, ast::proto_bare, m.decl),
560+
purity: m.decl.purity}
560561
}
561562
fn ty_of_ty_method(tcx: ty::ctxt, mode: mode, m: ast::ty_method)
562563
-> ty::method {
563564
{ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps),
564-
fty: ty_of_fn_decl(tcx, mode, ast::proto_bare, m.decl)}
565+
fty: ty_of_fn_decl(tcx, mode, ast::proto_bare, m.decl),
566+
purity: m.decl.purity}
565567
}
566568

567569
// A convenience function to use a crate_ctxt to resolve names for
@@ -817,6 +819,12 @@ mod collect {
817819
alt vec::find(my_methods,
818820
{|m| if_m.ident == m.mty.ident}) {
819821
some({mty: m, id, span}) {
822+
if m.purity != if_m.purity {
823+
cx.tcx.sess.span_err(
824+
span, "method `" + m.ident + "`'s purity \
825+
not match the iface method's \
826+
purity");
827+
}
820828
let mt = compare_impl_method(
821829
cx.tcx, span, m, vec::len(tps), if_m, tys,
822830
selfty);
@@ -1536,30 +1544,39 @@ fn require_impure(sess: session, f_purity: ast::purity, sp: span) {
15361544

15371545
fn require_pure_call(ccx: @crate_ctxt, caller_purity: ast::purity,
15381546
callee: @ast::expr, sp: span) {
1539-
alt caller_purity {
1540-
ast::unsafe_fn { ret; }
1541-
ast::impure_fn {
1542-
alt ccx.tcx.def_map.find(callee.id) {
1543-
some(ast::def_fn(_, ast::unsafe_fn)) {
1544-
ccx.tcx.sess.span_err(
1545-
sp,
1546-
"safe function calls function marked unsafe");
1547+
if caller_purity == ast::unsafe_fn { ret; }
1548+
let callee_purity = alt ccx.tcx.def_map.find(callee.id) {
1549+
some(ast::def_fn(_, p)) { p }
1550+
some(ast::def_variant(_, _)) { ast::pure_fn }
1551+
_ {
1552+
alt ccx.method_map.find(callee.id) {
1553+
some(method_static(did)) {
1554+
if did.crate == ast::local_crate {
1555+
alt ccx.tcx.items.get(did.node) {
1556+
ast_map::node_method(m, _, _) { m.decl.purity }
1557+
_ { fail; }
1558+
}
1559+
} else {
1560+
csearch::lookup_method_purity(ccx.tcx.sess.cstore, did)
1561+
}
15471562
}
1548-
_ {
1563+
some(method_param(iid, n_m, _, _)) | some(method_iface(iid, n_m)) {
1564+
ty::iface_methods(ccx.tcx, iid)[n_m].purity
15491565
}
1566+
none { ast::impure_fn }
15501567
}
1551-
ret;
15521568
}
1553-
ast::pure_fn {
1554-
alt ccx.tcx.def_map.find(callee.id) {
1555-
some(ast::def_fn(_, ast::pure_fn)) |
1556-
some(ast::def_variant(_, _)) { ret; }
1557-
_ {
1558-
ccx.tcx.sess.span_err
1559-
(sp, "pure function calls function not known to be pure");
1560-
}
1561-
}
1569+
};
1570+
alt (caller_purity, callee_purity) {
1571+
(ast::impure_fn, ast::unsafe_fn) {
1572+
ccx.tcx.sess.span_err(sp, "safe function calls function marked \
1573+
unsafe");
15621574
}
1575+
(ast::pure_fn, ast::unsafe_fn) | (ast::pure_fn, ast::impure_fn) {
1576+
ccx.tcx.sess.span_err(sp, "pure function calls function not \
1577+
known to be pure");
1578+
}
1579+
_ {}
15631580
}
15641581
}
15651582

@@ -1686,7 +1703,7 @@ fn lookup_method_inner(fcx: @fn_ctxt, expr: @ast::expr,
16861703
ret some({method_ty: fty,
16871704
n_tps: vec::len(*m.tps),
16881705
substs: tps,
1689-
origin: method_iface(i),
1706+
origin: method_iface(did, i),
16901707
self_sub: none});
16911708
}
16921709
i += 1u;
@@ -1875,12 +1892,12 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
18751892
// A generic function for doing all of the checking for call expressions
18761893
fn check_call_full(fcx: @fn_ctxt, sp: span, f: @ast::expr,
18771894
args: [@ast::expr], id: ast::node_id) -> bool {
1895+
let bot = check_call(fcx, sp, f, args);
18781896
/* here we're kind of hosed, as f can be any expr
18791897
need to restrict it to being an explicit expr_path if we're
18801898
inside a pure function, and need an environment mapping from
18811899
function name onto purity-designation */
18821900
require_pure_call(fcx.ccx, fcx.purity, f, sp);
1883-
let bot = check_call(fcx, sp, f, args);
18841901

18851902
// Pull the return type out of the type of the function.
18861903
let fty = ty::expr_ty(fcx.ccx.tcx, f);

branches/try/src/comp/syntax/parse/parser.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -274,21 +274,22 @@ fn parse_ty_fn(p: parser) -> ast::fn_decl {
274274
let constrs: [@ast::constr] = [];
275275
let (ret_style, ret_ty) = parse_ret_ty(p);
276276
ret {inputs: inputs.node, output: ret_ty,
277-
purity: ast::impure_fn, cf: ret_style,
278-
constraints: constrs};
277+
purity: ast::impure_fn, cf: ret_style,
278+
constraints: constrs};
279279
}
280280

281281
fn parse_ty_methods(p: parser) -> [ast::ty_method] {
282282
parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(), {|p|
283283
let attrs = parse_outer_attributes(p);
284284
let flo = p.span.lo;
285-
expect_word(p, "fn");
285+
let pur = parse_fn_purity(p);
286286
let ident = parse_method_name(p);
287287
let tps = parse_ty_params(p);
288288
let d = parse_ty_fn(p), fhi = p.last_span.hi;
289289
expect(p, token::SEMI);
290-
{ident: ident, attrs: attrs, decl: d, tps: tps,
291-
span: ast_util::mk_sp(flo, fhi)}}, p).node
290+
{ident: ident, attrs: attrs, decl: {purity: pur with d}, tps: tps,
291+
span: ast_util::mk_sp(flo, fhi)}
292+
}, p).node
292293
}
293294

294295
fn parse_mt(p: parser) -> ast::mt {
@@ -1889,11 +1890,10 @@ fn parse_method_name(p: parser) -> ast::ident {
18891890

18901891
fn parse_method(p: parser) -> @ast::method {
18911892
let attrs = parse_outer_attributes(p);
1892-
let lo = p.span.lo;
1893-
expect_word(p, "fn");
1893+
let lo = p.span.lo, pur = parse_fn_purity(p);
18941894
let ident = parse_method_name(p);
18951895
let tps = parse_ty_params(p);
1896-
let decl = parse_fn_decl(p, ast::impure_fn);
1896+
let decl = parse_fn_decl(p, pur);
18971897
let (inner_attrs, body) = parse_inner_attrs_and_block(p, true);
18981898
let attrs = attrs + inner_attrs;
18991899
@{ident: ident, attrs: attrs, tps: tps, decl: decl, body: body,
@@ -2109,17 +2109,16 @@ fn parse_item_native_fn(p: parser, attrs: [ast::attribute],
21092109
span: ast_util::mk_sp(lo, hi)};
21102110
}
21112111

2112+
fn parse_fn_purity(p: parser) -> ast::purity {
2113+
if eat_word(p, "fn") { ast::impure_fn }
2114+
else if eat_word(p, "pure") { expect_word(p, "fn"); ast::pure_fn }
2115+
else if eat_word(p, "unsafe") { expect_word(p, "fn"); ast::unsafe_fn }
2116+
else { unexpected(p, p.token); }
2117+
}
2118+
21122119
fn parse_native_item(p: parser, attrs: [ast::attribute]) ->
21132120
@ast::native_item {
2114-
if eat_word(p, "fn") {
2115-
ret parse_item_native_fn(p, attrs, ast::impure_fn);
2116-
} else if eat_word(p, "pure") {
2117-
expect_word(p, "fn");
2118-
ret parse_item_native_fn(p, attrs, ast::pure_fn);
2119-
} else if eat_word(p, "unsafe") {
2120-
expect_word(p, "fn");
2121-
ret parse_item_native_fn(p, attrs, ast::unsafe_fn);
2122-
} else { unexpected(p, p.token); }
2121+
parse_item_native_fn(p, attrs, parse_fn_purity(p))
21232122
}
21242123

21252124
fn parse_native_mod_items(p: parser, first_item_attrs: [ast::attribute]) ->

0 commit comments

Comments
 (0)