Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation on fun argument conversion is incorrect #683

Open
HertzDevil opened this issue Apr 5, 2023 · 1 comment
Open

Documentation on fun argument conversion is incorrect #683

HertzDevil opened this issue Apr 5, 2023 · 1 comment

Comments

@HertzDevil
Copy link
Contributor

HertzDevil commented Apr 5, 2023

The docs say:

Note that there are no implicit conversions (except to_unsafe, which is explained later) when invoking a C function: you must pass the exact type that is expected. For integers and floats you can use the various to_... methods.

But this is not true:

lib LibC
  alias Int = Int32
  fun exit(status : Int) : NoReturn
end

LibC.exit(69_u8)   # okay
LibC.exit(69_i128) # okay

More surprising is that it is okay to pass a BigInt here too, but not its unsafe counterpart:

require "big"

LibC.exit(69.to_big_i)           # okay
LibC.exit(69.to_big_i.to_unsafe) # Error: argument 'x0' of 'LibC#exit' must be Int32, not Pointer(LibGMP::MPZ)

So something else must be going on.

@straight-shoota
Copy link
Member

Yes, on fun calls, the compiler applies some special conversions for numeric parameters. If the argument responds to #to_i32!, this methods return value is used.

struct NotInt
  def to_i32!
    42
  end
end

LibC.exit(NoInt.new)

The implementation is very old and predates the more recent number autocasting which serves a similar purpose.

https://github.com/crystal-lang/crystal/blob/7982ff6533fd5f6cf5eda8a0be49987ef6775359/src/compiler/crystal/semantic/conversions.cr#L2-L21

Autocasting applies in more situations and is safer. Unchecked conversions such as BigInt#to_i32! can fail at runtime.

I believe we could probably retire these special numeric argument conversions for fun calls and replace them with general autocasting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants