# Printing user defined unsigned primitive typed

**URL:** https://discourse.julialang.org/t/printing-user-defined-unsigned-primitive-typed/26467
**Category:** General Usage
**Created:** [July 17, 2019, 3:27pm UTC](https://discourse.julialang.org/t/printing-user-defined-unsigned-primitive-typed/26467 "2019-07-17T15:27:45Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![hros](https://avatars.discourse-cdn.com/v4/letter/h/97f17d/32.png) [@hros](https://discourse.julialang.org/u/hros)
#### Post date: [July 17, 2019, 3:27pm UTC](https://discourse.julialang.org/t/printing-user-defined-unsigned-primitive-typed/26467/1 "2019-07-17T15:27:45Z")

</div>

Following the advice in this [post](https://discourse.julialang.org/t/constructors-for-primitive-types/19139/2) I declared a user defined primitive type of 32 bits.  
This works when declared as a signed 32 bit integer:

```julia
abstract type MyType <: Signed end
primitive type MyType32 <: MyType 32 end
MyType32(x::Int32) = reinterpret(MyType32, x)
Int32(x::MyType32) = reinterpret(Int32, x)
Base.show(io::IO, x::MyType32) = print(io, Int32(x))

x=MyType32(Int32(5))
println(x)

```

However, when changing to unsigned integers:

```julia
abstract type MyType <: Unsigned end
primitive type MyType32 <: MyType 32 end
MyType32(x::UInt32) = reinterpret(MyType32, x)
UInt32(x::MyType32) = reinterpret(UInt32, x)
Base.show(io::IO, x::MyType32) = print(io, UInt32(x))

x=MyType32(UInt32(5))
println(x)

```

The `println` function raises an error:  
`LoadError: promotion of types MyType32 and Int64 failed to change any arguments`

The stack trace shows that `println` calls `string` which calls `dec`, and suddenly the value becomes `Int64` which is not supported by my primitive type

---

<div class="post-metadata">

### Author: ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)
#### Post date: [July 18, 2019, 3:04am UTC](https://discourse.julialang.org/t/printing-user-defined-unsigned-primitive-typed/26467/2 "2019-07-18T03:04:36Z")

</div>

you need to define corresponding converters:

```julia
Base.convert(::Type{T}, x::MyType32) where {T<:Integer} = convert(T, UInt32(x))
Base.convert(::Type{MyType32}, x::T) where {T<:Integer} = MyType32(convert(UInt32, x))

```

---

<div class="post-metadata">

### Author: ![hros](https://avatars.discourse-cdn.com/v4/letter/h/97f17d/32.png) [@hros](https://discourse.julialang.org/u/hros)
#### Post date: [July 18, 2019, 7:20am UTC](https://discourse.julialang.org/t/printing-user-defined-unsigned-primitive-typed/26467/3 "2019-07-18T07:20:50Z")

</div>

Thanks for your reply, and naturally it works.  
Please clarify the flow of function calls when `println(x)` is called.  
When adding debug print statements I could not see that the additional `Base.convert` methods are called. Yet, evidently, they are necessary for the sample program to compile and run

---

<div class="post-metadata">

### Author: ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)
#### Post date: [July 18, 2019, 11:28am UTC](https://discourse.julialang.org/t/printing-user-defined-unsigned-primitive-typed/26467/4 "2019-07-18T11:28:01Z")

</div>

> [@hros](#):
>
> Please clarify the flow of function calls when `println(x)` is called.

I think the stacktrace already told this every clearly:

```julia
julia> println(x)
ERROR: promotion of types MyType32 and Int64 failed to change any arguments
Stacktrace:
 [1] error(::String, ::String, ::String) at ./error.jl:42
 [2] sametype_error(::Tuple{MyType32,Int64}) at ./promotion.jl:308
 [3] not_sametype(::Tuple{MyType32,Int64}, ::Tuple{MyType32,Int64}) at ./promotion.jl:302
 [4] promote at ./promotion.jl:285 [inlined]
 [5] ==(::MyType32, ::Int64) at ./promotion.jl:350
 [6] ndigits0zpb(::MyType32, ::Int64) at ./intfuncs.jl:450
 [7] ndigits0z(::MyType32, ::Int64) at ./intfuncs.jl:512

```

In REPL, you could simply type the stacktrace number and press `Ctrl+Q` to jump to the source code and search for the root cause manually.

Another way is to use `Debugger.jl`:

```julia
# we start from [5] ==(::MyType32, ::Int64) at ./promotion.jl:350 
# since it's simple to make a trivial test example and it's also every close to the final error site
julia> @enter x == 5 
[ Info: tracking Base
In ==(x, y) at promotion.jl:350
>350 ==(x::Number, y::Number) = (==)(promote(x,y)...)

About to run: (promote)(5, 5)

```

```julia
# tell debugger to break on error
1|debug> bp on
Breaking on error
# continue
1|debug> c
Breaking for error:
ERROR: promotion of types MyType32 and Int64 failed to change any arguments
Stacktrace:
 [1] error(::Tuple{String,String,String}) at error.jl:42
 [2] sametype_error(::Tuple{MyType32,Int64}) at promotion.jl:308
 [3] not_sametype(::Tuple{MyType32,Int64}, ::Tuple{MyType32,Int64}) at promotion.jl:302
 [4] promote(::MyType32, ::Int64) at promotion.jl:285
 [5] ==(::MyType32, ::Int64) at promotion.jl:350

In error(s) at error.jl:41
 40 function error(s::Vararg{Any,N}) where {N}
 41 @_noinline_meta
>42 throw(ErrorException(Main.Base.string(s...)))
 43 end

About to run: (throw)(ErrorException("promotion of types MyType32 and Int64 failed to change any arguments"))

```

We arrived at the error site, but often this is not the root cause, so let’s go down to the stacktrace:

```julia
# OK, just some error message handling stuff, nothing helpful
1|debug> down
In sametype_error(input) at promotion.jl:307
 306 function sametype_error(input)
 307 @_noinline_meta
>308 error("promotion of types ",
 309 join(map(x->string(typeof(x)), input), ", ", " and "),
 310 " failed to change any arguments")
 311 end

About to run: (error)("promotion of types ", "MyType32 and Int64", " failed to change any arguments")

```

```julia
# same
2|debug> down
In not_sametype(x, y) at promotion.jl:302
>302 not_sametype(x::T, y::T) where {T} = sametype_error(x)

About to run: (Base.sametype_error)((5, 5))

```

```julia
# finally, this function truely did something non-trivial by calling `_promote(x,y)`
3|debug> down
In promote(x, y) at promotion.jl:283
 282 function promote(x, y)
 283 @_inline_meta
 284 px, py = _promote(x, y)
>285 not_sametype((x,y), (px,py))
 286 px, py
 287 end

About to run: (Base.not_sametype)((5, 5), (5, 5))

# so, let's add a breakpoint at 284 and quit
4|debug> bp add 284
┌ Warning: skipping (::getfield(Base, Symbol("##23#24")))(x) in Base at promotion.jl:309 to avoid parsing too much code
└ @ Revise ~/.julia/packages/Revise/agmgx/src/Revise.jl:813
Breaking on error
1] /Applications/Julia-1.1.app/Contents/Resources/julia/share/julia/base/promotion.jl:284 

4|debug> q

```

```julia
# enter again and continue to the bp
julia> @enter x == 5
In ==(x, y) at promotion.jl:350
>350 ==(x::Number, y::Number) = (==)(promote(x,y)...)

About to run: (promote)(5, 5)
1|debug> bp
Breaking on error
1] /Applications/Julia-1.1.app/Contents/Resources/julia/share/julia/base/promotion.jl:284

1|debug> c
Hit breakpoint:
In promote(x, y) at promotion.jl:283
 282 function promote(x, y)
 283 @_inline_meta
>284 px, py = _promote(x, y)
 285 not_sametype((x,y), (px,py))
 286 px, py
 287 end

About to run: (Base._promote)(5, 5)
1|debug> s
In _promote(x, y) at promotion.jl:259
 258 function _promote(x::T, y::S) where {T,S}
 259 @_inline_meta
>260 R = promote_type(T, S)
 261 return (convert(R, x), convert(R, y))
 262 end

About to run: (promote_type)(MyType32, Int64)

```

then, it’s clear that we need to define a converter for `MyType32` to `Integer`:

```julia
1|debug> n
In _promote(x, y) at promotion.jl:259
 258 function _promote(x::T, y::S) where {T,S}
 259 @_inline_meta
 260 R = promote_type(T, S)
>261 return (convert(R, x), convert(R, y))
 262 end

About to run: (convert)(Integer, 5)
1|debug> fr
[1] _promote(x, y) at promotion.jl:259
  | x::MyType32 = 5
  | y::Int64 = 5
  | R::DataType = Integer
  | T::DataType = MyType32
  | S::DataType = Int64
1|debug> 

```
