Skip to content

Commit 4b9b1a1

Browse files
committed
---
yaml --- r: 33518 b: refs/heads/snap-stage3 c: d5a27a0 h: refs/heads/master v: v3
1 parent d0f8d1f commit 4b9b1a1

File tree

9 files changed

+281
-64
lines changed

9 files changed

+281
-64
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: cd6f24f9d14ac90d167386a56e7a6ac1f0318195
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: 2ab614f3569f34eee2fd70862e8f35548282fb11
4+
refs/heads/snap-stage3: d5a27a0e0c6e64d1532443a6bd45b3416e7597fe
55
refs/heads/try: d324a424d8f84b1eb049b12cf34182bda91b0024
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b

branches/snap-stage3/doc/rust.md

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1951,48 +1951,32 @@ while i < 10 {
19511951

19521952
### Infinite loops
19531953

1954-
The keyword `loop` in Rust appears both in _loop expressions_ and in _continue expressions_.
1955-
A loop expression denotes an infinite loop;
1956-
see [Continue expressions](#continue-expressions) for continue expressions.
1954+
A `loop` expression denotes an infinite loop:
19571955

19581956
~~~~~~~~{.ebnf .gram}
1959-
loop_expr : "loop" [ ident ':' ] '{' block '}';
1957+
loop_expr : "loop" '{' block '}';
19601958
~~~~~~~~
19611959

1962-
A `loop` expression may optionally have a _label_.
1963-
If a label is present,
1964-
then labeled `break` and `loop` expressions nested within this loop may exit out of this loop or return control to its head.
1965-
See [Break expressions](#break-expressions).
1966-
19671960
### Break expressions
19681961

19691962
~~~~~~~~{.ebnf .gram}
1970-
break_expr : "break" [ ident ];
1963+
break_expr : "break" ;
19711964
~~~~~~~~
19721965

1973-
A `break` expression has an optional `label`.
1974-
If the label is absent, then executing a `break` expression immediately terminates the innermost loop enclosing it.
1975-
It is only permitted in the body of a loop.
1976-
If the label is present, then `break foo` terminates the loop with label `foo`,
1977-
which need not be the innermost label enclosing the `break` expression,
1978-
but must enclose it.
1966+
Executing a `break` expression immediately terminates the innermost loop
1967+
enclosing it. It is only permitted in the body of a loop.
19791968

1980-
### Continue expressions
1969+
### Loop expressions
19811970

19821971
~~~~~~~~{.ebnf .gram}
1983-
continue_expr : "loop" [ ident ];
1984-
~~~~~~~~
1985-
1986-
A continue expression, written `loop`, also has an optional `label`.
1987-
If the label is absent,
1988-
then executing a `loop` expression immediately terminates the current iteration of the innermost loop enclosing it,
1989-
returning control to the loop *head*.
1990-
In the case of a `while` loop,
1991-
the head is the conditional expression controlling the loop.
1992-
In the case of a `for` loop, the head is the call-expression controlling the loop.
1993-
If the label is present, then `loop foo` returns control to the head of the loop with label `foo`,
1994-
which need not be the innermost label enclosing the `break` expression,
1995-
but must enclose it.
1972+
loop_expr : "loop" ;
1973+
~~~~~~~~
1974+
1975+
Evaluating a `loop` expression immediately terminates the current iteration of
1976+
the innermost loop enclosing it, returning control to the loop *head*. In the
1977+
case of a `while` loop, the head is the conditional expression controlling the
1978+
loop. In the case of a `for` loop, the head is the call-expression controlling
1979+
the loop.
19961980

19971981
A `loop` expression is only permitted in the body of a loop.
19981982

branches/snap-stage3/src/libsyntax/ast_map.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ enum ast_node {
7474
// Destructor for a class
7575
node_dtor(~[ty_param], @class_dtor, def_id, @path),
7676
node_block(blk),
77-
node_struct_ctor(@struct_def, @item, @path)
77+
node_struct_ctor(@struct_def, @item, @path),
7878
}
7979

8080
type map = std::map::HashMap<node_id, ast_node>;

branches/snap-stage3/src/rustc/middle/trans/base.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ use util::ppaux;
4242
use util::ppaux::{ty_to_str, ty_to_short_str};
4343
use syntax::diagnostic::expect;
4444
use util::common::indenter;
45+
use ty::DerivedMethodInfo;
4546

4647
use build::*;
4748
use shape::*;
@@ -1843,7 +1844,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
18431844
match ms_opt {
18441845
None => {
18451846
deriving::trans_deriving_impl(ccx, *path, item.ident, tps,
1846-
None, item.id);
1847+
item.id);
18471848
}
18481849
Some(ms) => {
18491850
meth::trans_impl(ccx, *path, item.ident, ms, tps, None,
@@ -2079,6 +2080,20 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
20792080
match ccx.item_vals.find(id) {
20802081
Some(v) => v,
20812082
None => {
2083+
// First, check whether we need to automatically generate a method
2084+
// via the deriving mechanism.
2085+
match ccx.tcx.automatically_derived_methods.find(local_def(id)) {
2086+
None => {} // Continue.
2087+
Some(ref derived_method_info) => {
2088+
// XXX: Mark as internal if necessary.
2089+
let llfn = register_deriving_method(
2090+
ccx, id, derived_method_info);
2091+
ccx.item_vals.insert(id, llfn);
2092+
return llfn;
2093+
}
2094+
}
2095+
2096+
// Failing that, look for an item.
20822097
let mut exprt = false;
20832098
let val = match ccx.tcx.items.get(id) {
20842099
ast_map::node_item(i, pth) => {
@@ -2226,6 +2241,32 @@ fn register_method(ccx: @crate_ctxt, id: ast::node_id, pth: @ast_map::path,
22262241
llfn
22272242
}
22282243

2244+
fn register_deriving_method(ccx: @crate_ctxt,
2245+
id: ast::node_id,
2246+
derived_method_info: &DerivedMethodInfo) ->
2247+
ValueRef {
2248+
// Find the path of the item.
2249+
let path, span;
2250+
match ccx.tcx.items.get(derived_method_info.containing_impl.node) {
2251+
ast_map::node_item(item, found_path) => {
2252+
path = found_path;
2253+
span = item.span;
2254+
}
2255+
_ => {
2256+
ccx.tcx.sess.bug(~"derived method info containing impl didn't \
2257+
refer to an item");
2258+
}
2259+
}
2260+
2261+
let path = vec::append(*path, ~[
2262+
ast_map::path_name(derived_method_info.method_info.ident)
2263+
]);
2264+
let mty = ty::lookup_item_type(ccx.tcx, local_def(id)).ty;
2265+
let llfn = register_fn_full(ccx, span, path, id, mty);
2266+
// XXX: Inline hint.
2267+
llfn
2268+
}
2269+
22292270
// The constant translation pass.
22302271
fn trans_constant(ccx: @crate_ctxt, it: @ast::item) {
22312272
let _icx = ccx.insn_ctxt("trans_constant");

branches/snap-stage3/src/rustc/middle/trans/callee.rs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -210,23 +210,30 @@ fn trans_fn_ref_with_vtables(
210210
// intrinsic, or is a default method. In particular, if we see an
211211
// intrinsic that is inlined from a different crate, we want to reemit the
212212
// intrinsic instead of trying to call it in the other crate.
213-
let must_monomorphise = type_params.len() > 0 ||
214-
opt_impl_did.is_some() || {
215-
if def_id.crate == ast::local_crate {
216-
let map_node = session::expect(
217-
ccx.sess,
218-
ccx.tcx.items.find(def_id.node),
219-
|| fmt!("local item should be in ast map"));
220-
221-
match map_node {
222-
ast_map::node_foreign_item(
223-
_, ast::foreign_abi_rust_intrinsic, _) => true,
224-
_ => false
213+
let must_monomorphise;
214+
if type_params.len() > 0 || opt_impl_did.is_some() {
215+
must_monomorphise = true;
216+
} else if ccx.tcx.automatically_derived_methods.contains_key(def_id) {
217+
must_monomorphise = false;
218+
} else if def_id.crate == ast::local_crate {
219+
let map_node = session::expect(
220+
ccx.sess,
221+
ccx.tcx.items.find(def_id.node),
222+
|| fmt!("local item should be in ast map"));
223+
224+
match map_node {
225+
ast_map::node_foreign_item(_,
226+
ast::foreign_abi_rust_intrinsic,
227+
_) => {
228+
must_monomorphise = true;
229+
}
230+
_ => {
231+
must_monomorphise = false;
225232
}
226-
} else {
227-
false
228233
}
229-
};
234+
} else {
235+
must_monomorphise = false;
236+
}
230237

231238
// Create a monomorphic verison of generic functions
232239
if must_monomorphise {
@@ -434,6 +441,15 @@ fn trans_call_inner(
434441
_ => {}
435442
}
436443

444+
// Uncomment this to debug calls.
445+
/*
446+
io::println(fmt!("calling: %s", bcx.val_str(llfn)));
447+
for llargs.each |llarg| {
448+
io::println(fmt!("arg: %s", bcx.val_str(*llarg)));
449+
}
450+
io::println("---");
451+
*/
452+
437453
// If the block is terminated, then one or more of the args
438454
// has type _|_. Since that means it diverges, the code for
439455
// the call itself is unreachable.
Lines changed: 111 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,126 @@
11
// Translation of automatically-derived trait implementations. This handles
22
// enums and structs only; other types cannot be automatically derived.
33

4-
use middle::trans::base::get_insn_ctxt;
5-
use middle::trans::common::crate_ctxt;
6-
use syntax::ast::{ident, node_id, ty_param};
4+
use lib::llvm::llvm;
5+
use middle::trans::base::{finish_fn, get_insn_ctxt, get_item_val};
6+
use middle::trans::base::{new_fn_ctxt, sub_block, top_scope_block};
7+
use middle::trans::build::{Br, CondBr, GEPi, Load, PointerCast, Store};
8+
use middle::trans::build::{ValueRef};
9+
use middle::trans::callee;
10+
use middle::trans::callee::{ArgVals, Callee, DontAutorefArg, Method};
11+
use middle::trans::callee::{MethodData};
12+
use middle::trans::common;
13+
use middle::trans::common::{C_bool, T_ptr, block, crate_ctxt};
14+
use middle::trans::expr::SaveIn;
15+
use middle::trans::type_of::type_of;
16+
use middle::typeck::method_static;
17+
use syntax::ast;
18+
use syntax::ast::{def_id, ident, node_id, ty_param};
719
use syntax::ast_map::path;
20+
use syntax::ast_util;
21+
use syntax::ast_util::local_def;
822

923
/// The main "translation" pass for automatically-derived impls. Generates
1024
/// code for monomorphic methods only. Other methods will be generated when
1125
/// they are invoked with specific type parameters; see
1226
/// `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
1327
pub fn trans_deriving_impl(ccx: @crate_ctxt, _path: path, _name: ident,
14-
tps: ~[ty_param], _self_ty: Option<ty::t>,
15-
_id: node_id) {
28+
tps: ~[ty_param], id: node_id) {
1629
let _icx = ccx.insn_ctxt("deriving::trans_deriving_impl");
1730
if tps.len() > 0 { return; }
1831

19-
// XXX: Unimplemented.
32+
let impl_def_id = local_def(id);
33+
let self_ty = ty::lookup_item_type(ccx.tcx, impl_def_id);
34+
let method_dids = ccx.tcx.automatically_derived_methods_for_impl.get(
35+
impl_def_id);
36+
37+
for method_dids.each |method_did| {
38+
let llfn = get_item_val(ccx, method_did.node);
39+
match ty::get(self_ty.ty).sty {
40+
ty::ty_class(*) => {
41+
trans_deriving_struct_method(ccx, llfn, impl_def_id,
42+
self_ty.ty);
43+
}
44+
_ => {
45+
ccx.tcx.sess.unimpl(~"translation of non-struct deriving \
46+
method");
47+
}
48+
}
49+
}
50+
}
51+
52+
fn trans_deriving_struct_method(ccx: @crate_ctxt, llfn: ValueRef,
53+
impl_did: def_id, self_ty: ty::t) {
54+
let _icx = ccx.insn_ctxt("trans_deriving_struct_method");
55+
let fcx = new_fn_ctxt(ccx, ~[], llfn, None);
56+
let top_bcx = top_scope_block(fcx, None);
57+
let lltop = top_bcx.llbb;
58+
let mut bcx = top_bcx;
59+
60+
let llselfty = type_of(ccx, self_ty);
61+
let llselfval = PointerCast(bcx, fcx.llenv, T_ptr(llselfty));
62+
let llotherval = llvm::LLVMGetParam(llfn, 2);
63+
64+
let struct_field_tys;
65+
match ty::get(self_ty).sty {
66+
ty::ty_class(struct_id, ref struct_substs) => {
67+
struct_field_tys = ty::class_items_as_fields(
68+
ccx.tcx, struct_id, struct_substs);
69+
}
70+
_ => {
71+
ccx.tcx.sess.bug(~"passed non-struct to \
72+
trans_deriving_struct_method");
73+
}
74+
}
75+
76+
// Iterate over every element of the struct.
77+
for ccx.tcx.deriving_struct_methods.get(impl_did).eachi
78+
|i, derived_method_info| {
79+
let target_method_def_id;
80+
match *derived_method_info {
81+
method_static(did) => target_method_def_id = did,
82+
_ => fail ~"derived method didn't resolve to a static method"
83+
}
84+
85+
let fn_expr_ty =
86+
ty::lookup_item_type(ccx.tcx, target_method_def_id).ty;
87+
88+
let llselfval = GEPi(bcx, llselfval, [0, 0, i]);
89+
let llotherval = GEPi(bcx, llotherval, [0, 0, i]);
90+
91+
// XXX: Cross-crate won't work!
92+
let llfn = get_item_val(ccx, target_method_def_id.node);
93+
let cb: &fn(block) -> Callee = |block| {
94+
Callee {
95+
bcx: block,
96+
data: Method(MethodData {
97+
llfn: llfn,
98+
llself: llselfval,
99+
self_ty: struct_field_tys[i].mt.ty,
100+
self_mode: ast::by_copy
101+
})
102+
}
103+
};
104+
105+
bcx = callee::trans_call_inner(bcx,
106+
None,
107+
fn_expr_ty,
108+
ty::mk_bool(ccx.tcx),
109+
cb,
110+
ArgVals(~[llotherval]),
111+
SaveIn(fcx.llretptr),
112+
DontAutorefArg);
113+
114+
// Return immediately if the call returned false.
115+
let next_block = sub_block(top_bcx, ~"next");
116+
let llcond = Load(bcx, fcx.llretptr);
117+
CondBr(bcx, llcond, next_block.llbb, fcx.llreturn);
118+
bcx = next_block;
119+
}
120+
121+
Store(bcx, C_bool(true), fcx.llretptr);
122+
Br(bcx, fcx.llreturn);
123+
124+
finish_fn(fcx, lltop);
20125
}
21126

branches/snap-stage3/src/rustc/middle/ty.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ export provided_trait_methods;
200200
export trait_supertraits;
201201
export AutoAdjustment;
202202
export AutoRef, AutoRefKind, AutoSlice, AutoPtr;
203+
export DerivedMethodInfo;
203204

204205
// Data types
205206

@@ -333,6 +334,11 @@ struct InstantiatedTraitRef {
333334
tpt: ty_param_substs_and_ty
334335
}
335336

337+
struct DerivedMethodInfo {
338+
method_info: @middle::resolve::MethodInfo,
339+
containing_impl: ast::def_id
340+
}
341+
336342
type ctxt =
337343
@{diag: syntax::diagnostic::span_handler,
338344
interner: HashMap<intern_key, t_box>,
@@ -379,7 +385,17 @@ type ctxt =
379385
provided_method_sources: HashMap<ast::def_id, ProvidedMethodSource>,
380386
supertraits: HashMap<ast::def_id, @~[InstantiatedTraitRef]>,
381387
deriving_struct_methods: HashMap<ast::def_id,
382-
@~[typeck::method_origin]>};
388+
@~[typeck::method_origin]>,
389+
390+
// A mapping from the def ID of a method that was automatically derived
391+
// to information about it.
392+
automatically_derived_methods: HashMap<ast::def_id, DerivedMethodInfo>,
393+
394+
// A mapping from the def ID of an impl to the IDs of the derived
395+
// methods within it.
396+
automatically_derived_methods_for_impl:
397+
HashMap<ast::def_id, @~[ast::def_id]>
398+
};
383399

384400
enum tbox_flag {
385401
has_params = 1,
@@ -942,7 +958,9 @@ fn mk_ctxt(s: session::Session,
942958
legacy_boxed_traits: HashMap(),
943959
provided_method_sources: HashMap(),
944960
supertraits: HashMap(),
945-
deriving_struct_methods: HashMap()}
961+
deriving_struct_methods: HashMap(),
962+
automatically_derived_methods: HashMap(),
963+
automatically_derived_methods_for_impl: HashMap()}
946964
}
947965

948966

0 commit comments

Comments
 (0)