Skip to content

Commit 02674e3

Browse files
committed
add some "no invalidations" tests
Test that adding certain type-method pairs doesn't cause any invalidation. Currently the new type subtypes `Integer` in all cases. Some of the tests are marked as broken. Merging this will make the contribution process more demanding: when someone makes a PR they might need to fix unrelated type stability issues, or decrease `max_methods` for some function before being able to merge their initial PR. However that's better than ignoring the constant danger of type instability/invalidation regressions making the sysimage and precompilation less useful.
1 parent 148493d commit 02674e3

File tree

2 files changed

+87
-1
lines changed

2 files changed

+87
-1
lines changed

test/choosetests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const TESTNAMES = [
1616
"operators", "ordering", "path", "ccall", "parse", "loading", "gmp",
1717
"sorting", "spawn", "backtrace", "exceptions",
1818
"file", "read", "version", "namedtuple",
19-
"mpfr", "broadcast", "complex",
19+
"mpfr", "broadcast", "complex", "no_invalidations",
2020
"floatapprox", "stdlib", "reflection", "regex", "float16",
2121
"combinatorics", "sysinfo", "env", "rounding", "ranges", "mod2pi",
2222
"euler", "show", "client", "terminfo",

test/no_invalidations.jl

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# This file is a part of Julia. License is MIT: https://julialang.org/license
2+
3+
using Test
4+
5+
module ThereAreNoInvalidations
6+
function julia_expr_cmd(expr::Expr)
7+
`$(Base.julia_cmd()) -e $expr`
8+
end
9+
function readline_julia_expr_cmd(expr::Expr)
10+
open(readline, julia_expr_cmd(expr))
11+
end
12+
function invalidations_expr(expr::Expr)
13+
quote
14+
try
15+
let invs = ccall(:jl_debug_method_invalidation, Any, (Cint,), 1)
16+
@eval $expr
17+
invs
18+
end
19+
finally
20+
ccall(:jl_debug_method_invalidation, Any, (Cint,), 0)
21+
end
22+
end
23+
end
24+
function there_are_no_invalidations_expr(expr::Expr)
25+
e = invalidations_expr(expr)
26+
quote
27+
let invalidations = $e
28+
show(isempty(invalidations))
29+
end
30+
end
31+
end
32+
function there_are_no_invalidations(expr::Expr)
33+
e = there_are_no_invalidations_expr(expr)
34+
s = readline_julia_expr_cmd(e)
35+
parse(Bool, s)
36+
end
37+
end
38+
39+
function type_expr(f, supertype::Type)
40+
type_name = :T
41+
rest = f(type_name)
42+
quote
43+
struct $type_name <: $supertype end
44+
$rest
45+
end
46+
end
47+
48+
function test_expr(f, supertype::Type = Integer)
49+
e = type_expr(f, supertype)
50+
ThereAreNoInvalidations.there_are_no_invalidations(e)
51+
end
52+
53+
@testset "no invalidations test set" begin
54+
int_types = (Bool, Int8, UInt8, Int16, UInt16, Int, UInt, BigInt)
55+
@testset "construction of old int types from new type" begin
56+
broken = (Int8, UInt8, UInt16, Int, UInt)
57+
@testset "T: $T" for T int_types
58+
@test test_expr(n -> :(Base.$T(::$n) = $T(0))) broken=(T broken)
59+
end
60+
end
61+
@testset "arithmetic between old int types and new int type" begin
62+
ops = (:+, :*)
63+
broken = ()
64+
@testset "T: $T" for T int_types
65+
@testset "op: $op" for op ops
66+
@test (
67+
test_expr(n -> :(Base.$op(::$n, m::$T) = m)) &&
68+
test_expr(n -> :(Base.$op(m::$T, ::$n) = m))
69+
) broken=((T, op) broken)
70+
end
71+
end
72+
end
73+
@testset "promotion between old int types and new int type" begin
74+
broken = (Bool, UInt8, Int)
75+
@testset "T: $T" for T int_types
76+
@test (
77+
test_expr(n -> :(Base.promote_rule(::Type{$T}, ::Type{$n}) = $T)) &&
78+
test_expr(n -> :(Base.promote_rule(::Type{$n}, ::Type{$T}) = $T))
79+
) broken=(T broken)
80+
end
81+
end
82+
@testset "unary functions" begin
83+
@test test_expr(n -> :(Base.zero(::$n) = $n())) broken=true
84+
@test test_expr(n -> :(Base.one(::$n) = $n())) broken=true
85+
end
86+
end

0 commit comments

Comments
 (0)