Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turn warning 31 (Module_linked_twice) into a hard error #11635

Merged
merged 2 commits into from Jan 5, 2023

Conversation

hhugo
Copy link
Contributor

@hhugo hhugo commented Oct 17, 2022

Fix #5461
Fix #10564

@hhugo
Copy link
Contributor Author

hhugo commented Oct 17, 2022

cc @gasche

@hhugo hhugo marked this pull request as ready for review October 28, 2022 11:51
Copy link
Contributor

@v-gb v-gb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the issues linked, there seems to be consensus for making this change, and I think the code change does what's intended.

I tested the behavior of this change with the script at the bottom of this comment, and it works fine but I observe error messages that are a bit worse:

4.14:

native:
File "_none_", line 1:
Error: Files 2/a.cmx and 1/a.cmx both define a module named A

bytecode:
File "2/a.cmo", line 1:
Error (warning 31 [module-linked-twice]): files 2/a.cmo and 1/a.cmo both define a module named A
File "2/b.cmo", line 1:
Error (warning 31 [module-linked-twice]): files 2/b.cmo and 1/b.cmo both define a module named B

this PR:

native:
File "_none_", line 1:
Error: Files 2/a.cmx and 1/a.cmx
       make inconsistent assumptions over interface A

bytecode:
File "_none_", line 1:
Error: Files 2/a.cmo and 1/a.cmo
       make inconsistent assumptions over interface A

Not the end of the world when the build system ensures uniqueness of compilation units, but I think it's trivial to fix (as I indicated in an inline comment), so may as well.

Other than addressing the review comments, please do the usual rebase, adding a Changes entry (and maybe squash the commits? not sure what's expected).

The test script:

#!/bin/bash
set -e -u -o pipefail
which ocamlopt
which ocamlc
rm -rf /tmp/test
mkdir /tmp/test
cd /tmp/test
mkdir 1 2
echo "type t = int" > 1/a.ml
echo "Printf.printf \"%d\\n\" (1 : A.t)" > 1/b.ml
echo "type t = string" > 2/a.ml
echo "Printf.printf \"%s\\n\" (\"qwerty\" : A.t)" > 2/b.ml
echo "native:"
(cd 1; ocamlopt -c {a,b}.ml)
(cd 2; ocamlopt -c {a,b}.ml)
ocamlopt 1/{a,b}.cmx 2/{a,b}.cmx || true
echo "bytecode:"
(cd 1; ocamlc -c {a,b}.ml)
(cd 2; ocamlc -c {a,b}.ml)
ocamlc 1/{a,b}.cmo 2/{a,b}.cmo

@@ -90,7 +87,7 @@ let check_consistency file_name unit crc =
with Not_found -> ()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on my test script, I think we should move the raise (Error(Multiple_definition ...)) above at the top of the function, so the errors are improved.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines 778 to 785
| Module_linked_twice (modname, file1, file2) ->
fprintf ppf "Files %a and %a both define a module named %s"
Location.print_filename file1
Location.print_filename file2
modname


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use the same code as in asmlink.ml (more format boxes than here), and in fact let's use the same constructor name as well (Multiple_definition), for easier comparison between bytelink.ml and asmlink.ml.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

(Warnings.Module_linked_twice(cu.cu_name,
Location.show_filename file_name,
Location.show_filename source))
raise (Error (Module_linked_twice(cu.cu_name, file_name, source)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing as in asmlink.ml: I think we should move the check to the top of the function, for better error messages.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@hhugo
Copy link
Contributor Author

hhugo commented Jan 4, 2023

Thanks for the review @sliquister. I meant to add a new test in the testsuite but my few attempts weren't successful.
Here is the output of your script with this PR

native:
File "_none_", line 1:
Error: Files 2/a.cmx and 1/a.cmx both define a module named A
bytecode:
File "_none_", line 1:
Error: Files 2/a.cmo and 1/a.cmo both define a module named A

Running more tests, I noticed that, when linking a library that contain units also present elsewhere on the command line, we don't fail/warn if theses units don't end up being linked. The behavior seems fine but it means that adding -linkall would suddenly trigger the error.

Copy link
Contributor

@v-gb v-gb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, modulo the Changes entry.

Changes Outdated
@@ -219,6 +219,9 @@ Working version
modules with mismatching -for-pack
(Pierre Chambart and Vincent Laviron, review by Mark Shinwell)

- #11635: Turn warning 31 (Module_linked_twice) into a hard error
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please list the issues as well, not just the PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@v-gb
Copy link
Contributor

v-gb commented Jan 4, 2023

The appveyor failure looks spurious.

Running more tests, I noticed that, when linking a library that contain units also present elsewhere on the command line, we don't fail/warn if theses units don't end up being linked. The behavior seems fine but it means that adding -linkall would suddenly trigger the error.

Yeah, that behavior seems fine, although a stricter behavior would probably also make sense.

{ number = 31;
names = ["module-linked-twice"];
description = "A module is linked twice in the same executable.";
since = since 4 0 };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to understand well what is going on with the warning from a compatibility perspective:

  • what happens if a user manually specifies this warning, on the command-line or in an attribute, by number or by name?
  • what is shown in -warn-help?

My current understanding is as follows:

  • Warning modifiers are interpreted by mutating dense flag arrays of all warning numbers.
  • Using a number-based modifier -31 or +31 will modify the flag array and do nothing else (as the warning is never raised anymore). In practice this is silently ignored, which is probably fine.
  • Using -module-linked-twice will result in a lookup failure because the description entry is removed here, which will eventually result in a confusing ocaml_deprecated_cli alert. This is not good.
  • The warning will not appear in -warn-help anymore, because the description entry is removed.

I think that we should do this instead: keep the description entry, but extend the description to say that the warning is now ignored and replaced by a hard error.

My understanding is that we would then get the following behavior:

  • specifying the warning by number or by name is ignored
  • the warning shows up in -warn-help, with a mention that it is ignored

I think that this new behavior would be reasonable, a better default.

One may think of something even more informative (if users try to disable the warning, letting them know that this does not work anymore through... another warning?), but I think that it would not be worth the implementation and conceptual complexity.

Minor note: the definition of defaults_warn_error further down still mentions +31, it should be removed I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've kept the description entry, updated defaults_warn_error and updated manual and man pages.

I'm not super happy with the updated description.

31 [module-linked-twice] Ignored: now a hard error (since 5.0).
    A module is linked twice in the same executable.

I've tried to follow what was done for number 25

25 Ignored: now part of warning 8.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed it to

 31 [module-linked-twice] A module is linked twice in the same executable.
    Ignored: now a hard error (since 5.0).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine with me, thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5.1 rather than 5.0 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Octachron, fixed thanks.

Copy link
Member

@gasche gasche left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i agree with @sliquister that this is a good implementation of the proposed change. I am in favor of merging once the commits have been rebased/fixupped by @hhugo as he prefers, and the CI is green.

Thanks a lot @sliquister for your careful review. I don't think that I would have had the energy to look at this by myself without your contribution.

@hhugo
Copy link
Contributor Author

hhugo commented Jan 4, 2023

i agree with @sliquister that this is a good implementation of the proposed change. I am in favor of merging once the commits have been rebased/fixupped by @hhugo as he prefers, and the CI is green.

Thanks a lot @sliquister for your careful review. I don't think that I would have had the energy to look at this by myself without your contribution.

I've squashed the commits and rebased.

@v-gb
Copy link
Contributor

v-gb commented Jan 4, 2023

Looks like the warning changes are breaking tests/warnings/mnemonics.mll.

@nojb
Copy link
Contributor

nojb commented Jan 4, 2023

Looks like the warning changes are breaking tests/warnings/mnemonics.mll.

Indeed. This test checks that every constructor of the sum type has a corresponding textual mnemonic, and vice-versa. This fails because the mnemonic for warning 31 does not have a corresponding constructor.

The simplest workaround is to add a hard-coded list of deprecated warnings to this test (for which there is no associated constructor).

@hhugo
Copy link
Contributor Author

hhugo commented Jan 4, 2023

I've pushed a fix for the tests/warnings/mnemonics.mll test following @nojb suggestion

@hhugo
Copy link
Contributor Author

hhugo commented Jan 4, 2023

The appveyor failure is due to #11853

@nojb nojb merged commit 0ec8679 into ocaml:trunk Jan 5, 2023
@nojb
Copy link
Contributor

nojb commented Jan 5, 2023

Merged, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Link time consistency check is incomplete Double linking of bytecode modules
5 participants