Merge pull request #3885 from pcwalton/master

rustc: Implement typechecking for automatically-derived enums
This commit is contained in:
Patrick Walton 2012-10-29 14:23:22 -07:00
commit dd76050e51
3 changed files with 79 additions and 2 deletions

View File

@ -387,6 +387,11 @@ struct DerivedMethodInfo {
deriving_struct_methods: HashMap<ast::def_id,
@~[typeck::method_origin]>,
// The outer vector here describes each enum variant, while the inner
// nested vector describes each enum variant argument.
deriving_enum_methods: HashMap<ast::def_id,
@~[@~[typeck::method_origin]]>,
// A mapping from the def ID of a method that was automatically derived
// to information about it.
automatically_derived_methods: HashMap<ast::def_id, DerivedMethodInfo>,
@ -959,6 +964,7 @@ fn mk_ctxt(s: session::Session,
provided_method_sources: HashMap(),
supertraits: HashMap(),
deriving_struct_methods: HashMap(),
deriving_enum_methods: HashMap(),
automatically_derived_methods: HashMap(),
automatically_derived_methods_for_impl: HashMap()}
}

View File

@ -113,6 +113,48 @@ trait `%s`",
tcx.deriving_struct_methods.insert(local_def(impl_id), field_info);
}
fn check_deriving_for_enum(enum_def_id: def_id,
enum_substs: &substs,
trait_ref: @trait_ref,
impl_id: node_id,
impl_span: span) {
let tcx = self.crate_context.tcx;
let enum_methods = dvec::DVec();
let variants = ty::substd_enum_variants(
tcx, enum_def_id, enum_substs);
for variants.each |enum_variant_info| {
let variant_methods = dvec::DVec();
for enum_variant_info.args.eachi |i, variant_arg_type| {
match self.check_deriving_for_substructure_type(
*variant_arg_type, trait_ref, impl_span) {
Some(method_target_def_id) => {
variant_methods.push(method_static(
method_target_def_id));
}
None => {
let trait_str = pprust::path_to_str(
trait_ref.path, tcx.sess.parse_sess.interner);
tcx.sess.span_err(impl_span,
fmt!("cannot automatically derive \
an implementation for `%s`: \
argument %u of variant `%s` \
does not implement the trait \
`%s`",
trait_str,
i + 1,
tcx.sess.str_of(
enum_variant_info.name),
trait_str));
}
}
}
enum_methods.push(@dvec::unwrap(move variant_methods));
}
let enum_methods = @dvec::unwrap(move enum_methods);
tcx.deriving_enum_methods.insert(local_def(impl_id), enum_methods);
}
fn check_deriving(crate: @crate) {
let tcx = self.crate_context.tcx;
visit_crate(*crate, (), mk_simple_visitor(@{
@ -123,8 +165,13 @@ fn check_deriving(crate: @crate) {
let superty = ty::lookup_item_type(
tcx, local_def(item.id)).ty;
match ty::get(superty).sty {
ty_enum(_def_id, _substs) => {
// XXX: Handle enums.
ty_enum(def_id, ref substs) => {
self.check_deriving_for_enum(
def_id,
substs,
trait_ref,
item.id,
item.span);
}
ty_class(def_id, ref substs) => {
self.check_deriving_for_struct(

View File

@ -0,0 +1,24 @@
trait MyEq {
pure fn eq(other: &self) -> bool;
}
struct A {
x: int
}
enum B {
C(A),
D(A),
E(A)
}
impl B : MyEq;
//~^ ERROR cannot automatically derive
//~^^ ERROR cannot automatically derive
//~^^^ ERROR cannot automatically derive
fn main() {
let c = C(A { x: 15 });
assert c.eq(&c);
}