www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using enum constant from different modules

reply Jacob Carlborg <doob me.com> writes:
Here's a code example:

module main;

import foo;

enum Get = "GET";

void bar (string a)
{
     assert(a is Get);
}

void main ()
{
     asd();
}

module foo;

import main;

void asd()
{
     bar(Get);
}

Running the above code will cause an assert error in the function "bar". 
But if I move the function "asd" into the "main" module and completely 
skip the "foo" module the assert passes.

I don't know if I'm thinking completely wrong here but this seems like a 
bug to me.

-- 
/Jacob Carlborg
Jul 10 2014
next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Thursday, 10 July 2014 at 20:27:39 UTC, Jacob Carlborg wrote:
 Here's a code example:

 module main;

 import foo;

 enum Get = "GET";

 void bar (string a)
 {
     assert(a is Get);
 }

 void main ()
 {
     asd();
 }

 module foo;

 import main;

 void asd()
 {
     bar(Get);
 }

 Running the above code will cause an assert error in the 
 function "bar". But if I move the function "asd" into the 
 "main" module and completely skip the "foo" module the assert 
 passes.

 I don't know if I'm thinking completely wrong here but this 
 seems like a bug to me.
No, this is equivalent to: void bar (string a) { assert(a is "GET"); } void asd() { bar("GET"); } Enums behave as if their values are copy-n-pasted everywhere they are used (you probably know that). The compiler probably conflates the two identical strings when they're in the same module. This is safe for immutable data. I'm sure there's something in the spec about it...
Jul 10 2014
next sibling parent reply simendsjo <simendsjo gmail.com> writes:
On 07/10/2014 10:47 PM, "Marc Schütz" <schuetzm gmx.net>" wrote:
 On Thursday, 10 July 2014 at 20:27:39 UTC, Jacob Carlborg wrote:
 Here's a code example:

 module main;

 import foo;

 enum Get = "GET";

 void bar (string a)
 {
     assert(a is Get);
 }

 void main ()
 {
     asd();
 }

 module foo;

 import main;

 void asd()
 {
     bar(Get);
 }

 Running the above code will cause an assert error in the function
 "bar". But if I move the function "asd" into the "main" module and
 completely skip the "foo" module the assert passes.

 I don't know if I'm thinking completely wrong here but this seems like
 a bug to me.
No, this is equivalent to: void bar (string a) { assert(a is "GET"); } void asd() { bar("GET"); } Enums behave as if their values are copy-n-pasted everywhere they are used (you probably know that). The compiler probably conflates the two identical strings when they're in the same module. This is safe for immutable data. I'm sure there's something in the spec about it...
Strings behaves a bit odd with is(). The following passes: import std.stdio; void f(string a, string b) { assert(a is b); // also true } void main() { string a = "aoeu"; string b = "aoeu"; assert(a is b); // true f(a, b); writeln("passed"); } changing a and b to enum gives the same results.
Jul 10 2014
next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Thursday, 10 July 2014 at 20:59:17 UTC, simendsjo wrote:
 Strings behaves a bit odd with is(). The following passes:

 import std.stdio;
 void f(string a, string b) {
     assert(a is b); // also true
 }
 void main() {
     string a = "aoeu";
     string b = "aoeu";
     assert(a is b); // true
     f(a, b);
     writeln("passed");
 }

 changing a and b to enum gives the same results.
Try other immutable variables (int arrays, structs), and non-immutable ones. They will probably behave differently.
Jul 10 2014
parent Jacob Carlborg <doob me.com> writes:
On 10/07/14 23:48, "Marc Schütz" <schuetzm gmx.net>" wrote:

 Try other immutable variables (int arrays, structs), and non-immutable
 ones. They will probably behave differently.
String literals are put directly in the executable and therefore should be the same. Array literals are dynamically allocated. -- /Jacob Carlborg
Jul 10 2014
prev sibling parent reply "sigod" <sigod.mail gmail.com> writes:
On Thursday, 10 July 2014 at 20:59:17 UTC, simendsjo wrote:
 Strings behaves a bit odd with is(). The following passes:

 import std.stdio;
 void f(string a, string b) {
     assert(a is b); // also true
 }
 void main() {
     string a = "aoeu";
     string b = "aoeu";
     assert(a is b); // true
     f(a, b);
     writeln("passed");
 }
```d import std.stdio; void f(string a, string b) { writeln("a: ", a.ptr, ", b: ", b.ptr); assert(a is b); // also true } void main() { string a = "aoeu"; string b = "aoeu"; writeln("a: ", a.ptr, ", b: ", b.ptr); assert(a is b); // true f(a, b); writeln("passed"); } ``` Output: ``` a: 4210A0, b: 4210A0 a: 4210A0, b: 4210A0 passed ``` Seems legit to me.
Jul 10 2014
parent simendsjo <simendsjo gmail.com> writes:
On 07/11/2014 01:08 AM, sigod wrote:
 On Thursday, 10 July 2014 at 20:59:17 UTC, simendsjo wrote:
 Strings behaves a bit odd with is(). The following passes:

 import std.stdio;
 void f(string a, string b) {
     assert(a is b); // also true
 }
 void main() {
     string a = "aoeu";
     string b = "aoeu";
     assert(a is b); // true
     f(a, b);
     writeln("passed");
 }
```d import std.stdio; void f(string a, string b) { writeln("a: ", a.ptr, ", b: ", b.ptr); assert(a is b); // also true } void main() { string a = "aoeu"; string b = "aoeu"; writeln("a: ", a.ptr, ", b: ", b.ptr); assert(a is b); // true f(a, b); writeln("passed"); } ``` Output: ``` a: 4210A0, b: 4210A0 a: 4210A0, b: 4210A0 passed ``` Seems legit to me.
I forgot to check for compiler optimizations (even without -O). immutable(int)[] a = [1]; immutable(int)[] b = [1]; assert(a is b); // fails as .ptr is different. So it looks like string literals is cached by the compiler and reused. Changing "aoeu" to 10.to!string for instance breaks this optimization. But the fact that immutable(char)[] behaves different from immutable(int)[] is a bit strange.
Jul 10 2014
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 10/07/14 22:47, "Marc Schütz" <schuetzm gmx.net>" wrote:

 No, this is equivalent to:

 void bar (string a)
 {
      assert(a is "GET");
 }

 void asd()
 {
      bar("GET");
 }

 Enums behave as if their values are copy-n-pasted everywhere they are
 used (you probably know that).
Yes, I was thinking that. Then I was thinking string literals are put directly in the executable and then I got confused about it behaving differently in out in a separate module.
 The compiler probably conflates the two identical strings when they're
 in the same module. This is safe for immutable data. I'm sure there's
 something in the spec about it...
Sounds reasonable. -- /Jacob Carlborg
Jul 10 2014
prev sibling parent reply "anonymous" <anonymous example.com> writes:
On Thursday, 10 July 2014 at 20:27:39 UTC, Jacob Carlborg wrote:
 Here's a code example:

 module main;

 import foo;

 enum Get = "GET";

 void bar (string a)
 {
     assert(a is Get);
 }

 void main ()
 {
     asd();
 }

 module foo;

 import main;

 void asd()
 {
     bar(Get);
 }

 Running the above code will cause an assert error in the 
 function "bar". But if I move the function "asd" into the 
 "main" module and completely skip the "foo" module the assert 
 passes.

 I don't know if I'm thinking completely wrong here but this 
 seems like a bug to me.
I don't think this is a bug. Remember that enums have copy-paste semantics. So, this is the same as comparing literals from different modules. Apparently, in the same module, a duplicate string literal is optimized out. But that's not done across the module boundary. I'd guess that's because of the separate compilation model.
Jul 10 2014
parent Jacob Carlborg <doob me.com> writes:
On 10/07/14 22:48, anonymous wrote:

 I don't think this is a bug.

 Remember that enums have copy-paste semantics. So, this is the
 same as comparing literals from different modules. Apparently, in
 the same module, a duplicate string literal is optimized out. But
 that's not done across the module boundary. I'd guess that's
 because of the separate compilation model.
That seems to be the case. I just got confused about the different behavior when put in a single or two modules. -- /Jacob Carlborg
Jul 10 2014