Skip to content

Commit 94c3a15

Browse files
authored
Improve nothrow analysis of :new with missing sparam (#46754)
Similar to #46693, but for :new, rather than getfield. Unfortunately, this is somewhat limited as we don't really have the ability to encode type equality constraints in the lattice. In particular, it would be nice to analyze: ``` struct Foo{T} x::T Foo(x::T) where {T} = new{T}(x) end ``` and be able to prove this nothrow. If it's really important, we could probably pattern match it, but for the moment, this is not easy to do. Nevertheless, we can do something about the similar, but simpler pattern ``` struct Foo{T} x Foo(x::T) where {T} = new{T}(x) end ``` which is what this PR does.
1 parent e758982 commit 94c3a15

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

base/compiler/optimize.jl

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,16 +254,31 @@ function stmt_effect_flags(lattice::AbstractLattice, @nospecialize(stmt), @nospe
254254
nothrow = is_nothrow(effects)
255255
return (consistent, effect_free & nothrow, nothrow)
256256
elseif head === :new
257-
typ = argextype(args[1], src)
257+
atyp = argextype(args[1], src)
258258
# `Expr(:new)` of unknown type could raise arbitrary TypeError.
259-
typ, isexact = instanceof_tfunc(typ)
260-
isexact || return (false, false, false)
261-
isconcretedispatch(typ) || return (false, false, false)
259+
typ, isexact = instanceof_tfunc(atyp)
260+
if !isexact
261+
atyp = unwrap_unionall(widenconst(atyp))
262+
if isType(atyp) && isTypeDataType(atyp.parameters[1])
263+
typ = atyp.parameters[1]
264+
else
265+
return (false, false, false)
266+
end
267+
isabstracttype(typ) && return (false, false, false)
268+
else
269+
isconcretedispatch(typ) || return (false, false, false)
270+
end
262271
typ = typ::DataType
263272
fieldcount(typ) >= length(args) - 1 || return (false, false, false)
264273
for fld_idx in 1:(length(args) - 1)
265274
eT = argextype(args[fld_idx + 1], src)
266275
fT = fieldtype(typ, fld_idx)
276+
# Currently, we cannot represent any type equality constraints
277+
# in the lattice, so if we see any type of type parameter,
278+
# there is very little we can say about it
279+
if !isexact && has_free_typevars(fT)
280+
return (false, false, false)
281+
end
267282
eT ₒ fT || return (false, false, false)
268283
end
269284
return (false, true, true)

test/compiler/effects.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,3 +655,13 @@ end # @testset "effects analysis on array ops" begin
655655

656656
# Test that builtin_effects handles vararg correctly
657657
@test !Core.Compiler.is_nothrow(Core.Compiler.builtin_effects(Core.Compiler.fallback_lattice, Core.isdefined, Any[String, Vararg{Any}], Bool))
658+
659+
# Test that :new can be eliminated even if an sparam is unknown
660+
struct SparamUnused{T}
661+
x
662+
SparamUnused(x::T) where {T} = new{T}(x)
663+
end
664+
mksparamunused(x) = (SparamUnused(x); nothing)
665+
let src = code_typed1(mksparamunused, (Any,))
666+
@test count(isnew, src.code) == 0
667+
end

0 commit comments

Comments
 (0)