I tried out an old project and got a rather strange error.
The project is bindgencr. Unfortunately I don't really know what the root cause of the bug / error is, but (at least on my system) it can be easily reproduced by downloading the rep. and running the sample code.
Here's an example:
位 crystal run src/bindgencr.cr -- -l cimgui -n LibCimgui samples/cimgui/cimgui.xml
Error in src/bindgencr.cr:1: while requiring "prelude"
require "./bindgencr/*"
^
in /usr/lib/crystal/prelude.cr:48: while requiring "main": BUG: called Pointer(Pointer(UInt8)).restriction_of?(Array(String))
require "main"
^
I've tried running it with the --prelude=empty flag, but that gives out the same output as before.
My setup info:
位 uname -s -r
Linux 4.12.3-1-MANJARO
位 crystal -v
Crystal 0.23.1 (2017-07-17) LLVM 4.0.1
To reproduce:
def main(options, arguments : Array(String))
end
main("foo", ["bar", "baz"])
Looks like your def main collides with fun main which is probably the only fun outside a lib - and ofc also defined in the empty prelude.
A minimal sample to reproduce doesn't even to call main itself:
def main(options, arguments : Array(String))
end
At the very least we should have a nicer error message for this.
Yes, the parser could prevent to define a method named main as a special case. Or, better find a way around this. From inside a Crystal program you'll never need to call the main function so this could perhaps be fixed with proper scoping or - as a naive approach - transparently renaming main method and calls.
Error in line 1: while requiring "prelude"
in /usr/lib/crystal/prelude.cr:39: while requiring "crystal/main": BUG: called Pointer(Pointer(UInt8)).restriction_of?(Array(String))
require "crystal/main"
^
I think we need to use a different name for main, maybe __main, or even __crystal_main. Then the compiler could look up that name to define the C main function, but allowing users to define main methods without conflict.
fun main is already defined in the prelude, we should just disallow a def with the same name.
The compiler shouldn't assume the main method name, it already pregenerates __crystal_main. Having fun main be defined in crystal makes a bunch of usecases possible, such as using SDL.
Yes. What I'm saying is, there's no need to use main for the C function. It's more common to define a main top level method. Or, put another way, no other language prevents you from using main (or any other non keyword name) as a name.
If you want to change the symbol mangling so that fun and top-level-def with the same name don't collide I'm fine with that. Changing around how fun main works right now I'm not so sure...
I actually see no problem with not being able to define fun main to redefine main, that's what we have redefine_main for, no?
I was thinking that maybe top-level fun could be implicitly added to LibC, and only called by doing LibC.whatever. That way fun main (or any other fun, for that matter) would never conflict with a main method.
I like the idea of another namespace for toplevel funs, but not with adding them to LibC, since the manually defined functions are usually not related to libc.
Maybe something more like ExternalFunctions.
Note: A "long" module name is not a problem I think, because those functions are usually not called by crystal code (or very occasionally).
I actually see no problem with not being able to define
fun mainto redefinemain, that's what we haveredefine_mainfor, no?
We removed redefine_main in favour of this commit: https://github.com/crystal-lang/crystal/commit/5f0fe1c09a93a8b5f53f3cb8db99af2f03644096
I like that as-is.
I like that as-is.
@RX14 As-is generates the error linked above in https://github.com/crystal-lang/crystal/issues/4761#issuecomment-429661099
Yes. The error should be improved. But I don't think the ability to define a top-level def main (this has been complained about once in the 2.5 years since that commit) is worth changing it around.
Most helpful comment
I think we need to use a different name for
main, maybe__main, or even__crystal_main. Then the compiler could look up that name to define the Cmainfunction, but allowing users to definemainmethods without conflict.