C++ Logo

sg15

Advanced search

Re: [isocpp-core] unimported implementation partitions

From: Gabriel Dos Reis <gdr_at_[hidden]>
Date: Thu, 9 Jun 2022 12:44:16 +0000
[Mathias]

  * Sure, if we are talking strictly about the wording of the standard.

I thought that was your take with Daniela’s answer? đŸ˜‰


  * However, I would expect that in practice the guarantees that real-world tools provide today will continue to be provided with modules, at least by default. That includes that dynamic init for all .o files passed to the linker will run. And that if you use the whole-archive flag when linking, every initializer in that static lib will also run. I think that should apply regardless of the type of TU that the .o is derived from (and that includes header units and implementation partition units). That said, I can buy that it doesn't apply to interface partitions not transitively imported by the PMI because http://eel.is/c++draft/module.unit#3<https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Feel.is%2Fc%2B%2Bdraft%2Fmodule.unit%233&data=05%7C01%7Cgdr%40microsoft.com%7Cbc9119493d64446df53508da4a143959%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637903747982485245%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=eMzJxIFnnMPxzQcP%2BZUV4Y31Vx7DzQP%2BnrUnhEcItKU%3D&reserved=0> says that they can't exist (ideally this would be diagnosed by the linker but I can accept the usual IFNDR rules applying)

Well, there are several things there.

  1. The pre-C++20 behavior for dynamic initializations of objects
  2. The strengthened guarantees offered by C++20 regarding modules.

I thought Nathan’s original question was about (B)? I expect (A) to continue to hold except at the places where (2) supplants it. No?

And by the way, the behavior of whole archive linking vs. explicit objects supplied on link time varies between platforms – e.g. traditional unix-style vs. windows-style.


  * what would you say the behavior should be

The pre-C++20 behavior, which is (A) corresponding to your (1) -- assuming you actually provided the TU corresponding to ‘m:part’ to the linker, otherwise you would get undefined symbol reference error, no?

-- Gaby

From: Mathias Stearn <redbeard0531+isocpp_at_[hidden]>
Sent: Thursday, June 9, 2022 5:33 AM
To: C++ Core Language Working Group <core_at_[hidden]>
Cc: sg15_at_[hidden]; Gabriel Dos Reis <gdr_at_[hidden]>; Nathan Sidwell <nathan_at_[hidden]>
Subject: Re: [isocpp-core] [SG15] unimported implementation partitions



On Thu, Jun 9, 2022 at 2:16 PM Gabriel Dos Reis via Core <core_at_[hidden]<mailto:core_at_[hidden]>> wrote:
[Mathias]

  * So the most logical conclusion is that implementation partitions are made part of the program image in the same way as every other TU in the program (outside the purview of the ISO C++ standard, ie in the build system).

By the same token, they would be subject to the same lack of guarantees that other Tus enjoy. No?

Sure, if we are talking strictly about the wording of the standard. However, I would expect that in practice the guarantees that real-world tools provide today will continue to be provided with modules, at least by default. That includes that dynamic init for all .o files passed to the linker will run. And that if you use the whole-archive flag when linking, every initializer in that static lib will also run. I think that should apply regardless of the type of TU that the .o is derived from (and that includes header units and implementation partition units). That said, I can buy that it doesn't apply to interface partitions not transitively imported by the PMI because http://eel.is/c++draft/module.unit#3<https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Feel.is%2Fc%2B%2Bdraft%2Fmodule.unit%233&data=05%7C01%7Cgdr%40microsoft.com%7Cbc9119493d64446df53508da4a143959%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637903747982485245%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=eMzJxIFnnMPxzQcP%2BZUV4Y31Vx7DzQP%2BnrUnhEcItKU%3D&reserved=0> says that they can't exist (ideally this would be diagnosed by the linker but I can accept the usual IFNDR rules applying)

Considering the concrete example of the program I included below the line you quoted, assuming that the object files for all TUs are supplied to the linker, what would you say the behavior should be 1) Both "init" and "foo" are printed in that order, 2) Diagnosed error because foo() isn't defined in the program image, 3) No error, but only "foo" is printed indicating that foo() is in the program image but its TU's dynamic init didn't run (this feels like either non-conformance or malicious conformance to me), 4) something else?


  * I'm guessing it is too late to DR implementation partitions out of existence as more trouble than they are worth? ;)

I would prefer a fix that makes the interface vs. implementation correspondence more useful, e.g. make them implementation partitions of interface partition, and maybe provide a special syntax for what is specified in C++20 to avoid confusion.

-- Gaby


From: SG15 <sg15-bounces_at_[hidden]socpp.org<mailto:sg15-bounces_at_[hidden]>> On Behalf Of Mathias Stearn via SG15
Sent: Thursday, June 9, 2022 1:56 AM
To: C++ Core Language Working Group <core_at_lists.isocpp.org<mailto:core_at_[hidden]>>
Cc: Mathias Stearn <redbeard0531+isocpp_at_[hidden]<mailto:redbeard0531%2Bisocpp_at_[hidden]>>; sg15_at_[hidden]<mailto:sg15_at_[hidden]>; Nathan Sidwell <nathan_at_[hidden]<mailto:nathan_at_[hidden]>>
Subject: Re: [SG15] [isocpp-core] unimported implementation partitions



On Thu, Jun 9, 2022 at 10:31 AM Daniela Engert via Core <core_at_[hidden]<mailto:core_at_[hidden]>> wrote:
Am 09.06.2022 um 09:55 schrieb Boris Kolpackov via SG15:
> Gabriel Dos Reis via SG15 <sg15_at_[hidden]<mailto:sg15_at_[hidden]>> writes:
>
>> How would a program observe that an implementation partition isn't
>> imported but is relevant to the behavior of the entire program?
> The implementation partition can register itself (as part of the
> static initialization) in some registry.
>
> For example, the implementation partition may include a unit test
> (because that's the only way to access the private parts) which
> is registered with the test harness.

The standard is totally silent about module partitions [module.unit]/3
that are also module implementation units [module.unit]/2, and which are
not required to be reachable [module.reach]/2 because they are not part
of the interface dependency [module.import]/10 graph of a module. They
may or may not have semantic effects.

If you want the behaviour from your example be portable you need to form
an interface dependency to that partition.

The standard _isn't_ really silent on that. Or at least any more than it is silent on how only other TU is made part of the "program image" in http://eel.is/c++draft/lex.phases#1.9<https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Feel.is%2Fc%2B%2Bdraft%2Flex.phases%231.9&data=05%7C01%7Cgdr%40microsoft.com%7Cbc9119493d64446df53508da4a143959%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637903747982485245%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=jQKL40uCo1%2BYbmydo%2FQMXCY%2BLjwbLDo8lFREFIQekw4%3D&reserved=0>. So the most logical conclusion is that implementation partitions are made part of the program image in the same way as every other TU in the program (outside the purview of the ISO C++ standard, ie in the build system). Consider the following program:

module m:part;
import m;
static auto _ = puts("init");
void foo() { puts("foo"); }

export module m;
export void foo();

import m;
int main() { foo(); }


Either the m:part TU is part of the program, and it is well defined that "init" and "foo" will be printed (the http://eel.is/c++draft/basic.start.dynamic#5<https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Feel.is%2Fc%2B%2Bdraft%2Fbasic.start.dynamic%235&data=05%7C01%7Cgdr%40microsoft.com%7Cbc9119493d64446df53508da4a143959%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637903747982485245%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=jP2b%2BFGrAzNiEyVwVVhXWC70WHzY7QIEpqEUGnqDjlA%3D&reserved=0> loophole doesn't apply here), or that TU isn't part of the program and you have an ODR violation because there was no definition of foo (and in practice, you would expect a linker error rather than successful compilation). I don't think there is any way to read the standard such that it allows "foo" to be printed but not "init". I'm intentionally ignoring the trivial sense that you could declare this an ODR violation and under IFNDR anything can happen.

To be clear, I'm not saying that that TU _should_ say m:part rather than just m, just that it shouldn't change the behavior if it does.

I'm guessing it is too late to DR implementation partitions out of existence as more trouble than they are worth? ;)


_______________________________________________
Core mailing list
Core_at_lists.isocpp.org<mailto:Core_at_[hidden]>
Subscription: https://lists.isocpp.org/mailman/listinfo.cgi/core<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.isocpp.org%2Fmailman%2Flistinfo.cgi%2Fcore&data=05%7C01%7Cgdr%40microsoft.com%7Cbc9119493d64446df53508da4a143959%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637903747982485245%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=E8hPsWv3CJdUyUHFPgFt9pbpA%2FMeoCdeHd%2BcbvyxI4Q%3D&reserved=0>
Link to this post: http://lists.isocpp.org/core/2022/06/12661.php<https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Flists.isocpp.org%2Fcore%2F2022%2F06%2F12661.php&data=05%7C01%7Cgdr%40microsoft.com%7Cbc9119493d64446df53508da4a143959%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637903747982485245%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=RmtadT%2BhMPkiCmvXlQ3%2BcA9RTZFhAnQuz0pZ3SpR1m8%3D&reserved=0>
_______________________________________________
Core mailing list
Core_at_[hidden]<mailto:Core_at_lists.isocpp.org>
Subscription: https://lists.isocpp.org/mailman/listinfo.cgi/core<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.isocpp.org%2Fmailman%2Flistinfo.cgi%2Fcore&data=05%7C01%7Cgdr%40microsoft.com%7Cbc9119493d64446df53508da4a143959%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637903747982485245%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=E8hPsWv3CJdUyUHFPgFt9pbpA%2FMeoCdeHd%2BcbvyxI4Q%3D&reserved=0>
Link to this post: http://lists.isocpp.org/core/2022/06/12664.php<https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Flists.isocpp.org%2Fcore%2F2022%2F06%2F12664.php&data=05%7C01%7Cgdr%40microsoft.com%7Cbc9119493d64446df53508da4a143959%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637903747982485245%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=VPOYa5f2F9%2FE%2FJSceJAb1pYIwLR1sXq8tAH7Gax%2FRCc%3D&reserved=0>

Received on 2022-06-09 12:44:19