report nested decl aliases in todo

This commit is contained in:
Mitchell Rosen 2024-07-03 11:53:45 -04:00
parent 052fd51948
commit 1857640da4
3 changed files with 131 additions and 25 deletions

View File

@ -1450,6 +1450,7 @@ notifyUser dir = \case
<> IP.makeExample IP.aliasTerm ["<hash>", prettyName name <> ".<ConstructorName>"] <> IP.makeExample IP.aliasTerm ["<hash>", prettyName name <> ".<ConstructorName>"]
<> "to give names to each unnamed constructor, and then try the merge again." <> "to give names to each unnamed constructor, and then try the merge again."
] ]
-- Note [NestedDeclAliasMessage] If you change this, also change the other similar one
MergeNestedDeclAlias aliceOrBob shorterName longerName -> MergeNestedDeclAlias aliceOrBob shorterName longerName ->
pure . P.wrap $ pure . P.wrap $
"On" "On"
@ -2732,30 +2733,48 @@ handleTodoOutput todo
else mempty else mempty
prettyConstructorAliases <- prettyConstructorAliases <-
case todo.incoherentDeclReasons.constructorAliases of let -- We want to filter out constructor aliases whose types are part of a "nested decl alias" problem, because
[] -> pure mempty -- otherwise we'd essentially be reporting those issues twice.
aliases -> do --
things <- -- That is, if we have two nested aliases like
for aliases \(typeName, conName1, conName2) -> do --
n1 <- addNumberedArg (SA.Name conName1) -- Foo = #XYZ
n2 <- addNumberedArg (SA.Name conName2) -- Foo.Bar = #XYZ#0
pure (typeName, formatNum n1 <> prettyName conName1, formatNum n2 <> prettyName conName2) --
pure $ -- Foo.inner.Alias = #XYZ
things -- Foo.inner.Alias.Constructor = #XYZ#0
& map --
( \(typeName, prettyCon1, prettyCon2) -> -- then we'd prefer to say "oh no Foo and Foo.inner.Alias are aliases" but *not* additionally say "oh no
-- Note [ConstructorAliasMessage] If you change this, also change the other similar one -- Foo.Bar and Foo.inner.Alias.Constructor are aliases".
P.wrap notNestedDeclAlias (typeName, _, _) =
( "The type" foldr
<> prettyName typeName (\(short, long) acc -> typeName /= short && typeName /= long && acc)
<> "has a constructor with multiple names. Please delete all but one name for each" True
<> "constructor." todo.incoherentDeclReasons.nestedDeclAliases
) in case filter notNestedDeclAlias todo.incoherentDeclReasons.constructorAliases of
<> P.newline [] -> pure mempty
<> P.newline aliases -> do
<> P.indentN 2 (P.lines [prettyCon1, prettyCon2]) things <-
) for aliases \(typeName, conName1, conName2) -> do
& P.sep "\n\n" n1 <- addNumberedArg (SA.Name conName1)
n2 <- addNumberedArg (SA.Name conName2)
pure (typeName, formatNum n1 <> prettyName conName1, formatNum n2 <> prettyName conName2)
pure $
things
& map
( \(typeName, prettyCon1, prettyCon2) ->
-- Note [ConstructorAliasMessage] If you change this, also change the other similar one
P.wrap
( "The type"
<> prettyName typeName
<> "has a constructor with multiple names. Please delete all but one name for each"
<> "constructor."
)
<> P.newline
<> P.newline
<> P.indentN 2 (P.lines [prettyCon1, prettyCon2])
)
& P.sep "\n\n"
prettyMissingConstructorNames <- prettyMissingConstructorNames <-
case todo.incoherentDeclReasons.missingConstructorNames of case todo.incoherentDeclReasons.missingConstructorNames of
@ -2773,6 +2792,30 @@ handleTodoOutput todo
<> P.newline <> P.newline
<> P.indentN 2 (P.lines types1) <> P.indentN 2 (P.lines types1)
prettyNestedDeclAliases <-
case todo.incoherentDeclReasons.nestedDeclAliases of
[] -> pure mempty
aliases0 -> do
aliases1 <-
for aliases0 \(short, long) -> do
n1 <- addNumberedArg (SA.Name short)
n2 <- addNumberedArg (SA.Name long)
pure (formatNum n1 <> prettyName short, formatNum n2 <> prettyName long)
-- Note [NestedDeclAliasMessage] If you change this, also change the other similar one
pure $
aliases1
& map
( \(short, long) ->
P.wrap
( "These types are aliases, but one is nested under the other. Please separate them or delete"
<> "one copy."
)
<> P.newline
<> P.newline
<> P.indentN 2 (P.lines [short, long])
)
& P.sep "\n\n"
(pure . P.sep "\n\n" . P.nonEmpty) (pure . P.sep "\n\n" . P.nonEmpty)
[ prettyDependentsOfTodo, [ prettyDependentsOfTodo,
prettyDirectTermDependenciesWithoutNames, prettyDirectTermDependenciesWithoutNames,
@ -2780,7 +2823,8 @@ handleTodoOutput todo
prettyConflicts, prettyConflicts,
prettyDefnsInLib, prettyDefnsInLib,
prettyConstructorAliases, prettyConstructorAliases,
prettyMissingConstructorNames prettyMissingConstructorNames,
prettyNestedDeclAliases
] ]
listOfDefinitions :: listOfDefinitions ::

View File

@ -142,3 +142,25 @@ scratch/main> todo
```ucm:hide ```ucm:hide
scratch/main> delete.project scratch scratch/main> delete.project scratch
``` ```
# Nested decl aliases
The `todo` command complains about nested decl aliases.
```ucm:hide
scratch/main> builtins.mergeio lib.builtins
```
```unison
structural type Foo a = One a | Two a a
structural type Foo.inner.Bar a = Uno a | Dos a a
```
```ucm
scratch/main> add
scratch/main> todo
```
```ucm:hide
scratch/main> delete.project scratch
```

View File

@ -261,3 +261,43 @@ scratch/main> todo
1. Foo 1. Foo
``` ```
# Nested decl aliases
The `todo` command complains about nested decl aliases.
```unison
structural type Foo a = One a | Two a a
structural type Foo.inner.Bar a = Uno a | Dos a a
```
```ucm
Loading changes detected in scratch.u.
I found and typechecked these definitions in scratch.u. If you
do an `add` or `update`, here's how your codebase would
change:
⍟ These new definitions are ok to `add`:
structural type Foo a
structural type Foo.inner.Bar a
```
```ucm
scratch/main> add
⍟ I've added these definitions:
structural type Foo a
structural type Foo.inner.Bar a
scratch/main> todo
These types are aliases, but one is nested under the other.
Please separate them or delete one copy.
1. Foo
2. Foo.inner.Bar
```