Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
this is a combination of convert(Rational{T},x) not returning the
correct type, and the lack of a type check in codegen for new().
  • Loading branch information
JeffBezanson committed Jul 13, 2014
1 parent cf26976 commit 5ef0d8f
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 6 deletions.
1 change: 1 addition & 0 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ t_func[pointerref] = (2,2,(a,i)->(isa(a,DataType) && a<:Ptr ? a.parameters[1] :
t_func[pointerset] = (3, 3, (a,v,i)->a)

const convert_default_tfunc = function (to, from, f)
to === () && return to
!isType(to) && return Any
to = to.parameters[1]

Expand Down
4 changes: 2 additions & 2 deletions base/rational.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ function show(io::IO, x::Rational)
show(io, den(x))
end

convert{T<:Integer}(::Type{Rational{T}}, x::Rational) = Rational(convert(T,x.num),convert(T,x.den))
convert{T<:Integer}(::Type{Rational{T}}, x::Integer) = Rational(convert(T,x), convert(T,1))
convert{T<:Integer}(::Type{Rational{T}}, x::Rational) = Rational{T}(convert(T,x.num),convert(T,x.den))
convert{T<:Integer}(::Type{Rational{T}}, x::Integer) = Rational{T}(convert(T,x), convert(T,1))

convert(::Type{Rational}, x::Rational) = x
convert(::Type{Rational}, x::Integer) = convert(Rational{typeof(x)},x)
Expand Down
14 changes: 12 additions & 2 deletions src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -778,8 +778,16 @@ static void emit_type_error(Value *x, jl_value_t *type, const std::string &msg,
static void emit_typecheck(Value *x, jl_value_t *type, const std::string &msg,
jl_codectx_t *ctx)
{
Value *istype =
builder.CreateICmpEQ(emit_typeof(x), literal_pointer_val(type));
Value *istype;
if (jl_is_tuple(type) && type != (jl_value_t*)jl_tuple_type) {
istype = builder.
CreateICmpNE(builder.CreateCall3(jlsubtype_func, x, literal_pointer_val(type),
ConstantInt::get(T_int32,1)),
ConstantInt::get(T_int32,0));
}
else {
istype = builder.CreateICmpEQ(emit_typeof(x), literal_pointer_val(type));
}
BasicBlock *failBB = BasicBlock::Create(getGlobalContext(),"fail",ctx->f);
BasicBlock *passBB = BasicBlock::Create(getGlobalContext(),"pass");
builder.CreateCondBr(istype, passBB, failBB);
Expand Down Expand Up @@ -922,6 +930,8 @@ static jl_value_t *expr_type(jl_value_t *e, jl_codectx_t *ctx)
{
if (jl_is_expr(e))
return ((jl_expr_t*)e)->etype;
if (e == (jl_value_t*)jl_null)
return e;
if (jl_is_symbolnode(e))
return jl_symbolnode_type(e);
if (jl_is_quotenode(e)) {
Expand Down
20 changes: 18 additions & 2 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ static Function *jlallocobj_func;
static Function *jlalloc2w_func;
static Function *jlalloc3w_func;
static Function *jl_alloc_tuple_func;
static Function *jlsubtype_func;
static Function *setjmp_func;
static Function *box_int8_func;
static Function *box_uint8_func;
Expand Down Expand Up @@ -2704,8 +2705,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed,
else if (head == new_sym) {
jl_value_t *ty = expr_type(args[0], ctx);
size_t nargs = jl_array_len(ex->args);
if (jl_is_type_type(ty) &&
jl_is_datatype(jl_tparam0(ty)) &&
if (jl_is_type_type(ty) && jl_is_datatype(jl_tparam0(ty)) &&
jl_is_leaf_type(jl_tparam0(ty))) {
ty = jl_tparam0(ty);
jl_datatype_t *sty = (jl_datatype_t*)ty;
Expand Down Expand Up @@ -2756,6 +2756,8 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed,
builder.CreateStore(literal_pointer_val((jl_value_t*)ty),
emit_nthptr_addr(strct, (size_t)0));
if (f1) {
if (!jl_subtype(expr_type(args[1],ctx), jl_t0(sty->types), 0))
emit_typecheck(f1, jl_t0(sty->types), "new", ctx);
emit_setfield(sty, strct, 0, f1, ctx, false);
ctx->argDepth = fieldStart;
if (nf > 1 && needroots)
Expand All @@ -2778,6 +2780,10 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed,
make_gcroot(strct, ctx);
needroots = true;
}
if (rhs->getType() == jl_pvalue_llvmt) {
if (!jl_subtype(expr_type(args[i],ctx), jl_tupleref(sty->types,i-1), 0))
emit_typecheck(rhs, jl_tupleref(sty->types,i-1), "new", ctx);
}
emit_setfield(sty, strct, i-1, rhs, ctx, false);
}
ctx->argDepth = fieldStart;
Expand Down Expand Up @@ -4209,6 +4215,16 @@ static void init_julia_llvm_env(Module *m)
"jl_egal", m);
add_named_global(jlegal_func, (void*)&jl_egal);

std::vector<Type *> subt_args(0);
subt_args.push_back(jl_pvalue_llvmt);
subt_args.push_back(jl_pvalue_llvmt);
subt_args.push_back(T_int32);
jlsubtype_func =
Function::Create(FunctionType::get(T_int32, subt_args, false),
Function::ExternalLinkage,
"jl_subtype", m);
add_named_global(jlsubtype_func, (void*)&jl_subtype);

std::vector<Type*> aoargs(0);
aoargs.push_back(T_size);
jlallocobj_func =
Expand Down
3 changes: 3 additions & 0 deletions test/numbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,9 @@ for N = int_types, D = int_types
@test typeof(convert(N,2)//convert(D,3)) <: Rational{T}
end

# issue #7564
@test typeof(convert(Rational{Integer},1)) === Rational{Integer}

# check type of constructed complexes
real_types = {Int8, Uint8, Int16, Uint16, Int32, Uint32, Int64, Uint64, Float32, Float64,
Rational{Int8}, Rational{Uint8}, Rational{Int16}, Rational{Uint16},
Expand Down

0 comments on commit 5ef0d8f

Please sign in to comment.