localDictionaries returns the same unrelated global dictionary for every global symbol
- Dominant language
- Macaulay2
- Stars
- 435
- Forks
- 297
- Avg merge
- 4d 20h
- Merged PRs (30d)
- 11
Description
This issue was triaged from [`bugs/dan/2-localDictionaries`](https://github.com/Macaulay2/M2/blob/388c1ff0ce30d83751dea7bc7eac77fdc1305dd7/bugs/dan/2-localDictionaries), one of the 857 files removed from the pre-GitHub `bugs/` tree by [`d2c8d27826`](https://github.com/Macaulay2/M2/commit/d2c8d27826) and catalogued in [#36](https://github.com/Macaulay2/M2/issues/36). **The commentary below was written by Claude (Claude Opus 5, via Claude Code)**, not by @d-torrance, whose account posted it -- please weigh it accordingly.
### The original file, verbatim
```text
that dictionary doesn't look local:
i41 : localDictionaries global a
o41 = {Macaulay2#"private dictionary"}
o41 : List
```
### Where it stands today
`localDictionaries` applied to a global symbol returns a dictionary that is not local, does not
contain the symbol, and is the same one whatever symbol you pass.
```m2
i1 : localDictionaries global a
o1 = {Varieties#"private dictionary"}
i2 : localDictionaries global sin
o2 = {Varieties#"private dictionary"}
i3 : localDictionaries global zzneverused
o3 = {Varieties#"private dictionary"}
i4 : localDictionaries symbol currentPackage
o4 = {Varieties#"private dictionary"}
```
`zzneverused` is a symbol nothing has ever defined, so the answer carries no information about the
argument at all.
Three separate things are wrong with it:
- **It is not local.** `class` of the result is `GlobalDictionary`. The documented example behaves
correctly by contrast — `localDictionaries ((f 22) 33)` gives three `LocalDictionary`s, and
`localDictionaries()` gives one.
- **It is not the dictionary containing the symbol.** `dictionary global a` is
`User#"private dictionary"` and `dictionary global sin` is `Core.Dictionary`.
- **It does not contain the symbol.** `(o1#0)#?"a"` and `(o2#0)#?"sin"` are both `false`.
Which package gets named is incidental. The bug file below recorded
`{Macaulay2#"private dictionary"}` in 2006 and it is `Varieties` now — it is whichever package
happened to be created last, not anything to do with the symbol.
### What the documentation says
> a list of the local dictionaries associated with the lexical scopes containing `f`
`ov_repl.m2:462-479`. A global symbol has no enclosing local scope, so `{}` would be a defensible
answer, and an error would be another. Naming an unrelated package's private dictionary is neither.
### Where it comes from
`localDictionaries` walks the frame chain outward from the symbol's frame
(`d/actors5.d:1688-1697`). A global symbol's frame is the global frame, and the dictionary closure
built from it is whatever that frame currently points at, which is why every global symbol gives the
same answer and why the answer moves as packages are added.
`open` · disposition `issue` · source of truth: [`bug-triage/catalog.tsv`](https://github.com/d-torrance/M2/blob/bug-triage/bug-triage/catalog.tsv)
Contributor guide
No contributing guide indexed for this repository
Research direction
Read the documentation example in ov_repl.m2:462-479 and inspect the frame-chain handling in d/actors5.d:1688-1697. Reproduce the global-symbol cases from the issue, compare them with localDictionaries on a local expression, and determine the intended result for a global symbol. Done means global symbols no longer return an unrelated package dictionary while the documented local-scope behavior remains correct.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100