From 4cd3d4ab1ec70f7d572c585168b225a3ce83100a Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 20 Feb 2012 21:37:37 -0800 Subject: [PATCH] More work on typechecking classes classes-simple doesn't fail until trans now! --- src/comp/middle/ty.rs | 1 - src/comp/middle/typeck.rs | 54 ++++++++++++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 3e9822ab4fd9..2bd37585d04d 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -2493,7 +2493,6 @@ fn enum_variant_with_id(cx: ctxt, enum_id: ast::def_id, // If the given item is in an external crate, looks up its type and adds it to // the type cache. Returns the type parameters and type. -// a precondition (did.crate != ast::local_crate) would be nice fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_bounds_and_ty { alt cx.tcache.find(did) { some(tpt) { ret tpt; } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 69db4b8bca69..f844ad4c2eae 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -209,7 +209,7 @@ fn structurally_resolved_type(fcx: @fn_ctxt, sp: span, tp: ty::t) -> ty::t { } -// Returns the one-level-deep structure of the given type.f +// Returns the one-level-deep structure of the given type. fn structure_of(fcx: @fn_ctxt, sp: span, typ: ty::t) -> ty::sty { ty::get(structurally_resolved_type(fcx, sp, typ)).struct } @@ -1835,6 +1835,30 @@ fn lookup_method_inner(fcx: @fn_ctxt, expr: @ast::expr, result } +fn lookup_field_ty(cx: ty::ctxt, items:[@ast::class_item], + fieldname: ast::ident, sp: span) + -> ty::t { + for item in items { + // this is an access outside the class, so accessing a private + // field is an error + alt item.node.decl { + ast::instance_var(declname, t, _, _) if declname == fieldname { + alt item.node.privacy { + ast::priv { + cx.sess.span_fatal(sp, "Accessed private field outside \ + its enclosing class"); + } + ast::pub { + ret ast_ty_to_ty(cx, m_check, t); + } + } + } + _ { /* do nothing */ } + } + } + cx.sess.span_fatal(sp, #fmt("Unbound field %s", fieldname)); +} + fn check_expr_fn_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, proto: ast::proto, @@ -2507,11 +2531,29 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, _ {} } } - ty::ty_class(_id, _params) { - // TODO (classes) - tcx.sess.span_bug(expr.span, - #fmt("can't check class field accesses yet: %s", - ty_to_str(fcx.ccx.tcx, base_t))); + ty::ty_class(base_id, _params) { + // (1) verify that the class id actually has a field called + // field + // For now, this code assumes the class is defined in the local + // crate + // TODO: handle field references to classes in external crate + let err = "Class ID is not bound to a class"; + let field_ty = alt fcx.ccx.tcx.items.find(base_id.node) { + some(ast_map::node_item(i,_)) { + alt i.node { + ast::item_class(_, items, _, _, _) { + lookup_field_ty(fcx.ccx.tcx, items, field, + expr.span) + } + _ { fcx.ccx.tcx.sess.span_bug(expr.span, err); } + } + } + _ { fcx.ccx.tcx.sess.span_bug(expr.span, err); } + }; + // (2) look up what field's type is, and return it + // TODO: actually instantiate any type params + write_ty(tcx, id, field_ty); + handled = true; } _ {} }