November 30, 2012
On Friday, 30 November 2012 at 01:07:57 UTC, Andrei Alexandrescu wrote:
> I think we either do it right or leave it as it is. It's not like there's no workaround so if we take a stand here we better have something compelling.
>
> Andrei

Finally some sanity here !
November 30, 2012
On Thursday, November 29, 2012 20:07:57 Andrei Alexandrescu wrote:
> I think we either do it right or leave it as it is. It's not like there's no workaround so if we take a stand here we better have something compelling.

I think that an attribute per static constructor indicating that it had no circular dependencies would solve the problem just fine (putting it on the module is problematic, because new static constructors which _do_ have actual circular dependencies could be added), but we certainly want to be sure of this before doing it.

And if we want to focus on shared or whatever now because it's higher priority, that's fine, but we do need to move forward with outstanding issues like these, and I do think that really need to solve this particular problem rather than considering the workarounds to be okay. A situation where static constructors effectively must be shunned because of the problems that they cause is definitely problematic considering how many features require them (e.g. a const or immutable static variable). And that's what we have right now.

- Jonathan M Davis
November 30, 2012
Walter Bright wrote:

> yes, it is ambiguous, but it is not an error.
> One gets picked arbitrarily.

I did not see that it would not be erroneous. But if it is true, then I do not see a sense in manually adding pragmas: they can be assumed to exist.

-manfred




November 30, 2012
Timon Gehr wrote:

> what module reflect imposes

Thank you.

It seems to be true then, that no issue would be generated if the compiler assumes, that Walters pragma is existent in every module.

-manfred
November 30, 2012
On Friday, November 30, 2012 03:10:57 Manfred Nowak wrote:
> Timon Gehr wrote:
> > what module reflect imposes
> 
> Thank you.
> 
> It seems to be true then, that no issue would be generated if the compiler assumes, that Walters pragma is existent in every module.

So, you're suggesting that the runtime should just not worry about circular dependencies between modules at all? What if you have something like

module a;
import b;

immutable Foo foo;
shared static this()
{
 foo = new immutable(Foo)(bar);
}

module b;
import a;

immutable Bar bar;
shared static this()
{
 bar = new immutable(Bar)(foo);
}

That's a true circular dependency. It's a big problem if that's allowed. D rightly disallows it. The problem is that in the vast majority of cases, there is no such circular dependency, so the circular dependency detection disallows many valid use cases.

Or do you mean something else by the suggestion that the existence of Walter's pragma can be assumed? I don't know what else you could mean other than suggesting that assuming that it's present in all modules which is the same as throwing away circular dependency detection entirely.

- Jonathan M Davis
November 30, 2012

On 11/29/2012 5:51 PM, Max Samukha wrote:
> On Thursday, 29 November 2012 at 15:18:11 UTC, Paulo Pinto wrote:
>>
>> Maybe you care to provide an example?
>>
>
> The general problem is constructing global data structures based on data
> introspected at compile-time.
>
> My specific problem is extending scarce runtime type information
> provided by the language with something usable for runtime reflection.
> With lots of detail omitted:
>
> module reflect;
>
> Meta[string] metas;
> mixin template Reflect(alias object) {
>      static this()
>      {
>          auto m = meta!(object);
>          metas[m.fullName] ~= m;
>      }
> }
>
>
> module a;
> import reflect;
>
> struct S
> {
> }
> mixin Reflect!S;
>
> The meta-object for S is automatically made available at runtime through
> the global metas array. Note that we do not want to force the user to
> register the meta-object manually because then it would not be a "better
> architecture".
>
> The important (Andrei somehow thinks it is not) requirement is there
> must not be circular dependency issues for the users of the "reflect"
> module.
>

How about running your own set of "constructors" searching the module info array, searching for specific classes in the module that are added by a mixin:

----------------------------------
module register;

RegisterBase[string] registry;

void doRegister(string name, RegisterBase r) { registry[name] = r; }

class RegisterBase
{
	abstract void _register();
}

template Register(string name)
{
	enum string Register = "
	class Register : RegisterBase
	{
		override void _register() { doRegister(\"" ~ name ~ "\", this); }
	}
	";
}

void registerAll()
{
	foreach(m; ModuleInfo)
	{
		TypeInfo_Class[] clss = m.localClasses();
		foreach(c; clss)
		{
			if(c.base is RegisterBase.classinfo)
			{
				if(auto reg = cast(RegisterBase) c.create())
				{
					reg._register();
				}
			}
		}
	}
}


-----------------------
module a;
import register;

mixin(Register!"a");

-----------------------
module main;
import std.stdio;
import register;

void main()
{
	registerAll();
	foreach(a, o; registry)
		writeln(a, " ", o);
}

This might also work for the benchmark module.
November 30, 2012
On 2012-11-29 22:43, Jonathan M Davis wrote:

> They just let you blow your foot off. All static variables can be directly
> initialized at runtime, so it's easy to use variables before they're actually
> initialized. I don't know how they decide what order to run static
> constructors in, but AFAIK, it never worries about circular dependencies.
> We're only running into this problem beacuse we're trying to provide higher
> safety and better guarantees with regards to when and how variables are
> initialized.

I see.

-- 
/Jacob Carlborg
November 30, 2012
On 11/29/12 23:34, Jonathan M Davis wrote:
> On Thursday, November 29, 2012 23:28:07 Timon Gehr wrote:
>> On 11/29/2012 01:17 PM, Jonathan M Davis wrote:
>>> In the past when I've brought up similar solutions, he's been completely opposed to them. ...
>>
>> It is not a solution, it is a workaround.
> 
> What do you mean? The runtime sees circular dependencies between modules even when there's no actual circular dependency between static constructors. We need to fix that. One way is to just make the runtime not care, which wouldn't be particularly safe. Another is to explicitly tell it that there are no such dependencies. I don't see how that's not a solution. And unless someone can come up with a way for the runtime to somehow determine on its own that there's no actual, circular dependency, I don't see how anything better could be done.

It's relatively easy for the /compiler/ to figure it out; it's just that
implementing a simple user-provided flag requires the least amount of work.
What Walter suggested can be tweaked to be sane (per-ctor flag) and will
still be useful if/when the compiler becomes smarter (think lazily initted
module fields).
For the compiler to check if the value of every imported symbol accessed
inside a mod-ctor can be evaluated at compile-time (if you encounter a case
where this is not true it means there (potentially) is a true dependency and
the ctors should be ordered) would require more work.

artur
November 30, 2012
On Friday, 30 November 2012 at 01:07:57 UTC, Andrei Alexandrescu wrote:
> On 11/29/12 5:43 PM, Walter Bright wrote:
>> On 11/30/2012 12:09 AM, Daniel Murphy wrote:
>>> I don't think this is sufficient. Imagine a group of modules that really
>>> _do_ have a cyclic dependency, and a mixin that adds an independent
>>> static
>>> this. Ideally you'd be able to mark the mixed-in constructor as
>>> independent
>>> without tainting the whole module.
>>>
>>> So just make the pragma apply to declarations, you either mark specific
>>> functions (which can then be mixed in) or put `pragma(...):` at the
>>> top of
>>> your module and you get your behaviour.
>>
>> It is possible for each static constructor to specify independently of
>> the other static constructors which imports must be constructed first.
>> But do we really want to go that far?
>
> I think we either do it right or leave it as it is. It's not like there's no workaround so if we take a stand here we better have something compelling.
>
> Andrei

+1

FWIW, I think this proposal sounds like a massive hack. Not a fan.
November 30, 2012
On 11/30/2012 9:05 PM, Peter Alexander wrote:
> On Friday, 30 November 2012 at 01:07:57 UTC, Andrei Alexandrescu wrote:
>> I think we either do it right or leave it as it is. It's not like
>> there's no workaround so if we take a stand here we better have
>> something compelling.
>>
>> Andrei
>
> +1
>
> FWIW, I think this proposal sounds like a massive hack. Not a fan.

Andrei has a point.