www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 24451] New: Private imports can create conflicts with public

https://issues.dlang.org/show_bug.cgi?id=24451

          Issue ID: 24451
           Summary: Private imports can create conflicts with public
                    imports when using selective imports
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: issues.dlang jmdavisProg.com

Okay. This is a bit weird, but if we have

--- foo/bar.d ---
module foo.bar;

bool empty(T)(T[] arr)
{
    return arr.length == 0;
}
---

--- foo/package.d ---
module foo;

import baz;

public import foo.bar;
---

--- baz.d ---
module baz;

bool empty(T)(T[] arr)
{
    return arr.length == 0;
}
---

--- q.d ---
import foo : empty;

void main()
{
    int[] arr;
    auto result = arr.empty;
}
---

This results in
---
q.d(6): Error: `empty` matches conflicting symbols:
foo/bar.d(3):        function `foo.bar.empty!int.empty`
baz.d(3):        function `baz.empty!int.empty
---

If the import in q.d is changed to

import foo;

then the problem goes away. So, something about how the selective import works
makes it so that the symbols from the private import are in the overload set.

I don't know how likely it is for this situation to come up in practice is, but
the way that I ran into it was by trying to add the range API functions for
arrays to object.d to see what would happen. Unsurprisingly, there were a bunch
of symbol conflicts, but surprisingly, I couldn't fix the symbol conflicts with
selective imports from std.range, e.g.

import std.range : empty;

didn't fix anything. On the other hand, selective imports from
std.range.primitives _did_ resolve the conflicts, e.g.

import std.range.primitives : empty;

So, something about the public import was screwing up the selective import, and
the test case here is what I came up with. With empty being in object.d, it's
implicitly imported just like happens in the example here with baz being
explicitly imported.

In any case, I don't know how likely it is that this problem would come up
normally, but it _will_ affect any conflicts with symbols that we add to
object.d in the future, and it affects any symbols that are in there now. It's
just that it would only come up when public imports are involved, and they're
less common, though it will definitely cause problems if we ever add the
current range API functions to object.d.

--
Mar 25