From 51a30691c50a86542ac9b0ba052017bb66df9d77 Mon Sep 17 00:00:00 2001
From: Jeff Bezanson <jeff.bezanson@gmail.com>
Date: Sat, 11 Oct 2014 13:51:59 -0400
Subject: [PATCH] fully redesign constructors to use `call` overloading

this does not work yet, but gets past the first bootstrap stage.

so far this is a significant net simplification.
---
 base/array.jl          |   8 +++
 base/boot.jl           |  31 +++++++++++
 base/inference.jl      |  79 ++++++++++----------------
 base/linalg/cholmod.jl |   2 +-
 base/reflection.jl     |   6 +-
 base/subarray.jl       |  60 ++++++++++----------
 src/alloc.c            | 111 ++-----------------------------------
 src/builtin_proto.h    |   5 --
 src/builtins.c         |  42 +-------------
 src/codegen.cpp        |  20 +++----
 src/dump.c             |  21 ++-----
 src/gf.c               |  27 +--------
 src/interpreter.c      |  16 +++---
 src/jltypes.c          |  87 +++++++++--------------------
 src/julia-syntax.scm   | 122 ++++++++++++++++++++++++++++-------------
 src/julia.h            |  20 +++----
 src/julia_internal.h   |   3 -
 src/module.c           |  11 +---
 src/task.c             |  27 +--------
 src/toplevel.c         |  37 +++++++++++--
 20 files changed, 280 insertions(+), 455 deletions(-)

diff --git a/base/array.jl b/base/array.jl
index cd27de4944ce6..6d64b508e5629 100644
--- a/base/array.jl
+++ b/base/array.jl
@@ -123,6 +123,14 @@ function getindex(T::NonTupleType, vals...)
     return a
 end
 
+function getindex(::Type{Any}, vals::ANY...)
+    a = Array(Any,length(vals))
+    for i = 1:length(vals)
+        a[i] = vals[i]
+    end
+    return a
+end
+
 getindex(T::(Type...)) = Array(T,0)
 
 # T[a:b] and T[a:s:b] also construct typed ranges
diff --git a/base/boot.jl b/base/boot.jl
index ffe6e6d3cb353..7e3cf56cd9994 100644
--- a/base/boot.jl
+++ b/base/boot.jl
@@ -245,3 +245,34 @@ end
 typealias ByteString Union(ASCIIString,UTF8String)
 
 include(fname::ByteString) = ccall(:jl_load_, Any, (Any,), fname)
+
+# constructors for built-in types
+
+TypeVar(n::Symbol) =
+    ccall(:jl_new_typevar, Any, (Any, Any, Any), n, Union(), Any)::TypeVar
+TypeVar(n::Symbol, ub::ANY) =
+    ccall(:jl_new_typevar, Any, (Any, Any, Any), n, Union(), ub::Type)::TypeVar
+TypeVar(n::Symbol, lb::ANY, ub::ANY) =
+    ccall(:jl_new_typevar, Any, (Any, Any, Any), n, lb::Type, ub::Type)::TypeVar
+TypeVar(n::Symbol, b::Bool) =
+    ccall(:jl_new_typevar_, Any, (Any, Any, Any, Any), n, Union(), Any, b)::TypeVar
+TypeVar(n::Symbol, ub::ANY, b::Bool) =
+    ccall(:jl_new_typevar_, Any, (Any, Any, Any, Any), n, Union(), ub::Type, b)::TypeVar
+TypeVar(n::Symbol, lb::ANY, ub::ANY, b::Bool) =
+    ccall(:jl_new_typevar_, Any, (Any, Any, Any, Any), n, lb::Type, ub::Type, b)::TypeVar
+
+TypeConstructor(p::ANY, t::ANY) = ccall(:jl_new_type_constructor, Any, (Any, Any), p::Tuple, t::Type)
+
+Expr(hd::Symbol, args::ANY...) = ccall(:jl_new_expr, Any, (Any, Any), hd, args)::Expr
+
+LineNumberNode(n::Int) = ccall(:jl_new_struct, Any, (Any,Any...), LineNumberNode, n)::LineNumberNode
+LabelNode(n::Int) = ccall(:jl_new_struct, Any, (Any,Any...), LabelNode, n)::LabelNode
+GotoNode(n::Int) = ccall(:jl_new_struct, Any, (Any,Any...), GotoNode, n)::GotoNode
+QuoteNode(x::ANY) = ccall(:jl_new_struct, Any, (Any,Any...), QuoteNode, x)::QuoteNode
+NewvarNode(s::Symbol) = ccall(:jl_new_struct, Any, (Any,Any...), NewvarNode, s)::NewvarNode
+TopNode(s::Symbol) = ccall(:jl_new_struct, Any, (Any,Any...), TopNode, s)::TopNode
+
+Module(name::Symbol) = ccall(:jl_f_new_module, Any, (Any,), name)::Module
+Module() = Module(:anonymous)
+
+Task(f::ANY) = ccall(:jl_new_task, Any, (Any, Int), f::Function, 0)::Task
diff --git a/base/inference.jl b/base/inference.jl
index 65d318fdd034e..22db441361663 100644
--- a/base/inference.jl
+++ b/base/inference.jl
@@ -29,7 +29,7 @@ type CallStack
     prev::Union(EmptyCallStack,CallStack)
     sv::StaticVarInfo
 
-    CallStack(ast, mod, types, prev) = new(ast, mod, types, false, 0, Bottom, prev)
+    CallStack(ast, mod, types::ANY, prev) = new(ast, mod, types, false, 0, Bottom, prev)
 end
 
 inference_stack = EmptyCallStack()
@@ -516,10 +516,6 @@ function builtin_tfunction(f::ANY, args::ANY, argtypes::ANY)
     end
     tf = get(t_func::ObjectIdDict, f, false)
     if is(tf,false)
-        # struct constructor
-        if isstructtype(f)
-            return f
-        end
         # unknown/unhandled builtin
         return Any
     end
@@ -828,30 +824,25 @@ end
 function abstract_call(f, fargs, argtypes, vtypes, sv::StaticVarInfo, e)
     if is(f,_apply) && length(fargs)>1
         a2type = argtypes[2]
-        if isType(a2type) && isleaftype(a2type.parameters[1])
-            af = a2type.parameters[1]
-            _methods(af,(),0)
-        else
-            af = isconstantfunc(fargs[2], sv)
-        end
+        af = isconstantfunc(fargs[2], sv)
 
         if !is(af,false)
             af = _ieval(af)
-            if isa(af,Function) || isa(af,DataType)
+            if isa(af,Function)
                 aargtypes = map(to_tuple_of_Types, argtypes[3:end])
                 return abstract_apply(af, aargtypes, vtypes, sv, e)
             end
         end
         # TODO: this slows down inference a lot
-        # if !(a2type===Function || a2type===DataType) && isleaftype(a2type)
-        #     # would definitely use call()
-        #     call_func = isconstantfunc(fargs[1])
-        #     if !is(call_func,false)
-        #         aargtypes = Any[ to_tuple_of_Types(argtypes[i]) for i=2:length(argtypes) ]
-        #         aargtypes[1] = (aargtypes[1],)  # don't splat "function"
-        #         return abstract_apply(_ieval(call_func), tuple(aargtypes...), vtypes, sv, e)
-        #     end
-        # end
+        if !(a2type===Function) && isleaftype(a2type)
+            # would definitely use call()
+            call_func = isconstantfunc(fargs[1], sv)
+            if !is(call_func,false)
+                aargtypes = Any[ to_tuple_of_Types(argtypes[i]) for i=2:length(argtypes) ]
+                aargtypes[1] = (aargtypes[1],)  # don't splat "function"
+                return abstract_apply(_ieval(call_func), tuple(aargtypes...), vtypes, sv, e)
+            end
+        end
         return Any
     end
     if isgeneric(f)
@@ -897,9 +888,9 @@ function abstract_call(f, fargs, argtypes, vtypes, sv::StaticVarInfo, e)
         # TODO: call() case
         return Any
     end
-    if !isa(f,Function) && !isa(f,DataType) && !isa(f,IntrinsicFunction) && _iisdefined(:call)
+    if !isa(f,Function) && !isa(f,IntrinsicFunction) && _iisdefined(:call)
         call_func = _ieval(:call)
-        return abstract_call(call_func, e.args, tuple(Any[typeof(f),argtypes...]...), vtypes, sv, e)
+        return abstract_call(call_func, e.args, tuple(Any[abstract_eval_constant(f),argtypes...]...), vtypes, sv, e)
     end
     rt = builtin_tfunction(f, fargs, argtypes)
     #print("=> ", rt, "\n")
@@ -933,21 +924,7 @@ function abstract_eval_call(e, vtypes, sv::StaticVarInfo)
             return result
         end
         ft = abstract_eval(called, vtypes, sv)
-        if isType(ft)
-            st = ft.parameters[1]
-            if isa(st,TypeVar)
-                st = st.ub
-            end
-            if isa(st,DataType)
-                _methods(st,(),0)
-                if isgeneric(st) && isleaftype(st)
-                    return abstract_call_gf(st, fargs, argtypes, e)
-                end
-                # struct constructor
-                return st
-            end
-        end
-        if !(Function <: ft) && typeintersect(DataType, ft)==Bottom && _iisdefined(:call)
+        if !(Function <: ft) && _iisdefined(:call)
             call_func = _ieval(:call)
             return abstract_call(call_func, e.args, tuple(Any[ft,argtypes...]...), vtypes, sv, e)
         end
@@ -1300,6 +1277,10 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop)
             end
         end
     end
+    # TODO: typeinf currently gets stuck without this
+    if linfo.name === :abstract_interpret || linfo.name === :tuple_elim_pass || linfo.name === :abstract_call_gf
+        return (linfo.ast, Any)
+    end
 
     ast0 = def.ast
 
@@ -1621,6 +1602,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop)
         # just the return type in place of it.
         tfarr[idx+1] = rec ? frame.result : fulltree
         tfarr[idx+2] = rec
+        #tfunc_idx = idx+1
     else
         def.tfunc[tfunc_idx] = rec ? frame.result : fulltree
         def.tfunc[tfunc_idx+1] = rec
@@ -2063,7 +2045,7 @@ end
 # static parameters are ok if all the static parameter values are leaf types,
 # meaning they are fully known.
 function inlineable(f, e::Expr, atypes, sv, enclosing_ast)
-    if !(isa(f,Function) || isstructtype(f) || isa(f,IntrinsicFunction))
+    if !(isa(f,Function) || isa(f,IntrinsicFunction))
         return NF
     end
     argexprs = e.args[2:end]
@@ -2675,18 +2657,13 @@ function inlining_pass(e::Expr, sv, ast)
         end
         if is(e.head,:call1)
             e.head = :call
-            ET = exprtype(arg1)
-            if isType(ET)
-                f = ET.parameters[1]
-            else
-                f1 = f = isconstantfunc(arg1, sv)
-                if !is(f,false)
-                    f = _ieval(f)
-                end
-                if f1===false || !(isa(f,Function) || isa(f,Type) || isa(f,IntrinsicFunction))
-                    f = _ieval(:call)
-                    e.args = Any[f, e.args...]
-                end
+            f1 = f = isconstantfunc(arg1, sv)
+            if !is(f,false)
+                f = _ieval(f)
+            end
+            if f1===false || !(isa(f,Function) || isa(f,IntrinsicFunction))
+                f = _ieval(:call)
+                e.args = Any[f, e.args...]
             end
 
             if is(f, ^) || is(f, .^)
diff --git a/base/linalg/cholmod.jl b/base/linalg/cholmod.jl
index 7ac19eba71ba7..47464c6784c6e 100644
--- a/base/linalg/cholmod.jl
+++ b/base/linalg/cholmod.jl
@@ -294,7 +294,7 @@ type c_CholmodTriplet{Tv<:CHMVTypes,Ti<:CHMITypes}
     j::Ptr{Ti}
     x::Ptr{Tv}
     z::Ptr{Void}
-    stype:Cint
+    stype::Cint
     itype::Cint
     xtype::Cint
     dtype::Cint
diff --git a/base/reflection.jl b/base/reflection.jl
index d3aef01b41008..ac61eb44226ea 100644
--- a/base/reflection.jl
+++ b/base/reflection.jl
@@ -87,7 +87,7 @@ subtypes(x::DataType) = subtypes(Main, x)
 subtypetree(x::DataType, level=-1) = (level == 0 ? (x, []) : (x, Any[subtypetree(y, level-1) for y in subtypes(x)]))
 
 # function reflection
-isgeneric(f::ANY) = (isa(f,Function)||isa(f,DataType)) && isa(f.env,MethodTable)
+isgeneric(f::ANY) = (isa(f,Function) && isa(f.env,MethodTable))
 
 function_name(f::Function) = isgeneric(f) ? f.env.name : (:anonymous)
 
@@ -126,8 +126,8 @@ function methods(f::Function)
     f.env
 end
 
-methods(t::DataType) = (_methods(t,Tuple,0);  # force constructor creation
-                        t.env)
+#methods(t::DataType) = (_methods(t,Tuple,0);  # force constructor creation
+#                        t.env)
 
 function length(mt::MethodTable)
     n = 0
diff --git a/base/subarray.jl b/base/subarray.jl
index 139ffb18850b7..a0d621fb43713 100644
--- a/base/subarray.jl
+++ b/base/subarray.jl
@@ -11,39 +11,39 @@ type SubArray{T,N,A<:AbstractArray,I<:(RangeIndex...,)} <: AbstractArray{T,N}
     first_index::Int
 
     # Note: no bounds-checking on construction. See issue #4044
+
     #linear indexing constructor (scalar)
-    if N == 0 && length(I) == 1 && A <: Array
-        function SubArray(p::A, i::(Int,))
-            new(p, i, (), Int[], i[1])
-        end
-    #linear indexing constructor (ranges)
-    elseif N == 1 && length(I) == 1 && A <: Array
-        function SubArray(p::A, i::(UnitRange{Int},))
-            new(p, i, (length(i[1]),), [1], first(i[1]))
-        end
-        function SubArray(p::A, i::(Range{Int},))
-            new(p, i, (length(i[1]),), [step(i[1])], first(i[1]))
-        end
-    else
-        function SubArray(p::A, i::I)
-            newdims = Array(Int, 0)
-            newstrides = Array(Int, 0)
-            newfirst = 1
-            pstride = 1
-            for j = 1:length(i)
-                if isa(i[j], Int)
-                    newfirst += (i[j]-1)*pstride
-                else
-                    push!(newdims, length(i[j]))
-                    #may want to return error if step(i[j]) <= 0
-                    push!(newstrides, isa(i[j],UnitRange) ? pstride :
-                         pstride * step(i[j]))
-                    newfirst += (first(i[j])-1)*pstride
-                end
-                pstride *= size(p,j)
+    global call
+    function call{T,A<:Array,I<:(Any,)}(::Type{SubArray{T,0,A,I}}, p::A, i::(Int,))
+        new(p, i, (), Int[], i[1])
+    end
+
+    function call{T,A<:Array,I<:(Any,)}(::Type{SubArray{T,1,A,I}}, p::A, i::(UnitRange{Int},))
+        new(p, i, (length(i[1]),), [1], first(i[1]))
+    end
+
+    function call{T,A<:Array,I<:(Any,)}(::Type{SubArray{T,1,A,I}}, p::A, i::(Range{Int},))
+        new(p, i, (length(i[1]),), [step(i[1])], first(i[1]))
+    end
+
+    function SubArray(p::A, i::I)
+        newdims = Array(Int, 0)
+        newstrides = Array(Int, 0)
+        newfirst = 1
+        pstride = 1
+        for j = 1:length(i)
+            if isa(i[j], Int)
+                newfirst += (i[j]-1)*pstride
+            else
+                push!(newdims, length(i[j]))
+                #may want to return error if step(i[j]) <= 0
+                push!(newstrides, isa(i[j],UnitRange) ? pstride :
+                      pstride * step(i[j]))
+                newfirst += (first(i[j])-1)*pstride
             end
-            new(p, i, tuple(newdims...), newstrides, newfirst)
+            pstride *= size(p,j)
         end
+        new(p, i, tuple(newdims...), newstrides, newfirst)
     end
 end
 
diff --git a/src/alloc.c b/src/alloc.c
index daaa3f64ac007..d203198bd4644 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -578,8 +578,6 @@ jl_typename_t *jl_new_typename(jl_sym_t *name)
     tn->module = jl_current_module;
     tn->primary = NULL;
     tn->cache = (jl_value_t*)jl_null;
-    tn->ctor_factory = (jl_value_t*)jl_null;
-    tn->static_ctor_factory = NULL;
     return tn;
 }
 
@@ -593,65 +591,6 @@ jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_datatype_t *super,
 
 jl_function_t *jl_instantiate_method(jl_function_t *f, jl_tuple_t *sp);
 
-void jl_add_constructors(jl_datatype_t *t)
-{
-    if (t->name == jl_array_typename) {
-        t->fptr = jl_f_no_function;
-        return;
-    }
-
-    jl_initialize_generic_function((jl_function_t*)t, t->name->name);
-
-    if (t->name->ctor_factory == (jl_value_t*)jl_nothing ||
-        t->name->ctor_factory == (jl_value_t*)jl_null) {
-    }
-    else {
-        assert(jl_tuple_len(t->parameters) > 0);
-        if (t == (jl_datatype_t*)t->name->primary)
-            return;
-        jl_function_t *cfactory = NULL;
-        jl_tuple_t *env = NULL;
-        JL_GC_PUSH2(&cfactory, &env);
-        if (jl_compileropts.compile_enabled) {
-            // instantiating
-            assert(jl_is_function(t->name->ctor_factory));
-            // add type's static parameters to the ctor factory
-            size_t np = jl_tuple_len(t->parameters);
-            env = jl_alloc_tuple_uninit(np*2);
-            for(size_t i=0; i < np; i++) {
-                jl_tupleset(env, i*2+0,
-                            jl_tupleref(((jl_datatype_t*)t->name->primary)->parameters, i));
-                jl_tupleset(env, i*2+1,
-                            jl_tupleref(t->parameters, i));
-            }
-            cfactory = jl_instantiate_method((jl_function_t*)t->name->ctor_factory, env);
-            cfactory->linfo->ast = jl_prepare_ast(cfactory->linfo,
-                                                  cfactory->linfo->sparams);
-        }
-        else {
-            cfactory = ((jl_datatype_t*)t)->name->static_ctor_factory;
-            if (cfactory == NULL) {
-                JL_PRINTF(JL_STDERR,"code missing for type %s\n", t->name->name);
-                exit(1);
-            }
-            // in generically-compiled case, pass static parameters via closure
-            // environment.
-            env = jl_tuple_append((jl_tuple_t*)cfactory->env, t->parameters);
-            cfactory = jl_new_closure(cfactory->fptr, (jl_value_t*)env, cfactory->linfo);
-        }
-        // call user-defined constructor factory on (type,)
-        jl_value_t *cfargs[1] = { (jl_value_t*)t };
-        jl_apply(cfactory, cfargs, 1);
-        JL_GC_POP();
-    }
-}
-
-JL_CALLABLE(jl_f_ctor_trampoline)
-{
-    jl_add_constructors((jl_datatype_t*)F);
-    return jl_apply((jl_function_t*)F, args, nargs);
-}
-
 jl_datatype_t *jl_new_uninitialized_datatype(size_t nfields)
 {
     return (jl_datatype_t*)
@@ -732,9 +671,6 @@ jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super,
     t->abstract = abstract;
     t->mutabl = mutabl;
     t->pointerfree = 0;
-    t->fptr = jl_f_no_function;
-    t->env = (jl_value_t*)t;
-    t->linfo = NULL;
     t->instance = NULL;
     t->struct_decl = NULL;
     t->size = 0;
@@ -956,57 +892,22 @@ jl_expr_t *jl_exprn(jl_sym_t *head, size_t n)
     return ex;
 }
 
-// this constructor has to be built-in for bootstrapping, because we can't
-// do anything without being able to make Exprs.
-JL_CALLABLE(jl_f_new_expr)
+DLLEXPORT jl_value_t *jl_new_expr(jl_sym_t *head, jl_tuple_t *args)
 {
-    JL_NARGSV(Expr, 1);
-    JL_TYPECHK(Expr, symbol, args[0]);
-    jl_array_t *ar = jl_alloc_cell_1d(nargs-1);
+    size_t nargs = jl_tuple_len(args);
+    jl_array_t *ar = jl_alloc_cell_1d(nargs);
     JL_GC_PUSH1(&ar);
-    for(size_t i=1; i < nargs; i++)
-        jl_cellset(ar, i-1, args[i]);
+    for(size_t i=0; i < nargs; i++)
+        jl_cellset(ar, i, jl_tupleref(args,i));
     jl_expr_t *ex = (jl_expr_t*)alloc_4w();
     ex->type = (jl_value_t*)jl_expr_type;
-    ex->head = (jl_sym_t*)args[0];
+    ex->head = head;
     ex->args = ar;
     ex->etype = (jl_value_t*)jl_any_type;
     JL_GC_POP();
     return (jl_value_t*)ex;
 }
 
-JL_CALLABLE(jl_f_new_box)
-{
-    JL_NARGS(Box, 1, 1);
-    jl_value_t *box = (jl_value_t*)alloc_2w();
-    box->type = jl_box_any_type;
-    ((jl_value_t**)box)[1] = args[0];
-    return box;
-}
-
-JL_CALLABLE(jl_f_default_ctor_1)
-{
-    if (nargs != 1)
-        jl_error("wrong number of arguments (expected 1)");
-    jl_value_t *ft = jl_t0(((jl_datatype_t*)F)->types);
-    if (!jl_subtype(args[0], ft, 1))
-        jl_type_error(((jl_datatype_t*)F)->name->name->name, ft, args[0]);
-    return jl_new_struct((jl_datatype_t*)F, args[0]);
-}
-
-JL_CALLABLE(jl_f_default_ctor_2)
-{
-    if (nargs != 2)
-        jl_error("wrong number of arguments (expected 2)");
-    jl_value_t *ft = jl_t0(((jl_datatype_t*)F)->types);
-    if (!jl_subtype(args[0], ft, 1))
-        jl_type_error(((jl_datatype_t*)F)->name->name->name, ft, args[0]);
-    ft = jl_t1(((jl_datatype_t*)F)->types);
-    if (!jl_subtype(args[1], ft, 1))
-        jl_type_error(((jl_datatype_t*)F)->name->name->name, ft, args[1]);
-    return jl_new_struct((jl_datatype_t*)F, args[0], args[1]);
-}
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/builtin_proto.h b/src/builtin_proto.h
index d2e361d89b1f8..76d25d6acbc25 100644
--- a/src/builtin_proto.h
+++ b/src/builtin_proto.h
@@ -7,9 +7,6 @@ extern "C" {
 
 // declarations for julia-callable builtin functions
 
-JL_CALLABLE(jl_f_new_expr);
-JL_CALLABLE(jl_f_new_box);
-JL_CALLABLE(jl_f_new_module);
 JL_CALLABLE(jl_f_throw);
 JL_CALLABLE(jl_f_is);
 JL_CALLABLE(jl_f_typeof);
@@ -33,13 +30,11 @@ JL_CALLABLE(jl_f_arrayset);
 JL_CALLABLE(jl_f_arraysize);
 JL_CALLABLE(jl_f_instantiate_type);
 JL_CALLABLE(jl_f_convert_default);
-JL_CALLABLE(jl_f_new_type_constructor);
 JL_CALLABLE(jl_f_typevar);
 JL_CALLABLE(jl_f_union);
 JL_CALLABLE(jl_f_methodexists);
 JL_CALLABLE(jl_f_applicable);
 JL_CALLABLE(jl_f_invoke);
-JL_CALLABLE(jl_f_task);
 JL_CALLABLE(jl_f_yieldto);
 
 #ifdef __cplusplus
diff --git a/src/builtins.c b/src/builtins.c
index 4adb71c505160..3d7a5be00b6e4 100644
--- a/src/builtins.c
+++ b/src/builtins.c
@@ -373,8 +373,6 @@ JL_CALLABLE(jl_f_apply)
     return result;
 }
 
-void jl_add_constructors(jl_datatype_t *t);
-
 JL_CALLABLE(jl_f_kwcall)
 {
     if (nargs < 4)
@@ -399,8 +397,6 @@ JL_CALLABLE(jl_f_kwcall)
         args[pa-2] = (jl_value_t*)f;
     }
 
-    if (f->fptr == jl_f_ctor_trampoline)
-        jl_add_constructors((jl_datatype_t*)f);
     if (!jl_is_gf(f))
         jl_error("function does not accept keyword arguments");
     jl_function_t *sorter = ((jl_methtable_t*)f->env)->kwsorter;
@@ -856,49 +852,15 @@ JL_CALLABLE(jl_f_instantiate_type)
     return jl_apply_type_(args[0], &args[1], nargs-1);
 }
 
-JL_CALLABLE(jl_f_new_type_constructor)
+DLLEXPORT jl_value_t *jl_new_type_constructor(jl_tuple_t *p, jl_value_t *t)
 {
-    JL_NARGS(new_type_constructor, 2, 2);
-    JL_TYPECHK(new_type_constructor, tuple, args[0]);
-    if (!jl_is_type(args[1]))
-        jl_type_error("typealias", (jl_value_t*)jl_type_type, args[1]);
-    jl_tuple_t *p = (jl_tuple_t*)args[0];
-    jl_value_t *tc = (jl_value_t*)jl_new_type_ctor(p, args[1]);
+    jl_value_t *tc = (jl_value_t*)jl_new_type_ctor(p, t);
     int i;
     for(i=0; i < jl_tuple_len(p); i++)
         ((jl_tvar_t*)jl_tupleref(p,i))->bound = 0;
     return tc;
 }
 
-JL_CALLABLE(jl_f_typevar)
-{
-    if (nargs < 1 || nargs > 3) {
-        JL_NARGS(TypeVar, 1, 1);
-    }
-    JL_TYPECHK(TypeVar, symbol, args[0]);
-    jl_value_t *lb = (jl_value_t*)jl_bottom_type;
-    jl_value_t *ub = (jl_value_t*)jl_any_type;
-    int b = 0;
-    if (args[nargs-1] == jl_true) {
-        b = 1;
-        nargs--;
-    }
-    if (nargs > 1) {
-        JL_TYPECHK(TypeVar, type, args[1]);
-        if (nargs > 2) {
-            JL_TYPECHK(TypeVar, type, args[2]);
-            lb = args[1];
-            ub = args[2];
-        }
-        else {
-            ub = args[1];
-        }
-    }
-    jl_tvar_t *tv = jl_new_typevar((jl_sym_t*)args[0], lb, ub);
-    tv->bound = b;
-    return (jl_value_t*)tv;
-}
-
 JL_CALLABLE(jl_f_union)
 {
     if (nargs == 0) return (jl_value_t*)jl_bottom_type;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 84ff537beae60..485d581e1efe9 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -2324,13 +2324,7 @@ static Value *emit_is_function(Value *x, jl_codectx_t *ctx)
 {
     Value *xty = emit_typeof(x);
     Value *isfunc =
-        builder.
-        CreateOr(builder.
-                 CreateICmpEQ(xty,
-                              literal_pointer_val((jl_value_t*)jl_function_type)),
-                 builder.
-                 CreateICmpEQ(xty,
-                              literal_pointer_val((jl_value_t*)jl_datatype_type)));
+        builder.CreateICmpEQ(xty, literal_pointer_val((jl_value_t*)jl_function_type));
     return isfunc;
 }
 
@@ -2364,10 +2358,7 @@ static Value *emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx, jl_
     }
 
     hdtype = expr_type(a0, ctx);
-    definitely_function |= (hdtype == (jl_value_t*)jl_function_type ||
-                            hdtype == (jl_value_t*)jl_datatype_type ||
-                            (jl_is_type_type(hdtype) &&
-                             jl_is_datatype(jl_tparam0(hdtype))));
+    definitely_function |= (hdtype == (jl_value_t*)jl_function_type);
     definitely_not_function |= (jl_is_leaf_type(hdtype) && !definitely_function);
 
     assert(!(definitely_function && definitely_not_function));
@@ -2894,9 +2885,11 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed,
         make_gcroot(a1, ctx);
         Value *a2 = boxed(emit_expr(args[2], ctx),ctx);
         make_gcroot(a2, ctx);
-        Value *mdargs[6] = { name, bp, literal_pointer_val(bnd), a1, a2, literal_pointer_val(args[3]) };
+        Value *mdargs[7] =
+            { name, bp, literal_pointer_val(bnd), a1, a2, literal_pointer_val(args[3]),
+              literal_pointer_val((jl_value_t*)jl_module_call_func(ctx->module)) };
         ctx->argDepth = last_depth;
-        return builder.CreateCall(prepare_call(jlmethod_func), ArrayRef<Value*>(&mdargs[0], 6));
+        return builder.CreateCall(prepare_call(jlmethod_func), ArrayRef<Value*>(&mdargs[0], 7));
     }
     else if (head == const_sym) {
         jl_sym_t *sym = (jl_sym_t*)args[0];
@@ -4464,6 +4457,7 @@ static void init_julia_llvm_env(Module *m)
     mdargs.push_back(jl_pvalue_llvmt);
     mdargs.push_back(jl_pvalue_llvmt);
     mdargs.push_back(jl_pvalue_llvmt);
+    mdargs.push_back(jl_pvalue_llvmt);
     jlmethod_func =
         Function::Create(FunctionType::get(jl_pvalue_llvmt, mdargs, false),
                          Function::ExternalLinkage,
diff --git a/src/dump.c b/src/dump.c
index 50c8f57e9c6c2..7cec6dc7966f3 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -302,9 +302,6 @@ static void jl_serialize_datatype(ios_t *s, jl_datatype_t *dt)
     jl_serialize_value(s, dt->parameters);
     jl_serialize_value(s, dt->name);
     jl_serialize_value(s, dt->super);
-    jl_serialize_value(s, dt->env);
-    jl_serialize_value(s, dt->linfo);
-    jl_serialize_fptr(s, (void*)dt->fptr);
 }
 
 static void jl_serialize_module(ios_t *s, jl_module_t *m)
@@ -650,9 +647,6 @@ static jl_value_t *jl_deserialize_datatype(ios_t *s, int pos)
     dt->parameters = (jl_tuple_t*)jl_deserialize_value(s);
     dt->name = (jl_typename_t*)jl_deserialize_value(s);
     dt->super = (jl_datatype_t*)jl_deserialize_value(s);
-    dt->env = jl_deserialize_value(s);
-    dt->linfo = (jl_lambda_info_t*)jl_deserialize_value(s);
-    dt->fptr = jl_deserialize_fptr(s);
     if (dt->name == jl_array_type->name || dt->name == jl_pointer_type->name ||
         dt->name == jl_type_type->name || dt->name == jl_vararg_type->name ||
         dt->name == jl_abstractarray_type->name ||
@@ -969,8 +963,6 @@ void jl_save_system_image(char *fname)
 
     jl_idtable_type = jl_get_global(jl_base_module, jl_symbol("ObjectIdDict"));
 
-    jl_serialize_value(&f, jl_array_type->env);
-
     jl_serialize_value(&f, jl_main_module);
 
     // deser_tag is an array indexed from 2 until HT_NOTFOUND
@@ -1040,8 +1032,6 @@ void jl_restore_system_image(char *fname)
 
     datatype_list = jl_alloc_cell_1d(0);
 
-    jl_array_type->env = jl_deserialize_value(&f);
-    
     jl_main_module = (jl_module_t*)jl_deserialize_value(&f);
     jl_internal_main_module = jl_main_module;
     jl_core_module = (jl_module_t*)jl_get_global(jl_main_module,
@@ -1314,8 +1304,7 @@ void jl_init_serializer(void)
     assert(i <= Null_tag);
     VALUE_TAGS = (ptrint_t)ptrhash_get(&ser_tag, jl_null);
 
-    jl_fptr_t fptrs[] = { jl_f_new_expr, jl_f_new_box,
-                          jl_f_throw, jl_f_is,
+    jl_fptr_t fptrs[] = { jl_f_throw, jl_f_is,
                           jl_f_no_function, jl_f_typeof,
                           jl_f_subtype, jl_f_isa,
                           jl_f_typeassert, jl_f_apply,
@@ -1327,13 +1316,11 @@ void jl_init_serializer(void)
                           jl_f_arrayset, jl_f_arraysize,
                           jl_f_instantiate_type, jl_f_kwcall,
                           jl_f_convert_default,
-                          jl_trampoline, jl_f_new_type_constructor,
-                          jl_f_typevar, jl_f_union,
+                          jl_trampoline, jl_f_union,
                           jl_f_methodexists, jl_f_applicable,
                           jl_f_invoke, jl_apply_generic,
-                          jl_unprotect_stack, jl_f_task,
-                          jl_f_yieldto, jl_f_ctor_trampoline,
-                          jl_f_new_module, jl_f_sizeof,
+                          jl_unprotect_stack,
+                          jl_f_yieldto, jl_f_sizeof,
                           NULL };
     i=2;
     while (fptrs[i-2] != NULL) {
diff --git a/src/gf.c b/src/gf.c
index 9efc13e8c87bb..1737c9672090e 100644
--- a/src/gf.c
+++ b/src/gf.c
@@ -1194,10 +1194,7 @@ jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tuple_t *type,
             sigs_eq((jl_value_t*)type, (jl_value_t*)l->sig, 1)) {
             // method overwritten
             if (check_amb && l->func->linfo && method->linfo &&
-                (l->func->linfo->module != method->linfo->module) &&
-                // special case: allow adding Array() methods in Base
-                (pml != &((jl_methtable_t*)jl_array_type->env)->defs ||
-                 method->linfo->module != jl_base_module)) {
+                (l->func->linfo->module != method->linfo->module)) {
                 jl_module_t *newmod = method->linfo->module;
                 jl_value_t *errstream = jl_stderr_obj();
                 JL_STREAM *s = JL_STDERR;
@@ -1335,8 +1332,8 @@ jl_value_t *jl_no_method_error(jl_function_t *f, jl_value_t **args, size_t na)
 {
     jl_value_t *argtup = jl_f_tuple(NULL, args, na);
     JL_GC_PUSH1(&argtup);
-    jl_value_t *fargs[2] = { (jl_value_t*)f, argtup };
-    jl_throw(jl_apply((jl_function_t*)jl_methoderror_type, fargs, 2));
+    jl_value_t *fargs[3] = { (jl_value_t*)jl_methoderror_type, (jl_value_t*)f, argtup };
+    jl_throw(jl_apply(jl_module_call_func(jl_base_module), fargs, 3));
     // not reached
     return jl_nothing;
 }
@@ -1386,7 +1383,6 @@ jl_function_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t na
     return sf;
 }
 
-void jl_add_constructors(jl_datatype_t *t);
 DLLEXPORT jl_value_t *jl_matching_methods(jl_function_t *gf, jl_value_t *type, int lim);
 
 // compile-time method lookup
@@ -1394,8 +1390,6 @@ jl_function_t *jl_get_specialization(jl_function_t *f, jl_tuple_t *types)
 {
     if (!jl_is_leaf_type((jl_value_t*)types))
         return NULL;
-    if (f->fptr == jl_f_ctor_trampoline)
-        jl_add_constructors((jl_datatype_t*)f);
     assert(jl_is_gf(f));
 
     // make sure exactly 1 method matches (issue #7302).
@@ -1518,19 +1512,6 @@ static void _compile_all(jl_module_t *m, htable_t *h)
             jl_binding_t *b = (jl_binding_t*)table[i];
             if (b->value != NULL) {
                 jl_value_t *v = b->value;
-                if (jl_is_datatype(v)) {
-                    jl_datatype_t *dt = (jl_datatype_t*)v;
-                    if (dt->fptr == jl_f_ctor_trampoline) {
-                        jl_add_constructors(dt);
-                        jl_compile_all_defs((jl_function_t*)dt);
-                    }
-                    if (v == dt->name->primary && dt->parameters != jl_null &&
-                        jl_is_function(dt->name->ctor_factory) &&
-                        dt->name->static_ctor_factory == NULL) {
-                        dt->name->static_ctor_factory = jl_instantiate_method((jl_function_t*)dt->name->ctor_factory, jl_null);
-                        precompile_unspecialized(dt->name->static_ctor_factory, NULL, dt->parameters);
-                    }
-                }
                 if (jl_is_gf(v)) {
                     jl_compile_all_defs((jl_function_t*)v);
                 }
@@ -1920,8 +1901,6 @@ jl_value_t *jl_matching_methods(jl_function_t *gf, jl_value_t *type, int lim)
     assert(jl_is_func(gf));
     if (gf->fptr == jl_f_no_function)
         return (jl_value_t*)jl_an_empty_cell;
-    if (gf->fptr == jl_f_ctor_trampoline)
-        jl_add_constructors((jl_datatype_t*)gf);
     if (!jl_is_gf(gf)) {
         return (jl_value_t*)jl_an_empty_cell;
     }
diff --git a/src/interpreter.c b/src/interpreter.c
index 6bfdf341f731b..7c8248709fe5a 100644
--- a/src/interpreter.c
+++ b/src/interpreter.c
@@ -263,14 +263,17 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl)
                 fname = (jl_sym_t*)jl_exprarg(fname, 0);
             }
             gf = eval((jl_value_t*)fname, locals, nl);
-            assert(jl_is_function(gf));
-            assert(jl_is_gf(gf));
+            jl_value_t *bp_f = gf;
+            if (jl_is_datatype(bp_f))
+                bp_f = jl_module_call_func(jl_current_module);
+            assert(jl_is_function(bp_f)); // TODO: type check for this
+            assert(jl_is_gf(bp_f));
             if (jl_is_expr(fname))
                 fname = (jl_sym_t*)jl_fieldref(jl_exprarg(fname, 2), 0);
             if (!kw)
                 bp = &gf;
             else
-                bp = (jl_value_t**)&((jl_methtable_t*)((jl_function_t*)gf)->env)->kwsorter;
+                bp = (jl_value_t**)&((jl_methtable_t*)((jl_function_t*)bp_f)->env)->kwsorter;
             assert(jl_is_symbol(fname));
         }
         else {
@@ -292,7 +295,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl)
             jl_check_static_parameter_conflicts((jl_lambda_info_t*)args[2], (jl_tuple_t*)jl_t1(atypes), fname);
         }
         meth = eval(args[2], locals, nl);
-        jl_method_def(fname, bp, b, (jl_tuple_t*)atypes, (jl_function_t*)meth, args[3]);
+        jl_method_def(fname, bp, b, (jl_tuple_t*)atypes, (jl_function_t*)meth, args[3], NULL);
         JL_GC_POP();
         return *bp;
     }
@@ -373,7 +376,6 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl)
         return (jl_value_t*)jl_nothing;
     }
     else if (ex->head == compositetype_sym) {
-        void jl_add_constructors(jl_datatype_t *t);
         jl_value_t *name = args[0];
         assert(jl_is_symbol(name));
         jl_value_t *para = eval(args[1], locals, nl);
@@ -386,8 +388,6 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl)
         dt = jl_new_datatype((jl_sym_t*)name, jl_any_type, (jl_tuple_t*)para,
                              (jl_tuple_t*)temp, NULL,
                              0, args[6]==jl_true ? 1 : 0);
-        dt->fptr = jl_f_ctor_trampoline;
-        dt->name->ctor_factory = eval(args[3], locals, nl);
 
         jl_binding_t *b = jl_get_binding_wr(jl_current_module, (jl_sym_t*)name);
         temp = b->value;  // save old value
@@ -418,8 +418,6 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl)
         b->value = temp;
         if (temp==NULL || !equiv_type(dt, (jl_datatype_t*)temp)) {
             jl_checked_assignment(b, (jl_value_t*)dt);
-
-            jl_add_constructors(dt);
         }
         else {
             // TODO: remove all old ctors and set temp->name->ctor_factory = dt->name->ctor_factory
diff --git a/src/jltypes.c b/src/jltypes.c
index 745d18e865098..ab256f65f557f 100644
--- a/src/jltypes.c
+++ b/src/jltypes.c
@@ -55,8 +55,6 @@ jl_datatype_t *jl_number_type;
 jl_tuple_t *jl_null;
 jl_value_t *jl_nothing;
 
-void jl_add_constructors(jl_datatype_t *t);
-
 // --- type properties and predicates ---
 
 int jl_is_type(jl_value_t *v)
@@ -1931,14 +1929,8 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_value_t **env, size_t n,
         ndt->parameters = iparams_tuple;
         ndt->names = dt->names;
         ndt->types = jl_null; // to be filled in below
-        if (isabstract || !jl_is_function(tn->ctor_factory))
-            ndt->fptr = jl_f_no_function;
-        else
-            ndt->fptr = jl_f_ctor_trampoline;
         ndt->mutabl = dt->mutabl;
         ndt->abstract = dt->abstract;
-        ndt->env = (jl_value_t*)ndt;
-        ndt->linfo = NULL;
         ndt->instance = NULL;
         ndt->uid = 0;
         ndt->struct_decl = NULL;
@@ -2822,16 +2814,21 @@ jl_value_t *jl_type_match_morespecific(jl_value_t *a, jl_value_t *b)
 
 // initialization -------------------------------------------------------------
 
-jl_tvar_t *jl_new_typevar(jl_sym_t *name, jl_value_t *lb, jl_value_t *ub)
+DLLEXPORT jl_tvar_t *jl_new_typevar_(jl_sym_t *name, jl_value_t *lb, jl_value_t *ub, jl_value_t *b)
 {
     jl_tvar_t *tv = (jl_tvar_t*)newobj((jl_value_t*)jl_tvar_type, 4);
     tv->name = name;
     tv->lb = lb;
     tv->ub = ub;
-    tv->bound = 0;
+    tv->bound = (b != jl_false);
     return tv;
 }
 
+jl_tvar_t *jl_new_typevar(jl_sym_t *name, jl_value_t *lb, jl_value_t *ub)
+{
+    return jl_new_typevar_(name, lb, ub, jl_false);
+}
+
 static jl_tvar_t *tvar(const char *name)
 {
     return jl_new_typevar(jl_symbol(name), (jl_value_t*)jl_bottom_type,
@@ -2843,9 +2840,9 @@ extern void jl_init_int32_int64_cache(void);
 void jl_init_types(void)
 {
     // create base objects
-    jl_datatype_type = jl_new_uninitialized_datatype(13);
+    jl_datatype_type = jl_new_uninitialized_datatype(10);
     jl_datatype_type->type = (jl_value_t*)jl_datatype_type;
-    jl_typename_type = jl_new_uninitialized_datatype(6);
+    jl_typename_type = jl_new_uninitialized_datatype(4);
     jl_sym_type = jl_new_uninitialized_datatype(0);
     jl_symbol_type = jl_sym_type;
 
@@ -2867,10 +2864,7 @@ void jl_init_types(void)
     jl_datatype_type->name->primary = (jl_value_t*)jl_datatype_type;
     jl_datatype_type->super = jl_type_type;
     jl_datatype_type->parameters = jl_null;
-    jl_datatype_type->names = jl_tuple(13, jl_symbol("fptr"),
-                                       jl_symbol("env"),
-                                       jl_symbol("code"),
-                                       jl_symbol("name"),
+    jl_datatype_type->names = jl_tuple(10, jl_symbol("name"),
                                        jl_symbol("super"),
                                        jl_symbol("parameters"),
                                        jl_symbol("names"),
@@ -2880,15 +2874,11 @@ void jl_init_types(void)
                                        jl_symbol("abstract"),
                                        jl_symbol("mutable"),
                                        jl_symbol("pointerfree"));
-    jl_datatype_type->types = jl_tuple(13, jl_any_type,jl_any_type,jl_any_type,
-                                       jl_typename_type, jl_type_type,
+    jl_datatype_type->types = jl_tuple(10, jl_typename_type, jl_type_type,
                                        jl_tuple_type, jl_tuple_type,
                                        jl_tuple_type, jl_any_type,
                                        jl_any_type, //types will be fixed later
                                        jl_any_type, jl_any_type, jl_any_type);
-    jl_datatype_type->fptr = jl_f_no_function;
-    jl_datatype_type->env = (jl_value_t*)jl_null;
-    jl_datatype_type->linfo = NULL;
     jl_datatype_type->instance = NULL;
     jl_datatype_type->uid = jl_assign_type_uid();
     jl_datatype_type->struct_decl = NULL;
@@ -2902,16 +2892,11 @@ void jl_init_types(void)
     jl_typename_type->name->primary = (jl_value_t*)jl_typename_type;
     jl_typename_type->super = jl_any_type;
     jl_typename_type->parameters = jl_null;
-    jl_typename_type->names = jl_tuple(6, jl_symbol("name"), jl_symbol("module"),
-                                       jl_symbol("primary"), jl_symbol("cache"),
-                                       jl_symbol("ctor_factory"), jl_symbol("static_ctor_factory"));
-    jl_typename_type->types = jl_tuple(6, jl_sym_type, jl_any_type,
-                                       jl_type_type, jl_any_type,
-                                       jl_any_type, jl_any_type);
+    jl_typename_type->names = jl_tuple(4, jl_symbol("name"), jl_symbol("module"),
+                                       jl_symbol("primary"), jl_symbol("cache"));
+    jl_typename_type->types = jl_tuple(4, jl_sym_type, jl_any_type,
+                                       jl_type_type, jl_any_type);
     jl_typename_type->uid = jl_assign_type_uid();
-    jl_typename_type->fptr = jl_f_no_function;
-    jl_typename_type->env = (jl_value_t*)jl_null;
-    jl_typename_type->linfo = NULL;
     jl_typename_type->instance = NULL;
     jl_typename_type->struct_decl = NULL;
     jl_typename_type->abstract = 0;
@@ -2924,9 +2909,6 @@ void jl_init_types(void)
     jl_sym_type->parameters = jl_null;
     jl_sym_type->names = jl_null;
     jl_sym_type->types = jl_null;
-    jl_sym_type->fptr = jl_f_no_function;
-    jl_sym_type->env = (jl_value_t*)jl_null;
-    jl_sym_type->linfo = NULL;
     jl_sym_type->instance = NULL;
     jl_sym_type->uid = jl_assign_type_uid();
     jl_sym_type->struct_decl = NULL;
@@ -2946,19 +2928,17 @@ void jl_init_types(void)
                                         jl_tuple(1, jl_symbol("types")),
                                         jl_tuple(1, jl_tuple_type),
                                         0, 0);
-    jl_uniontype_type->fptr = jl_f_no_function;
 
     jl_bottom_type = (jl_value_t*)jl_new_struct(jl_uniontype_type, jl_null);
 
     jl_tvar_type = jl_new_datatype(jl_symbol("TypeVar"),
                                    jl_any_type, jl_null,
-                                   jl_tuple(3, jl_symbol("name"),
-                                            jl_symbol("lb"),
-                                            jl_symbol("ub")),
-                                   jl_tuple(3, jl_sym_type, jl_type_type,
-                                            jl_type_type),
+                                   jl_tuple(4, jl_symbol("name"),
+                                            jl_symbol("lb"), jl_symbol("ub"),
+                                            jl_symbol("bound")),
+                                   jl_tuple(4, jl_sym_type, jl_type_type,
+                                            jl_type_type, jl_any_type),
                                    0, 0);
-    jl_tvar_type->fptr = jl_f_typevar;
 
     jl_undef_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Undef"),
                                         jl_any_type, jl_null);
@@ -3012,7 +2992,6 @@ void jl_init_types(void)
                                  jl_tuple_type, jl_any_type,
                                  jl_any_type, jl_any_type),
                         0, 1);
-    jl_method_type->fptr = jl_f_no_function;
 
     jl_methtable_type =
         jl_new_datatype(jl_symbol("MethodTable"), jl_any_type, jl_null,
@@ -3024,7 +3003,6 @@ void jl_init_types(void)
                                  jl_any_type, jl_any_type, jl_long_type,
                                  jl_any_type),
                         0, 1);
-    jl_methtable_type->fptr = jl_f_no_function;
 
     tv = jl_tuple2(tvar("T"), tvar("N"));
     jl_abstractarray_type =
@@ -3047,10 +3025,7 @@ void jl_init_types(void)
                         tv,
                         jl_null, jl_null, 0, 1);
     jl_array_typename = jl_array_type->name;
-    jl_array_type->linfo = NULL;
     jl_array_type->pointerfree = 0;
-    jl_initialize_generic_function((jl_function_t*)jl_array_type,
-                                   jl_array_typename->name);
 
     jl_array_any_type =
         (jl_value_t*)jl_apply_type((jl_value_t*)jl_array_type,
@@ -3070,49 +3045,41 @@ void jl_init_types(void)
                         jl_tuple(3, jl_sym_type, jl_array_any_type,
                                  jl_any_type),
                         0, 1);
-    jl_expr_type->fptr = jl_f_new_expr;
 
     jl_linenumbernode_type =
         jl_new_datatype(jl_symbol("LineNumberNode"), jl_any_type, jl_null,
                         jl_tuple(1, jl_symbol("line")),
                         jl_tuple(1, jl_long_type), 0, 0);
-    jl_linenumbernode_type->fptr = jl_f_default_ctor_1;
 
     jl_labelnode_type =
         jl_new_datatype(jl_symbol("LabelNode"), jl_any_type, jl_null,
                         jl_tuple(1, jl_symbol("label")),
                         jl_tuple(1, jl_long_type), 0, 0);
-    jl_labelnode_type->fptr = jl_f_default_ctor_1;
 
     jl_gotonode_type =
         jl_new_datatype(jl_symbol("GotoNode"), jl_any_type, jl_null,
                         jl_tuple(1, jl_symbol("label")),
                         jl_tuple(1, jl_long_type), 0, 0);
-    jl_gotonode_type->fptr = jl_f_default_ctor_1;
 
     jl_quotenode_type =
         jl_new_datatype(jl_symbol("QuoteNode"), jl_any_type, jl_null,
                         jl_tuple(1, jl_symbol("value")),
                         jl_tuple(1, jl_any_type), 0, 0);
-    jl_quotenode_type->fptr = jl_f_default_ctor_1;
 
     jl_newvarnode_type =
         jl_new_datatype(jl_symbol("NewvarNode"), jl_any_type, jl_null,
                         jl_tuple(1, jl_symbol("name")),
                         jl_tuple(1, jl_sym_type), 0, 0);
-    jl_newvarnode_type->fptr = jl_f_default_ctor_1;
 
     jl_topnode_type =
         jl_new_datatype(jl_symbol("TopNode"), jl_any_type, jl_null,
                         jl_tuple(1, jl_symbol("name")),
                         jl_tuple(1, jl_sym_type), 0, 0);
-    jl_topnode_type->fptr = jl_f_default_ctor_1;
 
     jl_module_type =
         jl_new_datatype(jl_symbol("Module"), jl_any_type, jl_null,
                         jl_tuple(2, jl_symbol("name"), jl_symbol("parent")),
                         jl_tuple(2, jl_sym_type, jl_any_type), 0, 1);
-    jl_module_type->fptr = jl_f_new_module;
 
     jl_tupleset(jl_typename_type->types, 1, jl_module_type);
 
@@ -3139,14 +3106,12 @@ void jl_init_types(void)
                                  jl_sym_type, jl_int32_type,
                                  jl_bool_type),
                         0, 1);
-    jl_lambda_info_type->fptr = jl_f_no_function;
 
     jl_box_type =
         jl_new_datatype(jl_symbol("Box"),
                         jl_any_type, jl_null,
                         jl_tuple(1, jl_symbol("contents")),
                         jl_tuple(1, jl_any_type), 0, 1);
-    jl_box_type->fptr = jl_f_new_box;
     jl_box_typename = jl_box_type->name;
     jl_box_any_type = (jl_value_t*)jl_box_type;
 
@@ -3157,7 +3122,6 @@ void jl_init_types(void)
                                  jl_symbol("body")),
                         jl_tuple(2, jl_tuple_type, jl_any_type),
                         0, 0);
-    jl_typector_type->fptr = jl_f_new_type_constructor;
 
     jl_function_type =
         jl_new_datatype(jl_symbol("Function"), jl_any_type, jl_null,
@@ -3166,7 +3130,6 @@ void jl_init_types(void)
                         jl_tuple(3, jl_any_type, jl_any_type,
                                  jl_lambda_info_type),
                         0, 1);
-    jl_function_type->fptr = jl_f_no_function;
 
     jl_tupleset(jl_method_type->types, 3, jl_function_type);
     jl_tupleset(jl_lambda_info_type->types, 6, jl_function_type);
@@ -3193,12 +3156,12 @@ void jl_init_types(void)
     jl_value_t *pointer_void = jl_apply_type((jl_value_t*)jl_pointer_type,
                                              jl_tuple(1,jl_void_type));
     jl_voidpointer_type = (jl_datatype_t*)pointer_void;
-    jl_tupleset(jl_datatype_type->types, 0, pointer_void);
-    jl_tupleset(jl_datatype_type->types, 9, jl_int32_type);
-    jl_tupleset(jl_datatype_type->types, 10, (jl_value_t*)jl_bool_type);
-    jl_tupleset(jl_datatype_type->types, 11, (jl_value_t*)jl_bool_type);
-    jl_tupleset(jl_datatype_type->types, 12, (jl_value_t*)jl_bool_type);
+    jl_tupleset(jl_datatype_type->types, 6, jl_int32_type);
+    jl_tupleset(jl_datatype_type->types, 7, (jl_value_t*)jl_bool_type);
+    jl_tupleset(jl_datatype_type->types, 8, (jl_value_t*)jl_bool_type);
+    jl_tupleset(jl_datatype_type->types, 9, (jl_value_t*)jl_bool_type);
     jl_tupleset(jl_function_type->types, 0, pointer_void);
+    jl_tupleset(jl_tvar_type->types, 3, (jl_value_t*)jl_bool_type);
 
     jl_compute_field_offsets(jl_datatype_type);
     jl_compute_field_offsets(jl_typename_type);
diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm
index da54ef8fd3c3e..4258c8c9dfaa3 100644
--- a/src/julia-syntax.scm
+++ b/src/julia-syntax.scm
@@ -732,7 +732,7 @@
 	  `(function (call ,name ,@field-names)
 		     (block
 		      (call new ,@field-names)))))
-    (if gen-specific?
+    (if (and gen-specific? (any (lambda (t) (not (eq? t 'Any))) field-types))
 	(list
 	 ;; definition with field types for all arguments
 	 `(function (call ,name
@@ -775,8 +775,42 @@
 	     `(block ,stmt ,@(cdr body))))
       body))
 
+;; insert item at start of arglist
+(define (arglist-unshift sig item)
+  (if (and (pair? sig) (pair? (car sig)) (eq? (caar sig) 'parameters))
+      `(,(car sig) ,item ,@(cdr sig))
+      `(,item ,@sig)))
+
+(define (ctor-signature name params method-params sig)
+  (if (null? params)
+      (if (null? method-params)
+	  (cons `(call call
+		       ,@(arglist-unshift sig `(|::| ,(gensy) (curly Type ,name))))
+		params)
+	  (cons `(call (curly call ,@method-params)
+		       ,@(arglist-unshift sig `(|::| ,(gensy) (curly Type ,name))))
+		params))
+      (if (null? method-params)
+	  (cons `(call (curly call ,@params)
+		       ,@(arglist-unshift sig `(|::| ,(gensy) (curly Type (curly ,name ,@params)))))
+		params)
+	  ;; rename parameters that conflict with user-written method parameters
+	  (let ((new-params (map (lambda (p) (if (memq p method-params)
+						 (gensy)
+						 p))
+				 params)))
+	    (cons `(call (curly call ,@new-params ,@method-params)
+			 ,@(arglist-unshift sig `(|::| ,(gensy) (curly Type (curly ,name ,@new-params)))))
+		  new-params)))))
+
+(define (ctor-def keyword name params method-params sig ctor-body body)
+  (let* ((temp   (ctor-signature name params method-params sig))
+	 (sig    (car temp))
+	 (params (cdr temp)))
+    `(,keyword ,sig ,(ctor-body body params))))
+
 (define (rewrite-ctor ctor Tname params field-names field-types mutabl iname)
-  (define (ctor-body body)
+  (define (ctor-body body params)
     (pattern-replace (pattern-set
 		      (pattern-lambda
 		       (call (-/ new) . args)
@@ -791,29 +825,39 @@
 				 field-types
 				 mutabl)))
 		     body))
-  (let ((ctor2
-	 (pattern-replace
-	  (pattern-set
-	   (pattern-lambda (function (call (curly name . p) . sig) body)
-			   `(function (call (curly ,(if (eq? name Tname) iname name) ,@p) ,@sig)
-				      ,(ctor-body body)))
-       (pattern-lambda (stagedfunction (call (curly name . p) . sig) body)
-               `(stagedfunction (call (curly ,(if (eq? name Tname) iname name) ,@p) ,@sig)
-                      ,(ctor-body body)))
-	   (pattern-lambda (function (call name . sig) body)
-			   `(function (call ,(if (eq? name Tname) iname name) ,@sig)
-				      ,(ctor-body body)))
-       (pattern-lambda (stagedfunction (call name . sig) body)
-               `(stagedfunction (call ,(if (eq? name Tname) iname name) ,@sig)
-                      ,(ctor-body body)))
-	   (pattern-lambda (= (call (curly name . p) . sig) body)
-			   `(= (call (curly ,(if (eq? name Tname) iname name) ,@p) ,@sig)
-			       ,(ctor-body body)))
-	   (pattern-lambda (= (call name . sig) body)
-			   `(= (call ,(if (eq? name Tname) iname name) ,@sig)
-			       ,(ctor-body body))))
-	  ctor)))
-    ctor2))
+  (pattern-replace
+   (pattern-set
+    (pattern-lambda (function (call (curly name . p) . sig) body)
+		    (if (eq? name Tname)
+			(ctor-def 'function name params p sig ctor-body body)
+			`(function (call (curly ,name ,@p) ,@sig)
+				   ,(ctor-body body params))))
+    (pattern-lambda (stagedfunction (call (curly name . p) . sig) body)
+		    (if (eq? name Tname)
+			(ctor-def 'stagedfunction name params p sig ctor-body body)
+			`(stagedfunction (call (curly ,name ,@p) ,@sig)
+					 ,(ctor-body body params))))
+    (pattern-lambda (function (call name . sig) body)
+		    (if (eq? name Tname)
+			(ctor-def 'function name params '() sig ctor-body body)
+			`(function (call ,name ,@sig)
+				   ,(ctor-body body params))))
+    (pattern-lambda (stagedfunction (call name . sig) body)
+		    (if (eq? name Tname)
+			(ctor-def 'stagedfunction name params '() sig ctor-body body)
+			`(stagedfunction (call ,name ,@sig)
+					 ,(ctor-body body params))))
+    (pattern-lambda (= (call (curly name . p) . sig) body)
+		    (if (eq? name Tname)
+			(ctor-def 'function name params p sig ctor-body body)
+			`(function (call (curly ,name ,@p) ,@sig)
+				   ,(ctor-body body params))))
+    (pattern-lambda (= (call name . sig) body)
+		    (if (eq? name Tname)
+			(ctor-def 'function name params '() sig ctor-body body)
+			`(function (call ,name ,@sig)
+				   ,(ctor-body body params)))))
+   ctor))
 
 ;; remove line numbers and nested blocks
 (define (flatten-blocks e)
@@ -854,6 +898,7 @@
 	      (scope-block
 	       (block
 		(global ,name)
+		(global call)
 		,@(map (lambda (c)
 			 (rewrite-ctor c name '() field-names field-types mut name))
 		       defs2)))))
@@ -868,25 +913,24 @@
 	     ,@(map make-assignment params (symbols->typevars params bounds #t))
 	     (composite_type ,name (tuple ,@params)
 			     (tuple ,@(map (lambda (x) `',x) field-names))
-			     ,(let ((instantiation-name (gensy)))
-				`(lambda (,instantiation-name)
-				   (scope-block
-				    ;; don't capture params; in here they are static
-				    ;; parameters
-				    (block
-				     (global ,@params)
-				     ,@(map
-					(lambda (c)
-					  (rewrite-ctor c name params field-names
-							field-types mut instantiation-name))
-					defs2)
-				     ,name))))
+			     (null)
 			     ,super (tuple ,@field-types)
 			     ,mut)))
+	   ;; "inner" constructors
+	   (call
+	    (lambda ()
+	      (scope-block
+	       (block
+		(global ,name)
+		(global call)
+		,@(map (lambda (c)
+			 (rewrite-ctor c name params field-names
+				       field-types mut name))
+		       defs2)))))
+	   ;; "outer" constructors
 	   (scope-block
 	    (block
 	     (global ,name)
-	     (global ,@params)
 	     ,@(if (and (null? defs)
 			;; don't generate an outer constructor if the type has
 			;; parameters not mentioned in the field types. such a
diff --git a/src/julia.h b/src/julia.h
index 2952851f27df2..ae0a3633da63e 100644
--- a/src/julia.h
+++ b/src/julia.h
@@ -162,14 +162,11 @@ typedef struct _jl_lambda_info_t {
 
 #define LAMBDA_INFO_NW (NWORDS(sizeof(jl_lambda_info_t))-1)
 
-#define JL_FUNC_FIELDS                          \
-    jl_fptr_t fptr;                             \
-    jl_value_t *env;                            \
-    jl_lambda_info_t *linfo;
-
 typedef struct _jl_function_t {
     JL_DATA_TYPE
-    JL_FUNC_FIELDS
+    jl_fptr_t fptr;
+    jl_value_t *env;
+    jl_lambda_info_t *linfo;
 } jl_function_t;
 
 typedef struct {
@@ -188,9 +185,6 @@ typedef struct {
     // not the original.
     jl_value_t *primary;
     jl_value_t *cache;
-    // to create a set of constructors for this sort of type
-    jl_value_t *ctor_factory;
-    jl_function_t *static_ctor_factory;
 } jl_typename_t;
 
 typedef struct {
@@ -206,7 +200,6 @@ typedef struct {
 
 typedef struct _jl_datatype_t {
     JL_DATA_TYPE
-    JL_FUNC_FIELDS
     jl_typename_t *name;
     struct _jl_datatype_t *super;
     jl_tuple_t *parameters;
@@ -229,7 +222,7 @@ typedef struct {
     jl_sym_t *name;
     jl_value_t *lb;   // lower bound
     jl_value_t *ub;   // upper bound
-    uptrint_t bound;  // part of a constraint environment
+    uint8_t bound;    // part of a constraint environment
 } jl_tvar_t;
 
 typedef struct {
@@ -526,7 +519,7 @@ extern jl_sym_t *arrow_sym; extern jl_sym_t *ldots_sym;
 #define jl_is_module(v)      jl_typeis(v,jl_module_type)
 #define jl_is_mtable(v)      jl_typeis(v,jl_methtable_type)
 #define jl_is_task(v)        jl_typeis(v,jl_task_type)
-#define jl_is_func(v)        (jl_typeis(v,jl_function_type) || jl_is_datatype(v))
+#define jl_is_func(v)        jl_typeis(v,jl_function_type)
 #define jl_is_function(v)    jl_is_func(v)
 #define jl_is_ascii_string(v) jl_typeis(v,jl_ascii_string_type)
 #define jl_is_utf8_string(v) jl_typeis(v,jl_utf8_string_type)
@@ -677,7 +670,8 @@ jl_function_t *jl_new_generic_function(jl_sym_t *name);
 void jl_add_method(jl_function_t *gf, jl_tuple_t *types, jl_function_t *meth,
                    jl_tuple_t *tvars, int8_t isstaged);
 DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd,
-                                    jl_tuple_t *argtypes, jl_function_t *f, jl_value_t *isstaged);
+                                    jl_tuple_t *argtypes, jl_function_t *f, jl_value_t *isstaged,
+                                    jl_value_t *call_func);
 DLLEXPORT jl_value_t *jl_box_bool(int8_t x);
 DLLEXPORT jl_value_t *jl_box_int8(int32_t x);
 DLLEXPORT jl_value_t *jl_box_uint8(uint32_t x);
diff --git a/src/julia_internal.h b/src/julia_internal.h
index 157740f37f110..c8c55a03a6bff 100644
--- a/src/julia_internal.h
+++ b/src/julia_internal.h
@@ -33,13 +33,10 @@ void jl_set_gs_ctr(uint32_t ctr);
     DLLEXPORT jl_value_t *name(jl_value_t *F, jl_value_t **args, uint32_t nargs)
 
 JL_CALLABLE(jl_trampoline);
-JL_CALLABLE(jl_f_ctor_trampoline);
 JL_CALLABLE(jl_apply_generic);
 JL_CALLABLE(jl_unprotect_stack);
 JL_CALLABLE(jl_f_no_function);
 JL_CALLABLE(jl_f_tuple);
-JL_CALLABLE(jl_f_default_ctor_1);
-JL_CALLABLE(jl_f_default_ctor_2);
 extern jl_function_t *jl_unprotect_stack_func;
 extern jl_function_t *jl_bottom_func;
 
diff --git a/src/module.c b/src/module.c
index 5f8ed958d4e14..ce9a4685416eb 100644
--- a/src/module.c
+++ b/src/module.c
@@ -35,17 +35,8 @@ jl_module_t *jl_new_module(jl_sym_t *name)
     return m;
 }
 
-JL_CALLABLE(jl_f_new_module)
+DLLEXPORT jl_value_t *jl_f_new_module(jl_sym_t *name)
 {
-    jl_sym_t *name;
-    if (nargs == 0) {
-        name = anonymous_sym;
-    }
-    else {
-        JL_NARGS(Module, 1, 1);
-        JL_TYPECHK(Module, symbol, args[0]);
-        name = (jl_sym_t*)args[0];
-    }
     jl_module_t *m = jl_new_module(name);
     m->parent = jl_main_module;
     jl_add_standard_imports(m);
diff --git a/src/task.c b/src/task.c
index 4af206a582d64..025aa0f0218d2 100644
--- a/src/task.c
+++ b/src/task.c
@@ -714,7 +714,8 @@ DLLEXPORT void gdblookup(ptrint_t ip)
 
 DLLEXPORT void jlbacktrace()
 {
-    for(size_t i=0; i < bt_size; i++)
+    size_t n = bt_size; //bt_size > 40 ? 40 : bt_size;
+    for(size_t i=0; i < n; i++)
         gdblookup(bt_data[i]);
 }
 
@@ -770,7 +771,7 @@ DLLEXPORT void jl_throw_with_superfluous_argument(jl_value_t *e, int line)
     jl_throw(e);
 }
 
-jl_task_t *jl_new_task(jl_function_t *start, size_t ssize)
+DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, size_t ssize)
 {
     size_t pagesz = jl_page_size;
     jl_task_t *t = (jl_task_t*)allocobj(sizeof(jl_task_t));
@@ -827,27 +828,6 @@ JL_CALLABLE(jl_unprotect_stack)
     return (jl_value_t*)jl_null;
 }
 
-#define JL_MIN_STACK     (4096*sizeof(void*))
-#define JL_DEFAULT_STACK (2*12288*sizeof(void*))
-
-JL_CALLABLE(jl_f_task)
-{
-    JL_NARGS(Task, 1, 2);
-    JL_TYPECHK(Task, function, args[0]);
-    /*
-      we need a somewhat large stack, because execution can trigger
-      compilation, which uses perhaps too much stack space.
-    */
-    size_t ssize = JL_DEFAULT_STACK;
-    if (nargs == 2) {
-        JL_TYPECHK(Task, long, args[1]);
-        ssize = jl_unbox_long(args[1]);
-        if (ssize < JL_MIN_STACK)
-            jl_error("Task: stack size too small");
-    }
-    return (jl_value_t*)jl_new_task((jl_function_t*)args[0], ssize);
-}
-
 JL_CALLABLE(jl_f_yieldto)
 {
     JL_NARGSV(yieldto, 1);
@@ -894,7 +874,6 @@ void jl_init_tasks(void *stack, size_t ssize)
                                             jl_any_type, jl_any_type, jl_function_type),
                                    0, 1);
     jl_tupleset(jl_task_type->types, 0, (jl_value_t*)jl_task_type);
-    jl_task_type->fptr = jl_f_task;
 
     done_sym = jl_symbol("done");
     failed_sym = jl_symbol("failed");
diff --git a/src/toplevel.c b/src/toplevel.c
index c7753a2d500d0..8c966a4a057e0 100644
--- a/src/toplevel.c
+++ b/src/toplevel.c
@@ -624,7 +624,6 @@ void jl_set_datatype_super(jl_datatype_t *tt, jl_value_t *super)
 // method definition ----------------------------------------------------------
 
 extern int jl_boot_file_loaded;
-void jl_add_constructors(jl_datatype_t *t);
 
 static int type_contains(jl_value_t *ty, jl_value_t *x)
 {
@@ -647,12 +646,14 @@ static int type_contains(jl_value_t *ty, jl_value_t *x)
 void print_func_loc(JL_STREAM *s, jl_lambda_info_t *li);
 
 DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd,
-                                    jl_tuple_t *argtypes, jl_function_t *f, jl_value_t *isstaged)
+                                    jl_tuple_t *argtypes, jl_function_t *f, jl_value_t *isstaged,
+                                    jl_value_t *call_func)
 {
     // argtypes is a tuple ((types...), (typevars...))
     jl_tuple_t *t = (jl_tuple_t*)jl_t1(argtypes);
     argtypes = (jl_tuple_t*)jl_t0(argtypes);
     jl_value_t *gf=NULL;
+    JL_GC_PUSH3(&gf, &argtypes, &t);
 
     if (bnd && bnd->value != NULL && !bnd->constp) {
         jl_errorf("cannot define function %s; it already has a value",
@@ -662,9 +663,34 @@ DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_
     if (*bp != NULL) {
         gf = *bp;
         if (!jl_is_gf(gf)) {
-            if (jl_is_datatype(gf) &&
-                ((jl_function_t*)gf)->fptr == jl_f_ctor_trampoline) {
-                jl_add_constructors((jl_datatype_t*)gf);
+            if (jl_is_datatype(gf)) {
+                // DataType: define `call`, for backwards compat with outer constructors
+                // TODO: this does not yet handle keyword sorters correctly
+                if (call_func == NULL)
+                    call_func = (jl_value_t*)jl_module_call_func(jl_current_module);
+                size_t na = jl_tuple_len(argtypes);
+                jl_tuple_t *newargtypes = jl_alloc_tuple(1 + na);
+                JL_GC_PUSH1(&newargtypes);
+                jl_tupleset(newargtypes, 0, jl_wrap_Type(gf));
+                size_t i;
+                for(i=0; i < na; i++) {
+                    jl_tupleset(newargtypes, i+1, jl_tupleref(argtypes, i));
+                }
+                argtypes = newargtypes;
+                JL_GC_POP();
+                gf = call_func;
+                // TODO: edit args, insert type first
+                if (!jl_is_expr(f->linfo->ast))
+                    f->linfo->ast = jl_uncompress_ast(f->linfo, f->linfo->ast);
+                jl_array_t *al = jl_lam_args((jl_expr_t*)f->linfo->ast);
+                if (jl_array_len(al) == 0) {
+                    al = jl_alloc_cell_1d(1);
+                    jl_exprarg(f->linfo->ast, 0) = (jl_value_t*)al;
+                }
+                else {
+                    jl_array_grow_beg(al, 1);
+                }
+                jl_cellset(al, 0, (jl_value_t*)jl_gensym());
             }
             if (!jl_is_gf(gf)) {
                 jl_error("invalid method definition: not a generic function");
@@ -702,7 +728,6 @@ DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_
         gf = (jl_value_t*)jl_new_generic_function(name);
         *bp = gf;
     }
-    JL_GC_PUSH1(&gf);
     assert(jl_is_function(f));
     assert(jl_is_tuple(argtypes));
     assert(jl_is_tuple(t));