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

UInt32 literals are typed as Int32 when used as enum values #194

Closed
mverzilli opened this Issue Sep 2, 2014 · 5 comments

Comments

Projects
None yet
4 participants
@mverzilli
Member

mverzilli commented Sep 2, 2014

lib LibFoo("AnyLib")
  enum Foo
    A = 0x00000001_u32
  end
end

puts LibFoo::Foo::A.class #=> Int32

I expected Foo::A.class to yield UInt32 instead

@asterite

This comment has been minimized.

Contributor

asterite commented Sep 2, 2014

This is by design. Enum constants are usually all of the same type. To do the above you can write:

lib LibFoo
  enum Foo < UInt32
    A = 0x00000001
  end
end

puts LibFoo::Foo::A.class #=> UInt32

More info here (little by little we are growing the docs)

@mverzilli

This comment has been minimized.

Member

mverzilli commented Sep 2, 2014

Then, shouldn't my example break compilation? As a programmer, if I take care of defining a literal with a trailing "_u32" it's likely that my intent is for A to end up being a UInt32.

If that's not supported by the language I'd rather have it pointed out by the compiler than just silently typed to Int32.

The compiler exception could even do the same as you did: suggest having the enum extend UInt32 if that's what the programmer wants to achieve. In that case, I'd also expect to be warned if I assign something other than a UInt32 literal.

@fernandes

This comment has been minimized.

Contributor

fernandes commented Jun 1, 2016

hi, I'm trying to solve this issue, I did the test and implementation, they are ok (at least I think so), but need to define some things like, on src/time/time.cr we have an enum like:

enum Kind : Int64
  Unspecified = 0
  Utc         = 1
  Local       = 2
end

According to this issue, should break unless defined like:

enum Kind : Int64
  Unspecified = 0_i64
  Utc         = 1_i64
  Local       = 2_i64
end

another possible solution is to raise the exception only when enum_base_type is the default i32 and was specified another type for enum values. (PR is covering this case so we don't break crystal current behavior).

Opened PR to make easier to discuss

@asterite

This comment has been minimized.

Contributor

asterite commented Jun 1, 2016

@fernandes No, it should not break, it should work. The idea of writing enum Kind : UInt64 is to say "I want the values to be UInt64", so there's really no point in repeating that information in all of the constants.

The case you fixed is important, though, because it's unexpected that 0x00000001_u32 silently changes to Int32. But I wouldn't worry about other combinations right now. I suspect the original error came from not knowing that you can specify the underlying type of an enum, and that all enum members have the same type.

@asterite asterite closed this in c6a0355 Jun 1, 2016

asterite added a commit that referenced this issue Jun 1, 2016

Merge pull request #2703 from fernandes/fix/do_not_cast_enum_value
Compiler: Do not cast enum value to i32 if not specified. Fixes #194
@fernandes

This comment has been minimized.

Contributor

fernandes commented Jun 1, 2016

that's perfect, good to know! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment