Skip to content

Commit

Permalink
rustc: Implement typechecking for simple monomorphic derivable traits…
Browse files Browse the repository at this point in the history
… on monomorphic types. r=brson
  • Loading branch information
pcwalton committed Oct 23, 2012
1 parent 575950d commit 3bf0a9b
Show file tree
Hide file tree
Showing 23 changed files with 422 additions and 123 deletions.
2 changes: 1 addition & 1 deletion src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1508,7 +1508,7 @@ enum item_ {
item_impl(~[ty_param],
Option<@trait_ref>, /* (optional) trait this impl implements */
@Ty, /* self */
~[@method]),
Option<~[@method]>),
item_mac(mac),
}

Expand Down
10 changes: 6 additions & 4 deletions src/libsyntax/ast_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,13 @@ fn map_item(i: @item, cx: ctx, v: vt) {
let item_path = @/* FIXME (#2543) */ copy cx.path;
cx.map.insert(i.id, node_item(i, item_path));
match i.node {
item_impl(_, _, _, ms) => {
item_impl(_, _, _, ms_opt) => {
let impl_did = ast_util::local_def(i.id);
for ms.each |m| {
map_method(impl_did, extend(cx, i.ident), *m,
cx);
for ms_opt.each |ms| {
for ms.each |m| {
map_method(impl_did, extend(cx, i.ident), *m,
cx);
}
}
}
item_enum(enum_definition, _) => {
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/ext/auto_serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ fn mk_impl(
ident: ast::token::special_idents::clownshoes_extensions,
attrs: ~[],
id: cx.next_id(),
node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]),
node: ast::item_impl(trait_tps, opt_trait, ty, Some(~[f(ty)])),
vis: ast::public,
span: span,
}
Expand Down
6 changes: 4 additions & 2 deletions src/libsyntax/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,13 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
let struct_def = fold_struct_def(struct_def, fld);
item_class(struct_def, /* FIXME (#2543) */ copy typms)
}
item_impl(tps, ifce, ty, methods) => {
item_impl(tps, ifce, ty, ref methods_opt) => {
item_impl(fold_ty_params(tps, fld),
ifce.map(|p| fold_trait_ref(*p, fld)),
fld.fold_ty(ty),
vec::map(methods, |x| fld.fold_method(*x)))
option::map(methods_opt,
|methods| vec::map(
*methods, |x| fld.fold_method(*x))))
}
item_trait(tps, traits, methods) => {
item_trait(fold_ty_params(tps, fld),
Expand Down
19 changes: 13 additions & 6 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2603,13 +2603,20 @@ impl Parser {
None
};

let mut meths = ~[];
self.expect(token::LBRACE);
while !self.eat(token::RBRACE) {
let vis = self.parse_visibility();
meths.push(self.parse_method(vis));
let meths_opt;
if self.eat(token::SEMI) {
meths_opt = None;
} else {
let mut meths = ~[];
self.expect(token::LBRACE);
while !self.eat(token::RBRACE) {
let vis = self.parse_visibility();
meths.push(self.parse_method(vis));
}
meths_opt = Some(move meths);
}
(ident, item_impl(tps, opt_trait, ty, meths), None)

(ident, item_impl(tps, opt_trait, ty, meths_opt), None)
}

// Instantiates ident <i> with references to <typarams> as arguments.
Expand Down
17 changes: 12 additions & 5 deletions src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ fn print_item(s: ps, &&item: @ast::item) {
print_struct(s, struct_def, tps, item.ident, item.span);
}

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

bopen(s);
for methods.each |meth| {
print_method(s, *meth);
match methods_opt {
None => {
word(s.s, ~";");
}
Some(methods) => {
bopen(s);
for methods.each |meth| {
print_method(s, *meth);
}
bclose(s, item.span);
}
}
bclose(s, item.span);
}
ast::item_trait(tps, traits, methods) => {
head(s, visibility_qualified(item.vis, ~"trait"));
Expand Down
8 changes: 5 additions & 3 deletions src/libsyntax/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,16 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
v.visit_ty_params(tps, e, v);
visit_enum_def(enum_definition, tps, e, v);
}
item_impl(tps, traits, ty, methods) => {
item_impl(tps, traits, ty, methods_opt) => {
v.visit_ty_params(tps, e, v);
for traits.each |p| {
visit_path(p.path, e, v);
}
v.visit_ty(ty, e, v);
for methods.each |m| {
visit_method_helper(*m, e, v)
for methods_opt.each |methods| {
for methods.each |m| {
visit_method_helper(*m, e, v)
}
}
}
item_class(struct_def, tps) => {
Expand Down
25 changes: 15 additions & 10 deletions src/rustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
encode_index(ebml_w, bkts, write_int);
ebml_w.end_tag();
}
item_impl(tps, opt_trait, ty, methods) => {
item_impl(tps, opt_trait, ty, methods_opt) => {
add_to_index();
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
Expand All @@ -729,10 +729,13 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
}
_ => {}
}
for methods.each |m| {
ebml_w.start_tag(tag_item_impl_method);
ebml_w.writer.write(str::to_bytes(def_to_str(local_def(m.id))));
ebml_w.end_tag();
for methods_opt.each |methods| {
for methods.each |m| {
ebml_w.start_tag(tag_item_impl_method);
let method_def_id = local_def(m.id);
ebml_w.writer.write(str::to_bytes(def_to_str(method_def_id)));
ebml_w.end_tag();
}
}
do opt_trait.iter() |associated_trait| {
encode_trait_ref(ebml_w, ecx, *associated_trait)
Expand All @@ -742,11 +745,13 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer,

let impl_path = vec::append_one(path,
ast_map::path_name(item.ident));
for methods.each |m| {
index.push({val: m.id, pos: ebml_w.writer.tell()});
encode_info_for_method(ecx, ebml_w, impl_path,
should_inline(m.attrs), item.id, *m,
vec::append(tps, m.tps));
for methods_opt.each |methods| {
for methods.each |m| {
index.push({val: m.id, pos: ebml_w.writer.tell()});
encode_info_for_method(ecx, ebml_w, impl_path,
should_inline(m.attrs), item.id, *m,
vec::append(tps, m.tps));
}
}
}
item_trait(tps, traits, ms) => {
Expand Down
102 changes: 58 additions & 44 deletions src/rustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,7 @@ impl Resolver {
visit_item(item, new_parent, visitor);
}

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

// Bail out early if there are no static methods.
let mut has_static_methods = false;
for methods.each |method| {
match method.self_ty.node {
sty_static => has_static_methods = true,
_ => {}
for methods_opt.each |methods| {
for methods.each |method| {
match method.self_ty.node {
sty_static => has_static_methods = true,
_ => {}
}
}
}

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

// For each static method...
for methods.each |method| {
match method.self_ty.node {
sty_static => {
// Add the static method to the module.
let ident = method.ident;
let (method_name_bindings, _) =
self.add_child(ident,
new_parent,
ForbidDuplicateValues,
method.span);
let def = def_fn(local_def(method.id),
method.purity);
method_name_bindings.define_value(
Public, def, method.span);
for methods_opt.each |methods| {
for methods.each |method| {
match method.self_ty.node {
sty_static => {
// Add the static method to the
// module.
let ident = method.ident;
let (method_name_bindings, _) =
self.add_child(
ident,
new_parent,
ForbidDuplicateValues,
method.span);
let def = def_fn(local_def(method.id),
method.purity);
method_name_bindings.define_value(
Public, def, method.span);
}
_ => {}
}
_ => {}
}
}
}
Expand Down Expand Up @@ -3446,12 +3452,14 @@ impl Resolver {
}

item_impl(type_parameters, implemented_traits, self_type,
methods) => {

self.resolve_implementation(item.id, item.span,
methods_opt) => {
self.resolve_implementation(item.id,
item.span,
type_parameters,
implemented_traits,
self_type, methods, visitor);
self_type,
methods_opt,
visitor);
}

item_trait(type_parameters, traits, methods) => {
Expand Down Expand Up @@ -3876,7 +3884,7 @@ impl Resolver {
type_parameters: ~[ty_param],
opt_trait_reference: Option<@trait_ref>,
self_type: @Ty,
methods: ~[@method],
opt_methods: Option<~[@method]>,
visitor: ResolveVisitor) {
// If applicable, create a rib for the type parameters.
let outer_type_parameter_count = type_parameters.len();
Expand Down Expand Up @@ -3915,27 +3923,33 @@ impl Resolver {
// Resolve the self type.
self.resolve_type(self_type, visitor);

for methods.each |method| {
// We also need a new scope for the method-specific
// type parameters.
self.resolve_method(MethodRibKind(id, Provided(method.id)),
*method,
outer_type_parameter_count,
visitor);
for opt_methods.each |methods| {
for methods.each |method| {
// We also need a new scope for the method-specific
// type parameters.
self.resolve_method(MethodRibKind(
id,
Provided(method.id)),
*method,
outer_type_parameter_count,
visitor);
/*
let borrowed_type_parameters = &method.tps;
self.resolve_function(MethodRibKind(id, Provided(method.id)),
Some(@method.decl),
HasTypeParameters
(borrowed_type_parameters,
method.id,
outer_type_parameter_count,
NormalRibKind),
method.body,
HasSelfBinding(method.self_id),
NoCaptureClause,
visitor);
let borrowed_type_parameters = &method.tps;
self.resolve_function(MethodRibKind(
id,
Provided(method.id)),
Some(@method.decl),
HasTypeParameters
(borrowed_type_parameters,
method.id,
outer_type_parameter_count,
NormalRibKind),
method.body,
HasSelfBinding(method.self_id),
NoCaptureClause,
visitor);
*/
}
}

// Restore the original trait references.
Expand Down
13 changes: 11 additions & 2 deletions src/rustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1798,8 +1798,17 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
}
}
}
ast::item_impl(tps, _, _, ms) => {
meth::trans_impl(ccx, *path, item.ident, ms, tps, None, item.id);
ast::item_impl(tps, _, _, ms_opt) => {
match ms_opt {
None => {
deriving::trans_deriving_impl(ccx, *path, item.ident, tps,
None, item.id);
}
Some(ms) => {
meth::trans_impl(ccx, *path, item.ident, ms, tps, None,
item.id);
}
}
}
ast::item_mod(m) => {
trans_mod(ccx, m);
Expand Down
21 changes: 21 additions & 0 deletions src/rustc/middle/trans/deriving.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Translation of automatically-derived trait implementations. This handles
// enums and structs only; other types cannot be automatically derived.

use middle::trans::base::get_insn_ctxt;
use middle::trans::common::crate_ctxt;
use syntax::ast::{ident, node_id, ty_param};
use syntax::ast_map::path;

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

// XXX: Unimplemented.
}

3 changes: 2 additions & 1 deletion src/rustc/middle/trans/meth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,8 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
name: ast::ident) -> ast::def_id {
if impl_id.crate == ast::local_crate {
match ccx.tcx.items.get(impl_id.node) {
ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) => {
ast_map::node_item(@{node: ast::item_impl(_, _, _, Some(ms)), _},
_) => {
method_from_methods(ms, name)
}
ast_map::node_item(@{node:
Expand Down
14 changes: 8 additions & 6 deletions src/rustc/middle/trans/reachable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,14 @@ fn traverse_public_item(cx: ctx, item: @item) {
traverse_inline_body(cx, blk);
}
}
item_impl(tps, _, _, ms) => {
for vec::each(ms) |m| {
if tps.len() > 0u || m.tps.len() > 0u ||
attr::find_inline_attr(m.attrs) != attr::ia_none {
cx.rmap.insert(m.id, ());
traverse_inline_body(cx, m.body);
item_impl(tps, _, _, ms_opt) => {
for ms_opt.each |ms| {
for vec::each(*ms) |m| {
if tps.len() > 0u || m.tps.len() > 0u ||
attr::find_inline_attr(m.attrs) != attr::ia_none {
cx.rmap.insert(m.id, ());
traverse_inline_body(cx, m.body);
}
}
}
}
Expand Down
Loading

0 comments on commit 3bf0a9b

Please sign in to comment.