Commit 5ebdba2
authored
## Summary
Item 1 of the qualified-path adjacent gaps surfaced by #448: the
`qualified_type_name` production in `lib/parser.mly:154-161` required
`upper_ident` as the head segment, so qualified type paths whose first
segment was a lowercase stdlib module name (`json`, `option`, `prelude`,
`dict`, `alib`, `collections`, `io`, `string`, `result`, `testing`,
`effects`, `math`) parse-errored at the separator (`.` or `::`).
Reported symptom: `parse error at .` on `x: json.Value` even with `use
json;` in scope.
## Fix
Add a parallel production with `lower_ident` head:
```ocaml
qualified_type_name:
| head = upper_ident qsep rest = qualified_type_name_rest
{ head ^ "::" ^ rest }
| head = lower_ident qsep rest = qualified_type_name_rest
{ head ^ "::" ^ rest }
```
`qualified_type_name_rest` stays `upper_ident`-only — the tail segment
is the type/effect name proper (a TyCon), so it must remain uppercase.
Only the *qualifier* segment was wrongly constrained.
Option (b) from #448 (relax the parser) rather than (a) (rename stdlib
modules), per the original triage.
## LR(1) safety
The disambiguation strategy is symmetric to the existing `upper_ident`
path: a bare `lower_ident` in type position reduces to TyVar (existing
rule at line 504); the parser only shifts past the `lower_ident` if the
next token is a `qsep` (`.` or `::`).
Menhir reports the **same conflict counts** as before the change (21 / 1
/ 68 / 7), confirming no new conflicts introduced.
## Tests
Three new cases in `test/test_qualified_paths.ml`:
- `#448(1) lowercase qualifier head parses` — `x: json.Value` no longer
emits a parse error
- `#448(1) lowercase qualifier head + ::` parses — same with the `::`
separator
- `#448(1) fully-lowercase qualified path still rejected` — `x:
json.value` MUST still parse-error because the tail segment is now
reaching `qualified_type_name_rest` which still requires `upper_ident`
(regression guard)
Test results: `dune runtest` → **366 tests passed** (was 363); no
regressions on existing `test_qualified_paths` cases.
## Scope
Closes **#448 item 1** only. Does NOT address:
- Item 2 (`use A.B;` leaf-only qualifier registration)
- Item 3 (`use A::{Item}` multi-segment brace-list parse)
- Item 4 (bare unknown TyCon permissive lookup)
Those remain open under the parent issue.
## Downstream
Unblocks `Pkg.Type` syntax with lowercase stdlib heads — directly helps
hyperpolymath/echidna#117 (Client.res AffineScript-TEA port) which had
`json.Value` / `dict.Dict` references that were stranded behind this
parse error.
Refs #228, refs #447, refs #241.
1 parent fffae8b commit 5ebdba2
2 files changed
Lines changed: 50 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
154 | 154 | | |
155 | 155 | | |
156 | 156 | | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
157 | 165 | | |
158 | 166 | | |
159 | 167 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
103 | 103 | | |
104 | 104 | | |
105 | 105 | | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
106 | 142 | | |
107 | 143 | | |
108 | 144 | | |
| |||
116 | 152 | | |
117 | 153 | | |
118 | 154 | | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
119 | 161 | | |
0 commit comments