From a3be0b105436118e187ea52deb89788afaf1edb5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 24 May 2012 06:20:46 -0700 Subject: [PATCH] fix classes and parameterized ifaces; remove needless self check ref #1726, #2434 --- src/rustc/driver/driver.rs | 2 - src/rustc/middle/check_self.rs | 60 ------------------- src/rustc/middle/typeck/collect.rs | 19 +++--- src/rustc/rustc.rc | 1 - src/test/compile-fail/issue-2294.rs | 6 -- .../run-pass/class-iface-bounded-param.rs | 23 +++++++ src/test/run-pass/class-implement-ifaces.rs | 6 +- 7 files changed, 39 insertions(+), 78 deletions(-) delete mode 100644 src/rustc/middle/check_self.rs delete mode 100644 src/test/compile-fail/issue-2294.rs create mode 100644 src/test/run-pass/class-iface-bounded-param.rs diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs index 655a6f82b78..82a42700ea1 100644 --- a/src/rustc/driver/driver.rs +++ b/src/rustc/driver/driver.rs @@ -192,8 +192,6 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, bind middle::check_loop::check_crate(ty_cx, crate)); time(time_passes, "alt checking", bind middle::check_alt::check_crate(ty_cx, crate)); - time(time_passes, "self checking", - bind middle::check_self::check_crate(ty_cx, crate)); time(time_passes, "typestate checking", bind middle::tstate::ck::check_crate(ty_cx, crate)); let (root_map, mutbl_map) = time( diff --git a/src/rustc/middle/check_self.rs b/src/rustc/middle/check_self.rs deleted file mode 100644 index b1d2c4b8215..00000000000 --- a/src/rustc/middle/check_self.rs +++ /dev/null @@ -1,60 +0,0 @@ -/* - This module checks that within a class, "self" doesn't escape. - That is, it rejects any class in which "self" occurs other than - as the left-hand side of a field reference. - */ -import syntax::ast::*; -import syntax::visit::*; -import driver::session::session; -import std::map::hashmap; -import resolve::def_map; - -fn check_crate(cx: ty::ctxt, crate: @crate) { - visit_crate(*crate, cx, mk_vt(@{ - visit_item: bind check_item(_, _, _) - with *default_visitor() - })); - cx.sess.abort_if_errors(); -} - -fn check_item(it: @item, &&cx: ty::ctxt, &&_v: vt) { - alt it.node { - item_class(*) { - visit_item(it, cx, check_self_visitor()); - } - _ {} - } -} - -fn check_self_visitor() -> vt { - mk_vt(@{ - visit_expr: bind check_self_expr(_, _, _) - with *default_visitor() - }) -} - -fn check_self_expr(e: @expr, &&cx: ty::ctxt, &&v: vt) { - alt e.node { - expr_field(@{node: expr_path(p),_},_,_) { - // self is ok here; don't descend - } - expr_path(_) { - alt cx.def_map.find(e.id) { - some(def_self(_)) { - cx.sess.span_err(e.span, "can't return self or store \ - it in a data structure"); - } - _ {} - } - } - _ { visit_expr(e, cx, v); } - } -} - -// Local Variables: -// mode: rust -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// End: diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index 69c2e778d3d..0674a5e79df 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -359,8 +359,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) { // Write the class type let tpt = ty_of_item(ccx, it); write_ty_to_tcx(tcx, it.id, tpt.ty); - tcx.tcache.insert(local_def(it.id), {bounds: tpt.bounds, - rp: rp, ty: tpt.ty}); + tcx.tcache.insert(local_def(it.id), tpt); // Write the ctor type let t_ctor = ty::mk_fn( @@ -416,13 +415,17 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) { for ifaces.each { |ifce| check_methods_against_iface(ccx, tps, rp, selfty, ifce, methods); - let t = ty::node_id_to_type(tcx, ifce.id); - // FIXME: This assumes classes only implement - // non-parameterized ifaces. add a test case for - // a class implementing a parameterized iface. - // -- tjc (#1726) - tcx.tcache.insert(local_def(ifce.id), no_params(t)); + // FIXME #2434---this is somewhat bogus, but it seems that + // the id of iface_ref is also the id of the impl, and so + // we want to store the "self type" of the impl---in this + // case, the class. The reason I say this is somewhat + // bogus (and should be refactored) is that the tcache + // stores the class type for ifce.id but the node_type + // table stores the iface type. Weird. Probably just + // adding a "self type" table rather than overloading the + // tcache would be ok, or else adding more than one id. + tcx.tcache.insert(local_def(ifce.id), tpt); } } _ { diff --git a/src/rustc/rustc.rc b/src/rustc/rustc.rc index 2f75a7c2e22..b3956c2ab02 100644 --- a/src/rustc/rustc.rc +++ b/src/rustc/rustc.rc @@ -68,7 +68,6 @@ mod middle { mod check_loop; mod check_alt; mod check_const; - mod check_self; mod lint; mod borrowck; mod alias; diff --git a/src/test/compile-fail/issue-2294.rs b/src/test/compile-fail/issue-2294.rs deleted file mode 100644 index 292a4aa3947..00000000000 --- a/src/test/compile-fail/issue-2294.rs +++ /dev/null @@ -1,6 +0,0 @@ -class cat { - fn kitty() -> cat { self } //! ERROR: can't return self or store it in a data structure - new() { } -} - -fn main() {} diff --git a/src/test/run-pass/class-iface-bounded-param.rs b/src/test/run-pass/class-iface-bounded-param.rs new file mode 100644 index 00000000000..fd0ea20b5fb --- /dev/null +++ b/src/test/run-pass/class-iface-bounded-param.rs @@ -0,0 +1,23 @@ +use std; +import std::map::{map, hashmap, int_hash}; + +class keys> + implements iter::base_iter { + + let map: M; + + new(map: M) { + self.map = map; + } + + fn each(blk: fn(K) -> bool) { self.map.each { |k, _v| blk(k)} } + fn size_hint() -> option { some(self.map.size()) } + fn eachi(blk: fn(uint, K) -> bool) { iter::eachi(self, blk) } +} + +fn main() { + let m = int_hash(); + m.insert(1, 2); + m.insert(3, 4); + assert iter::to_vec(keys(m)) == [1, 3]; +} diff --git a/src/test/run-pass/class-implement-ifaces.rs b/src/test/run-pass/class-implement-ifaces.rs index 01fde15d02d..e19f06b3b7d 100644 --- a/src/test/run-pass/class-implement-ifaces.rs +++ b/src/test/run-pass/class-implement-ifaces.rs @@ -35,10 +35,14 @@ class cat implements noisy { } } +fn make_speak(c: C) { + c.speak(); +} + fn main() { let nyan = cat(0u, 2, "nyan"); nyan.eat(); assert(!nyan.eat()); - uint::range(1u, 10u, {|_i| nyan.speak(); }); + uint::range(1u, 10u, {|_i| make_speak(nyan); }); assert(nyan.eat()); } \ No newline at end of file