Skip to content

Implement construction of monomorphic struct-like variants #3844

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions src/rustc/middle/privacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

use /*mod*/ syntax::ast;
use /*mod*/ syntax::visit;
use syntax::ast::{expr_field, expr_struct, ident, item_class, item_impl};
use syntax::ast::{item_trait, local_crate, node_id, pat_struct, private};
use syntax::ast::{provided, required};
use syntax::ast::{def_variant, expr_field, expr_struct, ident, item_class};
use syntax::ast::{item_impl, item_trait, local_crate, node_id, pat_struct};
use syntax::ast::{private, provided, required};
use syntax::ast_map::{node_item, node_method};
use ty::ty_class;
use ty::{ty_class, ty_enum};
use typeck::{method_map, method_origin, method_param, method_self};
use typeck::{method_static, method_trait};

Expand Down Expand Up @@ -188,6 +188,30 @@ fn check_crate(tcx: ty::ctxt, method_map: &method_map, crate: @ast::crate) {
}
}
}
ty_enum(id, _) => {
if id.crate != local_crate ||
!privileged_items.contains(&(id.node)) {
match tcx.def_map.get(expr.id) {
def_variant(_, variant_id) => {
for fields.each |field| {
debug!("(privacy checking) \
checking field in \
struct variant \
literal");
check_field(expr.span, variant_id,
field.node.ident);
}
}
_ => {
tcx.sess.span_bug(expr.span,
~"resolve didn't \
map enum struct \
constructor to a \
variant def");
}
}
}
}
_ => {
tcx.sess.span_bug(expr.span, ~"struct expr \
didn't have \
Expand Down
4 changes: 2 additions & 2 deletions src/rustc/middle/trans/alt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,7 @@ fn compile_submatch(bcx: block,
let rec_fields = collect_record_or_struct_fields(m, col);
if rec_fields.len() > 0 {
let pat_ty = node_id_type(bcx, pat_id);
do expr::with_field_tys(tcx, pat_ty) |_has_dtor, field_tys| {
do expr::with_field_tys(tcx, pat_ty, None) |_has_dtor, field_tys| {
let rec_vals = rec_fields.map(|field_name| {
let ix = ty::field_idx_strict(tcx, *field_name, field_tys);
GEPi(bcx, val, struct_field(ix))
Expand Down Expand Up @@ -1257,7 +1257,7 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
ast::pat_rec(fields, _) | ast::pat_struct(_, fields, _) => {
let tcx = bcx.tcx();
let pat_ty = node_id_type(bcx, pat.id);
do expr::with_field_tys(tcx, pat_ty) |_has_dtor, field_tys| {
do expr::with_field_tys(tcx, pat_ty, None) |_hd, field_tys| {
for vec::each(fields) |f| {
let ix = ty::field_idx_strict(tcx, f.ident, field_tys);
let fldptr = GEPi(bcx, val, struct_field(ix));
Expand Down
2 changes: 1 addition & 1 deletion src/rustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
let mut cx = cx;
match ty::get(t).sty {
ty::ty_rec(*) | ty::ty_class(*) => {
do expr::with_field_tys(cx.tcx(), t) |_has_dtor, field_tys| {
do expr::with_field_tys(cx.tcx(), t, None) |_has_dtor, field_tys| {
for vec::eachi(field_tys) |i, field_ty| {
let llfld_a = GEPi(cx, av, struct_field(i));
cx = f(cx, llfld_a, field_ty.mt.ty);
Expand Down
6 changes: 4 additions & 2 deletions src/rustc/middle/trans/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
let bt = ty::expr_ty(cx.tcx, base);
let bv = const_expr(cx, base);
let (bt, bv) = const_autoderef(cx, bt, bv);
do expr::with_field_tys(cx.tcx, bt) |_has_dtor, field_tys| {
do expr::with_field_tys(cx.tcx, bt, None) |_has_dtor, field_tys| {
let ix = ty::field_idx_strict(cx.tcx, field, field_tys);

// Note: ideally, we'd use `struct_field()` here instead
Expand Down Expand Up @@ -294,7 +294,9 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
}
ast::expr_struct(_, ref fs, _) => {
let ety = ty::expr_ty(cx.tcx, e);
let cs = do expr::with_field_tys(cx.tcx, ety) |_hd, field_tys| {
let cs = do expr::with_field_tys(cx.tcx,
ety,
None) |_hd, field_tys| {
field_tys.map(|field_ty| {
match fs.find(|f| field_ty.ident == f.node.ident) {
Some(f) => const_expr(cx, f.node.expr),
Expand Down
68 changes: 65 additions & 3 deletions src/rustc/middle/trans/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,9 @@ fn fn_data_to_datum(bcx: block,
return bcx;
}

fn with_field_tys<R>(tcx: ty::ctxt, ty: ty::t,
fn with_field_tys<R>(tcx: ty::ctxt,
ty: ty::t,
node_id_opt: Option<ast::node_id>,
op: fn(bool, (&[ty::field])) -> R) -> R {
match ty::get(ty).sty {
ty::ty_rec(ref fields) => {
Expand All @@ -867,6 +869,30 @@ fn with_field_tys<R>(tcx: ty::ctxt, ty: ty::t,
op(has_dtor, class_items_as_mutable_fields(tcx, did, substs))
}

ty::ty_enum(_, ref substs) => {
// We want the *variant* ID here, not the enum ID.
match node_id_opt {
None => {
tcx.sess.bug(fmt!(
"cannot get field types from the enum type %s \
without a node ID",
ty_to_str(tcx, ty)));
}
Some(node_id) => {
match tcx.def_map.get(node_id) {
ast::def_variant(_, variant_id) => {
op(false, class_items_as_mutable_fields(
tcx, variant_id, substs))
}
_ => {
tcx.sess.bug(~"resolve didn't map this expr to a \
variant ID")
}
}
}
}
}

_ => {
tcx.sess.bug(fmt!(
"cannot get field types from the type %s",
Expand All @@ -882,7 +908,7 @@ fn trans_rec_field(bcx: block,
let _icx = bcx.insn_ctxt("trans_rec_field");

let base_datum = unpack_datum!(bcx, trans_to_datum(bcx, base));
do with_field_tys(bcx.tcx(), base_datum.ty) |_has_dtor, field_tys| {
do with_field_tys(bcx.tcx(), base_datum.ty, None) |_dtor, field_tys| {
let ix = ty::field_idx_strict(bcx.tcx(), field, field_tys);
DatumBlock {
datum: base_datum.GEPi(bcx, [0u, 0u, ix], field_tys[ix].mt.ty),
Expand Down Expand Up @@ -974,9 +1000,45 @@ fn trans_rec_or_struct(bcx: block,
}
}

// If this is a struct-like variant, write in the discriminant if
// necessary, position the address at the right location, and cast the
// address.
let ty = node_id_type(bcx, id);
let tcx = bcx.tcx();
do with_field_tys(tcx, ty) |has_dtor, field_tys| {
let addr = match ty::get(ty).sty {
ty::ty_enum(_, ref substs) => {
match tcx.def_map.get(id) {
ast::def_variant(enum_id, variant_id) => {
let variant_info = ty::enum_variant_with_id(
tcx, enum_id, variant_id);
let addr = if ty::enum_is_univariant(tcx, enum_id) {
addr
} else {
Store(bcx,
C_int(bcx.ccx(), variant_info.disr_val),
GEPi(bcx, addr, [0, 0]));
GEPi(bcx, addr, [0, 1])
};
let fields = ty::class_items_as_mutable_fields(
tcx, variant_id, substs);
let field_lltys = do fields.map |field| {
type_of(bcx.ccx(),
ty::subst_tps(
tcx, substs.tps, None, field.mt.ty))
};
PointerCast(bcx, addr,
T_ptr(T_struct(~[T_struct(field_lltys)])))
}
_ => {
tcx.sess.bug(~"resolve didn't write the right def in for \
this struct-like variant")
}
}
}
_ => addr
};

do with_field_tys(tcx, ty, Some(id)) |has_dtor, field_tys| {
// evaluate each of the fields and store them into their
// correct locations
let mut temp_cleanups = ~[];
Expand Down
11 changes: 11 additions & 0 deletions src/rustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3722,6 +3722,17 @@ fn lookup_class_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] {
_ => cx.sess.bug(~"class ID bound to non-class")
}
}
Some(ast_map::node_variant(variant, _, _)) => {
match variant.node.kind {
ast::struct_variant_kind(struct_def) => {
class_field_tys(struct_def.fields)
}
_ => {
cx.sess.bug(~"struct ID bound to enum variant that isn't \
struct-like")
}
}
}
_ => {
cx.sess.bug(
fmt!("class ID not bound to an item: %s",
Expand Down
Loading