# Minimal working example that demonstrates the danger of type piracy

**URL:** <https://discourse.julialang.org/t/minimal-working-example-that-demonstrates-the-danger-of-type-piracy/66922>\
**Category:** General Usage\
**Tags:** question, type-piracy\
**Created:** [August 24, 2021, 4:10pm UTC](https://discourse.julialang.org/t/minimal-working-example-that-demonstrates-the-danger-of-type-piracy/66922 "2021-08-24T16:10:19Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [August 24, 2021, 4:10pm UTC](https://discourse.julialang.org/t/minimal-working-example-that-demonstrates-the-danger-of-type-piracy/66922/1 "2021-08-24T16:10:20Z")

</div>

I understand what type piracy is, but I’m still hazy on exactly what sort of problems it can cause. Can someone provide a minimal working example that demonstrates the unexpected behavior that can result from type piracy?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 24, 2021, 4:13pm UTC](https://discourse.julialang.org/t/minimal-working-example-that-demonstrates-the-danger-of-type-piracy/66922/2 "2021-08-24T16:13:45Z")

</div>

How extreme do you want to go? The most extreme example I know of is `Base.:(+)(::Int, ::Int) = "oops"` 🙂 Though “working example” is a bit stretched here…

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [August 24, 2021, 4:40pm UTC](https://discourse.julialang.org/t/minimal-working-example-that-demonstrates-the-danger-of-type-piracy/66922/3 "2021-08-24T16:40:24Z")

</div>

Ha, well preferably something that doesn’t crash my Julia session.

Here’s the type of example that I’m looking for:

```julia
Base.size(::Pair{T, T}) where T = (2,)

```

Except I can’t think of anything bad that would result from that example of type piracy… 🤷‍♂️

A good MWE would probably involve 2 or 3 modules with new functions and types like `foo`, `bar`, `A`, and `B`, rather than showing type piracy with Base functions and types. I imagine that such a MWE would demonstrate unexpected behavior resulting from type piracy, i.e. not a runtime error but wrong results.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [August 24, 2021, 5:07pm UTC](https://discourse.julialang.org/t/minimal-working-example-that-demonstrates-the-danger-of-type-piracy/66922/4 "2021-08-24T17:07:16Z")

</div>

Imagine doing this for `DataFrame` or something in a package you wrote, now `DataFrames.jl` may not use it, but a third package that uses `size()` blindly (doesn’t care about DataFrame for example), or a user’s function, now instead of a error they may be getting weird result, silently.

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [August 24, 2021, 5:25pm UTC](https://discourse.julialang.org/t/minimal-working-example-that-demonstrates-the-danger-of-type-piracy/66922/5 "2021-08-24T17:25:13Z")

</div>

`size` already works on a `DataFrame`, so I don’t see a reason why a user or package would want to define their own `size(df::Dataframe)` method. Below is a short example that demonstrates the kind of type piracy that might actually be useful. However, the example doesn’t show any ill-effects of the type piracy. Perhaps the example can be elaborated a bit to demonstrate an ill-effect or wrong result that occurs due to the type piracy.

```julia
module Package1
    struct A end
    foo(::A) = 42
    export foo, A
end

module Package2
    struct B end
    export B
end

module Package3
    using ..Package1, ..Package2
    Package1.foo(::B) = 1
    export foo
end

```

```julia
julia> using .Package1, .Package2, .Package3

julia> foo(A())
42

julia> foo(B())
1

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 24, 2021, 5:28pm UTC](https://discourse.julialang.org/t/minimal-working-example-that-demonstrates-the-danger-of-type-piracy/66922/6 "2021-08-24T17:28:55Z")

</div>

The classic argument is that the type piracy can unexpectedly change how a package works by loading a seemingly unrelated package. I can’t imagine someone intentionally doing this though, unless upstream is unwilling to take a patch or something similar though.

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [August 24, 2021, 5:30pm UTC](https://discourse.julialang.org/t/minimal-working-example-that-demonstrates-the-danger-of-type-piracy/66922/7 "2021-08-24T17:30:02Z")

</div>

I know this is the classic argument, but I’m looking for an MWE here. 😅

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [August 24, 2021, 5:47pm UTC](https://discourse.julialang.org/t/minimal-working-example-that-demonstrates-the-danger-of-type-piracy/66922/8 "2021-08-24T17:47:14Z")

</div>

> [@CameronBieganek](#):
>
> `size` already works on a `DataFrame`

You could replace size with something that doesn’t work but “makes sense to an individual” so they decided to define it in their package, later causes issues.

idk what MWE you want because it’s hard to “just come up with real-life example” while keeping it simple/not contrived.

> [@\`using\` a package that uses \`OrderedCollections\` can silently add function methods?](https://discourse.julialang.org/t/using-a-package-that-uses-orderedcollections-can-silently-add-function-methods/60741):
>
> (This might not be specific to Revise, but I have not looked for other examples yet. Will change the title if this topic applies more generally.) sort usually does not work with dictionaries, but it starts to work after using Revise, even though [Revise does not export sort](https://github.com/timholy/Revise.jl/search?q=export). test\_dict = Dict(1=\>2, 2=\>1) sort(test\_dict) # this errors using Revise sort(test\_dict) # this does not error and prints the following OrderedCollections.OrderedDict{Int64, Int64} with 2 entries: 1 =\> 2 2 =\> 1 @which …

> [@Bizarre Possible "Piracy Bug" Stalls Julia](https://discourse.julialang.org/t/bizarre-possible-piracy-bug-stalls-julia/4103):
>
> I have been tracking down this bizarre bug all night. I think it could be a Julia bug, but I am not certain. The funny thing is I know the solution: use the latest master for StaticArrays (which will be tagged soon). However, that doesn’t seem to be a good answer because now it seems that “the old” StaticArrays.jl release is causing Julia to stall in a part of the code which does not deal with StaticArrays at all. This “action at a distance” is reminiscent of the Optim/Roots causing type-instabi…

> <https://github.com/JuliaLang/julia/issues/39988>
>
> I am working on package \[BitStructs\](https://github.com/rryi/BitStructs.jl) and …encounter a strange error running my benchmarks with julia 1.6.0-RC1.
> 
> \### Environment:
> 
> System Ryzen 1700, 16 GB RAM, Windows 10 Pro, version 20H2
> Julia 64 bit 1.6.0-rc1 (2021-02-06)
> Package https://github.com/rryi/BitStructs.jl, commit 50ea2e46b77d098ba61ab65d15e31aa289848e24
> 
> \### Steps to reproduce:
> 
> \* use a Win10 machine
> \* install julia 1.6.0 RC1 64 bit
> \* download/clone package BitStructs.jl to a local directory
> \* enter that directory in a CMD shell
> \* start julia
> \* activate package dir
> \* add BenchmarkTools (I did it some days ago with v0.5.0. Retry with version 0.6.0 had the same result)
> \* exit julia
> \* execute in CMD shell: julia test\\crash.jl
> 
> My log for that, showing the crash under 1.6.0RC1
> 
> \`\`\`
> Microsoft Windows \[Version 10.0.19042.867\]
> (c) 2020 Microsoft Corporation. Alle Rechte vorbehalten.
> 
> C:\\Users\\RR\\julia\\BitStructs\>julia test\\crash.jl
> Activating environment at \`C:\\Users\\RR\\julia\\BitStructs\\Project.toml\`
> S(S\_RUNNING, BIGMINUS, Float16(-1.0), true, false, false, true, 0, 'a', 'c', 0x0001, 0x0002, 3, 4)BitStruct{NamedTuple{(:status, :strange, :sign, :flag1, :flag2, :flag3, :flag4, :bit1, :ac, :lc, :id1, :id2, :delta1, :delta2), Tuple{ProcStatus, Strange, Sign, Bool, Bool, Bool, Bool, BInt{1}, AsciiChar, Latin1Char, BUInt{9}, BUInt{12}, BInt{9}, BInt{9}}}} 0x0200c00802c78531
> status::ProcStatus = S\_RUNNING
> strange::Strange = BIGMINUS
> sign::Sign = -1.0
> flag1::Bool = true
> flag2::Bool = false
> flag3::Bool = false
> flag4::Bool = true
> bit1::BInt{1} = 0
> ac::AsciiChar = 'a'
> lc::Latin1Char = 'c'
> id1::BUInt{9} = 0x0000000000000001
> id2::BUInt{12} = 0x0000000000000002
> delta1::BInt{9} = 3
> delta2::BInt{9} = 4
> end
> struct/BitStruct simple field access ENTER:
> 2.700 ns (0 allocations: 0 bytes)
> 2.700 ns (0 allocations: 0 bytes)
> struct/BitStruct field access in @noinline function ENTER:
> 2.600 ns (0 allocations: 0 bytes)
> 9.500 ns (0 allocations: 0 bytes)
> set 2 fields on struct then BitStruct ENTER:
> 2.600 ns (0 allocations: 0 bytes)
> 358.571 ns (3 allocations: 48 bytes)
> set 2 fields on struct then BitStruct (large struct) ENTER:
> 2.600 ns (0 allocations: 0 bytes)
> the statements executed by set2fields run, if executed directly
> BitStruct{NamedTuple{(:status, :strange, :sign, :flag1, :flag2, :flag3, :flag4, :bit1, :ac, :lc, :id1, :id2, :delta1, :delta2), Tuple{ProcStatus, Strange, Sign, Bool, Bool, Bool, Bool, BInt{1}, AsciiChar, Latin1Char, BUInt{9}, BUInt{12}, BInt{9}, BInt{9}}}} 0x0200c00804c78511
> status::ProcStatus = S\_RUNNING
> strange::Strange = BIGMINUS
> sign::Sign = -1.0
> flag1::Bool = false
> flag2::Bool = false
> flag3::Bool = false
> flag4::Bool = true
> bit1::BInt{1} = 0
> ac::AsciiChar = 'a'
> lc::Latin1Char = 'c'
> id1::BUInt{9} = 0x0000000000000002
> id2::BUInt{12} = 0x0000000000000002
> delta1::BInt{9} = 3
> delta2::BInt{9} = 4
> end
> Calling set2fields(bs) causes a crash
> 
> Unreachable reached at 00000000610aa1b6
> 
> Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
> Exception: EXCEPTION\_ILLEGAL\_INSTRUCTION at 0x610aa1b6 -- set2fields at C:\\Users\\RR\\julia\\BitStructs\\test\\benchmark.jl:293
> in expression starting at C:\\Users\\RR\\julia\\BitStructs\\test\\benchmark.jl:316
> set2fields at C:\\Users\\RR\\julia\\BitStructs\\test\\benchmark.jl:293
> unknown function (ip: 00000000610aa1d9)
> jl\_apply at /cygdrive/c/buildbot/worker/package\_win64/build/src\\julia.h:1703 \[inlined\]
> do\_call at /cygdrive/c/buildbot/worker/package\_win64/build/src\\interpreter.c:115
> eval\_value at /cygdrive/c/buildbot/worker/package\_win64/build/src\\interpreter.c:204
> eval\_stmt\_value at /cygdrive/c/buildbot/worker/package\_win64/build/src\\interpreter.c:155 \[inlined\]
> eval\_body at /cygdrive/c/buildbot/worker/package\_win64/build/src\\interpreter.c:575
> jl\_interpret\_toplevel\_thunk at /cygdrive/c/buildbot/worker/package\_win64/build/src\\interpreter.c:669
> jl\_toplevel\_eval\_flex at /cygdrive/c/buildbot/worker/package\_win64/build/src\\toplevel.c:879
> jl\_toplevel\_eval\_flex at /cygdrive/c/buildbot/worker/package\_win64/build/src\\toplevel.c:827
> jl\_toplevel\_eval at /cygdrive/c/buildbot/worker/package\_win64/build/src\\toplevel.c:888 \[inlined\]
> jl\_toplevel\_eval\_in at /cygdrive/c/buildbot/worker/package\_win64/build/src\\toplevel.c:931
> eval at .\\boot.jl:360 \[inlined\]
> include\_string at .\\loading.jl:1090
> \_include at .\\loading.jl:1144
> include at .\\client.jl:444
> jl\_apply at /cygdrive/c/buildbot/worker/package\_win64/build/src\\julia.h:1703 \[inlined\]
> do\_call at /cygdrive/c/buildbot/worker/package\_win64/build/src\\interpreter.c:115
> eval\_value at /cygdrive/c/buildbot/worker/package\_win64/build/src\\interpreter.c:204
> eval\_stmt\_value at /cygdrive/c/buildbot/worker/package\_win64/build/src\\interpreter.c:155 \[inlined\]
> eval\_body at /cygdrive/c/buildbot/worker/package\_win64/build/src\\interpreter.c:575
> jl\_interpret\_toplevel\_thunk at /cygdrive/c/buildbot/worker/package\_win64/build/src\\interpreter.c:669
> jl\_toplevel\_eval\_flex at /cygdrive/c/buildbot/worker/package\_win64/build/src\\toplevel.c:879
> jl\_toplevel\_eval\_flex at /cygdrive/c/buildbot/worker/package\_win64/build/src\\toplevel.c:827
> jl\_toplevel\_eval at /cygdrive/c/buildbot/worker/package\_win64/build/src\\toplevel.c:888 \[inlined\]
> jl\_toplevel\_eval\_in at /cygdrive/c/buildbot/worker/package\_win64/build/src\\toplevel.c:931
> eval at .\\boot.jl:360 \[inlined\]
> include\_string at .\\loading.jl:1090
> \_include at .\\loading.jl:1144
> include at .\\Base.jl:386
> exec\_options at .\\client.jl:285
> \_start at .\\client.jl:485
> jfptr\_\_start\_33914.clone\_1 at C:\\RRtool\\julia-1.6.0-RC1\\lib\\julia\\sys.dll (unknown line)
> jl\_apply at /cygdrive/c/buildbot/worker/package\_win64/build/src\\julia.h:1703 \[inlined\]
> true\_main at /cygdrive/c/buildbot/worker/package\_win64/build/src\\jlapi.c:557
> repl\_entrypoint at /cygdrive/c/buildbot/worker/package\_win64/build/src\\jlapi.c:699
> mainCRTStartup at /cygdrive/c/buildbot/worker/package\_win64/build/cli\\loader\_exe.c:51
> BaseThreadInitThunk at C:\\WINDOWS\\System32\\KERNEL32.DLL (unknown line)
> RtlUserThreadStart at C:\\WINDOWS\\SYSTEM32\\ntdll.dll (unknown line)
> Allocations: 19362754 (Pool: 19359441; Big: 3313); GC: 70
> 
> C:\\Users\\RR\\julia\\BitStructs\>
> \`\`\`
> 
> here the run with julia 1.5.3, no crash:
> 
> \`\`\`
> C:\\Users\\RR\\julia\\BitStructs\>C:\\RRtool\\julia-1.5.3\\bin\\julia.exe test\\crash.jl
> Activating environment at \`C:\\Users\\RR\\julia\\BitStructs\\Project.toml\`
> S(S\_RUNNING, BIGMINUS, Float16(-1.0), true, false, false, true, 0, 'a', 'c', 0x0001, 0x0002, 3, 4)BitStruct{NamedTuple{(:status, :strange, :sign, :flag1, :flag2, :flag3, :flag4, :bit1, :ac, :lc, :id1, :id2, :delta1, :delta2),Tuple{ProcStatus,Strange,Sign,Bool,Bool,Bool,Bool,BInt{1},AsciiChar,Latin1Char,BUInt{9},BUInt{12},BInt{9},BInt{9}}}} 0x0200c00802c78531
> status::ProcStatus = S\_RUNNING
> strange::Strange = BIGMINUS
> sign::Sign = -1.0
> flag1::Bool = true
> flag2::Bool = false
> flag3::Bool = false
> flag4::Bool = true
> bit1::BInt{1} = 0
> ac::AsciiChar = 'a'
> lc::Latin1Char = 'c'
> id1::BUInt{9} = 0x0000000000000001
> id2::BUInt{12} = 0x0000000000000002
> delta1::BInt{9} = 3
> delta2::BInt{9} = 4
> end
> struct/BitStruct simple field access ENTER:
> 2.699 ns (0 allocations: 0 bytes)
> 397.995 ns (1 allocation: 32 bytes)
> struct/BitStruct field access in @noinline function ENTER:
> 2.399 ns (0 allocations: 0 bytes)
> 364.423 ns (1 allocation: 32 bytes)
> set 2 fields on struct then BitStruct ENTER:
> 2.399 ns (0 allocations: 0 bytes)
> 8.733 µs (5 allocations: 96 bytes)
> set 2 fields on struct then BitStruct (large struct) ENTER:
> 2.399 ns (0 allocations: 0 bytes)
> the statements executed by set2fields run, if executed directly
> BitStruct{NamedTuple{(:status, :strange, :sign, :flag1, :flag2, :flag3, :flag4, :bit1, :ac, :lc, :id1, :id2, :delta1, :delta2),Tuple{ProcStatus,Strange,Sign,Bool,Bool,Bool,Bool,BInt{1},AsciiChar,Latin1Char,BUInt{9},BUInt{12},BInt{9},BInt{9}}}} 0x0200c00804c78511
> status::ProcStatus = S\_RUNNING
> strange::Strange = BIGMINUS
> sign::Sign = -1.0
> flag1::Bool = false
> flag2::Bool = false
> flag3::Bool = false
> flag4::Bool = true
> bit1::BInt{1} = 0
> ac::AsciiChar = 'a'
> lc::Latin1Char = 'c'
> id1::BUInt{9} = 0x0000000000000002
> id2::BUInt{12} = 0x0000000000000002
> delta1::BInt{9} = 3
> delta2::BInt{9} = 4
> end
> Calling set2fields(bs) causes a crash
> b1 set field in loop by /= ENTER:
> 2.122 µs (0 allocations: 0 bytes)
> b2 set field in loop by set(..) ENTER:
> 2.133 µs (0 allocations: 0 bytes)
> struct/BitStruct: access 4 fields in a loop ENTER:
> 103.389 ns (0 allocations: 0 bytes)
> 66.400 µs (70 allocations: 1.09 KiB)
> struct/BitStruct: write 4 fields in a loop ENTER:
> 173.947 ns (0 allocations: 0 bytes)
> struct/BitStruct: access 4 fields in a loop, large struct ENTER:
> 104.979 ns (0 allocations: 0 bytes)
> 105.200 µs (0 allocations: 0 bytes)
> struct/BitStruct: write 4 fields in a loop, large struct ENTER:
> 175.520 ns (0 allocations: 0 bytes)
> struct/BitStruct: access 4 fields, direct code ENTER:
> 1.799 ns (0 allocations: 0 bytes)
> 1.070 µs (1 allocation: 32 bytes)
> function parameter benchmark: struct/BitStruct/parameterlist ENTER:
> 1.590 µs (17 allocations: 1.38 KiB)
> 1.610 µs (18 allocations: 1.39 KiB)
> 
> C:\\Users\\RR\\julia\\BitStructs\>
> \`\`\`

> <https://github.com/JuliaMath/Polynomials.jl/issues/150>
>
> The Polynomials package commits \[type piracy\](https://docs.julialang.org/en/v1/m…anual/style-guide/index.html#Avoid-type-piracy-1) for the \`show\` method, by adding \`show\` methods for \`Number\` and \`Rational\` that don't involve types defined by Polynomials.jl. See \[here\](https://github.com/JuliaMath/Polynomials.jl/blob/a94fed9d40710c75b19be4564a56b02b466d922f/src/show.jl#L215-L217), for example.
> 
> This leads to unexpected side effects for other packages by changing how numeric types defined in other packages are displayed in (e.g.) IJulia. For example, this affects the \`Sym \<: Number\` type defined by SymPy.jl, leading to \[this issue brought up on discourse\](https://discourse.julialang.org/t/sympy-latexstrings-ijulia-display-of-syms-in-latex-expression-in-jupyter/14902).
> 
> Suggestion: don't overload \`show\` for \`Number\`. Write your own \`myshow\` function and call it in \[\`printcoefficient\`\](https://github.com/JuliaMath/Polynomials.jl/blob/a94fed9d40710c75b19be4564a56b02b466d922f/src/show.jl#L132-L152) \*etcetera\* rather than \`show\`.

---

<div class="post-metadata">

**Author:** ![genkuroki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/genkuroki/32/18030_2.png) [@genkuroki](https://discourse.julialang.org/u/genkuroki)\
**Post date:** [August 24, 2021, 6:08pm UTC](https://discourse.julialang.org/t/minimal-working-example-that-demonstrates-the-danger-of-type-piracy/66922/9 "2021-08-24T18:08:33Z")

</div>

The following is a type piracy of the signature `Tuple{typeof(Base.findmin), Any, Any}`:

```julia
Base.findmin(f, X) = mapfoldl(x -> (f(x), x), min, X)

```

This is almost harmless in Julia v1.6.2, and moreover is very useful as follows:

```julia
ts = range(0, 2; length=201)
findmin(sinpi, ts)

```

```julia
(1.0, 0.5)

```

```julia
rosenbrock2d((x, y),) = (1 - x)^2 + 100(y - x^2)^2
xs = ys = range(-5, 5; length=1001)
findmin(rosenbrock2d, Iterators.product(xs, ys))

```

```julia
(0.0, (1.0, 1.0))

```

However, in Julia v1.7.0-beta3 and above, it is destructive because `Base.findmin(f, domain)` is already and more carefully defined in a different specification. (See [https://github.com/JuliaLang/julia/blob/master/base/reduce.jl#L862](https://github.com/JuliaLang/julia/blob/master/base/reduce.jl#L862))

The following is not a type piracy, because its signature `Tuple{typeof(Base.findmin), Foo, Any}` contains the user-defined type `Foo`:

```julia
struct Foo{F} f::F end
Base.findmin(foo::Foo, X) = mapfoldl(x -> (foo.f(x), x), min, X)

rosenbrock2d((x, y),) = -(1 - x)^2 + 100(y - x^2)^2
xs = ys = range(-5, 5; length=1001)
findmin(Foo(rosenbrock2d), Iterators.product(xs, ys))

```

```julia
(0.0, (1.0, 1.0))

```

The following is also not a type piracy, because its signature `Tuple{typeof(My.findmin), Any, Any}` contains the type of the user-defined function `My.findmin`:

```julia
module My
findmin(f, X) = mapfoldl(x -> (f(x), x), min, X)
end

rosenbrock2d((x, y),) = (1 - x)^2 + 100(y - x^2)^2
xs = ys = range(-5, 5; length=1001)
My.findmin(rosenbrock2d, Iterators.product(xs, ys))

```

```julia
(0.0, (1.0, 1.0))

```

**Another story**

The following causes the error below in Julia v1.7.0-beta3 and above:

```julia
rosenbrock2d((x, y),) = (1 - x)^2 + 100(y - x^2)^2
xs = ys = range(-5, 5; length=1001)
findmin(rosenbrock2d, Iterators.product(xs, ys))

```

> MethodError: no method matching keys(::Base.Iterators.ProductIterator{Tuple{StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base. TwicePrecision{Float64}}, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}})

The easiest way to solve this problem is a type piracy of the signature `Tuple{typeof(Base.keys), Base.Iterators.ProductIterator}` 😅:

```julia
Base.keys(itr::Iterators.ProductIterator) = Iterators.product(keys.(itr.iterators)...)
findmin(rosenbrock2d, Iterators.product(xs, ys))

```

```julia
(0.0, (601, 601))

```

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [August 24, 2021, 7:08pm UTC](https://discourse.julialang.org/t/minimal-working-example-that-demonstrates-the-danger-of-type-piracy/66922/10 "2021-08-24T19:08:32Z")

</div>

Ok, here’s the MWE that I came up with. Comments and other MWEs are welcome.

```julia
julia> module Package1
           foo(::Integer) = 42
           export foo
       end
Main.Package1

julia> using .Package1

julia> foo(1)
42

julia> module Package2
           using ..Package1
           Package1.foo(::Int) = 100
           export foo
       end
Main.Package2

julia> using .Package2

julia> foo(1)
100

```

Here’s my take:

- Type piracy of the kind in my previous MWE where `Package3` added a `foo(::B)` method is usually not an issue since it turns code that would have been a `MethodError` into runnable code.
- Type piracy is a problem when code that is runnable with `Package1` returns a different result after loading `Package2`. This typically happens when `Package2` adds a method specialized for type `T` (where `T` is a type not defined in `Package2`) to a function that already has a method in `Package1` for a supertype of `T`.
