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