Jump to page: 1 2 3
Thread overview
[frustration, sorry] Import conflict madness.
Jun 17, 2006
Deewiant
Jun 17, 2006
Derek Parnell
Jun 17, 2006
BCS
Jun 17, 2006
Sean Kelly
Jun 17, 2006
Derek Parnell
Jun 17, 2006
Deewiant
Jun 17, 2006
Chris Miller
Jun 17, 2006
Derek Parnell
Jun 18, 2006
Bruno Medeiros
Jun 18, 2006
Derek Parnell
OMG -- Re: [frustration, sorry] Import conflict madness.
Jun 18, 2006
Georg Wrede
Jun 18, 2006
kris
Jun 19, 2006
Bruno Medeiros
Jun 19, 2006
Bruno Medeiros
Jun 17, 2006
Sean Kelly
Jun 18, 2006
Bruno Medeiros
Jun 18, 2006
Sean Kelly
Jun 17, 2006
I hear ya
Jun 17, 2006
Tom S
June 17, 2006
You write your great soft in D. You're coding with smile because everything in seems to be so good. You added few new files, new classes. Porting your project from C++ to D seems to be so good idea. You type "make".

And then out of nowhere: BANG!!!

battle.d(31): import battle.map conflicts with cell.cell.map at
cell/cell.d(29)

GAME OVER!

You're stuck with this nothing telling you error message. You start wondering what is wrong. Imports probably, but ... why? It takes 15 minutes of frustrating checking your files. You seek help on #D irc channel (nice people BTW) - but they can not help you. They can only tell "It might be that in some unrelated file you are trying to use map without importing map but are importing files that do import map" which is great help but still will require you to spend great amount of time finding this place.

Please Walter - fix this. It is sooooooo frustrating and everyone confirms that. It's something that all D people hits once or more.
June 17, 2006
Dawid Ciężarkiewicz wrote:
> Imports probably, but ... why? It takes 15 minutes of frustrating checking your files. You seek help on #D irc channel (nice people BTW) - but they can not help you. They can only tell "It might be that in some unrelated file you are trying to use map without importing map but are importing files that do import map" which is great help but still will require you to spend great amount of time finding this place.
> 

Seems to me that using "private import" instead of "public import" (the default) might help in locating this. When using "private import A;" in a module B, any other module that imports B does not automatically import A.

I have long felt that private should be the default.
June 17, 2006
On Sun, 18 Jun 2006 03:49:44 +1000, Deewiant <deewiant.doesnotlike.spam@gmail.com> wrote:

> Dawid Ciężarkiewicz wrote:
>> Imports probably, but ... why? It takes 15 minutes of frustrating checking
>> your files. You seek help on #D irc channel (nice people BTW) - but they can
>> not help you. They can only tell "It might be that in some unrelated file you
>> are trying to use map without importing map but are importing files that do
>> import map" which is great help but still will require you to spend great
>> amount of time finding this place.
>>
>
> Seems to me that using "private import" instead of "public import" (the default)
> might help in locating this. When using "private import A;" in a module B, any
> other module that imports B does not automatically import A.
>
> I have long felt that private should be the default.

I have yet to find a *need* for public imports.

-- 
Derek Parnell
Melbourne, Australia
June 17, 2006
Derek Parnell wrote:
> On Sun, 18 Jun 2006 03:49:44 +1000, Deewiant  <deewiant.doesnotlike.spam@gmail.com> wrote:
[...]
>> Seems to me that using "private import" instead of "public import" (the  default) might help in locating this. When using "private 
>> import A;" in a module  B, any other module that imports B does
>> not automatically import A. I have long felt that private should 
>> be the default.
>  I have yet to find a *need* for public imports.
> 

A single-point-of-access module for a lib might count as a use. OTOH I have taken to doing all imports as private.

import myBigLib;

<code file="myBigLib.d>
public import theFirstFile;
public import theSecondFile;
public import theThirdFile;
...
</code>
June 17, 2006
Here's a simple example of the issue:


// -- foo.d --
private import std.stdio;


// -- bar.d --
private import std.stdio;


// -- test.d --

import foo, bar;

void main()
{
    char[] hi = std.string.toString(3);
}


DMD 0.160:
   foo.d(1): import foo.std conflicts with bar.std at bar.d(1)


Of course, the code in test.d is a mistake, but look how unhelpful the error message is. It will blame a library's code for a mistake the library-user made.

Also notice that it's considering *private* imports, which shouldn't even be available to test.d.
June 17, 2006
Dawid Ciężarkiewicz wrote:
> You write your great soft in D. You're coding with smile because everything
> in seems to be so good. You added few new files, new classes. Porting your
> project from C++ to D seems to be so good idea. You type "make".
> 
> And then out of nowhere: BANG!!!
> 
> battle.d(31): import battle.map conflicts with cell.cell.map at
> cell/cell.d(29)

For what it's worth, the symbol resolution rules styled after the C++ class-scope rules.  On the surface, this does seem to provide solid support for the approach: it's a sticky issue and an established language has solved the problem this way, so why not do that?  However, I think the reasons that this rule was chosen for C++ may be related to language syntax that D simply doesn't have, thus reducing the strength of the correlation.

I decided to go looking for information on why the C++ rules are the way they are, and oddly enough the first hit was the C++ Module proposal (available here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1964.pdf) Section 4.3 reads thus:

  4.3 Shielding from private members

  The fact that private members are inaccessible but not invisible
  regularly surprises incidental programmers. Like macros, seemingly
  unrelated declarations interfere with subsequent code. Unfortunately,
  there are good reasons for this state of affair: Without it, private
  out-of-class member declarations become impractical to parse in the
  general case.

  Module namespaces appear to be an ideal boundary for making the
  private member fully invisible: Within the module the implementer has
  full control over naming conventions and can therefore easily avoid
  interference, while outside the module the client will never
  have to implement private members. (Note that this also addresses the
  concerns of N1602 "Class Scope Using Declarations & private Members"
  by Francis Glassborow; the extension proposed therein is then no
  longer needed.)

It's worth noting that the issue discussed in the first paragraph: out-of-class declarations, is not supported in D.  All members must be declared in class scope.  The second paragraph goes on to make an argument for why private symbols should not be considered across modules for lookup resolution.  The only issue not addressed is package visibility, but I believe the same approach could be done at the package level as at the module level.  After all, there's a file separation either way.

I was unable to find older discussions relating why these rules were chosen for C++, but if there are other arguments against the approach which apply to D, either for current or future features, I would love to hear them.  The current state of affairs is annoying and somewhat confusing to new users, but I'd prefer an annoying system that works for all corner-cases to a cleaner one that doesn't.


Sean
June 17, 2006
Deewiant wrote:

> Dawid Ciężarkiewicz wrote:
>> Imports probably, but ... why? It takes 15 minutes of frustrating checking your files. You seek help on #D irc channel (nice people BTW) - but they can not help you. They can only tell "It might be that in some unrelated file you are trying to use map without importing map but are importing files that do import map" which is great help but still will require you to spend great amount of time finding this place.
>> 
> 
> Seems to me that using "private import" instead of "public import" (the default) might help in locating this. When using "private import A;" in a module B, any other module that imports B does not automatically import A.

I'm not that sure about that. This might be an oversimplified case, but I
think the problem comes up, when (A,B,C,D are modules here) B and C
(privately) import A, and D imports both B and C. Now DMD regards function
foo() in module A as B.foo() and C.foo() through the import chains. When D
imports both B and C and a name conflict comes up, since they can't both
become D.foo().

Ok, how do we fix this problem? A proper way to handle these would be IMO to save full info about the symbols and their origins in the symbol table. I'm not a compiler writer and haven't had much time to find out how this is done at the moment. But as a workaround you can (private) import B in module C. After that there's only one route to the symbol source.


> I have long felt that private should be the default.

Yes. But imports should work properly, too.

-- 
Jari-Matti
June 17, 2006
Derek Parnell wrote:
> 
> I have yet to find a *need* for public imports.

I have.  Implementing C headers it's common for an alias to be declared in one header that must be visible in other headers.  Sure, you could require the user to manually import both headers, but that's non-intuitive and a tad annoying.  And the alternative (private import combined with aliasing symbols to expose them piecemeal) results in symbol collision problems.


Sean
June 17, 2006
Chris Miller wrote:

> Here's a simple example of the issue:
> 
> 
> // -- foo.d --
> private import std.stdio;
> 
> 
> // -- bar.d --
> private import std.stdio;
> 
> 
> // -- test.d --
> 
> import foo, bar;
> 
> void main()
> {
>      char[] hi = std.string.toString(3);
> }
> 
> 
> DMD 0.160:
>     foo.d(1): import foo.std conflicts with bar.std at bar.d(1)
> 
> 
> Of course, the code in test.d is a mistake, but look how unhelpful the error message is. It will blame a library's code for a mistake the library-user made.
> 
> Also notice that it's considering *private* imports, which shouldn't even be available to test.d.

The compiler should say something like "function module1.foo is private and thus cannot be used in module2", when it's not accessible.

The annoying thing is that when there's a function name conflict and the first conflicting function is privately imported and the other is publicly imported, the public version does not override the private one. And when the same symbol is imported using 2+ import routes, there's the same old bogus naming conflict again.

-- 
Jari-Matti
June 17, 2006
Dawid Ciężarkiewicz wrote:
> And then out of nowhere: BANG!!!
> 
> battle.d(31): import battle.map conflicts with cell.cell.map at
> cell/cell.d(29)

OK. After some time I've finally discovered where the problem was and I see that my previous post is not very informative. Instead it gives good look how such "details" can frustrate people.

The problem is (if I understand right):
When you use identifier which was imported privately by something you
imported in current module you get this missleading "import X conficts with
Y" instead of info where it happens.

battle.d(31) == "private import map";
cell/cell/d(29) == "private import map";

As you can see your IDE will take you to battle.d, line 31 and you'll be confused. You don't know which line of code triggered error. If you are lucky and smart enough, you'll try fixing later errors and find which part of the code triggered this one. If you're not - you'll be siting and screaming knowing not what to do.

The good error msg would look like:

$file($line): triggered import conflict with X ($X:$Xline) and Y ($Y:$Yline)

Where $file($line) is place where compiler found that this two modules are conflicting. This would be quite informative IMO.

Another thing is that I do "private import $i" for purpose - I don't want names from module be _anyhow_ visible - not triggering any conflicts.
« First   ‹ Prev
1 2 3