From 84e80f411922e1830bf18983997c529e9cdcf066 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 14 Feb 2015 15:19:58 -0500 Subject: [PATCH] eliminate Undef and Top types. fixes #8631 thanks to @vtjnash for the test case. It's hard to tell whether this is the real fix for the problem, but it works, and having a type that's not a subtype of Any around was just a huge pain. Things are simpler without it. Inside the compiler, undefinedness is no longer part of a variable's type. Instead there is a bit per variable telling whether it is ever used when undefined. This has the disadvantage of being coarser, since it doesn't give the undefinedness of each variable use. However it has the advantage of giving better type info: if a variable is either a Float64 or undefined, its type is just "Float64" and we can optimize accordingly. This combines well with the future optimization of storing possibly-undefined variables unboxed (#6914). For that we will add a run time 1-bit flag to track definedness, and then LLVM can hopefully eliminate checks along paths where the flag is known to be set, gaining back the previous granularity. --- base/base.jl | 2 +- base/boot.jl | 2 +- base/inference.jl | 127 ++++++++++++++++++++++++---------------------- base/serialize.jl | 2 +- base/show.jl | 8 +-- base/sysimg.jl | 1 - src/alloc.c | 1 - src/builtins.c | 2 - src/cgutils.cpp | 4 +- src/codegen.cpp | 20 +++----- src/dump.c | 42 +++++++-------- src/jltypes.c | 28 ++-------- src/julia.h | 7 ++- src/toplevel.c | 3 +- test/core.jl | 11 ++-- 15 files changed, 115 insertions(+), 145 deletions(-) diff --git a/base/base.jl b/base/base.jl index bdfc7dfcb441b..54aa8b0f66402 100644 --- a/base/base.jl +++ b/base/base.jl @@ -271,7 +271,7 @@ call{T}(::Type{Array{T}}, m::Integer, n::Integer, o::Integer) = # TODO: possibly turn these into deprecations Array{T,N}(::Type{T}, d::NTuple{N,Int}) = Array{T}(d) -Array(T::Type, d::Integer...) = Array{T}(convert((Int...), d)) +Array{T}(::Type{T}, d::Integer...) = Array{T}(convert((Int...), d)) Array{T}(::Type{T}, m::Integer) = Array{T}(m) Array{T}(::Type{T}, m::Integer,n::Integer) = Array{T}(m,n) Array{T}(::Type{T}, m::Integer,n::Integer,o::Integer) = Array{T}(m,n,o) diff --git a/base/boot.jl b/base/boot.jl index af793cbf3c5b5..686aea13b16f6 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -117,7 +117,7 @@ import Core.Intrinsics.ccall export # key types - Any, DataType, Vararg, ANY, NTuple, Top, + Any, DataType, Vararg, ANY, NTuple, Tuple, Type, TypeConstructor, TypeName, TypeVar, Union, UnionType, Void, AbstractArray, DenseArray, # special objects diff --git a/base/inference.jl b/base/inference.jl index 24044823e92bb..4ccdc4c94ccf9 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -15,6 +15,7 @@ type StaticVarInfo vars::Array{Any,1} # names of args and locals gensym_types::Array{Any,1} # types of the GenSym's in this function label_counter::Int # index of the current highest label for this function + fedbackvars::ObjectIdDict end type EmptyCallStack @@ -342,7 +343,7 @@ const getfield_tfunc = function (A, s0, name) return abstract_eval_constant(eval(A1,fld)) end if s === Module - return Top + return Any end if isType(s0) sp = s0.parameters[1] @@ -939,9 +940,6 @@ end function abstract_eval_arg(a::ANY, vtypes::ANY, sv::StaticVarInfo) t = abstract_eval(a, vtypes, sv) - if isa(a,Symbol) || isa(a,SymbolNode) || isa(a,GenSym) - t = typeintersect(t,Any) # remove Undef - end if isa(t,TypeVar) && t.lb == Bottom && isleaftype(t.ub) t = t.ub end @@ -1018,19 +1016,18 @@ function abstract_eval(e::ANY, vtypes, sv::StaticVarInfo) abstract_eval(e.args[1], vtypes, sv) t = Any elseif is(e.head,:static_typeof) - t0 = abstract_eval(e.args[1], vtypes, sv) - # intersect with Any to remove Undef - t = typeintersect(t0, Any) + var = e.args[1] + t = t0 = abstract_eval(var, vtypes, sv) if isa(t,DataType) && typeseq(t,t.name.primary) # remove unnecessary typevars t = t.name.primary end - if is(t,Bottom) && Undef<:t0 - # the first time we see this statement the variable will probably - # be Undef; return Bottom so this doesn't contribute to the type - # we eventually pick. - elseif is(t,Bottom) - t = Type{Bottom} + if is(t,Bottom) + # if we haven't gotten fed-back type info yet, return Bottom. otherwise + # Bottom is the actual type of the variable, so return Type{Bottom}. + if haskey(sv.fedbackvars, var) + t = Type{Bottom} + end elseif isleaftype(t) t = Type{t} elseif isleaftype(inference_stack.types) @@ -1059,7 +1056,7 @@ function abstract_eval(e::ANY, vtypes, sv::StaticVarInfo) else t = Any end - if isa(t,TypeVar) && t.lb === Bottom + if isa(t,TypeVar) # no need to use a typevar as the type of an expression t = t.ub end @@ -1082,12 +1079,6 @@ function abstract_eval_constant(x::ANY) return typeof(x) end -# Undef is the static type of a value location (e.g. variable) that is -# undefined. The corresponding run-time type is Bottom, since accessing an -# undefined location is an error. A non-lvalue expression cannot have -# type Undef, only Bottom. -# typealias Top Union(Any,Undef) - abstract_eval_global(s::Symbol) = abstract_eval_global((inference_stack::CallStack).mod, s) @@ -1095,17 +1086,13 @@ function abstract_eval_global(M, s::Symbol) if isconst(M,s) return abstract_eval_constant(eval(M,s)) end - if !isdefined(M,s) - return Top - end - # TODO: change to Undef if there's a way to clear variables return Any end function abstract_eval_gensym(s::GenSym, sv::StaticVarInfo) typ = sv.gensym_types[s.id+1] if typ === NF - return Undef + return Bottom end return typ end @@ -1137,7 +1124,7 @@ function abstract_eval_symbol(s::Symbol, vtypes::ObjectIdDict, sv::StaticVarInfo end if s in sv.vars # local variable use not reached - return Top + return Bottom end # global return abstract_eval_global(s) @@ -1208,18 +1195,10 @@ function type_too_complex(t::ANY, d) end function tmerge(typea::ANY, typeb::ANY) - if is(typea,NF) - return typeb - end - if is(typeb,NF) - return typea - end - if typea <: typeb - return typeb - end - if typeb <: typea - return typea - end + is(typea, NF ) && return typeb + is(typeb, NF) && return typea + typea <: typeb && return typeb + typeb <: typea && return typea if isa(typea, Tuple) && isa(typeb, Tuple) if length(typea) == length(typeb) && !isvatuple(typea) && !isvatuple(typeb) return typejoin(typea, typeb) @@ -1230,7 +1209,7 @@ function tmerge(typea::ANY, typeb::ANY) if length(u.types) > MAX_TYPEUNION_LEN || type_too_complex(u, 0) # don't let type unions get too big # TODO: something smarter, like a common supertype - return Undef<:u ? Top : Any + return Any end return u end @@ -1252,13 +1231,19 @@ function stupdate(state::ObjectIdDict, changes::Union(StateUpdate,VarTable), var state end -function stchanged(new::Union(StateUpdate,VarTable), old, vars) +function stchanged(new::Union(StateUpdate,VarTable), old, vinflist) if is(old,()) return true end - for i = 1:length(vars) - v = vars[i] - if tchanged(new[v], get(old,v,NF)) + for vi in vinflist + v = vi[1] + newtype = new[v] + oldtype = get(old,v,NF) + if (newtype === Bottom && oldtype !== NF && oldtype !== Bottom) || + (oldtype === Bottom && newtype !== NF && newtype !== Bottom) + vi[3] |= 32 + end + if tchanged(newtype, oldtype) return true end end @@ -1457,7 +1442,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) # initial types s[1] = ObjectIdDict() for v in vars - s[1][v] = Undef + s[1][v] = Bottom end if la > 0 lastarg = ast.args[1][la] @@ -1507,7 +1492,8 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) cenv[vname] = vtype s[1][vname] = vtype end - for vi = ((ast.args[2][2])::Array{Any,1}) + vinflist = ast.args[2][2]::Array{Any,1} + for vi in vinflist vi::Array{Any,1} if (vi[3]&4)!=0 # variables assigned by inner functions are treated like @@ -1523,7 +1509,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) gensym_init = Any[ NF for i = 1:length(gensym_uses) ] gensym_types = copy(gensym_init) - sv = StaticVarInfo(sparams, cenv, vars, gensym_types, length(labels)) + sv = StaticVarInfo(sparams, cenv, vars, gensym_types, length(labels), ObjectIdDict()) frame.sv = sv recpts = IntSet() # statements that depend recursively on our value @@ -1565,7 +1551,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) if !is(cur_hand,()) # propagate type info to exception handler l = cur_hand[1]::Int - if stchanged(changes, s[l], vars) + if stchanged(changes, s[l], vinflist) push!(W, l) s[l] = stupdate(s[l], changes, vars) end @@ -1598,7 +1584,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) else # general case handler_at[l] = cur_hand - if stchanged(changes, s[l], vars) + if stchanged(changes, s[l], vinflist) push!(W, l) s[l] = stupdate(s[l], changes, vars) end @@ -1619,6 +1605,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) gensym_init[id] = vt typegotoredo = true end + sv.fedbackvars[var] = true end elseif is(hd,:return) pc´ = n+1 @@ -1663,7 +1650,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) end end if pc´<=n && (handler_at[pc´] = cur_hand; true) && - stchanged(changes, s[pc´], vars) + stchanged(changes, s[pc´], vinflist) s[pc´] = stupdate(s[pc´], changes, vars) pc = pc´ elseif pc´ in W @@ -1752,7 +1739,7 @@ function record_var_type(e::Symbol, t::ANY, decls) end end -function eval_annotate(e::ANY, vtypes::ANY, sv::StaticVarInfo, decls, clo) +function eval_annotate(e::ANY, vtypes::ANY, sv::StaticVarInfo, decls, clo, undefs) if isa(e, Symbol) e = e::Symbol @@ -1761,6 +1748,9 @@ function eval_annotate(e::ANY, vtypes::ANY, sv::StaticVarInfo, decls, clo) return e end t = abstract_eval(e, vtypes, sv) + if t === Bottom + undefs[e] = true + end record_var_type(e, t, decls) return (is(t,Any) || is(t,IntrinsicFunction)) ? e : SymbolNode(e, t) end @@ -1768,6 +1758,9 @@ function eval_annotate(e::ANY, vtypes::ANY, sv::StaticVarInfo, decls, clo) if isa(e, SymbolNode) e = e::SymbolNode curtype = e.typ + if curtype === Bottom + undefs[e.name] = true + end t = abstract_eval(e.name, vtypes, sv) if !(curtype <: t) || typeseq(curtype, t) record_var_type(e.name, t, decls) @@ -1800,7 +1793,7 @@ function eval_annotate(e::ANY, vtypes::ANY, sv::StaticVarInfo, decls, clo) # we don't use types on assignment LHS s = s.name end - e.args[2] = eval_annotate(e.args[2], vtypes, sv, decls, clo) + e.args[2] = eval_annotate(e.args[2], vtypes, sv, decls, clo, undefs) if isa(s,Symbol) # TODO: if this def does not reach any uses, maybe don't do this rhstype = exprtype(e.args[2], sv) @@ -1814,7 +1807,7 @@ function eval_annotate(e::ANY, vtypes::ANY, sv::StaticVarInfo, decls, clo) for i=i0:length(e.args) subex = e.args[i] if !(isa(subex,Number) || isa(subex,AbstractString)) - e.args[i] = eval_annotate(subex, vtypes, sv, decls, clo) + e.args[i] = eval_annotate(subex, vtypes, sv, decls, clo, undefs) end end if (head === :call || head === :call1) && isa(e.args[1],LambdaStaticData) @@ -1832,6 +1825,7 @@ end function type_annotate(ast::Expr, states::Array{Any,1}, sv::ANY, rettype::ANY, args) decls = ObjectIdDict() + undefs = ObjectIdDict() # initialize decls with argument types for arg in args decls[arg] = states[1][arg] @@ -1842,7 +1836,7 @@ function type_annotate(ast::Expr, states::Array{Any,1}, sv::ANY, rettype::ANY, st_i = states[i] if st_i !== () # st_i === () => unreached statement (see issue #7836) - body[i] = eval_annotate(body[i], st_i, sv, decls, closures) + body[i] = eval_annotate(body[i], st_i, sv, decls, closures, undefs) end end ast.args[3].typ = rettype @@ -1852,11 +1846,17 @@ function type_annotate(ast::Expr, states::Array{Any,1}, sv::ANY, rettype::ANY, if (vi[3]&4)==0 vi[2] = get(decls, vi[1], vi[2]) end + if haskey(undefs, vi[1]) + vi[3] |= 32 + end end for vi in ast.args[2][3]::Array{Any,1} if (vi[3]&4)==0 vi[2] = get(decls, vi[1], vi[2]) end + if haskey(undefs, vi[1]) + vi[3] |= 32 + end end ast.args[2][4] = sv.gensym_types @@ -2350,7 +2350,6 @@ function inlineable(f::ANY, e::Expr, atypes::Tuple, sv::StaticVarInfo, enclosing for i = 1:numarg name = newnames[i] argtype = exprtype(argexprs[i],sv) - argtype = typeintersect(argtype,Any) # remove Undef push!(locals, Any[name,argtype,0]) push!(newcall.args, argtype===Any ? name : SymbolNode(name, argtype)) end @@ -3044,7 +3043,7 @@ function remove_redundant_temp_vars(ast, sa) # this transformation is not valid for vars used before def. # we need to preserve the point of assignment to know where to # throw errors (issue #4645). - if !occurs_undef(v, ast.args[3]) + if !occurs_undef(v, ast.args[3], varinfo) # the transformation is not ideal if the assignment # is present for the auto-unbox functionality @@ -3063,18 +3062,22 @@ end function local_typeof(v, varinfo) for (v2, typ, info) in varinfo - if v === v2 - return typ - end + v === v2 && return typ + end + @assert false "v not in varinfo" +end +function var_infobits(v, varinfo) + for (v2, typ, info) in varinfo + v === v2 && return info end @assert false "v not in varinfo" end -occurs_undef(var::GenSym, expr) = false +occurs_undef(var::GenSym, expr, varinfo) = false -occurs_undef(var, expr) = - occurs_more(expr, - e->(isa(e,SymbolNode) && symequal(var,e) && issubtype(Undef,e.typ)), 0)>0 +occurs_undef(var, expr, varinfo) = + occurs_more(expr, e->(isa(e,SymbolNode) && symequal(var,e) && + ((var_infobits(e.name,varinfo)&32)!=0)), 0)>0 # compute set of vars assigned once function find_sa_vars(ast) diff --git a/base/serialize.jl b/base/serialize.jl index b475de2371b0e..9f6ff635cf148 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -22,7 +22,7 @@ let i = 2 UTF16String, UTF32String, Float16, :reserved9, :reserved10, :reserved11, :reserved12, - (), Bool, Any, :Any, Bottom, Top, Undef, Type, + (), Bool, Any, :Any, Bottom, :reserved21, :reserved22, Type, :Array, :TypeVar, :Box, :lambda, :body, :return, :call, symbol("::"), :(=), :null, :gotoifnot, :A, :B, :C, :M, :N, :T, :S, :X, :Y, diff --git a/base/show.jl b/base/show.jl index 6309574ced132..5b78f1f0e986d 100644 --- a/base/show.jl +++ b/base/show.jl @@ -66,13 +66,7 @@ function show(io::IO, x::IntrinsicFunction) print(io, "(intrinsic function #", box(Int32,unbox(IntrinsicFunction,x)), ")") end -function show(io::IO, x::UnionType) - if is(x,Top) - print(io, "Top") - else - print(io, "Union", x.types) - end -end +show(io::IO, x::UnionType) = print(io, "Union", x.types) show(io::IO, x::TypeConstructor) = show(io, x.body) diff --git a/base/sysimg.jl b/base/sysimg.jl index c06826a328fbc..f6f422eb00bbf 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -74,7 +74,6 @@ importall .SimdLoop include("reduce.jl") # compiler -import Core.Undef # used internally by compiler include("inference.jl") # For OS specific stuff in I/O diff --git a/src/alloc.c b/src/alloc.c index 808cb570cb86a..2c8ad19c43243 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -15,7 +15,6 @@ extern "C" { jl_value_t *jl_true; jl_value_t *jl_false; -jl_datatype_t *jl_undef_type; jl_tvar_t *jl_typetype_tvar; jl_datatype_t *jl_typetype_type; jl_value_t *jl_ANY_flag; diff --git a/src/builtins.c b/src/builtins.c index 225707fb7b46c..1e509b9928505 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1138,7 +1138,6 @@ void jl_init_primitives(void) // builtin types add_builtin("Any", (jl_value_t*)jl_any_type); - add_builtin("Top", (jl_value_t*)jl_top_type); add_builtin("Void", (jl_value_t*)jl_void_type); add_builtin("nothing", (jl_value_t*)jl_nothing); add_builtin("TypeVar", (jl_value_t*)jl_tvar_type); @@ -1150,7 +1149,6 @@ void jl_init_primitives(void) add_builtin("Vararg", (jl_value_t*)jl_vararg_type); add_builtin("DataType", (jl_value_t*)jl_datatype_type); add_builtin("UnionType", (jl_value_t*)jl_uniontype_type); - add_builtin("Undef", (jl_value_t*)jl_undef_type); add_builtin("Module", (jl_value_t*)jl_module_type); add_builtin("Method", (jl_value_t*)jl_method_type); diff --git a/src/cgutils.cpp b/src/cgutils.cpp index a34970434446f..114155005fb2a 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1074,7 +1074,7 @@ static jl_value_t *expr_type(jl_value_t *e, jl_codectx_t *ctx) e = jl_fieldref(e,0); jl_binding_t *b = jl_get_binding(topmod(ctx), (jl_sym_t*)e); if (!b || !b->value) - return jl_top_type; + return (jl_value_t*)jl_any_type; if (b->constp) { e = b->value; goto type_of_constant; @@ -1101,7 +1101,7 @@ static jl_value_t *expr_type(jl_value_t *e, jl_codectx_t *ctx) } jl_binding_t *b = jl_get_binding(ctx->module, (jl_sym_t*)e); if (!b || !b->value) - return jl_top_type; + return (jl_value_t*)jl_any_type; if (b->constp) e = b->value; else diff --git a/src/codegen.cpp b/src/codegen.cpp index 907968a1c7a6d..187c9662155f6 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1360,7 +1360,6 @@ static void simple_escape_analysis(jl_value_t *expr, bool esc, jl_codectx_t *ctx } return; } - jl_value_t *ty = expr_type(expr, ctx); if (jl_is_symbolnode(expr)) { expr = (jl_value_t*)jl_symbolnode_sym(expr); } @@ -1369,9 +1368,6 @@ static void simple_escape_analysis(jl_value_t *expr, bool esc, jl_codectx_t *ctx if (ctx->vars.find(vname) != ctx->vars.end()) { jl_varinfo_t &vi = ctx->vars[vname]; vi.escapes |= esc; - vi.usedUndef |= (jl_subtype((jl_value_t*)jl_undef_type,ty,0)!=0); - if (!ctx->linfo->inferred) - vi.usedUndef = true; vi.used = true; } } @@ -2869,8 +2865,7 @@ static Value *emit_var(jl_sym_t *sym, jl_value_t *ty, jl_codectx_t *ctx, bool is } assert(jbp == NULL); if (arg != NULL || // arguments are always defined - ((!is_var_closed(sym, ctx) || !vi.isAssigned) && - !jl_subtype((jl_value_t*)jl_undef_type, ty, 0))) { + ((!is_var_closed(sym, ctx) || !vi.isAssigned) && !vi.usedUndef)) { Value *theLoad = builder.CreateLoad(bp, vi.isVolatile); if (vi.closureidx > -1 && !(vi.isAssigned && vi.isCaptured)) theLoad = tbaa_decorate(tbaa_const, (Instruction*)theLoad); @@ -3001,7 +2996,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, jl_sym_t *sym = (jl_sym_t*)expr; if (valuevar != NULL) *valuevar = sym; - return emit_var(sym, (jl_value_t*)jl_undef_type, ctx, isboxed); + return emit_var(sym, (jl_value_t*)jl_any_type, ctx, isboxed); } if (jl_is_symbolnode(expr)) { if (!valuepos) return NULL; @@ -3067,15 +3062,12 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, } if (jl_is_topnode(expr)) { jl_sym_t *var = (jl_sym_t*)jl_fieldref(expr,0); - jl_value_t *etype = expr_type(expr, ctx); jl_module_t *mod = topmod(ctx); jl_binding_t *b = jl_get_binding(mod, var); if (b == NULL) b = jl_get_binding_wr(mod, var); Value *bp = julia_binding_gv(b); - if ((b->constp && b->value!=NULL) || - (etype!=(jl_value_t*)jl_any_type && - !jl_subtype((jl_value_t*)jl_undef_type, etype, 0))) { + if (b->constp && b->value!=NULL) { return builder.CreateLoad(bp, false); } return emit_checked_var(bp, var, ctx); @@ -3446,7 +3438,7 @@ static bool store_unboxed_p(jl_sym_t *s, jl_codectx_t *ctx) jl_varinfo_t &vi = ctx->vars[s]; // only store a variable unboxed if type inference has run, which // checks that the variable is not referenced undefined. - return (ctx->linfo->inferred && !vi.isCaptured && + return (ctx->linfo->inferred && !vi.isCaptured && !vi.usedUndef && // don't unbox vararg tuples s != ctx->vaName && store_unboxed_p(vi.declType)); } @@ -3749,6 +3741,7 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) if (varinfo.isCaptured) varinfo.used = true; varinfo.isSA = (jl_vinfo_sa(vi)!=0); + varinfo.usedUndef = (jl_vinfo_usedundef(vi)!=0) || (!varinfo.isArgument && !lam->inferred); varinfo.declType = jl_cellref(vi,1); } vinfos = jl_lam_capt(ast); @@ -3763,8 +3756,9 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) varinfo.closureidx = i; varinfo.isAssigned = (jl_vinfo_assigned(vi)!=0); varinfo.isCaptured = true; - varinfo.used = true; varinfo.escapes = true; + varinfo.used = true; + varinfo.usedUndef = (jl_vinfo_usedundef(vi)!=0) || !lam->inferred; varinfo.declType = jl_cellref(vi,1); } diff --git a/src/dump.c b/src/dump.c index 2ba43dee1d20d..86c53ddb5a2e7 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1848,30 +1848,26 @@ void jl_init_serializer(void) jl_box_int64(51), jl_box_int64(52), jl_box_int64(53), jl_box_int64(54), jl_box_int64(55), jl_box_int64(56), #endif - jl_labelnode_type, jl_linenumbernode_type, - jl_gotonode_type, jl_quotenode_type, jl_topnode_type, - jl_type_type, jl_bottom_type, jl_pointer_type, - jl_vararg_type, jl_ntuple_type, jl_abstractarray_type, - jl_densearray_type, jl_box_type, jl_void_type, - jl_typector_type, jl_undef_type, jl_top_type, jl_typename_type, - jl_task_type, jl_uniontype_type, jl_typetype_type, jl_typetype_tvar, - jl_ANY_flag, jl_array_any_type, jl_intrinsic_type, jl_method_type, - jl_methtable_type, jl_voidpointer_type, jl_newvarnode_type, - jl_array_symbol_type, jl_tupleref(jl_tuple_type,0), - - jl_symbol_type->name, jl_gensym_type->name, - jl_pointer_type->name, jl_datatype_type->name, - jl_uniontype_type->name, jl_array_type->name, jl_expr_type->name, - jl_typename_type->name, jl_type_type->name, jl_methtable_type->name, - jl_method_type->name, jl_tvar_type->name, jl_vararg_type->name, - jl_ntuple_type->name, jl_abstractarray_type->name, - jl_densearray_type->name, jl_void_type->name, - jl_lambda_info_type->name, jl_module_type->name, jl_box_type->name, - jl_function_type->name, jl_typector_type->name, - jl_intrinsic_type->name, jl_undef_type->name, jl_task_type->name, + jl_labelnode_type, jl_linenumbernode_type, jl_gotonode_type, + jl_quotenode_type, jl_topnode_type, jl_type_type, jl_bottom_type, + jl_pointer_type, jl_vararg_type, jl_ntuple_type, + jl_abstractarray_type, jl_densearray_type, jl_box_type, jl_void_type, + jl_typector_type, jl_typename_type, jl_task_type, jl_uniontype_type, + jl_typetype_type, jl_typetype_tvar, jl_ANY_flag, jl_array_any_type, + jl_intrinsic_type, jl_method_type, jl_methtable_type, + jl_voidpointer_type, jl_newvarnode_type, jl_array_symbol_type, + jl_tupleref(jl_tuple_type,0), + + jl_symbol_type->name, jl_gensym_type->name, jl_pointer_type->name, + jl_datatype_type->name, jl_uniontype_type->name, jl_array_type->name, + jl_expr_type->name, jl_typename_type->name, jl_type_type->name, + jl_methtable_type->name, jl_method_type->name, jl_tvar_type->name, + jl_vararg_type->name, jl_ntuple_type->name, jl_abstractarray_type->name, + jl_densearray_type->name, jl_void_type->name, jl_lambda_info_type->name, + jl_module_type->name, jl_box_type->name, jl_function_type->name, + jl_typector_type->name, jl_intrinsic_type->name, jl_task_type->name, jl_labelnode_type->name, jl_linenumbernode_type->name, - jl_gotonode_type->name, jl_quotenode_type->name, - jl_topnode_type->name, + jl_gotonode_type->name, jl_quotenode_type->name, jl_topnode_type->name, jl_root_task, jl_bottom_func, diff --git a/src/jltypes.c b/src/jltypes.c index 3d54010947f1c..9ab1c5e26efe7 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -33,7 +33,6 @@ jl_datatype_t *jl_uniontype_type; jl_datatype_t *jl_datatype_type; jl_value_t *jl_bottom_type; -jl_value_t *jl_top_type; jl_datatype_t *jl_vararg_type; jl_datatype_t *jl_abstractarray_type; jl_datatype_t *jl_densearray_type; @@ -842,8 +841,6 @@ static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, return intersect_union((jl_uniontype_t*)a, b, penv, eqc, var); if (jl_is_uniontype(b)) return intersect_union((jl_uniontype_t*)b, a, penv, eqc, var); - if (a == (jl_value_t*)jl_undef_type) return (jl_value_t*)jl_bottom_type; - if (b == (jl_value_t*)jl_undef_type) return (jl_value_t*)jl_bottom_type; if (a == (jl_value_t*)jl_any_type || a == jl_ANY_flag) return b; if (b == (jl_value_t*)jl_any_type || b == jl_ANY_flag) return a; // tuple @@ -1925,14 +1922,9 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_value_t **env, size_t n, iparams[i] = t; } else { - jl_value_t *tv = - jl_tupleref(((jl_datatype_t*)tc)->parameters, i); - iparams[i] = (jl_value_t*)inst_type_w_(elt, env, n, stack, - elt != tv); + jl_value_t *tv = jl_tupleref(((jl_datatype_t*)tc)->parameters, i); + iparams[i] = (jl_value_t*)inst_type_w_(elt, env, n, stack, elt != tv); if (jl_is_typevar(tv) && !jl_is_typevar(iparams[i])) { - // TODO: Undef should not be special here; fix. - // maybe introduce Top == Union(Any,Undef), and make this - // the default upper bound. if (!jl_subtype(iparams[i], tv, 0)) { jl_type_error_rt(tt->name->name->name, ((jl_tvar_t*)tv)->name->name, @@ -2249,9 +2241,6 @@ static int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int invariant) if (ta) a = (jl_value_t*)jl_typeof(a); if (a == b) return 1; - if ((a==(jl_value_t*)jl_undef_type && !jl_is_typevar(b)) || - b==(jl_value_t*)jl_undef_type) - return 0; if (!invariant && (jl_datatype_t*)b == jl_any_type) return 1; if (jl_is_type_type(b) && jl_is_typevar(jl_tparam0(b)) && jl_is_tuple(a)) { @@ -2512,9 +2501,6 @@ static int jl_type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant) return 0; } - if ((a==(jl_value_t*)jl_undef_type && !jl_is_typevar(b)) || - b==(jl_value_t*)jl_undef_type) - return 0; if (!invariant && (jl_datatype_t*)b == jl_any_type) return 1; if (jl_is_type_type(b) && jl_is_typevar(jl_tparam0(b)) && jl_is_tuple(a)) { @@ -3049,14 +3035,8 @@ void jl_init_types(void) jl_type_type, jl_any_type), 0, 0, 0); - jl_undef_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Undef"), - jl_any_type, jl_null); - - jl_top_type = jl_new_struct(jl_uniontype_type, - jl_tuple2(jl_any_type, jl_undef_type)); - jl_tvar_t *tttvar = jl_new_typevar(jl_symbol("T"), - (jl_value_t*)jl_bottom_type,jl_top_type); + (jl_value_t*)jl_bottom_type,(jl_value_t*)jl_any_type); jl_type_type->parameters = jl_tuple(1, tttvar); jl_tuple_t *tv; @@ -3261,7 +3241,7 @@ void jl_init_types(void) // Type{T} jl_typetype_tvar = jl_new_typevar(jl_symbol("T"), - (jl_value_t*)jl_bottom_type,jl_top_type); + (jl_value_t*)jl_bottom_type,(jl_value_t*)jl_any_type); jl_typetype_type = (jl_datatype_t*)jl_apply_type((jl_value_t*)jl_type_type, jl_tuple(1,jl_typetype_tvar)); diff --git a/src/julia.h b/src/julia.h index 5944d2775f403..33fc1e34ba742 100644 --- a/src/julia.h +++ b/src/julia.h @@ -306,7 +306,6 @@ extern DLLEXPORT jl_datatype_t *jl_type_type; extern DLLEXPORT jl_tvar_t *jl_typetype_tvar; extern DLLEXPORT jl_datatype_t *jl_typetype_type; extern DLLEXPORT jl_value_t *jl_ANY_flag; -extern DLLEXPORT jl_datatype_t *jl_undef_type; extern DLLEXPORT jl_datatype_t *jl_typename_type; extern DLLEXPORT jl_datatype_t *jl_typector_type; extern DLLEXPORT jl_datatype_t *jl_sym_type; @@ -323,7 +322,6 @@ extern DLLEXPORT jl_datatype_t *jl_uniontype_type; extern DLLEXPORT jl_datatype_t *jl_datatype_type; extern DLLEXPORT jl_value_t *jl_bottom_type; -extern DLLEXPORT jl_value_t *jl_top_type; extern DLLEXPORT jl_datatype_t *jl_lambda_info_type; extern DLLEXPORT jl_datatype_t *jl_module_type; extern DLLEXPORT jl_datatype_t *jl_vararg_type; @@ -1060,6 +1058,11 @@ STATIC_INLINE int jl_vinfo_sa(jl_array_t *vi) return (jl_unbox_long(jl_cellref(vi,2))&16)!=0; } +STATIC_INLINE int jl_vinfo_usedundef(jl_array_t *vi) +{ + return (jl_unbox_long(jl_cellref(vi,2))&32)!=0; +} + // calling into julia --------------------------------------------------------- STATIC_INLINE diff --git a/src/toplevel.c b/src/toplevel.c index 9fda351abcbda..0439c764b3c59 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -613,8 +613,7 @@ void jl_check_type_tuple(jl_tuple_t *t, jl_sym_t *name, const char *ctx) void jl_set_datatype_super(jl_datatype_t *tt, jl_value_t *super) { - if (!jl_is_datatype(super) || super == (jl_value_t*)jl_undef_type || - !jl_is_abstracttype(super) || + if (!jl_is_datatype(super) || !jl_is_abstracttype(super) || tt->name == ((jl_datatype_t*)super)->name || jl_subtype(super,(jl_value_t*)jl_vararg_type,0) || jl_subtype(super,(jl_value_t*)jl_type_type,0)) { diff --git a/test/core.jl b/test/core.jl index 24698683d9721..6be520c0a174d 100644 --- a/test/core.jl +++ b/test/core.jl @@ -52,9 +52,9 @@ let T = TypeVar(:T,true) @test typeintersect((T,T), (Union(Float64,Int64),Int64)) == (Int64,Int64) @test typeintersect((T,T), (Int64,Union(Float64,Int64))) == (Int64,Int64) - TT = TypeVar(:T,Top) - S = TypeVar(:S,true); N = TypeVar(:N,true) - @test typeintersect(Type{TypeVar(:T,Array{TT,1})},Type{Array{S,N}}) == Type{Array{S,1}} + TT = TypeVar(:T) + S = TypeVar(:S,true); N = TypeVar(:N,true); SN = TypeVar(:S,Number,true) + @test typeintersect(Type{TypeVar(:T,Array{TT,1})},Type{Array{SN,N}}) == Type{Array{SN,1}} # issue #5359 @test typeintersect((Type{Array{T,1}},Array{T,1}), (Type{AbstractVector},Vector{Int})) === Bottom @@ -2156,3 +2156,8 @@ let @test g((),Int) == 0 @test g((),()) == () end + +# issue #8631 +f8631(::(Type, Type...), ::(Any, Any...)) = 1 +f8631{T}(::Type{(T...)}, x::Tuple) = 2 +@test length(methods(f8631, ((Type, Type...), (Any, Any...)))) == 2