about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-07-19 12:26:39 +0000
committerbors <bors@rust-lang.org>2014-07-19 12:26:39 +0000
commite0a6e2b41421928206cc71be27da1239b4598ed1 (patch)
tree09df47d31f54d773b355884f74b6323b1e08d14b
parentf05a2c97b8e41177e531c4440519333057f9ac55 (diff)
parent61ded48fbcc79e0b3d532bb17f38b1c1baf56d41 (diff)
auto merge of #15765 : luqmana/rust/iec, r=pcwalton
Fixes #15400.
-rw-r--r--src/librustc/metadata/encoder.rs12
-rw-r--r--src/librustc/middle/trans/adt.rs7
-rw-r--r--src/librustc/middle/trans/base.rs108
-rw-r--r--src/librustc/middle/trans/callee.rs77
-rw-r--r--src/librustc/middle/trans/closure.rs2
-rw-r--r--src/librustc/middle/trans/expr.rs26
-rw-r--r--src/libserialize/json.rs1
7 files changed, 144 insertions, 89 deletions
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index b86f5ee6cc2..439455ff3d1 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -314,8 +314,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
                             ebml_w: &mut Encoder,
                             id: NodeId,
                             variants: &[P<Variant>],
-                            index: &mut Vec<entry<i64>>,
-                            generics: &ast::Generics) {
+                            index: &mut Vec<entry<i64>>) {
     debug!("encode_enum_variant_info(id={:?})", id);
 
     let mut disr_val = 0;
@@ -343,10 +342,6 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
         encode_stability(ebml_w, stab);
 
         match variant.node.kind {
-            ast::TupleVariantKind(ref args)
-                    if args.len() > 0 && generics.ty_params.len() == 0 => {
-                encode_symbol(ecx, ebml_w, variant.node.id);
-            }
             ast::TupleVariantKind(_) => {},
             ast::StructVariantKind(_) => {
                 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
@@ -1019,7 +1014,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_stability(ebml_w, stab);
         ebml_w.end_tag();
       }
-      ItemEnum(ref enum_definition, ref generics) => {
+      ItemEnum(ref enum_definition, _) => {
         add_to_index(item, ebml_w, index);
 
         ebml_w.start_tag(tag_items_data_item);
@@ -1046,8 +1041,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
                                  ebml_w,
                                  item.id,
                                  (*enum_definition).variants.as_slice(),
-                                 index,
-                                 generics);
+                                 index);
       }
       ItemStruct(struct_def, _) => {
         let fields = ty::lookup_struct_fields(tcx, def_id);
diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs
index 1d0108fa3f7..54c30e72154 100644
--- a/src/librustc/middle/trans/adt.rs
+++ b/src/librustc/middle/trans/adt.rs
@@ -674,11 +674,10 @@ pub fn trans_case<'a>(bcx: &'a Block<'a>, r: &Repr, discr: Disr)
 }
 
 /**
- * Begin initializing a new value of the given case of the given
- * representation.  The fields, if any, should then be initialized via
- * `trans_field_ptr`.
+ * Set the discriminant for a new value of the given case of the given
+ * representation.
  */
-pub fn trans_start_init(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) {
+pub fn trans_set_discr(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) {
     match *r {
         CEnum(ity, min, max) => {
             assert_discr_in_range(ity, min, max, discr);
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 98342bfbcdc..7d7922ebfa9 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -80,7 +80,6 @@ use std::c_str::ToCStr;
 use std::cell::{Cell, RefCell};
 use std::rc::Rc;
 use std::{i8, i16, i32, i64};
-use std::gc::Gc;
 use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel, Rust, RustCall};
 use syntax::abi::{RustIntrinsic, Abi};
 use syntax::ast_util::{local_def, is_local};
@@ -1704,6 +1703,59 @@ pub fn trans_enum_variant(ccx: &CrateContext,
         llfndecl);
 }
 
+pub fn trans_named_tuple_constructor<'a>(mut bcx: &'a Block<'a>,
+                                         ctor_ty: ty::t,
+                                         disr: ty::Disr,
+                                         args: callee::CallArgs,
+                                         dest: expr::Dest) -> Result<'a> {
+
+    let ccx = bcx.fcx.ccx;
+    let tcx = &ccx.tcx;
+
+    let result_ty = match ty::get(ctor_ty).sty {
+        ty::ty_bare_fn(ref bft) => bft.sig.output,
+        _ => ccx.sess().bug(
+            format!("trans_enum_variant_constructor: \
+                     unexpected ctor return type {}",
+                     ctor_ty.repr(tcx)).as_slice())
+    };
+
+    // Get location to store the result. If the user does not care about
+    // the result, just make a stack slot
+    let llresult = match dest {
+        expr::SaveIn(d) => d,
+        expr::Ignore => {
+            if !type_is_zero_size(ccx, result_ty) {
+                alloc_ty(bcx, result_ty, "constructor_result")
+            } else {
+                C_undef(type_of::type_of(ccx, result_ty))
+            }
+        }
+    };
+
+    if !type_is_zero_size(ccx, result_ty) {
+        let repr = adt::represent_type(ccx, result_ty);
+
+        match args {
+            callee::ArgExprs(exprs) => {
+                let fields = exprs.iter().map(|x| *x).enumerate().collect::<Vec<_>>();
+                bcx = expr::trans_adt(bcx, &*repr, disr, fields.as_slice(),
+                                      None, expr::SaveIn(llresult));
+            }
+            _ => ccx.sess().bug("expected expr as arguments for variant/struct tuple constructor")
+        }
+    }
+
+    // If the caller doesn't care about the result
+    // drop the temporary we made
+    let bcx = match dest {
+        expr::SaveIn(_) => bcx,
+        expr::Ignore => glue::drop_ty(bcx, llresult, result_ty)
+    };
+
+    Result::new(bcx, llresult)
+}
+
 pub fn trans_tuple_struct(ccx: &CrateContext,
                           _fields: &[ast::StructField],
                           ctor_id: ast::NodeId,
@@ -1746,7 +1798,6 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
 
     if !type_is_zero_size(fcx.ccx, result_ty) {
         let repr = adt::represent_type(ccx, result_ty);
-        adt::trans_start_init(bcx, &*repr, fcx.llretptr.get().unwrap(), disr);
         for (i, arg_datum) in arg_datums.move_iter().enumerate() {
             let lldestptr = adt::trans_field_ptr(bcx,
                                                  &*repr,
@@ -1755,36 +1806,12 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
                                                  i);
             arg_datum.store_to(bcx, lldestptr);
         }
+        adt::trans_set_discr(bcx, &*repr, fcx.llretptr.get().unwrap(), disr);
     }
 
     finish_fn(&fcx, bcx, result_ty);
 }
 
-fn trans_enum_def(ccx: &CrateContext, enum_definition: &ast::EnumDef,
-                  sp: Span, id: ast::NodeId, vi: &[Rc<ty::VariantInfo>],
-                  i: &mut uint) {
-    for variant in enum_definition.variants.iter() {
-        let disr_val = vi[*i].disr_val;
-        *i += 1;
-
-        match variant.node.kind {
-            ast::TupleVariantKind(ref args) if args.len() > 0 => {
-                let llfn = get_item_val(ccx, variant.node.id);
-                trans_enum_variant(ccx, id, &**variant, args.as_slice(),
-                                   disr_val, &param_substs::empty(), llfn);
-            }
-            ast::TupleVariantKind(_) => {
-                // Nothing to do.
-            }
-            ast::StructVariantKind(struct_def) => {
-                trans_struct_def(ccx, struct_def);
-            }
-        }
-    }
-
-    enum_variant_size_lint(ccx, enum_definition, sp, id);
-}
-
 fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &ast::EnumDef, sp: Span, id: ast::NodeId) {
     let mut sizes = Vec::new(); // does no allocation if no pushes, thankfully
 
@@ -1877,12 +1904,8 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
       ast::ItemMod(ref m) => {
         trans_mod(ccx, m);
       }
-      ast::ItemEnum(ref enum_definition, ref generics) => {
-        if !generics.is_type_parameterized() {
-            let vi = ty::enum_variants(ccx.tcx(), local_def(item.id));
-            let mut i = 0;
-            trans_enum_def(ccx, enum_definition, item.span, item.id, vi.as_slice(), &mut i);
-        }
+      ast::ItemEnum(ref enum_definition, _) => {
+        enum_variant_size_lint(ccx, enum_definition, item.span, item.id);
       }
       ast::ItemStatic(_, m, ref expr) => {
           // Recurse on the expression to catch items in blocks
@@ -1909,11 +1932,6 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
       ast::ItemForeignMod(ref foreign_mod) => {
         foreign::trans_foreign_mod(ccx, foreign_mod);
       }
-      ast::ItemStruct(struct_def, ref generics) => {
-        if !generics.is_type_parameterized() {
-            trans_struct_def(ccx, struct_def);
-        }
-      }
       ast::ItemTrait(..) => {
         // Inside of this trait definition, we won't be actually translating any
         // functions, but the trait still needs to be walked. Otherwise default
@@ -1926,20 +1944,6 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
     }
 }
 
-pub fn trans_struct_def(ccx: &CrateContext, struct_def: Gc<ast::StructDef>) {
-    // If this is a tuple-like struct, translate the constructor.
-    match struct_def.ctor_id {
-        // We only need to translate a constructor if there are fields;
-        // otherwise this is a unit-like struct.
-        Some(ctor_id) if struct_def.fields.len() > 0 => {
-            let llfndecl = get_item_val(ccx, ctor_id);
-            trans_tuple_struct(ccx, struct_def.fields.as_slice(),
-                               ctor_id, &param_substs::empty(), llfndecl);
-        }
-        Some(_) | None => {}
-    }
-}
-
 // Translate a module. Doing this amounts to translating the items in the
 // module; there ends up being no artifact (aside from linkage names) of
 // separate modules in the compiled program.  That's because modules exist
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 8eab227ad16..e2ad8b4fd46 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -19,6 +19,7 @@
 use arena::TypedArena;
 use back::abi;
 use back::link;
+use driver::session;
 use llvm::{ValueRef, get_param};
 use llvm;
 use metadata::csearch;
@@ -54,6 +55,7 @@ use util::ppaux::Repr;
 
 use std::gc::Gc;
 use syntax::ast;
+use syntax::ast_map;
 use synabi = syntax::abi;
 
 pub struct MethodData {
@@ -64,6 +66,10 @@ pub struct MethodData {
 pub enum CalleeData {
     Closure(Datum<Lvalue>),
 
+    // Constructor for enum variant/tuple-like-struct
+    // i.e. Some, Ok
+    NamedTupleConstructor(subst::Substs, ty::Disr),
+
     // Represents a (possibly monomorphized) top-level fn item or method
     // item. Note that this is just the fn-ptr and is not a Rust closure
     // value (which is a pair).
@@ -134,6 +140,23 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
         debug!("trans_def(def={}, ref_expr={})", def.repr(bcx.tcx()), ref_expr.repr(bcx.tcx()));
         let expr_ty = node_id_type(bcx, ref_expr.id);
         match def {
+            def::DefFn(did, _) if {
+                let def_id = if did.krate != ast::LOCAL_CRATE {
+                    inline::maybe_instantiate_inline(bcx.ccx(), did)
+                } else {
+                    did
+                };
+                match bcx.tcx().map.find(def_id.node) {
+                    Some(ast_map::NodeStructCtor(_)) => true,
+                    _ => false
+                }
+            } => {
+                let substs = node_id_substs(bcx, ExprId(ref_expr.id));
+                Callee {
+                    bcx: bcx,
+                    data: NamedTupleConstructor(substs, 0)
+                }
+            }
             def::DefFn(did, _) if match ty::get(expr_ty).sty {
                 ty::ty_bare_fn(ref f) => f.abi == synabi::RustIntrinsic,
                 _ => false
@@ -158,14 +181,23 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
                                                                 ref_expr.id))
             }
             def::DefVariant(tid, vid, _) => {
-                // nullary variants are not callable
-                assert!(ty::enum_variant_with_id(bcx.tcx(),
-                                                      tid,
-                                                      vid).args.len() > 0u);
-                fn_callee(bcx, trans_fn_ref(bcx, vid, ExprId(ref_expr.id)))
+                let vinfo = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
+                let substs = node_id_substs(bcx, ExprId(ref_expr.id));
+
+                // Nullary variants are not callable
+                assert!(vinfo.args.len() > 0u);
+
+                Callee {
+                    bcx: bcx,
+                    data: NamedTupleConstructor(substs, vinfo.disr_val)
+                }
             }
-            def::DefStruct(def_id) => {
-                fn_callee(bcx, trans_fn_ref(bcx, def_id, ExprId(ref_expr.id)))
+            def::DefStruct(_) => {
+                let substs = node_id_substs(bcx, ExprId(ref_expr.id));
+                Callee {
+                    bcx: bcx,
+                    data: NamedTupleConstructor(substs, 0)
+                }
             }
             def::DefStatic(..) |
             def::DefArg(..) |
@@ -490,8 +522,27 @@ pub fn trans_fn_ref_with_vtables(
         }
     };
 
-    // We must monomorphise if the fn has type parameters or is a default method.
-    let must_monomorphise = !substs.types.is_empty() || is_default;
+    // We must monomorphise if the fn has type parameters, is a default method,
+    // or is a named tuple constructor.
+    let must_monomorphise = if !substs.types.is_empty() || is_default {
+        true
+    } else if def_id.krate == ast::LOCAL_CRATE {
+        let map_node = session::expect(
+            ccx.sess(),
+            tcx.map.find(def_id.node),
+            || "local item should be in ast map".to_string());
+
+        match map_node {
+            ast_map::NodeVariant(v) => match v.node.kind {
+                ast::TupleVariantKind(ref args) => args.len() > 0,
+                _ => false
+            },
+            ast_map::NodeStructCtor(_) => true,
+            _ => false
+        }
+    } else {
+        false
+    };
 
     // Create a monomorphic version of generic functions
     if must_monomorphise {
@@ -710,6 +761,14 @@ pub fn trans_call_inner<'a>(
                                                    arg_cleanup_scope, args,
                                                    dest.unwrap(), substs);
         }
+        NamedTupleConstructor(substs, disr) => {
+            assert!(dest.is_some());
+            fcx.pop_custom_cleanup_scope(arg_cleanup_scope);
+
+            let ctor_ty = callee_ty.subst(bcx.tcx(), &substs);
+            return base::trans_named_tuple_constructor(bcx, ctor_ty, disr,
+                                                       args, dest.unwrap());
+        }
     };
 
     // Intrinsics should not become actual functions.
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index a3d8ab1733f..ed6050b6543 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -502,7 +502,6 @@ pub fn trans_unboxed_closure<'a>(
     let repr = adt::represent_type(bcx.ccx(), node_id_type(bcx, id));
 
     // Create the closure.
-    adt::trans_start_init(bcx, &*repr, dest_addr, 0);
     for freevar in freevars_ptr.iter() {
         let datum = expr::trans_local_var(bcx, freevar.def);
         let upvar_slot_dest = adt::trans_field_ptr(bcx,
@@ -512,6 +511,7 @@ pub fn trans_unboxed_closure<'a>(
                                                    0);
         bcx = datum.store_to(bcx, upvar_slot_dest);
     }
+    adt::trans_set_discr(bcx, &*repr, dest_addr, 0);
 
     bcx
 }
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index e7bde00b3de..68f577faefe 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -876,8 +876,8 @@ fn trans_def_dps_unadjusted<'a>(
                 // Nullary variant.
                 let ty = expr_ty(bcx, ref_expr);
                 let repr = adt::represent_type(bcx.ccx(), ty);
-                adt::trans_start_init(bcx, &*repr, lldest,
-                                      variant_info.disr_val);
+                adt::trans_set_discr(bcx, &*repr, lldest,
+                                     variant_info.disr_val);
                 return bcx;
             }
         }
@@ -886,7 +886,7 @@ fn trans_def_dps_unadjusted<'a>(
             match ty::get(ty).sty {
                 ty::ty_struct(did, _) if ty::has_dtor(bcx.tcx(), did) => {
                     let repr = adt::represent_type(bcx.ccx(), ty);
-                    adt::trans_start_init(bcx, &*repr, lldest, 0);
+                    adt::trans_set_discr(bcx, &*repr, lldest, 0);
                 }
                 _ => {}
             }
@@ -1098,7 +1098,7 @@ fn trans_rec_or_struct<'a>(
  * Note that `fields` may be empty; the base expression must always be
  * evaluated for side-effects.
  */
-struct StructBaseInfo {
+pub struct StructBaseInfo {
     /// The base expression; will be evaluated after all explicit fields.
     expr: Gc<ast::Expr>,
     /// The indices of fields to copy paired with their types.
@@ -1114,14 +1114,12 @@ struct StructBaseInfo {
  * - `optbase` contains information on the base struct (if any) from
  * which remaining fields are copied; see comments on `StructBaseInfo`.
  */
-fn trans_adt<'a>(
-             bcx: &'a Block<'a>,
-             repr: &adt::Repr,
-             discr: ty::Disr,
-             fields: &[(uint, Gc<ast::Expr>)],
-             optbase: Option<StructBaseInfo>,
-             dest: Dest)
-             -> &'a Block<'a> {
+pub fn trans_adt<'a>(bcx: &'a Block<'a>,
+                     repr: &adt::Repr,
+                     discr: ty::Disr,
+                     fields: &[(uint, Gc<ast::Expr>)],
+                     optbase: Option<StructBaseInfo>,
+                     dest: Dest) -> &'a Block<'a> {
     let _icx = push_ctxt("trans_adt");
     let fcx = bcx.fcx;
     let mut bcx = bcx;
@@ -1143,8 +1141,6 @@ fn trans_adt<'a>(
     // failure occur before the ADT as a whole is ready.
     let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
 
-    adt::trans_start_init(bcx, repr, addr, discr);
-
     for &(i, ref e) in fields.iter() {
         let dest = adt::trans_field_ptr(bcx, repr, addr, discr, i);
         let e_ty = expr_ty_adjusted(bcx, &**e);
@@ -1166,6 +1162,8 @@ fn trans_adt<'a>(
         }
     }
 
+    adt::trans_set_discr(bcx, repr, addr, discr);
+
     fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
 
     return bcx;
diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs
index e28c51d517e..a56904c9ef4 100644
--- a/src/libserialize/json.rs
+++ b/src/libserialize/json.rs
@@ -2795,6 +2795,7 @@ mod tests {
         }
     }
     #[test]
+    #[ignore] // FIXME(#15763)
     fn test_decode_errors_struct() {
         check_err::<DecodeStruct>("[]", ExpectedError("Object".to_string(), "[]".to_string()));
         check_err::<DecodeStruct>("{\"x\": true, \"y\": true, \"z\": \"\", \"w\": []}",