Skip to content

Commit 2585384

Browse files
committed
First working monomorphic type-reflection.
1 parent 5dbf881 commit 2585384

File tree

4 files changed

+210
-18
lines changed

4 files changed

+210
-18
lines changed

src/rustc/front/intrinsic.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ mod intrinsic {
1818
}
1919

2020
iface ty_visitor {
21+
fn visit_bot();
2122
fn visit_nil();
2223
fn visit_bool();
2324

@@ -36,6 +37,8 @@ mod intrinsic {
3637
fn visit_float();
3738
fn visit_f32();
3839
fn visit_f64();
40+
41+
fn visit_char();
3942
fn visit_str();
4043

4144
fn visit_vec(cells_mut: bool,
@@ -68,6 +71,7 @@ mod intrinsic {
6871
iface val_visitor {
6972

7073
// Basic types we can visit directly.
74+
fn visit_bot();
7175
fn visit_nil();
7276
fn visit_bool(b: &bool);
7377

@@ -87,6 +91,8 @@ mod intrinsic {
8791
fn visit_f32(f: &f32);
8892
fn visit_f64(f: &f64);
8993

94+
fn visit_char(c: &char);
95+
9096
// Vecs and strs we can provide a stub view of.
9197
fn visit_str(repr: &vec::unsafe::vec_repr,
9298
visit_cell: fn(uint,self));

src/rustc/middle/trans/native.rs

Lines changed: 71 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,7 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::native_item,
782782
ref_id: option<ast::node_id>) {
783783
let fcx = new_fn_ctxt_w_id(ccx, path, decl, item.id,
784784
some(substs), some(item.span));
785-
let bcx = top_scope_block(fcx, none), lltop = bcx.llbb;
785+
let mut bcx = top_scope_block(fcx, none), lltop = bcx.llbb;
786786
let tp_ty = substs.tys[0], lltp_ty = type_of::type_of(ccx, tp_ty);
787787
alt check item.ident {
788788
"size_of" {
@@ -835,27 +835,83 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::native_item,
835835
fcx.llretptr);
836836
}
837837
"visit_ty" {
838-
let vp_ty = substs.tys[1], _llvp_ty = type_of::type_of(ccx, vp_ty);
838+
839+
// signature: fn visit_ty<T,V:ty_visitor>(tv: V);
840+
841+
let tp_ty = substs.tys[0];
842+
let vp_ty = substs.tys[1];
839843
let visitor = get_param(decl, first_real_arg);
840-
// FIXME: implement a proper iface-call. Nontrivial.
841-
Call(bcx, visitor, []);
844+
845+
// We're going to synthesize a monomorphized vtbl call here much
846+
// like what impl::trans_monomorphized_callee does, but without
847+
// having quite as much source machinery to go on.
848+
849+
alt impl::find_vtable_in_fn_ctxt(substs,
850+
1u, /* n_param */
851+
0u /* n_bound */ ) {
852+
853+
typeck::vtable_static(impl_did, impl_substs, sub_origins) {
854+
855+
let (tyname, args) = alt ty::get(tp_ty).struct {
856+
ty::ty_bot { ("bot", []) }
857+
ty::ty_nil { ("nil", []) }
858+
ty::ty_bool { ("bool", []) }
859+
ty::ty_int(ast::ty_i) { ("int", []) }
860+
ty::ty_int(ast::ty_char) { ("char", []) }
861+
ty::ty_int(ast::ty_i8) { ("i8", []) }
862+
ty::ty_int(ast::ty_i16) { ("i16", []) }
863+
ty::ty_int(ast::ty_i32) { ("i32", []) }
864+
ty::ty_int(ast::ty_i64) { ("i64", []) }
865+
ty::ty_uint(ast::ty_u) { ("uint", []) }
866+
ty::ty_uint(ast::ty_u8) { ("u8", []) }
867+
ty::ty_uint(ast::ty_u16) { ("u16", []) }
868+
ty::ty_uint(ast::ty_u32) { ("u32", []) }
869+
ty::ty_uint(ast::ty_u64) { ("u64", []) }
870+
ty::ty_float(ast::ty_f) { ("float", []) }
871+
ty::ty_float(ast::ty_f32) { ("f32", []) }
872+
ty::ty_float(ast::ty_f64) { ("f64", []) }
873+
ty::ty_str { ("str", []) }
874+
_ {
875+
bcx.sess().unimpl("trans::native::visit_ty on "
876+
+ ty_to_str(ccx.tcx, tp_ty));
877+
}
878+
};
879+
880+
let mth_id = impl::method_with_name(ccx, impl_did,
881+
"visit_" + tyname);
882+
let mth_ty = ty::lookup_item_type(ccx.tcx, mth_id).ty;
883+
884+
// FIXME: is this safe? There is no callee AST node,
885+
// we're synthesizing it.
886+
let callee_id = (-1) as ast::node_id;
887+
888+
let dest = ignore;
889+
890+
bcx = trans_call_inner(bcx,
891+
mth_ty,
892+
ty::mk_nil(ccx.tcx),
893+
{|bcx|
894+
let lval =
895+
lval_static_fn_inner
896+
(bcx, mth_id, callee_id,
897+
impl_substs, some(sub_origins));
898+
{env: self_env(visitor, vp_ty, none)
899+
with lval}
900+
}, arg_vals(args), dest);
901+
}
902+
_ {
903+
ccx.sess.span_bug(item.span,
904+
"non-static callee in 'visit_ty' intrinsinc");
905+
}
906+
}
842907
}
843908

844909
"visit_val" {
845-
let vp_ty = substs.tys[1], _llvp_ty = type_of::type_of(ccx, vp_ty);
846-
let val = get_param(decl, first_real_arg);
847-
let visitor = get_param(decl, first_real_arg + 1u);
848-
// FIXME: implement a proper iface-call. Nontrivial.
849-
Call(bcx, visitor, [val]);
910+
bcx.sess().unimpl("trans::native::visit_val");
850911
}
851912

852913
"visit_val_pair" {
853-
let vp_ty = substs.tys[1], _llvp_ty = type_of::type_of(ccx, vp_ty);
854-
let a = get_param(decl, first_real_arg);
855-
let b = get_param(decl, first_real_arg + 1u);
856-
let visitor = get_param(decl, first_real_arg + 2u);
857-
// FIXME: implement a proper iface-call. Nontrivial.
858-
Call(bcx, visitor, [a, b]);
914+
bcx.sess().unimpl("trans::native::visit_val_pair");
859915
}
860916
}
861917
build_return(bcx);

src/rustc/middle/trans/type_use.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
7676
ast_map::node_native_item(i@@{node: native_item_fn(_, _), _}, abi, _) {
7777
if abi == native_abi_rust_intrinsic {
7878
let flags = alt check i.ident {
79-
"size_of" |
80-
"pref_align_of" | "min_align_of" | "init" |
81-
"reinterpret_cast" { use_repr }
79+
"visit_ty" | "visit_val" | "visit_val_pair" { 3u }
80+
"size_of" | "pref_align_of" | "min_align_of" |
81+
"init" | "reinterpret_cast" { use_repr }
8282
"get_tydesc" | "needs_drop" { use_tydesc }
8383
"forget" | "addr_of" { 0u }
8484
};
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// xfail-test
2+
//
3+
// This works on stage2 currently. Once we have a snapshot
4+
// and some fiddling with inject_intrinsic (and possibly another
5+
// snapshot after _that_) it can be un-xfailed and changed
6+
// to use the intrinsic:: interface and native module.
7+
//
8+
9+
iface ty_visitor {
10+
fn visit_bot();
11+
fn visit_nil();
12+
fn visit_bool();
13+
14+
fn visit_int();
15+
fn visit_i8();
16+
fn visit_i16();
17+
fn visit_i32();
18+
fn visit_i64();
19+
20+
fn visit_uint();
21+
fn visit_u8();
22+
fn visit_u16();
23+
fn visit_u32();
24+
fn visit_u64();
25+
26+
fn visit_float();
27+
fn visit_f32();
28+
fn visit_f64();
29+
30+
fn visit_char();
31+
fn visit_str();
32+
33+
fn visit_vec(cells_mut: bool,
34+
visit_cell: fn(uint, self));
35+
36+
fn visit_box(inner_mut: bool,
37+
visit_inner: fn(self));
38+
39+
fn visit_uniq(inner_mut: bool,
40+
visit_inner: fn(self));
41+
42+
fn visit_ptr(inner_mut: bool,
43+
visit_inner: fn(self));
44+
45+
fn visit_rptr(inner_mut: bool,
46+
visit_inner: fn(self));
47+
48+
fn visit_rec(n_fields: uint,
49+
field_name: fn(uint) -> str/&,
50+
field_mut: fn(uint) -> bool,
51+
visit_field: fn(uint, self));
52+
fn visit_tup(n_fields: uint,
53+
visit_field: fn(uint, self));
54+
fn visit_enum(n_variants: uint,
55+
variant: uint,
56+
variant_name: fn(uint) -> str/&,
57+
visit_variant: fn(uint, self));
58+
}
59+
60+
enum my_visitor = { mut types: [str] };
61+
62+
impl of ty_visitor for my_visitor {
63+
fn visit_bot() { self.types += ["bot"] }
64+
fn visit_nil() { self.types += ["nil"] }
65+
fn visit_bool() { self.types += ["bool"] }
66+
67+
fn visit_int() { self.types += ["int"] }
68+
fn visit_i8() { self.types += ["i8"] }
69+
fn visit_i16() { self.types += ["i16"] }
70+
fn visit_i32() { }
71+
fn visit_i64() { }
72+
73+
fn visit_uint() { }
74+
fn visit_u8() { }
75+
fn visit_u16() { }
76+
fn visit_u32() { }
77+
fn visit_u64() { }
78+
79+
fn visit_float() { }
80+
fn visit_f32() { }
81+
fn visit_f64() { }
82+
83+
fn visit_char() { }
84+
fn visit_str() { }
85+
86+
fn visit_vec(_cells_mut: bool,
87+
_visit_cell: fn(uint, my_visitor)) { }
88+
89+
fn visit_box(_inner_mut: bool,
90+
_visit_inner: fn(my_visitor)) { }
91+
92+
fn visit_uniq(_inner_mut: bool,
93+
_visit_inner: fn(my_visitor)) { }
94+
95+
fn visit_ptr(_inner_mut: bool,
96+
_visit_inner: fn(my_visitor)) { }
97+
98+
fn visit_rptr(_inner_mut: bool,
99+
_visit_inner: fn(my_visitor)) { }
100+
101+
fn visit_rec(_n_fields: uint,
102+
_field_name: fn(uint) -> str/&,
103+
_field_mut: fn(uint) -> bool,
104+
_visit_field: fn(uint, my_visitor)) { }
105+
fn visit_tup(_n_fields: uint,
106+
_visit_field: fn(uint, my_visitor)) { }
107+
fn visit_enum(_n_variants: uint,
108+
_variant: uint,
109+
_variant_name: fn(uint) -> str/&,
110+
_visit_variant: fn(uint, my_visitor)) { }
111+
}
112+
113+
#[abi = "rust-intrinsic"]
114+
native mod rusti {
115+
fn visit_ty<T,V:ty_visitor>(tv: V);
116+
}
117+
118+
fn main() {
119+
let v = my_visitor({mut types: []});
120+
121+
rusti::visit_ty::<bool,my_visitor>(v);
122+
rusti::visit_ty::<int,my_visitor>(v);
123+
rusti::visit_ty::<i8,my_visitor>(v);
124+
rusti::visit_ty::<i16,my_visitor>(v);
125+
126+
for v.types.each {|s|
127+
io::println(#fmt("type: %s", s));
128+
}
129+
assert v.types == ["bool", "int", "i8", "i16"];
130+
}

0 commit comments

Comments
 (0)