# Please explain this error

**URL:** <https://forum.crystal-lang.org/t/please-explain-this-error/4537>\
**Category:** Help & Support\
**Created:** [April 1, 2022, 3:23am UTC](https://forum.crystal-lang.org/t/please-explain-this-error/4537 "2022-04-01T03:23:03Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [April 1, 2022, 3:23am UTC](https://forum.crystal-lang.org/t/please-explain-this-error/4537/1 "2022-04-01T03:23:03Z")

</div>

I was experimenting with some code.  
These compile.

```auto
cnt = seg[..(kn - 1) >> s].map { |m| (~m).popcount }.sum

cnt = seg[0..(kn - 1) >> s].map { |m| (~m).popcount }.sum

cnt = seg[0i32..(kn - 1).to_i32 >> s].map { |m| (~m).popcount }.sum

```

But these don’t

```auto
cnt = seg.to_unsafe[0..(kn - 1) >> s].map { |m| (~m).popcount }.sum

cnt = seg.to_unsafe[0i32..(kn - 1).to_i32 >> s].map { |m| (~m).popcount }.sum

```

And gives this. error for both.

```auto
➜ crystal build twinprimes_ssozgisty.cr -Dpreview_mt --release
Showing last frame. Use --error-trace for full trace.

In /home/jzakiya/crystal/share/crystal/src/pointer.cr:117:11

 117 | (self + offset).value
             ^
Error: no overload matches 'Pointer(UInt64)#+' with type Range(Int32, Int32)

Overloads are:
 - Pointer(T)#+(offset : Int64)
 - Pointer(T)#+(other : Int)

```

---

<div class="post-metadata">

**Author:** ![yxhuvud](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/yxhuvud/32/27_2.png) [@yxhuvud](https://forum.crystal-lang.org/u/yxhuvud)\
**Post date:** [April 1, 2022, 6:09am UTC](https://forum.crystal-lang.org/t/please-explain-this-error/4537/2 "2022-04-01T06:09:21Z")

</div>

It is hard to fully know as you don’t provide enough information (what is seg? what do you get if you add `--error-trace` when you compile?), but `seg.to_unsafe` likely returns a pointer, which define `[]` as

```auto
  def [](offset)
    (self + offset).value
  end

```

which would then trigger your error.

What do you expect to happen if you add a range to a pointer? I’d expect the compilation error you are getting.

---

<div class="post-metadata">

**Author:** ![hholst](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hholst/32/1573_2.png) [@hholst](https://forum.crystal-lang.org/u/hholst)\
**Post date:** [April 1, 2022, 6:11am UTC](https://forum.crystal-lang.org/t/please-explain-this-error/4537/3 "2022-04-01T06:11:58Z")

</div>

Well, a ranged pointer, i.e. an Array? I think the semantics makes sense, less so the operator overload.

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [April 1, 2022, 3:20pm UTC](https://forum.crystal-lang.org/t/please-explain-this-error/4537/4 "2022-04-01T15:20:00Z")

</div>

`seg = Slice(UInt64).new(((ks - 1) >> s) + 1)`

It seems odd the same line with bounds checking will compile but won’t compile when bounds checking turned off: `seg.to_unsafe[range]`

Without knowing the motivations behind it, I would consider this a bug.

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [April 1, 2022, 4:13pm UTC](https://forum.crystal-lang.org/t/please-explain-this-error/4537/5 "2022-04-01T16:13:07Z")

</div>

What do you expect the return type of asking a subrange of a pointer? That doesn’t make a lot of sense. With a pointer you can only point to a single place, not a range, exactly because the pointer has no bounds.

In general I would avoid not doing bound checks. In all my tests avoiding this leads to the same performance, not a better performance. I don’t know why, maybe it’s branch prediction.

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [April 1, 2022, 5:34pm UTC](https://forum.crystal-lang.org/t/please-explain-this-error/4537/6 "2022-04-01T17:34:19Z")

</div>

> [@asterite](#):
>
> What do you expect the return type of asking a subrange of a pointer? That doesn’t make a lot of sense. With a pointer you can only point to a single place, not a range, exactly because the pointer has no bounds.

As you can see, I’m reading over a range in all cases.  
It compiles and runs fine as I initially show, but using `.to_unsafe` causes an error.  
As a user, this is surprising, because I would expect if it compiles with bounds checks it should compile with no bounds checks (I thought that’s what `.to_unsafe` does). I had|have no knowledge of the implementation details (pointers, etc), but I didn’t expect this behavior, as it worked everywhere else I used it.

> [@asterite](#):
>
> In general I would avoid not doing bound checks. In all my tests avoiding this leads to the same performance, not a better performance. I don’t know why, maybe it’s branch prediction.

I have code sections, particularly in inner loops, where doing read|writes using `.to_unsafe` produces substantial performance benefits. I normally don’t use it willy-nilly, but it DOES make a difference in certain places. (I first observed this in the Rust version of the same code when turning off bounds checking in it.)

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [April 1, 2022, 7:47pm UTC](https://forum.crystal-lang.org/t/please-explain-this-error/4537/7 "2022-04-01T19:47:59Z")

</div>

To clarify, `to_unsafe` isn’t equivalent to “I want to do things without bound checks”

Maybe that’s why your expectations don’t match what ends up happening.

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [April 1, 2022, 8:02pm UTC](https://forum.crystal-lang.org/t/please-explain-this-error/4537/8 "2022-04-01T20:02:13Z")

</div>

OK, but I’m just trying to understand why the later code doesn’t compile.  
Doesn’t `to_unsafe` not do bounds checking?  
Isn’t that why it’s faster for the uses I cited?  
Or where, or for what other purposes, would you use it?  
Again, I’m just trying to understand what’s going on.

```auto
def **to_unsafe** : [Pointer](https://crystal-lang.org/api/1.3.2/Pointer.html)(T) [#](https://crystal-lang.org/api/1.3.2/Array.html#to_unsafe%3APointer%28T%29-instance-method)

Returns a pointer to the internal buffer where `self` 's elements are stored.

This method is **unsafe** because it returns a pointer, and the pointed might eventually not be that of `self` if the array grows and its internal buffer is reallocated.

ary = [1, 2, 3]
ary.to_unsafe[0] # => 1

```

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [April 1, 2022, 8:23pm UTC](https://forum.crystal-lang.org/t/please-explain-this-error/4537/9 "2022-04-01T20:23:24Z")

</div>

Right, `to_unsafe` returns a `Pointer`, as you mention. If you check the available methods of `Pointer` there’s no `#[](Range)` overload, simply because such overload doesn’t make sense.

> Doesn’t `to_unsafe` not do bounds checking?

No, `to_unsafe` returns a `Pointer`.

> Isn’t that why it’s faster for the uses I cited?

I don’t have a proof that it’s faster.

> Or where, or for what other purposes, would you use it?

I would never use it unless I need to interface with C.

---

<div class="post-metadata">

**Author:** ![HertzDevil](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hertzdevil/32/1023_2.png) [@HertzDevil](https://forum.crystal-lang.org/u/HertzDevil)\
**Post date:** [April 1, 2022, 8:43pm UTC](https://forum.crystal-lang.org/t/please-explain-this-error/4537/10 "2022-04-01T20:43:03Z")

</div>

Some methods in `Pointer` still have range semantics, e.g. `Pointer#map!` implements `Slice#map!` and not the other way round, which may be where the confusion comes from. I think we should drop those instance methods from `Pointer`.
