Conversation
|
Also: the code to remove these local bindings calls @lpw25 just voiced (offline) that he'd rather not use |
IMO, that would be better. |
|
Did you consider introducing new constructors in the AST (Parsetree and Typedtree) instead of adding a component to a tuple? That would reduce the impact on e.g. ppx rewriting, and should not make the code really more complex. Also, at the Typedtree level, you could use a more precise representation than the generic one (just a type expression, not a type declaration). |
I had a first implementation doing just that, but the churn was actually much bigger and I eventually gave up on it. As for allowing the forbidden construction to parse and reject them later: I'll make the change; but I'd like to revisit that once we get menhir to generate nice syntax error messages. |
Even with good support for error messages, LR messages will detect a situation of the sort So you can reasonably hope to get "we were expecting a type (expression) here", but not "you are trying to write a type declaration, but only type synonyms are accepted", I think. |
a8889c2 to
fdc51ef
Compare
I'm not sure we'll have the control, as for the courage: we have it right now to produce it from a different part of the compiler, so I don't think it would make much difference. I updated the code to emit a proper error message from typemod (doing it in |
12d72ea to
0db1c35
Compare
|
I pushed two new commits:
|
|
OK I now also introduced a new constructor for type substitutions.
Which was very painful. I'm currently not doing that, I still use a type declaration but that's precisely what destructive substitution uses. This should now be ready for review: the history is a bit less clean than I'd have hoped, but the whole diff should be easy to read. |
lpw25
left a comment
There was a problem hiding this comment.
There's a few things that need fixing, but other than those this looks good to merge.
parsing/parsetree.mli
Outdated
| and module_substitution = | ||
| { | ||
| pms_name: string loc; | ||
| pms_synonym: Longident.t loc; |
There was a problem hiding this comment.
Maybe pms_manifest to match the type declaration case?
parsing/parsetree.mli
Outdated
| *) | ||
| | Psig_type of rec_flag * type_declaration list | ||
| (* type t1 = ... and ... and tn = ... *) | ||
| (* type t1 = ... and ... and tn = ... *) |
There was a problem hiding this comment.
Accidental change to whitespace.
parsing/parsetree.mli
Outdated
| | Psig_type of rec_flag * type_declaration list | ||
| (* type t1 = ... and ... and tn = ... *) | ||
| (* type t1 = ... and ... and tn = ... *) | ||
| | Psig_typesubst of rec_flag * type_declaration list |
There was a problem hiding this comment.
This rec_flag should be removed because substitutions should all be "nonrec".
ocamldoc/odoc_sig.ml
Outdated
|
|
||
| | Parsetree.Psig_type (rf, name_type_decl_list) -> | ||
| | Parsetree.Psig_type (rf, name_type_decl_list) | ||
| | Parsetree.Psig_typesubst (rf, name_type_decl_list) (* FIXME *) -> |
There was a problem hiding this comment.
Maybe we can do better here. Perhaps @Octachron would like to think about how we want to display these in OCamldoc's output.
typing/typemod.ml
Outdated
| user_kind: Sig_component_kind.t; | ||
| user_loc: Location.t; | ||
| } | ||
| type hidding_error = |
typing/typemod.ml
Outdated
| | Cannot_scrape_alias of Path.t | ||
| | Badly_formed_signature of string * Typedecl.error | ||
| | Cannot_hide_id of hidding_error | ||
| | Invalid_subst_rhs of [ `Module | `Type ] |
There was a problem hiding this comment.
No real need for a polymorphic variant here.
| Line 3, characters 15-18: | ||
| 3 | module M1 := sig end | ||
| ^^^ | ||
| Error: Syntax error: 'end' expected |
There was a problem hiding this comment.
I think you need an error production in the parser to give this a better error message
| ^^^^ | ||
| Error: Unbound module N | ||
| |}] | ||
|
|
There was a problem hiding this comment.
I suggest adding tests for type ... and and potentially recursive substitutions somewhere in this file.
typing/typemod.ml
Outdated
| Typedecl.transl_type_decl env rec_flag sdecls | ||
| in | ||
| List.iter (fun td -> | ||
| if td.typ_kind <> Ttype_abstract || td.typ_manifest = None |
| `Substituted_away (Subst.add_module id path Subst.identity) | ||
| in | ||
| Signature_names.check_module ~info names pms.pms_name.loc id; | ||
| let newenv = Env.enter_module_declaration id md env in |
There was a problem hiding this comment.
This should sometimes be an alias.
093143e to
4f3638f
Compare
|
OK I pushed a few more commits addressing @lpw25's comments (there should be one commit per review comment). |
type [params] id := type_expr { and [params] id := type_expr }
module Uid := extended-module-path
ceb5802 to
912b841
Compare
lpw25
left a comment
There was a problem hiding this comment.
I think this is ready to merge now.
This is the revamped version of #2016: it allows some type and module aliases to be bound in a signature without being exported.
The chosen syntax is the one that @garrigue proposed, which is reminiscent of destructive substitution:
A few things to note:
type t := { x : int }the error message will be pretty bad.I could allow it in the parser and reject it later, e.g. from
Ast_invariants, with a decent error message. But I'm hopeful that we could get good syntax error messages soon. Am I too optimistic?