@@ -199,3 +199,115 @@ end
199199notify (c26506_1)
200200wait (c26506_2)
201201@test result26506[1 ] == 3
202+
203+
204+ # # Invalidation tests
205+
206+ function instance (f, types)
207+ m = which (f, types)
208+ inst = nothing
209+ tt = Tuple{typeof (f), types... }
210+ specs = m. specializations
211+ if isa (specs, Nothing)
212+ elseif isa (specs, Core. SimpleVector)
213+ for i = 1 : length (specs)
214+ if isassigned (specs, i)
215+ mi = specs[i]:: Core.MethodInstance
216+ if mi. specTypes === tt
217+ inst = mi
218+ break
219+ end
220+ end
221+ end
222+ else
223+ Base. visit (specs) do mi
224+ if mi. specTypes === tt
225+ inst = mi
226+ end
227+ end
228+ end
229+ return inst
230+ end
231+
232+ function worlds (mi:: Core.MethodInstance )
233+ w = Tuple{UInt,UInt}[]
234+ if isdefined (mi, :cache )
235+ ci = mi. cache
236+ push! (w, (ci. min_world, ci. max_world))
237+ while isdefined (ci, :next )
238+ ci = ci. next
239+ push! (w, (ci. min_world, ci. max_world))
240+ end
241+ end
242+ return w
243+ end
244+
245+ # avoid adding this to Base
246+ function equal (ci1:: Core.CodeInfo , ci2:: Core.CodeInfo )
247+ return ci1. code == ci2. code &&
248+ ci1. codelocs == ci2. codelocs &&
249+ ci1. ssavaluetypes == ci2. ssavaluetypes &&
250+ ci1. ssaflags == ci2. ssaflags &&
251+ ci1. method_for_inference_limit_heuristics == ci2. method_for_inference_limit_heuristics &&
252+ ci1. linetable == ci2. linetable &&
253+ ci1. slotnames == ci2. slotnames &&
254+ ci1. slotflags == ci2. slotflags &&
255+ ci1. slottypes == ci2. slottypes &&
256+ ci1. rettype == ci2. rettype
257+ end
258+ equal (p1:: Pair , p2:: Pair ) = p1. second == p2. second && equal (p1. first, p2. first)
259+
260+ # # Union-splitting based on state-of-the-world: check that each invalidation corresponds to new code
261+ applyf35855 (c) = f35855 (c[1 ])
262+ f35855 (:: Int ) = 1
263+ f35855 (:: Float64 ) = 2
264+ applyf35855 ([1 ])
265+ applyf35855 ([1.0 ])
266+ applyf35855 (Any[1 ])
267+ wint = worlds (instance (applyf35855, (Vector{Int},)))
268+ wfloat = worlds (instance (applyf35855, (Vector{Float64},)))
269+ wany2 = worlds (instance (applyf35855, (Vector{Any},)))
270+ src2 = code_typed (applyf35855, (Vector{Any},))[1 ]
271+ f35855 (:: String ) = 3
272+ applyf35855 (Any[1 ])
273+ @test worlds (instance (applyf35855, (Vector{Int},))) == wint
274+ @test worlds (instance (applyf35855, (Vector{Float64},))) == wfloat
275+ wany3 = worlds (instance (applyf35855, (Vector{Any},)))
276+ src3 = code_typed (applyf35855, (Vector{Any},))[1 ]
277+ @test (wany3 == wany2) == equal (src3, src2) # don't invalidate unless you also change the code
278+ f35855 (:: AbstractVector ) = 4 # next test would pass if this were ::Vector{Int}
279+ applyf35855 (Any[1 ])
280+ wany4 = worlds (instance (applyf35855, (Vector{Any},)))
281+ src4 = code_typed (applyf35855, (Vector{Any},))[1 ]
282+ @test_broken (wany4 == wany3) == equal (src4, src3)
283+ f35855 (:: Dict ) = 5
284+ applyf35855 (Any[1 ])
285+ wany5 = worlds (instance (applyf35855, (Vector{Any},)))
286+ src5 = code_typed (applyf35855, (Vector{Any},))[1 ]
287+ @test (wany5 == wany4) == equal (src5, src4)
288+ f35855 (:: Set ) = 6 # with current settings, this shouldn't invalidate
289+ applyf35855 (Any[1 ])
290+ wany6 = worlds (instance (applyf35855, (Vector{Any},)))
291+ src6 = code_typed (applyf35855, (Vector{Any},))[1 ]
292+ @test (wany6 == wany5) == equal (src6, src5)
293+
294+ # # ambiguities do not trigger invalidation
295+ using Printf
296+ Printf. gen (" %f" )
297+ mi = instance (+ , (AbstractChar, UInt8))
298+ w = worlds (mi)
299+
300+ abstract type FixedPoint35855{T <: Integer } <: Real end
301+ struct Normed35855 <: FixedPoint35855{UInt8}
302+ i:: UInt8
303+ Normed35855 (i:: Integer , _) = new (i % UInt8)
304+ end
305+ (:: Type{X} )(x:: Real ) where X<: FixedPoint35855{T} where T = X (round (T, typemax (T)* x), 0 )
306+
307+ @test_broken worlds (mi) == w
308+
309+ mi = instance (convert, (Type{Nothing}, String))
310+ w = worlds (mi)
311+ abstract type Colorant35855 end
312+ Base. convert (:: Type{C} , c) where C<: Colorant35855 = false
313+ @test_broken worlds (mi) == w
0 commit comments