C is Brittle D is Plastic

H. S. Teoh hsteoh at qfbox.info
Tue Mar 24 15:41:59 UTC 2026


On Tue, Mar 24, 2026 at 03:25:29PM +0000, user1234 via Digitalmars-d wrote:
> On Tuesday, 24 March 2026 at 14:36:57 UTC, H. S. Teoh wrote:
[...]
> > In the beginning, D's symbol lookup mechanism was very simple and
> > straightforward: whenever an import statement is encountered,
> > symbols from an imported module are loaded and injected into the
> > symbol table at the current scope.  This is straightforward to
> > implement (you literally translate "import xyz" as parsing xyz and
> > adding its public symbols to the current scope's symbol table).
> > 
> > However, that led to counterintuitive behaviours like:
> > 
> > 	void main() {
> > 		myFunc("abc");
> > 	}
> > 	void myFunc(string text) {
> > 		writeln(text);	// prints "abc"
> > 		import std.conv;
> > 		writeln(text);	// prints ""
> > 	}
[...]
> I would not like to be rude and reopen old wounds but this looks more
> a problem of `text` being either a variable or a function and as D
> allows function calls without params to me it looks like it has never
> been a problem of lookup. Now imagine std.conv.text is a global
> variable. That does not change anything. Order of declaration matters
> in the local scope.

It's not about `text` being a function called without parens; it's about
an imported module hijacking symbols in the local scope.  The same
problem occurs in this situation:

```
	// xyz.d
	module xyz;
	static immutable text = "haha you got hijacked";

	// main.d
	module main;
	void main() {
		myFunc("abc");
	}
	void myFunc(string text) {
		writeln(text);	// prints "abc"

		import xyz;	// N.B.: we never imported `text` explicitly
		writeln(text);	// prints "haha you got hijacked"
	}
```

This is a problem because perhaps module xyz didn't declare `text` when
this code was written.  Then later on, upstream rewrote the
implementation and added a declaration of `text`.  Suddenly, unrelated
code in myFunc() has broken because its semantics silently changed from
under its carpet: the newly-added declaration of `text` in xyz has
hijacked the function parameter `text` in an unrelated module that just
happened to import it.

This is only one instance of the problem. Another instance concerns
*private* symbols in the imported module causing a conflict with a local
symbol in the importing module. (Remember, this is a logical consequence
of the simple and elegant concept that `import` simply injects symbols
into the local scope -- the injected symbols include private symbols.
Treating private symbols specially was one of the "inelegant" things
that complicated the implementation of imports, among other things.)


T

-- 
My stomach is flat. The L is just silent!


More information about the Digitalmars-d mailing list