[Issue 17548] New: Forward reference error with scope function parameters

2017-06-24 Thread via Digitalmars-d-bugs
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")

2017-06-24 Thread via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=17547

Alexandre Bléron  changed:

   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")

2017-06-24 Thread via Digitalmars-d-bugs
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

2017-06-24 Thread via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=17545

Vladimir Panteleev  changed:

   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

2017-06-24 Thread via Digitalmars-d-bugs
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

2017-06-24 Thread via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=17545

Ketmar Dark  changed:

   What|Removed |Added

 CC||ket...@ketmar.no-ip.org

--


[Issue 17545] [REG2.072] __traits(getAttributes, name) evaluates name to value prematurely

2017-06-24 Thread via Digitalmars-d-bugs
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

2017-06-24 Thread via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=17546

Ketmar Dark  changed:

   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

2017-06-24 Thread via Digitalmars-d-bugs
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

2017-06-24 Thread via Digitalmars-d-bugs
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

2017-06-24 Thread via Digitalmars-d-bugs
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

2017-06-24 Thread via Digitalmars-d-bugs
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

2017-06-24 Thread via Digitalmars-d-bugs
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

2017-06-24 Thread via Digitalmars-d-bugs
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

2017-06-24 Thread via Digitalmars-d-bugs
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

2017-06-24 Thread via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=17543

ZombineDev  changed:

   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

2017-06-24 Thread via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=17543

ZombineDev  changed:

   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

2017-06-24 Thread via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=17544

Iain Buclaw  changed:

   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

2017-06-24 Thread via Digitalmars-d-bugs
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()
  {
  }
}
---

--