C++ Logo

sg15

Advanced search

Re: [isocpp-core] unimported implementation partitions

From: Herring, Davis <herring_at_[hidden]>
Date: Wed, 8 Jun 2022 22:51:24 +0000
> Reachability, scope of declaration and linkage of an internal
> partition (i.e.: the file with `module foo:bar`) is the same as with
> interface partitions (the only difference being that it can't
> contribute to the external interface).

Reachability affects what imports you, which is trivially the empty set for a non-partition implementation unit (a "normal module unit"). Whatever scope means here, it's also the same in a normal module unit, and translation units don't have linkage at all.

> So it's a bit more than "gain the ability to be imported", the
> semantics of the declarations are very different than the semantics of
> declarations in a module implementation unit (i.e.: the file with
> `module foo`).

That's not what "module implementation unit" means, but it is what I called a "normal module unit" above.

> The feeling I have is that folks wanted to create a symmetry matching
> what we see in the .h/.cpp pairs of files, where you would have the
> module interface units (primary and partition) be the equivalent of
> the header, and the module implementation units (including internal
> partitions) to be the equivalent of the .cpp files. And the wording
> seems to attempt to communicate something like that.

I think it's rather that two syntactically orthogonal properties were observed (implementation vs. interface and partition vs. not) and named separately. It's probably not a good way to teach things, but it's not news that the standard isn't a tutorial.

> The distinction between the interface units (primary and partitions)
> and the internal partition is more akin to "public" and "private"
> headers. The internal partition is declaring things to be used in
> other translation units, and it doesn't really contribute to the
> module if it's not imported anywhere.

...Unless it provides definitions for entities declared elsewhere. That might be a weird use of the technology, but it's not invalid.

> In other words. The grouping we can make is that we have "importable
> units", with primary interface, interface partition and internal
> partitions (and header units), and then we have "implementation units"
> as a separate group.

Certainly you can and should talk about importable translation units, but implementation units are not the (relative) complement of that set.

> ```
> module m:interfacepart;
> export void foo();
> ```
>
> ```
> module m:part1;
> void foo() {};
> ```
>
> ```
> export module m;
> import m:part1;
> export import m:interfacepart;
> ```
>
> You actually have an ill-formed program because "An exported
> redeclaration of a non-exported declaration of an entity is
> ill-formed." (10.2.6)

Supplying the missing 'export' at the beginning of the first of these three, the violation is rather that foo is declared with inconsistent linkage. Unfortunately, we don't actually forbid this case properly: [basic.link]/8 fails to unify them because they have different linkage, so [dcl.stc]/6 fails to catch them. (Jens: as soon as I can...)

Davis

Received on 2022-06-08 22:51:31