diff --git a/base/inference.jl b/base/inference.jl index 77f2160ba6459..18fe89154bed9 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -698,9 +698,10 @@ function abstract_call_gf(f, fargs, argtype, e) return Any end for (m::SimpleVector) in x + sig = m[1] local linfo linfo = try - func_for_method(m[3],argtype,m[2]) + func_for_method(m[3],sig,m[2]) catch NF end @@ -709,7 +710,6 @@ function abstract_call_gf(f, fargs, argtype, e) break end linfo = linfo::LambdaStaticData - sig = m[1] lsig = length(m[3].sig.parameters) # limit argument type tuple based on size of definition signature. # for example, given function f(T, Any...), limit to 3 arguments diff --git a/src/gf.c b/src/gf.c index c367a5841e289..91f5dce8736dc 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1052,6 +1052,15 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *tt, assert(jl_is_svec(env)); func = m->func; + if (inexact && !jl_types_equal(ti, (jl_value_t*)tt)) { + // the compiler might attempt jl_get_specialization on e.g. + // convert(::Type{Type{Int}}, ::DataType), which is concrete but might not + // equal the run time type. in this case ti would be {Type{Type{Int}}, Type{Int}} + // but tt would be {Type{Type{Int}}, DataType}. + JL_GC_POP(); + return jl_bottom_func; + } + if (m->isstaged) func = jl_instantiate_staged(m,tt,env); diff --git a/src/jltypes.c b/src/jltypes.c index d7b29e3706944..ccbde80774b1e 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1238,8 +1238,15 @@ static jl_value_t *meet(jl_value_t *X, jl_value_t *Y, variance_t var) // example: {Type{Int},} => {DataType,} // calling f{T}(x::T) as f({Int,}) should give T == {DataType,}, but we // might temporarily represent this type as {Type{Int},} for more precision. -static jl_value_t *type_to_static_parameter_value(jl_value_t *t) +static jl_value_t *type_to_static_parameter_value(jl_value_t *t, jl_value_t *tv, jl_value_t **tvs, int ntv) { + int i; + for(i=0; i < ntv; i++) { + if (tv == tvs[i]) + break; + } + if (i >= ntv) + return t; // don't widen vars not in env if (jl_is_type_type(t) && !jl_is_typevar(jl_tparam0(t))) return jl_typeof(jl_tparam0(t)); if (jl_is_tuple_type(t)) { @@ -1249,7 +1256,7 @@ static jl_value_t *type_to_static_parameter_value(jl_value_t *t) jl_svec_t *np = jl_alloc_svec(l); JL_GC_PUSH1(&np); for(size_t i=0; i < l; i++) { - jl_value_t *el = type_to_static_parameter_value(jl_svecref(p,i)); + jl_value_t *el = type_to_static_parameter_value(jl_svecref(p,i), NULL, NULL, 0); jl_svecset(np, i, el); if (el != jl_svecref(p,i)) changed = 1; @@ -1275,7 +1282,7 @@ void print_env(cenv_t *soln) } */ -static int solve_tvar_constraints(cenv_t *env, cenv_t *soln) +static int solve_tvar_constraints(cenv_t *env, cenv_t *soln, jl_value_t **tvs, int ntv) { jl_value_t *rt1=NULL, *rt2=NULL, *S=NULL; JL_GC_PUSH3(&rt1, &rt2, &S); @@ -1319,8 +1326,8 @@ static int solve_tvar_constraints(cenv_t *env, cenv_t *soln) if (TT == T) { // found T=SS in env if (!jl_is_typevar(SS)) { - rt1 = type_to_static_parameter_value(S); - rt2 = type_to_static_parameter_value(SS); + rt1 = type_to_static_parameter_value(S, T, tvs, ntv); + rt2 = type_to_static_parameter_value(SS, TT, tvs, ntv); jl_value_t *m = meet(rt1, rt2, covariant); if (m == NULL) goto ret_no; S = m; @@ -1359,7 +1366,7 @@ static int solve_tvar_constraints(cenv_t *env, cenv_t *soln) } } else { - extend(T, type_to_static_parameter_value(S), soln); + extend(T, type_to_static_parameter_value(S, T, tvs, ntv), soln); } } else { @@ -1389,8 +1396,8 @@ static int solve_tvar_constraints(cenv_t *env, cenv_t *soln) jl_value_t *TT = env->data[j]; jl_value_t *SS = env->data[j+1]; if (TT == T) { - rt1 = type_to_static_parameter_value(S); - rt2 = type_to_static_parameter_value(SS); + rt1 = type_to_static_parameter_value(S, T, tvs, ntv); + rt2 = type_to_static_parameter_value(SS, TT, tvs, ntv); jl_value_t *m = meet(rt1, rt2, covariant); if (m == NULL) goto ret_no; S = m; @@ -1406,7 +1413,7 @@ static int solve_tvar_constraints(cenv_t *env, cenv_t *soln) S = (jl_value_t*)jl_new_typevar(underscore_sym, (jl_value_t*)jl_bottom_type, S); } - extend(T, type_to_static_parameter_value(S), soln); + extend(T, type_to_static_parameter_value(S, T, tvs, ntv), soln); } } } @@ -1473,14 +1480,6 @@ jl_value_t *jl_type_intersection_matching(jl_value_t *a, jl_value_t *b, } } - if (!solve_tvar_constraints(&env, &eqc)) { - JL_GC_POP(); - return (jl_value_t*)jl_bottom_type; - } - //jl_printf(JL_STDOUT, "env: "); print_env(&env); - //jl_printf(JL_STDOUT, "sol: "); print_env(&eqc); - - int env0 = eqc.n; jl_value_t **tvs; int tvarslen; if (jl_is_typevar(tvars)) { @@ -1492,6 +1491,15 @@ jl_value_t *jl_type_intersection_matching(jl_value_t *a, jl_value_t *b, tvs = jl_svec_data(tvars); tvarslen = jl_svec_len(tvars); } + + if (!solve_tvar_constraints(&env, &eqc, tvs, tvarslen)) { + JL_GC_POP(); + return (jl_value_t*)jl_bottom_type; + } + //jl_printf(JL_STDOUT, "env: "); print_env(&env); + //jl_printf(JL_STDOUT, "sol: "); print_env(&eqc); + + int env0 = eqc.n; for(int tk=0; tk < tvarslen; tk++) { jl_tvar_t *tv = (jl_tvar_t*)tvs[tk]; for(e=0; e < env0; e+=2) { diff --git a/test/arrayops.jl b/test/arrayops.jl index d278eaa7bef63..c43525f2f092c 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1443,3 +1443,6 @@ let A = zeros(Int, 2, 2), B = zeros(Float64, 2, 2) @test isleaftype(Base.return_types(f, ())[1]) end end + +# issue #14482 +@inferred Base.map_to!(Int8, 1, Int8[0], Int[0]) diff --git a/test/core.jl b/test/core.jl index 31b232c4c87b1..8fe36c9eefe57 100644 --- a/test/core.jl +++ b/test/core.jl @@ -3468,8 +3468,7 @@ end # issue #11327 and #13547 @test_throws MethodError convert(Type{Int}, Float32) -# TODO: this should probably be a MethodError in `convert`; not sure what's going on -@test_throws TypeError Array{Type{Int64}}([Float32]) +@test_throws MethodError Array{Type{Int64}}([Float32]) abstract A11327 abstract B11327 <: A11327 f11327{T}(::Type{T},x::T) = x @@ -3606,3 +3605,9 @@ let z1 = Z14477() @test isa(z1, Z14477) @test isa(z1.fld, Z14477) end + +# issue #14482 +let T = TypeVar(:T, true) + @test typeintersect(T, Type{Int8}) == Type{Int8} + @test typeintersect(Tuple{T}, Tuple{Type{Int8}}) == Tuple{Type{Int8}} +end