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
Add Hint when a module is used in place of a module type #9673
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! This looks good overall, but see comments (in particular on the wording of the new warning).
We would have the option to hint: "Did you mean (module type of Equal)". Do we want to do this? I'm not sure this is a good idea, but I sort of like making this feature more discoverable through hints.
typing/env.ml
Outdated
| None -> () | ||
| Some _ -> | ||
fprintf ppf | ||
"@\nHint: There is a module called [%a] %s@?" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The warning says "there is a module called [Foo]", I would (1) drop the brackets and (2) use "named" instead of "called": "there is a module named Foo".
typing/env.ml
Outdated
fprintf ppf "Unbound module type %a" !print_longident lid; | ||
spellcheck ppf extract_modtypes env lid; | ||
match find_namesake_module lid env with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't find the find_namesake_module
auxiliary function very helpful, in part because "namesake" is a term I am not so familiar with. You could just call find_module_by_name
directly. (You can use match ... with exception Not_found -> ... | _ -> ...
if it leads to nicer code than try .. with ..
.)
typing/env.ml
Outdated
@@ -3075,9 +3081,17 @@ let report_lookup_error _loc env ppf = function | |||
| Unbound_class lid -> | |||
fprintf ppf "Unbound class %a" !print_longident lid; | |||
spellcheck ppf extract_classes env lid; | |||
| Unbound_modtype lid -> | |||
| Unbound_modtype lid -> begin | |||
fprintf ppf "Unbound module type %a" !print_longident lid; | |||
spellcheck ppf extract_modtypes env lid; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want this new hint before, or after, the spellchecking hint (if any)? (I'm not sure if one order is objectively better than the other.)
I am not sure if I like the hint: we are special casing the Moreover, I don't expect to be ever right in code that I write, because having a module and module type named the same is just an accident and reporting this accident doesn't bring much information to me. This is thus a beginner-oriented hint. However, the hint message doesn't give any hint on how to solve the error, because this is fundamentally a programmer mental model error. At best, the hint may explain that module and module types are not the same thing. I would thus suggest to at least amend the hint to:
(which somehow exacerbates my issue with the hint: why are we reporting that an unrelated entity is also named Am I missing some case where the hint can help a beginner to fix its code? |
It would be fine to add other situations where similar confusions occur with class types, here or in another PR. Do you have an example of class-vs-class-type confusion that would benefit from a hint?
We should ask the people who were confused, but my impression is that it is not so surprising that people would expect to use a module as a module type: modules have an obvious module type they correspond to, and using for example After having written the paragraph above, I do see a situation where that oculd happen: for type-only modules which are isomorphic to signatures. If someones defines a type-only module and then tries to use it as a signature, we could give a hint.
Yes, this is a good point. It may be necessary to refactor the spellchecking code a bit to return the information of whether a hint was given or not.
I like the proposed rephrasing. We could possibly refer to the manual for more explanations? |
For the reverse error, beginners try to use module types as interfaces: module type S = sig type t val show: t -> string end
let f (x: S.t ) = () often enough that I have a ready-made answer for that situation. For class types, the problem can only appear when using class types as classes: class type ct = object method m: int end
class c = object inherit ct end We could refer to the manual chapter on modules as a hint that there may be deeper issues at work. For the no-runtime component subcase, it is true that in this situation, we have a more direct hint that makes sense: |
Your answer is very useful, but a bit lacking in actionability: what do you propose that @xvw should do to address your concern? A proposal for a scope (which hint(s) to implement for a PR that you would like?) and maybe slightly more specific on the wording (what do you think would be actual good hints to give?) would be even more useful. |
Thanks both of you for your suggestions and insight. I've sligthly remanied the PR with some opiniated choices (but I'm open to update anything, of course).
|
I think the prioritization of the same name, different category hint over the spellchecking is fine. Moreover, we could tweak it later if needed.
yields
whereas there is no type nor modules at play. It would be possible to keep enough context in order to specialize the message when it makes sense. However, I would propose to stop at the generic hint message first and refine it in a later PR. |
Thanks @Octachron for your feedback. The hint is now more concise (and avoid misleading information). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new implementation looks good to me. I think this is good to merge if @Octachron agrees and also the CI.
Note: we could have had the symmetric support in the Unbound_cltype
case.
It would be impossible to trigger the hint since class declarations automatically define a class type with the same name as the class. |
Makes sense, thanks. Do you also approve merging? @xvw you should write a Changes entry (see CONTRIBUTING.md for details, or just imitate existing entries). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think the added symmetry (where it makes sense) and interaction with the spellchecker hint makes the new hint useful enough.
Thanks. I'll write the Change Entry (and try to have the CI green). Thanks both of you for your help and your insight. Just to be sure, |
module types. |
Add hint when a module is used instead of a module type or when a module type is used instead of a module or when a class type is used instead of a class.
Attempt to fix #6633
The patch add an Hint if a module is used in place of a module type. For example:
Will add to the error:
The following Hint:
If there is namesake the hint is not displayed.