diff --git a/base/compiler/typelimits.jl b/base/compiler/typelimits.jl index dc68f026e6b8f..406a5494d2f20 100644 --- a/base/compiler/typelimits.jl +++ b/base/compiler/typelimits.jl @@ -128,7 +128,6 @@ function _limit_type_size(@nospecialize(t), @nospecialize(c), sources::SimpleVec return Type{<:Type} end # try to peek into c to get a comparison object, but if we can't perhaps t is already simple enough on its own - # (this is slightly more permissive than type_more_complex implements for the same case). if isType(c) ct = c.parameters[1] else @@ -178,7 +177,7 @@ function _limit_type_size(@nospecialize(t), @nospecialize(c), sources::SimpleVec return Any end widert = t.name.wrapper - if !(t <: widert) + if !(t <: widert) # XXX: we should call has_free_typevars(t) here, but usually t does not have those wrappers by the time it got here # This can happen when a typevar has bounds too wide for its context, e.g. # `Complex{T} where T` is not a subtype of `Complex`. In that case widen even # faster to something safe to ensure the result is a supertype of the input. @@ -229,20 +228,22 @@ function type_more_complex(@nospecialize(t), @nospecialize(c), sources::SimpleVe return false # Bottom is as simple as they come elseif isa(t, DataType) && isempty(t.parameters) return false # fastpath: unparameterized types are always finite - elseif tupledepth > 0 && is_derived_type_from_any(unwrap_unionall(t), sources, depth) + elseif is_derived_type_from_any(unwrap_unionall(t), sources, depth) return false # t isn't something new end # peel off wrappers isvarargtype(t) && (t = unwrapva(t)) isvarargtype(c) && (c = unwrapva(c)) if isa(c, UnionAll) - # allow wrapping type with fewer UnionAlls than comparison if in a covariant context + # allow wrapping type with fewer UnionAlls than comparison only if in a covariant context if !isa(t, UnionAll) && tupledepth == 0 return true end - t = unwrap_unionall(t) c = unwrap_unionall(c) end + if isa(t, UnionAll) + t = unwrap_unionall(t) + end # rules for various comparison types if isa(c, TypeVar) tupledepth = 1 @@ -265,7 +266,24 @@ function type_more_complex(@nospecialize(t), @nospecialize(c), sources::SimpleVe # base case for data types if isa(t, DataType) tP = t.parameters - if isa(c, DataType) && t.name === c.name + if isType(t) + # Type is fairly important, so do not widen it as fast as other types if avoidable + tt = tP[1] + ttu = unwrap_unionall(tt) # TODO: use argument_datatype(tt) after #50692 fixed + if isType(c) + ct = c.parameters[1] + else + ct = Union{} + tupledepth == 0 && return true # cannot allow nesting + end + # allow creating variation within a nested Type, but not very deep + if tupledepth > 1 + tupledepth = 1 + else + tupledepth = 0 + end + return type_more_complex(tt, ct, sources, depth + 1, tupledepth, 0) + elseif isa(c, DataType) && t.name === c.name cP = c.parameters length(cP) < length(tP) && return true isempty(tP) && return false diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index ca3e20b552470..aaf587000be67 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -60,7 +60,8 @@ end # issue #42835 @test !Core.Compiler.type_more_complex(Int, Any, Core.svec(), 1, 1, 1) @test !Core.Compiler.type_more_complex(Int, Type{Int}, Core.svec(), 1, 1, 1) -@test Core.Compiler.type_more_complex(Type{Int}, Any, Core.svec(), 1, 1, 1) # maybe should be fixed? +@test !Core.Compiler.type_more_complex(Type{Int}, Any, Core.svec(), 1, 1, 1) +@test Core.Compiler.type_more_complex(Type{Type{Int}}, Any, Core.svec(), 1, 1, 1) @test Core.Compiler.limit_type_size(Type{Int}, Any, Union{}, 0, 0) == Type{Int} @test Core.Compiler.type_more_complex(Type{Type{Int}}, Type{Int}, Core.svec(Type{Int}), 1, 1, 1) @test Core.Compiler.type_more_complex(Type{Type{Int}}, Int, Core.svec(Type{Int}), 1, 1, 1) @@ -80,15 +81,16 @@ end @test Core.Compiler.type_more_complex(Type{Type{Type{ComplexF32}}}, Type{Type{ComplexF32}}, Core.svec(Type{ComplexF32}), 1, 1, 1) # n.b. Type{Type{Union{}} === Type{Core.TypeofBottom} -@test Core.Compiler.type_more_complex(Type{Union{}}, Any, Core.svec(), 1, 1, 1) -@test Core.Compiler.type_more_complex(Type{Type{Union{}}}, Any, Core.svec(), 1, 1, 1) +@test !Core.Compiler.type_more_complex(Type{Union{}}, Any, Core.svec(), 1, 1, 1) +@test !Core.Compiler.type_more_complex(Type{Type{Union{}}}, Any, Core.svec(), 1, 1, 1) @test Core.Compiler.type_more_complex(Type{Type{Type{Union{}}}}, Any, Core.svec(), 1, 1, 1) @test Core.Compiler.type_more_complex(Type{Type{Type{Union{}}}}, Type{Type{Union{}}}, Core.svec(Type{Type{Union{}}}), 1, 1, 1) @test Core.Compiler.type_more_complex(Type{Type{Type{Type{Union{}}}}}, Type{Type{Type{Union{}}}}, Core.svec(Type{Type{Type{Union{}}}}), 1, 1, 1) @test !Core.Compiler.type_more_complex(Type{1}, Type{2}, Core.svec(), 1, 1, 1) @test Core.Compiler.type_more_complex(Type{Union{Float32,Float64}}, Union{Float32,Float64}, Core.svec(Union{Float32,Float64}), 1, 1, 1) -@test Core.Compiler.type_more_complex(Type{Union{Float32,Float64}}, Union{Float32,Float64}, Core.svec(Union{Float32,Float64}), 0, 1, 1) +@test Core.Compiler.type_more_complex(Type{Type{Union{Float32,Float64}}}, Union{Float32,Float64}, Core.svec(Union{Float32,Float64}), 1, 1, 1) +@test Core.Compiler.type_more_complex(Type{Type{Union{Float32,Float64}}}, Type{Union{Float32,Float64}}, Core.svec(Type{Union{Float32,Float64}}), 1, 1, 1) @test Core.Compiler.type_more_complex(Type{<:Union{Float32,Float64}}, Type{Union{Float32,Float64}}, Core.svec(Union{Float32,Float64}), 1, 1, 1) @test Core.Compiler.type_more_complex(Type{<:Union{Float32,Float64}}, Any, Core.svec(Union{Float32,Float64}), 1, 1, 1) @@ -97,8 +99,8 @@ end @test Core.Compiler.type_more_complex(Tuple{Vararg{Tuple}}, Tuple{Vararg{Tuple{}}}, Core.svec(), 0, 0, 0) let # 40336 - t = Type{Type{Int}} - c = Type{Int} + t = Type{Type{Type{Int}}} + c = Type{Type{Int}} r = Core.Compiler.limit_type_size(t, c, c, 100, 100) @test t !== r && t <: r end