Pathological import symbol shadowing

Timon Gehr timon.gehr at gmx.ch
Wed Nov 18 01:28:41 UTC 2020


On 18.11.20 02:11, Walter Bright wrote:
> On 11/15/2020 6:24 AM, Timon Gehr wrote:
>> Straw man.
> 
> Doing "import std;" is just asking for trouble. I argued against it for 
> years, and yet it was slipped in a few months ago without my knowledge. 
> Having everything in Phobos in scope is just causing trouble. For just 
> one of the problems, it prevents adding new modules to Phobos as it can 
> break existing code. For another, it turns the world's fastest compiler 
> into a pig.
> 
> The example given was another example of why it's a bad idea, as the 
> more names there are the more the likelihood of a collision.
> ...

There is no collision with proper overload resolution. The error is 
spurious.

>> I think it's safe to say that the snippet was written to illustrate a 
>> point and to focus on anything else to the detriment of a discussion 
>> of that point is just deflection.
> 
> Teoh would have never run into this issue if he hadn't used import std;
> 

I'm not so sure, it's likely that one would import both std.stdio and 
std.file as in my example below.

> I don't blame Teoh, a user should expect that import std; should not 
> cause problems although the problems are inevitable. It should NEVER 
> have been added to Phobos.
> ...

It's useful for scripting and, apparently, for exposing bugs in name 
lookup and overload resolution.

>> If the language was working properly, the code would compile and run 
>> fine. There is a hole in the design of the language here. There's no 
>> need to prioritize this particular issue, but I don't understand why 
>> you don't just acknowledge that this is not how the compiler should 
>> behave in this situation.
> 
> Frankly, I don't know how the compiler should behave. The original 
> import scheme was simple, sound, and easy to explain, but everyone 
> complained it wasn't "intuitive" and put in a complex scheme full of 
> special cases. Complex special cases produce an endless stream of 
> unanticipated special cases.
> ...

I don't think that's what happened in this case. There is the original 
simple, sound, easy to explain import scheme, but for mysterious reasons 
it was _never applied_ to nested imports. Why not?

What kinds of special cases have been added, by the way?

> Altering how the compiler does lookups now, regardless of how it 
> "should" behave, could break existing code in mysterious ways. 
> Especially if one imports every symbol in existence into a local scope :-(
> ...

I think that's not true in this case. (As I know you are aware, 
hijacking protection is designed precisely to avoid breaking code in 
mysterious ways!)

> 
>> It's not just rejects-valid either, this issue has accepts-invalid cases:
>>
>> ---
>> import std.stdio;
>>
>> string readAndLog(string filename){
>>      import std.file;
>>      auto text=readText(filename);
>>      write(filename," read successfully!\n");
>>      return text;
>> }
>>
>> void main(){
>>      writeln(readAndLog("important_data.txt"));
>> }
>> ---
> 
> Please elaborate on what is invalid about it? Don't make me guess!

It's a prototypical example of symbol hijacking. std.file.write hides 
std.stdio.write. Therefore, the code above overwrites the contents of 
the file "important_data.txt" with the string " read sucessfully!\n". 
The code should result in an ambiguity error as there are matches in two 
distinct overload sets.

I think it's explained in the issue I linked.


More information about the Digitalmars-d mailing list