[Issue 17548] New: Forward reference error with scope function parameters
https://issues.dlang.org/show_bug.cgi?id=17548 Issue ID: 17548 Summary: Forward reference error with scope function parameters Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: major Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: syniu...@gmail.com //-fwdref1.d-- // import fwdref2; struct S1 { void foo(scope S2 arg) {} int myField; } enum cnst = 4321; import fwdref2; //-fwdref2.d-- import fwdref1; struct S2 { void bar(int arg = .fwdref1.cnst) {} S1 s; } // $ dmd fwdref1.d fwdref2.d(3): Error: struct fwdref2.S2 has forward references The error disappears if "scope" is removed from fwdref1.d, or if the first dot in ".fwdref1.cnst" i.e the module scope operator is removed. What seems to happen: - in TypeFunction.semantic for S1.foo, the right hand of if (fparam.storageClass & STCscope && !fparam.type.hasPointers()) gets evaluated. - hasPointers() calls .size() on S2 which then calls .determineSize() - S2 having _scope set, .determineSize() calls StructDeclaration.semantic() on S2 - the default argument of S2.bar() gets semantic'd(), and DsymbolExp.resolve() calls semantic() on the fwdref2 module - since fwdref2.semanticRun is still at PASSinit, Module.semantic() calls semantic() for each of its members, including S2 - S2 doesn't have _scope set anymore, scx remains null, so StructDeclaration.semantic() ends with: else if (symtab && !scx) { semanticRun = PASSsemanticdone; return; } (while we're clearly not done, the first call is ongoing) - back to the first semantic() call on S2, after determineFields() it then checks that for every field with a struct type, the struct symbol is at PASSsemanticdone. But since S1 is still at PASSsemantic, it hits: _scope = scx ? scx : sc.copy(); _scope.setNoFree(); _scope._module.addDeferredSemantic(this); //printf("\tdeferring %s\n", toChars()); return; - so now S2 has _scope set yet is at PASSsemanticdone. The deferred semantic() call returns immediately, and then semantic2() greets S2 with our error: if (_scope) { error("has forward references"); return; } Sorry if this a little too detailed. I'm not entirely sure what the proper fix is. Is Module.semantic() always supposed to get called before any semantic-ing of its members? (this would have prevented "." from disrupting StructDeclaration.semantic()'s assumptions) Placing "import fwdref2;" on top also produces an error, but a different one: "struct fwdref2.S2 no size because of forward reference". --
[Issue 17547] Compile-time map!(...) fails to compile inside a struct when using lambdas ("this.__lambda1 has no value")
https://issues.dlang.org/show_bug.cgi?id=17547 Alexandre Bléronchanged: What|Removed |Added Hardware|x86 |x86_64 Severity|enhancement |normal --
[Issue 17547] New: Compile-time map!(...) fails to compile inside a struct when using lambdas ("this.__lambda1 has no value")
https://issues.dlang.org/show_bug.cgi?id=17547 Issue ID: 17547 Summary: Compile-time map!(...) fails to compile inside a struct when using lambdas ("this.__lambda1 has no value") Product: D Version: D2 Hardware: x86 OS: Windows Status: NEW Severity: enhancement Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: alex.ble...@gmail.com The following code fails to compile: // https://dpaste.dzfl.pl/2573f6fb2ff5 import std.algorithm : map; import std.array : join; struct Test { pragma(msg, ["a", "b", "c", "d"].map!(a => a).join("\n")); } Compiler output: src/phobos/std/algorithm/iteration.d(455): Error: this.__lambda1 has no value 6 : Error: CTFE failed because of previous errors in map 6 : called from here: join(map(["a", "b", "c", "d"]), "\x0a") 6 : while evaluating pragma(msg, join(map(["a", "b", "c", "d"]), "\x0a")) Compilation failed Expected compiler output: a b c d --- This code also fails (replacing the lambda with a function literal): import std.algorithm : map; import std.array : join; struct Test { // std/algorithm/iteration.d(455): Error: this.__funcliteral1 has no value pragma(msg, ["a", "b", "c", "d"].map!(function (a) { return a; }).join("\n")); } --- However, this works: import std.algorithm : map; import std.array : join; struct Test { pragma(msg, ["a", "b", "c", "d"].map!("a").join("\n")); } --- And this works too: import std.algorithm : map; import std.array : join; struct Test { pragma(msg, ["a", "b", "c", "d"].map!(function string(string a) { return a; }).join("\n")); } --
[Issue 17545] [REG2.072] __traits(getAttributes, name) evaluates name to value prematurely
https://issues.dlang.org/show_bug.cgi?id=17545 Vladimir Panteleevchanged: What|Removed |Added CC||dlang-bugzilla@thecybershad ||ow.net --- Comment #3 from Vladimir Panteleev --- Introduced in https://github.com/dlang/dmd/pull/5588 --
[Issue 17545] [REG2.072] __traits(getAttributes, name) evaluates name to value prematurely
https://issues.dlang.org/show_bug.cgi?id=17545 --- Comment #2 from monkeywork...@hotmail.com --- If you don't want to modify the enum the following code also seems to work. The main thing is to avoid using __traits(getMember) which could get passed a non-symbol. module example; import std.meta: staticIndexOf; import std.traits; struct Attrib {} @Attrib enum TEST = 123; void foo() { foreach(sym; getSymbolsByUDA!(example, Attrib)) { pragma(msg, sym.stringof); //Prints 123 } } The fact that it prints 123 instead of TEST seems to suggest that it is indeed a problem with the compiler pasting the value where the identifier is used. I'd recommend taking a look at the implementation of getSymbolsByUDA to see how it's done there. --
[Issue 17545] [REG2.072] __traits(getAttributes, name) evaluates name to value prematurely
https://issues.dlang.org/show_bug.cgi?id=17545 Ketmar Darkchanged: What|Removed |Added CC||ket...@ketmar.no-ip.org --
[Issue 17545] [REG2.072] __traits(getAttributes, name) evaluates name to value prematurely
https://issues.dlang.org/show_bug.cgi?id=17545 monkeywork...@hotmail.com changed: What|Removed |Added CC||monkeywork...@hotmail.com --- Comment #1 from monkeywork...@hotmail.com --- This code is *supposed* to be equivalent as far as I know, but it actually fixes the issue. Change `@Attrib enum TEST = 123` to `@Attrib enum TEST { val = 123; }` and it will compile (you can also make it immutable; basically anything that introduces an actual symbol). I think it's because the compiler does not even see the enum; the symbol TEST is replaced with the actual value at the usage site so it's like you're doing `pragma(msg, __traits(getAttributes, 123))`, which of course doesn't make any sense. --
[Issue 17546] Cannot call .stringof on a function symbol if it does not have a no-args overload
https://issues.dlang.org/show_bug.cgi?id=17546 Ketmar Darkchanged: What|Removed |Added CC||ket...@ketmar.no-ip.org --
[Issue 17546] New: Cannot call .stringof on a function symbol if it does not have a no-args overload
https://issues.dlang.org/show_bug.cgi?id=17546 Issue ID: 17546 Summary: Cannot call .stringof on a function symbol if it does not have a no-args overload Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: normal Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: monkeywork...@hotmail.com int test() { return 0; } void main() { pragma(msg, test.stringof); } It seems that the only way to make this work is add a no-args overload of `test`. It still seems that something weird is going on if I do that, however: int test() { return 0; } void main() { //Prints "test()" pragma(msg, test.stringof); } Currently I am resorting to a hacky workaround by doing `().stringof[2..$]`. --
[Issue 17543] __gshared block modifier is ignored by static variables
https://issues.dlang.org/show_bug.cgi?id=17543 --- Comment #5 from ZombineDev--- Just a tip: it's useful to encode such assumptions about how your code works by using 'static assert'. For example: class Test { int instanceMember; __gshared int globalGSharedMember; static int threadLocalStaticMember; static int globalSharedMember; } import std.traits : hasStaticMember; static assert (!hasStaticMember!(Test, "instanceMember")); static assert ( hasStaticMember!(Test, "globalGSharedMember")); static assert ( hasStaticMember!(Test, "threadLocalStaticMember")); static assert ( hasStaticMember!(Test, "globalSharedMember")); --
[Issue 17545] [REG2.072] __traits(getAttributes, name) evaluates name to value prematurely
https://issues.dlang.org/show_bug.cgi?id=17545 johanenge...@weka.io changed: What|Removed |Added Summary|[REG2.072] |[REG2.072] |__traits(getMember, mod,|__traits(getAttributes, |name) evaluates enum to |name) evaluates name to |value prematurely |value prematurely --
[Issue 17543] __gshared block modifier is ignored by static variables
https://issues.dlang.org/show_bug.cgi?id=17543 --- Comment #4 from ZombineDev--- (In reply to Robert Luger from comment #3) > This works though: > > > import std.stdio, std.parallelism; > > > __gshared: > > > auto return_gshared(){ > > class Test { > bool set; > } > > return new Test(); > > } > > > void main(){ > auto obj = return_gshared(); > auto t = { obj.set = true; }.task; > t.executeInNewThread; > t.spinForce; > writeln(obj.set); > } __gshared has no effect in the program above (e.g. commenting it out doesn't change the result). That's because the variable 'obj' of type 'Test' is shared by both the main thread and the thread on which the task is executed. One simple test to verify if a class/struct member is effectively 'static' (i.e. shared by all instances of the current thread, or all threads (if it's declared as either '__gshared' or 'static shared') is to check if: * It has the 'offsetof' property, or * If it can be accessed with the 'Type.staticMember' sytnax (which is what I think effectively http://dlang.org/phobos/std_traits#hasStaticMembery does) __gshared: auto return_gshared(){ class Test { bool set; } pragma (msg, __traits(compiles, { size_t offset = Test.set.offsetof; })); // true pragma (msg, Test.set.offsetof); // 16LU pragma (msg, __traits(compiles, { auto copyOfStaticVariable = Test.set; })); // false return new Test(); } --
[Issue 17545] [REG2.072] __traits(getMember, mod, name) evaluates enum to value prematurely
https://issues.dlang.org/show_bug.cgi?id=17545 johanenge...@weka.io changed: What|Removed |Added Keywords||industry --
[Issue 17545] New: [REG2.072] __traits(getMember, mod, name) evaluates enum to value prematurely
https://issues.dlang.org/show_bug.cgi?id=17545 Issue ID: 17545 Summary: [REG2.072] __traits(getMember, mod, name) evaluates enum to value prematurely Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: regression Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: johanenge...@weka.io The following code used to compile with DMD 2.071, but fails for >=2.072. ``` module example; import std.meta: staticIndexOf; struct Attrib {} @Attrib enum TEST = 123; pragma(msg, __traits(getAttributes, __traits(getMember, example, "TEST"))); ``` --
[Issue 17543] __gshared block modifier is ignored by static variables
https://issues.dlang.org/show_bug.cgi?id=17543 --- Comment #3 from Robert Luger--- This works though: import std.stdio, std.parallelism; __gshared: auto return_gshared(){ class Test { bool set; } return new Test(); } void main(){ auto obj = return_gshared(); auto t = { obj.set = true; }.task; t.executeInNewThread; t.spinForce; writeln(obj.set); } --
[Issue 17543] __gshared block modifier is ignored by static variables
https://issues.dlang.org/show_bug.cgi?id=17543 ZombineDevchanged: What|Removed |Added Status|NEW |RESOLVED Hardware|x86 |All Resolution|--- |INVALID OS|Windows |All --- Comment #2 from ZombineDev --- I'll close this bug as there's nothing specific to __gshared, but of course you're free to open a discussion on the newsgroup and to propose a way to control this. I have an idea for a DIP (D improvement proposal) on that matter, but no promises when I'll have enough time to sit down, write it down and submit it. --
[Issue 17543] __gshared block modifier is ignored by static variables
https://issues.dlang.org/show_bug.cgi?id=17543 ZombineDevchanged: What|Removed |Added CC||petar.p.ki...@gmail.com --- Comment #1 from ZombineDev --- All attributes (e.g. public/private, pure/nothrow/@safe/@nogc, const/shared, final, __gshared, and so on) are applied only to the scope they are declared in. As soon as you open a new scope they are effectively reset. --
[Issue 17544] Versions derived from predefined versions not reserved
https://issues.dlang.org/show_bug.cgi?id=17544 Iain Buclawchanged: What|Removed |Added CC||ibuc...@gdcproject.org --- Comment #1 from Iain Buclaw --- On an implementation note, VersionCondition.isReserved() could probably be cleaned up a little more by implementing this. Assuming that it ends up being similar to how the "D_*" versions are checked, but a bit more generic, the following could be removed from the list: ARM_*, PPC_*, MIPS_*, SPARC_*, Alpha_*. --
[Issue 17544] New: Versions derived from predefined versions not reserved
https://issues.dlang.org/show_bug.cgi?id=17544 Issue ID: 17544 Summary: Versions derived from predefined versions not reserved Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: normal Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: ibuc...@gdcproject.org The documentations says (emphasis on the last sentence): --- It is inevitable that the D language will evolve over time. Therefore, the version identifier namespace beginning with "D_" is reserved for identifiers indicating D language specification or new feature conformance. Further, all identifiers derived from the ones listed above by appending any character(s) are reserved. This means that e.g. ARM_foo and Windows_bar are reserved while foo_ARM and bar_Windows are not. --- However, this code compiles, which seems contrary to the spec. --- version = ARM_foo; version = Windows_bar; version (ARM_foo) { void foo() { } } version (Windows_bar) { void bar() { } } --- --