# A playful competition: who can define a method that invalidates the most code?

**URL:** <https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543>\
**Category:** Tooling\
**Tags:** competition\
**Created:** [September 30, 2020, 3:21pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543 "2020-09-30T15:21:54Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [September 30, 2020, 6:13pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/22 "2020-09-30T18:13:39Z")

</div>

But it’s easily defeated; after you’ve triggered the invalidations and collected the data, just set it back again. And the fact that `invalidations` is empty is a dead giveaway.

But of course, this deserves gobs of “devilishness” points! I’m impressed by all the impishness here.

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [September 30, 2020, 6:48pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/23 "2020-09-30T18:48:13Z")

</div>

Idea was to prevent another form of fiendish cheating: anyone building from source might just greatly expand the list of things we precompile in `contrib/generate_precompiles.jl` and then get a much bigger, juicier set of targets that haven’t been spruced up as much as the stuff we’ve been shipping precompiled.

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [September 30, 2020, 7:15pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/24 "2020-09-30T19:15:30Z")

</div>

Is this the Julia version of a spooky Halloween?

---

<div class="post-metadata">

**Author:** ![simonbyrne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simonbyrne/32/19_2.png) [@simonbyrne](https://discourse.julialang.org/u/simonbyrne)\
**Post date:** [October 1, 2020, 10:33pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/25 "2020-10-01T22:33:54Z")

</div>

This is an issue in real code:  
[https://github.com/invenia/Intervals.jl/issues/144](https://github.com/invenia/Intervals.jl/issues/144)

---

<div class="post-metadata">

**Author:** ![simonbyrne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simonbyrne/32/19_2.png) [@simonbyrne](https://discourse.julialang.org/u/simonbyrne)\
**Post date:** [October 1, 2020, 10:49pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/26 "2020-10-01T22:49:24Z")

</div>

A late contribution:

```julia
julia> using SnoopCompileCore

julia> inv = @snoopr Base.getproperty(x, s::Symbol) = getfield(x, s);

julia> using SnoopCompile

julia> length(uinvalidated(inv))
17016

```

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [October 2, 2020, 11:00am UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/27 "2020-10-02T11:00:58Z")

</div>

Turns out the `BitInteger` union is not needed. I was starting to feel that using Union Types might even have to become its own category, as I was building larger and larger ones to get more invalidations with a single method. But this is just as effective with convert:

```julia-repl
julia> using SnoopCompileCore

julia> invalidations = @snoopr Base.convert(::Type{T}, x::Number) where T<:Real = T(x);

julia> using SnoopCompile

julia> length(uinvalidated(invalidations))
18362

```

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [October 2, 2020, 1:51pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/28 "2020-10-02T13:51:39Z")

</div>

Some i had high hopes for but that didn’t work out:

Redefining `Expr`:

```julia
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 1.6.0-DEV.1073 (2020-09-29)
 _/ |\ __'_|_|_|\__'_| | Commit 4f0145b7b0* (3 days old master)
|__/ |

julia> using SnoopCompile

julia> inv = @snoopr Base.Expr(args...) = Core._expr(args...);

julia> length(uinvalidated(inv))
868

```

Redefining `@nospecialize` to actually specialize.  
I thought this should invalidate a bunch of things that otherwise wouldn’t be invalidatable, but seems not to have.  
MIght have missed something

```julia
julia> inv = @snoopr Base.@eval macro nospecialize(x)
           x
       end
Any[]

julia> length(uinvalidated(inv))
0

```

Same idea for `@noinline`

```julia
julia> inv = @snoopr Base.@eval macro noinline(x)
           :(@inline x)
       end
Any[]

julia> length(uinvalidated(inv))
0

```

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [October 2, 2020, 1:54pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/29 "2020-10-02T13:54:29Z")

</div>

Does changing macros effect code that’s already defined?

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [October 2, 2020, 1:59pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/30 "2020-10-02T13:59:27Z")

</div>

No, changing a macro shouldn’t change anything for already applied macro, only future use. There might be exceptions, i.e. code that uses eval.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [October 2, 2020, 2:09pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/31 "2020-10-02T14:09:39Z")

</div>

> [@oxinabox](#):
>
> I thought this should invalidate a bunch of things that otherwise wouldn’t be invalidatable, but seems not to have.

Redefining a macro doesn’t have any effect on already-evaluated uses of the macro—the current meaning of the macro is used at parse time and after that there’s no connection. I’m pretty sure that’s how all macro systems work. Otherwise it would be like trying to go back and fix the results of past calls to functions when you redefine them.

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [October 2, 2020, 2:24pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/32 "2020-10-02T14:24:08Z")

</div>

Today, I learned.  
Thinking about it, yes, that makes sense.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [October 2, 2020, 5:24pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/33 "2020-10-02T17:24:37Z")

</div>

If these macros called some auxiliary inner function (inside the methods they modify) that could be invalidated, then this could work. But I do not know if it is the case (would guess no).

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [October 2, 2020, 5:26pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/34 "2020-10-02T17:26:16Z")

</div>

No because that still only affects future macro expansions: code that’s already been order and macro-expanded will not be released and expanded.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [October 2, 2020, 6:14pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/35 "2020-10-02T18:14:17Z")

</div>

Just to clarify, I meant something like: `@my_macro args` expands to `my_aux_f(args...)` inside the method body of a function `outer`, so changing function `my_aux_f` (not macro `my_macro`) could invalidate the method `outer`. Having a programmer write the call to `my_aux_f` and a macro to do the same has indistinguishable results no?

For a concrete example, if I somehow change `print`, and `@show` is expanded to `print`, then every method calling `@show` may be invalidated, no?

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [October 5, 2020, 12:18pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/36 "2020-10-05T12:18:07Z")

</div>

Yikes, realized I forgot to announce the results on Friday. To evaluate the submissions, I tested each using a script that I executed from the linux prompt to ensure there weren’t differences in my typing at the REPL (since hitting certain keys can force the compilation of new methods). In a couple of cases, this led to a pretty different count than provided by the submitter, perhaps mostly because some REPL methods did not compile. (At least the rank order was consistent with the numbers provided by the applicants.)

Without further ado, here are the results of my analysis and the winners…

For the category of “pirating methods,” we had several submissions including a nail-biter for the win:

- **third place** variants of overloading +:
  - the original submission was `Base.:+(x::Int, y::Int) = Base.inferencebarrier(Base.add_int(x, y))` (the `inferencebarrier` isn’t required ) by @simeonschaub at 15782
  - an improved/more evil version `Base.:+(x::T, y::T) where {T<:Base.BitInteger} = Base.add_int(x, y)` by @StefanKarpinski at 15933

- **second place** : `Base.getproperty(x, s::Symbol) = getfield(x, s)` by @simonbyrne at 17035
- **first place** `Base.convert(::Type{T}, x::Number) where T<:Real = T(x)` by @tomerarnon at 17093

In the non-pirating category, we had:

- **second place** `struct DoNotCare<:Real end; Base.:(==)(x::DoNotCare, ::Any) = true` by @oxinabox at 58
- `convert` methods:
  - `struct X end; Base.convert(::Any, ::X) = nothing` by @oxinabox at 1666 was disqualified (sorry) because to be a valid `convert` method it should have been `Base.convert(::Type{Any}, ::X)` (which has 1152 and would have won), so the winner is…
  - **first place** `struct X end; Base.convert(::Union{}, ::X) = nothing` by @mbauman at 903

In case you’re curious, in the non-pirating category I believe that it’s not currently possible to do better than the following rather arcane submission:

```julia
struct X end
Base._str_sizehint(::X) = nothing

```

at 2622 invalidations. You can discover this and similar opportunities by installing MethodAnalysis and then running `demos/abstract.jl` and typing `mipriv` on the command line. (`mipriv` means “`MethodInstances` of private, a.k.a. non-exported, names”; the analog for exported names is `miexp`).

Congrats to the winners, and let the second phase commence! Announcement will likely be made on Saturday as I am reserving Friday afternoon for a family bike trip.

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [October 5, 2020, 5:31pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/37 "2020-10-05T17:31:14Z")

</div>

> [@tim.holy](#):
>
> `struct X end; Base.convert(::Any, ::X) = nothing` by @oxinabox at 1666 was disqualified (sorry) because to be a valid `convert` method it should have been

I’ld like to appeal. 👨‍⚖️😂  
`convert(::Any, ::X)` isn’t against the rules.  
It’s not piracy since `X` is my own type, and i see no special rule for `convert` .  
It’s not sensible julia code, but that wasn’t a requirement. 😹  
I think the only vaguely sensible things submitted were my `DoNotCare` one and the `MyCustomString` one at the start.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [October 5, 2020, 6:32pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/38 "2020-10-05T18:32:47Z")

</div>

I agree, although I am kicking myself for not realizing that `Union{}` is just a wonky subcategory. I do like it though since it’s a non-callable method 🙂

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [October 5, 2020, 7:17pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/39 "2020-10-05T19:17:32Z")

</div>

…it looks like the referees and the linejudges are conferring… they seem to be going to the video…

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [October 5, 2020, 7:20pm UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/40 "2020-10-05T19:20:19Z")

</div>

…and the appeal is upheld! We have a new winner, @oxinabox 🎆

I realized the same remark could apply to the second: that the way `convert` is intended, it should probably be `convert(::Type{Union{}}, ::X)`. So either way, @oxinabox wins.

---

<div class="post-metadata">

**Author:** ![TsurHerman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tsurherman/32/1234_2.png) [@TsurHerman](https://discourse.julialang.org/u/TsurHerman)\
**Post date:** [October 6, 2020, 10:21am UTC](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543/41 "2020-10-06T10:21:29Z")

</div>

I wonder if this is for amusement only or … what’s the plan?

[Previous page](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543.md?page=1)

[Next page](https://discourse.julialang.org/t/a-playful-competition-who-can-define-a-method-that-invalidates-the-most-code/47543.md?page=3)
