Skip to content

Commit dbdf24c

Browse files
authored
chore: switch the association of stored suggestions (#11590)
This PR switches the way olean files store identifier suggestions. The ordering introduced in #11367 and #11529 made sense if we were only storing incorrect -> correct mappings, but for the reference manual we want to store the correct -> incorrect mappings as well, and so it is more sensible to store just the correct -> incorrect mapping that mimics the author-generated data better.
1 parent acb7bc5 commit dbdf24c

File tree

2 files changed

+50
-21
lines changed

2 files changed

+50
-21
lines changed

src/Lean/Elab/App.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1424,7 +1424,7 @@ where
14241424
type{inlineExprTrailing eType}"
14251425

14261426
-- Possible alternatives provided with `@[suggest_for]` annotations
1427-
let suggestions := (← Lean.getSuggestions fullName).filter (·.getPrefix = fullName.getPrefix)
1427+
let suggestions := (← Lean.getSuggestions fullName).filter (·.getPrefix = fullName.getPrefix) |>.toArray
14281428
let suggestForHint ←
14291429
if h : suggestions.size = 0 then
14301430
pure .nil

src/Lean/IdentifierSuggestion.lean

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,35 @@ namespace Lean
1717

1818
set_option doc.verso true
1919

20+
public structure IdentSuggestion where
21+
existingToIncorrect : NameMap NameSet := {}
22+
incorrectToExisting : NameMap NameSet := {}
23+
deriving Inhabited
24+
25+
def IdentSuggestion.add (table : IdentSuggestion) (trueName : Name) (altNames : Array Name) : IdentSuggestion :=
26+
{ existingToIncorrect :=
27+
table.existingToIncorrect.alter trueName fun old =>
28+
altNames.foldl (β := NameSet) (init := old.getD {}) fun accum altName =>
29+
accum.insert altName
30+
incorrectToExisting :=
31+
altNames.foldl (init := table.incorrectToExisting) fun accum altName =>
32+
accum.alter altName fun old =>
33+
old.getD {} |>.insert trueName
34+
}
2035

2136
builtin_initialize identifierSuggestionForAttr : PersistentEnvExtension
22-
(Name × Array Name) /- *Store* mappings from incorrect names to corrections (identifiers that exist) -/
23-
(Name × Array Name) /- *Add* mappings from existing functions to possible incorrect namings -/
24-
(NameMap NameSet) /- *Use* mapping from incorrect names to corrections (identifiers that exist) -/
37+
(Name × Array Name) /- Mapping from existing constant to potential incorrect alternative names -/
38+
(Name × Array Name) /- Mapping from existing constant to potential incorrect alternative names -/
39+
IdentSuggestion /- Two directional mapping between existing identifier and alternative incorrect mappings -/
2540
let ext ← registerPersistentEnvExtension {
2641
mkInitial := pure {},
2742
addImportedFn := fun modules => pure <|
28-
modules.foldl (init := {}) fun accum entries =>
29-
entries.foldl (init := accum) fun accum (altName, trueNames) =>
30-
accum.alter altName (fun old => trueNames.foldl (β := NameSet) (init := old.getD ∅) fun accum trueName =>
31-
accum.insert trueName),
32-
addEntryFn := fun table (trueName, altNames) =>
33-
altNames.foldl (init := table) fun accum alt =>
34-
accum.alter alt (·.getD {} |>.insert trueName)
35-
exportEntriesFn table := table.toArray.map fun (altName, trueNames) =>
36-
(altName, trueNames.toArray)
43+
(modules.foldl (init := {}) fun accum entries =>
44+
entries.foldl (init := accum) fun accum (trueName, altNames) =>
45+
accum.add trueName altNames),
46+
addEntryFn := fun table (trueName, altNames) => table.add trueName altNames
47+
exportEntriesFn table := table.existingToIncorrect.toArray.map fun (trueName, altNames) =>
48+
(trueName, altNames.toArray)
3749
}
3850

3951
registerBuiltinAttribute {
@@ -47,32 +59,48 @@ builtin_initialize identifierSuggestionForAttr : PersistentEnvExtension
4759
| -- Attributes parsed _before the suggest_for notation is added
4860
.node _ ``Parser.Attr.simple #[.ident _ _ `suggest_for [], .node _ `null #[id]] => pure #[id]
4961
| _ => throwError "Invalid `[suggest_for]` attribute syntax {repr stx}"
62+
if isPrivateName decl then
63+
throwError "Cannot make suggestions for private names"
5064
modifyEnv (ext.addEntry · (decl, altSyntaxIds.map (·.getId)))
5165
}
5266

5367
return ext
5468

55-
public def getSuggestions [Monad m] [MonadEnv m] (fullName : Name) : m (Array Name) := do
69+
/--
70+
Given a name, find all the stored correct, existing identifiers that mention that name in a
71+
{lit}`suggest_for` annotation.
72+
-/
73+
public def getSuggestions [Monad m] [MonadEnv m] (incorrectName : Name) : m NameSet := do
74+
return identifierSuggestionForAttr.getState (← getEnv)
75+
|>.incorrectToExisting
76+
|>.find? incorrectName
77+
|>.getD {}
78+
79+
/--
80+
Given a (presumably existing) identifier, find all the {lit}`suggest_for` annotations that were given
81+
for that identifier.
82+
-/
83+
public def getStoredSuggestions [Monad m] [MonadEnv m] (trueName : Name) : m NameSet := do
5684
return identifierSuggestionForAttr.getState (← getEnv)
57-
|>.find? fullName
85+
|>.existingToIncorrect
86+
|>.find? trueName
5887
|>.getD {}
59-
|>.toArray
6088

6189
/--
6290
Throw an unknown constant error message, potentially suggesting alternatives using
6391
{name}`suggest_for` attributes. (Like {name}`throwUnknownConstantAt` but with suggestions.)
6492
6593
The "Unknown constant `<id>`" message will fully qualify the name, whereas the
6694
-/
67-
public def throwUnknownConstantWithSuggestions (constName : Name) : CoreM α := do
68-
let suggestions ← getSuggestions constName
69-
let ref ← getRef
95+
public def throwUnknownConstantWithSuggestions (constName : Name) (ref? : Option Syntax := .none) : CoreM α := do
96+
let suggestions := (← getSuggestions constName).toArray
97+
let ref := ref?.getD (← getRef)
7098
let hint ← if suggestions.size = 0 then
7199
pure MessageData.nil
72100
else
73101
-- Modify suggestions to have the same structure as the user-provided identifier, but only
74102
-- if that doesn't cause ambiguity.
75-
let rawId := (← getRef).getId
103+
let rawId := ref.getId
76104
let env ← getEnv
77105
let ns ← getCurrNamespace
78106
let openDecls ← getOpenDecls
@@ -86,7 +114,8 @@ public def throwUnknownConstantWithSuggestions (constName : Name) : CoreM α :=
86114
candidate
87115

88116
let alternative := if h : suggestions.size = 1 then m!"`{.ofConstName suggestions[0]}`" else m!"one of these"
89-
m!"Perhaps you meant {alternative} in place of `{.ofName rawId}`:".hint (suggestions.map fun suggestion =>
117+
let inPlaceOfThis := if rawId.isAnonymous then .nil else m!" in place of `{.ofName rawId}`"
118+
m!"Perhaps you meant {alternative}{inPlaceOfThis}:".hint (suggestions.map fun suggestion =>
90119
let modified := modifySuggestion suggestion
91120
{
92121
suggestion := s!"{modified}",

0 commit comments

Comments
 (0)