Description
For the most part this looks good. If you'd prefer I can break this up into multiple issues.
Modules
...
The first two rules mean that there is a strict nesting: packages contain modules which contain libraries (which may contain parts).
It sounds, from the rest of the doc, like modules will largely (hopefully completely) negate the need for part files. As a result, I wonder whether we might consider removing part files in some future version of Dart, and if so whether we might want to discourage their use now by doing something like making it invalid for a module to contain more than one library if any of those libraries have parts. That's probably too strong a restriction, but you get the idea.
Also, what will it mean if a user opts a given library out of module support? Would that library still be in an implicitly named module? Would other libraries be able to be in the same module or be friends of the module?
Module names
...
Is this the right rule? What about dots in file names?
Dots in file and directory names can result in unintentionally having two libraries in the same module. Consider /lib/a.b/c.dart
and /lib/a/b.c.dart
. It probably isn't likely to happen, and I can't think of any solution that can't be subverted, but we might be able to reduce the probability by replacing the dots in the names with another character or by removing them. It isn't clear that it's worth the effort.
Module boundaries
It isn't explicit, but I assume that it's possible to explicitly use an implicit module name. That is, define a library A but don't specify a module name, then define a library B and explicitly put it in the module implicitly defined for A. That seems error prone and might be something we want to discourage if not disallow outright.
One way to disallow it is for libraries that don't explicitly specify a module name to be given a unique but opaque module name (that isn't necessarily expressible as a dotted name). No other libraries could be added to the module, but the names would never conflict.
Friend modules
I suspect that I'm not fully understanding this part of the proposal.
This appears to assume that libraries outside lib
can't be part of the same module as those inside lib
. While that makes sense, we might want to make that restriction explicit. For example, what about libraries defined in bin
?
Private identifiers in friend modules are visible to all libraries in both modules. Friendship is transitive. If module A is a friend of B which is a friend of C, then A, B, and C, all have access to each other's private identifiers.
I'm guessing that an identifier from a friend module is only in scope if the library that declares the identifier is imported. If that's not the case (and maybe even if it is), consider making the requirement more explicit.
But if that's true, then it raises a question. If a library La in A imports a library Lb in B, then Lb can't import La because that would violate the rule that modules can't have cycles. So what do you mean by "have access to each other's private identifiers"?
It is a compile-time error if multiple libraries in the same module have
friend
clauses.
That has some implications for compilers. They're basically required to figure out the module structure before they can finish generating diagnostics for any given library, even if that library is the only library in a dependency cycle.
@scheglov In case you didn't see this or the next item.
A module can only friend one other module. (But a module can be a friend of multiple other modules. Friendship forms a tree where all modules in the tree share the same private names.)
Aside from the compiler implications of needing to identify the friendship tree before resolving any of the code in any of the libraries in the tree, I'm a bit concerned about the usability implications here (assuming I understand this). If module B is a friend of A, and module C is a friend of A, then it would be possible for code in B to access private names in C, but I think that could be very confusing to users when there's no explicit reference from B to C in either direction.