# Switching off implicit conversion

**URL:** <https://discourse.julialang.org/t/switching-off-implicit-conversion/134568>\
**Category:** General Usage\
**Tags:** convert\
**Created:** [December 15, 2025, 9:09pm UTC](https://discourse.julialang.org/t/switching-off-implicit-conversion/134568 "2025-12-15T21:09:20Z")\
**Posts on this page:** 6\
**Page:** 2

<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:** [December 16, 2025, 2:36pm UTC](https://discourse.julialang.org/t/switching-off-implicit-conversion/134568/21 "2025-12-16T14:36:52Z")

</div>

Yes, exactly! So you want two functions: One named `implicit_convert` that gets used in default constructors and assertions and a number of generic definitions, and one named `explicit_convert` that is _never_ called by base.

That’s _exactly the status quo!_ It’s just that the former is called `convert`, and the latter is left to you to define as you wish.

---

<div class="post-metadata">

**Author:** ![sadish-d](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sadish-d/32/48058_2.png) [@sadish-d](https://discourse.julialang.org/u/sadish-d)\
**Post date:** [December 16, 2025, 3:10pm UTC](https://discourse.julialang.org/t/switching-off-implicit-conversion/134568/22 "2025-12-16T15:10:31Z")

</div>

That would not solve the problem. I would need base to call some `Base.convert1` when I push a something into an array and `Base.convert2` when I use default constructors. That way I could keep `convert1` behavior by defining `convert1(t, x::MyType) = my_convert(t, x)` while switching off `convert2` by defining `convert2(t, x::MyType) = identity(x)`. Then I get the error I want when the wrong argument is passed to the constructor when a `MyType` is expected, while letting me pass the “wrong” type to a vector and have it be accepted as `MyType`.

---

<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:** [December 16, 2025, 4:13pm UTC](https://discourse.julialang.org/t/switching-off-implicit-conversion/134568/23 "2025-12-16T16:13:15Z")

</div>

Well, the constructor case is easy to override with a custom constructor, but I get your general point.

I think the trouble is stemming from wanting to have what Base Julia would consider as a “surprising” convert in Julia’s builtin containers’ `setindex!` — and only in that one case. And, unfortunately, unlike arithmetic, promotion, and constructors, that’s a case where it’s not really possible to customize and something different than `convert`.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [December 16, 2025, 5:48pm UTC](https://discourse.julialang.org/t/switching-off-implicit-conversion/134568/24 "2025-12-16T17:48:10Z")

</div>

> [@sadish-d](#):
>
> All the things that call `convert` still do; they just go through `implicit_convert`. So my proposal is not breaking. All code that are valid remain valid.

This is not true. All prior code that assumed implicit conversion is exactly the same as manual `convert` calls, as documented, glitch when composed with a new type that opts out of this fallback and strictly implements `convert` for explicit conversion. They are forced to replace all the calls with `implicit_convert` to reflect their intent and properly error with the new types, as opposed to unlucky users hitting an implicit conversion error 2 days into a simulation. v1.3+ libraries failing with v1.15+ libraries is not backwards compatibility. Again, an `explicit_convert` would not cause this problem.

> [@sadish-d](#):
>
> It’s been done before and done without breaking changes (example: `getfield` vs `getproperty`).

This is also not true. `getproperty` for dot syntax and `getfield` were designed for [v0.7](https://github.com/JuliaLang/julia/blob/22590d529dceed93ae1dd8f32d569edba3be9f50/base/docs/basedocs.jl#L1792) when the API was unstable, and this has not changed in v1’s stable API.

> [@sadish-d](#):
>
> what if we want some conversions implicitly done (say, pushing into a vector) but not others (say, wherever `::` is used). Right now, it’s all or nothing…I would need base to call some `Base.convert1` when I push a something into an array and `Base.convert2` when I use default constructors.

Implicit conversion is _supposed_ to be all-or-nothing and independent of type. If you toggled implicit conversion at the 6+ contexts for each type, making 2^6=64 configurations, type-generic code using implicit conversion would be incredibly brittle, and the only “fix” would be to dispatch on sets of 64 Holy traits for very slightly different behaviors. I don’t think people who sometimes avoid dealing with strong typing would rather deal with type-dependent implicit conversion. If you want conversions to only occur in some contexts but not others, implement and use explicit type checks and conversions (constructors, a `explicit_convert`-like function) instead of `Base.convert`.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [December 16, 2025, 8:34pm UTC](https://discourse.julialang.org/t/switching-off-implicit-conversion/134568/25 "2025-12-16T20:34:45Z")

</div>

If you feel motivated to play around with this idea, one thing you can do is create compilation contexts where the rules you want are enforced.

E.g. probably the easiest way to do this is with IRTools.jl:

```julia-auto
using IRTools: IRTools, IR, @dynamo, recurse!

@dynamo function no_implict(args...)
    ir = IR(args...)
    ir == nothing && return
    recurse!(ir)
    return ir
end
function no_implict(::typeof(Base.setindex!), collection::AbstractArray{T}, elem::U, inds...) where {T, U}
    if !(T <: U)
        error("That's not allowed in this mode!")
    end
    setindex!(collection, elem, inds...)
end

function no_implict(::typeof(Base.push!), collection::AbstractArray{T}, elem::U) where {T, U}
    if !(T <: U)
        error("That's not allowed in this mode!")
    end
    push!(collection, elem)
end

```

and then tada!

```julia-auto
julia> no_implict() do
           v = [1,2,3]
           push!(v, 4.0)
       end
ERROR: That's not allowed in this mode!
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:44
 [2] no_implict(::typeof(push!), collection::Vector{Int64}, elem::Float64)
   @ Main ~/Nextcloud/Julia/scrap/implicit_convert/scrap.jl:19
 [3] #20
   @ ./REPL[10]:3 [inlined]
 [4] no_implict(args::var"#20#21")
   @ Main ~/.julia/packages/IRTools/v0mn8/src/reflection/dynamo.jl:0
 [5] top-level scope
   @ REPL[10]:1

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [December 17, 2025, 2:04pm UTC](https://discourse.julialang.org/t/switching-off-implicit-conversion/134568/26 "2025-12-17T14:04:29Z")

</div>

> [@Mason](#):
>
> `if !(T <: U)`

Just checking, shouldn’t that be `U <: T`, that is the value’s type should be a subtype of the array element type?

[Previous page](https://discourse.julialang.org/t/switching-off-implicit-conversion/134568.md?page=1)
