Skip to content

Commit 3bf0a9b

Browse files
committed
rustc: Implement typechecking for simple monomorphic derivable traits on monomorphic types. r=brson
1 parent 575950d commit 3bf0a9b

File tree

23 files changed

+422
-123
lines changed

23 files changed

+422
-123
lines changed

src/libsyntax/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1508,7 +1508,7 @@ enum item_ {
15081508
item_impl(~[ty_param],
15091509
Option<@trait_ref>, /* (optional) trait this impl implements */
15101510
@Ty, /* self */
1511-
~[@method]),
1511+
Option<~[@method]>),
15121512
item_mac(mac),
15131513
}
15141514

src/libsyntax/ast_map.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,13 @@ fn map_item(i: @item, cx: ctx, v: vt) {
202202
let item_path = @/* FIXME (#2543) */ copy cx.path;
203203
cx.map.insert(i.id, node_item(i, item_path));
204204
match i.node {
205-
item_impl(_, _, _, ms) => {
205+
item_impl(_, _, _, ms_opt) => {
206206
let impl_did = ast_util::local_def(i.id);
207-
for ms.each |m| {
208-
map_method(impl_did, extend(cx, i.ident), *m,
209-
cx);
207+
for ms_opt.each |ms| {
208+
for ms.each |m| {
209+
map_method(impl_did, extend(cx, i.ident), *m,
210+
cx);
211+
}
210212
}
211213
}
212214
item_enum(enum_definition, _) => {

src/libsyntax/ext/auto_serialize.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ fn mk_impl(
398398
ident: ast::token::special_idents::clownshoes_extensions,
399399
attrs: ~[],
400400
id: cx.next_id(),
401-
node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]),
401+
node: ast::item_impl(trait_tps, opt_trait, ty, Some(~[f(ty)])),
402402
vis: ast::public,
403403
span: span,
404404
}

src/libsyntax/fold.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,13 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
248248
let struct_def = fold_struct_def(struct_def, fld);
249249
item_class(struct_def, /* FIXME (#2543) */ copy typms)
250250
}
251-
item_impl(tps, ifce, ty, methods) => {
251+
item_impl(tps, ifce, ty, ref methods_opt) => {
252252
item_impl(fold_ty_params(tps, fld),
253253
ifce.map(|p| fold_trait_ref(*p, fld)),
254254
fld.fold_ty(ty),
255-
vec::map(methods, |x| fld.fold_method(*x)))
255+
option::map(methods_opt,
256+
|methods| vec::map(
257+
*methods, |x| fld.fold_method(*x))))
256258
}
257259
item_trait(tps, traits, methods) => {
258260
item_trait(fold_ty_params(tps, fld),

src/libsyntax/parse/parser.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2603,13 +2603,20 @@ impl Parser {
26032603
None
26042604
};
26052605

2606-
let mut meths = ~[];
2607-
self.expect(token::LBRACE);
2608-
while !self.eat(token::RBRACE) {
2609-
let vis = self.parse_visibility();
2610-
meths.push(self.parse_method(vis));
2606+
let meths_opt;
2607+
if self.eat(token::SEMI) {
2608+
meths_opt = None;
2609+
} else {
2610+
let mut meths = ~[];
2611+
self.expect(token::LBRACE);
2612+
while !self.eat(token::RBRACE) {
2613+
let vis = self.parse_visibility();
2614+
meths.push(self.parse_method(vis));
2615+
}
2616+
meths_opt = Some(move meths);
26112617
}
2612-
(ident, item_impl(tps, opt_trait, ty, meths), None)
2618+
2619+
(ident, item_impl(tps, opt_trait, ty, meths_opt), None)
26132620
}
26142621

26152622
// Instantiates ident <i> with references to <typarams> as arguments.

src/libsyntax/print/pprust.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ fn print_item(s: ps, &&item: @ast::item) {
522522
print_struct(s, struct_def, tps, item.ident, item.span);
523523
}
524524

525-
ast::item_impl(tps, opt_trait, ty, methods) => {
525+
ast::item_impl(tps, opt_trait, ty, methods_opt) => {
526526
head(s, visibility_qualified(item.vis, ~"impl"));
527527
if tps.is_not_empty() {
528528
print_type_params(s, tps);
@@ -539,11 +539,18 @@ fn print_item(s: ps, &&item: @ast::item) {
539539
};
540540
space(s.s);
541541

542-
bopen(s);
543-
for methods.each |meth| {
544-
print_method(s, *meth);
542+
match methods_opt {
543+
None => {
544+
word(s.s, ~";");
545+
}
546+
Some(methods) => {
547+
bopen(s);
548+
for methods.each |meth| {
549+
print_method(s, *meth);
550+
}
551+
bclose(s, item.span);
552+
}
545553
}
546-
bclose(s, item.span);
547554
}
548555
ast::item_trait(tps, traits, methods) => {
549556
head(s, visibility_qualified(item.vis, ~"trait"));

src/libsyntax/visit.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,16 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
142142
v.visit_ty_params(tps, e, v);
143143
visit_enum_def(enum_definition, tps, e, v);
144144
}
145-
item_impl(tps, traits, ty, methods) => {
145+
item_impl(tps, traits, ty, methods_opt) => {
146146
v.visit_ty_params(tps, e, v);
147147
for traits.each |p| {
148148
visit_path(p.path, e, v);
149149
}
150150
v.visit_ty(ty, e, v);
151-
for methods.each |m| {
152-
visit_method_helper(*m, e, v)
151+
for methods_opt.each |methods| {
152+
for methods.each |m| {
153+
visit_method_helper(*m, e, v)
154+
}
153155
}
154156
}
155157
item_class(struct_def, tps) => {

src/rustc/metadata/encoder.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
712712
encode_index(ebml_w, bkts, write_int);
713713
ebml_w.end_tag();
714714
}
715-
item_impl(tps, opt_trait, ty, methods) => {
715+
item_impl(tps, opt_trait, ty, methods_opt) => {
716716
add_to_index();
717717
ebml_w.start_tag(tag_items_data_item);
718718
encode_def_id(ebml_w, local_def(item.id));
@@ -729,10 +729,13 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
729729
}
730730
_ => {}
731731
}
732-
for methods.each |m| {
733-
ebml_w.start_tag(tag_item_impl_method);
734-
ebml_w.writer.write(str::to_bytes(def_to_str(local_def(m.id))));
735-
ebml_w.end_tag();
732+
for methods_opt.each |methods| {
733+
for methods.each |m| {
734+
ebml_w.start_tag(tag_item_impl_method);
735+
let method_def_id = local_def(m.id);
736+
ebml_w.writer.write(str::to_bytes(def_to_str(method_def_id)));
737+
ebml_w.end_tag();
738+
}
736739
}
737740
do opt_trait.iter() |associated_trait| {
738741
encode_trait_ref(ebml_w, ecx, *associated_trait)
@@ -742,11 +745,13 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
742745

743746
let impl_path = vec::append_one(path,
744747
ast_map::path_name(item.ident));
745-
for methods.each |m| {
746-
index.push({val: m.id, pos: ebml_w.writer.tell()});
747-
encode_info_for_method(ecx, ebml_w, impl_path,
748-
should_inline(m.attrs), item.id, *m,
749-
vec::append(tps, m.tps));
748+
for methods_opt.each |methods| {
749+
for methods.each |m| {
750+
index.push({val: m.id, pos: ebml_w.writer.tell()});
751+
encode_info_for_method(ecx, ebml_w, impl_path,
752+
should_inline(m.attrs), item.id, *m,
753+
vec::append(tps, m.tps));
754+
}
750755
}
751756
}
752757
item_trait(tps, traits, ms) => {

src/rustc/middle/resolve.rs

Lines changed: 58 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,7 +1192,7 @@ impl Resolver {
11921192
visit_item(item, new_parent, visitor);
11931193
}
11941194

1195-
item_impl(_, trait_ref_opt, ty, methods) => {
1195+
item_impl(_, trait_ref_opt, ty, methods_opt) => {
11961196
// If this implements an anonymous trait and it has static
11971197
// methods, then add all the static methods within to a new
11981198
// module, if the type was defined within this module.
@@ -1203,10 +1203,12 @@ impl Resolver {
12031203

12041204
// Bail out early if there are no static methods.
12051205
let mut has_static_methods = false;
1206-
for methods.each |method| {
1207-
match method.self_ty.node {
1208-
sty_static => has_static_methods = true,
1209-
_ => {}
1206+
for methods_opt.each |methods| {
1207+
for methods.each |method| {
1208+
match method.self_ty.node {
1209+
sty_static => has_static_methods = true,
1210+
_ => {}
1211+
}
12101212
}
12111213
}
12121214

@@ -1233,22 +1235,26 @@ impl Resolver {
12331235
name_bindings.get_module());
12341236

12351237
// For each static method...
1236-
for methods.each |method| {
1237-
match method.self_ty.node {
1238-
sty_static => {
1239-
// Add the static method to the module.
1240-
let ident = method.ident;
1241-
let (method_name_bindings, _) =
1242-
self.add_child(ident,
1243-
new_parent,
1244-
ForbidDuplicateValues,
1245-
method.span);
1246-
let def = def_fn(local_def(method.id),
1247-
method.purity);
1248-
method_name_bindings.define_value(
1249-
Public, def, method.span);
1238+
for methods_opt.each |methods| {
1239+
for methods.each |method| {
1240+
match method.self_ty.node {
1241+
sty_static => {
1242+
// Add the static method to the
1243+
// module.
1244+
let ident = method.ident;
1245+
let (method_name_bindings, _) =
1246+
self.add_child(
1247+
ident,
1248+
new_parent,
1249+
ForbidDuplicateValues,
1250+
method.span);
1251+
let def = def_fn(local_def(method.id),
1252+
method.purity);
1253+
method_name_bindings.define_value(
1254+
Public, def, method.span);
1255+
}
1256+
_ => {}
12501257
}
1251-
_ => {}
12521258
}
12531259
}
12541260
}
@@ -3446,12 +3452,14 @@ impl Resolver {
34463452
}
34473453

34483454
item_impl(type_parameters, implemented_traits, self_type,
3449-
methods) => {
3450-
3451-
self.resolve_implementation(item.id, item.span,
3455+
methods_opt) => {
3456+
self.resolve_implementation(item.id,
3457+
item.span,
34523458
type_parameters,
34533459
implemented_traits,
3454-
self_type, methods, visitor);
3460+
self_type,
3461+
methods_opt,
3462+
visitor);
34553463
}
34563464

34573465
item_trait(type_parameters, traits, methods) => {
@@ -3876,7 +3884,7 @@ impl Resolver {
38763884
type_parameters: ~[ty_param],
38773885
opt_trait_reference: Option<@trait_ref>,
38783886
self_type: @Ty,
3879-
methods: ~[@method],
3887+
opt_methods: Option<~[@method]>,
38803888
visitor: ResolveVisitor) {
38813889
// If applicable, create a rib for the type parameters.
38823890
let outer_type_parameter_count = type_parameters.len();
@@ -3915,27 +3923,33 @@ impl Resolver {
39153923
// Resolve the self type.
39163924
self.resolve_type(self_type, visitor);
39173925

3918-
for methods.each |method| {
3919-
// We also need a new scope for the method-specific
3920-
// type parameters.
3921-
self.resolve_method(MethodRibKind(id, Provided(method.id)),
3922-
*method,
3923-
outer_type_parameter_count,
3924-
visitor);
3926+
for opt_methods.each |methods| {
3927+
for methods.each |method| {
3928+
// We also need a new scope for the method-specific
3929+
// type parameters.
3930+
self.resolve_method(MethodRibKind(
3931+
id,
3932+
Provided(method.id)),
3933+
*method,
3934+
outer_type_parameter_count,
3935+
visitor);
39253936
/*
3926-
let borrowed_type_parameters = &method.tps;
3927-
self.resolve_function(MethodRibKind(id, Provided(method.id)),
3928-
Some(@method.decl),
3929-
HasTypeParameters
3930-
(borrowed_type_parameters,
3931-
method.id,
3932-
outer_type_parameter_count,
3933-
NormalRibKind),
3934-
method.body,
3935-
HasSelfBinding(method.self_id),
3936-
NoCaptureClause,
3937-
visitor);
3937+
let borrowed_type_parameters = &method.tps;
3938+
self.resolve_function(MethodRibKind(
3939+
id,
3940+
Provided(method.id)),
3941+
Some(@method.decl),
3942+
HasTypeParameters
3943+
(borrowed_type_parameters,
3944+
method.id,
3945+
outer_type_parameter_count,
3946+
NormalRibKind),
3947+
method.body,
3948+
HasSelfBinding(method.self_id),
3949+
NoCaptureClause,
3950+
visitor);
39383951
*/
3952+
}
39393953
}
39403954

39413955
// Restore the original trait references.

src/rustc/middle/trans/base.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,8 +1798,17 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
17981798
}
17991799
}
18001800
}
1801-
ast::item_impl(tps, _, _, ms) => {
1802-
meth::trans_impl(ccx, *path, item.ident, ms, tps, None, item.id);
1801+
ast::item_impl(tps, _, _, ms_opt) => {
1802+
match ms_opt {
1803+
None => {
1804+
deriving::trans_deriving_impl(ccx, *path, item.ident, tps,
1805+
None, item.id);
1806+
}
1807+
Some(ms) => {
1808+
meth::trans_impl(ccx, *path, item.ident, ms, tps, None,
1809+
item.id);
1810+
}
1811+
}
18031812
}
18041813
ast::item_mod(m) => {
18051814
trans_mod(ccx, m);

src/rustc/middle/trans/deriving.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Translation of automatically-derived trait implementations. This handles
2+
// enums and structs only; other types cannot be automatically derived.
3+
4+
use middle::trans::base::get_insn_ctxt;
5+
use middle::trans::common::crate_ctxt;
6+
use syntax::ast::{ident, node_id, ty_param};
7+
use syntax::ast_map::path;
8+
9+
/// The main "translation" pass for automatically-derived impls. Generates
10+
/// code for monomorphic methods only. Other methods will be generated when
11+
/// they are invoked with specific type parameters; see
12+
/// `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
13+
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) {
16+
let _icx = ccx.insn_ctxt("deriving::trans_deriving_impl");
17+
if tps.len() > 0 { return; }
18+
19+
// XXX: Unimplemented.
20+
}
21+

src/rustc/middle/trans/meth.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,8 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
306306
name: ast::ident) -> ast::def_id {
307307
if impl_id.crate == ast::local_crate {
308308
match ccx.tcx.items.get(impl_id.node) {
309-
ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) => {
309+
ast_map::node_item(@{node: ast::item_impl(_, _, _, Some(ms)), _},
310+
_) => {
310311
method_from_methods(ms, name)
311312
}
312313
ast_map::node_item(@{node:

src/rustc/middle/trans/reachable.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,14 @@ fn traverse_public_item(cx: ctx, item: @item) {
9090
traverse_inline_body(cx, blk);
9191
}
9292
}
93-
item_impl(tps, _, _, ms) => {
94-
for vec::each(ms) |m| {
95-
if tps.len() > 0u || m.tps.len() > 0u ||
96-
attr::find_inline_attr(m.attrs) != attr::ia_none {
97-
cx.rmap.insert(m.id, ());
98-
traverse_inline_body(cx, m.body);
93+
item_impl(tps, _, _, ms_opt) => {
94+
for ms_opt.each |ms| {
95+
for vec::each(*ms) |m| {
96+
if tps.len() > 0u || m.tps.len() > 0u ||
97+
attr::find_inline_attr(m.attrs) != attr::ia_none {
98+
cx.rmap.insert(m.id, ());
99+
traverse_inline_body(cx, m.body);
100+
}
99101
}
100102
}
101103
}

0 commit comments

Comments
 (0)