crystal-lang / crystal

The Crystal Programming Language
https://crystal-lang.org
Apache License 2.0
19.35k stars 1.62k forks source link

Stored value type does not match pointer operand type #4136

Open faustinoaq opened 7 years ago

faustinoaq commented 7 years ago

I was playing with fun and found something. I try to show you a minimal example:

fun print_chrray(value : Char[5])
  puts value
end

print_chrray(StaticArray(Char, 5).new('x'))

The above code produce the following message:

Module validation failed: Stored value type does not match pointer operand type!
  store [5 x i32]* %value, [5 x i32]* %value1, !dbg !54
 [5 x i32]
0x53c10e: ??? at ??
0x14e67a0: ??? at ??
0x1422e3d: ??? at ??
0x1cac555: ??? at ??
0x597c79: ??? at ??
0x56374d: main at ??
0x7f2f715c4291: __libc_start_main at ??
0x53b831: ??? at ??

Error: you've found a bug in the Crystal compiler.
Please open an issue, including source code that will allow us to reproduce the bug:
https://github.com/crystal-lang/crystal/issues
asterite commented 7 years ago

I don't think static arrays can be passed around in C, so maybe this shouldn't even compile. Maybe it's a bug, but it has very low priority.

faustinoaq commented 7 years ago

@asterite Yes C don't allow array literal as argument but array pointer

Pass by reference work as in C

fun print_chrray(sarr : Char[5]*)
  puts sarr.value
end

sarr = StaticArray(Char, 5).new('x')

print_chrray(pointerof(sarr)) # => StaticArray['x', 'x', 'x', 'x', 'x']
bew commented 7 years ago

What do you mean by passing array literal in C, I got this to work: (C code)

#include <stdio.h>

int func(const int bla[3])
{
  return bla[0];
}

int main()
{
  printf("%d\n", func( (const int[3]){42, 43, 44} )); // => 42
  return (0);
}

Is it what you're trying to do in Crystal @faustinoaq ?

faustinoaq commented 7 years ago

@bew You're right. I was confused. My mistake :sweat_smile:

refi64 commented 7 years ago

@bew Actually, you're just passing a pointer to the first element of the array, because C is C and reasons unknown.

bew commented 7 years ago

@kirbyfan64 You're right, and I was confused too, so @faustinoaq you're right 😄

edit:

I think the type syntax in fun is weird, because in C:

void print_chrray(char value[5]);

The argument value has type char*, and in Crystal, you need an extra * to represent the same thing:

fun print_chrray(value : Char[5] *)

It feels weird, because then the crystal type Char[5] has no representation in C (if I understand it well)

refi64 commented 7 years ago

@bew Well...

Actually, C already completely ignores the bound on an array parameter. So, like you already said, value is of type char* in C. Therefore, the equivalent in Crystal is just Char* (no [5]).

konovod commented 7 years ago

Maybe C ignore bounds, but Crystal doesn't, so i like this little bit of additional typesafety in bindings: https://github.com/konovod/monocypher/blob/master/src/monocypher/libmonocypher.cr. Never encountered this issue though, maybe because i wrap all staticarrays in a structs with to_unsafe method.